]>
Dogcows Code - chaz/homebank/blob - src/hb-filter.c
a4f8fb9792b0d8dd4a199583badbe0d575f757c1
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 void filter_preset_daterange_add_futuregap(Filter
*filter
, gint nbdays
)
246 DB( g_print("\n[filter] range add future gap\n") );
251 filter->nbdaysfuture = 0;
255 filter
->nbdaysfuture
= 0;
257 switch( filter
->range
)
259 case FLT_RANGE_THISMONTH
:
260 case FLT_RANGE_THISQUARTER
:
261 case FLT_RANGE_THISYEAR
:
262 case FLT_RANGE_LAST30DAYS
:
263 case FLT_RANGE_LAST60DAYS
:
264 case FLT_RANGE_LAST90DAYS
:
265 case FLT_RANGE_LAST12MONTHS
:
266 filter
->nbdaysfuture
= nbdays
;
272 void filter_preset_daterange_set(Filter
*flt
, gint range
, guint32 kacc
)
275 guint32 jtoday
, jfiscal
;
276 guint16 month
, year
, yfiscal
, qnum
;
278 DB( g_print("\n[filter] daterange set %p %d\n", flt
, range
) );
282 jtoday
= GLOBALS
->today
;
284 tmpdate
= g_date_new_julian(jtoday
);
286 month
= g_date_get_month(tmpdate
);
287 year
= g_date_get_year(tmpdate
);
288 DB( hb_print_date(jtoday
, "today ") );
290 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, year
);
291 jfiscal
= g_date_get_julian(tmpdate
);
292 DB( hb_print_date(jfiscal
, "fiscal") );
294 yfiscal
= (jtoday
>= jfiscal
) ? year
: year
-1;
297 if( range
== FLT_RANGE_THISQUARTER
|| range
== FLT_RANGE_LASTQUARTER
)
299 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, yfiscal
);
300 while( (qnum
< 5) && (g_date_get_julian(tmpdate
) < jtoday
) )
303 g_date_add_months (tmpdate
, 3);
305 DB( g_print(" qnum: %d\n", qnum
) );
310 case FLT_RANGE_THISMONTH
:
311 case FLT_RANGE_LASTMONTH
:
312 g_date_set_dmy(tmpdate
, 1, month
, year
);
313 if( range
== FLT_RANGE_LASTMONTH
)
314 g_date_subtract_months(tmpdate
, 1);
315 flt
->mindate
= g_date_get_julian(tmpdate
);
316 month
= g_date_get_month(tmpdate
);
317 year
= g_date_get_year(tmpdate
);
318 g_date_add_days(tmpdate
, g_date_get_days_in_month(month
, year
));
319 flt
->maxdate
= g_date_get_julian(tmpdate
) - 1;
322 case FLT_RANGE_THISQUARTER
:
323 case FLT_RANGE_LASTQUARTER
:
324 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, yfiscal
);
325 if( range
== FLT_RANGE_LASTQUARTER
)
326 g_date_subtract_months(tmpdate
, 3);
327 g_date_add_months(tmpdate
, 3 * (qnum
-1) );
328 flt
->mindate
= g_date_get_julian(tmpdate
);
329 g_date_add_months(tmpdate
, 3);
330 flt
->maxdate
= g_date_get_julian(tmpdate
) - 1;
333 case FLT_RANGE_THISYEAR
:
334 case FLT_RANGE_LASTYEAR
:
335 g_date_set_dmy(tmpdate
, PREFS
->fisc_year_day
, PREFS
->fisc_year_month
, yfiscal
);
336 if( range
== FLT_RANGE_LASTYEAR
)
337 g_date_subtract_years(tmpdate
, 1);
338 flt
->mindate
= g_date_get_julian(tmpdate
);
339 g_date_add_years (tmpdate
, 1);
340 flt
->maxdate
= g_date_get_julian(tmpdate
) - 1;
343 case FLT_RANGE_LAST30DAYS
:
344 flt
->mindate
= jtoday
- 30;
345 flt
->maxdate
= jtoday
;
348 case FLT_RANGE_LAST60DAYS
:
349 flt
->mindate
= jtoday
- 60;
350 flt
->maxdate
= jtoday
;
353 case FLT_RANGE_LAST90DAYS
:
354 flt
->mindate
= jtoday
- 90;
355 flt
->maxdate
= jtoday
;
358 case FLT_RANGE_LAST12MONTHS
:
359 g_date_set_julian (tmpdate
, jtoday
);
360 g_date_subtract_months(tmpdate
, 12);
361 flt
->mindate
= g_date_get_julian(tmpdate
);
362 flt
->maxdate
= jtoday
;
365 // case FLT_RANGE_OTHER:
368 case FLT_RANGE_ALLDATE
:
369 filter_set_date_bounds(flt
, kacc
);
372 g_date_free(tmpdate
);
376 void filter_preset_type_set(Filter
*flt
, gint type
)
379 DB( g_print("\n[filter] preset type set\n") );
383 flt
->option
[FILTER_AMOUNT
] = 0;
384 flt
->minamount
= G_MINDOUBLE
;
385 flt
->maxamount
= G_MINDOUBLE
;
389 case FLT_TYPE_EXPENSE
:
390 flt
->option
[FILTER_AMOUNT
] = 1;
391 flt
->minamount
= -G_MAXDOUBLE
;
392 flt
->maxamount
= G_MINDOUBLE
;
395 case FLT_TYPE_INCOME
:
396 flt
->option
[FILTER_AMOUNT
] = 1;
397 flt
->minamount
= G_MINDOUBLE
;
398 flt
->maxamount
= G_MAXDOUBLE
;
405 void filter_preset_status_set(Filter
*flt
, gint status
)
408 DB( g_print("\n[filter] preset status set\n") );
411 flt
->status
= status
;
412 flt
->option
[FILTER_STATUS
] = 0;
413 flt
->option
[FILTER_CATEGORY
] = 0;
414 flt
->option
[FILTER_PAYMODE
] = 0;
415 flt
->reconciled
= TRUE
;
417 //#1602835 fautly set
418 //flt->forceadd = TRUE;
419 //flt->forcechg = TRUE;
423 case FLT_STATUS_UNCATEGORIZED
:
424 flt
->option
[FILTER_CATEGORY
] = 1;
425 filter_status_cat_clear_except(flt
, 0);
426 flt
->option
[FILTER_PAYMODE
] = 1;
427 flt
->paymode
[PAYMODE_INTXFER
] = FALSE
;
430 case FLT_STATUS_UNRECONCILED
:
431 flt
->option
[FILTER_STATUS
] = 2;
432 flt
->reconciled
= TRUE
;
433 flt
->cleared
= FALSE
;
436 case FLT_STATUS_UNCLEARED
:
437 flt
->option
[FILTER_STATUS
] = 2;
438 flt
->reconciled
= FALSE
;
442 case FLT_STATUS_RECONCILED
:
443 flt
->option
[FILTER_STATUS
] = 1;
444 flt
->reconciled
= TRUE
;
445 flt
->cleared
= FALSE
;
448 case FLT_STATUS_CLEARED
:
449 flt
->option
[FILTER_STATUS
] = 1;
450 flt
->reconciled
= FALSE
;
458 gchar
*filter_daterange_text_get(Filter
*flt
)
464 gchar
*retval
= NULL
;
466 DB( g_print("\n[filter] daterange text get\n") );
468 date
= g_date_new_julian(flt
->mindate
);
469 g_date_strftime (buffer1
, 128-1, PREFS
->date_format
, date
);
471 g_date_set_julian(date
, flt
->maxdate
);
472 g_date_strftime (buffer2
, 128-1, PREFS
->date_format
, date
);
474 if( flt
->nbdaysfuture
> 0 )
476 g_date_set_julian(date
, flt
->maxdate
+ flt
->nbdaysfuture
);
477 g_date_strftime (buffer3
, 128-1, PREFS
->date_format
, date
);
478 retval
= g_strdup_printf("%s — <s>%s</s> %s", buffer1
, buffer2
, buffer3
);
481 retval
= g_strdup_printf("%s — %s", buffer1
, buffer2
);
485 //return g_strdup_printf(_("<i>from</i> %s <i>to</i> %s — "), buffer1, buffer2);
490 /* used for quicksearch text into transaction */
491 gboolean
filter_txn_search_match(gchar
*needle
, Transaction
*txn
, gint flags
)
493 gboolean retval
= FALSE
;
498 DB( g_print("\n[filter] tnx search match\n") );
500 if(flags
& FLT_QSEARCH_MEMO
)
502 //#1668036 always try match on txn memo first
505 retval
|= hb_string_utf8_strstr(txn
->memo
, needle
, FALSE
);
510 if(txn
->flags
& OF_SPLIT
)
515 count
= da_splits_length(txn
->splits
);
520 split
= da_splits_get(txn
->splits
, i
);
521 tmpinsert
= hb_string_utf8_strstr(split
->memo
, needle
, FALSE
);
530 if(flags
& FLT_QSEARCH_INFO
)
534 retval
|= hb_string_utf8_strstr(txn
->info
, needle
, FALSE
);
539 if(flags
& FLT_QSEARCH_PAYEE
)
541 payitem
= da_pay_get(txn
->kpay
);
544 retval
|= hb_string_utf8_strstr(payitem
->name
, needle
, FALSE
);
549 if(flags
& FLT_QSEARCH_CATEGORY
)
552 if(txn
->flags
& OF_SPLIT
)
557 count
= da_splits_length(txn
->splits
);
562 split
= da_splits_get(txn
->splits
, i
);
563 catitem
= da_cat_get(split
->kcat
);
566 tmpinsert
= hb_string_utf8_strstr(catitem
->fullname
, needle
, FALSE
);
576 catitem
= da_cat_get(txn
->kcat
);
579 retval
|= hb_string_utf8_strstr(catitem
->fullname
, needle
, FALSE
);
585 if(flags
& FLT_QSEARCH_TAGS
)
587 tags
= tags_tostring(txn
->tags
);
590 retval
|= hb_string_utf8_strstr(tags
, needle
, FALSE
);
596 //#1741339 add quicksearch for amount
597 if(flags
& FLT_QSEARCH_AMOUNT
)
599 gchar formatd_buf
[G_ASCII_DTOSTR_BUF_SIZE
];
601 hb_strfnum(formatd_buf
, G_ASCII_DTOSTR_BUF_SIZE
-1, txn
->amount
, txn
->kcur
, FALSE
);
602 retval
|= hb_string_utf8_strstr(formatd_buf
, needle
, FALSE
);
611 gint
filter_txn_match(Filter
*flt
, Transaction
*txn
)
618 //DB( g_print("\n[filter] txn match\n") );
622 /*** start filtering ***/
625 if(flt
->forceadd
== TRUE
&& (txn
->flags
& OF_ADDED
))
628 if(flt
->forcechg
== TRUE
&& (txn
->flags
& OF_CHANGED
))
631 /* force remind if not filter on status */
632 if(flt
->forceremind
== TRUE
&& (txn
->status
== TXN_STATUS_REMIND
))
636 if(flt
->option
[FILTER_DATE
]) {
637 insert
= ( (txn
->date
>= flt
->mindate
) && (txn
->date
<= (flt
->maxdate
+ flt
->nbdaysfuture
) ) ) ? 1 : 0;
638 if(flt
->option
[FILTER_DATE
] == 2) insert
^= 1;
640 if(!insert
) goto end
;
643 if(flt
->option
[FILTER_ACCOUNT
]) {
644 accitem
= da_acc_get(txn
->kacc
);
647 insert
= ( accitem
->flt_select
== TRUE
) ? 1 : 0;
648 if(flt
->option
[FILTER_ACCOUNT
] == 2) insert
^= 1;
651 if(!insert
) goto end
;
654 if(flt
->option
[FILTER_PAYEE
]) {
655 payitem
= da_pay_get(txn
->kpay
);
658 insert
= ( payitem
->flt_select
== TRUE
) ? 1 : 0;
659 if(flt
->option
[FILTER_PAYEE
] == 2) insert
^= 1;
662 if(!insert
) goto end
;
665 if(flt
->option
[FILTER_CATEGORY
]) {
666 if(txn
->flags
& OF_SPLIT
)
671 insert
= 0; //fix: 1151259
672 count
= da_splits_length(txn
->splits
);
677 split
= da_splits_get(txn
->splits
, i
);
678 catitem
= da_cat_get(split
->kcat
);
681 tmpinsert
= ( catitem
->flt_select
== TRUE
) ? 1 : 0;
682 if(flt
->option
[FILTER_CATEGORY
] == 2) tmpinsert
^= 1;
689 catitem
= da_cat_get(txn
->kcat
);
692 insert
= ( catitem
->flt_select
== TRUE
) ? 1 : 0;
693 if(flt
->option
[FILTER_CATEGORY
] == 2) insert
^= 1;
697 if(!insert
) goto end
;
700 if(flt
->option
[FILTER_STATUS
]) {
701 gint insert1
= 0, insert2
= 0;
704 insert1
= ( txn
->status
== TXN_STATUS_RECONCILED
) ? 1 : 0;
706 insert2
= ( txn
->status
== TXN_STATUS_CLEARED
) ? 1 : 0;
708 insert
= insert1
| insert2
;
709 if(flt
->option
[FILTER_STATUS
] == 2) insert
^= 1;
711 if(!insert
) goto end
;
714 if(flt
->option
[FILTER_PAYMODE
]) {
715 insert
= ( flt
->paymode
[txn
->paymode
] == TRUE
) ? 1 : 0;
716 if(flt
->option
[FILTER_PAYMODE
] == 2) insert
^= 1;
718 if(!insert
) goto end
;
721 if(flt
->option
[FILTER_AMOUNT
]) {
722 insert
= ( (txn
->amount
>= flt
->minamount
) && (txn
->amount
<= flt
->maxamount
) ) ? 1 : 0;
724 if(flt
->option
[FILTER_AMOUNT
] == 2) insert
^= 1;
726 if(!insert
) goto end
;
729 if(flt
->option
[FILTER_TEXT
])
732 gint insert1
, insert2
, insert3
;
734 insert1
= insert2
= insert3
= 0;
739 insert1
= hb_string_utf8_strstr(txn
->info
, flt
->info
, flt
->exact
);
747 //#1668036 always try match on txn memo first
750 insert2
= hb_string_utf8_strstr(txn
->memo
, flt
->memo
, flt
->exact
);
753 if( (insert2
== 0) && (txn
->flags
& OF_SPLIT
) )
758 count
= da_splits_length(txn
->splits
);
763 split
= da_splits_get(txn
->splits
, i
);
764 tmpinsert
= hb_string_utf8_strstr(split
->memo
, flt
->memo
, flt
->exact
);
765 insert2
|= tmpinsert
;
776 tags
= tags_tostring(txn
->tags
);
779 insert3
= hb_string_utf8_strstr(tags
, flt
->tag
, flt
->exact
);
786 insert
= insert1
&& insert2
&& insert3
? 1 : 0;
788 if(flt
->option
[FILTER_TEXT
] == 2) insert
^= 1;
791 if(!insert
) goto end
;
794 // DB( g_print(" %d :: %d :: %d\n", flt->mindate, txn->date, flt->maxdate) );
795 // DB( g_print(" [%d] %s => %d (%d)\n", txn->account, txn->memo, insert, count) );
This page took 0.067543 seconds and 3 git commands to generate.