GnuCash c935c2f+
Loading...
Searching...
No Matches
dialog-customer-import.c
1/*
2 * customer_import.c --
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, contact:
16 *
17 * Free Software Foundation Voice: +1-617-542-5942
18 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
19 * Boston, MA 02110-1301, USA gnu@gnu.org
20 */
21
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32#include <glib/gi18n.h>
33#include <regex.h>
34#include <glib.h>
35#include <glib/gstdio.h>
36
37#include "gnc-glib-utils.h"
38#include "gnc-ui.h"
39#include "gnc-ui-util.h"
40#include "gnc-gui-query.h"
41#include "gncAddress.h"
42#include "gncCustomerP.h"
43#include "gncVendorP.h"
44// query
45#include "Query.h"
46#include "qof.h"
47#include "gncIDSearch.h"
48
50
51// private prototypes
52//static GncCustomer *gnc_customer_import_searchCustomer (const gchar *id, QofBook *book);
53
54
55
56// perl regular expressions are available
57
58// this helper macro takes a regexp match and fills the model
59#define FILL_IN_HELPER(match_name,column) \
60 temp = g_match_info_fetch_named (match_info, match_name); \
61 if (temp) \
62 { \
63 g_strstrip( temp ); \
64 gtk_list_store_set (store, &iter, column, temp, -1); \
65 g_free (temp); \
66 }
67customer_import_result
68gnc_customer_import_read_file (const gchar *filename, const gchar *parser_regexp, GtkListStore *store, guint max_rows, customer_import_stats *stats)
69{
70 // some statistics
71 customer_import_stats stats_fallback;
72 FILE *f;
73
74 // regexp
75 char *line;
76 gchar *line_utf8, *temp;
77 GMatchInfo *match_info;
78 GError *err;
79 GRegex *regexpat;
80
81 // model
82 GtkTreeIter iter;
83
84 f = g_fopen( filename, "rt" );
85 if (!f)
86 {
87 //gnc_error_dialog (NULL, _("File %s cannot be opened."), filename );
88 return CI_RESULT_OPEN_FAILED;
89 }
90
91 // set up statistics
92 if (!stats)
93 stats = &stats_fallback;
94
95 // compile the regular expression and check for errors
96 err = NULL;
97 regexpat = g_regex_new (parser_regexp, G_REGEX_EXTENDED | G_REGEX_OPTIMIZE | G_REGEX_DUPNAMES, 0, &err);
98 if (err != NULL)
99 {
100 GtkWidget *dialog;
101 gchar *errmsg;
102
103 errmsg = g_strdup_printf (_("Error in regular expression '%s':\n%s"),
104 parser_regexp, err->message);
105 g_error_free (err);
106 err = NULL;
107
108 dialog = gtk_message_dialog_new (NULL,
109 GTK_DIALOG_MODAL,
110 GTK_MESSAGE_ERROR,
111 GTK_BUTTONS_OK,
112 "%s", errmsg);
113 gtk_dialog_run (GTK_DIALOG (dialog));
114 gtk_widget_destroy(dialog);
115 g_free (errmsg);
116 errmsg = 0;
117
118 fclose (f);
119 return CI_RESULT_ERROR_IN_REGEXP;
120 }
121
122 // start the import
123 stats->n_imported = 0;
124 stats->n_ignored = 0;
125 stats->ignored_lines = g_string_new (NULL);
126#define buffer_size 1000
127 line = g_malloc0 (buffer_size);
128 while (!feof (f) && ((max_rows == 0) || (stats->n_imported + stats->n_ignored < max_rows)))
129 {
130 int l;
131 // read one line
132 if (!fgets (line, buffer_size, f))
133 break; // eof
134 // now strip the '\n' from the end of the line
135 l = strlen (line);
136 if ((l > 0) && (line[l - 1] == '\n'))
137 line[l - 1] = 0;
138
139 // if the line doesn't conform to UTF-8, try a default charcter set
140 // conversion based on locale
141 if (g_utf8_validate(line, -1, NULL))
142 line_utf8 = line;
143 else
144 line_utf8 = g_locale_to_utf8 (line, -1, NULL, NULL, NULL);
145
146 // Remove the potential XML-prohibited codepoints from the UTF-8 compliant string
147 gnc_utf8_strip_invalid(line_utf8);
148
149 // parse the line
150 match_info = NULL; // it seems, that in contrast to documentation, match_info is not always set -> g_match_info_free will segfault
151 if (g_regex_match (regexpat, line_utf8, 0, &match_info))
152 {
153 // match found
154 stats->n_imported++;
155
156 // fill in the values
157 gtk_list_store_append (store, &iter);
158 FILL_IN_HELPER ("id", CI_ID);
159 FILL_IN_HELPER ("company", CI_COMPANY);
160 FILL_IN_HELPER ("name", CI_NAME);
161 FILL_IN_HELPER ("addr1", CI_ADDR1);
162 FILL_IN_HELPER ("addr2", CI_ADDR2);
163 FILL_IN_HELPER ("addr3", CI_ADDR3);
164 FILL_IN_HELPER ("addr4", CI_ADDR4);
165 FILL_IN_HELPER ("phone", CI_PHONE);
166 FILL_IN_HELPER ("fax", CI_FAX);
167 FILL_IN_HELPER ("email", CI_EMAIL);
168 FILL_IN_HELPER ("notes", CI_NOTES);
169 FILL_IN_HELPER ("shipname", CI_SHIPNAME);
170 FILL_IN_HELPER ("shipaddr1", CI_SHIPADDR1);
171 FILL_IN_HELPER ("shipaddr2", CI_SHIPADDR2);
172 FILL_IN_HELPER ("shipaddr3", CI_SHIPADDR3);
173 FILL_IN_HELPER ("shipaddr4", CI_SHIPADDR4);
174 FILL_IN_HELPER ("shipphone", CI_SHIPPHONE);
175 FILL_IN_HELPER ("shipfax", CI_SHIPFAX);
176 FILL_IN_HELPER ("shipemail", CI_SHIPEMAIL);
177 }
178 else
179 {
180 // ignore line
181 stats->n_ignored++;
182 g_string_append (stats->ignored_lines, line_utf8);
183 g_string_append_c (stats->ignored_lines, '\n');
184 }
185
186 g_match_info_free (match_info);
187 if (line_utf8 != line)
188 g_free (line_utf8);
189 }
190 g_free (line);
191 line = 0;
192
193 g_regex_unref (regexpat);
194 regexpat = 0;
195 fclose (f);
196
197 if (stats == &stats_fallback)
198 // stats are not requested -> free the string
199 g_string_free (stats->ignored_lines, TRUE);
200
201 return CI_RESULT_OK;
202}
203
204
205
206void
207gnc_customer_import_fix_customers (GtkListStore *store, guint *fixed, guint *deleted, gchar * type)
208{
209 GtkTreeIter iter;
210 gboolean valid;
211 gchar *company, *name, *addr1, *addr2, *addr3, *addr4;
212 guint dummy;
213
214 // allow the call to this function with only GtkListeStore* specified
215 if (!fixed)
216 fixed = &dummy;
217 if (!deleted)
218 deleted = &dummy;
219
220 *fixed = 0;
221 *deleted = 0;
222
223 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter);
224 while (valid)
225 {
226 // Walk through the list, reading each row
227 gtk_tree_model_get (GTK_TREE_MODEL(store), &iter,
228 CI_COMPANY, &company,
229 CI_NAME, &name,
230 CI_ADDR1, &addr1,
231 CI_ADDR2, &addr2,
232 CI_ADDR3, &addr3,
233 CI_ADDR4, &addr4,
234 -1);
235
236 // Company name is mandatory.
237 // If not provided, default the company name to the value of the field name.
238 if (strlen(company) == 0)
239 {
240 //But if the field name is also blank, then delete the row.
241 if (strlen(name) == 0)
242 {
243 // no fix possible -> delete row
244 valid = gtk_list_store_remove (store, &iter);
245 (*deleted)++;
246 continue;
247 }
248 else
249 {
250 // fix possible -> copy name to company
251 gtk_list_store_set (store, &iter, CI_COMPANY, name, -1);
252 (*fixed)++;
253 }
254 }
255
256
257 g_free (company);
258 g_free (name);
259 g_free (addr1);
260 g_free (addr2);
261 g_free (addr3);
262 g_free (addr4);
263
264 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
265 }
266}
267
268void
269gnc_customer_import_create_customers (GtkListStore *store, QofBook *book, guint *n_customers_created, guint *n_customers_updated, gchar * type)
270{
271 gboolean valid;
272 GtkTreeIter iter;
273 gchar *id, *company, *name, *addr1, *addr2, *addr3, *addr4, *phone, *fax, *email;
274 gchar *notes, *shipname, *shipaddr1, *shipaddr2, *shipaddr3, *shipaddr4, *shipphone, *shipfax, *shipemail;
275 GncAddress *addr, *shipaddr;
276 guint dummy;
277 GncCustomer *customer;
278 GncVendor *vendor;
279 customer = NULL;
280 vendor = NULL;
281 addr = NULL;
282 shipaddr = NULL;
283 // these arguments are needed
284 g_return_if_fail (store && book);
285 printf("\nTYPE = %s\n", type);
286
287 // allow to call this function without statistics
288 if (!n_customers_created)
289 n_customers_created = &dummy;
290 if (!n_customers_updated)
291 n_customers_updated = &dummy;
292 *n_customers_created = 0;
293 *n_customers_updated = 0;
294
295 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter);
296 while (valid)
297 {
298 // Walk through the list, reading each row
299 gtk_tree_model_get (GTK_TREE_MODEL(store), &iter,
300 CI_ID, &id,
301 CI_COMPANY, &company,
302 CI_NAME, &name,
303 CI_ADDR1, &addr1,
304 CI_ADDR2, &addr2,
305 CI_ADDR3, &addr3,
306 CI_ADDR4, &addr4,
307 CI_PHONE, &phone,
308 CI_FAX, &fax,
309 CI_EMAIL, &email,
310 CI_NOTES, &notes,
311 CI_SHIPNAME, &shipname,
312 CI_SHIPADDR1, &shipaddr1,
313 CI_SHIPADDR2, &shipaddr2,
314 CI_SHIPADDR3, &shipaddr3,
315 CI_SHIPADDR4, &shipaddr4,
316 CI_SHIPPHONE, &shipphone,
317 CI_SHIPFAX, &shipfax,
318 CI_SHIPEMAIL, &shipemail,
319 -1);
320
321 // Set the customer id if one has not been chosen
322 if (strlen (id) == 0)
323 {
324 if (g_ascii_strcasecmp (type, "CUSTOMER") == 0) id = gncCustomerNextID (book);
325 else if (g_ascii_strcasecmp (type, "VENDOR") == 0)id = gncVendorNextID (book);
326 //printf("ASSIGNED ID = %s\n",id);
327 }
328
329 // Now save it off after checking if a vend/cust number doesn't already exist
330 {
331 if (g_ascii_strcasecmp (type, "CUSTOMER") == 0)
332 {
333 customer = gnc_search_customer_on_id (book, id);
334 if (!customer)
335 {
336 customer = gncCustomerCreate( book );
337 gncCustomerSetCurrency( customer, gnc_default_currency() );
338 (*n_customers_created)++;
339 }
340 else (*n_customers_updated)++;
341 }
342 else if (g_ascii_strcasecmp (type, "VENDOR") == 0)
343 {
344 vendor = gnc_search_vendor_on_id (book, id);
345 if ( !vendor)
346 {
347 vendor = gncVendorCreate( book );
348 gncVendorSetCurrency( vendor, gnc_default_currency() );
349 (*n_customers_created)++;
350 }
351 else (*n_customers_updated)++;
352 }
353
354 if (g_ascii_strcasecmp (type, "CUSTOMER") == 0)
355 {
356 gncCustomerBeginEdit (customer);
357 gncCustomerSetID (customer, id);
358 gncCustomerSetName (customer, company);
359 gncCustomerSetNotes (customer, notes);
360 addr = gncCustomerGetAddr (customer);
361 shipaddr = gncCustomerGetShipAddr (customer);
362 }
363 else if (g_ascii_strcasecmp (type, "VENDOR") == 0)
364 {
365 gncVendorBeginEdit (vendor);
366 gncVendorSetID (vendor, id);
367 gncVendorSetName (vendor, company);
368 gncVendorSetNotes (vendor, notes);
369 addr = gncVendorGetAddr (vendor);
370 }
371 gncAddressSetName (addr, name);
372 gncAddressSetAddr1 (addr, addr1);
373 gncAddressSetAddr2 (addr, addr2);
374 gncAddressSetAddr3 (addr, addr3);
375 gncAddressSetAddr4 (addr, addr4);
376 gncAddressSetPhone (addr, phone);
377 gncAddressSetFax (addr, fax);
378 gncAddressSetEmail (addr, email);
379 if (g_ascii_strcasecmp (type, "CUSTOMER") == 0)
380 {
381 gncAddressSetName (shipaddr, shipname);
382 gncAddressSetAddr1 (shipaddr, shipaddr1);
383 gncAddressSetAddr2 (shipaddr, shipaddr2);
384 gncAddressSetAddr3 (shipaddr, shipaddr3);
385 gncAddressSetAddr4 (shipaddr, shipaddr4);
386 gncAddressSetPhone (shipaddr, shipphone);
387 gncAddressSetFax (shipaddr, shipfax);
388 gncAddressSetEmail (shipaddr, shipemail);
389 gncCustomerSetActive (customer, TRUE);
390 gncCustomerCommitEdit (customer);
391 }
392 else if (g_ascii_strcasecmp (type, "VENDOR") == 0)
393 {
394 gncVendorSetActive (vendor, TRUE);
395 gncVendorCommitEdit (vendor);
396 }
397 //printf("TYPE %s created with ID = %s.\n", type, id); // DEBUG
398 }
399
400 g_free (id);
401 g_free (company);
402 g_free (name);
403 g_free (addr1);
404 g_free (addr2);
405 g_free (addr3);
406 g_free (addr4);
407 g_free (phone);
408 g_free (fax);
409 g_free (email);
410 g_free (notes);
411 g_free (shipname);
412 g_free (shipaddr1);
413 g_free (shipaddr2);
414 g_free (shipaddr3);
415 g_free (shipaddr4);
416 g_free (shipphone);
417 g_free (shipfax);
418 g_free (shipemail);
419 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
420 }
421}
422
core import functions for customer import plugin
GLib helper routines.
utility functions for the GnuCash UI
an Address object
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
void gnc_utf8_strip_invalid(gchar *str)
Strip any non-UTF-8 characters from a string.
credit, discount and shipaddr are unique to GncCustomer id, name, notes, terms, addr,...
QofBook reference.
Definition qofbook-p.hpp:47