1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2016 Maxime DOYEN
4 * This file is part of HomeBank.
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "hb-transaction.h"
29 /****************************************************************************/
31 /****************************************************************************/
40 /* our global datas */
41 extern struct HomeBank
*GLOBALS
;
42 extern struct Preferences
*PREFS
;
45 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
48 da_transaction_clean(Transaction
*item
)
52 if(item
->wording
!= NULL
)
54 g_free(item
->wording
);
57 if(item
->info
!= NULL
)
62 if(item
->tags
!= NULL
)
64 DB( g_print(" -> item->tags %p\n", item
->tags
) );
69 da_splits_free(item
->splits
);
70 item
->flags
&= ~(OF_SPLIT
); //Flag that Splits are cleared
72 if(item
->same
!= NULL
)
74 g_list_free(item
->same
);
83 da_transaction_free(Transaction
*item
)
87 da_transaction_clean(item
);
94 da_transaction_malloc(void)
96 return rc_alloc(sizeof(Transaction
));
100 Transaction
*da_transaction_copy(Transaction
*src_txn
, Transaction
*dst_txn
)
102 DB( g_print("da_transaction_copy\n") );
104 da_transaction_clean (dst_txn
);
106 memmove(dst_txn
, src_txn
, sizeof(Transaction
));
108 //duplicate the string
109 dst_txn
->wording
= g_strdup(src_txn
->wording
);
110 dst_txn
->info
= g_strdup(src_txn
->info
);
113 transaction_tags_clone(src_txn
, dst_txn
);
115 if (da_splits_clone(src_txn
->splits
, dst_txn
->splits
) > 0)
116 dst_txn
->flags
|= OF_SPLIT
; //Flag that Splits are active
122 Transaction
*da_transaction_init_from_template(Transaction
*txn
, Archive
*arc
)
125 txn
->amount
= arc
->amount
;
126 //#1258344 keep the current account if tpl is empty
128 txn
->kacc
= arc
->kacc
;
129 txn
->paymode
= arc
->paymode
;
130 txn
->flags
= arc
->flags
| OF_ADDED
;
131 txn
->status
= arc
->status
;
132 txn
->kpay
= arc
->kpay
;
133 txn
->kcat
= arc
->kcat
;
134 txn
->kxferacc
= arc
->kxferacc
;
135 txn
->wording
= g_strdup(arc
->wording
);
137 if( da_splits_clone(arc
->splits
, txn
->splits
) > 0)
138 txn
->flags
|= OF_SPLIT
; //Flag that Splits are active
144 Transaction
*da_transaction_clone(Transaction
*src_item
)
146 Transaction
*new_item
= rc_dup(src_item
, sizeof(Transaction
));
148 DB( g_print("da_transaction_clone\n") );
152 //duplicate the string
153 new_item
->wording
= g_strdup(src_item
->wording
);
154 new_item
->info
= g_strdup(src_item
->info
);
157 transaction_tags_clone(src_item
, new_item
);
159 if( da_splits_clone(src_item
->splits
, new_item
->splits
) > 0)
160 new_item
->flags
|= OF_SPLIT
; //Flag that Splits are active
168 da_transaction_new(void)
175 da_transaction_length(void)
177 GList
*lst_acc
, *lnk_acc
;
180 lst_acc
= g_hash_table_get_values(GLOBALS
->h_acc
);
181 lnk_acc
= g_list_first(lst_acc
);
182 while (lnk_acc
!= NULL
)
184 Account
*acc
= lnk_acc
->data
;
186 count
+= g_queue_get_length (acc
->txn_queue
);
187 lnk_acc
= g_list_next(lnk_acc
);
189 g_list_free(lst_acc
);
194 static void da_transaction_queue_free_ghfunc(Transaction
*item
, gpointer data
)
196 da_transaction_free (item
);
200 void da_transaction_destroy(void)
204 lacc
= g_hash_table_get_values(GLOBALS
->h_acc
);
205 list
= g_list_first(lacc
);
208 Account
*acc
= list
->data
;
210 g_queue_foreach(acc
->txn_queue
, (GFunc
)da_transaction_queue_free_ghfunc
, NULL
);
211 list
= g_list_next(list
);
217 static gint
da_transaction_compare_datafunc(Transaction
*a
, Transaction
*b
, gpointer data
)
219 return ((gint
)a
->date
- b
->date
);
223 void da_transaction_queue_sort(GQueue
*queue
)
225 g_queue_sort(queue
, (GCompareDataFunc
)da_transaction_compare_datafunc
, NULL
);
229 static gint
da_transaction_compare_func(Transaction
*a
, Transaction
*b
)
231 return ((gint
)a
->date
- b
->date
);
235 GList
*da_transaction_sort(GList
*list
)
237 return( g_list_sort(list
, (GCompareFunc
)da_transaction_compare_func
));
241 static void da_transaction_insert_memo(Transaction
*item
)
243 // append the memo if new
244 if( item
->wording
!= NULL
)
246 if( g_hash_table_lookup(GLOBALS
->h_memo
, item
->wording
) == NULL
)
248 g_hash_table_insert(GLOBALS
->h_memo
, g_strdup(item
->wording
), NULL
);
254 gboolean
da_transaction_insert_sorted(Transaction
*newitem
)
259 acc
= da_acc_get(newitem
->kacc
);
263 lnk_txn
= g_queue_peek_tail_link(acc
->txn_queue
);
264 while (lnk_txn
!= NULL
)
266 Transaction
*item
= lnk_txn
->data
;
268 if(item
->date
<= newitem
->date
)
271 lnk_txn
= g_list_previous(lnk_txn
);
274 // we're at insert point, insert after txn
275 g_queue_insert_after(acc
->txn_queue
, lnk_txn
, newitem
);
277 da_transaction_insert_memo(newitem
);
282 // nota: this is called only when loading xml file
283 gboolean
da_transaction_prepend(Transaction
*item
)
287 acc
= da_acc_get(item
->kacc
);
289 item
->kcur
= acc
->kcur
;
290 g_queue_push_tail(acc
->txn_queue
, item
);
291 da_transaction_insert_memo(item
);
296 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
299 da_transaction_get_max_kxfer(void)
301 GList
*lst_acc
, *lnk_acc
;
305 DB( g_print("da_transaction_get_max_kxfer\n") );
307 lst_acc
= g_hash_table_get_values(GLOBALS
->h_acc
);
308 lnk_acc
= g_list_first(lst_acc
);
309 while (lnk_acc
!= NULL
)
311 Account
*acc
= lnk_acc
->data
;
313 list
= g_queue_peek_head_link(acc
->txn_queue
);
316 Transaction
*item
= list
->data
;
318 if( item
->paymode
== PAYMODE_INTXFER
)
320 max_key
= MAX(max_key
, item
->kxfer
);
322 list
= g_list_next(list
);
325 lnk_acc
= g_list_next(lnk_acc
);
327 g_list_free(lst_acc
);
329 DB( g_print(" max_key : %d \n", max_key
) );
335 static void da_transaction_goto_orphan(Transaction
*txn
)
337 const gchar
*oatn
= "orphaned transactions";
340 acc
= da_acc_get_by_name((gchar
*)oatn
);
343 acc
= da_acc_malloc();
344 acc
->name
= g_strdup(oatn
);
347 txn
->kacc
= acc
->key
;
351 void da_transaction_consistency(Transaction
*item
)
358 // ensure date is between range
359 item
->date
= CLAMP(item
->date
, HB_MINDATE
, HB_MAXDATE
);
361 // check account exists
362 acc
= da_acc_get(item
->kacc
);
365 g_warning("txn consistency: fixed invalid acc %d", item
->kacc
);
366 da_transaction_goto_orphan(item
);
367 GLOBALS
->changes_count
++;
370 // check category exists
371 cat
= da_cat_get(item
->kcat
);
374 g_warning("txn consistency: fixed invalid cat %d", item
->kcat
);
376 GLOBALS
->changes_count
++;
379 // check split category #1340142
380 split_cat_consistency(item
->splits
);
382 //# 1416624 empty category when split
383 nbsplit
= da_splits_count(item
->splits
);
384 if(nbsplit
> 0 && item
->kcat
> 0)
386 g_warning("txn consistency: fixed invalid cat on split txn");
388 GLOBALS
->changes_count
++;
391 // check payee exists
392 pay
= da_pay_get(item
->kpay
);
395 g_warning("txn consistency: fixed invalid pay %d", item
->kpay
);
397 GLOBALS
->changes_count
++;
400 // reset dst acc for non xfer transaction
401 if( item
->paymode
!= PAYMODE_INTXFER
)
404 //#1628678 tags for internal xfer should be checked as well
407 //#1295877 ensure income flag is correctly set
408 item
->flags
&= ~(OF_INCOME
);
409 if( item
->amount
> 0)
410 item
->flags
|= (OF_INCOME
);
412 //#1308745 ensure remind flag unset if reconciled
414 //if( item->flags & OF_VALID )
415 // item->flags &= ~(OF_REMIND);
420 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
421 /* new transfer functions */
423 static void transaction_xfer_create_child(Transaction
*ope
)
429 DB( g_print("\n[transaction] transaction_xfer_create_child\n") );
431 if( ope
->kxferacc
> 0 )
433 child
= da_transaction_clone(ope
);
435 ope
->flags
|= OF_CHANGED
;
436 child
->flags
|= OF_ADDED
;
438 child
->amount
= -child
->amount
;
439 child
->flags
^= (OF_INCOME
); // invert flag
441 child
->status
= TXN_STATUS_NONE
;
442 //child->flags &= ~(OF_VALID); // delete reconcile state
445 child
->kacc
= child
->kxferacc
;
446 child
->kxferacc
= swap
;
448 /* update acc flags */
449 acc
= da_acc_get( child
->kacc
);
452 acc
->flags
|= AF_ADDED
;
455 guint maxkey
= da_transaction_get_max_kxfer();
457 DB( g_print(" + maxkey is %d\n", maxkey
) );
460 ope
->kxfer
= maxkey
+1;
461 child
->kxfer
= maxkey
+1;
463 DB( g_print(" + strong link to %d\n", ope
->kxfer
) );
466 DB( g_print(" + add transfer, %p\n", child
) );
468 da_transaction_insert_sorted(child
);
470 account_balances_add (child
);
472 GValue txn_value
= G_VALUE_INIT
;
473 ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value
, child
), NULL
);
481 //todo: add strong control and extend to payee, maybe memo ?
482 static gboolean
transaction_xfer_child_might(Transaction
*stxn
, Transaction
*dtxn
, gint daygap
)
484 gboolean retval
= FALSE
;
491 g_print(" %d %d %d %f %d\n",
492 stxn->kcur, stxn->date, stxn->kacc, ABS(stxn->amount), stxn->kxfer );
495 g_print(" %d %d %d %f %d\n",
496 dtxn->kcur, dtxn->date, dtxn->kacc, ABS(dtxn->amount), dtxn->kxfer );
499 if( stxn
->kcur
== dtxn
->kcur
&&
500 stxn
->date
== dtxn
->date
&&
501 //v5.1 make no sense: stxn->kxferacc == dtxn->kacc &&
502 stxn
->kacc
!= dtxn
->kacc
&&
503 ABS(stxn
->amount
) == ABS(dtxn
->amount
) &&
509 //g_print(" return %d\n", retval);
514 static GList
*transaction_xfer_child_might_list_get(Transaction
*ope
)
516 GList
*lst_acc
, *lnk_acc
;
517 GList
*list
, *matchlist
= NULL
;
519 DB( g_print("\n[transaction]xfer_get_potential_child\n") );
521 lst_acc
= g_hash_table_get_values(GLOBALS
->h_acc
);
522 lnk_acc
= g_list_first(lst_acc
);
523 while (lnk_acc
!= NULL
)
525 Account
*acc
= lnk_acc
->data
;
527 if( !(acc
->flags
& AF_CLOSED
) && (acc
->key
!= ope
->kacc
) )
529 list
= g_queue_peek_tail_link(acc
->txn_queue
);
532 Transaction
*item
= list
->data
;
534 // no need to go higher than src txn date
535 if(item
->date
< ope
->date
)
538 if( transaction_xfer_child_might(ope
, item
, 0) == TRUE
)
540 //DB( g_print(" - match : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->account, item->kxferacc) );
541 matchlist
= g_list_append(matchlist
, item
);
543 list
= g_list_previous(list
);
547 lnk_acc
= g_list_next(lnk_acc
);
549 g_list_free(lst_acc
);
555 void transaction_xfer_search_or_add_child(GtkWindow
*parentwindow
, Transaction
*ope
, gboolean manual
)
560 DB( g_print("\n[transaction] transaction_xfer_search_or_add_child\n") );
562 matchlist
= transaction_xfer_child_might_list_get(ope
);
563 count
= g_list_length(matchlist
);
565 DB( g_print(" - found result is %d, switching\n", count
) );
569 case 0: //we should create the child
570 transaction_xfer_create_child(ope
);
573 //todo: maybe with just 1 match the user must choose ?
574 //#942346: bad idea so to no let the user confirm, so let hil confirm
576 case 1: //transform the transaction to a child transfer
578 GList *list = g_list_first(matchlist);
579 transaction_xfer_change_to_child(ope, list->data);
584 default: //the user must choose himself
588 child
= ui_dialog_transaction_xfer_select_child(ope
, matchlist
);
590 transaction_xfer_create_child(ope
);
592 transaction_xfer_change_to_child(ope
, child
);
596 g_list_free(matchlist
);
600 Transaction
*transaction_xfer_child_strong_get(Transaction
*src
)
605 DB( g_print("\n[transaction] transaction_xfer_child_strong_get\n") );
607 dstacc
= da_acc_get(src
->kxferacc
);
608 if( !dstacc
|| src
->kxfer
<= 0 )
611 DB( g_print(" - search: %d %s %f %d=>%d - %d\n", src
->date
, src
->wording
, src
->amount
, src
->kacc
, src
->kxferacc
, src
->kxfer
) );
613 list
= g_queue_peek_tail_link(dstacc
->txn_queue
);
616 Transaction
*item
= list
->data
;
619 //if( item->paymode == PAYMODE_INTXFER
620 // && item->kacc == src->kxferacc
621 // && item->kxfer == src->kxfer )
622 if( item
->paymode
== PAYMODE_INTXFER
623 && item
->kxfer
== src
->kxfer
626 DB( g_print(" - found : %d %s %f %d=>%d - %d\n", item
->date
, item
->wording
, item
->amount
, item
->kacc
, item
->kxferacc
, src
->kxfer
) );
629 list
= g_list_previous(list
);
632 DB( g_print(" - not found...\n") );
639 void transaction_xfer_change_to_child(Transaction
*ope
, Transaction
*child
)
643 DB( g_print("\n[transaction] transaction_xfer_change_to_child\n") );
645 if(ope
->kcur
!= child
->kcur
)
648 ope
->flags
|= OF_CHANGED
;
649 child
->flags
|= OF_CHANGED
;
651 child
->paymode
= PAYMODE_INTXFER
;
653 ope
->kxferacc
= child
->kacc
;
654 child
->kxferacc
= ope
->kacc
;
656 /* update acc flags */
657 dstacc
= da_acc_get( child
->kacc
);
659 dstacc
->flags
|= AF_CHANGED
;
662 guint maxkey
= da_transaction_get_max_kxfer();
663 ope
->kxfer
= maxkey
+1;
664 child
->kxfer
= maxkey
+1;
669 void transaction_xfer_sync_child(Transaction
*s_txn
, Transaction
*child
)
672 DB( g_print("\n[transaction] transaction_xfer_sync_child\n") );
674 account_balances_sub (child
);
676 child
->date
= s_txn
->date
;
677 child
->amount
= -s_txn
->amount
;
678 child
->flags
= child
->flags
| OF_CHANGED
;
680 child
->flags
&= ~(OF_INCOME
);
681 if( child
->amount
> 0)
682 child
->flags
|= (OF_INCOME
);
683 child
->kpay
= s_txn
->kpay
;
684 child
->kcat
= s_txn
->kcat
;
686 g_free(child
->wording
);
687 child
->wording
= g_strdup(s_txn
->wording
);
690 child
->info
= g_strdup(s_txn
->info
);
692 //#1252230 sync account also
693 child
->kacc
= s_txn
->kxferacc
;
694 child
->kxferacc
= s_txn
->kacc
;
696 account_balances_add (child
);
698 //synchronise tags since 5.1
701 transaction_tags_clone (s_txn
, child
);
706 void transaction_xfer_remove_child(Transaction
*src
)
710 DB( g_print("\n[transaction] transaction_xfer_remove_child\n") );
712 dst
= transaction_xfer_child_strong_get( src
);
714 DB( g_print(" -> return is %s, %p\n", dst
->wording
, dst
) );
718 Account
*acc
= da_acc_get(dst
->kacc
);
720 DB( g_print("deleting...") );
723 account_balances_sub(dst
);
724 g_queue_remove(acc
->txn_queue
, dst
);
725 da_transaction_free (dst
);
730 // still useful for upgrade from < file v0.6 (hb v4.4 kxfer)
731 Transaction
*transaction_old_get_child_transfer(Transaction
*src
)
736 DB( g_print("\n[transaction] transaction_get_child_transfer\n") );
738 //DB( g_print(" search: %d %s %f %d=>%d\n", src->date, src->wording, src->amount, src->account, src->kxferacc) );
739 acc
= da_acc_get(src
->kxferacc
);
741 list
= g_queue_peek_head_link(acc
->txn_queue
);
744 Transaction
*item
= list
->data
;
746 // no need to go higher than src txn date
747 if(item
->date
> src
->date
)
750 if( item
->paymode
== PAYMODE_INTXFER
)
752 if( src
->date
== item
->date
&&
753 src
->kacc
== item
->kxferacc
&&
754 src
->kxferacc
== item
->kacc
&&
755 ABS(src
->amount
) == ABS(item
->amount
) )
757 //DB( g_print(" found : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->account, item->kxferacc) );
762 list
= g_list_next(list
);
765 DB( g_print(" not found...\n") );
771 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
774 void transaction_add(Transaction
*ope
, GtkWidget
*treeview
, guint32 accnum
)
779 DB( g_print("\n[transaction] transaction add\n") );
781 //controls accounts valid (archive scheduled maybe bad)
782 acc
= da_acc_get(ope
->kacc
);
783 if(acc
== NULL
) return;
785 ope
->kcur
= acc
->kcur
;
787 if(ope
->paymode
== PAYMODE_INTXFER
)
789 acc
= da_acc_get(ope
->kxferacc
);
790 if(acc
== NULL
) return;
793 da_splits_free(ope
->splits
);
794 ope
->flags
&= ~(OF_SPLIT
); //Flag that Splits are cleared
797 //allocate a new entry and copy from our edited structure
798 newope
= da_transaction_clone(ope
);
800 //init flag and keep remind status
801 // already done in deftransaction_get
802 //ope->flags |= (OF_ADDED);
803 //remind = (ope->flags & OF_REMIND) ? TRUE : FALSE;
804 //ope->flags &= (~OF_REMIND);
806 /* cheque number is already stored in deftransaction_get */
807 /* todo:move this to transaction add
808 store a new cheque number into account ? */
810 if( (newope
->paymode
== PAYMODE_CHECK
) && (newope
->info
) && !(newope
->flags
& OF_INCOME
) )
814 /* get the active account and the corresponding cheque number */
815 acc
= da_acc_get( newope
->kacc
);
816 cheque
= atol(newope
->info
);
818 //DB( g_print(" -> should store cheque number %d to %d", cheque, newope->account) );
819 if( newope
->flags
& OF_CHEQ2
)
821 acc
->cheque2
= MAX(acc
->cheque2
, cheque
);
825 acc
->cheque1
= MAX(acc
->cheque1
, cheque
);
829 /* add normal transaction */
830 acc
= da_acc_get( newope
->kacc
);
833 acc
->flags
|= AF_ADDED
;
835 DB( g_print(" + add normal %p\n", newope
) );
836 //da_transaction_append(newope);
837 da_transaction_insert_sorted(newope
);
840 transaction_add_treeview(newope
, treeview
, accnum
);
842 account_balances_add(newope
);
844 if(newope
->paymode
== PAYMODE_INTXFER
)
846 transaction_xfer_search_or_add_child(NULL
, newope
, FALSE
);
849 GValue txn_value
= G_VALUE_INIT
;
850 ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value
, newope
), NULL
);
855 void transaction_add_treeview(Transaction
*ope
, GtkWidget
*treeview
, guint32 accnum
)
860 //GtkTreeSelection *sel;
862 DB( g_print("\n[transaction] transaction add treeview\n") );
864 if(ope
->kacc
== accnum
)
866 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(treeview
));
867 gtk_list_store_append (GTK_LIST_STORE(model
), &iter
);
869 gtk_list_store_set (GTK_LIST_STORE(model
), &iter
,
870 LST_DSPOPE_DATAS
, ope
,
873 //activate that new line
874 //path = gtk_tree_model_get_path(model, &iter);
875 //gtk_tree_view_expand_to_path(GTK_TREE_VIEW(treeview), path);
877 //sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
878 //gtk_tree_selection_select_iter(sel, &iter);
880 //gtk_tree_path_free(path);
886 gboolean
transaction_acc_move(Transaction
*txn
, guint32 okacc
, guint32 nkacc
)
888 Account
*oacc
, *nacc
;
890 oacc
= da_acc_get(okacc
);
891 nacc
= da_acc_get(nkacc
);
894 if( g_queue_remove(oacc
->txn_queue
, txn
) )
896 g_queue_push_tail(nacc
->txn_queue
, txn
);
897 txn
->kacc
= nacc
->key
;
898 txn
->kcur
= nacc
->kcur
;
899 nacc
->flags
|= AF_CHANGED
;
903 //ensure to keep txn into current account
910 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
913 static gboolean
misc_text_match(gchar
*text
, gchar
*searchtext
, gboolean exact
)
915 gboolean match
= FALSE
;
920 //DB( g_print("search %s in %s\n", rul->name, ope->wording) );
921 if( searchtext
!= NULL
)
925 if( g_strrstr(text
, searchtext
) != NULL
)
927 DB( g_print(" found case '%s'\n", searchtext
) );
933 gchar
*word
= g_utf8_casefold(text
, -1);
934 gchar
*needle
= g_utf8_casefold(searchtext
, -1);
936 if( g_strrstr(word
, needle
) != NULL
)
938 DB( g_print(" found nocase '%s'\n", searchtext
) );
949 static gboolean
misc_regex_match(gchar
*text
, gchar
*searchtext
, gboolean exact
)
951 gboolean match
= FALSE
;
956 DB( g_print("match RE %s in %s\n", searchtext
, text
) );
957 if( searchtext
!= NULL
)
959 match
= g_regex_match_simple(searchtext
, text
, ((exact
== TRUE
)?0:G_REGEX_CASELESS
) | G_REGEX_OPTIMIZE
, G_REGEX_MATCH_NOTEMPTY
);
960 if (match
== TRUE
) { DB( g_print(" found pattern '%s'\n", searchtext
) ); }
966 static Assign
*transaction_auto_assign_eval_txn(GList
*l_rul
, Transaction
*txn
)
971 DB( g_print("- eval every rules, and return the last that match\n") );
973 list
= g_list_first(l_rul
);
976 Assign
*rul
= list
->data
;
980 if(rul
->field
== 1) //payee
982 Payee
*pay
= da_pay_get(txn
->kpay
);
987 if( !(rul
->flags
& ASGF_REGEX
) )
989 if( misc_text_match(text
, rul
->text
, rul
->flags
& ASGF_EXACT
) )
994 if( misc_regex_match(text
, rul
->text
, rul
->flags
& ASGF_EXACT
) )
998 list
= g_list_next(list
);
1005 static Assign
*transaction_auto_assign_eval(GList
*l_rul
, gchar
*text
)
1007 Assign
*rule
= NULL
;
1010 DB( g_print("- eval every rules, and return the last that match\n") );
1012 list
= g_list_first(l_rul
);
1013 while (list
!= NULL
)
1015 Assign
*rul
= list
->data
;
1017 if( rul
->field
== 0 ) //memo
1019 if( !(rul
->flags
& ASGF_REGEX
) )
1021 if( misc_text_match(text
, rul
->text
, rul
->flags
& ASGF_EXACT
) )
1026 if( misc_regex_match(text
, rul
->text
, rul
->flags
& ASGF_EXACT
) )
1030 list
= g_list_next(list
);
1037 gint
transaction_auto_assign(GList
*ope_list
, guint32 kacc
)
1043 DB( g_print("\n[transaction] transaction_auto_assign\n") );
1045 l_rul
= g_hash_table_get_values(GLOBALS
->h_rul
);
1047 l_ope
= g_list_first(ope_list
);
1048 while (l_ope
!= NULL
)
1050 Transaction
*ope
= l_ope
->data
;
1051 gboolean changed
= FALSE
;
1053 DB( g_print("- eval ope '%s' : acc=%d, pay=%d, cat=%d\n", ope
->wording
, ope
->kacc
, ope
->kpay
, ope
->kcat
) );
1055 //#1215521: added kacc == 0
1056 if( (kacc
== ope
->kacc
|| kacc
== 0) )
1060 rul
= transaction_auto_assign_eval_txn(l_rul
, ope
);
1063 if( (ope
->kpay
== 0 && (rul
->flags
& ASGF_DOPAY
)) || (rul
->flags
& ASGF_OVWPAY
) )
1065 if(ope
->kpay
!= rul
->kpay
) { changed
= TRUE
; }
1066 ope
->kpay
= rul
->kpay
;
1069 if( !(ope
->flags
& OF_SPLIT
) )
1071 if( (ope
->kcat
== 0 && (rul
->flags
& ASGF_DOCAT
)) || (rul
->flags
& ASGF_OVWCAT
) )
1073 if(ope
->kcat
!= rul
->kcat
) { changed
= TRUE
; }
1074 ope
->kcat
= rul
->kcat
;
1078 if( (ope
->paymode
== 0 && (rul
->flags
& ASGF_DOMOD
)) || (rul
->flags
& ASGF_OVWMOD
) )
1080 //ugly hack - don't allow modify intxfer
1081 if(ope
->paymode
!= PAYMODE_INTXFER
&& rul
->paymode
!= PAYMODE_INTXFER
)
1083 if(ope
->paymode
!= rul
->paymode
) { changed
= TRUE
; }
1084 ope
->paymode
= rul
->paymode
;
1090 if( ope
->flags
& OF_SPLIT
)
1092 guint i
, nbsplit
= da_splits_count(ope
->splits
);
1094 for(i
=0;i
<nbsplit
;i
++)
1096 Split
*split
= ope
->splits
[i
];
1098 DB( g_print("- eval split '%s'\n", split
->memo
) );
1100 rul
= transaction_auto_assign_eval(l_rul
, split
->memo
);
1103 //#1501144: check if user wants to set category in rule
1104 if( (split
->kcat
== 0 || (rul
->flags
& ASGF_OVWCAT
)) && (rul
->flags
& ASGF_DOCAT
) )
1106 if(split
->kcat
!= rul
->kcat
) { changed
= TRUE
; }
1107 split
->kcat
= rul
->kcat
;
1115 ope
->flags
|= OF_CHANGED
;
1120 l_ope
= g_list_next(l_ope
);
1129 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1133 transaction_tags_count(Transaction
*ope
)
1136 guint32
*ptr
= ope
->tags
;
1138 DB( g_print("(transaction_tags_count)\n") );
1140 if( ope
->tags
== NULL
)
1143 while(*ptr
++ != 0 && count
< 32)
1150 void transaction_tags_clone(Transaction
*src_txn
, Transaction
*dst_txn
)
1154 dst_txn
->tags
= NULL
;
1155 count
= transaction_tags_count(src_txn
);
1158 //1501962: we must also copy the final 0
1159 dst_txn
->tags
= g_memdup(src_txn
->tags
, (count
+1)*sizeof(guint32
));
1164 transaction_tags_parse(Transaction
*ope
, const gchar
*tagstring
)
1170 DB( g_print("(transaction_tags_parse)\n") );
1172 DB( g_print(" - tagstring='%s'\n", tagstring
) );
1174 str_array
= g_strsplit (tagstring
, " ", 0);
1175 count
= g_strv_length( str_array
);
1180 DB( g_print(" -> reset storage %p\n", ope
->tags
) );
1186 ope
->tags
= g_new0(guint32
, count
+ 1);
1188 DB( g_print(" -> storage %p\n", ope
->tags
) );
1190 for(i
=0;i
<count
;i
++)
1192 tag
= da_tag_get_by_name(str_array
[i
]);
1195 Tag
*newtag
= da_tag_malloc();
1197 newtag
->name
= g_strdup(str_array
[i
]);
1198 da_tag_append(newtag
);
1199 tag
= da_tag_get_by_name(str_array
[i
]);
1202 DB( g_print(" -> storing %d=>%s at tags pos %d\n", tag
->key
, tag
->name
, i
) );
1204 ope
->tags
[i
] = tag
->key
;
1209 //hex_dump(ope->tags, sizeof(guint32*)*count+1);
1211 g_strfreev (str_array
);
1217 transaction_tags_tostring(Transaction
*ope
)
1224 DB( g_print("transaction_tags_tostring\n") );
1226 DB( g_print(" -> tags at=%p\n", ope
->tags
) );
1228 if( ope
->tags
== NULL
)
1235 count
= transaction_tags_count(ope
);
1237 DB( g_print(" -> tags at=%p, nbtags=%d\n", ope
->tags
, count
) );
1239 str_array
= g_new0(gchar
*, count
+1);
1241 DB( g_print(" -> str_array at %p\n", str_array
) );
1243 //hex_dump(ope->tags, sizeof(guint32*)*(count+1));
1245 for(i
=0;i
<count
;i
++)
1247 DB( g_print(" -> try to get tag %d\n", ope
->tags
[i
]) );
1249 tag
= da_tag_get(ope
->tags
[i
]);
1252 DB( g_print(" -> get %s at %d\n", tag
->name
, i
) );
1253 str_array
[i
] = tag
->name
;
1256 str_array
[i
] = NULL
;
1261 tagstring
= g_strjoinv(" ", str_array
);