]>
Dogcows Code - chaz/homebank/blob - hb-filter.c
74f81ce696abda4285d46afb0141fb74c4ddf163
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 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/>.
21 #include "hb-filter.h"
23 /****************************************************************************/
25 /****************************************************************************/
34 /* our global datas */
35 extern struct HomeBank
*GLOBALS
;
36 extern struct Preferences
*PREFS
;
39 /* = = = = = = = = = = = = = = = = */
41 void da_flt_free(Filter
*flt
)
43 DB( g_print("da_flt_free\n") );
54 Filter
*da_flt_malloc(void)
56 DB( g_print("da_flt_malloc\n") );
57 return g_malloc0(sizeof(Filter
));
61 /* = = = = = = = = = = = = = = = = = = = = */
64 void filter_status_acc_clear_except(Filter
*flt
, guint32 selkey
)
70 g_hash_table_iter_init (&iter
, GLOBALS
->h_acc
);
71 while (g_hash_table_iter_next (&iter
, &key
, &value
))
73 Account
*item
= value
;
74 item
->flt_select
= item
->key
== selkey
? TRUE
: FALSE
;
81 void filter_status_pay_clear_except(Filter
*flt
, guint32 selkey
)
87 g_hash_table_iter_init (&iter
, GLOBALS
->h_pay
);
88 while (g_hash_table_iter_next (&iter
, &key
, &value
))
91 item
->flt_select
= item
->key
== selkey
? TRUE
: FALSE
;
98 void filter_status_cat_clear_except(Filter
*flt
, guint32 selkey
)
104 g_hash_table_iter_init (&iter
, GLOBALS
->h_cat
);
105 while (g_hash_table_iter_next (&iter
, &key
, &value
))
107 Category
*item
= value
;
108 item
->flt_select
= item
->key
== selkey
? TRUE
: FALSE
;
114 /* = = = = = = = = = = = = = = = = */
117 void filter_reset(Filter
*flt
)
121 DB( g_print("\n[filter] default reset all %p\n", flt
) );
123 for(i
=0;i
<FILTER_MAX
;i
++)
128 flt
->option
[FILTER_DATE
] = 1;
129 flt
->range
= FLT_RANGE_LAST12MONTHS
;
130 filter_preset_daterange_set(flt
, flt
->range
, 0);
132 for(i
=0;i
<NUM_PAYMODE_MAX
;i
++)
133 flt
->paymode
[i
] = TRUE
;
143 flt
->nbdaysfuture
= 0;
144 flt
->type
= FLT_TYPE_ALL
;
145 flt
->status
= FLT_STATUS_ALL
;
146 flt
->forceremind
= PREFS
->showremind
;
148 *flt
->last_tab
= '\0';
152 void filter_set_tag_by_id(Filter
*flt
, guint32 key
)
156 DB( g_print("\n[filter] set tag by id\n") );
164 tag
= da_tag_get(key
);
167 flt
->tag
= g_strdup(tag
->name
);
172 static void filter_set_date_bounds(Filter
*flt
, guint32 kacc
)
174 GList
*lst_acc
, *lnk_acc
;
177 DB( g_print("\n[filter] set date bounds %p\n", flt
) );
182 lst_acc
= g_hash_table_get_values(GLOBALS
->h_acc
);
183 lnk_acc
= g_list_first(lst_acc
);
184 while (lnk_acc
!= NULL
)
186 Account
*acc
= lnk_acc
->data
;
188 //#1674045 only rely on nosummary
189 //if( !(acc->flags & AF_CLOSED) )
193 DB( g_print(" - do '%s'\n", acc
->name
) );
195 lnk_txn
= g_queue_peek_head_link(acc
->txn_queue
);
198 if( (kacc
== 0) || (txn
->kacc
== kacc
) )
200 if( flt
->mindate
== 0 )
201 flt
->mindate
= txn
->date
;
203 flt
->mindate
= MIN(flt
->mindate
, txn
->date
);
207 lnk_txn
= g_queue_peek_tail_link(acc
->txn_queue
);
210 if( (kacc
== 0) || (txn
->kacc
== kacc
) )
212 if( flt
->maxdate
== 0 )
213 flt
->maxdate
= txn
->date
;
215 flt
->maxdate
= MAX(flt
->maxdate
, txn
->date
);
220 lnk_acc
= g_list_next(lnk_acc
);
223 if( flt
->mindate
== 0 )
225 //flt->mindate = HB_MINDATE;
226 flt
->mindate
= GLOBALS
->today
- 365;
228 if( flt
->maxdate
== 0 )
230 //flt->maxdate = HB_MAXDATE;
231 flt
->maxdate
= GLOBALS
->today
+ flt
->nbdaysfuture
;
233 g_list_free(lst_acc
);
237 void filter_preset_daterange_add_futuregap(Filter
*filter
, gint nbdays
)
240 DB( g_print("\n[filter] range add future gap\n") );
245 filter->nbdaysfuture = 0;
249 filter
->nbdaysfuture
= 0;
251 switch( filter
->range
)
253 case FLT_RANGE_THISMONTH
:
254 case FLT_RANGE_THISQUARTER
:
255 case FLT_RANGE_THISYEAR
:
256 case FLT_RANGE_LAST30DAYS
:
257 case FLT_RANGE_LAST60DAYS
:
258 case FLT_RANGE_LAST90DAYS
:
259 case FLT_RANGE_LAST12MONTHS
:
260 filter
->nbdaysfuture
= nbdays
;
266 void filter_preset_daterange_set(Filter
*flt
, gint range
, guint32 kacc
)
269 guint32 jtoday
, jfiscal
;
270 guint16 month
, year
, yfiscal
, qnum
;
272 DB( g_print("\n[filter] daterange set %p %d\n", flt
, range
) );
276 jtoday
= GLOBALS
->today
;
278 tmpdate
= g_date_new_julian(jtoday
);
280 month
= g_date_get_month(tmpdate
);
281 year
= g_date_get_year(tmpdate
);
282 DB( hb_print_date(jtoday
, "today ") );
284 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, year
);
285 jfiscal
= g_date_get_julian(tmpdate
);
286 DB( hb_print_date(jfiscal
, "fiscal") );
288 yfiscal
= (jtoday
>= jfiscal
) ? year
: year
-1;
291 if( range
== FLT_RANGE_THISQUARTER
|| range
== FLT_RANGE_LASTQUARTER
)
293 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, yfiscal
);
294 while( (qnum
< 5) && (g_date_get_julian(tmpdate
) < jtoday
) )
297 g_date_add_months (tmpdate
, 3);
299 DB( g_print(" qnum: %d\n", qnum
) );
304 case FLT_RANGE_THISMONTH
:
305 case FLT_RANGE_LASTMONTH
:
306 g_date_set_dmy(tmpdate
, 1, month
, year
);
307 if( range
== FLT_RANGE_LASTMONTH
)
308 g_date_subtract_months(tmpdate
, 1);
309 flt
->mindate
= g_date_get_julian(tmpdate
);
310 month
= g_date_get_month(tmpdate
);
311 year
= g_date_get_year(tmpdate
);
312 g_date_add_days(tmpdate
, g_date_get_days_in_month(month
, year
));
313 flt
->maxdate
= g_date_get_julian(tmpdate
) - 1;
316 case FLT_RANGE_THISQUARTER
:
317 case FLT_RANGE_LASTQUARTER
:
318 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, yfiscal
);
319 if( range
== FLT_RANGE_LASTQUARTER
)
320 g_date_subtract_months(tmpdate
, 3);
321 g_date_add_months(tmpdate
, 3 * (qnum
-1) );
322 flt
->mindate
= g_date_get_julian(tmpdate
);
323 g_date_add_months(tmpdate
, 3);
324 flt
->maxdate
= g_date_get_julian(tmpdate
) - 1;
327 case FLT_RANGE_THISYEAR
:
328 case FLT_RANGE_LASTYEAR
:
329 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, yfiscal
);
330 if( range
== FLT_RANGE_LASTYEAR
)
331 g_date_subtract_years(tmpdate
, 1);
332 flt
->mindate
= g_date_get_julian(tmpdate
);
333 g_date_add_years (tmpdate
, 1);
334 flt
->maxdate
= g_date_get_julian(tmpdate
) - 1;
337 case FLT_RANGE_LAST30DAYS
:
338 flt
->mindate
= jtoday
- 30;
339 flt
->maxdate
= jtoday
;
342 case FLT_RANGE_LAST60DAYS
:
343 flt
->mindate
= jtoday
- 60;
344 flt
->maxdate
= jtoday
;
347 case FLT_RANGE_LAST90DAYS
:
348 flt
->mindate
= jtoday
- 90;
349 flt
->maxdate
= jtoday
;
352 case FLT_RANGE_LAST12MONTHS
:
353 g_date_set_julian (tmpdate
, jtoday
);
354 g_date_subtract_months(tmpdate
, 12);
355 flt
->mindate
= g_date_get_julian(tmpdate
);
356 flt
->maxdate
= jtoday
;
359 // case FLT_RANGE_OTHER:
362 case FLT_RANGE_ALLDATE
:
363 filter_set_date_bounds(flt
, kacc
);
366 g_date_free(tmpdate
);
370 void filter_preset_type_set(Filter
*flt
, gint type
)
373 DB( g_print("\n[filter] preset type set\n") );
377 flt
->option
[FILTER_AMOUNT
] = 0;
378 flt
->minamount
= G_MINDOUBLE
;
379 flt
->maxamount
= G_MINDOUBLE
;
383 case FLT_TYPE_EXPENSE
:
384 flt
->option
[FILTER_AMOUNT
] = 1;
385 flt
->minamount
= -G_MAXDOUBLE
;
386 flt
->maxamount
= G_MINDOUBLE
;
389 case FLT_TYPE_INCOME
:
390 flt
->option
[FILTER_AMOUNT
] = 1;
391 flt
->minamount
= G_MINDOUBLE
;
392 flt
->maxamount
= G_MAXDOUBLE
;
399 void filter_preset_status_set(Filter
*flt
, gint status
)
402 DB( g_print("\n[filter] preset status set\n") );
405 flt
->status
= status
;
406 flt
->option
[FILTER_STATUS
] = 0;
407 flt
->option
[FILTER_CATEGORY
] = 0;
408 flt
->option
[FILTER_PAYMODE
] = 0;
409 flt
->reconciled
= TRUE
;
411 //#1602835 fautly set
412 //flt->forceadd = TRUE;
413 //flt->forcechg = TRUE;
417 case FLT_STATUS_UNCATEGORIZED
:
418 flt
->option
[FILTER_CATEGORY
] = 1;
419 filter_status_cat_clear_except(flt
, 0);
420 flt
->option
[FILTER_PAYMODE
] = 1;
421 flt
->paymode
[PAYMODE_INTXFER
] = FALSE
;
424 case FLT_STATUS_UNRECONCILED
:
425 flt
->option
[FILTER_STATUS
] = 2;
426 flt
->reconciled
= TRUE
;
427 flt
->cleared
= FALSE
;
430 case FLT_STATUS_UNCLEARED
:
431 flt
->option
[FILTER_STATUS
] = 2;
432 flt
->reconciled
= FALSE
;
436 case FLT_STATUS_RECONCILED
:
437 flt
->option
[FILTER_STATUS
] = 1;
438 flt
->reconciled
= TRUE
;
439 flt
->cleared
= FALSE
;
442 case FLT_STATUS_CLEARED
:
443 flt
->option
[FILTER_STATUS
] = 1;
444 flt
->reconciled
= FALSE
;
452 gchar
*filter_daterange_text_get(Filter
*flt
)
458 gchar
*retval
= NULL
;
460 DB( g_print("\n[filter] daterange text get\n") );
462 date
= g_date_new_julian(flt
->mindate
);
463 g_date_strftime (buffer1
, 128-1, PREFS
->date_format
, date
);
465 g_date_set_julian(date
, flt
->maxdate
);
466 g_date_strftime (buffer2
, 128-1, PREFS
->date_format
, date
);
468 if( flt
->nbdaysfuture
> 0 )
470 g_date_set_julian(date
, flt
->maxdate
+ flt
->nbdaysfuture
);
471 g_date_strftime (buffer3
, 128-1, PREFS
->date_format
, date
);
472 retval
= g_strdup_printf("%s — <s>%s</s> %s", buffer1
, buffer2
, buffer3
);
475 retval
= g_strdup_printf("%s — %s", buffer1
, buffer2
);
479 //return g_strdup_printf(_("<i>from</i> %s <i>to</i> %s — "), buffer1, buffer2);
484 /* used for quicksearch text into transaction */
485 gboolean
filter_txn_search_match(gchar
*needle
, Transaction
*txn
, gint flags
)
487 gboolean retval
= FALSE
;
492 DB( g_print("\n[filter] tnx search match\n") );
494 if(flags
& FLT_QSEARCH_MEMO
)
496 //#1668036 always try match on txn memo first
499 retval
|= hb_string_utf8_strstr(txn
->memo
, needle
, FALSE
);
504 if(txn
->flags
& OF_SPLIT
)
509 count
= da_splits_length(txn
->splits
);
514 split
= da_splits_get(txn
->splits
, i
);
515 tmpinsert
= hb_string_utf8_strstr(split
->memo
, needle
, FALSE
);
524 if(flags
& FLT_QSEARCH_INFO
)
528 retval
|= hb_string_utf8_strstr(txn
->info
, needle
, FALSE
);
533 if(flags
& FLT_QSEARCH_PAYEE
)
535 payitem
= da_pay_get(txn
->kpay
);
538 retval
|= hb_string_utf8_strstr(payitem
->name
, needle
, FALSE
);
543 if(flags
& FLT_QSEARCH_CATEGORY
)
546 if(txn
->flags
& OF_SPLIT
)
551 count
= da_splits_length(txn
->splits
);
556 split
= da_splits_get(txn
->splits
, i
);
557 catitem
= da_cat_get(split
->kcat
);
560 tmpinsert
= hb_string_utf8_strstr(catitem
->fullname
, needle
, FALSE
);
570 catitem
= da_cat_get(txn
->kcat
);
573 retval
|= hb_string_utf8_strstr(catitem
->fullname
, needle
, FALSE
);
579 if(flags
& FLT_QSEARCH_TAGS
)
581 tags
= tags_tostring(txn
->tags
);
584 retval
|= hb_string_utf8_strstr(tags
, needle
, FALSE
);
590 //#1741339 add quicksearch for amount
591 if(flags
& FLT_QSEARCH_AMOUNT
)
593 gchar formatd_buf
[G_ASCII_DTOSTR_BUF_SIZE
];
595 hb_strfnum(formatd_buf
, G_ASCII_DTOSTR_BUF_SIZE
-1, txn
->amount
, txn
->kcur
, FALSE
);
596 retval
|= hb_string_utf8_strstr(formatd_buf
, needle
, FALSE
);
605 gint
filter_txn_match(Filter
*flt
, Transaction
*txn
)
612 //DB( g_print("\n[filter] txn match\n") );
616 /*** start filtering ***/
619 if(flt
->forceadd
== TRUE
&& (txn
->flags
& OF_ADDED
))
622 if(flt
->forcechg
== TRUE
&& (txn
->flags
& OF_CHANGED
))
625 /* force remind if not filter on status */
626 if(flt
->forceremind
== TRUE
&& (txn
->status
== TXN_STATUS_REMIND
))
630 if(flt
->option
[FILTER_DATE
]) {
631 insert
= ( (txn
->date
>= flt
->mindate
) && (txn
->date
<= (flt
->maxdate
+ flt
->nbdaysfuture
) ) ) ? 1 : 0;
632 if(flt
->option
[FILTER_DATE
] == 2) insert
^= 1;
634 if(!insert
) goto end
;
637 if(flt
->option
[FILTER_ACCOUNT
]) {
638 accitem
= da_acc_get(txn
->kacc
);
641 insert
= ( accitem
->flt_select
== TRUE
) ? 1 : 0;
642 if(flt
->option
[FILTER_ACCOUNT
] == 2) insert
^= 1;
645 if(!insert
) goto end
;
648 if(flt
->option
[FILTER_PAYEE
]) {
649 payitem
= da_pay_get(txn
->kpay
);
652 insert
= ( payitem
->flt_select
== TRUE
) ? 1 : 0;
653 if(flt
->option
[FILTER_PAYEE
] == 2) insert
^= 1;
656 if(!insert
) goto end
;
659 if(flt
->option
[FILTER_CATEGORY
]) {
660 if(txn
->flags
& OF_SPLIT
)
665 insert
= 0; //fix: 1151259
666 count
= da_splits_length(txn
->splits
);
671 split
= da_splits_get(txn
->splits
, i
);
672 catitem
= da_cat_get(split
->kcat
);
675 tmpinsert
= ( catitem
->flt_select
== TRUE
) ? 1 : 0;
676 if(flt
->option
[FILTER_CATEGORY
] == 2) tmpinsert
^= 1;
683 catitem
= da_cat_get(txn
->kcat
);
686 insert
= ( catitem
->flt_select
== TRUE
) ? 1 : 0;
687 if(flt
->option
[FILTER_CATEGORY
] == 2) insert
^= 1;
691 if(!insert
) goto end
;
694 if(flt
->option
[FILTER_STATUS
]) {
695 gint insert1
= 0, insert2
= 0;
698 insert1
= ( txn
->status
== TXN_STATUS_RECONCILED
) ? 1 : 0;
700 insert2
= ( txn
->status
== TXN_STATUS_CLEARED
) ? 1 : 0;
702 insert
= insert1
| insert2
;
703 if(flt
->option
[FILTER_STATUS
] == 2) insert
^= 1;
705 if(!insert
) goto end
;
708 if(flt
->option
[FILTER_PAYMODE
]) {
709 insert
= ( flt
->paymode
[txn
->paymode
] == TRUE
) ? 1 : 0;
710 if(flt
->option
[FILTER_PAYMODE
] == 2) insert
^= 1;
712 if(!insert
) goto end
;
715 if(flt
->option
[FILTER_AMOUNT
]) {
716 insert
= ( (txn
->amount
>= flt
->minamount
) && (txn
->amount
<= flt
->maxamount
) ) ? 1 : 0;
718 if(flt
->option
[FILTER_AMOUNT
] == 2) insert
^= 1;
720 if(!insert
) goto end
;
723 if(flt
->option
[FILTER_TEXT
])
726 gint insert1
, insert2
, insert3
;
728 insert1
= insert2
= insert3
= 0;
733 insert1
= hb_string_utf8_strstr(txn
->info
, flt
->info
, flt
->exact
);
741 //#1668036 always try match on txn memo first
744 insert2
= hb_string_utf8_strstr(txn
->memo
, flt
->memo
, flt
->exact
);
747 if( (insert2
== 0) && (txn
->flags
& OF_SPLIT
) )
752 count
= da_splits_length(txn
->splits
);
757 split
= da_splits_get(txn
->splits
, i
);
758 tmpinsert
= hb_string_utf8_strstr(split
->memo
, flt
->memo
, flt
->exact
);
759 insert2
|= tmpinsert
;
770 tags
= tags_tostring(txn
->tags
);
773 insert3
= hb_string_utf8_strstr(tags
, flt
->tag
, flt
->exact
);
780 insert
= insert1
&& insert2
&& insert3
? 1 : 0;
782 if(flt
->option
[FILTER_TEXT
] == 2) insert
^= 1;
785 if(!insert
) goto end
;
788 // DB( g_print(" %d :: %d :: %d\n", flt->mindate, txn->date, flt->maxdate) );
789 // DB( g_print(" [%d] %s => %d (%d)\n", txn->account, txn->memo, insert, count) );
This page took 0.06361 seconds and 3 git commands to generate.