37 #include <glib/gi18n.h>
40 #include <glib/gstdio.h>
44 #include "gnc-gui-query.h"
46 #include "gncVendorP.h"
51 #include "gnc-exp-parser.h"
56 #include "gncIDSearch.h"
58 #include "dialog-bi-import-helper.h"
63 #include "business/business-gnome/dialog-invoice.h"
64 #include "business/business-gnome/business-gnome-utils.h"
72 #define FILL_IN_HELPER(match_name,column) \
73 temp = g_match_info_fetch_named (match_info, match_name); \
77 gtk_list_store_set (store, &iter, column, temp, -1); \
84 gnc_bi_import_read_file (
const gchar * filename,
const gchar * parser_regexp,
85 GtkListStore * store, guint max_rows,
94 gchar *line_utf8, *temp;
95 GMatchInfo *match_info;
102 f = g_fopen (filename,
"rt");
106 return RESULT_OPEN_FAILED;
111 stats = &stats_fallback;
116 g_regex_new (parser_regexp, G_REGEX_EXTENDED | G_REGEX_OPTIMIZE | G_REGEX_DUPNAMES, 0, &err);
122 errmsg = g_strdup_printf (_(
"Error in regular expression '%s':\n%s"),
123 parser_regexp, err->message);
127 dialog = gtk_message_dialog_new (NULL,
130 GTK_BUTTONS_OK,
"%s", errmsg);
131 gtk_dialog_run (GTK_DIALOG (dialog));
132 gtk_widget_destroy (dialog);
137 return RESULT_ERROR_IN_REGEXP;
141 stats->n_imported = 0;
142 stats->n_ignored = 0;
143 stats->ignored_lines = g_string_new (NULL);
144 #define buffer_size 1000
145 line = g_malloc0 (buffer_size);
148 || (stats->n_imported + stats->n_ignored < max_rows)))
152 if (!fgets (line, buffer_size, f))
156 if ((l > 0) && (line[l - 1] ==
'\n'))
160 line_utf8 = g_locale_to_utf8 (line, -1, NULL, NULL, NULL);
164 if (g_regex_match (regexpat, line_utf8, 0, &match_info))
170 gtk_list_store_append (store, &iter);
171 FILL_IN_HELPER (
"id", ID);
172 FILL_IN_HELPER (
"date_opened", DATE_OPENED);
173 FILL_IN_HELPER (
"owner_id", OWNER_ID);
174 FILL_IN_HELPER (
"billing_id", BILLING_ID);
175 FILL_IN_HELPER (
"notes", NOTES);
177 FILL_IN_HELPER (
"date", DATE);
178 FILL_IN_HELPER (
"desc", DESC);
179 FILL_IN_HELPER (
"action", ACTION);
180 FILL_IN_HELPER (
"account", ACCOUNT);
181 FILL_IN_HELPER (
"quantity", QUANTITY);
182 FILL_IN_HELPER (
"price", PRICE);
183 FILL_IN_HELPER (
"disc_type", DISC_TYPE);
184 FILL_IN_HELPER (
"disc_how", DISC_HOW);
185 FILL_IN_HELPER (
"discount", DISCOUNT);
186 FILL_IN_HELPER (
"taxable", TAXABLE);
187 FILL_IN_HELPER (
"taxincluded", TAXINCLUDED);
188 FILL_IN_HELPER (
"tax_table", TAX_TABLE);
190 FILL_IN_HELPER (
"date_posted", DATE_POSTED);
191 FILL_IN_HELPER (
"due_date", DUE_DATE);
192 FILL_IN_HELPER (
"account_posted", ACCOUNT_POSTED);
193 FILL_IN_HELPER (
"memo_posted", MEMO_POSTED);
194 FILL_IN_HELPER (
"accu_splits", ACCU_SPLITS);
200 g_string_append (stats->ignored_lines, line_utf8);
201 g_string_append_c (stats->ignored_lines,
'\n');
204 g_match_info_free (match_info);
212 g_regex_unref (regexpat);
216 if (stats == &stats_fallback)
218 g_string_free (stats->ignored_lines, TRUE);
232 GString * info, gchar *type)
235 gboolean valid, row_deleted, row_fixed;
236 gchar *id, *date_opened, *date_posted, *due_date, *owner_id, *date, *quantity, *price;
237 GString *prev_id, *prev_date_opened, *prev_date_posted, *prev_owner_id, *prev_date;
245 DEBUG(
"date_format_string: %s",date_format_string);
256 prev_id = g_string_new (
"");
257 prev_date_opened = g_string_new (
"");
258 prev_date_posted = g_string_new (
"");
259 prev_owner_id = g_string_new (
"");
260 prev_date = g_string_new (
"");
262 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
269 gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
271 DATE_OPENED, &date_opened,
272 DATE_POSTED, &date_posted,
276 QUANTITY, &quantity, PRICE, &price, -1);
278 if (strlen (price) == 0)
282 valid = gtk_list_store_remove (store, &iter);
284 g_string_append_printf (info,
285 _(
"ROW %d DELETED, PRICE_NOT_SET: id=%s\n"),
289 else if (strlen (quantity) == 0)
293 valid = gtk_list_store_remove (store, &iter);
295 g_string_append_printf (info, _(
"ROW %d DELETED, QTY_NOT_SET: id=%s\n"),
300 if (strlen (
id) == 0)
303 if (prev_id->len == 0)
306 valid = gtk_list_store_remove (store, &iter);
308 g_string_append_printf (info,
309 _(
"ROW %d DELETED, ID_NOT_SET\n"), row);
314 gtk_list_store_set (store, &iter, ID, prev_id->str, -1);
321 g_string_assign (prev_id,
id);
323 g_string_assign (prev_date_opened,
"");
324 g_string_assign (prev_date_posted,
"");
325 g_string_assign (prev_owner_id,
"");
326 g_string_assign (prev_date,
"");
334 if(!isDateValid(date_opened))
336 if (prev_date_opened->len == 0)
341 g_date_clear (&date, 1);
343 g_date_strftime (temp, 20, date_format_string, &date);
344 g_string_assign (prev_date_opened, temp);
347 gtk_list_store_set (store, &iter, DATE_OPENED,
348 prev_date_opened->str, -1);
354 g_string_assign (prev_date_opened, date_opened);
359 if(!isDateValid(date_posted))
361 if (prev_date_posted->len == 0)
368 gtk_list_store_set (store, &iter, DATE_POSTED,
369 prev_date_posted->str, -1);
376 g_string_assign (prev_date_posted, date_posted);
392 if (strlen (quantity) == 0)
395 gtk_list_store_set (store, &iter, QUANTITY,
"1", -1);
402 if (strlen (owner_id) == 0)
404 if (prev_owner_id->len == 0)
407 valid = gtk_list_store_remove (store, &iter);
409 g_string_append_printf (info,
410 _(
"ROW %d DELETED, OWNER_NOT_SET: id=%s\n"),
415 gtk_list_store_set (store, &iter, owner_id,
416 prev_owner_id->str, -1);
423 g_string_assign (prev_owner_id, owner_id);
425 if (g_ascii_strcasecmp (type,
"BILL") == 0)
428 if (!gnc_search_vendor_on_id
429 (gnc_get_current_book (), prev_owner_id->str))
432 valid = gtk_list_store_remove (store, &iter);
434 g_string_append_printf (info,
435 _(
"ROW %d DELETED, VENDOR_DOES_NOT_EXIST: id=%s\n"),
439 else if (g_ascii_strcasecmp (type,
"INVOICE") == 0)
442 if (!gnc_search_customer_on_id
443 (gnc_get_current_book (), prev_owner_id->str))
446 valid = gtk_list_store_remove (store, &iter);
448 g_string_append_printf (info,
449 _(
"ROW %d DELETED, CUSTOMER_DOES_NOT_EXIST: id=%s\n"),
458 g_free (date_opened);
459 g_free (date_posted);
468 g_string_assign (prev_id,
"");
469 g_string_assign (prev_date_opened,
"");
470 g_string_assign (prev_date_posted,
"");
471 g_string_assign (prev_owner_id,
"");
472 g_string_assign (prev_date,
"");
478 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
484 g_string_free (prev_id, TRUE);
485 g_string_free (prev_date_opened, TRUE);
486 g_string_free (prev_date_posted, TRUE);
487 g_string_free (prev_owner_id, TRUE);
488 g_string_free (prev_date, TRUE);
490 if (info && (info->len > 0))
492 g_string_prepend (info,
"\n\n");
493 g_string_prepend (info, _(
"These rows were deleted:"));
507 gnc_bi_import_create_bis (GtkListStore * store,
QofBook * book,
508 guint * n_invoices_created,
509 guint * n_invoices_updated,
510 gchar * type, gchar * open_mode, GString * info)
514 gchar *id, *date_opened, *owner_id, *billing_id, *notes;
515 gchar *date, *desc, *action, *account, *quantity, *price, *disc_type,
516 *disc_how, *discount, *taxable, *taxincluded, *tax_table;
517 gchar *date_posted, *due_date, *account_posted, *memo_posted,
522 gint day, month, year;
526 enum update {YES = GTK_RESPONSE_YES, NO = GTK_RESPONSE_NO} update;
530 gchar *new_id = NULL;
535 g_return_if_fail (store && book);
537 g_return_if_fail ((g_ascii_strcasecmp (type,
"INVOICE") == 0) ||
538 (g_ascii_strcasecmp (type,
"BILL") == 0));
541 if (!n_invoices_created)
542 n_invoices_created = &dummy;
543 if (!n_invoices_updated)
544 n_invoices_updated = &dummy;
545 *n_invoices_created = 0;
546 *n_invoices_updated = 0;
551 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
555 gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
557 DATE_OPENED, &date_opened,
558 DATE_POSTED, &date_posted,
560 ACCOUNT_POSTED, &account_posted,
561 MEMO_POSTED, &memo_posted,
562 ACCU_SPLITS, &accumulatesplits,
564 BILLING_ID, &billing_id,
572 DISC_TYPE, &disc_type,
576 TAXINCLUDED, &taxincluded,
577 TAX_TABLE, &tax_table, -1);
586 if (g_ascii_strcasecmp (type,
"BILL") == 0)
587 invoice = gnc_search_bill_on_id (book,
id);
588 else if (g_ascii_strcasecmp (type,
"INVOICE") == 0)
589 invoice = gnc_search_invoice_on_id (book,
id);
590 DEBUG(
"Existing %s ID: %s\n", type, gncInvoiceGetID(invoice));
595 DEBUG(
"Creating a new : %s\n", type );
597 invoice = gncInvoiceCreate (book);
600 gncInvoiceBeginEdit (invoice);
601 gncInvoiceSetID (invoice,
id);
603 if (g_ascii_strcasecmp (type,
"BILL") == 0)
604 gncOwnerInitVendor (owner,
605 gnc_search_vendor_on_id (book, owner_id));
606 else if (g_ascii_strcasecmp (type,
"INVOICE") == 0)
607 gncOwnerInitCustomer (owner,
608 gnc_search_customer_on_id (book, owner_id));
609 gncInvoiceSetOwner (invoice, owner);
610 gncInvoiceSetCurrency (invoice, gncOwnerGetCurrency (owner));
611 if (strlen (date_opened) != 0)
615 gncInvoiceSetDateOpened (invoice,
623 gncInvoiceSetDateOpened (invoice, now_timespec);
625 gncInvoiceSetBillingID (invoice, billing_id ? billing_id :
"");
626 gncInvoiceSetNotes (invoice, notes ? notes :
"");
627 gncInvoiceSetActive (invoice, TRUE);
629 (*n_invoices_created)++;
633 if (g_ascii_strcasecmp(open_mode,
"ALL") == 0
634 || (g_ascii_strcasecmp(open_mode,
"NOT_POSTED") == 0
635 && strlen(date_posted) == 0))
637 iw = gnc_ui_invoice_edit (invoice);
640 gncInvoiceCommitEdit (invoice);
648 if (gncInvoiceIsPosted (invoice))
651 gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
656 dialog = gtk_message_dialog_new (NULL,
661 _(
"Are you sure you have bills/invoices to update?"));
662 update = gtk_dialog_run (GTK_DIALOG (dialog));
663 gtk_widget_destroy (dialog);
668 g_free (date_opened);
682 g_free (taxincluded);
684 g_free (date_posted);
686 g_free (account_posted);
687 g_free (memo_posted);
688 g_free (accumulatesplits);
692 (*n_invoices_updated)++;
697 entry = gncEntryCreate (book);
698 gncEntryBeginEdit(entry);
699 currency = gncInvoiceGetCurrency(invoice);
704 GDate *date = g_date_new_dmy(day, month, year);
709 gncEntrySetDateEntered (entry, today);
710 gncEntrySetDescription (entry, desc);
711 gncEntrySetAction (entry, action);
713 gnc_exp_parser_parse (quantity, &value, NULL);
718 if (g_ascii_strcasecmp (type,
"BILL") == 0)
720 gncEntrySetBillAccount (entry, acc);
721 gnc_exp_parser_parse (price, &value, NULL);
722 gncEntrySetBillPrice (entry, value);
723 gncEntrySetBillTaxable (entry, text2bool (taxable));
724 gncEntrySetBillTaxIncluded (entry, text2bool (taxincluded));
725 gncEntrySetBillTaxTable (entry, gncTaxTableLookupByName (book, tax_table));
726 gncEntryCommitEdit(entry);
729 else if (g_ascii_strcasecmp (type,
"INVOICE") == 0)
731 gncEntrySetNotes (entry, notes);
732 gncEntrySetInvAccount (entry, acc);
733 gnc_exp_parser_parse (price, &value, NULL);
734 gncEntrySetInvPrice (entry, value);
735 gncEntrySetInvTaxable (entry, text2bool (taxable));
736 gncEntrySetInvTaxIncluded (entry, text2bool (taxincluded));
737 gncEntrySetInvTaxTable (entry, gncTaxTableLookupByName (book, tax_table));
738 gnc_exp_parser_parse (discount, &value, NULL);
739 gncEntrySetInvDiscount (entry, value);
740 gncEntrySetInvDiscountType (entry, text2disc_type (disc_type));
741 gncEntrySetInvDiscountHow (entry, text2disc_how (disc_how));
742 gncEntryCommitEdit(entry);
743 gncInvoiceAddEntry (invoice, entry);
745 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
751 gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, ID, &new_id, -1);
752 if (g_strcmp0 (
id, new_id) != 0)
761 if (g_ascii_strcasecmp (type,
"INVOICE") == 0)
771 (gnc_get_current_root_account (), account_posted);
774 text2bool (accumulatesplits),
785 g_free (date_opened);
799 g_free (taxincluded);
801 g_free (date_posted);
803 g_free (account_posted);
804 g_free (memo_posted);
805 g_free (accumulatesplits);
void gnc_gdate_set_today(GDate *gd)
utility functions for the GnuCash UI
core import functions for invoice import plugin
int gnc_commodity_get_fraction(const gnc_commodity *cm)
void gncEntrySetQuantity(GncEntry *entry, gnc_numeric quantity)
utility functions for the GnuCash UI
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
#define DEBUG(format, args...)
Use a 64-bit unsigned int timespec.
Timespec gnc_dmy2timespec(gint day, gint month, gint year)
GncPluginPage * gnc_plugin_page_invoice_new(InvoiceWindow *iw)
void gncBillAddEntry(GncInvoice *bill, GncEntry *entry)
const gchar * qof_date_format_get_string(QofDateFormat df)
void gncEntrySetDateGDate(GncEntry *entry, const GDate *date)
Transaction * gncInvoicePostToAccount(GncInvoice *invoice, Account *acc, Timespec *post_date, Timespec *due_date, const char *memo, gboolean accumulatesplits, gboolean autopay)
Generic api to store and retrieve preferences.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
gboolean qof_scan_date(const char *buff, int *day, int *month, int *year)
QofDateFormat qof_date_format_get(void)
time64 gnc_time(time64 *tbuf)
get the current local time
Business Entry Interface.
Account * gnc_account_lookup_for_register(const Account *base_account, const gchar *name)
GncOwner * gncOwnerNew(void)
const gchar * QofLogModule
void timespecFromTime64(Timespec *ts, time64 t)