1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2014 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"
28 /****************************************************************************/
30 /****************************************************************************/
39 /* our global datas */
40 extern struct HomeBank
*GLOBALS
;
41 extern struct Preferences
*PREFS
;
44 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
47 static void da_split_free(Split
*item
)
51 if(item
->memo
!= NULL
)
59 static Split
*da_split_malloc(void)
61 return g_malloc0(sizeof(Split
));
65 Split
*da_split_new(guint32 kcat
, gdouble amount
, gchar
*memo
)
67 Split
*split
= da_split_malloc();
70 split
->amount
= amount
;
71 split
->memo
= g_strdup(memo
);
77 static Split
*da_split_clone(Split
*src_split
)
79 Split
*new_split
= g_memdup(src_split
, sizeof(Split
));
81 DB( g_print("da_split_clone\n") );
85 //duplicate the string
86 new_split
->memo
= g_strdup(src_split
->memo
);
87 DB( g_print(" clone %p -> %p\n", src_split
, new_split
) );
93 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
96 guint
da_transaction_splits_count(Transaction
*txn
)
100 for(i
=0;i
<TXN_MAX_SPLIT
;i
++)
102 if(txn
->splits
[i
] == NULL
)
110 void da_transaction_splits_free(Transaction
*txn
)
114 count
= da_transaction_splits_count(txn
);
118 DB( g_print("da_transaction_splits_free\n") );
122 DB( g_print("- freeing %d :: %p\n", i
, txn
->splits
[i
]) );
124 da_split_free(txn
->splits
[i
]);
125 txn
->splits
[i
] = NULL
;
128 txn
->flags
&= ~(OF_SPLIT
);
133 void da_transaction_splits_append(Transaction
*txn
, Split
*split
)
135 guint count
= da_transaction_splits_count(txn
);
137 DB( g_print("da_transaction_splits_append\n") );
139 DB( g_print("- split[%d] at %p for ope %p\n", count
, split
, txn
) );
141 txn
->flags
|= OF_SPLIT
;
142 txn
->splits
[count
] = split
;
143 txn
->splits
[count
+ 1] = NULL
;
145 DB( g_print("- %d splits\n", da_transaction_splits_count(txn
)) );
149 void da_transaction_splits_clone(Transaction
*stxn
, Transaction
*dtxn
)
153 DB( g_print("da_transaction_splits_clone\n") );
155 count
= da_transaction_splits_count(stxn
);
158 dtxn
->splits
[i
] = da_split_clone(stxn
->splits
[i
]);
162 dtxn
->flags
|= OF_SPLIT
;
164 DB( g_print(" clone %p -> %p, %d splits\n", stxn
, dtxn
, count
) );
169 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
172 da_transaction_clean(Transaction
*item
)
176 if(item
->wording
!= NULL
)
178 g_free(item
->wording
);
179 item
->wording
= NULL
;
181 if(item
->info
!= NULL
)
186 if(item
->tags
!= NULL
)
188 DB( g_print(" -> item->tags %p\n", item
->tags
) );
193 da_transaction_splits_free(item
);
195 if(item
->same
!= NULL
)
197 g_list_free(item
->same
);
206 da_transaction_free(Transaction
*item
)
210 da_transaction_clean(item
);
217 da_transaction_malloc(void)
219 return rc_alloc(sizeof(Transaction
));
223 Transaction
*da_transaction_copy(Transaction
*src_txn
, Transaction
*dst_txn
)
227 DB( g_print("da_transaction_copy\n") );
229 da_transaction_clean (dst_txn
);
231 memmove(dst_txn
, src_txn
, sizeof(Transaction
));
233 //duplicate the string
234 dst_txn
->wording
= g_strdup(src_txn
->wording
);
235 dst_txn
->info
= g_strdup(src_txn
->info
);
238 dst_txn
->tags
= NULL
;
239 count
= transaction_tags_count(src_txn
);
241 dst_txn
->tags
= g_memdup(src_txn
->tags
, count
*sizeof(guint32
));
243 da_transaction_splits_clone(src_txn
, dst_txn
);
249 Transaction
*da_transaction_init_from_template(Transaction
*txn
, Archive
*arc
)
252 txn
->amount
= arc
->amount
;
253 txn
->kacc
= arc
->kacc
;
254 txn
->paymode
= arc
->paymode
;
255 txn
->flags
= arc
->flags
| OF_ADDED
;
256 txn
->kpay
= arc
->kpay
;
257 txn
->kcat
= arc
->kcat
;
258 txn
->kxferacc
= arc
->kxferacc
;
259 txn
->wording
= g_strdup(arc
->wording
);
266 Transaction
*da_transaction_clone(Transaction
*src_item
)
268 Transaction
*new_item
= rc_dup(src_item
, sizeof(Transaction
));
271 DB( g_print("da_transaction_clone\n") );
275 //duplicate the string
276 new_item
->wording
= g_strdup(src_item
->wording
);
277 new_item
->info
= g_strdup(src_item
->info
);
280 new_item
->tags
= NULL
;
281 count
= transaction_tags_count(src_item
);
283 new_item
->tags
= g_memdup(src_item
->tags
, count
*sizeof(guint32
));
285 da_transaction_splits_clone(src_item
, new_item
);
292 da_transaction_new(void)
298 void da_transaction_destroy(GList
*list
)
300 GList
*tmplist
= g_list_first(list
);
302 while (tmplist
!= NULL
)
304 Transaction
*item
= tmplist
->data
;
305 da_transaction_free(item
);
306 tmplist
= g_list_next(tmplist
);
312 static gint
da_transaction_compare_func(Transaction
*a
, Transaction
*b
)
314 return ((gint
)a
->date
- b
->date
);
318 GList
*da_transaction_sort(GList
*list
)
320 return( g_list_sort(list
, (GCompareFunc
)da_transaction_compare_func
));
324 static void da_transaction_insert_memo(Transaction
*item
)
326 // append the memo if new
327 if( item
->wording
!= NULL
)
329 if( g_hash_table_lookup(GLOBALS
->h_memo
, item
->wording
) == NULL
)
331 g_hash_table_insert(GLOBALS
->h_memo
, g_strdup(item
->wording
), NULL
);
338 gboolean
da_transaction_insert_sorted(Transaction
*newitem
)
340 GList
*tmplist
= g_list_first(GLOBALS
->ope_list
);
342 // find the breaking date
343 while (tmplist
!= NULL
)
345 Transaction
*item
= tmplist
->data
;
347 if(item
->date
> newitem
->date
)
350 tmplist
= g_list_next(tmplist
);
353 // here we're at the insert point, let's insert our new txn just before
354 GLOBALS
->ope_list
= g_list_insert_before(GLOBALS
->ope_list
, tmplist
, newitem
);
356 da_transaction_insert_memo(newitem
);
361 // nota: this is called only when loading xml file
362 gboolean
da_transaction_prepend(Transaction
*item
)
364 GLOBALS
->ope_list
= g_list_prepend(GLOBALS
->ope_list
, item
);
365 da_transaction_insert_memo(item
);
370 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
373 da_transaction_get_max_kxfer(void)
379 DB( g_print("da_transaction_get_max_kxfer\n") );
381 list
= g_list_first(GLOBALS
->ope_list
);
385 if( item
->paymode
== PAYMODE_INTXFER
)
387 if( item
->kxfer
> max_key
)
388 max_key
= item
->kxfer
;
390 list
= g_list_next(list
);
393 DB( g_print(" max_key : %d \n", max_key
) );
399 static void da_transaction_goto_orphan(Transaction
*txn
)
401 const gchar
*oatn
= "orphaned transactions";
404 acc
= da_acc_get_by_name((gchar
*)oatn
);
407 acc
= da_acc_malloc();
408 acc
->name
= g_strdup(oatn
);
411 txn
->kacc
= acc
->key
;
415 void da_transaction_consistency(Transaction
*item
)
422 // check account exists
423 acc
= da_acc_get(item
->kacc
);
426 g_warning("txn consistency: fixed invalid acc %d", item
->kacc
);
427 da_transaction_goto_orphan(item
);
430 // check category exists
431 cat
= da_cat_get(item
->kcat
);
434 g_warning("txn consistency: fixed invalid cat %d", item
->kcat
);
438 // check split category #1340142
439 nbsplit
= da_transaction_splits_count(item
);
440 for(i
=0;i
<nbsplit
;i
++)
442 Split
*split
= item
->splits
[i
];
443 cat
= da_cat_get(split
->kcat
);
446 g_warning("txn consistency: fixed invalid split cat %d", split
->kcat
);
451 // check payee exists
452 pay
= da_pay_get(item
->kpay
);
455 g_warning("txn consistency: fixed invalid pay %d", item
->kpay
);
459 // reset dst acc for non xfer transaction
460 if( item
->paymode
!= PAYMODE_INTXFER
)
463 //#1295877 ensure income flag is correctly set
464 item
->flags
&= ~(OF_INCOME
);
465 if( item
->amount
> 0)
466 item
->flags
|= (OF_INCOME
);
468 //#1308745 ensure remind flag unset if reconciled
469 if( item
->flags
& OF_VALID
)
470 item
->flags
&= ~(OF_REMIND
);
475 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
476 /* new transfer functions */
478 Transaction
*transaction_strong_get_child_transfer(Transaction
*src
)
482 DB( g_print("\n[transaction] transaction_strong_get_child_transfer\n") );
484 DB( g_print(" - search: %d %s %f %d=>%d\n", src
->date
, src
->wording
, src
->amount
, src
->kacc
, src
->kxferacc
) );
486 list
= g_list_first(GLOBALS
->ope_list
);
489 Transaction
*item
= list
->data
;
491 //if( item->paymode == PAYMODE_INTXFER && item->kacc == src->kxferacc && item->kxfer == src->kxfer )
492 if( item
->paymode
== PAYMODE_INTXFER
&& item
->kxfer
== src
->kxfer
&& item
!= src
)
494 DB( g_print(" - found : %d %s %f %d=>%d\n", item
->date
, item
->wording
, item
->amount
, item
->kacc
, item
->kxferacc
) );
497 list
= g_list_next(list
);
499 DB( g_print(" - not found...\n") );
505 * this function retrieve into a glist the potential child transfer
506 * for the source transaction
508 GList
*transaction_match_get_child_transfer(Transaction
*src
)
513 DB( g_print("\n[transaction] transaction_match_get_child_transfer\n") );
515 //DB( g_print(" - search : %d %s %f %d=>%d\n", src->date, src->wording, src->amount, src->account, src->kxferacc) );
517 list
= g_list_first(GLOBALS
->ope_list
);
520 Transaction
*item
= list
->data
;
521 if( src
->date
== item
->date
&&
522 src
->kxferacc
== item
->kacc
&&
523 ABS(src
->amount
) == ABS(item
->amount
) &&
526 //DB( g_print(" - match : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->account, item->kxferacc) );
528 match
= g_list_append(match
, item
);
530 list
= g_list_next(list
);
533 DB( g_print(" - found : %d\n", g_list_length(match
)) );
539 void transaction_xfer_search_or_add_child(Transaction
*ope
, GtkWidget
*treeview
)
541 GList
*matchlist
= transaction_match_get_child_transfer(ope
);
543 guint count
= g_list_length(matchlist
);
546 DB( g_print("\n[transaction] transaction_xfer_search_or_add_child\n") );
548 DB( g_print(" - found result is %d, switching\n", count
) );
552 case 0: //we should create the child
553 transaction_xfer_create_child(ope
, treeview
);
556 //todo: maybe with just 1 match the user must choose ?
557 //#942346: bad idea so to no let the user confirm, so let hil confirm
559 case 1: //transform the transaction to a child transfer
561 GList *list = g_list_first(matchlist);
562 transaction_xfer_change_to_child(ope, list->data);
567 default: //the user must choose himself
571 child
= ui_dialog_transaction_xfer_select_child(matchlist
);
573 transaction_xfer_create_child(ope
, treeview
);
575 transaction_xfer_change_to_child(ope
, child
);
580 g_list_free(matchlist
);
589 void transaction_xfer_create_child(Transaction
*ope
, GtkWidget
*treeview
)
595 DB( g_print("\n[transaction] transaction_xfer_create_child\n") );
597 if( ope
->kxferacc
> 0 )
599 child
= da_transaction_clone(ope
);
601 child
->amount
= -child
->amount
;
602 child
->flags
^= (OF_INCOME
); // invert flag
603 child
->flags
&= ~(OF_REMIND
); // remove flag
605 child
->flags
&= ~(OF_VALID
); // remove reconcile state
609 child
->kacc
= child
->kxferacc
;
610 child
->kxferacc
= swap
;
612 /* update acc flags */
613 acc
= da_acc_get( child
->kacc
);
616 acc
->flags
|= AF_ADDED
;
619 guint maxkey
= da_transaction_get_max_kxfer();
621 DB( g_print(" + maxkey is %d\n", maxkey
) );
624 ope
->kxfer
= maxkey
+1;
625 child
->kxfer
= maxkey
+1;
627 DB( g_print(" + strong link to %d\n", ope
->kxfer
) );
630 DB( g_print(" + add transfer, %p\n", child
) );
632 da_transaction_insert_sorted(child
);
634 account_balances_add (child
);
637 transaction_add_treeview(child
, treeview
, ope
->kacc
);
639 GValue txn_value
= G_VALUE_INIT
;
640 ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value
, child
), NULL
);
647 void transaction_xfer_change_to_child(Transaction
*ope
, Transaction
*child
)
651 DB( g_print("\n[transaction] transaction_xfer_change_to_child\n") );
653 child
->paymode
= PAYMODE_INTXFER
;
655 ope
->kxferacc
= child
->kacc
;
656 child
->kxferacc
= ope
->kacc
;
658 /* update acc flags */
659 acc
= da_acc_get( child
->kacc
);
661 acc
->flags
|= AF_CHANGED
;
664 guint maxkey
= da_transaction_get_max_kxfer();
665 ope
->kxfer
= maxkey
+1;
666 child
->kxfer
= maxkey
+1;
671 void transaction_xfer_sync_child(Transaction
*s_txn
, Transaction
*child
)
674 DB( g_print("\n[transaction] transaction_xfer_sync_child\n") );
676 account_balances_sub (child
);
678 child
->date
= s_txn
->date
;
679 child
->amount
= -s_txn
->amount
;
680 child
->flags
= child
->flags
| OF_CHANGED
;
682 child
->flags
&= ~(OF_INCOME
);
683 if( child
->amount
> 0)
684 child
->flags
|= (OF_INCOME
);
685 child
->kpay
= s_txn
->kpay
;
686 child
->kcat
= s_txn
->kcat
;
688 g_free(child
->wording
);
689 child
->wording
= g_strdup(s_txn
->wording
);
692 child
->info
= g_strdup(s_txn
->info
);
694 //#1252230 sync account also
695 child
->kacc
= s_txn
->kxferacc
;
696 child
->kxferacc
= s_txn
->kacc
;
698 account_balances_add (child
);
700 //todo: synchronise tags here also ?
705 void transaction_xfer_delete_child(Transaction
*src
)
709 DB( g_print("\n[transaction] transaction_xfer_delete_child\n") );
711 dst
= transaction_strong_get_child_transfer( src
);
713 DB( g_print(" -> return is %s, %p\n", dst
->wording
, dst
) );
717 DB( g_print("deleting...") );
720 account_balances_sub(dst
);
721 GLOBALS
->ope_list
= g_list_remove(GLOBALS
->ope_list
, dst
);
726 Transaction
*transaction_old_get_child_transfer(Transaction
*src
)
731 DB( g_print("\n[transaction] transaction_get_child_transfer\n") );
733 //DB( g_print(" search: %d %s %f %d=>%d\n", src->date, src->wording, src->amount, src->account, src->kxferacc) );
735 list
= g_list_first(GLOBALS
->ope_list
);
739 if( item
->paymode
== PAYMODE_INTXFER
)
741 if( src
->date
== item
->date
&&
742 src
->kacc
== item
->kxferacc
&&
743 src
->kxferacc
== item
->kacc
&&
744 ABS(src
->amount
) == ABS(item
->amount
) )
746 //DB( g_print(" found : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->account, item->kxferacc) );
751 list
= g_list_next(list
);
754 DB( g_print(" not found...\n") );
762 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
765 void transaction_add(Transaction
*ope
, GtkWidget
*treeview
, guint32 accnum
)
770 DB( g_print("\n[transaction] transaction add\n") );
772 //controls accounts valid (archive scheduled maybe bad)
773 acc
= da_acc_get(ope
->kacc
);
774 if(acc
== NULL
) return;
776 if(ope
->paymode
== PAYMODE_INTXFER
)
778 acc
= da_acc_get(ope
->kxferacc
);
779 if(acc
== NULL
) return;
782 da_transaction_splits_free(ope
);
785 //allocate a new entry and copy from our edited structure
786 newope
= da_transaction_clone(ope
);
788 //init flag and keep remind status
789 // already done in deftransaction_get
790 //ope->flags |= (OF_ADDED);
791 //remind = (ope->flags & OF_REMIND) ? TRUE : FALSE;
792 //ope->flags &= (~OF_REMIND);
794 /* cheque number is already stored in deftransaction_get */
795 /* todo:move this to transaction add
796 store a new cheque number into account ? */
798 if( (newope
->paymode
== PAYMODE_CHECK
) && (newope
->info
) && !(newope
->flags
& OF_INCOME
) )
802 /* get the active account and the corresponding cheque number */
803 acc
= da_acc_get( newope
->kacc
);
804 cheque
= atol(newope
->info
);
806 //DB( g_print(" -> should store cheque number %d to %d", cheque, newope->account) );
807 if( newope
->flags
& OF_CHEQ2
)
809 acc
->cheque2
= MAX(acc
->cheque2
, cheque
);
813 acc
->cheque1
= MAX(acc
->cheque1
, cheque
);
817 /* add normal transaction */
818 acc
= da_acc_get( newope
->kacc
);
821 acc
->flags
|= AF_ADDED
;
823 DB( g_print(" + add normal %p\n", newope
) );
824 //da_transaction_append(newope);
825 da_transaction_insert_sorted(newope
);
828 transaction_add_treeview(newope
, treeview
, accnum
);
830 account_balances_add(newope
);
832 if(newope
->paymode
== PAYMODE_INTXFER
)
834 transaction_xfer_search_or_add_child(newope
, treeview
);
837 GValue txn_value
= G_VALUE_INIT
;
838 ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value
, newope
), NULL
);
845 void transaction_add_treeview(Transaction
*ope
, GtkWidget
*treeview
, guint32 accnum
)
850 //GtkTreeSelection *sel;
852 DB( g_print("\n[transaction] transaction add treeview\n") );
854 if(ope
->kacc
== accnum
)
856 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(treeview
));
857 gtk_list_store_append (GTK_LIST_STORE(model
), &iter
);
859 gtk_list_store_set (GTK_LIST_STORE(model
), &iter
,
860 LST_DSPOPE_DATAS
, ope
,
863 //activate that new line
864 //path = gtk_tree_model_get_path(model, &iter);
865 //gtk_tree_view_expand_to_path(GTK_TREE_VIEW(treeview), path);
867 //sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
868 //gtk_tree_selection_select_iter(sel, &iter);
870 //gtk_tree_path_free(path);
876 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
877 static gboolean
misc_text_match(gchar
*text
, gchar
*searchtext
, gboolean exact
)
879 gboolean match
= FALSE
;
884 //DB( g_print("search %s in %s\n", rul->name, ope->wording) );
885 if( searchtext
!= NULL
)
889 if( g_strrstr(text
, searchtext
) != NULL
)
891 DB( g_print(" found case '%s'\n", searchtext
) );
897 gchar
*word
= g_utf8_casefold(text
, -1);
898 gchar
*needle
= g_utf8_casefold(searchtext
, -1);
900 if( g_strrstr(word
, needle
) != NULL
)
902 DB( g_print(" found nocase '%s'\n", searchtext
) );
914 static Assign
*transaction_auto_assign_eval_txn(GList
*l_rul
, Transaction
*txn
)
919 DB( g_print("- eval every rules, and return the last that match\n") );
921 list
= g_list_first(l_rul
);
924 Assign
*rul
= list
->data
;
928 if(rul
->field
== 1) //payee
930 Payee
*pay
= da_pay_get(txn
->kpay
);
934 if( misc_text_match(text
, rul
->name
, rul
->flags
& ASGF_EXACT
))
937 list
= g_list_next(list
);
944 static Assign
*transaction_auto_assign_eval(GList
*l_rul
, gchar
*text
)
949 DB( g_print("- eval every rules, and return the last that match\n") );
951 list
= g_list_first(l_rul
);
954 Assign
*rul
= list
->data
;
956 if( rul
->field
== 0 ) //memo
958 if( misc_text_match(text
, rul
->name
, rul
->flags
& ASGF_EXACT
))
961 list
= g_list_next(list
);
968 gint
transaction_auto_assign(GList
*ope_list
, guint32 key
)
974 DB( g_print("\n[transaction] transaction_auto_assign\n") );
976 l_ope
= g_list_first(ope_list
);
977 l_rul
= g_hash_table_get_values(GLOBALS
->h_rul
);
979 while (l_ope
!= NULL
)
981 Transaction
*ope
= l_ope
->data
;
983 DB( g_print("- eval ope '%s' : acc=%d, pay=%d, cat=%d\n", ope
->wording
, ope
->kacc
, ope
->kpay
, ope
->kcat
) );
985 //#1215521: added key == 0
986 if( (key
== ope
->kacc
|| key
== 0) )
990 if( !(ope
->flags
& OF_SPLIT
) && (ope
->kpay
== 0 || ope
->kcat
== 0) )
992 rul
= transaction_auto_assign_eval_txn(l_rul
, ope
);
995 if( ope
->kpay
== 0 && (rul
->flags
& ASGF_DOPAY
) )
997 ope
->kpay
= rul
->kpay
;
998 ope
->flags
|= OF_CHANGED
;
1001 if( ope
->kcat
== 0 && (rul
->flags
& ASGF_DOCAT
) )
1003 ope
->kcat
= rul
->kcat
;
1004 ope
->flags
|= OF_CHANGED
;
1010 else if( ope
->flags
& OF_SPLIT
)
1012 guint i
, nbsplit
= da_transaction_splits_count(ope
);
1014 gboolean split_change
= FALSE
;
1016 for(i
=0;i
<nbsplit
;i
++)
1018 split
= ope
->splits
[i
];
1020 DB( g_print("- eval split '%s'\n", split
->memo
) );
1022 if(split
->kcat
== 0)
1024 rul
= transaction_auto_assign_eval(l_rul
, split
->memo
);
1027 if( split
->kcat
== 0 && rul
->kcat
> 0 )
1029 split
->kcat
= rul
->kcat
;
1030 ope
->flags
|= OF_CHANGED
;
1031 split_change
= TRUE
;
1038 if(split_change
== TRUE
)
1045 l_ope
= g_list_next(l_ope
);
1054 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1058 transaction_tags_count(Transaction
*ope
)
1061 guint32
*ptr
= ope
->tags
;
1063 if( ope
->tags
== NULL
)
1066 while(*ptr
++ != 0 && count
< 32)
1075 guint
transaction_splits_parse(Transaction
*ope
, gchar
*cats
, gchar
*amounts
, gchar
*memos
)
1077 gchar
**cat_a
, **amt_a
, **mem_a
;
1083 DB( g_print(" split parse %s :: %s :: %s\n", cats
, amounts
, memos
) );
1085 cat_a
= g_strsplit (cats
, "||", 0);
1086 amt_a
= g_strsplit (amounts
, "||", 0);
1087 mem_a
= g_strsplit (memos
, "||", 0);
1089 count
= g_strv_length(amt_a
);
1090 if( (count
== g_strv_length(cat_a
)) && (count
== g_strv_length(mem_a
)) )
1092 for(i
=0;i
<count
;i
++)
1094 kcat
= atoi(cat_a
[i
]);
1095 amount
= g_ascii_strtod(amt_a
[i
], NULL
);
1096 split
= da_split_new(kcat
, amount
, mem_a
[i
]);
1097 da_transaction_splits_append (ope
, split
);
1100 ope
->flags
|= OF_SPLIT
;
1104 g_warning("invalid split parse");
1116 guint
transaction_splits_tostring(Transaction
*ope
, gchar
**cats
, gchar
**amounts
, gchar
**memos
)
1120 char buf
[G_ASCII_DTOSTR_BUF_SIZE
];
1121 GString
*cat_a
= g_string_new (NULL
);
1122 GString
*amt_a
= g_string_new (NULL
);
1123 GString
*mem_a
= g_string_new (NULL
);
1125 count
= da_transaction_splits_count(ope
);
1126 for(i
=0;i
<count
;i
++)
1128 split
= ope
->splits
[i
];
1129 g_string_append_printf (cat_a
, "%d", split
->kcat
);
1130 g_string_append(amt_a
, g_ascii_dtostr (buf
, sizeof (buf
), split
->amount
) );
1131 g_string_append(mem_a
, split
->memo
);
1135 g_string_append(cat_a
, "||");
1136 g_string_append(amt_a
, "||");
1137 g_string_append(mem_a
, "||");
1141 *cats
= g_string_free(cat_a
, FALSE
);
1142 *amounts
= g_string_free(amt_a
, FALSE
);
1143 *memos
= g_string_free(mem_a
, FALSE
);
1150 transaction_tags_parse(Transaction
*ope
, const gchar
*tagstring
)
1156 DB( g_print("(transaction_set_tags)\n") );
1158 DB( g_print(" - tagstring='%s'\n", tagstring
) );
1160 str_array
= g_strsplit (tagstring
, " ", 0);
1161 count
= g_strv_length( str_array
);
1166 DB( g_print(" -> reset storage %p\n", ope
->tags
) );
1172 ope
->tags
= g_new0(guint32
, count
+ 1);
1174 DB( g_print(" -> storage %p\n", ope
->tags
) );
1176 for(i
=0;i
<count
;i
++)
1178 tag
= da_tag_get_by_name(str_array
[i
]);
1181 Tag
*newtag
= da_tag_malloc();
1183 newtag
->name
= g_strdup(str_array
[i
]);
1184 da_tag_append(newtag
);
1185 tag
= da_tag_get_by_name(str_array
[i
]);
1188 DB( g_print(" -> storing %d=>%s at tags pos %d\n", tag
->key
, tag
->name
, i
) );
1190 ope
->tags
[i
] = tag
->key
;
1194 //hex_dump(ope->tags, sizeof(guint32*)*count+1);
1196 g_strfreev (str_array
);
1202 transaction_tags_tostring(Transaction
*ope
)
1209 DB( g_print("transaction_get_tagstring\n") );
1211 DB( g_print(" -> tags at=%p\n", ope
->tags
) );
1213 if( ope
->tags
== NULL
)
1220 count
= transaction_tags_count(ope
);
1222 DB( g_print(" -> tags at=%p, nbtags=%d\n", ope
->tags
, count
) );
1224 str_array
= g_new0(gchar
*, count
+1);
1226 DB( g_print(" -> str_array at %p\n", str_array
) );
1228 //hex_dump(ope->tags, sizeof(guint32*)*(count+1));
1230 for(i
=0;i
<count
;i
++)
1232 DB( g_print(" -> try to get tag %d\n", ope
->tags
[i
]) );
1234 tag
= da_tag_get(ope
->tags
[i
]);
1237 DB( g_print(" -> get %s at %d\n", tag
->name
, i
) );
1238 str_array
[i
] = tag
->name
;
1241 str_array
[i
] = NULL
;
1246 tagstring
= g_strjoinv(" ", str_array
);