LCOV - code coverage report
Current view: top level - libgnucash/tax - gnc-locale-tax.c (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 5.1 % 117 6
Test Date: 2026-11-02 18:19:43 Functions: 33.3 % 3 1
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*********************************************************************
       2              :  * gnc-locale-tax.c
       3              :  * hack to load the proper guile based tax system
       4              :  *
       5              :  * Copyright (c) 2019 Geert Janssens <geert@kobaltwit.be>
       6              :  *********************************************************************/
       7              : /********************************************************************\
       8              :  * This program is free software; you can redistribute it and/or    *
       9              :  * modify it under the terms of the GNU General Public License as   *
      10              :  * published by the Free Software Foundation; either version 2 of   *
      11              :  * the License, or (at your option) any later version.              *
      12              :  *                                                                  *
      13              :  * This program is distributed in the hope that it will be useful,  *
      14              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
      15              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      16              :  * GNU General Public License for more details.                     *
      17              :  *                                                                  *
      18              :  * You should have received a copy of the GNU General Public License*
      19              :  * along with this program; if not, contact:                        *
      20              :  *                                                                  *
      21              :  * Free Software Foundation           Voice:  +1-617-542-5942       *
      22              :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
      23              :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
      24              :  *                                                                  *
      25              : \********************************************************************/
      26              : 
      27              : 
      28              : #include <config.h>
      29              : #include <string.h>
      30              : #include <locale.h>
      31              : #include <libguile.h>
      32              : #include <glib.h>
      33              : #include <glib/gi18n.h>
      34              : #include <Account.h>
      35              : #include <gnc-ui-util.h>
      36              : #include <guile-mappings.h>
      37              : #include <gnc-guile-utils.h>
      38              : #include "gnc-locale-tax.h"
      39              : #include <gnc-locale-utils.h>
      40              : 
      41              : 
      42              : void
      43            1 : gnc_locale_tax_init(void)
      44              : {
      45              :     /* This is a very simple hack that loads the (new, special) German
      46              :        tax definition file in a German locale, or (default) loads the
      47              :        US tax file. */
      48              : # ifdef G_OS_WIN32
      49              :     gchar *thislocale = g_win32_getlocale();
      50              :     gboolean is_de_DE = (strncmp(thislocale, "de_DE", 5) == 0);
      51              :     g_free(thislocale);
      52              : # else /* !G_OS_WIN32 */
      53            1 :     const char *thislocale = gnc_locale_name();
      54            1 :     gboolean is_de_DE = (strncmp(thislocale, "de_DE", 5) == 0);
      55              : # endif /* G_OS_WIN32 */
      56            1 :     if (is_de_DE)
      57            0 :         scm_c_use_module("gnucash locale de_DE tax");
      58              :     else
      59            1 :         scm_c_use_module("gnucash locale us tax");
      60            1 : }
      61              : 
      62              : /* Caller is responsible for g_free'ing returned memory */
      63              : char *
      64            0 : gnc_ui_account_get_tax_info_string (const Account *account)
      65              : {
      66              :     static SCM get_form = SCM_UNDEFINED;
      67              :     static SCM get_desc = SCM_UNDEFINED;
      68              : 
      69            0 :     gboolean tax_related = FALSE;
      70              :     const char *code;
      71              : 
      72            0 :     if (!account)
      73            0 :         return NULL;
      74              : 
      75            0 :     tax_related = xaccAccountGetTaxRelated (account);
      76            0 :     code = xaccAccountGetTaxUSCode (account);
      77              : 
      78            0 :     if (!code)
      79              :     {
      80            0 :         if (!tax_related)
      81            0 :             return NULL;
      82              :         /* tax_related && !code */
      83              :         else
      84              :             /* Translators: This and the following strings appear on
      85              :                the account tab if the Tax Info column is displayed,
      86              :                i.e. if the user wants to record the tax form number
      87              :                and location on that tax form which corresponds to this
      88              :                gnucash account. For the US Income Tax support in
      89              :                gnucash, each tax code that can be assigned to an
      90              :                account generally corresponds to a specific line number
      91              :                on a paper form and each form has a unique
      92              :                identification (e.g., Form 1040, Schedule A). */
      93            0 :             return g_strdup (_("Tax-related but has no tax code"));
      94              :     }
      95              :     else  /* with tax code */
      96              :     {
      97              :         const gchar *tax_type;
      98              :         GNCAccountType atype;
      99              :         SCM tax_entity_type;
     100              :         SCM category;
     101            0 :         gchar *num_code = NULL;
     102            0 :         const gchar *prefix = "N";
     103            0 :         gchar *return_string = NULL;
     104              : 
     105            0 :         tax_type = gnc_get_current_book_tax_type ();
     106            0 :         if (tax_type == NULL || (g_strcmp0 (tax_type, "") == 0))
     107            0 :             return g_strdup (_("Tax entity type not specified"));
     108              : 
     109            0 :         atype = xaccAccountGetType (account);
     110            0 :         tax_entity_type = scm_from_utf8_string (tax_type);
     111              : 
     112            0 :         if (get_form == SCM_UNDEFINED)
     113              :         {
     114              :             /* load the tax info */
     115            0 :             gnc_locale_tax_init ();
     116              : 
     117            0 :             get_form = scm_c_eval_string
     118              :                        ("(false-if-exception gnc:txf-get-form)");
     119            0 :             get_desc = scm_c_eval_string
     120              :                        ("(false-if-exception gnc:txf-get-description)");
     121              :         }
     122              : 
     123            0 :         g_return_val_if_fail (scm_is_procedure (get_form), NULL);
     124            0 :         g_return_val_if_fail (scm_is_procedure (get_desc), NULL);
     125              : 
     126            0 :         category = scm_c_eval_string (atype == ACCT_TYPE_INCOME ?
     127            0 :                                       "txf-income-categories" :
     128              :                                       (atype == ACCT_TYPE_EXPENSE ?
     129              :                                        "txf-expense-categories" :
     130            0 :                                        (((atype == ACCT_TYPE_BANK)      ||
     131            0 :                                          (atype == ACCT_TYPE_CASH)      ||
     132            0 :                                          (atype == ACCT_TYPE_ASSET)     ||
     133            0 :                                          (atype == ACCT_TYPE_STOCK)     ||
     134            0 :                                          (atype == ACCT_TYPE_MUTUAL)    ||
     135              :                                          (atype == ACCT_TYPE_RECEIVABLE)) ?
     136              :                                         "txf-asset-categories" :
     137            0 :                                         (((atype == ACCT_TYPE_CREDIT)    ||
     138            0 :                                           (atype == ACCT_TYPE_LIABILITY) ||
     139            0 :                                           (atype == ACCT_TYPE_EQUITY)    ||
     140              :                                           (atype == ACCT_TYPE_PAYABLE)) ?
     141              :                                          "txf-liab-eq-categories" : ""))));
     142              : 
     143            0 :         if (g_str_has_prefix (code, prefix))
     144              :         {
     145              :             const gchar *num_code_tmp;
     146            0 :             num_code_tmp = g_strdup (code);
     147            0 :             num_code_tmp++; /* to lose the leading N */
     148            0 :             num_code = g_strdup (num_code_tmp);
     149            0 :             num_code_tmp--;
     150            0 :             g_free ((gpointer *) num_code_tmp);
     151              :         }
     152              :         else
     153              :         {
     154            0 :             num_code = g_strdup (code);
     155              :         }
     156              : 
     157            0 :         if (category == SCM_UNDEFINED)
     158              :         {
     159            0 :             if (tax_related)
     160            0 :                 return_string = g_strdup_printf
     161            0 :                                 (_("Tax type %s: invalid code %s for account type"),
     162              :                                  tax_type, num_code);
     163              :             else
     164            0 :                 return_string = g_strdup_printf
     165            0 :                                 (_("Not tax-related; tax type %s: invalid code %s for account type"),
     166              :                                  tax_type, num_code);
     167              :         }
     168              :         else
     169              :         {
     170              :             SCM code_scm;
     171              :             SCM form_scm;
     172            0 :             code_scm = scm_from_locale_symbol (code);
     173            0 :             form_scm = scm_call_3 (get_form, category, code_scm, tax_entity_type);
     174            0 :             if (!scm_is_string (form_scm))
     175              :             {
     176            0 :                 if (tax_related)
     177            0 :                     return_string =  g_strdup_printf
     178            0 :                                      (_("Invalid code %s for tax type %s"),
     179              :                                       num_code, tax_type);
     180              :                 else
     181            0 :                     return_string =  g_strdup_printf
     182            0 :                                      (_("Not tax-related; invalid code %s for tax type %s"),
     183              :                                       num_code, tax_type);
     184              :             }
     185              :             else
     186              :             {
     187            0 :                 gchar *form = NULL;
     188              : 
     189              :                 /* Note: using scm_to_utf8_stringn directly here instead
     190              :                    of our wrapper gnc_scm_to_utf8_string. 'form' should
     191              :                    be freed with 'free' instead of 'g_free'. This will
     192              :                    be taken care of automatically during scm_dynwind_end,
     193              :                    because we inform guile of this memory allocation via
     194              :                    scm_dynwind_free a little further. */
     195            0 :                 form = scm_to_utf8_stringn (form_scm, NULL);
     196            0 :                 if (!form)
     197              :                 {
     198            0 :                     if (tax_related)
     199            0 :                         return_string = g_strdup_printf
     200            0 :                                         (_("No form: code %s, tax type %s"), num_code,
     201              :                                          tax_type);
     202              :                     else
     203            0 :                         return_string = g_strdup_printf
     204            0 :                                         (_("Not tax-related; no form: code %s, tax type %s"),
     205              :                                          num_code, tax_type);
     206              :                 }
     207              :                 else
     208              :                 {
     209              :                     SCM desc_scm;
     210              : 
     211              :                     /* Create a dynwind context because we will be calling (scm) functions
     212              :                        that potentially exit non-locally */
     213            0 :                     scm_dynwind_begin (0);
     214            0 :                     scm_dynwind_free (form);
     215            0 :                     desc_scm = scm_call_3 (get_desc, category, code_scm,
     216              :                                            tax_entity_type);
     217            0 :                     if (!scm_is_string (desc_scm))
     218              :                     {
     219            0 :                         if (tax_related)
     220            0 :                             return_string = g_strdup_printf
     221            0 :                                             (_("No description: form %s, code %s, tax type %s"),
     222              :                                              form, num_code, tax_type);
     223              :                         else
     224            0 :                             return_string = g_strdup_printf
     225            0 :                                             (_("Not tax-related; no description: form %s, code %s, tax type %s"),
     226              :                                              form, num_code, tax_type);
     227              :                     }
     228              :                     else
     229              :                     {
     230            0 :                         gchar *desc = NULL;
     231            0 :                         desc = gnc_scm_to_utf8_string (desc_scm);
     232            0 :                         if (!desc)
     233              :                         {
     234            0 :                             if (tax_related)
     235            0 :                                 return_string = g_strdup_printf
     236            0 :                                                 (_("No description: form %s, code %s, tax type %s"),
     237              :                                                  form, num_code, tax_type);
     238              :                             else
     239            0 :                                 return_string = g_strdup_printf
     240            0 :                                                 (_("Not tax-related; no description: form %s, code %s, tax type %s"),
     241              :                                                  form, num_code, tax_type);
     242              :                         }
     243              :                         else
     244              :                         {
     245              :                             gint64 copy_number;
     246            0 :                             gchar *copy_txt = NULL;
     247            0 :                             copy_number = xaccAccountGetTaxUSCopyNumber (account);
     248              :                             copy_txt = (copy_number == 1) ?
     249            0 :                                        g_strdup ("") :
     250            0 :                                        g_strdup_printf ("(%d)",
     251              :                                                         (gint) copy_number);
     252            0 :                             if (tax_related)
     253              :                             {
     254            0 :                                 if (g_strcmp0 (form, "") == 0)
     255            0 :                                     return_string = g_strdup_printf ("%s", desc);
     256              :                                 else
     257            0 :                                     return_string = g_strdup_printf ("%s%s: %s",
     258              :                                                                      form, copy_txt, desc);
     259              :                             }
     260              :                             else
     261              :                             {
     262            0 :                                 return_string = g_strdup_printf
     263            0 :                                                 (_("Not tax-related; %s%s: %s (code %s, tax type %s)"),
     264              :                                                  form, copy_txt, desc, num_code, tax_type);
     265              :                             }
     266            0 :                             g_free (copy_txt);
     267              :                         }
     268            0 :                         g_free (desc);
     269              :                     }
     270            0 :                     scm_dynwind_end ();
     271              :                 }
     272              :             }
     273              :         }
     274            0 :         g_free (num_code);
     275            0 :         return return_string;
     276              :     }
     277              : }
     278              : 
     279              : /* Caller is responsible for g_free'ing returned memory */
     280              : char *
     281            0 : gnc_ui_account_get_tax_info_sub_acct_string (const Account *account)
     282              : {
     283              :     GList *descendant, *account_descendants;
     284              : 
     285            0 :     if (!account)
     286            0 :         return NULL;
     287              : 
     288            0 :     account_descendants = gnc_account_get_descendants (account);
     289            0 :     if (account_descendants)
     290              :     {
     291            0 :         gint sub_acct_tax_number = 0;
     292            0 :         for (descendant = account_descendants; descendant;
     293            0 :                 descendant = g_list_next(descendant))
     294              :         {
     295            0 :             if (xaccAccountGetTaxRelated (descendant->data))
     296            0 :                 sub_acct_tax_number++;
     297              :         }
     298            0 :         g_list_free (account_descendants);
     299            0 :         g_list_free (descendant);
     300              :         /* Translators: This and the following strings appear on
     301              :            the account tab if the Tax Info column is displayed,
     302              :            i.e. if the user wants to record the tax form number
     303              :            and location on that tax form which corresponds to this
     304              :            gnucash account. For the US Income Tax support in
     305              :            gnucash, each tax code that can be assigned to an
     306              :            account generally corresponds to a specific line number
     307              :            on a paper form and each form has a unique
     308              :            identification (e.g., Form 1040, Schedule A). */
     309            0 :         return (sub_acct_tax_number == 0) ? NULL :
     310            0 :                g_strdup_printf (_("(Tax-related subaccounts: %d)"),
     311              :                                 sub_acct_tax_number);
     312              :     }
     313              :     else
     314            0 :         return NULL;
     315              : }
        

Generated by: LCOV version 2.0-1