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 : }
|