/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "homebank.h"
-#include "rep_budget.h"
+#include "rep-budget.h"
-#include "list_operation.h"
-#include "gtk-chart-stack.h"
+#include "list-operation.h"
+#include "gtk-chart-progress.h"
#include "gtk-dateentry.h"
-#include "dsp_mainwindow.h"
+#include "dsp-mainwindow.h"
#include "ui-transaction.h"
static GString *ui_list_repbudget_to_string(GtkTreeView *treeview, gboolean clipboard);
-gchar *CYA_BUDGSELECT[] = { N_("Category"), N_("Subcategory"), NULL };
-gchar *CYA_KIND[] = { N_("Exp. & Inc."), N_("Expense"), N_("Income"), NULL };
-
-gchar *CYA_BUDGETSELECT[] = { N_("Spent & Budget"), N_("Spent"), N_("Budget"), N_("Result"), NULL };
-
-
-//extern gchar *CYA_FLT_SELECT[];
+extern gchar *CYA_CATSUBCAT[];
+extern gchar *CYA_KIND[];
static GtkRadioActionEntry radio_entries[] = {
static GtkActionEntry entries[] = {
- { "Refresh" , ICONNAME_REFRESH, N_("Refresh"), NULL, N_("Refresh results"), G_CALLBACK (repbudget_action_refresh) },
+ { "Refresh" , ICONNAME_HB_REFRESH, N_("Refresh"), NULL, N_("Refresh results"), G_CALLBACK (repbudget_action_refresh) },
// { "Export" , ICONNAME_HB_FILE_EXPORT , N_("Export") , NULL, N_("Export as CSV"), G_CALLBACK (repbudget_action_export) },
};
//data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
tmpfor = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_for));
- name = g_strdup_printf("hb-repbudget_%s.csv", CYA_BUDGSELECT[tmpfor]);
+ name = g_strdup_printf("hb-repbudget_%s.csv", CYA_CATSUBCAT[tmpfor]);
if( ui_file_chooser_csv(GTK_WINDOW(data->window), GTK_FILE_CHOOSER_ACTION_SAVE, &filename, name) == TRUE )
{
//data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
tmpfor = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_for));
- name = g_strdup_printf("hb-repstat-detail_%s.csv", CYA_BUDGSELECT[tmpfor]);
+ name = g_strdup_printf("hb-repstat-detail_%s.csv", CYA_CATSUBCAT[tmpfor]);
if( ui_file_chooser_csv(GTK_WINDOW(data->window), GTK_FILE_CHOOSER_ACTION_SAVE, &filename, name) == TRUE )
{
//filter here
if( ope->flags & OF_SPLIT )
{
- guint nbsplit = da_splits_count(ope->splits);
+ guint nbsplit = da_splits_length(ope->splits);
Split *split;
guint i;
for(i=0;i<nbsplit;i++)
{
- split = ope->splits[i];
+ split = da_splits_get(ope->splits, i);
switch(tmpfor)
{
case BUDG_CATEGORY:
}
+static void repbudget_compute_cat_spent(guint32 key, gdouble amount, gdouble *tmp_spent, gdouble *tmp_budget)
+{
+Category *cat;
+
+ cat = da_cat_get(key);
+ if(cat)
+ {
+ DB( g_print(" -> affecting %.2f to cat %d sub=%d, bud=%.2f\n", amount, cat->key, (cat->flags & GF_SUB), tmp_budget[cat->key]) );
+ if( (cat->flags & GF_FORCED) || (cat->flags & GF_BUDGET) )
+ tmp_spent[cat->key] += amount;
+ //#1814213 only count subcat with budget
+ //if( (cat->flags & GF_SUB) )
+ if( (cat->flags & GF_FORCED) || ((cat->flags & GF_SUB) && (cat->flags & GF_BUDGET)) )
+ {
+ DB( g_print(" -> affecting %.2f to parent %d, bud=%.2f\n", amount, cat->parent, tmp_budget[cat->parent]) );
+ tmp_spent[cat->parent] += amount;
+ }
+ }
+}
+
+
static void repbudget_compute(GtkWidget *widget, gpointer user_data)
{
struct repbudget_data *data;
GList *list;
guint n_result, id;
gdouble *tmp_spent, *tmp_budget;
+gboolean *tmp_hassub;
gint nbmonth = 1;
gchar *title;
g_queue_free (data->txn_queue);
data->txn_queue = hbfile_transaction_get_partial_budget(data->filter->mindate, data->filter->maxdate);
-
DB( g_print(" for=%d, kind=%d\n", tmpfor, tmpkind) );
nbmonth = countmonth(mindate, maxdate);
/* allocate some memory */
tmp_spent = g_malloc0((n_result+1) * sizeof(gdouble));
tmp_budget = g_malloc0((n_result+1) * sizeof(gdouble));
+ tmp_hassub = g_malloc0((n_result+1) * sizeof(gboolean));
- if(tmp_spent && tmp_budget)
+ if(tmp_spent && tmp_budget && tmp_hassub)
{
guint i = 0;
/* compute the results */
for(i=1; i<=n_result; i++)
{
Category *entry;
- //gchar buffer[128];
- gint pos;
entry = da_cat_get(i);
if( entry == NULL)
entry->key, entry->name, (entry->flags & GF_SUB), (entry->flags & GF_BUDGET), (entry->flags & GF_CUSTOM)) );
//debug
- #if MYDEBUG == 1
+ /*#if MYDEBUG == 1
gint k;
g_print(" budget vector: ");
for(k=0;k<13;k++)
g_print( " %d:[%.2f]", k, entry->budget[k]);
g_print("\n");
- #endif
-
- pos = 0;
- switch(tmpfor)
- {
- case BUDG_CATEGORY:
- {
- Category *catentry = da_cat_get(i);
- if(catentry)
- pos = (catentry->flags & GF_SUB) ? catentry->parent : catentry->key;
- }
- break;
- case BUDG_SUBCATEGORY:
- pos = i;
- break;
- }
+ #endif*/
// same value each month ?
if(!(entry->flags & GF_CUSTOM))
{
DB( g_print(" - monthly %.2f\n", entry->budget[0]) );
- tmp_budget[pos] += entry->budget[0]*nbmonth;
+ tmp_budget[entry->key] += entry->budget[0]*nbmonth;
+ if( entry->flags & GF_SUB )
+ {
+ tmp_budget[entry->parent] += entry->budget[0]*nbmonth;
+ tmp_hassub[entry->parent] = TRUE;
+ }
}
//otherwise sum each month from mindate month
else
DB( g_print(" - custom each month for %d months\n", nbmonth) );
for(j=0;j<nbmonth;j++) {
DB( g_print(" j=%d month=%d budg=%.2f\n", j, month, entry->budget[month]) );
- tmp_budget[pos] += entry->budget[month];
- month++;
- if(month > 12) {
- month = 1;
+ tmp_budget[entry->key] += entry->budget[month];
+ if( entry->flags & GF_SUB )
+ {
+ tmp_budget[entry->parent] += entry->budget[month];
+ tmp_hassub[entry->parent] = TRUE;
}
+ month++;
+ if(month > 12) { month = 1; }
}
}
-
- //debug
- #if MYDEBUG == 1
- g_print(" final budget: %d:'%s' : budg[%d]=%.2f\n", entry->key, entry->name, pos, tmp_budget[pos] );
- #endif
}
// compute spent for each transaction */
DB( g_print("\n+ compute spent from transactions\n") );
-
list = g_queue_peek_head_link(data->txn_queue);
while (list != NULL)
{
Transaction *ope = list->data;
- gint pos = 0;
- gdouble trn_amount;
- //DB( g_print("%d, get ope: %s :: acc=%d, cat=%d, mnt=%.2f\n", i, ope->memo, ope->account, ope->category, ope->amount) );
+ DB( g_print("%d, get ope: %s :: acc=%d, cat=%d, mnt=%.2f\n", i, ope->memo, ope->kacc, ope->kcat, ope->amount) );
if( ope->flags & OF_SPLIT )
{
- guint nbsplit = da_splits_count(ope->splits);
+ guint nbsplit = da_splits_length(ope->splits);
Split *split;
for(i=0;i<nbsplit;i++)
{
- split = ope->splits[i];
- switch(tmpfor)
- {
- case BUDG_CATEGORY:
- {
- Category *catentry = da_cat_get(split->kcat);
- if(catentry)
- pos = (catentry->flags & GF_SUB) ? catentry->parent : catentry->key;
- }
- break;
- case BUDG_SUBCATEGORY:
- pos = split->kcat;
- break;
- }
-
- //trn_amount = split->amount;
- trn_amount = hb_amount_base(split->amount, ope->kcur);
-
- DB( g_print(" -> affecting split %.2f to cat pos %d\n", trn_amount, pos) );
-
- tmp_spent[pos] += trn_amount;
-
+ split = da_splits_get(ope->splits, i);
+ repbudget_compute_cat_spent(split->kcat, hb_amount_base(split->amount, ope->kcur), tmp_spent, tmp_budget);
}
}
else
{
- switch(tmpfor)
- {
- case BUDG_CATEGORY:
- {
- Category *catentry = da_cat_get(ope->kcat);
- if(catentry)
- pos = (catentry->flags & GF_SUB) ? catentry->parent : catentry->key;
- }
- break;
- case BUDG_SUBCATEGORY:
- pos = ope->kcat;
- break;
- }
-
- //trn_amount = ope->amount;
- trn_amount = hb_amount_base(ope->amount, ope->kcur);
-
- DB( g_print(" -> affecting %.2f to cat pos %d\n", trn_amount, pos) );
-
- tmp_spent[pos] += trn_amount;
-
+ repbudget_compute_cat_spent(ope->kcat, hb_amount_base(ope->amount, ope->kcur), tmp_spent, tmp_budget);
}
list = g_list_next(list);
g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_report), NULL); /* Detach model from view */
- DB( g_print("\n+ insert into treeview\n") );
-
- /* insert into the treeview */
for(i=1, id=0; i<=n_result; i++)
{
- gchar *name, *fullcatname;
+ gchar *name;
gboolean outofbudget;
Category *entry;
- fullcatname = NULL;
-
entry = da_cat_get(i);
if( entry == NULL)
continue;
- if(entry->flags & GF_SUB)
- {
- Category *parent = da_cat_get( entry->parent);
-
- fullcatname = g_strdup_printf("%s:%s", parent->name, entry->name);
- name = fullcatname;
- }
- else
- name = entry->name;
-
- if(name == NULL) name = "(None)";
+ name = entry->key == 0 ? "(None)" : entry->fullname;
//#1553862
//if( (tmpfor == BUDG_CATEGORY && !(entry->flags & GF_SUB)) || (tmpfor == BUDG_SUBCATEGORY) )
- if( (tmpfor == BUDG_CATEGORY && !(entry->flags & GF_SUB)) || (tmpfor == BUDG_SUBCATEGORY && (entry->flags & GF_SUB)) )
+ if( (tmpfor == BUDG_CATEGORY && !(entry->flags & GF_SUB)) ||
+ (tmpfor == BUDG_SUBCATEGORY && ((entry->flags & GF_SUB) || !tmp_hassub[i]) ) )
{
guint pos;
}
// display expense or income (filter on amount and not category hypothetical flag
- //if( tmpkind != (entry->flags & GF_INCOME)) continue;
if( tmpkind == 1 && tmp_budget[pos] > 0)
continue;
status = "";
outofbudget = FALSE;
- if(rawrate > 1.0)
- {
- status = _(" over");
- outofbudget = TRUE;
- }
- else
+ if( result )
{
- if(tmp_budget[pos] < 0.0)
- status = _(" left");
- else if(tmp_budget[pos] > 0.0)
+ if(rawrate > 1.0)
{
- status = _(" under");
+ status = _(" over");
outofbudget = TRUE;
}
+ else
+ {
+ if(tmp_budget[pos] < 0.0)
+ status = _(" left");
+ else if(tmp_budget[pos] > 0.0)
+ {
+ status = _(" under");
+ outofbudget = TRUE;
+ }
+ }
}
if(tmponlyout == TRUE && outofbudget == FALSE)
goto nextins;
- DB( g_print(" => insert %.2f | %.2f = %.2f (%.2f) '%s'\n\n", tmp_spent[pos], tmp_budget[pos], result, rawrate, status ) );
+ DB( g_print(" => insert '%s' s:%.2f b:%.2f r:%.2f (%%%.2f) '%s' '%d'\n\n", name, tmp_spent[pos], tmp_budget[pos], result, rawrate, status, outofbudget ) );
gtk_list_store_append (GTK_LIST_STORE(model), &iter);
gtk_list_store_set (GTK_LIST_STORE(model), &iter,
data->total_budget += tmp_budget[pos];
}
}
-
- g_free(fullcatname);
-
}
/* update column 0 title */
GtkTreeViewColumn *column = gtk_tree_view_get_column( GTK_TREE_VIEW(data->LV_report), 0);
- gtk_tree_view_column_set_title(column, _(CYA_BUDGSELECT[tmpfor]));
+ gtk_tree_view_column_set_title(column, _(CYA_CATSUBCAT[tmpfor]));
gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_report));
repbudget_update_total(widget, NULL);
/* update stack chart */
- title = g_strdup_printf(_("Budget for %s"), _(CYA_BUDGSELECT[tmpfor]) );
+ title = g_strdup_printf(_("Budget for %s"), _(CYA_CATSUBCAT[tmpfor]) );
- ui_chart_stack_set_currency(GTK_CHARTSTACK(data->RE_stack), GLOBALS->kcur);
+ ui_chart_progress_set_currency(GTK_CHARTPROGRESS(data->RE_stack), GLOBALS->kcur);
/* set chart color scheme */
- ui_chart_stack_set_color_scheme(GTK_CHARTSTACK(data->RE_stack), PREFS->report_color_scheme);
- ui_chart_stack_set_dualdatas(GTK_CHARTSTACK(data->RE_stack), model, _("Budget"), _("Result"), title, NULL);
+ ui_chart_progress_set_color_scheme(GTK_CHARTPROGRESS(data->RE_stack), PREFS->report_color_scheme);
+ ui_chart_progress_set_dualdatas(GTK_CHARTPROGRESS(data->RE_stack), model, _("Budget"), _("Result"), title, NULL);
g_free(title);
}
//DB( g_print(" inserting %i, %f %f\n", i, total_expense, total_income) );
/* free our memory */
+ g_free(tmp_hassub);
g_free(tmp_spent);
g_free(tmp_budget);
gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_report));
minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_minor));
- ui_chart_stack_show_minor(GTK_CHARTSTACK(data->RE_stack), minor);
+ ui_chart_progress_show_minor(GTK_CHARTPROGRESS(data->RE_stack), minor);
}
data->txn_queue = g_queue_new ();
- data->filter = da_filter_malloc();
- filter_default_all_set(data->filter);
+ data->filter = da_flt_malloc();
+ filter_reset(data->filter);
data->detail = PREFS->budg_showdetail;
data->legend = 1;
g_queue_free (data->txn_queue);
- da_filter_free(data->filter);
+ da_flt_free(data->filter);
g_free(data);
gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
row++;
- label = make_label_widget(_("_For:"));
+ label = make_label_widget(_("_View by:"));
gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
- widget = make_cycle(label, CYA_BUDGSELECT);
+ widget = make_cycle(label, CYA_CATSUBCAT);
data->CY_for = widget;
gtk_grid_attach (GTK_GRID (table), data->CY_for, 2, row, 1, 1);
row++;
- label = make_label_widget(_("_Kind:"));
+ label = make_label_widget(_("_Type:"));
gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
widget = make_cycle(label, CYA_KIND);
data->CY_kind = widget;
//page: 2d bar
//widget = gtk_chart_new(CHART_TYPE_COL);
- widget = ui_chart_stack_new();
+ widget = ui_chart_progress_new();
data->RE_stack = widget;
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), widget, NULL);
gtk_tree_model_get(model, b, LST_BUDGET_NAME, &entry2, -1);
retval = hb_string_utf8_compare(entry1, entry2);
- //retval = (entry1->flags & GF_INCOME) - (entry2->flags & GF_INCOME);
- //if(!retval)
- //{
- // retval = hb_string_utf8_compare(entry1->name, entry2->name);
- //}
- //leak
+
+
g_free(entry2);
g_free(entry1);