1 /* ************************************************************************** */
2 /*                                                                            */
3 /*                                                                            */
4 /*     Copyright (C)    2000-2007 Cédric Auger (cedric@grisbi.org)            */
5 /*          2003-2007 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 structure, no GUI here
27  */
28 
29 
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33 
34 #include "include.h"
35 
36 /*START_INCLUDE*/
37 #include "gsb_data_archive.h"
38 #include "dialog.h"
39 #include "gsb_data_transaction.h"
40 #include "utils_dates.h"
41 #include "utils_str.h"
42 /*END_INCLUDE*/
43 
44 
45 /**
46  * \struct
47  * Describe a archive
48  */
49 typedef struct
50 {
51     gint archive_number;
52     gchar *archive_name;
53 
54     /* for the archive created by date,
55      * else the 2 values are NULL */
56     GDate *beginning_date;
57     GDate *end_date;
58 
59     /* for the archive created by financial year,
60      * else the value is 0 */
61     gint fyear_number;
62 
63     /* if created by report, this is the title of
64      * the report */
65     gchar *report_title;
66 } struct_archive;
67 
68 /*START_STATIC*/
69 static void _gsb_data_archive_free ( struct_archive* archive);
70 static gpointer gsb_data_archive_get_structure ( gint archive_number );
71 static gint gsb_data_archive_max_number ( void );
72 /*END_STATIC*/
73 
74 /*START_EXTERN*/
75 /*END_EXTERN*/
76 
77 /** contains the g_slist of struct_archive */
78 static GSList *archive_list = NULL;
79 
80 /** a pointer to the last archive used (to increase the speed) */
81 static struct_archive *archive_buffer;
82 
83 
84 /**
85  * set the archives global variables to NULL,
86  * usually when we init all the global variables
87  *
88  * \param
89  *
90  * \return FALSE
91  * */
gsb_data_archive_init_variables(void)92 gboolean gsb_data_archive_init_variables ( void )
93 {
94     if ( archive_list )
95     {
96         g_slist_free_full ( archive_list, (GDestroyNotify) _gsb_data_archive_free );
97         archive_list = NULL;
98     }
99 
100     archive_buffer = NULL;
101 
102     return FALSE;
103 }
104 
105 
106 /**
107  * find and return the structure of the archive asked
108  *
109  * \param archive_number number of archive
110  *
111  * \return the adr of the struct of the archive (NULL if doesn't exit)
112  * */
gsb_data_archive_get_structure(gint archive_number)113 gpointer gsb_data_archive_get_structure ( gint archive_number )
114 {
115     GSList *tmp;
116 
117     if (!archive_number)
118 	return NULL;
119 
120     /* before checking all the archives, we check the buffer */
121 
122     if ( archive_buffer
123 	 &&
124 	 archive_buffer -> archive_number == archive_number )
125 	return archive_buffer;
126 
127     tmp = archive_list;
128 
129     while ( tmp )
130     {
131 	struct_archive *archive;
132 
133 	archive = tmp -> data;
134 
135 	if ( archive -> archive_number == archive_number )
136 	{
137 	    archive_buffer = archive;
138 	    return archive;
139 	}
140 
141 	tmp = tmp -> next;
142     }
143     return NULL;
144 }
145 
146 
147 /**
148  * give the g_slist of archives structure
149  * usefull when want to check all archives
150  *
151  * \param none
152  *
153  * \return the g_slist of archives structure
154  * */
gsb_data_archive_get_archives_list(void)155 GSList *gsb_data_archive_get_archives_list ( void )
156 {
157     return archive_list;
158 }
159 
160 /**
161  * return the number of the archives given in param
162  *
163  * \param archive_ptr a pointer to the struct of the archive
164  *
165  * \return the number of the archive, 0 if problem
166  * */
gsb_data_archive_get_no_archive(gpointer archive_ptr)167 gint gsb_data_archive_get_no_archive ( gpointer archive_ptr )
168 {
169     struct_archive *archive;
170 
171     if ( !archive_ptr )
172 	return 0;
173 
174     archive = archive_ptr;
175     archive_buffer = archive;
176     return archive -> archive_number;
177 }
178 
179 
180 /**
181  * find and return the last number of archive
182  *
183  * \param none
184  *
185  * \return last number of archive
186  * */
gsb_data_archive_max_number(void)187 gint gsb_data_archive_max_number ( void )
188 {
189     GSList *tmp;
190     gint number_tmp = 0;
191 
192     tmp = archive_list;
193 
194     while ( tmp )
195     {
196 	struct_archive *archive;
197 
198 	archive = tmp -> data;
199 
200 	if ( archive -> archive_number > number_tmp )
201 	    number_tmp = archive -> archive_number;
202 
203 	tmp = tmp -> next;
204     }
205     return number_tmp;
206 }
207 
208 
209 /**
210  * create a new archive, give him a number, append it to the list
211  * and return the number
212  *
213  * \param name the name of the archive (can be freed after, it's a copy) or NULL
214  *
215  * \return the number of the new archive
216  * */
gsb_data_archive_new(const gchar * name)217 gint gsb_data_archive_new ( const gchar *name )
218 {
219     struct_archive *archive;
220 
221     archive = g_malloc0 ( sizeof ( struct_archive ));
222     if (!archive)
223     {
224     dialogue_error_memory ();
225     return 0;
226     }
227     archive -> archive_number = gsb_data_archive_max_number () + 1;
228 
229     if (name)
230     archive -> archive_name = my_strdup (name);
231     else
232     archive -> archive_name = NULL;
233 
234     archive_list = g_slist_append ( archive_list, archive );
235     archive_buffer = archive;
236 
237     return archive -> archive_number;
238 }
239 
240 /**
241  * This internal function is called to free the memory used by an struct_archive structure
242  */
_gsb_data_archive_free(struct_archive * archive)243 static void _gsb_data_archive_free ( struct_archive* archive)
244 {
245     if ( ! archive )
246         return;
247     if ( archive -> archive_name )
248 	g_free ( archive -> archive_name );
249     if ( archive -> beginning_date )
250 	g_date_free ( archive -> beginning_date );
251     if ( archive -> end_date )
252 	g_date_free ( archive -> end_date );
253     if ( archive -> report_title )
254 	g_free ( archive -> report_title );
255     g_free ( archive );
256     if ( archive_buffer == archive )
257 	archive_buffer = NULL;
258 }
259 
260 /**
261  * remove an archive
262  * remove too the archive from the transactions linked to it
263  *
264  * \param archive_number the archive we want to remove
265  *
266  * \return TRUE ok
267  * */
gsb_data_archive_remove(gint archive_number)268 gboolean gsb_data_archive_remove ( gint archive_number )
269 {
270     struct_archive *archive;
271     GSList *tmp_list;
272 
273     archive = gsb_data_archive_get_structure ( archive_number );
274 
275     if (!archive)
276 	return FALSE;
277 
278     /* remove the archive from the transactions */
279     tmp_list = gsb_data_transaction_get_complete_transactions_list ();
280     while (tmp_list)
281     {
282 	gint transaction_number;
283 
284 	transaction_number = gsb_data_transaction_get_transaction_number (tmp_list -> data);
285 	if (gsb_data_transaction_get_archive_number (transaction_number) == archive -> archive_number)
286 	    gsb_data_transaction_set_archive_number ( transaction_number,
287 						      0 );
288 	tmp_list = tmp_list -> next;
289     }
290 
291     /* remove the archive from the list */
292     archive_list = g_slist_remove ( archive_list,
293 				    archive );
294 
295     _gsb_data_archive_free (archive);
296 
297     return TRUE;
298 }
299 
300 
301 /**
302  * set a new number for the archive
303  * normally used only while loading the file because
304  * the number are given automaticly
305  *
306  * \param archive_number the number of the archive
307  * \param new_no_archive the new number of the archive
308  *
309  * \return the new number or 0 if the archive doen't exist
310  * */
gsb_data_archive_set_new_number(gint archive_number,gint new_no_archive)311 gint gsb_data_archive_set_new_number ( gint archive_number,
312                         gint new_no_archive )
313 {
314     struct_archive *archive;
315 
316     archive = gsb_data_archive_get_structure ( archive_number );
317 
318     if (!archive)
319     return 0;
320 
321     archive -> archive_number = new_no_archive;
322     return new_no_archive;
323 }
324 
325 
326 /**
327  * return the name of the archive
328  *
329  * \param archive_number the number of the archive
330  *
331  * \return the name of the archive or NULL if fail
332  * */
gsb_data_archive_get_name(gint archive_number)333 const gchar *gsb_data_archive_get_name ( gint archive_number )
334 {
335     struct_archive *archive;
336 
337     archive = gsb_data_archive_get_structure ( archive_number );
338 
339     if (!archive)
340 	return NULL;
341 
342     return archive -> archive_name;
343 }
344 
345 
346 /**
347  * set the name of the archive
348  * the value is dupplicate in memory
349  *
350  * \param archive_number the number of the archive
351  * \param name the name of the archive
352  *
353  * \return TRUE if ok or FALSE if problem
354  * */
gsb_data_archive_set_name(gint archive_number,const gchar * name)355 gboolean gsb_data_archive_set_name ( gint archive_number,
356                         const gchar *name )
357 {
358     struct_archive *archive;
359 
360     archive = gsb_data_archive_get_structure ( archive_number );
361 
362     if (!archive)
363 	return FALSE;
364 
365     /* we free the last name */
366     if ( archive -> archive_name )
367 	g_free (archive -> archive_name);
368 
369     /* and copy the new one */
370     archive -> archive_name = my_strdup (name);
371 
372     return TRUE;
373 }
374 
375 
376 
377 /**
378  * return the beginning date of the archive
379  *
380  * \param archive_number the number of the archive
381  *
382  * \return the beginning date of the archive or NULL if fail
383  * */
gsb_data_archive_get_beginning_date(gint archive_number)384 GDate *gsb_data_archive_get_beginning_date ( gint archive_number )
385 {
386     struct_archive *archive;
387 
388     archive = gsb_data_archive_get_structure ( archive_number );
389 
390     if (!archive)
391 	return NULL;
392 
393     return archive -> beginning_date;
394 }
395 
396 
397 /**
398  * set the beginning date of the archive
399  * the value is dupplicate in memory
400  *
401  * \param archive_number the number of the archive
402  * \param date the beginning date of the archive
403  *
404  * \return TRUE if ok or FALSE if problem
405  * */
gsb_data_archive_set_beginning_date(gint archive_number,const GDate * date)406 gboolean gsb_data_archive_set_beginning_date ( gint archive_number,
407                         const GDate *date )
408 {
409     struct_archive *archive;
410 
411     archive = gsb_data_archive_get_structure ( archive_number );
412 
413     if (!archive)
414 	return FALSE;
415 
416     /* we free the last date */
417     if ( archive -> beginning_date )
418 	g_date_free (archive -> beginning_date);
419 
420     /* and copy the new one */
421     archive -> beginning_date = gsb_date_copy (date);
422 
423     return TRUE;
424 }
425 
426 
427 /**
428  * return the end date of the archive
429  *
430  * \param archive_number the number of the archive
431  *
432  * \return the end date of the archive or NULL if fail
433  * */
gsb_data_archive_get_end_date(gint archive_number)434 GDate *gsb_data_archive_get_end_date ( gint archive_number )
435 {
436     struct_archive *archive;
437 
438     archive = gsb_data_archive_get_structure ( archive_number );
439 
440     if (!archive)
441 	return NULL;
442 
443     return archive -> end_date;
444 }
445 
446 
447 /**
448  * set the end date of the archive
449  * the value is dupplicate in memory
450  *
451  * \param archive_number the number of the archive
452  * \param date the end date of the archive
453  *
454  * \return TRUE if ok or FALSE if problem
455  * */
gsb_data_archive_set_end_date(gint archive_number,const GDate * date)456 gboolean gsb_data_archive_set_end_date ( gint archive_number,
457                         const GDate *date )
458 {
459     struct_archive *archive;
460 
461     archive = gsb_data_archive_get_structure ( archive_number );
462 
463     if (!archive)
464 	return FALSE;
465 
466     /* we free the last date */
467     if ( archive -> end_date )
468 	g_date_free (archive -> end_date);
469 
470     /* and copy the new one */
471     archive -> end_date = gsb_date_copy (date);
472 
473     return TRUE;
474 }
475 
476 /**
477  * return the fyear of the archive
478  *
479  * \param archive_number the number of the archive
480  *
481  * \return the fyear of the archive or 0 if fail
482  * */
gsb_data_archive_get_fyear(gint archive_number)483 gint gsb_data_archive_get_fyear ( gint archive_number )
484 {
485     struct_archive *archive;
486 
487     archive = gsb_data_archive_get_structure ( archive_number );
488 
489     if (!archive)
490 	return 0;
491 
492     return archive -> fyear_number;
493 }
494 
495 
496 /**
497  * set the fyear of the archive
498  *
499  * \param archive_number the number of the archive
500  * \param fyear_number the fyear of the archive
501  *
502  * \return TRUE if ok or FALSE if problem
503  * */
gsb_data_archive_set_fyear(gint archive_number,gint fyear_number)504 gboolean gsb_data_archive_set_fyear ( gint archive_number,
505                         gint fyear_number )
506 {
507     struct_archive *archive;
508 
509     archive = gsb_data_archive_get_structure ( archive_number );
510 
511     if (!archive)
512 	return FALSE;
513 
514     archive -> fyear_number = fyear_number;
515 
516     return TRUE;
517 }
518 
519 
520 /**
521  * return the report creation of the archive
522  *
523  * \param archive_number the number of the archive
524  *
525  * \return the report_title or NULL
526  * */
gsb_data_archive_get_report_title(gint archive_number)527 const gchar *gsb_data_archive_get_report_title ( gint archive_number )
528 {
529     struct_archive *archive;
530 
531     archive = gsb_data_archive_get_structure ( archive_number );
532 
533     if (!archive)
534 	return NULL;
535 
536     return archive -> report_title;
537 }
538 
539 
540 /**
541  * set the report_title value,
542  *
543  * \param archive_number the number of the archive
544  * \param report_title the title to set if created by a report
545  *
546  * \return TRUE if ok or FALSE if problem
547  * */
gsb_data_archive_set_report_title(gint archive_number,const gchar * report_title)548 gboolean gsb_data_archive_set_report_title ( gint archive_number,
549                         const gchar *report_title )
550 {
551     struct_archive *archive;
552 
553     archive = gsb_data_archive_get_structure ( archive_number );
554 
555     if (!archive)
556 	return FALSE;
557 
558     if (archive -> report_title)
559 	g_free (archive -> report_title);
560 
561     archive -> report_title = my_strdup (report_title);
562 
563     return TRUE;
564 }
565 
566 
567 
568 /**
569  * get the archive corresponding to the given date
570  * if there is more than 1 archive corresponding to that date, return -1
571  *
572  * \param date
573  *
574  * \return the number of archive, 0 if none on that date, -1 if more than 1 on that date
575  * */
gsb_data_archive_get_from_date(const GDate * date)576 gint gsb_data_archive_get_from_date ( const GDate *date )
577 {
578     GSList *tmp_list;
579     gint return_value = 0;
580 
581     if (!date)
582 	return 0;
583 
584     tmp_list = archive_list;
585     while (tmp_list)
586     {
587 	struct_archive *archive;
588 
589 	archive = tmp_list -> data;
590 
591 	/* check the archive only if the dates are valid */
592 	if (archive -> beginning_date && archive -> end_date)
593 	{
594 	    if ( g_date_compare ( date, archive -> beginning_date) >= 0
595 		 &&
596 		 g_date_compare ( date, archive -> end_date) <= 0 )
597 	    {
598 		if (return_value)
599 		    return_value = -1;
600 		else
601 		    return_value = archive -> archive_number;
602 	    }
603 	}
604 	tmp_list = tmp_list -> next;
605     }
606     return return_value;
607 }
608 
609 
610 
611 
612 /**
613  * get the archive corresponding to the given financial year
614  *
615  * \param fyear_number
616  *
617  * \return the number of archive, 0 if none
618  * */
gsb_data_archive_get_from_fyear(gint fyear_number)619 gint gsb_data_archive_get_from_fyear ( gint fyear_number )
620 {
621     GSList *tmp_list;
622 
623     tmp_list = archive_list;
624     while (tmp_list)
625     {
626 	struct_archive *archive;
627 
628 	archive = tmp_list -> data;
629 
630 	if (archive -> fyear_number == fyear_number)
631 	    return archive -> archive_number;
632 
633 	tmp_list = tmp_list -> next;
634     }
635     return 0;
636 }
637 
638 
639 
640