]> Dogcows Code - chaz/homebank/blob - src/hb-report.c
Merge branch 'upstream'
[chaz/homebank] / src / hb-report.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
20 #include "homebank.h"
21 #include "hb-report.h"
22
23 /****************************************************************************/
24 /* Debug macros */
25 /****************************************************************************/
26 #define MYDEBUG 0
27
28 #if MYDEBUG
29 #define DB(x) (x);
30 #else
31 #define DB(x);
32 #endif
33
34 /* our global datas */
35 extern struct HomeBank *GLOBALS;
36 extern struct Preferences *PREFS;
37
38
39 extern gchar *CYA_ABMONTHS[];
40
41 /* = = = = = = = = = = = = = = = = = = = = */
42 /* CarCost */
43
44 void da_vehiclecost_free(CarCost *item)
45 {
46 if(item != NULL)
47 {
48 g_free(item);
49 }
50 }
51
52
53 CarCost *da_vehiclecost_malloc(void)
54 {
55 return g_malloc0(sizeof(CarCost));
56 }
57
58 void da_vehiclecost_destroy(GList *list)
59 {
60 GList *tmplist = g_list_first(list);
61
62 while (tmplist != NULL)
63 {
64 CarCost *item = tmplist->data;
65 da_vehiclecost_free(item);
66 tmplist = g_list_next(tmplist);
67 }
68 g_list_free(list);
69 }
70
71
72 /* = = = = = = = = = = = = = = = = = = = = */
73
74
75 /*
76 ** return the month list position correponding to the passed date
77 */
78 static guint DateInMonth(guint32 from, guint32 opedate)
79 {
80 GDate *date1, *date2;
81 guint pos;
82
83 //todo
84 // this return sometimes -1, -2 which is wrong
85
86 date1 = g_date_new_julian(from);
87 date2 = g_date_new_julian(opedate);
88
89 pos = ((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1);
90
91 //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);
92
93 g_date_free(date2);
94 g_date_free(date1);
95
96 return(pos);
97 }
98
99
100
101 //for fiscal sub gap between 1st fiscal and 1/1/year
102
103 //int quarterNumber = (date.Month-1)/3+1;
104 //DateTime firstDayOfQuarter = new DateTime(date.Year, (quarterNumber-1)*3+1,1);
105 //DateTime lastDayOfQuarter = firstDayOfQuarter.AddMonths(3).AddDays(-1);
106
107 static guint DateInQuarter(guint32 from, guint32 opedate)
108 {
109 GDate *date1, *date2;
110 guint quarter, pos;
111
112 date1 = g_date_new_julian(from);
113 date2 = g_date_new_julian(opedate);
114
115 //#1758532 shift to first quarter day of 'from date'
116 quarter = ((g_date_get_month(date1)-1)/3)+1;
117 DB( g_print("-- from=%02d/%d :: Q%d\n", g_date_get_month(date1), g_date_get_year(date1), quarter) );
118 g_date_set_day(date1, 1);
119 g_date_set_month(date1, ((quarter-1)*3)+1);
120
121 pos = (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/3;
122
123 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) );
124
125 g_date_free(date2);
126 g_date_free(date1);
127
128 return(pos);
129 }
130
131
132 static guint DateInHalfYear(guint32 from, guint32 opedate)
133 {
134 GDate *date1, *date2;
135 guint hyear, pos;
136
137 date1 = g_date_new_julian(from);
138 date2 = g_date_new_julian(opedate);
139
140 // shift to first half year of 'from date'
141 hyear = ((g_date_get_month(date1)-1)/6)+1;
142 DB( g_print("-- from=%02d/%d :: Q%d\n", g_date_get_month(date1), g_date_get_year(date1), hyear) );
143 g_date_set_day(date1, 1);
144 g_date_set_month(date1, ((hyear-1)*6)+1);
145
146 pos = (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/6;
147
148 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) );
149
150 g_date_free(date2);
151 g_date_free(date1);
152
153 return(pos);
154 }
155
156
157 /*
158 ** return the year list position correponding to the passed date
159 */
160 static guint DateInYear(guint32 from, guint32 opedate)
161 {
162 GDate *date;
163 guint year_from, year_ope, pos;
164
165 date = g_date_new_julian(from);
166 year_from = g_date_get_year(date);
167
168 g_date_set_julian(date, opedate);
169 year_ope = g_date_get_year(date);
170 g_date_free(date);
171
172 pos = year_ope - year_from;
173
174 //g_print(" from=%d ope=%d => %d\n", year_from, year_ope, pos);
175
176 return(pos);
177 }
178
179
180 gint report_items_count(gint src, guint32 jfrom, guint32 jto)
181 {
182 GDate *date1, *date2;
183 gint nbsrc = 0;
184
185 switch(src)
186 {
187 case REPORT_SRC_CATEGORY:
188 case REPORT_SRC_SUBCATEGORY:
189 nbsrc = da_cat_get_max_key() + 1;
190 break;
191 case REPORT_SRC_PAYEE:
192 nbsrc = da_pay_get_max_key() + 1;
193 break;
194 case REPORT_SRC_ACCOUNT:
195 nbsrc = da_acc_get_max_key() + 1;
196 break;
197 case REPORT_SRC_TAG:
198 nbsrc = da_tag_length();
199 break;
200 case REPORT_SRC_MONTH:
201 date1 = g_date_new_julian(jfrom);
202 date2 = g_date_new_julian(jto);
203 nbsrc = ((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1) + 1;
204 g_date_free(date2);
205 g_date_free(date1);
206 break;
207 case REPORT_SRC_YEAR:
208 date1 = g_date_new_julian(jfrom);
209 date2 = g_date_new_julian(jto);
210 nbsrc = g_date_get_year(date2) - g_date_get_year(date1) + 1;
211 g_date_free(date2);
212 g_date_free(date1);
213 break;
214 }
215
216 return nbsrc;
217 }
218
219
220
221 gint report_items_get_pos(gint tmpsrc, guint jfrom, Transaction *ope)
222 {
223 gint pos = 0;
224
225 switch(tmpsrc)
226 {
227 case REPORT_SRC_CATEGORY:
228 pos = category_report_id(ope->kcat, FALSE);
229 break;
230 case REPORT_SRC_SUBCATEGORY:
231 pos = ope->kcat;
232 break;
233 case REPORT_SRC_PAYEE:
234 pos = ope->kpay;
235 break;
236 case REPORT_SRC_ACCOUNT:
237 pos = ope->kacc;
238 break;
239 case REPORT_SRC_MONTH:
240 pos = DateInMonth(jfrom, ope->date);
241 break;
242 case REPORT_SRC_YEAR:
243 pos = DateInYear(jfrom, ope->date);
244 break;
245 }
246 return pos;
247 }
248
249
250 gint report_interval_get_pos(gint intvl, guint jfrom, Transaction *ope)
251 {
252 gint pos = 0;
253
254 switch(intvl)
255 {
256 case REPORT_INTVL_DAY:
257 pos = ope->date - jfrom;
258 break;
259 case REPORT_INTVL_WEEK:
260 pos = (ope->date - jfrom)/7;
261 break;
262 case REPORT_INTVL_MONTH:
263 pos = DateInMonth(jfrom, ope->date);
264 break;
265 case REPORT_INTVL_QUARTER:
266 pos = DateInQuarter(jfrom, ope->date);
267 break;
268 case REPORT_INTVL_HALFYEAR:
269 pos = DateInHalfYear(jfrom, ope->date);
270 break;
271 case REPORT_INTVL_YEAR:
272 pos = DateInYear(jfrom, ope->date);
273 break;
274 }
275
276 return pos;
277 }
278
279
280
281 gint report_interval_count(gint intvl, guint32 jfrom, guint32 jto)
282 {
283 GDate *date1, *date2;
284 gint nbintvl = 0;
285
286 date1 = g_date_new_julian(jfrom);
287 date2 = g_date_new_julian(jto);
288
289 switch(intvl)
290 {
291 case REPORT_INTVL_DAY:
292 nbintvl = 1 + (jto - jfrom);
293 break;
294 case REPORT_INTVL_WEEK:
295 nbintvl = 1 + ((jto - jfrom) / 7);
296 break;
297 case REPORT_INTVL_MONTH:
298 nbintvl = 1 + ((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1);
299 break;
300 case REPORT_INTVL_QUARTER:
301 nbintvl = 1 + (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/3;
302 break;
303 case REPORT_INTVL_HALFYEAR:
304 nbintvl = 1 + (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/6;
305 break;
306 case REPORT_INTVL_YEAR:
307 nbintvl = 1 + g_date_get_year(date2) - g_date_get_year(date1);
308 break;
309 }
310
311 g_date_free(date2);
312 g_date_free(date1);
313
314 return nbintvl;
315 }
316
317
318 void report_interval_snprint_name(gchar *s, gint slen, gint intvl, guint32 jfrom, gint idx)
319 {
320 GDate *date = g_date_new_julian(jfrom);
321
322 switch(intvl)
323 {
324 case REPORT_INTVL_DAY:
325 g_date_add_days(date, idx);
326 g_date_strftime (s, slen, PREFS->date_format, date);
327 break;
328
329 case REPORT_INTVL_WEEK:
330 g_date_add_days(date, idx*7);
331 //g_snprintf(buffer, 63, "%d-%02d", g_date_get_year(date), g_date_get_month(date));
332 //TRANSLATORS: printf string for year of week W, ex. 2019-W52 for week 52 of 2019
333 g_snprintf(s, slen, _("%d-w%d"), g_date_get_year(date), g_date_get_monday_week_of_year(date));
334 break;
335
336 case REPORT_INTVL_MONTH:
337 g_date_add_months(date, idx);
338 //g_snprintf(buffer, 63, "%d-%02d", g_date_get_year(date), g_date_get_month(date));
339 g_snprintf(s, slen, "%d-%s", g_date_get_year(date), _(CYA_ABMONTHS[g_date_get_month(date)]));
340 break;
341
342 case REPORT_INTVL_QUARTER:
343 g_date_add_months(date, idx*3);
344 //g_snprintf(buffer, 63, "%d-%02d", g_date_get_year(date), g_date_get_month(date));
345 //todo: will be innacurrate here if fiscal year start not 1/jan
346 //TRANSLATORS: printf string for year of quarter Q, ex. 2019-Q4 for quarter 4 of 2019
347 g_snprintf(s, slen, _("%d-q%d"), g_date_get_year(date), ((g_date_get_month(date)-1)/3)+1);
348 break;
349
350 case REPORT_INTVL_HALFYEAR:
351 g_date_add_months(date, idx*6);
352 g_snprintf(s, slen, "%d-%s", g_date_get_year(date), g_date_get_month(date) < 7 ? "h1" : "h2");
353 break;
354
355 case REPORT_INTVL_YEAR:
356 g_date_add_years(date, idx);
357 g_snprintf(s, slen, "%d", g_date_get_year(date));
358 break;
359 default:
360 *s ='\0';
361 break;
362 }
363
364 g_date_free(date);
365 }
366
367
368 //TODO: maybe migrate this to filter as well
369 //#1562372 in case of a split we need to take amount for filter categories only
370 gdouble report_txn_amount_get(Filter *flt, Transaction *txn)
371 {
372 gdouble amount;
373
374 amount = txn->amount;
375
376 if( flt->option[FILTER_CATEGORY] > 0 ) //not inactive
377 {
378 if( txn->flags & OF_SPLIT )
379 {
380 guint i, nbsplit = da_splits_length(txn->splits);
381 Split *split;
382 Category *catentry;
383 gint sinsert;
384
385 amount = 0.0;
386
387 for(i=0;i<nbsplit;i++)
388 {
389 split = da_splits_get(txn->splits, i);
390 catentry = da_cat_get(split->kcat);
391 if(catentry == NULL) continue;
392 sinsert = ( catentry->flt_select == TRUE ) ? 1 : 0;
393 if(flt->option[FILTER_CATEGORY] == 2) sinsert ^= 1;
394
395 DB( g_print(" split '%s' insert=%d\n",catentry->name, sinsert) );
396
397 if( (flt->option[FILTER_CATEGORY] == 0) || sinsert)
398 {
399 amount += split->amount;
400 }
401 }
402
403 }
404 }
405 return amount;
406 }
407
408
409
410
This page took 0.051472 seconds and 4 git commands to generate.