Branch data 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 : :
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 = setlocale(LC_ALL, NULL);
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 : 0 : 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 : : }
|