]>
Dogcows Code - chaz/homebank/blob - src/hb-filter.c
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
;
80 void filter_status_pay_clear_except(Filter
*flt
, guint32 selkey
)
86 g_hash_table_iter_init (&iter
, GLOBALS
->h_pay
);
87 while (g_hash_table_iter_next (&iter
, &key
, &value
))
90 item
->flt_select
= item
->key
== selkey
? TRUE
: FALSE
;
96 void filter_status_cat_clear_except(Filter
*flt
, guint32 selkey
)
102 g_hash_table_iter_init (&iter
, GLOBALS
->h_cat
);
103 while (g_hash_table_iter_next (&iter
, &key
, &value
))
105 Category
*item
= value
;
108 item
->flt_select
= FALSE
;
109 if( (item
->key
== selkey
)
110 //#1824561 don't forget subcat
111 //#1829076 but not when selkey is 0
112 || ((item
->parent
== selkey
) && selkey
> 0)
114 item
->flt_select
= TRUE
;
120 /* = = = = = = = = = = = = = = = = */
123 void filter_reset(Filter
*flt
)
127 DB( g_print("\n[filter] default reset all %p\n", flt
) );
129 for(i
=0;i
<FILTER_MAX
;i
++)
134 flt
->option
[FILTER_DATE
] = 1;
135 flt
->range
= FLT_RANGE_LAST12MONTHS
;
136 filter_preset_daterange_set(flt
, flt
->range
, 0);
138 for(i
=0;i
<NUM_PAYMODE_MAX
;i
++)
139 flt
->paymode
[i
] = TRUE
;
149 flt
->nbdaysfuture
= 0;
150 flt
->type
= FLT_TYPE_ALL
;
151 flt
->status
= FLT_STATUS_ALL
;
152 flt
->forceremind
= PREFS
->showremind
;
154 *flt
->last_tab
= '\0';
158 void filter_set_tag_by_id(Filter
*flt
, guint32 key
)
162 DB( g_print("\n[filter] set tag by id\n") );
170 tag
= da_tag_get(key
);
173 flt
->tag
= g_strdup(tag
->name
);
178 static void filter_set_date_bounds(Filter
*flt
, guint32 kacc
)
180 GList
*lst_acc
, *lnk_acc
;
183 DB( g_print("\n[filter] set date bounds %p\n", flt
) );
188 lst_acc
= g_hash_table_get_values(GLOBALS
->h_acc
);
189 lnk_acc
= g_list_first(lst_acc
);
190 while (lnk_acc
!= NULL
)
192 Account
*acc
= lnk_acc
->data
;
194 //#1674045 only rely on nosummary
195 //if( !(acc->flags & AF_CLOSED) )
199 DB( g_print(" - do '%s'\n", acc
->name
) );
201 lnk_txn
= g_queue_peek_head_link(acc
->txn_queue
);
204 if( (kacc
== 0) || (txn
->kacc
== kacc
) )
206 if( flt
->mindate
== 0 )
207 flt
->mindate
= txn
->date
;
209 flt
->mindate
= MIN(flt
->mindate
, txn
->date
);
213 lnk_txn
= g_queue_peek_tail_link(acc
->txn_queue
);
216 if( (kacc
== 0) || (txn
->kacc
== kacc
) )
218 if( flt
->maxdate
== 0 )
219 flt
->maxdate
= txn
->date
;
221 flt
->maxdate
= MAX(flt
->maxdate
, txn
->date
);
226 lnk_acc
= g_list_next(lnk_acc
);
229 if( flt
->mindate
== 0 )
231 //flt->mindate = HB_MINDATE;
232 flt
->mindate
= GLOBALS
->today
- 365;
234 if( flt
->maxdate
== 0 )
236 //flt->maxdate = HB_MAXDATE;
237 flt
->maxdate
= GLOBALS
->today
+ flt
->nbdaysfuture
;
239 g_list_free(lst_acc
);
243 gboolean
filter_preset_daterange_future_enable(gint range
)
247 case FLT_RANGE_THISMONTH
:
248 case FLT_RANGE_THISQUARTER
:
249 case FLT_RANGE_THISYEAR
:
250 case FLT_RANGE_LAST30DAYS
:
251 case FLT_RANGE_LAST60DAYS
:
252 case FLT_RANGE_LAST90DAYS
:
253 case FLT_RANGE_LAST12MONTHS
:
262 void filter_preset_daterange_add_futuregap(Filter
*filter
, gint nbdays
)
265 DB( g_print("\n[filter] range add future gap\n") );
270 filter->nbdaysfuture = 0;
274 filter
->nbdaysfuture
= 0;
275 if( filter_preset_daterange_future_enable(filter
->range
) )
276 filter
->nbdaysfuture
= nbdays
;
281 void filter_preset_daterange_set(Filter
*flt
, gint range
, guint32 kacc
)
284 guint32 jtoday
, jfiscal
;
285 guint16 month
, year
, yfiscal
, qnum
;
287 DB( g_print("\n[filter] daterange set %p %d\n", flt
, range
) );
291 jtoday
= GLOBALS
->today
;
293 tmpdate
= g_date_new_julian(jtoday
);
295 month
= g_date_get_month(tmpdate
);
296 year
= g_date_get_year(tmpdate
);
297 DB( hb_print_date(jtoday
, "today ") );
299 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, year
);
300 jfiscal
= g_date_get_julian(tmpdate
);
301 DB( hb_print_date(jfiscal
, "fiscal") );
303 yfiscal
= (jtoday
>= jfiscal
) ? year
: year
-1;
306 if( range
== FLT_RANGE_THISQUARTER
|| range
== FLT_RANGE_LASTQUARTER
)
308 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, yfiscal
);
309 while( (qnum
< 5) && (g_date_get_julian(tmpdate
) < jtoday
) )
312 g_date_add_months (tmpdate
, 3);
314 DB( g_print(" qnum: %d\n", qnum
) );
319 case FLT_RANGE_THISMONTH
:
320 case FLT_RANGE_LASTMONTH
:
321 g_date_set_dmy(tmpdate
, 1, month
, year
);
322 if( range
== FLT_RANGE_LASTMONTH
)
323 g_date_subtract_months(tmpdate
, 1);
324 flt
->mindate
= g_date_get_julian(tmpdate
);
325 month
= g_date_get_month(tmpdate
);
326 year
= g_date_get_year(tmpdate
);
327 g_date_add_days(tmpdate
, g_date_get_days_in_month(month
, year
));
328 flt
->maxdate
= g_date_get_julian(tmpdate
) - 1;
331 case FLT_RANGE_THISQUARTER
:
332 case FLT_RANGE_LASTQUARTER
:
333 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, yfiscal
);
334 if( range
== FLT_RANGE_LASTQUARTER
)
335 g_date_subtract_months(tmpdate
, 3);
336 g_date_add_months(tmpdate
, 3 * (qnum
-1) );
337 flt
->mindate
= g_date_get_julian(tmpdate
);
338 g_date_add_months(tmpdate
, 3);
339 flt
->maxdate
= g_date_get_julian(tmpdate
) - 1;
342 case FLT_RANGE_THISYEAR
:
343 case FLT_RANGE_LASTYEAR
:
344 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, yfiscal
);
345 if( range
== FLT_RANGE_LASTYEAR
)
346 g_date_subtract_years(tmpdate
, 1);
347 flt
->mindate
= g_date_get_julian(tmpdate
);
348 g_date_add_years (tmpdate
, 1);
349 flt
->maxdate
= g_date_get_julian(tmpdate
) - 1;
352 case FLT_RANGE_LAST30DAYS
:
353 flt
->mindate
= jtoday
- 30;
354 flt
->maxdate
= jtoday
;
357 case FLT_RANGE_LAST60DAYS
:
358 flt
->mindate
= jtoday
- 60;
359 flt
->maxdate
= jtoday
;
362 case FLT_RANGE_LAST90DAYS
:
363 flt
->mindate
= jtoday
- 90;
364 flt
->maxdate
= jtoday
;
367 case FLT_RANGE_LAST12MONTHS
:
368 g_date_set_julian (tmpdate
, jtoday
);
369 g_date_subtract_months(tmpdate
, 12);
370 flt
->mindate
= g_date_get_julian(tmpdate
);
371 flt
->maxdate
= jtoday
;
374 // case FLT_RANGE_OTHER:
377 case FLT_RANGE_ALLDATE
:
378 filter_set_date_bounds(flt
, kacc
);
381 g_date_free(tmpdate
);
385 void filter_preset_type_set(Filter
*flt
, gint type
)
388 DB( g_print("\n[filter] preset type set\n") );
392 flt
->option
[FILTER_AMOUNT
] = 0;
393 flt
->minamount
= G_MINDOUBLE
;
394 flt
->maxamount
= G_MINDOUBLE
;
398 case FLT_TYPE_EXPENSE
:
399 flt
->option
[FILTER_AMOUNT
] = 1;
400 flt
->minamount
= -G_MAXDOUBLE
;
401 flt
->maxamount
= G_MINDOUBLE
;
404 case FLT_TYPE_INCOME
:
405 flt
->option
[FILTER_AMOUNT
] = 1;
406 flt
->minamount
= G_MINDOUBLE
;
407 flt
->maxamount
= G_MAXDOUBLE
;
414 void filter_preset_status_set(Filter
*flt
, gint status
)
417 DB( g_print("\n[filter] preset status set\n") );
420 flt
->status
= status
;
421 flt
->option
[FILTER_STATUS
] = 0;
422 flt
->option
[FILTER_CATEGORY
] = 0;
423 flt
->option
[FILTER_PAYMODE
] = 0;
424 flt
->reconciled
= TRUE
;
426 //#1602835 fautly set
427 //flt->forceadd = TRUE;
428 //flt->forcechg = TRUE;
432 case FLT_STATUS_UNCATEGORIZED
:
433 flt
->option
[FILTER_CATEGORY
] = 1;
434 filter_status_cat_clear_except(flt
, 0);
435 flt
->option
[FILTER_PAYMODE
] = 1;
436 flt
->paymode
[PAYMODE_INTXFER
] = FALSE
;
439 case FLT_STATUS_UNRECONCILED
:
440 flt
->option
[FILTER_STATUS
] = 2;
441 flt
->reconciled
= TRUE
;
442 flt
->cleared
= FALSE
;
445 case FLT_STATUS_UNCLEARED
:
446 flt
->option
[FILTER_STATUS
] = 2;
447 flt
->reconciled
= FALSE
;
451 case FLT_STATUS_RECONCILED
:
452 flt
->option
[FILTER_STATUS
] = 1;
453 flt
->reconciled
= TRUE
;
454 flt
->cleared
= FALSE
;
457 case FLT_STATUS_CLEARED
:
458 flt
->option
[FILTER_STATUS
] = 1;
459 flt
->reconciled
= FALSE
;
467 gchar
*filter_daterange_text_get(Filter
*flt
)
473 gchar
*retval
= NULL
;
475 DB( g_print("\n[filter] daterange text get\n") );
477 date
= g_date_new_julian(flt
->mindate
);
478 g_date_strftime (buffer1
, 128-1, PREFS
->date_format
, date
);
480 g_date_set_julian(date
, flt
->maxdate
);
481 g_date_strftime (buffer2
, 128-1, PREFS
->date_format
, date
);
483 if( flt
->nbdaysfuture
> 0 )
485 g_date_set_julian(date
, flt
->maxdate
+ flt
->nbdaysfuture
);
486 g_date_strftime (buffer3
, 128-1, PREFS
->date_format
, date
);
487 retval
= g_strdup_printf("%s — <s>%s</s> %s", buffer1
, buffer2
, buffer3
);
490 retval
= g_strdup_printf("%s — %s", buffer1
, buffer2
);
494 //return g_strdup_printf(_("<i>from</i> %s <i>to</i> %s — "), buffer1, buffer2);
499 /* used for quicksearch text into transaction */
500 gboolean
filter_txn_search_match(gchar
*needle
, Transaction
*txn
, gint flags
)
502 gboolean retval
= FALSE
;
507 DB( g_print("\n[filter] tnx search match\n") );
509 if(flags
& FLT_QSEARCH_MEMO
)
511 //#1668036 always try match on txn memo first
514 retval
|= hb_string_utf8_strstr(txn
->memo
, needle
, FALSE
);
519 if(txn
->flags
& OF_SPLIT
)
524 count
= da_splits_length(txn
->splits
);
529 split
= da_splits_get(txn
->splits
, i
);
530 tmpinsert
= hb_string_utf8_strstr(split
->memo
, needle
, FALSE
);
539 if(flags
& FLT_QSEARCH_INFO
)
543 retval
|= hb_string_utf8_strstr(txn
->info
, needle
, FALSE
);
548 if(flags
& FLT_QSEARCH_PAYEE
)
550 payitem
= da_pay_get(txn
->kpay
);
553 retval
|= hb_string_utf8_strstr(payitem
->name
, needle
, FALSE
);
558 if(flags
& FLT_QSEARCH_CATEGORY
)
561 if(txn
->flags
& OF_SPLIT
)
566 count
= da_splits_length(txn
->splits
);
571 split
= da_splits_get(txn
->splits
, i
);
572 catitem
= da_cat_get(split
->kcat
);
575 tmpinsert
= hb_string_utf8_strstr(catitem
->fullname
, needle
, FALSE
);
585 catitem
= da_cat_get(txn
->kcat
);
588 retval
|= hb_string_utf8_strstr(catitem
->fullname
, needle
, FALSE
);
594 if(flags
& FLT_QSEARCH_TAGS
)
596 tags
= tags_tostring(txn
->tags
);
599 retval
|= hb_string_utf8_strstr(tags
, needle
, FALSE
);
605 //#1741339 add quicksearch for amount
606 if(flags
& FLT_QSEARCH_AMOUNT
)
608 gchar formatd_buf
[G_ASCII_DTOSTR_BUF_SIZE
];
610 hb_strfnum(formatd_buf
, G_ASCII_DTOSTR_BUF_SIZE
-1, txn
->amount
, txn
->kcur
, FALSE
);
611 retval
|= hb_string_utf8_strstr(formatd_buf
, needle
, FALSE
);
620 gint
filter_txn_match(Filter
*flt
, Transaction
*txn
)
627 //DB( g_print("\n[filter] txn match\n") );
631 /*** start filtering ***/
634 if(flt
->forceadd
== TRUE
&& (txn
->flags
& OF_ADDED
))
637 if(flt
->forcechg
== TRUE
&& (txn
->flags
& OF_CHANGED
))
640 /* force remind if not filter on status */
641 if(flt
->forceremind
== TRUE
&& (txn
->status
== TXN_STATUS_REMIND
))
645 if(flt
->option
[FILTER_DATE
]) {
646 insert
= ( (txn
->date
>= flt
->mindate
) && (txn
->date
<= (flt
->maxdate
+ flt
->nbdaysfuture
) ) ) ? 1 : 0;
647 if(flt
->option
[FILTER_DATE
] == 2) insert
^= 1;
649 if(!insert
) goto end
;
652 if(flt
->option
[FILTER_ACCOUNT
]) {
653 accitem
= da_acc_get(txn
->kacc
);
656 insert
= ( accitem
->flt_select
== TRUE
) ? 1 : 0;
657 if(flt
->option
[FILTER_ACCOUNT
] == 2) insert
^= 1;
660 if(!insert
) goto end
;
663 if(flt
->option
[FILTER_PAYEE
]) {
664 payitem
= da_pay_get(txn
->kpay
);
667 insert
= ( payitem
->flt_select
== TRUE
) ? 1 : 0;
668 if(flt
->option
[FILTER_PAYEE
] == 2) insert
^= 1;
671 if(!insert
) goto end
;
674 if(flt
->option
[FILTER_CATEGORY
]) {
675 if(txn
->flags
& OF_SPLIT
)
680 insert
= 0; //fix: 1151259
681 count
= da_splits_length(txn
->splits
);
686 split
= da_splits_get(txn
->splits
, i
);
687 catitem
= da_cat_get(split
->kcat
);
690 tmpinsert
= ( catitem
->flt_select
== TRUE
) ? 1 : 0;
691 if(flt
->option
[FILTER_CATEGORY
] == 2) tmpinsert
^= 1;
698 catitem
= da_cat_get(txn
->kcat
);
701 insert
= ( catitem
->flt_select
== TRUE
) ? 1 : 0;
702 if(flt
->option
[FILTER_CATEGORY
] == 2) insert
^= 1;
706 if(!insert
) goto end
;
709 if(flt
->option
[FILTER_STATUS
]) {
710 gint insert1
= 0, insert2
= 0;
713 insert1
= ( txn
->status
== TXN_STATUS_RECONCILED
) ? 1 : 0;
715 insert2
= ( txn
->status
== TXN_STATUS_CLEARED
) ? 1 : 0;
717 insert
= insert1
| insert2
;
718 if(flt
->option
[FILTER_STATUS
] == 2) insert
^= 1;
720 if(!insert
) goto end
;
723 if(flt
->option
[FILTER_PAYMODE
]) {
724 insert
= ( flt
->paymode
[txn
->paymode
] == TRUE
) ? 1 : 0;
725 if(flt
->option
[FILTER_PAYMODE
] == 2) insert
^= 1;
727 if(!insert
) goto end
;
730 if(flt
->option
[FILTER_AMOUNT
]) {
731 insert
= ( (txn
->amount
>= flt
->minamount
) && (txn
->amount
<= flt
->maxamount
) ) ? 1 : 0;
733 if(flt
->option
[FILTER_AMOUNT
] == 2) insert
^= 1;
735 if(!insert
) goto end
;
738 if(flt
->option
[FILTER_TEXT
])
741 gint insert1
, insert2
, insert3
;
743 insert1
= insert2
= insert3
= 0;
748 insert1
= hb_string_utf8_strstr(txn
->info
, flt
->info
, flt
->exact
);
756 //#1668036 always try match on txn memo first
759 insert2
= hb_string_utf8_strstr(txn
->memo
, flt
->memo
, flt
->exact
);
762 if( (insert2
== 0) && (txn
->flags
& OF_SPLIT
) )
767 count
= da_splits_length(txn
->splits
);
772 split
= da_splits_get(txn
->splits
, i
);
773 tmpinsert
= hb_string_utf8_strstr(split
->memo
, flt
->memo
, flt
->exact
);
774 insert2
|= tmpinsert
;
785 tags
= tags_tostring(txn
->tags
);
788 insert3
= hb_string_utf8_strstr(tags
, flt
->tag
, flt
->exact
);
795 insert
= insert1
&& insert2
&& insert3
? 1 : 0;
797 if(flt
->option
[FILTER_TEXT
] == 2) insert
^= 1;
800 if(!insert
) goto end
;
803 // DB( g_print(" %d :: %d :: %d\n", flt->mindate, txn->date, flt->maxdate) );
804 // DB( g_print(" [%d] %s => %d (%d)\n", txn->account, txn->memo, insert, count) );
This page took 0.072422 seconds and 5 git commands to generate.