1 /* ************************************************************************** */
2 /* */
3 /* */
4 /* Copyright (C) 2000-2008 Cédric Auger (cedric@grisbi.org) */
5 /* 2003-2008 Benjamin Drieu (bdrieu@april.org) */
6 /* https://www.grisbi.org/ */
7 /* */
8 /* This program is free software; you can redistribute it and/or modify */
9 /* it under the terms of the GNU General Public License as published by */
10 /* the Free Software Foundation; either version 2 of the License, or */
11 /* (at your option) any later version. */
12 /* */
13 /* This program is distributed in the hope that it will be useful, */
14 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16 /* GNU General Public License for more details. */
17 /* */
18 /* You should have received a copy of the GNU General Public License */
19 /* along with this program; if not, write to the Free Software */
20 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
21 /* */
22 /* ************************************************************************** */
23
24 /**
25 * \file gsb_data_archive.c
26 * work with the archive store structure, no GUI here
27 * the archive store are used to show the archive in the list of transactions
28 * as an archive by itself contains several accounts and no balance for each account
29 * at the opening of grisbi, we create an intermediate list of structures which contains
30 * the link to the archive, but 1 structure per account, with the number of transactions
31 * and the balance for each.
32 */
33
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include "include.h"
40
41 /*START_INCLUDE*/
42 #include "gsb_data_archive_store.h"
43 #include "dialog.h"
44 #include "gsb_data_account.h"
45 #include "gsb_data_currency.h"
46 #include "gsb_data_transaction.h"
47 #include "gsb_real.h"
48 #include "transaction_list.h"
49 #include "erreur.h"
50 /*END_INCLUDE*/
51
52
53 /*START_STATIC*/
54 static void _gsb_data_archive_store_free ( struct_store_archive *archive );
55 static struct_store_archive *gsb_data_archive_store_find_struct ( gint archive_number,
56 gint account_number );
57 static gint gsb_data_archive_store_max_number ( void );
58 static gint gsb_data_archive_store_new ( void );
59 /*END_STATIC*/
60
61 /*START_EXTERN*/
62 /*END_EXTERN*/
63
64 /** contains the g_slist of struct_store_archive */
65 static GSList *archive_store_list = NULL;
66
67 /** a pointer to the last archive_store used (to increase the speed) */
68 static struct_store_archive *archive_store_buffer;
69
70
71 /**
72 * set the archives global variables to NULL,
73 * usually when we init all the global variables
74 *
75 * \param
76 *
77 * \return FALSE
78 * */
gsb_data_archive_store_init_variables(void)79 gboolean gsb_data_archive_store_init_variables ( void )
80 {
81 if ( archive_store_list )
82 {
83 GSList *tmp_list;
84
85 tmp_list = archive_store_list;
86 while ( tmp_list )
87 {
88 struct_store_archive *archive;
89
90 archive = tmp_list -> data;
91 transaction_list_remove_archive ( archive->archive_number );
92 tmp_list = tmp_list -> next;
93 _gsb_data_archive_store_free ( archive );
94 }
95 g_slist_free ( archive_store_list );
96 }
97 archive_store_list = NULL;
98 archive_store_buffer = NULL;
99
100 return FALSE;
101 }
102
103
104 /**
105 * give the g_slist of archives structure
106 * usefull when want to check all archives
107 *
108 * \param none
109 *
110 * \return the g_slist of archives structure
111 * */
gsb_data_archive_store_get_archives_list(void)112 GSList *gsb_data_archive_store_get_archives_list ( void )
113 {
114 return archive_store_list;
115 }
116
117 /**
118 * return the number of the archives given in param
119 *
120 * \param archive_ptr a pointer to the struct of the archive
121 *
122 * \return the number of the archive, 0 if problem
123 * */
gsb_data_archive_store_get_number(gpointer archive_ptr)124 gint gsb_data_archive_store_get_number ( gpointer archive_ptr )
125 {
126 struct_store_archive *archive;
127
128 if ( !archive_ptr )
129 return 0;
130
131 archive = archive_ptr;
132 archive_store_buffer = archive;
133
134 return archive -> archive_store_number;
135 }
136
137
138
139 /**
140 * function called at the opening of grisbi
141 * create all the archive store according to the archives in grisbi
142 *
143 * \param
144 *
145 * \return
146 * */
gsb_data_archive_store_create_list(void)147 void gsb_data_archive_store_create_list ( void )
148 {
149 GSList *tmp_list;
150
151 tmp_list = gsb_data_transaction_get_complete_transactions_list ();
152 while (tmp_list)
153 {
154 gint transaction_number;
155 gint archive_number;
156
157 transaction_number = gsb_data_transaction_get_transaction_number (tmp_list -> data);
158
159 archive_number = gsb_data_transaction_get_archive_number (transaction_number);
160
161 if (archive_number)
162 {
163 struct_store_archive *archive_store;
164 gint floating_point;
165 gint account_number;
166
167 account_number = gsb_data_transaction_get_account_number (transaction_number);
168 floating_point = gsb_data_currency_get_floating_point (
169 gsb_data_account_get_currency (account_number) );
170 archive_store = gsb_data_archive_store_find_struct ( archive_number, account_number);
171 if (archive_store)
172 {
173 /* there is already a struct_store_archive for the same archive and the same account,
174 * we increase the balance except for operations */
175 if ( !gsb_data_transaction_get_mother_transaction_number ( transaction_number ) )
176 archive_store -> balance = gsb_real_add ( archive_store -> balance,
177 gsb_data_transaction_get_adjusted_amount (
178 transaction_number,
179 floating_point));
180 archive_store -> nb_transactions++;
181 }
182 else
183 {
184 /* there is no struct_store_archive for that transaction, we make a new one
185 * with the balance of the transaction as balance */
186 gint archive_store_number;
187
188 archive_store_number = gsb_data_archive_store_new ();
189 archive_store = gsb_data_archive_store_get_structure (archive_store_number);
190
191 archive_store -> archive_number = archive_number;
192 archive_store -> account_number = account_number;
193 archive_store -> balance = gsb_data_transaction_get_adjusted_amount (
194 transaction_number, floating_point);
195 if ( ! gsb_data_transaction_get_mother_transaction_number ( transaction_number ) )
196 archive_store -> nb_transactions = 1;
197 }
198 }
199 tmp_list = tmp_list -> next;
200 }
201 }
202
203 /**
204 * This internal function is called to free the memory used by a struct_store_archive structure
205 */
_gsb_data_archive_store_free(struct_store_archive * archive)206 static void _gsb_data_archive_store_free ( struct_store_archive *archive )
207 {
208 if ( !archive )
209 return;
210
211 g_free ( archive );
212
213 if ( archive_store_buffer == archive )
214 archive_store_buffer = NULL;
215 }
216
217 /**
218 * remove an archive store
219 *
220 * \param archive_store_number the archive store we want to remove
221 *
222 * \return TRUE ok
223 * */
gsb_data_archive_store_remove(gint archive_store_number)224 gboolean gsb_data_archive_store_remove ( gint archive_store_number )
225 {
226 struct_store_archive *archive;
227
228 archive = gsb_data_archive_store_get_structure ( archive_store_number );
229
230 if (!archive)
231 return FALSE;
232
233 archive_store_list = g_slist_remove ( archive_store_list,
234 archive );
235
236 _gsb_data_archive_store_free ( archive );
237 return TRUE;
238 }
239
240 /**
241 * remove all the archives stores corresponding to the archive
242 *
243 * \param archive_number the archive we want remove the corresponding archives stores
244 *
245 * \return TRUE ok
246 * */
gsb_data_archive_store_remove_by_archive(gint archive_number)247 gboolean gsb_data_archive_store_remove_by_archive ( gint archive_number )
248 {
249 GSList *tmp_list;
250
251 tmp_list = archive_store_list;
252 while (tmp_list)
253 {
254 struct_store_archive *archive;
255
256 archive = tmp_list -> data;
257 tmp_list = tmp_list -> next;
258 if (archive -> archive_number == archive_number)
259 {
260 archive_store_list = g_slist_remove ( archive_store_list,
261 archive );
262 _gsb_data_archive_store_free ( archive );
263 }
264 }
265 return TRUE;
266 }
267
268
269
270
271 /**
272 * return the number of the corresponding archive
273 *
274 * \param archive_store_number the number of the archive store
275 *
276 * \return the of the archive or 0 if fail
277 * */
gsb_data_archive_store_get_archive_number(gint archive_store_number)278 gint gsb_data_archive_store_get_archive_number ( gint archive_store_number )
279 {
280 struct_store_archive *archive;
281
282 archive = gsb_data_archive_store_get_structure ( archive_store_number );
283
284 if (!archive)
285 return 0;
286
287 return archive -> archive_number;
288 }
289
290 /**
291 * return the account_number of the archive store
292 *
293 * \param archive_store_number the number of the archive store
294 *
295 * \return the of the archive or 0 if fail
296 * */
gsb_data_archive_store_get_account_number(gint archive_store_number)297 gint gsb_data_archive_store_get_account_number ( gint archive_store_number )
298 {
299 struct_store_archive *archive;
300
301 archive = gsb_data_archive_store_get_structure ( archive_store_number );
302
303 if (!archive)
304 return 0;
305
306 return archive -> account_number;
307 }
308
309 /**
310 * return the balance of the archive store
311 * ie the balance of the archive for the account in the archive store
312 *
313 * \param archive_store_number the number of the archive store
314 *
315 * \return the of the archive or 0 if fail
316 * */
gsb_data_archive_store_get_balance(gint archive_store_number)317 GsbReal gsb_data_archive_store_get_balance ( gint archive_store_number )
318 {
319 struct_store_archive *archive;
320
321 archive = gsb_data_archive_store_get_structure ( archive_store_number );
322
323 if (!archive)
324 return null_real;
325
326 return archive -> balance;
327 }
328
329 /**
330 * return the number of transactions of the archive store
331 *
332 * \param archive_store_number the number of the archive store
333 *
334 * \return the of the archive or 0 if fail
335 * */
gsb_data_archive_store_get_transactions_number(gint archive_store_number)336 gint gsb_data_archive_store_get_transactions_number ( gint archive_store_number )
337 {
338 struct_store_archive *archive;
339
340 archive = gsb_data_archive_store_get_structure ( archive_store_number );
341
342 if (!archive)
343 return 0;
344
345 return archive -> nb_transactions;
346 }
347
348
349
350 /**
351 * find and return the structure of the archive asked
352 *
353 * \param archive_store_number number of archive
354 *
355 * \return the adr of the struct of the archive (NULL if doesn't exit)
356 * */
gsb_data_archive_store_get_structure(gint archive_store_number)357 gpointer gsb_data_archive_store_get_structure ( gint archive_store_number )
358 {
359 GSList *tmp;
360
361 if (!archive_store_number)
362 return NULL;
363
364 /* before checking all the archives, we check the buffer */
365 if ( archive_store_buffer
366 &&
367 archive_store_buffer -> archive_store_number == archive_store_number )
368 return archive_store_buffer;
369
370 tmp = archive_store_list;
371
372 while ( tmp )
373 {
374 struct_store_archive *archive;
375
376 archive = tmp -> data;
377
378 if ( archive -> archive_store_number == archive_store_number )
379 {
380 archive_store_buffer = archive;
381 return archive;
382 }
383
384 tmp = tmp -> next;
385 }
386 return NULL;
387 }
388
389 /**
390 * find and return the last number of archive
391 *
392 * \param none
393 *
394 * \return last number of archive
395 * */
gsb_data_archive_store_max_number(void)396 static gint gsb_data_archive_store_max_number ( void )
397 {
398 GSList *tmp;
399 gint number_tmp = 0;
400
401 tmp = archive_store_list;
402
403 while ( tmp )
404 {
405 struct_store_archive *archive;
406
407 archive = tmp -> data;
408
409 if ( archive -> archive_store_number > number_tmp )
410 number_tmp = archive -> archive_store_number;
411
412 tmp = tmp -> next;
413 }
414 return number_tmp;
415 }
416
417 /**
418 * find the archive store corresponding to the archive number and account number
419 * given in param
420 *
421 * \param archive_number the wanted archive number
422 * \param account_number the wanted account number
423 *
424 * \return a pointer to the found struct_store_archive or NULL
425 * */
gsb_data_archive_store_find_struct(gint archive_number,gint account_number)426 static struct_store_archive *gsb_data_archive_store_find_struct ( gint archive_number,
427 gint account_number )
428 {
429 GSList *tmp_list;
430
431 tmp_list = archive_store_list;
432 while (tmp_list)
433 {
434 struct_store_archive *archive;
435
436 archive = tmp_list -> data;
437
438 if (archive -> archive_number == archive_number
439 &&
440 archive -> account_number == account_number )
441 return archive;
442
443 tmp_list = tmp_list -> next;
444 }
445 return NULL;
446 }
447
448 /**
449 * create a new archive store, give it a number, append it to the list
450 * and return the number
451 *
452 * \param
453 *
454 * \return the number of the new archive store
455 * */
gsb_data_archive_store_new(void)456 static gint gsb_data_archive_store_new ( void )
457 {
458 struct_store_archive *archive;
459
460 archive = g_malloc0 ( sizeof ( struct_store_archive ));
461 if (!archive)
462 {
463 dialogue_error_memory ();
464 return 0;
465 }
466 archive -> archive_store_number = gsb_data_archive_store_max_number () + 1;
467
468 archive_store_list = g_slist_append ( archive_store_list, archive );
469 archive_store_buffer = archive;
470
471 return archive -> archive_store_number;
472 }
473
474
475 /**
476 *
477 *
478 *
479 */
gsb_data_archive_store_get_archives_balance(gint account_number)480 GsbReal gsb_data_archive_store_get_archives_balance ( gint account_number )
481 {
482 GSList *tmp_list;
483 GsbReal balance = null_real;
484
485 tmp_list = gsb_data_archive_store_get_archives_list ( );
486
487 while (tmp_list)
488 {
489 struct_store_archive *archive_store;
490
491 archive_store = tmp_list -> data;
492
493 if ( archive_store -> account_number == account_number )
494 balance = gsb_real_add ( balance, archive_store -> balance );
495
496 tmp_list = tmp_list -> next;
497 }
498
499 return balance;
500 }
501
502
503 /**
504 *
505 *
506 *
507 */
gsb_data_archive_store_get_transactions_visibles(gint archive_number,gint account_number)508 gboolean gsb_data_archive_store_get_transactions_visibles ( gint archive_number,
509 gint account_number )
510 {
511 struct_store_archive *archive_store;
512
513 archive_store = gsb_data_archive_store_find_struct ( archive_number, account_number );
514
515 if ( archive_store )
516 return archive_store -> transactions_visibles;
517 else
518 return FALSE;
519 }
520
521
522 /**
523 *
524 *
525 *
526 */
gsb_data_archive_store_set_transactions_visibles(gint archive_number,gint account_number,gboolean transactions_visibles)527 gboolean gsb_data_archive_store_set_transactions_visibles ( gint archive_number,
528 gint account_number,
529 gboolean transactions_visibles )
530 {
531 struct_store_archive *archive_store;
532
533 archive_store = gsb_data_archive_store_find_struct ( archive_number, account_number );
534
535 if ( archive_store )
536 {
537 archive_store -> transactions_visibles = transactions_visibles;
538 return TRUE;
539 }
540 else
541 return FALSE;
542 }
543
544
545 /**
546 *
547 *
548 *
549 */
gsb_data_archive_store_account_have_transactions_visibles(gint account_number)550 gboolean gsb_data_archive_store_account_have_transactions_visibles ( gint account_number )
551 {
552 GSList *tmp_list;
553
554 tmp_list = gsb_data_archive_store_get_archives_list ( );
555
556 while (tmp_list)
557 {
558 struct_store_archive *archive_store;
559
560 archive_store = tmp_list -> data;
561
562 if ( archive_store -> account_number == account_number
563 &&
564 archive_store -> transactions_visibles == TRUE )
565 return TRUE;
566
567 tmp_list = tmp_list -> next;
568 }
569
570 return FALSE;
571 }
572
573
574 /* Local Variables: */
575 /* c-basic-offset: 4 */
576 /* End: */
577