/* HomeBank -- Free, easy, personal accounting for everyone. * Copyright (C) 1995-2019 Maxime DOYEN * * This file is part of HomeBank. * * HomeBank is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * HomeBank is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "homebank.h" #include "hb-report.h" /****************************************************************************/ /* Debug macros */ /****************************************************************************/ #define MYDEBUG 0 #if MYDEBUG #define DB(x) (x); #else #define DB(x); #endif /* our global datas */ extern struct HomeBank *GLOBALS; extern struct Preferences *PREFS; extern gchar *CYA_ABMONTHS[]; /* = = = = = = = = = = = = = = = = = = = = */ /* CarCost */ void da_vehiclecost_free(CarCost *item) { if(item != NULL) { g_free(item); } } CarCost *da_vehiclecost_malloc(void) { return g_malloc0(sizeof(CarCost)); } void da_vehiclecost_destroy(GList *list) { GList *tmplist = g_list_first(list); while (tmplist != NULL) { CarCost *item = tmplist->data; da_vehiclecost_free(item); tmplist = g_list_next(tmplist); } g_list_free(list); } /* = = = = = = = = = = = = = = = = = = = = */ /* ** return the month list position correponding to the passed date */ static guint DateInMonth(guint32 from, guint32 opedate) { GDate *date1, *date2; guint pos; //todo // this return sometimes -1, -2 which is wrong date1 = g_date_new_julian(from); date2 = g_date_new_julian(opedate); pos = ((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1); //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); g_date_free(date2); g_date_free(date1); return(pos); } //for fiscal sub gap between 1st fiscal and 1/1/year //int quarterNumber = (date.Month-1)/3+1; //DateTime firstDayOfQuarter = new DateTime(date.Year, (quarterNumber-1)*3+1,1); //DateTime lastDayOfQuarter = firstDayOfQuarter.AddMonths(3).AddDays(-1); static guint DateInQuarter(guint32 from, guint32 opedate) { GDate *date1, *date2; guint quarter, pos; date1 = g_date_new_julian(from); date2 = g_date_new_julian(opedate); //#1758532 shift to first quarter day of 'from date' quarter = ((g_date_get_month(date1)-1)/3)+1; DB( g_print("-- from=%02d/%d :: Q%d\n", g_date_get_month(date1), g_date_get_year(date1), quarter) ); g_date_set_day(date1, 1); g_date_set_month(date1, ((quarter-1)*3)+1); pos = (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/3; 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) ); g_date_free(date2); g_date_free(date1); return(pos); } static guint DateInHalfYear(guint32 from, guint32 opedate) { GDate *date1, *date2; guint hyear, pos; date1 = g_date_new_julian(from); date2 = g_date_new_julian(opedate); // shift to first half year of 'from date' hyear = ((g_date_get_month(date1)-1)/6)+1; DB( g_print("-- from=%02d/%d :: Q%d\n", g_date_get_month(date1), g_date_get_year(date1), hyear) ); g_date_set_day(date1, 1); g_date_set_month(date1, ((hyear-1)*6)+1); pos = (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/6; 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) ); g_date_free(date2); g_date_free(date1); return(pos); } /* ** return the year list position correponding to the passed date */ static guint DateInYear(guint32 from, guint32 opedate) { GDate *date; guint year_from, year_ope, pos; date = g_date_new_julian(from); year_from = g_date_get_year(date); g_date_set_julian(date, opedate); year_ope = g_date_get_year(date); g_date_free(date); pos = year_ope - year_from; //g_print(" from=%d ope=%d => %d\n", year_from, year_ope, pos); return(pos); } gint report_items_count(gint src, guint32 jfrom, guint32 jto) { GDate *date1, *date2; gint nbsrc = 0; switch(src) { case REPORT_SRC_CATEGORY: case REPORT_SRC_SUBCATEGORY: nbsrc = da_cat_get_max_key() + 1; break; case REPORT_SRC_PAYEE: nbsrc = da_pay_get_max_key() + 1; break; case REPORT_SRC_ACCOUNT: nbsrc = da_acc_get_max_key() + 1; break; case REPORT_SRC_TAG: nbsrc = da_tag_length(); break; case REPORT_SRC_MONTH: date1 = g_date_new_julian(jfrom); date2 = g_date_new_julian(jto); nbsrc = ((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1) + 1; g_date_free(date2); g_date_free(date1); break; case REPORT_SRC_YEAR: date1 = g_date_new_julian(jfrom); date2 = g_date_new_julian(jto); nbsrc = g_date_get_year(date2) - g_date_get_year(date1) + 1; g_date_free(date2); g_date_free(date1); break; } return nbsrc; } gint report_items_get_pos(gint tmpsrc, guint jfrom, Transaction *ope) { gint pos = 0; switch(tmpsrc) { case REPORT_SRC_CATEGORY: pos = category_report_id(ope->kcat, FALSE); break; case REPORT_SRC_SUBCATEGORY: pos = ope->kcat; break; case REPORT_SRC_PAYEE: pos = ope->kpay; break; case REPORT_SRC_ACCOUNT: pos = ope->kacc; break; case REPORT_SRC_MONTH: pos = DateInMonth(jfrom, ope->date); break; case REPORT_SRC_YEAR: pos = DateInYear(jfrom, ope->date); break; } return pos; } gint report_interval_get_pos(gint intvl, guint jfrom, Transaction *ope) { gint pos = 0; switch(intvl) { case REPORT_INTVL_DAY: pos = ope->date - jfrom; break; case REPORT_INTVL_WEEK: pos = (ope->date - jfrom)/7; break; case REPORT_INTVL_MONTH: pos = DateInMonth(jfrom, ope->date); break; case REPORT_INTVL_QUARTER: pos = DateInQuarter(jfrom, ope->date); break; case REPORT_INTVL_HALFYEAR: pos = DateInHalfYear(jfrom, ope->date); break; case REPORT_INTVL_YEAR: pos = DateInYear(jfrom, ope->date); break; } return pos; } gint report_interval_count(gint intvl, guint32 jfrom, guint32 jto) { GDate *date1, *date2; gint nbintvl = 0; date1 = g_date_new_julian(jfrom); date2 = g_date_new_julian(jto); switch(intvl) { case REPORT_INTVL_DAY: nbintvl = 1 + (jto - jfrom); break; case REPORT_INTVL_WEEK: nbintvl = 1 + ((jto - jfrom) / 7); break; case REPORT_INTVL_MONTH: nbintvl = 1 + ((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1); break; case REPORT_INTVL_QUARTER: nbintvl = 1 + (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/3; break; case REPORT_INTVL_HALFYEAR: nbintvl = 1 + (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/6; break; case REPORT_INTVL_YEAR: nbintvl = 1 + g_date_get_year(date2) - g_date_get_year(date1); break; } g_date_free(date2); g_date_free(date1); return nbintvl; } void report_interval_snprint_name(gchar *s, gint slen, gint intvl, guint32 jfrom, gint idx) { GDate *date = g_date_new_julian(jfrom); switch(intvl) { case REPORT_INTVL_DAY: g_date_add_days(date, idx); g_date_strftime (s, slen, PREFS->date_format, date); break; case REPORT_INTVL_WEEK: g_date_add_days(date, idx*7); //g_snprintf(buffer, 63, "%d-%02d", g_date_get_year(date), g_date_get_month(date)); //TRANSLATORS: printf string for year of week W, ex. 2019-W52 for week 52 of 2019 g_snprintf(s, slen, _("%d-w%d"), g_date_get_year(date), g_date_get_monday_week_of_year(date)); break; case REPORT_INTVL_MONTH: g_date_add_months(date, idx); //g_snprintf(buffer, 63, "%d-%02d", g_date_get_year(date), g_date_get_month(date)); g_snprintf(s, slen, "%d-%s", g_date_get_year(date), _(CYA_ABMONTHS[g_date_get_month(date)])); break; case REPORT_INTVL_QUARTER: g_date_add_months(date, idx*3); //g_snprintf(buffer, 63, "%d-%02d", g_date_get_year(date), g_date_get_month(date)); //todo: will be innacurrate here if fiscal year start not 1/jan //TRANSLATORS: printf string for year of quarter Q, ex. 2019-Q4 for quarter 4 of 2019 g_snprintf(s, slen, _("%d-q%d"), g_date_get_year(date), ((g_date_get_month(date)-1)/3)+1); break; case REPORT_INTVL_HALFYEAR: g_date_add_months(date, idx*6); g_snprintf(s, slen, "%d-%s", g_date_get_year(date), g_date_get_month(date) < 7 ? "h1" : "h2"); break; case REPORT_INTVL_YEAR: g_date_add_years(date, idx); g_snprintf(s, slen, "%d", g_date_get_year(date)); break; default: *s ='\0'; break; } g_date_free(date); } //TODO: maybe migrate this to filter as well //#1562372 in case of a split we need to take amount for filter categories only gdouble report_txn_amount_get(Filter *flt, Transaction *txn) { gdouble amount; amount = txn->amount; if( flt->option[FILTER_CATEGORY] > 0 ) //not inactive { if( txn->flags & OF_SPLIT ) { guint i, nbsplit = da_splits_length(txn->splits); Split *split; Category *catentry; gint sinsert; amount = 0.0; for(i=0;isplits, i); catentry = da_cat_get(split->kcat); if(catentry == NULL) continue; sinsert = ( catentry->flt_select == TRUE ) ? 1 : 0; if(flt->option[FILTER_CATEGORY] == 2) sinsert ^= 1; DB( g_print(" split '%s' insert=%d\n",catentry->name, sinsert) ); if( (flt->option[FILTER_CATEGORY] == 0) || sinsert) { amount += split->amount; } } } } return amount; }