LCOV - code coverage report
Current view: top level - libgnucash/engine - ScrubBudget.c (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 0.0 % 90 0
Test Date: 2025-02-07 16:25:45 Functions: 0.0 % 5 0
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /********************************************************************\
       2                 :             :  * ScrubBudget.c -- fix budget amount signs                         *
       3                 :             :  * Copyright (c) 2020 Christoher Lam                                *
       4                 :             :  *                                                                  *
       5                 :             :  * This program is free software; you can redistribute it and/or    *
       6                 :             :  * modify it under the terms of the GNU General Public License as   *
       7                 :             :  * published by the Free Software Foundation; either version 2 of   *
       8                 :             :  * the License, or (at your option) any later version.              *
       9                 :             :  *                                                                  *
      10                 :             :  * This program is distributed in the hope that it will be useful,  *
      11                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
      12                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      13                 :             :  * GNU General Public License for more details.                     *
      14                 :             :  *                                                                  *
      15                 :             :  * You should have received a copy of the GNU General Public License*
      16                 :             :  * along with this program; if not, contact:                        *
      17                 :             :  *                                                                  *
      18                 :             :  * Free Software Foundation           Voice:  +1-617-542-5942       *
      19                 :             :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
      20                 :             :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
      21                 :             :  *                                                                  *
      22                 :             : \********************************************************************/
      23                 :             : 
      24                 :             : #include <config.h>
      25                 :             : 
      26                 :             : #include <glib.h>
      27                 :             : #include <glib/gi18n.h>
      28                 :             : #include <stdio.h>
      29                 :             : #include <string.h>
      30                 :             : #include <stdint.h>
      31                 :             : 
      32                 :             : #include "gnc-prefs.h"
      33                 :             : #include "gnc-budget.h"
      34                 :             : #include "gnc-features.h"
      35                 :             : #include "ScrubBudget.h"
      36                 :             : 
      37                 :             : static QofLogModule log_module = "gnc.engine.scrub";
      38                 :             : 
      39                 :             : typedef enum
      40                 :             : {
      41                 :             :     HEURISTICS_INC_EXP,
      42                 :             :     HEURISTICS_CREDIT_ACC,
      43                 :             :     HEURISTICS_NONE
      44                 :             : } SignReversals;
      45                 :             : 
      46                 :             : typedef struct
      47                 :             : {
      48                 :             :     GncBudget* budget;
      49                 :             :     SignReversals policy;
      50                 :             : } ReversalType;
      51                 :             : 
      52                 :             : typedef struct
      53                 :             : {
      54                 :             :     gint asset,liability,equity,income,expense;
      55                 :             :     gint num_periods;
      56                 :             :     GncBudget* budget;
      57                 :             : } ProcessData;
      58                 :             : 
      59                 :             : static void
      60                 :           0 : process_heuristics_acct (Account * account, gpointer user_data)
      61                 :             : {
      62                 :             :     /* each account- check type. sum budget period amounts. if sum<0,
      63                 :             :        decrease type tally by 1. if sum>0, increase type tally by 1. */
      64                 :           0 :     ProcessData *heuristics = (ProcessData*) user_data;
      65                 :           0 :     gnc_numeric total = gnc_numeric_zero(), val;
      66                 :             :     gint sign;
      67                 :             :     gchar *totalstr;
      68                 :             : 
      69                 :           0 :     for (gint i = 0; i < heuristics->num_periods; ++i)
      70                 :             :     {
      71                 :           0 :         if (!gnc_budget_is_account_period_value_set (heuristics->budget, account, i))
      72                 :           0 :             continue;
      73                 :           0 :         val = gnc_budget_get_account_period_value (heuristics->budget, account, i);
      74                 :           0 :         total = gnc_numeric_add_fixed (total, val);
      75                 :             :     }
      76                 :             : 
      77                 :           0 :     sign = gnc_numeric_compare (total, gnc_numeric_zero ());
      78                 :           0 :     totalstr = gnc_numeric_to_string (total);
      79                 :           0 :     PINFO ("acct=%s, total=%s, sign=%d",
      80                 :             :            xaccAccountGetName (account), totalstr, sign);
      81                 :           0 :     g_free (totalstr);
      82                 :             : 
      83                 :           0 :     switch (xaccAccountTypeGetFundamental (xaccAccountGetType (account)))
      84                 :             :     {
      85                 :           0 :     case ACCT_TYPE_ASSET:
      86                 :           0 :         heuristics->asset += sign;
      87                 :           0 :         break;
      88                 :           0 :     case ACCT_TYPE_LIABILITY:
      89                 :           0 :         heuristics->liability += sign;
      90                 :           0 :         break;
      91                 :           0 :     case ACCT_TYPE_EXPENSE:
      92                 :           0 :         heuristics->expense += sign;
      93                 :           0 :         break;
      94                 :           0 :     case ACCT_TYPE_INCOME:
      95                 :           0 :         heuristics->income += sign;
      96                 :           0 :         break;
      97                 :           0 :     case ACCT_TYPE_EQUITY:
      98                 :           0 :         heuristics->equity += sign;
      99                 :           0 :         break;
     100                 :           0 :     default:
     101                 :           0 :         break;
     102                 :             :     }
     103                 :           0 : }
     104                 :             : 
     105                 :             : static SignReversals
     106                 :           0 : heuristics_on_budget (GncBudget * budget, Account *root)
     107                 :             : {
     108                 :           0 :     ProcessData heuristics = {0, 0, 0, 0, 0, gnc_budget_get_num_periods (budget),
     109                 :             :                               budget};
     110                 :             :     SignReversals result;
     111                 :             : 
     112                 :           0 :     gnc_account_foreach_descendant (root, process_heuristics_acct, &heuristics);
     113                 :             : 
     114                 :           0 :     result =
     115                 :           0 :         heuristics.expense < 0 ? HEURISTICS_INC_EXP :
     116                 :           0 :         heuristics.income < 0 ? HEURISTICS_NONE :
     117                 :             :         HEURISTICS_CREDIT_ACC;
     118                 :             : 
     119                 :           0 :     LEAVE ("heuristics_on_budget %s: A(%d) L(%d) Inc(%d) Exp(%d) Eq(%d) = %d",
     120                 :             :            gnc_budget_get_name (budget),
     121                 :             :            heuristics.asset, heuristics.liability, heuristics.income,
     122                 :             :            heuristics.expense, heuristics.equity, result);
     123                 :             : 
     124                 :           0 :     return result;
     125                 :             : }
     126                 :             : 
     127                 :             : static void
     128                 :           0 : fix_budget_acc_sign (Account *acc, gpointer user_data)
     129                 :             : {
     130                 :           0 :     ReversalType* reversal = (ReversalType*) user_data;
     131                 :           0 :     GncBudget* budget = reversal->budget;
     132                 :           0 :     guint numperiods = gnc_budget_get_num_periods (budget);
     133                 :           0 :     int type = xaccAccountTypeGetFundamental (xaccAccountGetType (acc));
     134                 :             : 
     135                 :           0 :     ENTER ("budget account reversal [%s] starting", xaccAccountGetName(acc));
     136                 :             : 
     137                 :           0 :     switch (reversal->policy)
     138                 :             :     {
     139                 :           0 :     case HEURISTICS_INC_EXP:
     140                 :           0 :         if ((type != ACCT_TYPE_INCOME) && (type != ACCT_TYPE_EXPENSE))
     141                 :           0 :             return;
     142                 :           0 :         PINFO ("budget account [%s] is inc/exp. reverse!",
     143                 :             :                xaccAccountGetName(acc));
     144                 :           0 :         break;
     145                 :           0 :     case HEURISTICS_CREDIT_ACC:
     146                 :           0 :         if ((type != ACCT_TYPE_LIABILITY) &&
     147                 :           0 :             (type != ACCT_TYPE_EQUITY) &&
     148                 :             :             (type != ACCT_TYPE_INCOME))
     149                 :           0 :             return;
     150                 :           0 :         PINFO ("budget account [%s] is credit-account. reverse!",
     151                 :             :                xaccAccountGetName(acc));
     152                 :           0 :         break;
     153                 :           0 :     default:
     154                 :             :         /* shouldn't happen. */
     155                 :           0 :         return;
     156                 :             :     }
     157                 :             : 
     158                 :           0 :     for (guint i=0; i < numperiods; ++i)
     159                 :             :     {
     160                 :             :         gnc_numeric amt;
     161                 :           0 :         if (!gnc_budget_is_account_period_value_set (budget, acc, i))
     162                 :           0 :             continue;
     163                 :             : 
     164                 :           0 :         amt = gnc_budget_get_account_period_value (budget, acc, i);
     165                 :           0 :         amt = gnc_numeric_neg (amt);
     166                 :           0 :         gnc_budget_set_account_period_value (budget, acc, i, amt);
     167                 :             :     }
     168                 :             : 
     169                 :           0 :     LEAVE ("budget account reversal [%s] completed!", xaccAccountGetName(acc));
     170                 :             : }
     171                 :             : 
     172                 :             : static void
     173                 :           0 : maybe_scrub_budget (QofInstance* data, gpointer user_data)
     174                 :             : {
     175                 :           0 :     GncBudget* budget = GNC_BUDGET(data);
     176                 :           0 :     Account *root = (Account*) user_data;
     177                 :             :     ReversalType reversal;
     178                 :             : 
     179                 :           0 :     reversal.policy = heuristics_on_budget (budget, root);
     180                 :           0 :     if (reversal.policy == HEURISTICS_NONE)
     181                 :             :     {
     182                 :           0 :         PWARN ("budget [%s] doesn't need reversing", gnc_budget_get_name (budget));
     183                 :           0 :         return;
     184                 :             :     }
     185                 :             : 
     186                 :           0 :     reversal.budget = budget;
     187                 :             : 
     188                 :           0 :     ENTER ("processing budget [%s] for reversal", gnc_budget_get_name (budget));
     189                 :           0 :     gnc_account_foreach_descendant (root, fix_budget_acc_sign, &reversal);
     190                 :           0 :     LEAVE ("completed budget [%s] for reversal", gnc_budget_get_name (budget));
     191                 :             : }
     192                 :             : 
     193                 :             : gboolean
     194                 :           0 : gnc_maybe_scrub_all_budget_signs (QofBook *book)
     195                 :             : {
     196                 :           0 :     QofCollection* collection = qof_book_get_collection (book, GNC_ID_BUDGET);
     197                 :           0 :     gboolean has_no_budgets = (qof_collection_count (collection) == 0);
     198                 :           0 :     gboolean featured = gnc_features_check_used (book, GNC_FEATURE_BUDGET_UNREVERSED);
     199                 :             : 
     200                 :             :     /* If there are no budgets, there shouldn't be feature! */
     201                 :           0 :     if (has_no_budgets && featured)
     202                 :             :     {
     203                 :           0 :         gnc_features_set_unused (book, GNC_FEATURE_BUDGET_UNREVERSED);
     204                 :           0 :         PWARN ("There are no budgets, removing feature BUDGET_UNREVERSED");
     205                 :             :     }
     206                 :             : 
     207                 :           0 :     if (has_no_budgets || featured)
     208                 :           0 :         return FALSE;
     209                 :             : 
     210                 :             :     /* There are budgets and feature is not set. Scrub, and set
     211                 :             :        feature. Return TRUE to show budget fix warning. */
     212                 :           0 :     qof_collection_foreach (collection, maybe_scrub_budget,
     213                 :           0 :                             gnc_book_get_root_account (book));
     214                 :           0 :     gnc_features_set_used (book, GNC_FEATURE_BUDGET_UNREVERSED);
     215                 :           0 :     return TRUE;
     216                 :             : }
     217                 :             : /* ==================== END OF FILE ==================== */
        

Generated by: LCOV version 2.0-1