GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-locale-tax.c
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
42void
43gnc_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 const char *thislocale = gnc_locale_name();
54 gboolean is_de_DE = (strncmp(thislocale, "de_DE", 5) == 0);
55# endif /* G_OS_WIN32 */
56 if (is_de_DE)
57 scm_c_use_module("gnucash locale de_DE tax");
58 else
59 scm_c_use_module("gnucash locale us tax");
60}
61
62/* Caller is responsible for g_free'ing returned memory */
63char *
64gnc_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 gboolean tax_related = FALSE;
70 const char *code;
71
72 if (!account)
73 return NULL;
74
75 tax_related = xaccAccountGetTaxRelated (account);
76 code = xaccAccountGetTaxUSCode (account);
77
78 if (!code)
79 {
80 if (!tax_related)
81 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 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 gchar *num_code = NULL;
102 const gchar *prefix = "N";
103 gchar *return_string = NULL;
104
105 tax_type = gnc_get_current_book_tax_type ();
106 if (tax_type == NULL || (g_strcmp0 (tax_type, "") == 0))
107 return g_strdup (_("Tax entity type not specified"));
108
109 atype = xaccAccountGetType (account);
110 tax_entity_type = scm_from_utf8_string (tax_type);
111
112 if (get_form == SCM_UNDEFINED)
113 {
114 /* load the tax info */
115 gnc_locale_tax_init ();
116
117 get_form = scm_c_eval_string
118 ("(false-if-exception gnc:txf-get-form)");
119 get_desc = scm_c_eval_string
120 ("(false-if-exception gnc:txf-get-description)");
121 }
122
123 g_return_val_if_fail (scm_is_procedure (get_form), NULL);
124 g_return_val_if_fail (scm_is_procedure (get_desc), NULL);
125
126 category = scm_c_eval_string (atype == ACCT_TYPE_INCOME ?
127 "txf-income-categories" :
128 (atype == ACCT_TYPE_EXPENSE ?
129 "txf-expense-categories" :
130 (((atype == ACCT_TYPE_BANK) ||
131 (atype == ACCT_TYPE_CASH) ||
132 (atype == ACCT_TYPE_ASSET) ||
133 (atype == ACCT_TYPE_STOCK) ||
134 (atype == ACCT_TYPE_MUTUAL) ||
135 (atype == ACCT_TYPE_RECEIVABLE)) ?
136 "txf-asset-categories" :
137 (((atype == ACCT_TYPE_CREDIT) ||
138 (atype == ACCT_TYPE_LIABILITY) ||
139 (atype == ACCT_TYPE_EQUITY) ||
140 (atype == ACCT_TYPE_PAYABLE)) ?
141 "txf-liab-eq-categories" : ""))));
142
143 if (g_str_has_prefix (code, prefix))
144 {
145 const gchar *num_code_tmp;
146 num_code_tmp = g_strdup (code);
147 num_code_tmp++; /* to lose the leading N */
148 num_code = g_strdup (num_code_tmp);
149 num_code_tmp--;
150 g_free ((gpointer *) num_code_tmp);
151 }
152 else
153 {
154 num_code = g_strdup (code);
155 }
156
157 if (category == SCM_UNDEFINED)
158 {
159 if (tax_related)
160 return_string = g_strdup_printf
161 (_("Tax type %s: invalid code %s for account type"),
162 tax_type, num_code);
163 else
164 return_string = g_strdup_printf
165 (_("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 code_scm = scm_from_locale_symbol (code);
173 form_scm = scm_call_3 (get_form, category, code_scm, tax_entity_type);
174 if (!scm_is_string (form_scm))
175 {
176 if (tax_related)
177 return_string = g_strdup_printf
178 (_("Invalid code %s for tax type %s"),
179 num_code, tax_type);
180 else
181 return_string = g_strdup_printf
182 (_("Not tax-related; invalid code %s for tax type %s"),
183 num_code, tax_type);
184 }
185 else
186 {
187 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 form = scm_to_utf8_stringn (form_scm, NULL);
196 if (!form)
197 {
198 if (tax_related)
199 return_string = g_strdup_printf
200 (_("No form: code %s, tax type %s"), num_code,
201 tax_type);
202 else
203 return_string = g_strdup_printf
204 (_("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 scm_dynwind_begin (0);
214 scm_dynwind_free (form);
215 desc_scm = scm_call_3 (get_desc, category, code_scm,
216 tax_entity_type);
217 if (!scm_is_string (desc_scm))
218 {
219 if (tax_related)
220 return_string = g_strdup_printf
221 (_("No description: form %s, code %s, tax type %s"),
222 form, num_code, tax_type);
223 else
224 return_string = g_strdup_printf
225 (_("Not tax-related; no description: form %s, code %s, tax type %s"),
226 form, num_code, tax_type);
227 }
228 else
229 {
230 gchar *desc = NULL;
231 desc = gnc_scm_to_utf8_string (desc_scm);
232 if (!desc)
233 {
234 if (tax_related)
235 return_string = g_strdup_printf
236 (_("No description: form %s, code %s, tax type %s"),
237 form, num_code, tax_type);
238 else
239 return_string = g_strdup_printf
240 (_("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 gchar *copy_txt = NULL;
247 copy_number = xaccAccountGetTaxUSCopyNumber (account);
248 copy_txt = (copy_number == 1) ?
249 g_strdup ("") :
250 g_strdup_printf ("(%d)",
251 (gint) copy_number);
252 if (tax_related)
253 {
254 if (g_strcmp0 (form, "") == 0)
255 return_string = g_strdup_printf ("%s", desc);
256 else
257 return_string = g_strdup_printf ("%s%s: %s",
258 form, copy_txt, desc);
259 }
260 else
261 {
262 return_string = g_strdup_printf
263 (_("Not tax-related; %s%s: %s (code %s, tax type %s)"),
264 form, copy_txt, desc, num_code, tax_type);
265 }
266 g_free (copy_txt);
267 }
268 g_free (desc);
269 }
270 scm_dynwind_end ();
271 }
272 }
273 }
274 g_free (num_code);
275 return return_string;
276 }
277}
278
279/* Caller is responsible for g_free'ing returned memory */
280char *
281gnc_ui_account_get_tax_info_sub_acct_string (const Account *account)
282{
283 GList *descendant, *account_descendants;
284
285 if (!account)
286 return NULL;
287
288 account_descendants = gnc_account_get_descendants (account);
289 if (account_descendants)
290 {
291 gint sub_acct_tax_number = 0;
292 for (descendant = account_descendants; descendant;
293 descendant = g_list_next(descendant))
294 {
295 if (xaccAccountGetTaxRelated (descendant->data))
296 sub_acct_tax_number++;
297 }
298 g_list_free (account_descendants);
299 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 return (sub_acct_tax_number == 0) ? NULL :
310 g_strdup_printf (_("(Tax-related subaccounts: %d)"),
311 sub_acct_tax_number);
312 }
313 else
314 return NULL;
315}
Account handling public routines.
utility functions for the GnuCash UI
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed.
Definition Account.h:103
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
Definition Account.cpp:3267
GList * gnc_account_get_descendants(const Account *account)
This routine returns a flat list of all of the accounts that are descendants of the specified account...
Definition Account.cpp:3044
@ ACCT_TYPE_MUTUAL
Mutual Fund accounts will typically be shown in registers which show three columns: price,...
Definition Account.h:125
@ ACCT_TYPE_EXPENSE
Expense accounts are used to denote expenses.
Definition Account.h:143
@ ACCT_TYPE_BANK
The bank account type denotes a savings or checking account held at a bank.
Definition Account.h:107
@ ACCT_TYPE_PAYABLE
A/P account type.
Definition Account.h:151
@ ACCT_TYPE_ASSET
asset (and liability) accounts indicate generic, generalized accounts that are none of the above.
Definition Account.h:116
@ ACCT_TYPE_RECEIVABLE
A/R account type.
Definition Account.h:149
@ ACCT_TYPE_CASH
The cash account type is used to denote a shoe-box or pillowcase stuffed with * cash.
Definition Account.h:110
@ ACCT_TYPE_LIABILITY
liability (and asset) accounts indicate generic, generalized accounts that are none of the above.
Definition Account.h:119
@ ACCT_TYPE_EQUITY
Equity account is used to balance the balance sheet.
Definition Account.h:146
@ ACCT_TYPE_CREDIT
The Credit card account is used to denote credit (e.g.
Definition Account.h:113
@ ACCT_TYPE_STOCK
Stock accounts will typically be shown in registers which show three columns: price,...
Definition Account.h:122
gint64 xaccAccountGetTaxUSCopyNumber(const Account *acc)
Returns copy_number stored in KVP; if KVP doesn't exist or copy_number is zero, returns 1.
Definition Account.cpp:4071
gboolean xaccAccountGetTaxRelated(const Account *acc)
DOCUMENT ME!
Definition Account.cpp:4035
const char * xaccAccountGetTaxUSCode(const Account *acc)
DOCUMENT ME!
Definition Account.cpp:4047
STRUCTS.