~sjrct/homebank/resize-xfer-window

« back to all changes in this revision

Viewing changes to src/hb-report.c

  • Committer: Maxime Doyen
  • Date: 2023-09-06 19:23:05 UTC
  • Revision ID: homebank@free.fr-20230906192305-k19peze360g5cr9t
5.7 release

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
/****************************************************************************/
24
24
/* Debug macros                                                             */
25
25
/****************************************************************************/
26
 
#define MYDEBUG 0
27
 
 
28
 
#if MYDEBUG
29
 
#define DB(x) (x);
30
 
#else
31
 
#define DB(x);
32
 
#endif
 
26
 
 
27
#define DB1(x);
 
28
//#define DB1(x) (x);
 
29
 
 
30
#define DB2(x);
 
31
//#define DB2(x) (x);
 
32
 
 
33
#define DB3(x);
 
34
//#define DB3(x) (x);
33
35
 
34
36
 
35
37
/* our global datas */
39
41
 
40
42
extern gchar *CYA_ABMONTHS[];
41
43
 
 
44
 
 
45
static void _datatable_init_count_key_row(DataTable *dt, gint src, Filter *flt);
 
46
 
 
47
 
42
48
/* = = = = = = = = = = = = = = = = = = = = */
43
49
/* CarCost */
44
50
 
73
79
 
74
80
/* = = = = = = = = = = = = = = = = = = = = */
75
81
 
 
82
static void da_datacol_free(DataCol *col)
 
83
{
 
84
        if(col)
 
85
        {
 
86
                g_free(col->label);
 
87
                g_free(col->xlabel);
 
88
                g_free(col->misclabel);
 
89
        }
 
90
}
 
91
 
 
92
 
 
93
static DataCol *da_datacol_malloc(void)
 
94
{
 
95
        return g_malloc0(sizeof(DataCol));
 
96
}
 
97
 
 
98
 
76
99
static void da_datarow_free(DataRow *row)
77
100
{
78
101
        if(row)
79
102
        {
80
103
                g_free(row->label);
81
 
                g_free(row->expense);
82
 
                g_free(row->income);
 
104
                g_free(row->xlabel);
 
105
                g_free(row->misclabel);
 
106
                g_free(row->colexp);
 
107
                g_free(row->colinc);
83
108
        }
84
109
}
85
110
 
92
117
        if(!row)
93
118
                return NULL;
94
119
 
95
 
        row->nbcols = nbcol+2;
96
 
        row->expense = g_malloc0((nbcol+2) * sizeof(gdouble));
97
 
        row->income  = g_malloc0((nbcol+2) * sizeof(gdouble));
 
120
        row->nbcols = nbcol;
 
121
        row->colexp = g_malloc0((nbcol) * sizeof(gdouble));
 
122
        row->colinc = g_malloc0((nbcol) * sizeof(gdouble));
98
123
        return row;
99
124
}
100
125
 
101
126
 
 
127
//hub-reptime/hub-reptotal/repstats
102
128
void da_datatable_free(DataTable *dt)
103
129
{
104
130
guint i;
105
131
 
106
 
        DB( g_print("da_datatable_free\n") );
107
 
        
 
132
        DB1( g_print("\n[report] da_datatable_free: %p\n", dt) );
 
133
 
108
134
        if(dt != NULL)
109
135
        {
110
 
                //free each rows
 
136
                DB1( g_print(" free keylist\n") );
 
137
                g_free(dt->keylist);
 
138
                dt->keylist = NULL;
 
139
 
 
140
                DB1( g_print(" free datacol\n") );
 
141
                for(i=0;i<dt->nbcols;i++)
 
142
                {
 
143
                        da_datacol_free(dt->cols[i]);
 
144
                }
 
145
                g_free(dt->cols);
 
146
                dt->cols = NULL;                
 
147
 
 
148
                DB1( g_print(" free datarow\n") );
111
149
                for(i=0;i<dt->nbrows;i++)
112
150
                {
113
 
                DataRow *dr = dt->rows[i];
114
 
 
115
 
                        da_datarow_free(dr);
 
151
                        da_datarow_free(dt->rows[i]);
116
152
                }
 
153
                g_free(dt->rows);
 
154
                dt->rows = NULL;
117
155
 
 
156
                DB1( g_print(" free total datarow\n") );
118
157
                da_datarow_free(dt->totrow);
119
158
 
120
 
                g_free(dt->rows);
 
159
                DB1( g_print(" free keyindex\n") );
 
160
                g_free(dt->keyindex);
 
161
                dt->keyindex = NULL;
121
162
 
 
163
                DB1( g_print(" free datatable\n") );
122
164
                g_free(dt);
123
 
        
 
165
                
 
166
                DB1( g_print(" end free\n") );
124
167
        }
125
168
}
126
169
 
127
170
 
128
 
DataTable *da_datatable_malloc(gshort type, guint32 nbrows, guint32 nbcols)
 
171
static DataTable *da_datatable_malloc(gint src, gint intvl, Filter *flt)
129
172
{
130
173
DataTable *dt = g_malloc0(sizeof(DataTable));
131
174
guint i;
132
175
 
133
 
        DB( g_print("\nda_datatable_malloc\n") );
 
176
        DB1( g_print("\n[report] da_datatable_malloc: %p\n", dt) );
134
177
        
135
178
        if(!dt)
136
179
                return NULL;
137
 
        
138
 
        //allocate 2 more slot for total and average
139
 
        dt->nbrows = nbrows;
140
 
        dt->nbcols = nbcols;
141
 
        dt->rows = g_malloc0((nbrows) * sizeof(gpointer));
 
180
 
 
181
        _datatable_init_count_key_row(dt, src, flt);
 
182
        dt->nbcols = report_interval_count(intvl, flt->mindate, flt->maxdate);
 
183
        //dt->nbkeys = maximum keys for acc/pay/cat/tag
 
184
        //dt->nbrows = nb of items
 
185
        //dt->nbcols = nb of cols
 
186
 
 
187
        DB2( g_print(" src:%d\n intvl:%d\n maxk:%d\n rows:%d\n cols:%d\n", src, intvl, dt->nbkeys, dt->nbrows, dt->nbcols) );
 
188
 
 
189
        DB2( g_print(" alloc %d keyindex\n", dt->nbkeys) );
 
190
        dt->keyindex = g_malloc0(dt->nbkeys * sizeof(gpointer));
 
191
 
 
192
        DB2( g_print(" alloc %d rows\n", dt->nbrows) );
 
193
        dt->rows = g_malloc0(dt->nbrows * sizeof(gpointer));
142
194
        for(i=0;i<dt->nbrows;i++)
143
195
        {
144
 
        DataRow *dr = da_datarow_malloc(dt->nbcols+2);
 
196
        DataRow *dr = da_datarow_malloc(dt->nbcols);
145
197
 
146
198
                //dr->label = ;
147
199
                //dr.pos = ;
148
200
                dt->rows[i] = dr;
149
201
        }
150
202
 
151
 
        dt->totrow = da_datarow_malloc(dt->nbcols+2);
152
 
 
153
 
        DB( g_print("- @%p, r=%d, c=%d\n", dt, nbrows, nbcols) );
 
203
        DB2( g_print(" alloc total row\n") );
 
204
        dt->totrow = da_datarow_malloc(dt->nbcols);
 
205
 
 
206
        DB2( g_print(" alloc %d cols\n", dt->nbcols) );
 
207
        dt->cols = g_malloc0(dt->nbcols * sizeof(gpointer));
 
208
        for(i=0;i<dt->nbcols;i++)
 
209
        {
 
210
        DataCol *dc = da_datacol_malloc();
 
211
                dt->cols[i] = dc;
 
212
        }
 
213
 
 
214
        //ordered list to insert cat before subcat
 
215
        DB2( g_print(" alloc %d keylist\n", dt->nbrows) );
 
216
        dt->keylist = g_malloc0( dt->nbrows * sizeof(guint32) );
154
217
 
155
218
        return dt;
156
219
}
157
220
 
158
221
 
159
 
gdouble da_datarow_get_cell_sum(DataRow *dr, guint32 index)
160
 
{
161
 
        if( index <= dr->nbcols )
162
 
        {
163
 
                return (dr->expense[index] + dr->income[index]);
164
 
        }
165
 
 
166
 
        g_warning("invalid datarow column");
167
 
        return 0;
168
 
}
169
 
 
170
 
 
171
222
/* = = = = = = = = = = = = = = = = = = = = */
172
223
 
173
224
 
174
225
// slide the date to monday of the week
175
 
static void hb_date_clamp_iso8601(GDate *date)
 
226
static void _hb_date_clamp_iso8601(GDate *date)
176
227
{
177
228
GDateWeekday wday;
178
229
 
182
233
}
183
234
 
184
235
 
185
 
static guint date_in_week(guint32 from, guint32 opedate, guint days)
 
