1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2017 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"
26 /****************************************************************************/
28 /****************************************************************************/
37 /* our global datas */
38 extern struct HomeBank
*GLOBALS
;
39 extern struct Preferences
*PREFS
;
42 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
45 da_transaction_clean(Transaction
*item
)
49 if(item
->wording
!= NULL
)
51 g_free(item
->wording
);
54 if(item
->info
!= NULL
)
59 if(item
->tags
!= NULL
)
61 DB( g_print(" -> item->tags %p\n", item
->tags
) );
66 da_splits_free(item
->splits
);
67 item
->flags
&= ~(OF_SPLIT
); //Flag that Splits are cleared
69 if(item
->same
!= NULL
)
71 g_list_free(item
->same
);
80 da_transaction_free(Transaction
*item
)
84 da_transaction_clean(item
);
91 da_transaction_malloc(void)
93 return g_malloc0(sizeof(Transaction
));
97 Transaction
*da_transaction_copy(Transaction
*src_txn
, Transaction
*dst_txn
)
99 DB( g_print("da_transaction_copy\n") );
101 da_transaction_clean (dst_txn
);
103 memmove(dst_txn
, src_txn
, sizeof(Transaction
));
105 //duplicate the string
106 dst_txn
->wording
= g_strdup(src_txn
->wording
);
107 dst_txn
->info
= g_strdup(src_txn
->info
);
110 transaction_tags_clone(src_txn
, dst_txn
);
112 if (da_splits_clone(src_txn
->splits
, dst_txn
->splits
) > 0)
113 dst_txn
->flags
|= OF_SPLIT
; //Flag that Splits are active
119 Transaction
*da_transaction_init_from_template(Transaction
*txn
, Archive
*arc
)
122 txn
->amount
= arc
->amount
;
123 //#1258344 keep the current account if tpl is empty
125 txn
->kacc
= arc
->kacc
;
126 txn
->paymode
= arc
->paymode
;
127 txn
->flags
= arc
->flags
| OF_ADDED
;
128 txn
->status
= arc
->status
;
129 txn
->kpay
= arc
->kpay
;
130 txn
->kcat
= arc
->kcat
;
131 txn
->kxferacc
= arc
->kxferacc
;
132 txn
->wording
= g_strdup(arc
->wording
);
134 if( da_splits_clone(arc
->splits
, txn
->splits
) > 0)
135 txn
->flags
|= OF_SPLIT
; //Flag that Splits are active
141 Transaction
*da_transaction_clone(Transaction
*src_item
)
143 Transaction
*new_item
= g_memdup(src_item
, sizeof(Transaction
));
145 DB( g_print("da_transaction_clone\n") );
149 //duplicate the string
150 new_item
->wording
= g_strdup(src_item
->wording
);
151 new_item
->info
= g_strdup(src_item
->info
);
154 transaction_tags_clone(src_item
, new_item
);
156 if( da_splits_clone(src_item
->splits
, new_item
->splits
) > 0)
157 new_item
->flags
|= OF_SPLIT
; //Flag that Splits are active
165 da_transaction_new(void)
172 da_transaction_length(void)
174 GList
*lst_acc
, *lnk_acc
;
177 lst_acc
= g_hash_table_get_values(GLOBALS
->h_acc
);
178 lnk_acc
= g_list_first(lst_acc
);
179 while (lnk_acc
!= NULL
)
181 Account
*acc
= lnk_acc
->data
;
183 count
+= g_queue_get_length (acc
->txn_queue
);
184 lnk_acc
= g_list_next(lnk_acc
);
186 g_list_free(lst_acc
);
191 static void da_transaction_queue_free_ghfunc(Transaction
*item
, gpointer data
)
193 da_transaction_free (item
);
197 void da_transaction_destroy(void)
201 lacc
= g_hash_table_get_values(GLOBALS
->h_acc
);
202 list
= g_list_first(lacc
);
205 Account
*acc
= list
->data
;
207 g_queue_foreach(acc
->txn_queue
, (GFunc
)da_transaction_queue_free_ghfunc
, NULL
);
208 list
= g_list_next(list
);
214 static gint
da_transaction_compare_datafunc(Transaction
*a
, Transaction
*b
, gpointer data
)
216 return ((gint
)a
->date
- b
->date
);
220 void da_transaction_queue_sort(GQueue
*queue
)
222 g_queue_sort(queue
, (GCompareDataFunc
)da_transaction_compare_datafunc
, NULL
);
226 static gint
da_transaction_compare_func(Transaction
*a
, Transaction
*b
)
228 return ((gint
)a
->date
- b
->date
);
232 GList
*da_transaction_sort(GList
*list
)
234 return( g_list_sort(list
, (GCompareFunc
)da_transaction_compare_func
));
238 static void da_transaction_insert_memo(Transaction
*item
)
240 // append the memo if new
241 if( item
->wording
!= NULL
)
243 if( g_hash_table_lookup(GLOBALS
->h_memo
, item
->wording
) == NULL
)
245 g_hash_table_insert(GLOBALS
->h_memo
, g_strdup(item
->wording
), NULL
);
251 gboolean
da_transaction_insert_sorted(Transaction
*newitem
)
256 acc
= da_acc_get(newitem
->kacc
);
260 lnk_txn
= g_queue_peek_tail_link(acc
->txn_queue
);
261 while (lnk_txn
!= NULL
)
263 Transaction
*item
= lnk_txn
->data
;
265 if(item
->date
<= newitem
->date
)
268 lnk_txn
= g_list_previous(lnk_txn
);
271 // we're at insert point, insert after txn
272 g_queue_insert_after(acc
->txn_queue
, lnk_txn
, newitem
);
274 da_transaction_insert_memo(newitem
);
279 // nota: this is called only when loading xml file
280 gboolean
da_transaction_prepend(Transaction
*item
)
284 acc
= da_acc_get(item
->kacc
);
286 item
->kcur
= acc
->kcur
;
287 g_queue_push_tail(acc
->txn_queue
, item
);
288 da_transaction_insert_memo(item
);
293 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
296 da_transaction_get_max_kxfer(void)
298 GList
*lst_acc
, *lnk_acc
;
302 DB( g_print("da_transaction_get_max_kxfer\n") );
304 lst_acc
= g_hash_table_get_values(GLOBALS
->h_acc
);
305 lnk_acc
= g_list_first(lst_acc
);
306 while (lnk_acc
!= NULL
)
308 Account
*acc
= lnk_acc
->data
;
310 list
= g_queue_peek_head_link(acc
->txn_queue
);
313 Transaction
*item
= list
->data
;
315 if( item
->paymode
== PAYMODE_INTXFER
)
317 max_key
= MAX(max_key
, item
->kxfer
);
319 list
= g_list_next(list
);
322 lnk_acc
= g_list_next(lnk_acc
);
324 g_list_free(lst_acc
);
326 DB( g_print(" max_key : %d \n", max_key
) );
332 static void da_transaction_goto_orphan(Transaction
*txn
)
334 const gchar
*oatn
= "orphaned transactions";
337 acc
= da_acc_get_by_name((gchar
*)oatn
);
340 acc
= da_acc_malloc();
341 acc
->name
= g_strdup(oatn
);
344 txn
->kacc
= acc
->key
;
348 void da_transaction_consistency(Transaction
*item
)
355 // ensure date is between range
356 item
->date
= CLAMP(item
->date
, HB_MINDATE
, HB_MAXDATE
);
358 // check account exists
359 acc
= da_acc_get(item
->kacc
);
362 g_warning("txn consistency: fixed invalid acc %d", item
->kacc
);
363 da_transaction_goto_orphan(item
);
364 GLOBALS
->changes_count
++;
367 // check category exists
368 cat
= da_cat_get(item
->kcat
);
371 g_warning("txn consistency: fixed invalid cat %d", item
->kcat
);
373 GLOBALS
->changes_count
++;
376 // check split category #1340142
377 split_cat_consistency(item
->splits
);
379 //# 1416624 empty category when split
380 nbsplit
= da_splits_count(item
->splits
);
381 if(nbsplit
> 0 && item
->kcat
> 0)
383 g_warning("txn consistency: fixed invalid cat on split txn");
385 GLOBALS
->changes_count
++;
388 // check payee exists
389 pay
= da_pay_get(item
->kpay
);
392 g_warning("txn consistency: fixed invalid pay %d", item
->kpay
);
394 GLOBALS
->changes_count
++;
397 // reset dst acc for non xfer transaction
398 if( item
->paymode
!= PAYMODE_INTXFER
)
401 //#1628678 tags for internal xfer should be checked as well
404 //#1295877 ensure income flag is correctly set
405 item
->flags
&= ~(OF_INCOME
);
406 if( item
->amount
> 0)
407 item
->flags
|= (OF_INCOME
);
409 //#1308745 ensure remind flag unset if reconciled
411 //if( item->flags & OF_VALID )
412 // item->flags &= ~(OF_REMIND);
417 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
418 /* new transfer functions */
420 static void transaction_xfer_create_child(Transaction
*ope
)
426 DB( g_print("\n[transaction] xfer_create_child\n") );
428 if( ope
->kxferacc
> 0 )
430 child
= da_transaction_clone(ope
);
432 ope
->flags
|= OF_CHANGED
;
433 child
->flags
|= OF_ADDED
;
435 child
->amount
= -child
->amount
;
436 child
->flags
^= (OF_INCOME
); // invert flag
438 child
->status
= TXN_STATUS_NONE
;
439 //child->flags &= ~(OF_VALID); // delete reconcile state
442 child
->kacc
= child
->kxferacc
;
443 child
->kxferacc
= swap
;
445 /* update acc flags */
446 acc
= da_acc_get( child
->kacc
);
449 acc
->flags
|= AF_ADDED
;
452 guint maxkey
= da_transaction_get_max_kxfer();
454 DB( g_print(" + maxkey is %d\n", maxkey
) );
457 ope
->kxfer
= maxkey
+1;
458 child
->kxfer
= maxkey
+1;
460 DB( g_print(" + strong link to %d\n", ope
->kxfer
) );
463 DB( g_print(" + add transfer, %p to acc %d\n", child
, acc
->key
) );
465 da_transaction_insert_sorted(child
);
467 account_balances_add (child
);
475 //todo: add strong control and extend to payee, maybe memo ?
476 static gboolean
transaction_xfer_child_might(Transaction
*stxn
, Transaction
*dtxn
, gint daygap
)
478 gboolean retval
= FALSE
;
480 //DB( g_print("\n[transaction] xfer_child_might\n") );
487 g_print(" %d %d %d %f %d\n",
488 stxn->kcur, stxn->date, stxn->kacc, ABS(stxn->amount), stxn->kxfer );
491 g_print(" %d %d %d %f %d\n",
492 dtxn->kcur, dtxn->date, dtxn->kacc, ABS(dtxn->amount), dtxn->kxfer );
495 if( stxn
->kcur
== dtxn
->kcur
&&
496 stxn
->date
== dtxn
->date
&&
497 //v5.1 make no sense: stxn->kxferacc == dtxn->kacc &&
498 stxn
->kacc
!= dtxn
->kacc
&&
499 ABS(stxn
->amount
) == ABS(dtxn
->amount
) &&
505 //g_print(" return %d\n", retval);
510 static GList
*transaction_xfer_child_might_list_get(Transaction
*ope
)
512 GList
*lst_acc
, *lnk_acc
;
513 GList
*list
, *matchlist
= NULL
;
515 //DB( g_print("\n[transaction] xfer_child_might_list_get\n") );
517 lst_acc
= g_hash_table_get_values(GLOBALS
->h_acc
);
518 lnk_acc
= g_list_first(lst_acc
);
519 while (lnk_acc
!= NULL
)
521 Account
*acc
= lnk_acc
->data
;
523 if( !(acc
->flags
& AF_CLOSED
) && (acc
->key
!= ope
->kacc
) )
525 list
= g_queue_peek_tail_link(acc
->txn_queue
);
528 Transaction
*item
= list
->data
;
530 // no need to go higher than src txn date
531 if(item
->date
< ope
->date
)
534 if( transaction_xfer_child_might(ope
, item
, 0) == TRUE
)
536 //DB( g_print(" - match : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->account, item->kxferacc) );
537 matchlist
= g_list_append(matchlist
, item
);
539 list
= g_list_previous(list
);
543 lnk_acc
= g_list_next(lnk_acc
);
545 g_list_free(lst_acc
);
551 void transaction_xfer_search_or_add_child(GtkWindow
*parentwindow
, Transaction
*ope
, gboolean manual
)
556 DB( g_print("\n[transaction] xfer_search_or_add_child\n") );
558 matchlist
= transaction_xfer_child_might_list_get(ope
);
559 count
= g_list_length(matchlist
);
561 DB( g_print(" - found %d might match, switching\n", count
) );
565 case 0: //we should create the child
566 transaction_xfer_create_child(ope
);
569 //todo: maybe with just 1 match the user must choose ?
570 //#942346: bad idea so to no let the user confirm, so let hil confirm
572 case 1: //transform the transaction to a child transfer
574 GList *list = g_list_first(matchlist);
575 transaction_xfer_change_to_child(ope, list->data);
580 default: //the user must choose himself
584 child
= ui_dialog_transaction_xfer_select_child(ope
, matchlist
);
586 transaction_xfer_create_child(ope
);
588 transaction_xfer_change_to_child(ope
, child
);
592 g_list_free(matchlist
);
596 Transaction
*transaction_xfer_child_strong_get(Transaction
*src
)
601 DB( g_print("\n[transaction] xfer_child_strong_get\n") );
603 dstacc
= da_acc_get(src
->kxferacc
);
604 if( !dstacc
|| src
->kxfer
<= 0 )
607 DB( g_print(" - search: %d %s %f %d=>%d - %d\n", src
->date
, src
->wording
, src
->amount
, src
->kacc
, src
->kxferacc
, src
->kxfer
) );
609 list
= g_queue_peek_tail_link(dstacc
->txn_queue
);
612 Transaction
*item
= list
->data
;
615 //if( item->paymode == PAYMODE_INTXFER
616 // && item->kacc == src->kxferacc
617 // && item->kxfer == src->kxfer )
618 if( item
->paymode
== PAYMODE_INTXFER
619 && item
->kxfer
== src
->kxfer
622 DB( g_print(" - found : %d %s %f %d=>%d - %d\n", item
->date
, item
->wording
, item
->amount
, item
->kacc
, item
->kxferacc
, src
->kxfer
) );
625 list
= g_list_previous(list
);
628 DB( g_print(" - not found...\n") );
635 void transaction_xfer_change_to_child(Transaction
*ope
, Transaction
*child
)
639 DB( g_print("\n[transaction] xfer_change_to_child\n") );
641 if(ope
->kcur
!= child
->kcur
)
644 ope
->flags
|= OF_CHANGED
;
645 child
->flags
|= OF_CHANGED
;
647 child
->paymode
= PAYMODE_INTXFER
;
649 ope
->kxferacc
= child
->kacc
;
650 child
->kxferacc
= ope
->kacc
;
652 /* update acc flags */
653 dstacc
= da_acc_get( child
->kacc
);
655 dstacc
->flags
|= AF_CHANGED
;
658 guint maxkey
= da_transaction_get_max_kxfer();
659 ope
->kxfer
= maxkey
+1;
660 child
->kxfer
= maxkey
+1;
665 void transaction_xfer_sync_child(Transaction
*s_txn
, Transaction
*child
)
668 DB( g_print("\n[transaction] xfer_sync_child\n") );
670 account_balances_sub (child
);
672 child
->date
= s_txn
->date
;
673 child
->amount
= -s_txn
->amount
;
674 child
->flags
= child
->flags
| OF_CHANGED
;
676 child
->flags
&= ~(OF_INCOME
);
677 if( child
->amount
> 0)
678 child
->flags
|= (OF_INCOME
);
679 child
->kpay
= s_txn
->kpay
;
680 child
->kcat
= s_txn
->kcat
;
682 g_free(child
->wording
);
683 child
->wording
= g_strdup(s_txn
->wording
);
686 child
->info
= g_strdup(s_txn
->info
);
688 //#1252230 sync account also
689 child
->kacc
= s_txn
->kxferacc
;
690 child
->kxferacc
= s_txn
->kacc
;
692 account_balances_add (child
);
694 //synchronise tags since 5.1
697 transaction_tags_clone (s_txn
, child
);
702 void transaction_xfer_remove_child(Transaction
*src
)
706 DB( g_print("\n[transaction] xfer_remove_child\n") );
708 dst
= transaction_xfer_child_strong_get( src
);
710 DB( g_print(" -> return is %s, %p\n", dst
->wording
, dst
) );
714 Account
*acc
= da_acc_get(dst
->kacc
);
716 DB( g_print("deleting...") );
719 account_balances_sub(dst
);
720 g_queue_remove(acc
->txn_queue
, dst
);
721 da_transaction_free (dst
);
726 // still useful for upgrade from < file v0.6 (hb v4.4 kxfer)
727 Transaction
*transaction_old_get_child_transfer(Transaction
*src
)
732 DB( g_print("\n[transaction] get_child_transfer\n") );
734 //DB( g_print(" search: %d %s %f %d=>%d\n", src->date, src->wording, src->amount, src->account, src->kxferacc) );
735 acc
= da_acc_get(src
->kxferacc
);
737 list
= g_queue_peek_head_link(acc
->txn_queue
);
740 Transaction
*item
= list
->data
;
742 // no need to go higher than src txn date
743 if(item
->date
> src
->date
)
746 if( item
->paymode
== PAYMODE_INTXFER
)
748 if( src
->date
== item
->date
&&
749 src
->kacc
== item
->kxferacc
&&
750 src
->kxferacc
== item
->kacc
&&
751 ABS(src
->amount
) == ABS(item
->amount
) )
753 //DB( g_print(" found : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->account, item->kxferacc) );
758 list
= g_list_next(list
);
761 DB( g_print(" not found...\n") );
767 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
770 void transaction_add(Transaction
*ope
, GtkWidget
*treeview
, guint32 accnum
)
775 DB( g_print("\n[transaction] transaction_add\n") );
777 //controls accounts valid (archive scheduled maybe bad)
778 acc
= da_acc_get(ope
->kacc
);
779 if(acc
== NULL
) return;
781 DB( g_print(" acc is '%s' %d\n", acc
->name
, acc
->key
) );
783 ope
->kcur
= acc
->kcur
;
785 if(ope
->paymode
== PAYMODE_INTXFER
)
787 acc
= da_acc_get(ope
->kxferacc
);
788 if(acc
== NULL
) return;
791 da_splits_free(ope
->splits
);
792 ope
->flags
&= ~(OF_SPLIT
); //Flag that Splits are cleared
796 //allocate a new entry and copy from our edited structure
797 newope
= da_transaction_clone(ope
);
799 //init flag and keep remind status
800 // already done in deftransaction_get
801 //ope->flags |= (OF_ADDED);
802 //remind = (ope->flags & OF_REMIND) ? TRUE : FALSE;
803 //ope->flags &= (~OF_REMIND);
805 /* cheque number is already stored in deftransaction_get */
806 /* todo:move this to transaction add
807 store a new cheque number into account ? */
809 if( (newope
->paymode
== PAYMODE_CHECK
) && (newope
->info
) && !(newope
->flags
& OF_INCOME
) )
813 /* get the active account and the corresponding cheque number */
814 acc
= da_acc_get( newope
->kacc
);
815 cheque
= atol(newope
->info
);
817 //DB( g_print(" -> should store cheque number %d to %d", cheque, newope->account) );
818 if( newope
->flags
& OF_CHEQ2
)
820 acc
->cheque2
= MAX(acc
->cheque2
, cheque
);
824 acc
->cheque1
= MAX(acc
->cheque1
, cheque
);
828 /* add normal transaction */
829 acc
= da_acc_get( newope
->kacc
);
832 acc
->flags
|= AF_ADDED
;
834 DB( g_print(" + add normal %p to acc %d\n", newope
, acc
->key
) );
835 //da_transaction_append(newope);
836 da_transaction_insert_sorted(newope
);
839 transaction_add_treeview(newope
, treeview
, accnum
);
841 account_balances_add(newope
);
843 if(newope
->paymode
== PAYMODE_INTXFER
)
845 transaction_xfer_search_or_add_child(NULL
, newope
, FALSE
);
851 void transaction_add_treeview(Transaction
*ope
, GtkWidget
*treeview
, guint32 accnum
)
856 //GtkTreeSelection *sel;
858 DB( g_print("\n[transaction] add_treeview\n") );
860 if(ope
->kacc
== accnum
)
862 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(treeview
));
863 gtk_list_store_append (GTK_LIST_STORE(model
), &iter
);
865 gtk_list_store_set (GTK_LIST_STORE(model
), &iter
,
866 LST_DSPOPE_DATAS
, ope
,
869 //activate that new line
870 //path = gtk_tree_model_get_path(model, &iter);
871 //gtk_tree_view_expand_to_path(GTK_TREE_VIEW(treeview), path);
873 //sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
874 //gtk_tree_selection_select_iter(sel, &iter);
876 //gtk_tree_path_free(path);
882 gboolean
transaction_acc_move(Transaction
*txn
, guint32 okacc
, guint32 nkacc
)
884 Account
*oacc
, *nacc
;
886 DB( g_print("\n[transaction] acc_move\n") );
888 oacc
= da_acc_get(okacc
);
889 nacc
= da_acc_get(nkacc
);
892 if( g_queue_remove(oacc
->txn_queue
, txn
) )
894 g_queue_push_tail(nacc
->txn_queue
, txn
);
895 txn
->kacc
= nacc
->key
;
896 txn
->kcur
= nacc
->kcur
;
897 nacc
->flags
|= AF_CHANGED
;
901 //ensure to keep txn into current account
908 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
911 static gboolean
misc_text_match(gchar
*text
, gchar
*searchtext
, gboolean exact
)
913 gboolean match
= FALSE
;
918 //DB( g_print("search %s in %s\n", rul->name, ope->wording) );
919 if( searchtext
!= NULL
)
923 if( g_strrstr(text
, searchtext
) != NULL
)
925 DB( g_print(" found case '%s'\n", searchtext
) );
931 gchar
*word
= g_utf8_casefold(text
, -1);
932 gchar
*needle
= g_utf8_casefold(searchtext
, -1);
934 if( g_strrstr(word
, needle
) != NULL
)
936 DB( g_print(" found nocase '%s'\n", searchtext
) );
947 static gboolean
misc_regex_match(gchar
*text
, gchar
*searchtext
, gboolean exact
)
949 gboolean match
= FALSE
;
954 DB( g_print("- match RE %s in %s\n", searchtext
, text
) );
955 if( searchtext
!= NULL
)
957 match
= g_regex_match_simple(searchtext
, text
, ((exact
== TRUE
)?0:G_REGEX_CASELESS
) | G_REGEX_OPTIMIZE
, G_REGEX_MATCH_NOTEMPTY
);
958 if (match
== TRUE
) { DB( g_print(" found pattern '%s'\n", searchtext
) ); }
964 static Assign
*transaction_auto_assign_eval_txn(GList
*l_rul
, Transaction
*txn
)
969 DB( g_print("\n[transaction] auto_assign_eval_txn\n") );
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("\n[transaction] auto_assign_eval\n") );
1012 DB( g_print("- eval every rules, and return the last that match\n") );
1014 list
= g_list_first(l_rul
);
1015 while (list
!= NULL
)
1017 Assign
*rul
= list
->data
;
1019 if( rul
->field
== 0 ) //memo
1021 if( !(rul
->flags
& ASGF_REGEX
) )
1023 if( misc_text_match(text
, rul
->text
, rul
->flags
& ASGF_EXACT
) )
1028 if( misc_regex_match(text
, rul
->text
, rul
->flags
& ASGF_EXACT
) )
1032 list
= g_list_next(list
);
1039 gint
transaction_auto_assign(GList
*ope_list
, guint32 kacc
)
1045 DB( g_print("\n[transaction] auto_assign\n") );
1047 l_rul
= g_hash_table_get_values(GLOBALS
->h_rul
);
1049 l_ope
= g_list_first(ope_list
);
1050 while (l_ope
!= NULL
)
1052 Transaction
*ope
= l_ope
->data
;
1053 gboolean changed
= FALSE
;
1055 DB( g_print("- eval ope '%s' : acc=%d, pay=%d, cat=%d\n", ope
->wording
, ope
->kacc
, ope
->kpay
, ope
->kcat
) );
1057 //#1215521: added kacc == 0
1058 if( (kacc
== ope
->kacc
|| kacc
== 0) )
1062 rul
= transaction_auto_assign_eval_txn(l_rul
, ope
);
1065 if( (ope
->kpay
== 0 && (rul
->flags
& ASGF_DOPAY
)) || (rul
->flags
& ASGF_OVWPAY
) )
1067 if(ope
->kpay
!= rul
->kpay
) { changed
= TRUE
; }
1068 ope
->kpay
= rul
->kpay
;
1071 if( !(ope
->flags
& OF_SPLIT
) )
1073 if( (ope
->kcat
== 0 && (rul
->flags
& ASGF_DOCAT
)) || (rul
->flags
& ASGF_OVWCAT
) )
1075 if(ope
->kcat
!= rul
->kcat
) { changed
= TRUE
; }
1076 ope
->kcat
= rul
->kcat
;
1080 if( (ope
->paymode
== 0 && (rul
->flags
& ASGF_DOMOD
)) || (rul
->flags
& ASGF_OVWMOD
) )
1082 //ugly hack - don't allow modify intxfer
1083 if(ope
->paymode
!= PAYMODE_INTXFER
&& rul
->paymode
!= PAYMODE_INTXFER
)
1085 if(ope
->paymode
!= rul
->paymode
) { changed
= TRUE
; }
1086 ope
->paymode
= rul
->paymode
;
1092 if( ope
->flags
& OF_SPLIT
)
1094 guint i
, nbsplit
= da_splits_count(ope
->splits
);
1096 for(i
=0;i
<nbsplit
;i
++)
1098 Split
*split
= ope
->splits
[i
];
1100 DB( g_print("- eval split '%s'\n", split
->memo
) );
1102 rul
= transaction_auto_assign_eval(l_rul
, split
->memo
);
1105 //#1501144: check if user wants to set category in rule
1106 if( (split
->kcat
== 0 || (rul
->flags
& ASGF_OVWCAT
)) && (rul
->flags
& ASGF_DOCAT
) )
1108 if(split
->kcat
!= rul
->kcat
) { changed
= TRUE
; }
1109 split
->kcat
= rul
->kcat
;
1117 ope
->flags
|= OF_CHANGED
;
1122 l_ope
= g_list_next(l_ope
);
1131 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1135 transaction_tags_count(Transaction
*ope
)
1138 guint32
*ptr
= ope
->tags
;
1140 //DB( g_print("\n[transaction] tags_count\n") );
1142 if( ope
->tags
== NULL
)
1145 while(*ptr
++ != 0 && count
< 32)
1152 void transaction_tags_clone(Transaction
*src_txn
, Transaction
*dst_txn
)
1156 dst_txn
->tags
= NULL
;
1157 count
= transaction_tags_count(src_txn
);
1160 //1501962: we must also copy the final 0
1161 dst_txn
->tags
= g_memdup(src_txn
->tags
, (count
+1)*sizeof(guint32
));
1166 transaction_tags_parse(Transaction
*ope
, const gchar
*tagstring
)
1172 DB( g_print("\n[transaction] tags_parse\n") );
1174 DB( g_print(" - tagstring='%s'\n", tagstring
) );
1176 str_array
= g_strsplit (tagstring
, " ", 0);
1177 count
= g_strv_length( str_array
);
1182 DB( g_print(" -> reset storage %p\n", ope
->tags
) );
1188 ope
->tags
= g_new0(guint32
, count
+ 1);
1190 DB( g_print(" -> storage %p\n", ope
->tags
) );
1192 for(i
=0;i
<count
;i
++)
1194 tag
= da_tag_get_by_name(str_array
[i
]);
1197 Tag
*newtag
= da_tag_malloc();
1199 newtag
->name
= g_strdup(str_array
[i
]);
1200 da_tag_append(newtag
);
1201 tag
= da_tag_get_by_name(str_array
[i
]);
1204 DB( g_print(" -> storing %d=>%s at tags pos %d\n", tag
->key
, tag
->name
, i
) );
1206 ope
->tags
[i
] = tag
->key
;
1211 //hex_dump(ope->tags, sizeof(guint32*)*count+1);
1213 g_strfreev (str_array
);
1219 transaction_tags_tostring(Transaction
*ope
)
1226 DB( g_print("\n[transaction] tags_tostring\n") );
1228 DB( g_print(" -> tags at=%p\n", ope
->tags
) );
1230 if( ope
->tags
== NULL
)
1237 count
= transaction_tags_count(ope
);
1239 DB( g_print(" -> tags at=%p, nbtags=%d\n", ope
->tags
, count
) );
1241 str_array
= g_new0(gchar
*, count
+1);
1243 DB( g_print(" -> str_array at %p\n", str_array
) );
1245 //hex_dump(ope->tags, sizeof(guint32*)*(count+1));
1247 for(i
=0;i
<count
;i
++)
1249 DB( g_print(" -> try to get tag %d\n", ope
->tags
[i
]) );
1251 tag
= da_tag_get(ope
->tags
[i
]);
1254 DB( g_print(" -> get %s at %d\n", tag
->name
, i
) );
1255 str_array
[i
] = tag
->name
;
1258 str_array
[i
] = NULL
;
1263 tagstring
= g_strjoinv(" ", str_array
);