X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fhomebank;a=blobdiff_plain;f=src%2Fhb-archive.c;h=cbb732883fd598b6d53f70e06dd497dc69a80a7a;hp=43cfbeac68dc2908a8908a31185bd89c0fe35733;hb=HEAD;hpb=2ef3e601408ebaeeaf5f40d6967664b012a49979 diff --git a/src/hb-archive.c b/src/hb-archive.c index 43cfbea..cbb7328 100644 --- a/src/hb-archive.c +++ b/src/hb-archive.c @@ -1,5 +1,5 @@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2017 Maxime DOYEN + * Copyright (C) 1995-2019 Maxime DOYEN * * This file is part of HomeBank. * @@ -36,14 +36,60 @@ extern struct HomeBank *GLOBALS; -/* = = = = = = = = = = = = = = = = = = = = */ -/* Archive */ +/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ + + +static void +da_archive_clean(Archive *item) +{ + if(item != NULL) + { + if(item->memo != NULL) + { + g_free(item->memo); + item->memo = NULL; + } + + + + + + //5.3 added as it was a leak + if(item->tags != NULL) + { + g_free(item->tags); + item->tags = NULL; + } + if(item->splits != NULL) + { + da_split_destroy(item->splits); + item->splits = NULL; + item->flags &= ~(OF_SPLIT); //Flag that Splits are cleared + } + } +} + + +void da_archive_free(Archive *item) +{ + if(item != NULL) + { + da_archive_clean(item); + g_free(item); + } +} + Archive *da_archive_malloc(void) { - return g_malloc0(sizeof(Archive)); +Archive *item; + + item = g_malloc0(sizeof(Archive)); + item->key = 1; + return item; } + Archive *da_archive_clone(Archive *src_item) { Archive *new_item = g_memdup(src_item, sizeof(Archive)); @@ -51,27 +97,21 @@ Archive *new_item = g_memdup(src_item, sizeof(Archive)); if(new_item) { //duplicate the string - new_item->wording = g_strdup(src_item->wording); - - if( da_splits_clone(src_item->splits, new_item->splits) > 0) + new_item->memo = g_strdup(src_item->memo); + + //duplicate tags + //no g_free here to avoid free the src tags (memdup copie dthe ptr) + new_item->tags = tags_clone(src_item->tags); + + //duplicate splits + //no g_free here to avoid free the src tags (memdup copie dthe ptr) + new_item->splits = da_splits_clone(src_item->splits); + if( da_splits_length (new_item->splits) > 0 ) new_item->flags |= OF_SPLIT; //Flag that Splits are active } return new_item; } -void da_archive_free(Archive *item) -{ - if(item != NULL) - { - if(item->wording != NULL) - g_free(item->wording); - - da_splits_free(item->splits); - //item->flags &= ~(OF_SPLIT); //Flag that Splits are cleared - - g_free(item); - } -} void da_archive_destroy(GList *list) { @@ -86,9 +126,13 @@ GList *tmplist = g_list_first(list); g_list_free(list); } + +/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ + + static gint da_archive_glist_compare_func(Archive *a, Archive *b) { - return hb_string_utf8_compare(a->wording, b->wording); + return hb_string_utf8_compare(a->memo, b->memo); } @@ -97,16 +141,77 @@ GList *da_archive_sort(GList *list) return g_list_sort(list, (GCompareFunc)da_archive_glist_compare_func); } + guint da_archive_length(void) { return g_list_length(GLOBALS->arc_list); } + +/* append a fav with an existing key (from xml file only) */ +gboolean +da_archive_append(Archive *item) +{ + GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, item); + return TRUE; +} + + +gboolean +da_archive_append_new(Archive *item) +{ + item->key = da_archive_get_max_key() + 1; + GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, item); + return TRUE; +} + + +guint32 +da_archive_get_max_key(void) +{ +GList *tmplist = g_list_first(GLOBALS->arc_list); +guint32 max_key = 0; + + while (tmplist != NULL) + { + Archive *item = tmplist->data; + + max_key = MAX(item->key, max_key); + tmplist = g_list_next(tmplist); + } + + return max_key; +} + + +Archive * +da_archive_get(guint32 key) +{ +GList *tmplist; +Archive *retval = NULL; + + tmplist = g_list_first(GLOBALS->arc_list); + while (tmplist != NULL) + { + Archive *item = tmplist->data; + + if(item->key == key) + { + retval = item; + break; + } + tmplist = g_list_next(tmplist); + } + return retval; +} + + void da_archive_consistency(Archive *item) { Account *acc; Category *cat; Payee *pay; +guint nbsplit; // check category exists cat = da_cat_get(item->kcat); @@ -116,8 +221,19 @@ Payee *pay; item->kcat = 0; GLOBALS->changes_count++; } - - split_cat_consistency(item->splits); + + //#1340142 check split category + if( item->splits != NULL ) + { + nbsplit = da_splits_consistency(item->splits); + //# 1416624 empty category when split + if(nbsplit > 0 && item->kcat > 0) + { + g_warning("txn consistency: fixed invalid cat on split txn"); + item->kcat = 0; + GLOBALS->changes_count++; + } + } // check payee exists pay = da_pay_get(item->kpay); @@ -148,37 +264,41 @@ Payee *pay; Archive *da_archive_init_from_transaction(Archive *arc, Transaction *txn) { + DB( g_print("\n[scheduled] init from txn\n") ); + //fill it arc->amount = txn->amount; arc->kacc = txn->kacc; arc->kxferacc = txn->kxferacc; - arc->paymode = txn->paymode; - arc->flags = txn->flags & (OF_INCOME); + arc->paymode = txn->paymode; + arc->flags = txn->flags & (OF_INCOME); arc->status = txn->status; - arc->kpay = txn->kpay; + arc->kpay = txn->kpay; arc->kcat = txn->kcat; - if(txn->wording != NULL) - arc->wording = g_strdup(txn->wording); + if(txn->memo != NULL) + arc->memo = g_strdup(txn->memo); else - arc->wording = g_strdup(_("(new archive)")); + arc->memo = g_strdup(_("(new archive)")); - if( da_splits_clone(txn->splits, arc->splits) > 0) + arc->tags = tags_clone(txn->tags); + arc->splits = da_splits_clone(txn->splits); + if( da_splits_length (arc->splits) > 0 ) arc->flags |= OF_SPLIT; //Flag that Splits are active return arc; } - - -static guint32 _sched_date_get_next_post(Archive *arc, guint32 nextdate) +static guint32 _sched_date_get_next_post(GDate *tmpdate, Archive *arc, guint32 nextdate) { -GDate *tmpdate; guint32 nextpostdate = nextdate; - DB( g_print("\n[scheduled] _sched_date_get_next_post\n") ); + //DB( g_print("\n[scheduled] date_get_next_post\n") ); + + g_date_set_julian(tmpdate, nextpostdate); + + //DB( g_print("in : %2d-%2d-%4d\n", g_date_get_day(tmpdate), g_date_get_month (tmpdate), g_date_get_year(tmpdate) ) ); - tmpdate = g_date_new_julian(nextpostdate); switch(arc->unit) { case AUTO_UNIT_DAY: @@ -195,9 +315,11 @@ guint32 nextpostdate = nextdate; break; } + //DB( g_print("out: %2d-%2d-%4d\n", g_date_get_day(tmpdate), g_date_get_month (tmpdate), g_date_get_year(tmpdate) ) ); + + /* get the final post date and free */ nextpostdate = g_date_get_julian(tmpdate); - g_date_free(tmpdate); return nextpostdate; } @@ -222,7 +344,7 @@ GDateWeekday wday; guint32 finalpostdate; gint shift; - DB( g_print("\n[scheduled] scheduled_get_postdate\n") ); + DB( g_print("\n[scheduled] get_postdate\n") ); finalpostdate = postdate; @@ -233,7 +355,7 @@ gint shift; { wday = g_date_get_weekday(tmpdate); - DB( g_print(" %s wday=%d\n", arc->wording, wday) ); + DB( g_print(" %s wday=%d\n", arc->memo, wday) ); if( wday >= G_DATE_SATURDAY ) { @@ -264,10 +386,14 @@ gint shift; guint32 scheduled_get_latepost_count(Archive *arc, guint32 jrefdate) { -guint32 curdate = jrefdate - arc->nextdate; +GDate *post_date; +guint32 curdate; guint32 nblate = 0; + //DB( g_print("\n[scheduled] get_latepost_count\n") ); + /* + curdate = jrefdate - arc->nextdate; switch(arc->unit) { case AUTO_UNIT_DAY: @@ -303,16 +429,21 @@ guint32 nblate = 0; // pre 5.1 way + post_date = g_date_new(); curdate = arc->nextdate; while(curdate <= jrefdate) { - curdate = _sched_date_get_next_post(arc, curdate); + curdate = _sched_date_get_next_post(post_date, arc, curdate); nblate++; // break if over limit or at 11 max (to display +10) - if(nblate >= arc->limit || nblate >= 11) + if( nblate >= 11 || ( (arc->flags & OF_LIMIT) && (nblate >= arc->limit) ) ) break; } + //DB( g_print(" nblate=%d\n", nblate) ); + + g_date_free(post_date); + return nblate; } @@ -320,8 +451,45 @@ guint32 nblate = 0; /* return 0 is max number of post is reached */ guint32 scheduled_date_advance(Archive *arc) { - arc->nextdate = _sched_date_get_next_post(arc, arc->nextdate); - +GDate *post_date; +gushort lastday; + + DB( g_print("\n[scheduled] date_advance\n") ); + + DB( g_print(" arc: '%s'\n", arc->memo ) ); + + post_date = g_date_new(); + g_date_set_julian(post_date, arc->nextdate); + // saved the current day number + lastday = g_date_get_day(post_date); + + arc->nextdate = _sched_date_get_next_post(post_date, arc, arc->nextdate); + + DB( g_print(" raw next post date: %2d-%2d-%4d\n", g_date_get_day(post_date), g_date_get_month (post_date), g_date_get_year(post_date) ) ); + + //for day > 28 we might have a gap to compensate later + if( (arc->unit==AUTO_UNIT_MONTH) || (arc->unit==AUTO_UNIT_YEAR) ) + { + if( lastday >= 28 ) + { + DB( g_print(" lastday:%d, daygap:%d\n", lastday, arc->daygap) ); + if( arc->daygap > 0 ) + { + g_date_add_days (post_date, arc->daygap); + arc->nextdate = g_date_get_julian (post_date); + lastday += arc->daygap; + DB( g_print(" adjusted post date: %2d-%2d-%4d\n", g_date_get_day(post_date), g_date_get_month (post_date), g_date_get_year(post_date) ) ); + } + + arc->daygap = CLAMP(lastday - g_date_get_day(post_date), 0, 3); + + DB( g_print(" daygap is %d\n", arc->daygap) ); + } + else + arc->daygap = 0; + } + + //#1556289 /* check limit, update and maybe break */ if(arc->flags & OF_LIMIT) @@ -333,7 +501,9 @@ guint32 scheduled_date_advance(Archive *arc) arc->nextdate = 0; } } - + + g_date_free(post_date); + return arc->nextdate; } @@ -399,7 +569,7 @@ Transaction *txn; { Archive *arc = list->data; - DB( g_print("\n eval %d for '%s'\n", scheduled_is_postable(arc), arc->wording) ); + DB( g_print("\n eval %d for '%s'\n", scheduled_is_postable(arc), arc->memo) ); if(scheduled_is_postable(arc) == TRUE) { @@ -412,13 +582,13 @@ Transaction *txn; while(mydate < maxpostdate) { - DB( hb_print_date(mydate, arc->wording) ); + DB( hb_print_date(mydate, arc->memo) ); da_transaction_init_from_template(txn, arc); txn->date = scheduled_get_postdate(arc, mydate); /* todo: ? fill in cheque number */ - transaction_add(txn, NULL, 0); + transaction_add(NULL, txn); GLOBALS->changes_count++; count++;