236
static guint _date_in_week(guint32 from, guint32 opedate, guint days)
186
237
{
187
238
GDate *date1, *date2;
188
239
gint pos;
190
241
        date1 = g_date_new_julian(from);
191
242
        date2 = g_date_new_julian(opedate);
192
243
 
193
 
        DB( g_print(" from=%d %02d-%02d-%04d ", 
 
244
        DB3( g_print(" from=%d %02d-%02d-%04d ", 
194
245
                g_date_get_weekday(date1), g_date_get_day(date1), g_date_get_month(date1), g_date_get_year(date1)) );
195
246
 
196
247
        //#1915643 week iso 8601
197
 
        hb_date_clamp_iso8601(date1);
 
248
        _hb_date_clamp_iso8601(date1);
198
249
        pos = (opedate - g_date_get_julian(date1)) / days;
199
250
 
200
 
        DB( g_print(" shifted=%d %02d-%02d-%04d pos=%d\n", 
 
251
        DB3( g_print(" shifted=%d %02d-%02d-%04d pos=%d\n", 
201
252
                g_date_get_weekday(date1), g_date_get_day(date1), g_date_get_month(date1), g_date_get_year(date1), pos) );
202
253
 
203
254
 
213
264
*/
214
265
static guint DateInWeek(guint32 from, guint32 opedate)
215
266
{
216
 
        return date_in_week(from, opedate, 7);
 
267
        return _date_in_week(from, opedate, 7);
217
268
}       
218
269
 
219
270
 
222
273
*/
223
274
static guint DateInFortNight(guint32 from, guint32 opedate)
224
275
{
225
 
        return date_in_week(from, opedate, 14);
 
276
        return _date_in_week(from, opedate, 14);
226
277
}       
227
278
 
228
279
 
234
285
GDate *date1, *date2;
235
286
guint pos;
236
287
 
 
288
        DB3( g_print("DateInMonth %d ,%d\n", from, opedate) );
 
289
 
237
290
        //todo
238
291
        // this return sometimes -1, -2 which is wrong
239
292
 
242
295
 
243
296
        pos = ((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1);
244
297
 
245
 
        DB( g_print(" from=%d-%d ope=%d-%d => %d\n", g_date_get_month(date1), g_date_get_year(date1), g_date_get_month(date2), g_date_get_year(date2), pos) );
 
298
        DB3( g_print(" from=%d-%d ope=%d-%d => %d\n", g_date_get_month(date1), g_date_get_year(date1), g_date_get_month(date2), g_date_get_year(date2), pos) );
246
299
 
247
300
        g_date_free(date2);
248
301
        g_date_free(date1);
268
321
 
269
322
        //#1758532 shift to first quarter day of 'from date' 
270
323
        quarter = ((g_date_get_month(date1)-1)/3)+1;
271
 
        DB( g_print("-- from=%02d/%d :: Q%d\n", g_date_get_month(date1), g_date_get_year(date1), quarter) );
 
324
        DB3( g_print("-- from=%02d/%d :: Q%d\n", g_date_get_month(date1), g_date_get_year(date1), quarter) );
272
325
        g_date_set_day(date1, 1);
273
326
        g_date_set_month(date1, ((quarter-1)*3)+1);
274
327
 
275
328
        pos = (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/3;
276
329
 
277
 
        DB( g_print("-- from=%02d/%d ope=%02d/%d => pos=%d\n", g_date_get_month(date1), g_date_get_year(date1), g_date_get_month(date2), g_date_get_year(date2), pos) );
 
330
        DB3( g_print("-- from=%02d/%d ope=%02d/%d => pos=%d\n", g_date_get_month(date1), g_date_get_year(date1), g_date_get_month(date2), g_date_get_year(date2), pos) );
278
331
 
279
332
        g_date_free(date2);
280
333
        g_date_free(date1);
293
346
 
294
347
        // shift to first half year of 'from date'
295
348
        hyear = ((g_date_get_month(date1)-1)/6)+1;
296
 
        DB( g_print("-- from=%02d/%d :: Q%d\n", g_date_get_month(date1), g_date_get_year(date1), hyear) );
 
349
        DB3( g_print("-- from=%02d/%d :: Q%d\n", g_date_get_month(date1), g_date_get_year(date1), hyear) );
297
350
        g_date_set_day(date1, 1);
298
351
        g_date_set_month(date1, ((hyear-1)*6)+1);
299
352
        
300
353
        pos = (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/6;
301
354
 
302
 
        DB( g_print(" from=%d-%d ope=%d-%d => %d\n", g_date_get_month(date1), g_date_get_year(date1), g_date_get_month(date2), g_date_get_year(date2), pos) );
 
355
        DB3( g_print(" from=%d-%d ope=%d-%d => %d\n", g_date_get_month(date1), g_date_get_year(date1), g_date_get_month(date2), g_date_get_year(date2), pos) );
303
356
 
304
357
        g_date_free(date2);
305
358
        g_date_free(date1);
325
378
 
326
379
        pos = year_ope - year_from;
327
380
 
328
 
        DB( g_print(" from=%d ope=%d => %d\n", year_from, year_ope, pos) );
 
381
        DB3( g_print(" from=%d ope=%d => %d\n", year_from, year_ope, pos) );
329
382
 
330
383
        return(pos);
331
384
}
332
385
 
333
386
 
334
 
 
335
 
void datatable_init_items(DataTable *dt, gint src, guint32 jfrom)
336
 
{
337
 
GList *list = NULL;
338
 
gint pos;
339
 
gchar *name;
340
 
gchar buffer[64];
341
 
guint i;
342
 
 
343
 
        DB( g_print("\ndatatable_init_items\n") );
344
 
        
345
 
        switch(src)
346
 
        {
347
 
                case REPORT_SRC_CATEGORY:
348
 
                case REPORT_SRC_SUBCATEGORY:
349
 
                        list = category_glist_sorted(1);
350
 
                        break;
351
 
                case REPORT_SRC_PAYEE:
352
 
                        list = payee_glist_sorted(1);
353
 
                        break;
354
 
                case REPORT_SRC_ACCOUNT:
355
 
                        list = account_glist_sorted(1);
356
 
                        break;
357
 
                case REPORT_SRC_TAG:
358
 
                        list = tag_glist_sorted(1);
359
 
                        break;
360
 
        }
361
 
 
362
 
 
363
 
        //todo: list_index has a cost
364
 
        //preferable to iter through the list
365
 
        for(i=0;i<dt->nbrows;i++)
366
 
        {
367
 
        DataRow *dr = dt->rows[i];
 
387
static guint32 _datatable_interval_get_jdate(gint intvl, guint32 jfrom, gint idx)
 
388
{
 
389
GDate *date = g_date_new_julian(jfrom);
 
390
GDateWeekday wday;
 
391
guint32 jdate;
 
392
 
 
393
        switch(intvl)
 
394
        {
 
395
                case REPORT_INTVL_DAY:
 
396
                        g_date_add_days(date, idx);
 
397
                        break;
 
398
                case REPORT_INTVL_WEEK:
 
399
                        g_date_add_days(date, idx*7);
 
400
                        //#1915643 week iso 8601
 
401
                        //ISO 8601 from must be monday, to slice in correct week
 
402
                        wday = g_date_get_weekday(date);
 
403
                        g_date_subtract_days (date, wday-G_DATE_MONDAY);
 
404
                        g_date_add_days (date, G_DATE_WEDNESDAY);
 
405
                        break;
 
406
                //#2000290
 
407
                case REPORT_INTVL_FORTNIGHT:
 
408
                        _hb_date_clamp_iso8601(date);
 
409
                        g_date_add_days(date, idx*14);
 
410
                        break;
 
411
                case REPORT_INTVL_MONTH:
 
412
                        g_date_add_months(date, idx);
 
413
                        break;
 
414
                case REPORT_INTVL_QUARTER:
 
415
                        g_date_add_months(date, idx*3);
 
416
                        break;
 
417
                case REPORT_INTVL_HALFYEAR:
 
418
                        g_date_add_months(date, idx*6);
 
419
                        break;
 
420
                case REPORT_INTVL_YEAR:
 
421
                        g_date_add_years(date, idx);
 
422
                        break;
 
423
        }
 
424
 
 
425
        jdate = g_date_get_julian(date);
 
426
 
 
427
        g_date_free(date);
 
428
 
 
429
        return jdate;
 
430
}
 
431
 
 
432
 
 
433
/* = = = = = = = = = = = = = = = = = = = = */
 
434
 
 
435
static void datatable_set_keylist(DataTable *dt, guint32 idx, guint32 key)
 
436
{
 
437
        if( idx <= dt->nbrows )
 
438
                dt->keylist[idx] = key;
 
439
        else
 
440
                g_warning("datatable invalid set keylist %d of %d", idx , dt->nbrows);
 
441
}
 
442
 
 
443
static void datatable_set_keyindex(DataTable *dt, guint32 key, guint32 idx)
 
444
{
 
445
        if( key <= dt->nbkeys )
 
446
                dt->keyindex[key] = idx;
 
447
        else
 
448
                g_warning("datatable invalid set keyindex %d of %d", key , dt->nbkeys);
 
449
}
 
450
 
 
451
static void _datatable_init_count_key_row(DataTable *dt, gint src, Filter *flt)
 
452
{
 
453
guint n_row, n_key;
 
454
 
 
455
        n_row = n_key = 0;
 
456
        if( src != REPORT_SRC_MONTH && src != REPORT_SRC_YEAR )
 
457
        {
 
458
                switch(src)
 
459
                {
 
460
                        case REPORT_SRC_NONE:
 
461
                                n_row = 1;
 
462
                                n_key  = 1;
 
463
                                break;
 
464
                        case REPORT_SRC_CATEGORY:
 
465
                                n_row = da_cat_length();
 
466
                                n_key  = da_cat_get_max_key();
 
467
                                break;
 
468
                        case REPORT_SRC_PAYEE:
 
469
                                n_row = da_pay_length();
 
470
                                n_key  = da_pay_get_max_key();
 
471
                                break;
 
472
                        //5.7: todo check this +1
 
473
                        case REPORT_SRC_ACCOUNT:
 
474
                                n_row = da_acc_length();
 
475
                                n_key  = da_acc_get_max_key();
 
476
                                break;
 
477
                        case REPORT_SRC_TAG:
 
478
                                n_row = da_tag_length();
 
479
                                n_key  = da_tag_get_max_key();
 
480
                                break;
 
481
                }
 
482
        }
 
483
        else
 
484
        {
 
485
        GDate *date1 = g_date_new_julian(flt->mindate);
 
486
        GDate *date2 = g_date_new_julian(flt->maxdate);
 
487
        
 
488
                switch(src)
 
489
                {
 
490
                        case REPORT_SRC_MONTH:
 
491
                                n_row = ((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1) + 1;
 
492
                                n_key = n_row;
 
493
                                break;
 
494
                        case REPORT_SRC_YEAR:
 
495
                                n_row = g_date_get_year(date2) - g_date_get_year(date1) + 1;
 
496
                                n_key = n_row;
 
497
                        break;
 
498
                }
 
499
 
 
500
                g_date_free(date2);
 
501
                g_date_free(date1);
 
502
        }
 
503
 
 
504
        //we add 1 to every key as 0 is an item
 
505
        dt->nbkeys = n_key + 1;
 
506
        dt->nbrows = n_row;
 
507
}
 
508
 
 
509
 
 
510
static void _datatable_init_items_cat(DataTable *dt)
 
511
{
 
512
GList *lcat, *l;
 
513
guint idx = 0;
 
514
 
 
515
        lcat = l = category_glist_sorted(HB_GLIST_SORT_NAME);
 
516
        while (l != NULL )
 
517
        {
 
518
        Category *cat = l->data;
 
519
        DataRow *dr = dt->rows[idx];
 
520
 
 
521
                if( dr != NULL )
 
522
                {
 
523
                        dr->pos   = idx;
 
524
                        dr->label = g_strdup( (cat->key == 0) ? _("(no category)") : cat->name );
 
525
                        //dt->keyindex[cat->key] = idx;
 
526
                        datatable_set_keyindex(dt, cat->key, idx);
 
527
                        
 
528
                        DB1( g_print(" +cat k:%d, idx:%d %s'%s'\n", cat->key, idx, cat->parent==0 ? "" : " +", dr->label) );
 
529
                }
 
530
                l = g_list_next(l);
 
531
                idx++;
 
532
        }
 
533
        g_list_free(lcat);
 
534
 
 
535
        //init keylist
 
536
        DB2( g_print(" add cat keys") );
 
537
        idx = 0;
 
538
        lcat = l = category_glist_sorted(HB_GLIST_SORT_KEY);
 
539
        while (l != NULL)
 
540
        {
 
541
        Category *cat = l->data;
 
542
        
 
543
                //dt->keylist[idx] = cat->key;
 
544
                datatable_set_keylist(dt, idx, cat->key);
 
545
                DB2( g_print(" %d", cat->key) );
 
546
                l = g_list_next(l);
 
547
                idx++;
 
548
        }
 
549
        g_list_free(lcat);
 
550
        DB2( g_print("\n") );   
 
551
}
 
552
 
 
553
static void _datatable_init_items_pay(DataTable *dt)
 
554
{
 
555
GList *lpay, *l;
 
556
guint idx = 0;
 
557
 
 
558
        lpay = l = payee_glist_sorted(HB_GLIST_SORT_NAME);
 
559
        while (l != NULL )
 
560
        {
 
561
        Payee *pay = l->data;
 
562
        DataRow *dr = dt->rows[idx];
 
563
 
 
564
                if( dr != NULL )
 
565
                {
 
566
                        dr->pos   = idx;
 
567
                        dr->label = g_strdup( (pay->key == 0) ? _("(no payee)") : pay->name );
 
568
                        DB1( g_print(" +pay k:%d, idx:%d '%s'\n", pay->key, idx, dr->label) );
 
569
                        //store transpose
 
570
                        //dt->keyindex[pay->key] = idx;
 
571
                        datatable_set_keyindex(dt, pay->key, idx);
 
572
                        //store keylist
 
573
                        //dt->keylist[idx] = pay->key;
 
574
                        datatable_set_keylist(dt, idx, pay->key);
 
575
                }
 
576
                l = g_list_next(l);
 
577
                idx++;
 
578
        }
 
579
        g_list_free(lpay);
 
580
}
 
581
 
 
582
static void _datatable_init_items_acc(DataTable *dt)
 
583
{
 
584
GList *lacc, *l;
 
585
guint idx = 0;
 
586
 
 
587
        lacc = l = account_glist_sorted(HB_GLIST_SORT_NAME);
 
588
        while (l != NULL )
 
589
        {
 
590
        Account *acc = l->data;
 
591
        DataRow *dr = dt->rows[idx];
 
592
 
 
593
                if( dr != NULL )
 
594
                {
 
595
 
 
596
                        dr->pos   = idx;
 
597
                        dr->label = g_strdup( acc->name );
 
598
                        DB1( g_print(" +acc k:%d, idx:%d '%s'\n", acc->key, idx, dr->label) );
 
599
                        //store transpose
 
600
                        dt->keyindex[acc->key] = idx;
 
601
                        //datatable_set_keyindex(dt, acc->key, idx);
 
602
                        //store keylist
 
603
                        dt->keylist[idx] = acc->key;
 
604
                        //datatable_set_keylist(dt, idx, acc->key);
 
605
                }
 
606
                l = g_list_next(l);
 
607
                idx++;
 
608
        }
 
609
        g_list_free(lacc);
 
610
}
 
611
 
 
612
 
 
613
static void _datatable_init_items_tag(DataTable *dt)
 
614
{
 
615
GList *ltag, *l;
 
616
guint idx = 0;
 
617
 
 
618
        ltag = l = tag_glist_sorted(HB_GLIST_SORT_NAME);
 
619
        while (l != NULL )
 
620
        {
 
621
        Tag *tag = l->data;
 
622
        DataRow *dr = dt->rows[idx];
 
623
 
 
624
                if( dr != NULL )
 
625
                {
 
626
                        dr->pos   = idx;
 
627
                        dr->label = g_strdup( (tag->key == 0) ? _("(no tag)") : tag->name );
 
628
                        DB1( g_print(" +tag k:%d, idx:%d '%s'\n", tag->key, idx, dr->label) );
 
629
                        //store transpose
 
630
                        //dt->keyindex[tag->key] = idx;
 
631
                        datatable_set_keyindex(dt, tag->key, idx);
 
632
                        //store keylist
 
633
                        //dt->keylist[idx] = tag->key;
 
634
                        datatable_set_keylist(dt, idx, tag->key);
 
635
                }
 
636
                l = g_list_next(l);
 
637
                idx++;
 
638
        }
 
639
        g_list_free(ltag);
 
640
}
 
641
 
 
642
 
 
643
static void datatable_data_get_xlabel(GDate *date, guint intvl, gchar *intvlname, gsize slen)
 
644
{
 
645
        intvlname[0] ='\0';
 
646
        switch(intvl)
 
647
        {
 
648
                case REPORT_INTVL_DAY:
 
649
                case REPORT_INTVL_FORTNIGHT:
 
650
                        g_date_strftime (intvlname, slen, "%b-%d", date);
 
651
                        break;
 
652
                case REPORT_INTVL_WEEK:
 
653
                        //TRANSLATORS: printf string for year of week W, ex. 2019-W52 for week 52 of 2019
 
654
                        g_snprintf(intvlname, slen, _("w%02d"), g_date_get_iso8601_week_of_year(date));
 
655
                        break;
 
656
                case REPORT_INTVL_MONTH:
 
657
                        g_snprintf(intvlname, slen, "%s", _(CYA_ABMONTHS[g_date_get_month(date)]));
 
658
                        break;
 
659
                case REPORT_INTVL_QUARTER:
 
660
                        //todo: will be innacurrate here if fiscal year start not 1/jan
 
661
                        //TRANSLATORS: printf string for year of quarter Q, ex. 2019-Q4 for quarter 4 of 2019
 
662
                        g_snprintf(intvlname, slen, _("q%d"), ((g_date_get_month(date)-1)/3)+1);
 
663
                        break;
 
664
                case REPORT_INTVL_HALFYEAR:
 
665
                        //#2007712
 
666
                        //TRANSLATORS: printf string for half-year H, ex. 2019-H1 for 1st half-year of 2019
 
667
                        g_snprintf(intvlname, slen, _("h%d"), g_date_get_month(date) < 7 ? 1 : 2);
 
668
                        break;
 
669
                case REPORT_INTVL_YEAR:
 
670
                        g_snprintf(intvlname, slen, "%d", g_date_get_year(date));
 
671
                        break;
 
672
        }
 
673
}
 
674
 
 
675
 
 
676
static void datatable_init_items(DataTable *dt, gint src, guint32 jfrom)
 
677
{
 
678
GDate *date;
 
679
gchar buffer[64], *name;
 
680
guint32 jdate;
 
681
guint idx, slen = 63;
 
682
GDateYear prevyear = 0;
 
683
 
 
684
        DB1( g_print("\n-- datatable_init_items--\n") );
 
685
 
 
686
        if( src != REPORT_SRC_MONTH && src != REPORT_SRC_YEAR )
 
687
        {
 
688
                switch(src)
 
689
                {
 
690
                        case REPORT_SRC_CATEGORY:
 
691
                                _datatable_init_items_cat(dt);
 
692
                                break;
 
693
                        case REPORT_SRC_PAYEE:
 
694
                                _datatable_init_items_pay(dt);
 
695
                                break;
 
696
                        case REPORT_SRC_ACCOUNT:
 
697
                                _datatable_init_items_acc(dt);
 
698
                                break;
 
699
                        case REPORT_SRC_TAG:
 
700
                                _datatable_init_items_tag(dt);
 
701
                                break;
 
702
                }
 
703
                return;
 
704
        }
 
705
 
 
706
 
 
707
        date = g_date_new();
 
708
        for(idx=0;idx<dt->nbrows;idx++)
 
709
        {
 
710
        DataRow *dr = dt->rows[idx];
 
711
        guint intvl = REPORT_INTVL_NONE;
368
712
                
369
 
                pos = i;
370
713
                name = NULL;
371
714
                switch(src)
372
715
                {
373
 
                        case REPORT_SRC_CATEGORY:
374
 
                        case REPORT_SRC_SUBCATEGORY:
375
 
                                {       
376
 
                                Category *entry = da_cat_get(i);
377
 
                                        if(entry != NULL)
378
 
                                        {
379
 
                                                name = entry->key == 0 ? _("(no category)") : entry->fullname;
380
 
                                                //if( src == REPORT_SRC_SUBCATEGORY )
381
 
                                                        //name = entry->name;
382
 
                                                pos = g_list_index(list, entry);
383
 
                                        }
384
 
                                }       
385
 
                                break;
386
 
                        case REPORT_SRC_PAYEE:
387
 
                                {
388
 
                                Payee *entry = da_pay_get(i);
389
 
                                        if(entry != NULL)
390
 
                                        {
391
 
                                                name = entry->key == 0 ? _("(no payee)") : entry->name;
392
 
                                                pos = g_list_index(list, entry);
393
 
                                        }
394
 
                                }
395
 
                                break;
396
 
 
397
 
                        case REPORT_SRC_ACCOUNT:
398
 
                                {
399
 
                                Account *entry = da_acc_get(i);
400
 
                                        if(entry != NULL)
401
 
                                        {
402
 
                                                name = entry->name;
403
 
                                                pos = g_list_index(list, entry);
404
 
                                        }
405
 
                                }
406
 
                                break;
407
 
 
408
 
                        case REPORT_SRC_TAG:
409
 
                                {
410
 
                                Tag *entry = da_tag_get(i+1);
411
 
                                        if(entry != NULL)
412
 
                                        {
413
 
                                                name = entry->name;
414
 
                                                pos = g_list_index(list, entry);
415
 
                                        }
416
 
                                }
417
 
                                break;
418
 
 
 
716
                        case REPORT_SRC_NONE:
 
717
                                //technical label for sum
 
718
                                name = "total";
 
719
                                DB1( g_print(" +none k:%d, idx:%d '%s'\n", idx, idx, name) );
 
720
                                break;
419
721
                        case REPORT_SRC_MONTH:
420
 
                                report_interval_snprint_name(buffer, sizeof(buffer)-1, REPORT_INTVL_MONTH, jfrom, i);
 
722
                                intvl = REPORT_INTVL_MONTH;
 
723
                                jdate = report_interval_snprint_name(buffer, sizeof(buffer)-1, intvl, jfrom, idx);
421
724
                                name = buffer;
422
 
                                pos = i;
 
725
                                DB1( g_print(" +month k:%d, idx:%d '%s'\n", idx, idx, name) );
423
726
                                break;
424
 
 
425
727
                        case REPORT_SRC_YEAR:
426
 
                                report_interval_snprint_name(buffer, sizeof(buffer)-1, REPORT_INTVL_YEAR, jfrom, i);
 
728
                                intvl = REPORT_INTVL_YEAR;
 
729
                                jdate = report_interval_snprint_name(buffer, sizeof(buffer)-1, intvl, jfrom, idx);
427
730
                                name = buffer;
428
 
                                pos = i;
 
731
                                DB1( g_print(" +year k:%d, idx:%d '%s'\n", idx, idx, name) );
429
732
                                break;
430
733
                }
431
734
 
432
 
                DB( g_print("- init row:%d / pos:%d '%s'\n", i, pos, name) );
433
 
 
434
 
                dr->pos = pos;
435
 
                dr->label = g_strdup(name);
436
 
        }
437
 
 
438
 
        g_list_free(list);
439
 
 
440
 
}
441
 
 
442
 
 
443
 
// this is the add in total mode
444
 
void datatable_amount_add(DataTable *dt, guint32 idx, gdouble amount)
445
 
{
446
 
        if( idx <= (dt->nbrows) )
447
 
        {
448
 
        DataRow *dr = dt->rows[idx];
449
 
 
450
 
                if(amount > 0.0)
451
 
                {
452
 
                        dr->income[1] += amount;
453
 
                        dt->totinc += amount;
454
 
                }
455
 
                else
456
 
                {
457
 
                        dr->expense[0] += amount;
458
 
                        dt->totexp += amount;
459
 
                }
460
 
        }
461
 
        else
462
 
                g_warning("invalid datatable index");
463
 
}
464
 
 
465
 
 
466
 
DataTable *report_compute_total(gint tmpsrc, Filter *flt, GQueue *txn_queue)
467
 
{
468
 
DataTable *dt;
469
 
GList *list;
470
 
guint i;
471
 
gint n_result;
472
 
 
473
 
        DB( g_print("\n[report] compute_total\n") );
474
 
        
475
 
        //todo: remove this later on
476
 
        n_result = report_items_count(tmpsrc, flt->mindate, flt->maxdate);
477
 
 
478
 
        DB( g_print(" %d :: n_result=%d\n", tmpsrc, n_result) );
479
 
        
480
 
        dt = da_datatable_malloc (0, n_result, 3);
481
 
        if( dt != NULL )
482
 
        {
483
 
                datatable_init_items(dt, tmpsrc, flt->mindate);
484
 
 
485
 
                list = g_queue_peek_head_link(txn_queue);
486
 
                while (list != NULL)
487
 
                {
488
 
                Transaction *ope = list->data;
489
 
                        
490
 
                        DB( g_print("** testing '%s', cat=%d==> %d\n", ope->memo, ope->kcat, filter_txn_match(flt, ope)) );
491
 
 
492
 
                        if( (filter_txn_match(flt, ope) == 1) )
 
735
                dr->pos = idx;
 
736
                if( name != NULL )
 
737
                        dr->label = g_strdup(name);
 
738
 
 
739
                //store transpose
 
740
                //dt->keyindex[idx] = idx;
 
741
                datatable_set_keyindex(dt, idx, idx);
 
742
                //store keylist
 
743
                //dt->keylist[idx] = idx;
 
744
                datatable_set_keylist(dt, idx, idx);
 
745
                
 
746
                //manage xlabel
 
747
                g_date_set_julian(date, jdate);
 
748
 
 
749
                datatable_data_get_xlabel(date, intvl, buffer, slen);
 
750
 
 
751
                dr->xlabel = g_strdup(buffer);
 
752
                
 
753
                //set flags => moved into forecast
 
754
                //if( jdate > GLOBALS->today )
 
755
                //      dc->flags |= RF_FORECAST;
 
756
        
 
757
                if( (intvl != REPORT_INTVL_YEAR) && (g_date_get_year(date) > prevyear) && (g_date_get_month(date) == 1) )
 
758
                {
 
759
                        g_snprintf(buffer, slen, "%d", g_date_get_year(date));
 
760
                        dr->misclabel = g_strdup(buffer);
 
761
                        dr->flags |= RF_NEWYEAR;
 
762
                }
 
763
 
 
764
                prevyear = g_date_get_year(date);               
 
765
                
 
766
        }
 
767
        
 
768
        g_date_free(date);
 
769
 
 
770
/*end:
 
771
        //debug keyindex
 
772
        g_print(" keyindex:");
 
773
        for(idx=0;idx<dt->nbkeys;idx++)
 
774
                g_print(" %d", dt->keyindex[idx]);
 
775
        g_print("\n");
 
776
        
 
777
        //debug keylist
 
778
        g_print(" keylist:");
 
779
        for(idx=0;idx<dt->nbrows;idx++)
 
780
                g_print(" %d", dt->keylist[idx]);
 
781
        g_print("\n");
 
782
*/
 
783
}
 
784
 
 
785
 
 
786
static void datatable_init_columns(DataTable *dt, gint intvl, guint32 jfrom)
 
787
{
 
788
GDate *date;
 
789
gchar intvlname[64];
 
790
guint32 jdate;
 
791
guint idx, slen = 63;
 
792
GDateYear prevyear = 0;
 
793
 
 
794
        date = g_date_new();
 
795
 
 
796
        for(idx=0;idx<dt->nbcols;idx++)
 
797
        {
 
798
        DataCol *dc = dt->cols[idx];
 
799
 
 
800
                //TODO: check
 
801
                report_interval_snprint_name(intvlname, sizeof(intvlname)-1, intvl, jfrom, idx);
 
802
                dc->label = g_strdup(intvlname);
 
803
 
 
804
                //new stuff
 
805
                jdate = _datatable_interval_get_jdate(intvl, jfrom, idx);
 
806
                g_date_set_julian(date, jdate);
 
807
 
 
808
                datatable_data_get_xlabel(date, intvl, intvlname, slen);
 
809
 
 
810
                dc->xlabel = g_strdup(intvlname);
 
811
 
 
812
                //set flags => moved into forecast
 
813
                if( jdate > GLOBALS->today )
 
814
                        dc->flags |= RF_FORECAST;
 
815
        
 
816
                if( (intvl != REPORT_INTVL_YEAR) && (g_date_get_year(date) > prevyear) && (g_date_get_month(date) == 1) )
 
817
                {
 
818
                        g_snprintf(intvlname, slen, "%d", g_date_get_year(date));
 
819
                        dc->misclabel = g_strdup(intvlname);
 
820
                        dc->flags |= RF_NEWYEAR;
 
821
                }
 
822
 
 
823
                prevyear = g_date_get_year(date);
 
824
        }
 
825
 
 
826
        g_date_free(date);
 
827
 
 
828
}
 
829
 
 
830
static void datatable_add(DataTable *dt, guint32 key, guint32 col, gdouble amount, gboolean addtotal)
 
831
{
 
832
DataRow *dr;
 
833
 
 
834
        DB3( g_print("   add to k:%d c:%d %.2f\n", key, col, amount) );
 
835
 
 
836
        //row = dt->keyindex[key];
 
837
        dr = report_data_get_row(dt, key); 
 
838
 
 
839
        if( dr )
 
840
        {
 
841
                if( col <= dt->nbcols )
 
842
                {
 
843
                        if( hb_amount_equal(amount, 0.0) == FALSE )
493
844
                        {
494
 
                        guint32 pos = 0;
495
 
                        gdouble trn_amount;
496
 
 
497
 
                                DB( g_print(" - should insert\n") );
498
 
 
499
 
                                trn_amount = report_txn_amount_get(flt, ope);
500
 
                                trn_amount = hb_amount_base(trn_amount, ope->kcur);
501
 
 
502
 
 
503
 
                                if( tmpsrc != REPORT_SRC_TAG )
 
845
                                if( amount < 0.0 )
504
846
                                {
505
 
                                        //for split, affect the amount to the category
506
 
                                        if( (tmpsrc == REPORT_SRC_CATEGORY || tmpsrc == REPORT_SRC_SUBCATEGORY) && ope->flags & OF_SPLIT )
507
 
                                        {
508
 
                                        guint nbsplit = da_splits_length(ope->splits);
509
 
                                        Split *split;
510
 
                                        gboolean status;
511
 
                                        gint sinsert;
512
 
 
513
 
                                                for(i=0;i<nbsplit;i++)
514
 
                                                {
515
 
                                                        split = da_splits_get(ope->splits, i);
516
 
                                                        status = da_flt_status_cat_get(flt, split->kcat);
517
 
                                                        sinsert = ( status == TRUE ) ? 1 : 0;
518
 
                                                        if(flt->option[FLT_GRP_CATEGORY] == 2) sinsert ^= 1;
519
 
 
520
 
                                                        DB( g_print(" split insert=%d, kcat=%d\n", sinsert, split->kcat) );
521
 
 
522
 
                                                        if( (flt->option[FLT_GRP_CATEGORY] == 0) || sinsert)
523
 
                                                        {
524
 
                                                                pos = category_report_id(split->kcat, (tmpsrc == REPORT_SRC_SUBCATEGORY) ? TRUE : FALSE);
525
 
                                                                trn_amount = hb_amount_base(split->amount, ope->kcur);
526
 
                                                                datatable_amount_add(dt, pos, trn_amount);
527
 
                                                        }
528
 
                                                }
529
 
                                        }
530
 
                                        else
531
 
                                        {
532
 
                                                pos = report_items_get_pos(tmpsrc, flt->mindate, ope);
533
 
                                                datatable_amount_add(dt, pos, trn_amount);
 
847
                                        dr->colexp[col] += amount;
 
848
                                        dr->rowexp += amount;
 
849
                                        if( addtotal == TRUE )
 
850
                                        {
 
851
                                                dt->totrow->colexp[col] += amount;
 
852
                                                dt->totrow->rowexp += amount;
534
853
                                        }
535
854
                                }
536
855
                                else
537
 
                                /* the TAG process is particular */
538
 
                                {
539
 
                                        if(ope->tags != NULL)
540
 
                                        {
541
 
                                        guint32 *tptr = ope->tags;
542
 
 
543
 
                                                while(*tptr)
544
 
                                                {
545
 
                                                        pos = *tptr - 1;
546
 
                                                        datatable_amount_add(dt, pos, trn_amount);
547
 
                                                        tptr++;
548
 
                                                }
549
 
                                        }
550
 
                                }
551
 
                        }
552
 
                        list = g_list_next(list);
553
 
                }
554
 
        }
555
 
        
556
 
        return dt;
557
 
}
558
 
 
559
 
 
560
 
static void datatable_trend_add(DataTable *dt, guint32 row, guint32 col, gdouble amount, gboolean addtotal)
561
 
{
562
 
        DB( g_print("   add to r%d,c%d %.2f\n", row, col, amount) );
563
 
 
564
 
        if( row <= (dt->nbrows) )
565
 
        {
566
 
        DataRow *dr = dt->rows[row];
567
 
 
568
 
                if( col <= dt->nbcols )
569
 
                {
570
 
                        if(amount > 0.0)
571
 
                        {
572
 
                                dr->income[col] += amount;
573
 
                                dr->income[dt->nbcols] += (amount/dt->nbcols);
574
 
                                dr->income[dt->nbcols+1] += amount;
575
 
                                //dt->totinc += amount;
576
 
                                if( addtotal == TRUE )
577
 
                                {
578
 
                                        dt->totrow->income[col] += amount;
579
 
                                        dt->totrow->income[dt->nbcols] += (amount/dt->nbcols);
580
 
                                        dt->totrow->income[dt->nbcols+1] += amount;
581
 
                                }
582
 
                        }
583
 
                        else
584
 
                        {
585
 
                                dr->expense[col] += amount;
586
 
                                dr->expense[dt->nbcols] += (amount/dt->nbcols);
587
 
                                dr->expense[dt->nbcols+1] += amount;
588
 
                                //dt->totexp += amount;
589
 
                                if( addtotal == TRUE )
590
 
                                {
591
 
                                        dt->totrow->expense[col] += amount;
592
 
                                        dt->totrow->expense[dt->nbcols] += (amount/dt->nbcols);
593
 
                                        dt->totrow->expense[dt->nbcols+1] += amount;
594
 
                                }
595
 
                        }
596
 
                }
597
 
        }
598
 
        else
599
 
                g_warning("invalid datatable index");
600
 
}
601
 
 
602
 
 
603
 
DataTable *report_compute_trend(gint tmpsrc, gint tmpintvl, Filter *flt, GQueue *txn_queue)
604
 
{
605
 
DataTable *dt;
606
 
GList *list;
607
 
guint i;
608
 
gint n_result, n_cols;
609
 
 
610
 
        DB( g_print("\n[report] compute_trend\n") );
611
 
        
612
 
        //todo: remove this later on
613
 
        n_result = report_items_count(tmpsrc, flt->mindate, flt->maxdate);
614
 
        n_cols   = report_interval_count(tmpintvl, flt->mindate, flt->maxdate);
615
 
 
616
 
        DB( g_print(" %d :: rows=%d cols=%d\n", tmpsrc, n_result, n_cols) );
617
 
        
618
 
        dt = da_datatable_malloc (0, n_result, n_cols);
619
 
        if( dt != NULL )
620
 
        {
621
 
                datatable_init_items(dt, tmpsrc, flt->mindate);
622
 
                
623
 
                list = g_queue_peek_head_link(txn_queue);
624
 
                while (list != NULL)
625
 
                {
626
 
                Transaction *ope = list->data;
627
 
                        
628
 
                        if( (filter_txn_match(flt, ope) == 1) )
629
 
                        {
630
 
                        guint32 pos = 0;
631
 
                        guint32 col = 0;
632
 
                        gdouble trn_amount;
633
 
 
634
 
                                DB( g_print("\n srctxn '%s' %.2f, cat=%d, pay=%d, acc=%d\n", ope->memo, ope->amount, ope->kcat, ope->kpay, ope->kacc) );
635
 
                                
636
 
                                trn_amount = report_txn_amount_get(flt, ope);
637
 
                                trn_amount = hb_amount_base(trn_amount, ope->kcur);
638
 
 
639
 
                                col = report_interval_get_pos(tmpintvl, flt->mindate, ope);
640
 
 
641
 
                                switch( tmpsrc )
642
 
                                {
643
 
                                        case REPORT_SRC_CATEGORY:
644
 
                                        case REPORT_SRC_SUBCATEGORY:
645
 
                                                //for split, affect the amount to the category
646
 
                                                if( ope->flags & OF_SPLIT )
647
 
                                                {
648
 
                                                guint nbsplit = da_splits_length(ope->splits);
649
 
                                                Split *split;
650
 
                                                gboolean status;
651
 
                                                gint sinsert;
652
 
 
653
 
                                                        for(i=0;i<nbsplit;i++)
654
 
                                                        {
655
 
                                                                split = da_splits_get(ope->splits, i);
656
 
                                                                status = da_flt_status_cat_get(flt, split->kcat);
657
 
                                                                sinsert = ( status == TRUE ) ? 1 : 0;
658
 
                                                                if(flt->option[FLT_GRP_CATEGORY] == 2) sinsert ^= 1;
659
 
                                                                if( (flt->option[FLT_GRP_CATEGORY] == 0) || sinsert)
660
 
                                                                {
661
 
                                                                        DB( g_print(" split insert=%d, kcat=%d\n", sinsert, split->kcat) );
662
 
                                                                        trn_amount = hb_amount_base(split->amount, ope->kcur);
663
 
                                                                        pos = category_report_id(split->kcat, (tmpsrc == REPORT_SRC_CATEGORY) ? FALSE : TRUE);
664
 
                                                                        datatable_trend_add(dt, pos, col, trn_amount, TRUE);
665
 
                                                                        //add to parent as well
666
 
                                                                        //#1955046 treeview with child was a test faulty released
667
 
                                                                        /*if( tmpsrc == REPORT_SRC_SUBCATEGORY )
668
 
                                                                        {
669
 
                                                                        //#1859279 test cat as subtype here to avoid count twice
670
 
                                                                        Category *cat = da_cat_get(split->kcat);
671
 
 
672
 
                                                                                if((cat != NULL) && (cat->flags & GF_SUB))
673
 
                                                                                {
674
 
                                                                                        pos = cat->parent;
675
 
                                                                                        datatable_trend_add(dt, pos, col, trn_amount, FALSE);
676
 
                                                                                }
677
 
                                                                        }*/
678
 
                                                                }
679
 
                                                        }
680
 
                                                }
681
 
                                                else
682
 
                                                {
683
 
                                                        pos = category_report_id(ope->kcat, (tmpsrc == REPORT_SRC_CATEGORY) ? FALSE : TRUE);
684
 
                                                        datatable_trend_add(dt, pos, col, trn_amount, TRUE);
685
 
                                                        //add to parent as well
686
 
                                                        //#1955046 treeview with child was a test faulty released
687
 
                                                        /*if( tmpsrc == REPORT_SRC_SUBCATEGORY )
688
 
                                                        {
689
 
                                                        //#1859279 test cat as subtype here to avoid count twice
690
 
                                                        Category *cat = da_cat_get(ope->kcat);
691
 
 
692
 
                                                                if((cat != NULL) && (cat->flags & GF_SUB))
693
 
                                                                {
694
 
                                                                        pos = cat->parent;
695
 
                                                                        datatable_trend_add(dt, pos, col, trn_amount, FALSE);
696
 
                                                                }
697
 
                                                        }*/
698
 
                                                }
699
 
                                                break;
700
 
 
701
 
                                        case REPORT_SRC_TAG:
702
 
                                                if(ope->tags != NULL)
703
 
                                                {
704
 
                                                guint32 *tptr = ope->tags;
705
 
 
706
 
                                                        while(*tptr)
707
 
                                                        {
708
 
                                                                pos = *tptr - 1;
709
 
                                                                datatable_trend_add(dt, pos, col, trn_amount, TRUE);
710
 
                                                                tptr++;
711
 
                                                        }
712
 
                                                }
713
 
                                                break;
714
 
 
715
 
                                        default:
716
 
                                                pos = report_items_get_pos(tmpsrc, flt->mindate, ope);
717
 
                                                datatable_trend_add(dt, pos, col, trn_amount, TRUE);
718
 
                                                break;
719
 
 
720
 
                                }
721
 
                        }
722
 
                        list = g_list_next(list);
723
 
                }
724
 
        }
725
 
 
726
 
        return dt;
727
 
}
728
 
 
729
 
 
730
 
DataTable *report_compute_trend_balance(gint tmpsrc, gint tmpintvl, Filter *flt)
731
 
{
732
 
DataTable *dt;
733
 
GList *lst_acc, *lnk_acc;
734
 
GList *lnk_txn;
735
 
gint n_result, n_cols;
736
 
guint row, col;
737
 
 
738
 
        DB( g_print("\n[report] compute_trend_balance\n") );
739
 
        
740
 
        //todo: remove this later on
741
 
        n_result = report_items_count(tmpsrc, flt->mindate, flt->maxdate);
742
 
        n_cols   = report_interval_count(tmpintvl, flt->mindate, flt->maxdate);
743
 
 
744
 
        DB( g_print(" %d :: n_result=%d\n", tmpsrc, n_result) );
745
 
        
746
 
        dt = da_datatable_malloc (0, n_result, n_cols);
747
 
        if( dt != NULL )
748
 
        {
749
 
                datatable_init_items(dt, tmpsrc, flt->mindate);
750
 
 
751
 
                // account initial amount
752
 
                lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
753
 
                lnk_acc = g_list_first(lst_acc);
754
 
                while (lnk_acc != NULL)
755
 
                {
756
 
                Account *acc = lnk_acc->data;
757
 
                guint32 pos = 0;
758
 
                guint32 col = 0;
759
 
                gdouble trn_amount;
760
 
 
761
 
                        //#1674045 ony rely on nosummary
762
 
                        if( (acc->flags & (AF_NOREPORT)) )
763
 
                                goto next_acc;
764
 
                                
765
 
                        //#2000294 enable account filtering
766
 
                        if( filter_acc_match(flt, acc) == 0 )
767
 
                                goto next_acc;
768
 
 
769
 
                        //add initial amount
770
 
                        trn_amount = hb_amount_base(acc->initial, acc->kcur);
771
 
                        //col = column
772
 
                        //pos = kacc
773
 
                        DB( g_print("  ** add initbal %8.2f to row:%d, col:%d\n", trn_amount, acc->key, 0) );
774
 
                        datatable_trend_add(dt, acc->key, 0, trn_amount, TRUE);
775
 
 
776
 
                        lnk_txn = g_queue_peek_head_link(acc->txn_queue);
777
 
                        while (lnk_txn != NULL)
778
 
                        {
779
 
                        Transaction *txn = lnk_txn->data;
780
 
                        
781
 
                                //5.5 forgot to filter...
782
 
                                //#1886123 include remind based on user prefs
783
 
                                if( (txn->status == TXN_STATUS_REMIND) && (PREFS->includeremind == FALSE) )
784
 
                                        goto next_txn;
785
 
                                        
786
 
                                if( !( txn->status == TXN_STATUS_VOID ) )
787
 
                                //TODO: enable filters : make no sense no ?
788
 
                                //if( (filter_txn_match(flt, txn) == 1) )
789
 
                                {
790
 
                                        pos = report_items_get_pos(tmpsrc, flt->mindate, txn);
791
 
 
792
 
                                        trn_amount = report_txn_amount_get(flt, txn);
793
 
                                        trn_amount = hb_amount_base(trn_amount, txn->kcur);
794
 
 
795
 
                                        DB( g_print("srctxn: %d - cat=%d, pay=%d, acc=%d | [%d - %d]\n", txn->date, txn->kcat, txn->kpay, txn->kacc, flt->mindate, flt->maxdate) );
796
 
 
797
 
                                        //if( (filter_txn_match(flt, txn) == 1) )
798
 
                                        if( (txn->date >= flt->mindate) && (txn->date <= flt->maxdate) )
799
 
                                        {
800
 
                                                col = report_interval_get_pos(tmpintvl, flt->mindate, txn);
801
 
                                                DB( g_print("  add %8.2f row:%d, col:%d\n", trn_amount, pos, col) );
802
 
                                                datatable_trend_add(dt, pos, col, trn_amount, TRUE);
803
 
                                        }
804
 
                                        else
805
 
                                        if( txn->date < flt->mindate)
806
 
                                        {
807
 
                                                DB( g_print("  **add %8.2f row:%d, col:%d\n", trn_amount, pos, 0) );
808
 
                                                datatable_trend_add(dt, pos, 0, trn_amount, TRUE);
809
 
                                        }
810
 
                                }
811
 
                        next_txn:
812
 
                                lnk_txn = g_list_next(lnk_txn);
813
 
                        }
814
 
 
815
 
                next_acc:
816
 
                        lnk_acc = g_list_next(lnk_acc);
817
 
                }
818
 
                g_list_free(lst_acc);
819
 
 
820
 
        }
821
 
        
 
856
                                {
 
857
                                        dr->colinc[col] += amount;
 
858
                                        dr->rowinc += amount;
 
859
                                        if( addtotal == TRUE )
 
860
                                        {
 
861
                                                dt->totrow->colinc[col] += amount;
 
862
                                                dt->totrow->rowinc += amount;
 
863
                                        }
 
864
                                }
 
865
                        }
 
866
                }
 
867
                else
 
868
                        g_warning("datatable add invalid col %d of %d", col, dt->nbcols);
 
869
        }
 
870
}
 
871
 
 
872
 
 
873
static void datatable_data_cols_cumulate(DataTable *dt, gint intvl, Filter *flt)
 
874
{
 
875
 
 
876
 
 
877
        DB2( g_print("\n-- cumulate columns --\n") );
 
878
        DB2( g_print(" n_row=%d n_col=%d\n", dt->nbrows, dt->nbcols) );
822
879
        //cumulate columns
823
880
        if( dt->nbcols > 1 )
824
881
        {
 
882
        guint row, col;
 
883
 
825
884
                for(row=0;row<dt->nbrows;row++)
826
885
                {
827
886
                DataRow *dr = dt->rows[row];
828
 
 
829
 
                        //#2012576 nbcols-2 to not scratch avg and total columns
830
 
                        for(col=1;col<dt->nbcols-2;col++)
831
 
                        {
832
 
                                dr->income[col]  += dr->income[col-1];
833
 
                                dr->expense[col] += dr->expense[col-1];         
834
 
                        
835
 
                                dt->totrow->income[col] += dr->income[col-1];
836
 
                                dt->totrow->expense[col] += dr->expense[col-1];
837
 
                        }
838
 
                }
 
887
                        
 
888
                        DB2( g_print(" row %d: ", row) );
 
889
                        for(col=1;col<dr->nbcols;col++)
 
890
                        {
 
891
                        guint32 jdate = _datatable_interval_get_jdate(intvl, flt->mindate, col);
 
892
                        
 
893
                                if( jdate < dt->maxpostdate)
 
894
                                {
 
895
                                        DB2( g_print("%d, ", col) );
 
896
                                        dr->colinc[col] += dr->colinc[col-1];
 
897
                                        dr->colexp[col] += dr->colexp[col-1];           
 
898
 
 
899
                                        dt->totrow->colinc[col] += dr->colinc[col-1];
 
900
                                        dt->totrow->colexp[col] += dr->colexp[col-1];
 
901
                                }
 
902
                        }
 
903
                        DB2( g_print("\n") );
 
904
                }
 
905
        }
 
906
}
 
907
 
 
908
 
 
909
static void datatable_data_add_balance(DataTable *dt, gint src, gint intvl, Filter *flt)
 
910
{
 
911
GList *lst_acc, *lnk_acc;
 
912
GList *lnk_txn;
 
913
 
 
914
        if( src != REPORT_SRC_ACCOUNT && src != REPORT_SRC_NONE )
 
915
                return;
 
916
 
 
917
        DB1( g_print(" -- add balance\n") );
 
918
 
 
919
        //TODO: we should rely on rows...
 
920
        lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
 
921
        lnk_acc = g_list_first(lst_acc);
 
922
        while (lnk_acc != NULL)
 
923
        {
 
924
        Account *acc = lnk_acc->data;
 
925
        guint32 pos = 0;
 
926
        gdouble trn_amount;
 
927
 
 
928
                //#1674045 ony rely on nosummary
 
929
                if( (acc->flags & (AF_NOREPORT)) )
 
930
                        goto next_acc;
 
931
                        
 
932
                //#2000294 enable account filtering
 
933
                if( filter_acc_match(flt, acc) == 0 )
 
934
                        goto next_acc;
 
935
 
 
936
                //add initial amount to col[0]
 
937
                trn_amount = hb_amount_base(acc->initial, acc->kcur);
 
938
                //for none, we only allocate the row[0]
 
939
                datatable_add(dt, (src == REPORT_SRC_NONE) ? 0 : acc->key, 0, trn_amount, TRUE);
 
940
                DB2( g_print("  ** add initbal %8.2f to row:%d, col:%d\n", trn_amount, acc->key, 0) );
 
941
 
 
942
                //add txn amount prior mindate to col[0]
 
943
                lnk_txn = g_queue_peek_head_link(acc->txn_queue);
 
944
                while (lnk_txn != NULL)
 
945
                {
 
946
                Transaction *txn = lnk_txn->data;
 
947
                
 
948
                        //5.5 forgot to filter...
 
949
                        //#1886123 include remind based on user prefs
 
950
                        if( (txn->status == TXN_STATUS_REMIND) && (PREFS->includeremind == FALSE) )
 
951
                                goto next_txn;
 
952
                                
 
953
                        if( !( txn->status == TXN_STATUS_VOID ) )
 
954
                        //enable filters : make no sense or not
 
955
                        //if( (filter_txn_match(flt, txn) == 1) )
 
956
                        {
 
957
                                pos = report_items_get_key(src, flt->mindate, txn);
 
958
 
 
959
                                trn_amount = report_txn_amount_get(flt, txn);
 
960
                                trn_amount = hb_amount_base(trn_amount, txn->kcur);
 
961
 
 
962
                                if( txn->date < flt->mindate )
 
963
                                {
 
964
                                        //DB2( g_print("  **add %8.2f row:%d, col:%d\n", trn_amount, pos, 0) );
 
965
                                        datatable_add(dt, pos, 0, trn_amount, TRUE);
 
966
                                }
 
967
                        }
 
968
                next_txn:
 
969
                        lnk_txn = g_list_next(lnk_txn);
 
970
                }
 
971
 
 
972
        next_acc:
 
973
                lnk_acc = g_list_next(lnk_acc);
 
974
        }
 
975
        g_list_free(lst_acc);
 
976
 
 
977
}
 
978
 
 
979
 
 
980
static void datatable_data_add_txn(DataTable *dt, gint src, gint intvl, Transaction *txn, Filter *flt)
 
981
{
 
982
guint i;
 
983
guint key = 0;
 
984
guint col = 0;
 
985
gdouble trn_amount;
 
986
 
 
987
        //DB2( g_print("\n srctxn '%s' %.2f, cat=%d, pay=%d, acc=%d\n", txn->memo, txn->amount, txn->kcat, txn->kpay, txn->kacc) );
 
988
        
 
989
        trn_amount = report_txn_amount_get(flt, txn);
 
990
        trn_amount = hb_amount_base(trn_amount, txn->kcur);
 
991
 
 
992
        col = report_interval_get_pos(intvl, flt->mindate, txn);
 
993
 
 
994
        switch( src )
 
995
        {
 
996
                case REPORT_SRC_CATEGORY:
 
997
                //case REPORT_SRC_SUBCATEGORY:
 
998
                        //for split, affect the amount to the category
 
999
                        if( txn->flags & OF_SPLIT )
 
1000
                        {
 
1001
                        guint nbsplit = da_splits_length(txn->splits);
 
1002
                        Split *split;
 
1003
                        gboolean status;
 
1004
                        gint sinsert;
 
1005
 
 
1006
                                for(i=0;i<nbsplit;i++)
 
1007
                                {
 
1008
                                        split = da_splits_get(txn->splits, i);
 
1009
                                        status = da_flt_status_cat_get(flt, split->kcat);
 
1010
                                        sinsert = ( status == TRUE ) ? 1 : 0;
 
1011
                                        if(flt->option[FLT_GRP_CATEGORY] == 2) sinsert ^= 1;
 
1012
                                        if( (flt->option[FLT_GRP_CATEGORY] == 0) || sinsert)
 
1013
                                        {
 
1014
                                        Category *cat = da_cat_get(split->kcat);
 
1015
 
 
1016
                                                //DB2( g_print(" split insert=%d, kcat=%d\n", sinsert, split->kcat) );
 
1017
                                                trn_amount = hb_amount_base(split->amount, txn->kcur);
 
1018
                                                //pos = category_report_id(split->kcat, (src == REPORT_SRC_CATEGORY) ? FALSE : TRUE);
 
1019
                                                //datatable_add(dt, pos, col, trn_amount, TRUE);
 
1020
 
 
1021
                                                if( cat != NULL )
 
1022
                                                {
 
1023
                                                        datatable_add(dt, cat->key, col, trn_amount, TRUE);
 
1024
                                                        if( cat->parent != 0 )
 
1025
                                                                datatable_add(dt, cat->parent, col, trn_amount, FALSE);
 
1026
                                                }       
 
1027
                                        }
 
1028
                                }
 
1029
                        }
 
1030
                        else
 
1031
                        {
 
1032
                        Category *cat = da_cat_get(txn->kcat);
 
1033
 
 
1034
                                //pos = category_report_id(txn->kcat, (src == REPORT_SRC_CATEGORY) ? FALSE : TRUE);
 
1035
                                //datatable_add(dt, pos, col, trn_amount, TRUE);
 
1036
                                if( cat != NULL )
 
1037
                                {
 
1038
                                        datatable_add(dt, cat->key, col, trn_amount, TRUE);
 
1039
                                        if( cat->parent != 0 )
 
1040
                                                datatable_add(dt, cat->parent, col, trn_amount, FALSE);
 
1041
                                }
 
1042
                        }
 
1043
                        break;
 
1044
 
 
1045
                case REPORT_SRC_TAG:
 
1046
                        if(txn->tags != NULL)
 
1047
                        {
 
1048
                        guint32 *tptr = txn->tags;
 
1049
 
 
1050
                                while(*tptr)
 
1051
                                {
 
1052
                                        //#2031693 not -1 here
 
1053
                                        key = *tptr;
 
1054
                                        datatable_add(dt, key, col, trn_amount, TRUE);
 
1055
                                        tptr++;
 
1056
                                }
 
1057
                        }
 
1058
                        //2031693 + add notags
 
1059
                        else
 
1060
                                datatable_add(dt, 0, col, trn_amount, TRUE);
 
1061
                        break;
 
1062
 
 
1063
                default:
 
1064
                        key = report_items_get_key(src, flt->mindate, txn);
 
1065
                        datatable_add(dt, key, col, trn_amount, TRUE);
 
1066
                        break;
 
1067
 
 
1068
        }
 
1069
 
 
1070
 
 
1071
}
 
1072
 
 
1073
 
 
1074
//5.7 forecast attempt
 
1075
static void report_compute_forecast(DataTable *dt, gint src, gint intvl, Filter *flt)
 
1076
{
 
1077
GList *list;
 
1078
gint nbinsert;
 
1079
guint32 curdate, maxpostdate;
 
1080
GDate *post_date;
 
1081
 
 
1082
        DB1( g_print("\n[report] compute_forecast\n") );
 
1083
 
 
1084
        if( intvl == REPORT_INTVL_NONE )
 
1085
        {
 
1086
                DB1( g_print(" no forecast for total mode\n") );
 
1087
                return;
 
1088
        }
 
1089
 
 
1090
        post_date = g_date_new();
 
1091
 
 
1092
        //TODO: change this
 
1093
        maxpostdate = dt->maxpostdate;
 
1094
        
 
1095
 
 
1096
        list = g_list_first(GLOBALS->arc_list);
 
1097
        while (list != NULL)
 
1098
        {
 
1099
        Archive *arc = list->data;
 
1100
 
 
1101
                DB2( g_print("--------\n eval post of '%s' %.2f\n", arc->memo, arc->amount) );
 
1102
 
 
1103
                if(scheduled_is_postable(arc) == TRUE)
 
1104
                {
 
1105
                Account *acc;
 
1106
                Transaction *txn;
 
1107
 
 
1108
                        DB2( g_print(" is postable\n") );
 
1109
 
 
1110
                        nbinsert = 0;
 
1111
                        txn = da_transaction_malloc();
 
1112
                        da_transaction_init_from_template(txn, arc);
 
1113
                        
 
1114
                        acc = da_acc_get(txn->kacc);
 
1115
                        if(acc)
 
1116
                                txn->kcur = acc->kcur;
 
1117
 
 
1118
                        txn->date = curdate = arc->nextdate;
 
1119
 
 
1120
                        if( (filter_txn_match(flt, txn) == 1) )
 
1121
                        {
 
1122
                                while(curdate <= maxpostdate)
 
1123
                                {
 
1124
                                        txn->date = curdate; 
 
1125
                                        DB3( hb_print_date(curdate, "curdate=") );
 
1126
 
 
1127
                                        datatable_data_add_txn(dt, src, intvl, txn, flt);
 
1128
 
 
1129
                                        //mark column as forecast
 
1130
                                        guint idx = report_interval_get_pos(intvl, flt->mindate, txn);
 
1131
                                        DataCol *dc = report_data_get_col(dt, idx);
 
1132
                                        if( dc != NULL )
 
1133
                                                dc->flags |= RF_FORECAST;
 
1134
 
 
1135
                                        curdate = scheduled_date_get_next_post(post_date, arc, curdate);
 
1136
                                        nbinsert++;
 
1137
                                        // break if over limit
 
1138
                                        if( (arc->flags & OF_LIMIT) && (nbinsert >= arc->limit) )
 
1139
                                                break;
 
1140
                                }
 
1141
                        }
 
1142
 
 
1143
                        da_transaction_free (txn);
 
1144
                }
 
1145
                list = g_list_next(list);
 
1146
        }
 
1147
 
 
1148
        g_date_free(post_date);
 
1149
 
 
1150
}
 
1151
 
 
1152
/* = = = = = = = = = = = = = = = = = = = = */
 
1153
 
 
1154
 
 
1155
DataTable *report_compute(gint src, gint intvl, Filter *flt, GQueue *txn_queue, gboolean do_forecast, gboolean do_balance)
 
1156
{
 
1157
DataTable *dt;
 
1158
GList *list;
 
1159
guint32 maxpostdate = flt->maxdate;
 
1160
 
 
1161
        DB1( g_print("\n[report] == report_compute ==\n") );
 
1162
 
 
1163
        DB2( hb_print_date(maxpostdate, "maxdate") );
 
1164
 
 
1165
        //set maxpostdate
 
1166
        /*if( do_forecast )
 
1167
        {
 
1168
                if( filter_preset_daterange_future_enable(flt, flt->range) )
 
1169
                {
 
1170
                GDate *post_date = g_date_new();
 
1171
 
 
1172
                        g_date_set_time_t(post_date, time(NULL));
 
1173
                        g_date_add_months(post_date, PREFS->rep_forecat_nbmonth);
 
1174
                        g_date_set_day(post_date, g_date_get_days_in_month(g_date_get_month(post_date), g_date_get_year(post_date)));
 
1175
                        maxpostdate = g_date_get_julian(post_date);
 
1176
                        DB2( hb_print_date(maxpostdate, "max forecast date") );
 
1177
 
 
1178
                        g_date_free(post_date);
 
1179
 
 
1180
                        flt->maxdate = maxpostdate;
 
1181
                }
 
1182
        }*/
 
1183
 
 
1184
        dt = da_datatable_malloc(src, intvl, flt);
 
1185
 
 
1186
        if( dt == NULL )
 
1187
                return dt;
 
1188
 
 
1189
        dt->maxpostdate = maxpostdate;
 
1190
 
 
1191
        datatable_init_items(dt, src, flt->mindate);
 
1192
        datatable_init_columns(dt, intvl, flt->mindate);
 
1193
 
 
1194
        //balance must keep xfer
 
1195
        /*if( do_balance == TRUE )
 
1196
        {
 
1197
                
 
1198
        
 
1199
        }*/
 
1200
 
 
1201
        //process txn
 
1202
        list = g_queue_peek_head_link(txn_queue);
 
1203
        while (list != NULL)
 
1204
        {
 
1205
        Transaction *txn = list->data;
 
1206
                
 
1207
                if( (filter_txn_match(flt, txn) == 1) )
 
1208
                {
 
1209
                        datatable_data_add_txn(dt, src, intvl, txn, flt);
 
1210
                }
 
1211
                list = g_list_next(list);
 
1212
        }
 
1213
 
 
1214
        //TODO: add prefs
 
1215
        //if( PREFS->xxx )
 
1216
        if( do_forecast == TRUE )
 
1217
        {
 
1218
                //DB2( g_print("\n-- compute forecast --\n") );
 
1219
                report_compute_forecast(dt, src, intvl, flt);
 
1220
        }
 
1221
 
 
1222
        //process balance mode
 
1223
        if( do_balance == TRUE )
 
1224
        {
 
1225
                datatable_data_add_balance(dt, src, intvl, flt);
 
1226
                datatable_data_cols_cumulate(dt, intvl, flt);
839
1227
        }
840
1228
 
841
1229
        return dt;
842
1230
}
843
1231
 
844
1232
 
845
 
gint report_items_count(gint src, guint32 jfrom, guint32 jto)
846
 
{
847
 
GDate *date1, *date2;
848
 
gint nbsrc = 0;
 
1233
DataCol *report_data_get_col(DataTable *dt, guint32 idx)
 
1234
{
 
1235
DataCol *retval = NULL;
 
1236
 
 
1237
        if( idx <= dt->nbcols )
 
1238
        {
 
1239
                retval = dt->cols[idx];
 
1240
        }
 
1241
        else
 
1242
                g_warning("datatable invalid get col %d of %d", idx, dt->nbcols);
 
1243
 
 
1244
        return retval;
 
1245
}
 
1246
 
 
1247
 
 
1248
//get a specific row by key
 
1249
//hub-reptime/hub-reptotal/repstats
 
1250
DataRow *report_data_get_row(DataTable *dt, guint32 key)
 
1251
{
 
1252
DataRow *retval = NULL;
 
1253
guint32 idx;
 
1254
 
 
1255
        if( key <= dt->nbkeys )
 
1256
        {
 
1257
                //we should transpose here
 
1258
                idx = dt->keyindex[key];
 
1259
                if( idx <= dt->nbrows )
 
1260
                {
 
1261
                        DB1( g_print(" get row=%d for key=%d\n", idx, key) ); 
 
1262
                        retval = dt->rows[idx];
 
1263
                }
 
1264
                else
 
1265
                        g_warning("datatable invalid get row %d of %d", idx, dt->nbrows);
 
1266
        }
 
1267
        else
 
1268
                g_warning("datatable invalid get row key %d of %d", key, dt->nbkeys);
 
1269
 
 
1270
        return retval;
 
1271
}
 
1272
 
 
1273
 
 
1274
//gtk-chart/list-report
 
1275
gdouble da_datarow_get_cell_sum(DataRow *dr, guint32 index)
 
1276
{
 
1277
        if( index <= dr->nbcols )
 
1278
        {
 
1279
                return (dr->colexp[index] + dr->colinc[index]);
 
1280
        }
 
1281
 
 
1282
        g_warning("invalid datarow column");
 
1283
        return 0;
 
1284
}
 
1285
 
 
1286
 
 
1287
//rep-stat
 
1288
guint report_items_get_key(gint src, guint jfrom, Transaction *txn)
 
1289
{
 
1290
guint key = 0;
849
1291
 
850
1292
        switch(src)
851
1293
        {
852
 
                case REPORT_SRC_CATEGORY:
853
 
                case REPORT_SRC_SUBCATEGORY:
854
 
                        nbsrc = da_cat_get_max_key() + 1;
855
 
                        break;
856
 
                case REPORT_SRC_PAYEE:
857
 
                        nbsrc = da_pay_get_max_key() + 1;
858
 
                        break;
859
 
                case REPORT_SRC_ACCOUNT:
860
 
                        nbsrc = da_acc_get_max_key() + 1;
861
 
                        break;
862
 
                case REPORT_SRC_TAG:
863
 
                        nbsrc = da_tag_length();
864
 
                        break;
865
 
                case REPORT_SRC_MONTH:
866
 
                        date1 = g_date_new_julian(jfrom);
867
 
                        date2 = g_date_new_julian(jto);
868
 
                        nbsrc = ((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1) + 1;
869
 
                        g_date_free(date2);
870
 
                        g_date_free(date1);
871
 
                        break;
872
 
                case REPORT_SRC_YEAR:
873
 
                        date1 = g_date_new_julian(jfrom);
874
 
                        date2 = g_date_new_julian(jto);
875
 
                        nbsrc = g_date_get_year(date2) - g_date_get_year(date1) + 1;
876
 
                        g_date_free(date2);
877
 
                        g_date_free(date1);
878
 
                        break;
879
 
        }
880
 
 
881
 
        return nbsrc;
882
 
}
883
 
 
884
 
 
885
 
 
886
 
gint report_items_get_pos(gint tmpsrc, guint jfrom, Transaction *ope)
887
 
{
888
 
gint pos = 0;
889
 
 
890
 
        switch(tmpsrc)
891
 
        {
892
 
                case REPORT_SRC_CATEGORY:
893
 
                        pos = category_report_id(ope->kcat, FALSE);
894
 
                        break;
895
 
                case REPORT_SRC_SUBCATEGORY:
896
 
                        pos = ope->kcat;
897
 
                        break;
898
 
                case REPORT_SRC_PAYEE:
899
 
                        pos = ope->kpay;
900
 
                        break;
901
 
                case REPORT_SRC_ACCOUNT:
902
 
                        pos = ope->kacc;
903
 
                        break;
904
 
                case REPORT_SRC_MONTH:
905
 
                        pos = DateInMonth(jfrom, ope->date);
906
 
                        break;
907
 
                case REPORT_SRC_YEAR:
908
 
                        pos = DateInYear(jfrom, ope->date);
909
 
                        break;
910
 
        }
911
 
        return pos;
912
 
}
913
 
 
914
 
 
915
 
 
916
 
gint report_interval_get_pos(gint intvl, guint jfrom, Transaction *ope)
 
1294
                case REPORT_SRC_NONE:
 
1295
                        key = 0;
 
1296
                        break;
 
1297
                case REPORT_SRC_CATEGORY:
 
1298
                        key = category_report_id(txn->kcat, FALSE);
 
1299
                        break;
 
1300
                //case REPORT_SRC_SUBCATEGORY:
 
1301
                //      pos = txn->kcat;
 
1302
                //      break;
 
1303
                case REPORT_SRC_PAYEE:
 
1304
                        key = txn->kpay;
 
1305
                        break;
 
1306
                case REPORT_SRC_ACCOUNT:
 
1307
                        key = txn->kacc;
 
1308
                        break;
 
1309
                //TODO! miss TAG
 
1310
                        
 
1311
                case REPORT_SRC_MONTH:
 
1312
                        key = DateInMonth(jfrom, txn->date);
 
1313
                        break;
 
1314
                case REPORT_SRC_YEAR:
 
1315
                        key = DateInYear(jfrom, txn->date);
 
1316
                        break;
 
1317
        }
 
1318
        
 
1319
        return key;
 
1320
}
 
1321
 
 
1322
 
 
1323
//rep- balance/budget/time
 
1324
gint report_interval_get_pos(gint intvl, guint jfrom, Transaction *txn)
917
1325
{
918
1326
gint pos = 0;
919
1327
 
920
1328
        switch(intvl)
921
1329
        {
922
1330
                case REPORT_INTVL_DAY:
923
 
                        pos = ope->date - jfrom;
 
1331
                        pos = txn->date - jfrom;
924
1332
                        break;
925
1333
                case REPORT_INTVL_WEEK:
926
1334
                        //#1915643 week iso 8601
927
 
                        //pos = (ope->date - jfrom)/7;
928
 
                        pos = DateInWeek(jfrom, ope->date);
 
1335
                        //pos = (txn->date - jfrom)/7;
 
1336
                        pos = DateInWeek(jfrom, txn->date);
929
1337
                        break;
930
1338
                //#2000290
931
1339
                case REPORT_INTVL_FORTNIGHT:
932
 
                        pos = DateInFortNight(jfrom, ope->date);
 
1340
                        pos = DateInFortNight(jfrom, txn->date);
933
1341
                        break;
934
1342
                case REPORT_INTVL_MONTH:
935
 
                        pos = DateInMonth(jfrom, ope->date);
 
1343
                        pos = DateInMonth(jfrom, txn->date);
936
1344
                        break;
937
1345
                case REPORT_INTVL_QUARTER:
938
 
                        pos = DateInQuarter(jfrom, ope->date);
 
1346
                        pos = DateInQuarter(jfrom, txn->date);
939
1347
                        break;
940
1348
                case REPORT_INTVL_HALFYEAR:
941
 
                        pos = DateInHalfYear(jfrom, ope->date);
 
1349
                        pos = DateInHalfYear(jfrom, txn->date);
942
1350
                        break;
943
1351
                case REPORT_INTVL_YEAR:
944
 
                        pos = DateInYear(jfrom, ope->date);
 
1352
                        pos = DateInYear(jfrom, txn->date);
 
1353
                        break;
 
1354
                default: //REPORT_INTVL_NONE
 
1355
                        pos = 0;
945
1356
                        break;
946
1357
        }
947
1358
        
949
1360
}
950
1361
 
951
1362
 
952
 
 
 
1363
//rep-stats
 
1364
//rep- balance/time
953
1365
gint report_interval_count(gint intvl, guint32 jfrom, guint32 jto)
954
1366
{
955
1367
GDate *date1, *date2;
965
1377
                        break;
966
1378
                case REPORT_INTVL_WEEK:
967
1379
                        //#2000292 weeknum iso 8601 as well
968
 
                        hb_date_clamp_iso8601(date1);
 
1380
                        _hb_date_clamp_iso8601(date1);
969
1381
                        nbintvl = 1 + (g_date_days_between(date1, date2) / 7);
970
1382
                        break;
971
1383
                //#2000290
972
1384
                case REPORT_INTVL_FORTNIGHT:
973
 
                        hb_date_clamp_iso8601(date1);
 
1385
                        _hb_date_clamp_iso8601(date1);
974
1386
                        nbintvl = 1 + (g_date_days_between(date1, date2) / 14);         
975
1387
                        break;
976
1388
                case REPORT_INTVL_MONTH:
985
1397
                case REPORT_INTVL_YEAR:
986
1398
                        nbintvl = 1 + g_date_get_year(date2) - g_date_get_year(date1);
987
1399
                        break;
 
1400
                default: //REPORT_INTVL_NONE
 
1401
                        nbintvl = 1;
 
1402
                        break;
988
1403
        }
989
1404
 
990
1405
        g_date_free(date2);
994
1409
}
995
1410
 
996
1411
 
997
 
void report_interval_snprint_name(gchar *s, gint slen, gint intvl, guint32 jfrom, gint idx)
 
1412
 
 
1413
 
 
1414
//used in list-report / rep- balance/budget/time 
 
1415
guint32 report_interval_snprint_name(gchar *s, gint slen, gint intvl, guint32 jfrom, gint idx)
998
1416
{
999
 
GDate *date = g_date_new_julian(jfrom);
1000
 
GDateWeekday wday;
 
1417
GDate *date;
 
1418
guint32 jdate = _datatable_interval_get_jdate(intvl, jfrom, idx);
1001
1419
 
 
1420
        date = g_date_new_julian(jdate);
1002
1421
        switch(intvl)
1003
1422
        {
1004
1423
                case REPORT_INTVL_DAY:
1005
 
                        g_date_add_days(date, idx);
1006
1424
                        g_date_strftime (s, slen, PREFS->date_format, date);
1007
1425
                        break;
1008
 
 
1009
1426
                case REPORT_INTVL_WEEK:
1010
 
                        g_date_add_days(date, idx*7);
1011
 
 
1012
 
                        //#1915643 week iso 8601
1013
 
                        //ISO 8601 from must be monday, to slice in correct week
1014
 
                        wday = g_date_get_weekday(date);
1015
 
                        g_date_subtract_days (date, wday-G_DATE_MONDAY);
1016
 
                        g_date_add_days (date, G_DATE_WEDNESDAY);
1017
 
 
1018
 
                        //g_snprintf(s, slen, _("%d-w%d"), g_date_get_year(date), g_date_get_monday_week_of_year(date));
1019
1427
                        //TRANSLATORS: printf string for year of week W, ex. 2019-W52 for week 52 of 2019
1020
1428
                        g_snprintf(s, slen, _("%d-w%02d"), g_date_get_year(date), g_date_get_iso8601_week_of_year(date));
1021
1429
                        break;
1022
 
 
1023
1430
                //#2000290
1024
1431
                case REPORT_INTVL_FORTNIGHT:
1025
 
                        hb_date_clamp_iso8601(date);
1026
 
                        g_date_add_days(date, idx*14);
1027
1432
                        g_date_strftime (s, slen, PREFS->date_format, date);
1028
1433
                        break;
1029
 
 
1030
1434
                case REPORT_INTVL_MONTH:
1031
 
                        g_date_add_months(date, idx);
1032
 
                        //g_snprintf(buffer, 63, "%d-%02d", g_date_get_year(date), g_date_get_month(date));
1033
1435
                        g_snprintf(s, slen, "%d-%s", g_date_get_year(date), _(CYA_ABMONTHS[g_date_get_month(date)]));
1034
1436
                        break;
1035
 
 
1036
1437
                case REPORT_INTVL_QUARTER:
1037
 
                        g_date_add_months(date, idx*3);
1038
 
                        //g_snprintf(buffer, 63, "%d-%02d", g_date_get_year(date), g_date_get_month(date));
1039
1438
                        //todo: will be innacurrate here if fiscal year start not 1/jan
1040
1439
                        //TRANSLATORS: printf string for year of quarter Q, ex. 2019-Q4 for quarter 4 of 2019
1041
1440
                        g_snprintf(s, slen, _("%d-q%d"), g_date_get_year(date), ((g_date_get_month(date)-1)/3)+1);
1042
1441
                        break;
1043
 
 
1044
1442
                case REPORT_INTVL_HALFYEAR:
1045
 
                        g_date_add_months(date, idx*6);
1046
1443
                        //#2007712
1047
1444
                        //TRANSLATORS: printf string for half-year H, ex. 2019-H1 for 1st half-year of 2019
1048
1445
                        g_snprintf(s, slen, _("%d-h%d"), g_date_get_year(date), g_date_get_month(date) < 7 ? 1 : 2);
1049
1446
                        break;
1050
 
 
1051
1447
                case REPORT_INTVL_YEAR:
1052
 
                        g_date_add_years(date, idx);
1053
1448
                        g_snprintf(s, slen, "%d", g_date_get_year(date));
1054
1449
                        break;
1055
1450
                default:
1058
1453
        }
1059
1454
 
1060
1455
        g_date_free(date);
1061
 
}
1062
 
 
1063
 
 
1064
 
gdouble report_acc_initbalance_get(Filter *flt)
1065
 
{
1066
 
GList *lst_acc, *lnk_acc;
1067
 
gdouble initbal = 0.0;
1068
 
        
1069
 
        lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
1070
 
        lnk_acc = g_list_first(lst_acc);
1071
 
        while (lnk_acc != NULL)
1072
 
        {
1073
 
        Account *acc = lnk_acc->data;
1074
 
 
1075
 
                //later, filter on acc
1076
 
                if( !(acc->flags & AF_NOREPORT) )
1077
 
                        initbal += hb_amount_base(acc->initial, acc->kcur);
1078
 
 
1079
 
                lnk_acc = g_list_next(lnk_acc);
1080
 
        }
1081
 
        g_list_free(lst_acc);
1082
 
        return initbal;
1083
 
}
 
1456
 
 
1457
        return jdate;
 
1458
}
 
1459
 
1084
1460
 
1085
1461
 
1086
1462
//TODO: maybe migrate this to filter as well
1087
1463
//#1562372 in case of a split we need to take amount for filter categories only
 
1464
//used in rep-time
1088
1465
gdouble report_txn_amount_get(Filter *flt, Transaction *txn)
1089
1466
{
1090
1467
gdouble amount;
1109
1486
                                sinsert = ( status == TRUE ) ? 1 : 0;
1110
1487
                                if(flt->option[FLT_GRP_CATEGORY] == 2) sinsert ^= 1;
1111
1488
 
1112
 
                                DB( g_print(" split insert=%d, kcat=%d\n", sinsert, split->kcat) );
 
1489
                                DB2( g_print(" split insert=%d, kcat=%d\n", sinsert, split->kcat) );
1113
1490
 
1114
1491
                                if( (flt->option[FLT_GRP_CATEGORY] == 0) || sinsert)
1115
1492
                                {