|
GnuCash 2.4.99
|
00001 /* 00002 * dialog-bi-import.c -- Invoice importer Core functions 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License as 00006 * published by the Free Software Foundation; either version 2 of 00007 * the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, contact: 00016 * 00017 * Free Software Foundation Voice: +1-617-542-5942 00018 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 00019 * Boston, MA 02110-1301, USA gnu@gnu.org 00020 */ 00021 00033 #ifdef HAVE_CONFIG_H 00034 #include "config.h" 00035 #endif 00036 00037 #ifndef HAVE_LOCALTIME_R 00038 #include "localtime_r.h" 00039 #endif 00040 00041 #include <glib/gi18n.h> 00042 #include <regex.h> 00043 #include <glib.h> 00044 #include <glib/gstdio.h> 00045 00046 #include "gnc-ui.h" 00047 #include "gnc-ui-util.h" 00048 #include "gnc-gui-query.h" 00049 #include "gncAddress.h" 00050 #include "gncVendorP.h" 00051 #include "gncVendor.h" 00052 #include "gncEntry.h" 00053 00054 #include "gnc-exp-parser.h" 00055 00056 // query 00057 #include "Query.h" 00058 #include "qof.h" 00059 #include "GNCId.h" 00060 #include "gncIDSearch.h" 00061 #include "dialog-bi-import.h" 00062 #include "dialog-bi-import-helper.h" 00063 00064 // To open the invoices for editing 00065 #include "business/business-gnome/gnc-plugin-page-invoice.h" 00066 #include "business/business-gnome/dialog-invoice.h" 00067 00068 00069 //#ifdef HAVE_GLIB_2_14 00070 // glib >= 2.14.0 00071 // perl regular expressions are available 00072 00073 // this helper macro takes a regexp match and fills the model 00074 #define FILL_IN_HELPER(match_name,column) \ 00075 temp = g_match_info_fetch_named (match_info, match_name); \ 00076 if (temp) \ 00077 { \ 00078 g_strstrip( temp ); \ 00079 gtk_list_store_set (store, &iter, column, temp, -1); \ 00080 g_free (temp); \ 00081 } 00082 00083 00084 bi_import_result 00085 gnc_bi_import_read_file (const gchar * filename, const gchar * parser_regexp, 00086 GtkListStore * store, guint max_rows, 00087 bi_import_stats * stats) 00088 { 00089 // some statistics 00090 bi_import_stats stats_fallback; 00091 FILE *f; 00092 00093 // regexp 00094 char *line; 00095 gchar *line_utf8, *temp; 00096 GMatchInfo *match_info; 00097 GError *err; 00098 GRegex *regexpat; 00099 00100 // model 00101 GtkTreeIter iter; 00102 00103 f = g_fopen (filename, "rt"); 00104 if (!f) 00105 { 00106 //gnc_error_dialog( 0, _("File %s cannot be opened."), filename ); 00107 return RESULT_OPEN_FAILED; 00108 } 00109 00110 // set up statistics 00111 if (!stats) 00112 stats = &stats_fallback; 00113 00114 // compile the regular expression and check for errors 00115 err = NULL; 00116 regexpat = 00117 g_regex_new (parser_regexp, G_REGEX_EXTENDED | G_REGEX_OPTIMIZE | G_REGEX_DUPNAMES, 0, &err); 00118 if (err != NULL) 00119 { 00120 GtkWidget *dialog; 00121 gchar *errmsg; 00122 00123 errmsg = g_strdup_printf (_("Error in regular expression '%s':\n%s"), 00124 parser_regexp, err->message); 00125 g_error_free (err); 00126 err = NULL; 00127 00128 dialog = gtk_message_dialog_new (NULL, 00129 GTK_DIALOG_MODAL, 00130 GTK_MESSAGE_ERROR, 00131 GTK_BUTTONS_OK, "%s", errmsg); 00132 gtk_dialog_run (GTK_DIALOG (dialog)); 00133 gtk_widget_destroy (dialog); 00134 g_free (errmsg); 00135 errmsg = 0; 00136 00137 fclose (f); 00138 return RESULT_ERROR_IN_REGEXP; 00139 } 00140 00141 // start the import 00142 stats->n_imported = 0; 00143 stats->n_ignored = 0; 00144 stats->ignored_lines = g_string_new (NULL); 00145 #define buffer_size 1000 00146 line = g_malloc0 (buffer_size); 00147 while (!feof (f) 00148 && ((max_rows == 0) 00149 || (stats->n_imported + stats->n_ignored < max_rows))) 00150 { 00151 int l; 00152 // read one line 00153 if (!fgets (line, buffer_size, f)) 00154 break; // eof 00155 // now strip the '\n' from the end of the line 00156 l = strlen (line); 00157 if ((l > 0) && (line[l - 1] == '\n')) 00158 line[l - 1] = 0; 00159 00160 // convert line from locale into utf8 00161 line_utf8 = g_locale_to_utf8 (line, -1, NULL, NULL, NULL); 00162 00163 // parse the line 00164 match_info = NULL; // it seems, that in contrast to documentation, match_info is not alsways set -> g_match_info_free will segfault 00165 if (g_regex_match (regexpat, line_utf8, 0, &match_info)) 00166 { 00167 // match found 00168 stats->n_imported++; 00169 00170 // fill in the values 00171 gtk_list_store_append (store, &iter); 00172 FILL_IN_HELPER ("id", ID); /* FIXME: Should "id" be translated? I don't think so. */ 00173 FILL_IN_HELPER ("date_opened", DATE_OPENED); 00174 FILL_IN_HELPER ("owner_id", OWNER_ID); 00175 FILL_IN_HELPER ("billing_id", BILLING_ID); 00176 FILL_IN_HELPER ("notes", NOTES); 00177 00178 FILL_IN_HELPER ("date", DATE); 00179 FILL_IN_HELPER ("desc", DESC); 00180 FILL_IN_HELPER ("action", ACTION); 00181 FILL_IN_HELPER ("account", ACCOUNT); 00182 FILL_IN_HELPER ("quantity", QUANTITY); 00183 FILL_IN_HELPER ("price", PRICE); 00184 FILL_IN_HELPER ("disc_type", DISC_TYPE); 00185 FILL_IN_HELPER ("disc_how", DISC_HOW); 00186 FILL_IN_HELPER ("discount", DISCOUNT); 00187 FILL_IN_HELPER ("taxable", TAXABLE); 00188 FILL_IN_HELPER ("taxincluded", TAXINCLUDED); 00189 FILL_IN_HELPER ("tax_table", TAX_TABLE); 00190 00191 FILL_IN_HELPER ("date_posted", DATE_POSTED); 00192 FILL_IN_HELPER ("due_date", DUE_DATE); 00193 FILL_IN_HELPER ("account_posted", ACCOUNT_POSTED); 00194 FILL_IN_HELPER ("memo_posted", MEMO_POSTED); 00195 FILL_IN_HELPER ("accu_splits", ACCU_SPLITS); 00196 } 00197 else 00198 { 00199 // ignore line 00200 stats->n_ignored++; 00201 g_string_append (stats->ignored_lines, line_utf8); 00202 g_string_append_c (stats->ignored_lines, '\n'); 00203 } 00204 00205 g_match_info_free (match_info); 00206 match_info = 0; 00207 g_free (line_utf8); 00208 line_utf8 = 0; 00209 } 00210 g_free (line); 00211 line = 0; 00212 00213 g_regex_unref (regexpat); 00214 regexpat = 0; 00215 fclose (f); 00216 00217 if (stats == &stats_fallback) 00218 // stats are not requested -> free the string 00219 g_string_free (stats->ignored_lines, TRUE); 00220 00221 return RESULT_OK; 00222 } 00223 00224 00231 void 00232 gnc_bi_import_fix_bis (GtkListStore * store, guint * fixed, guint * deleted, 00233 GString * info, gchar *type) 00234 { 00235 GtkTreeIter iter; 00236 gboolean valid, row_deleted, row_fixed; 00237 gchar *id, *date_opened, *date_posted, *owner_id, *date, *quantity, *price; 00238 GString *prev_id, *prev_date_opened, *prev_date_posted, *prev_owner_id, *prev_date; // needed to fix multi line invoices 00239 guint dummy; 00240 gint row = 1; 00241 00242 // allow the call to this function with only GtkListeStore* specified 00243 if (!fixed) 00244 fixed = &dummy; 00245 if (!deleted) 00246 deleted = &dummy; 00247 00248 *fixed = 0; 00249 *deleted = 0; 00250 00251 // init strings 00252 prev_id = g_string_new (""); 00253 prev_date_opened = g_string_new (""); 00254 prev_date_posted = g_string_new (""); 00255 prev_owner_id = g_string_new (""); 00256 prev_date = g_string_new (""); 00257 00258 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); 00259 while (valid) 00260 { 00261 row_deleted = FALSE; 00262 row_fixed = FALSE; 00263 00264 // Walk through the list, reading each row 00265 gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 00266 ID, &id, 00267 DATE_OPENED, &date_opened, 00268 DATE_POSTED, &date_posted, 00269 OWNER_ID, &owner_id, 00270 DATE, &date, 00271 QUANTITY, &quantity, PRICE, &price, -1); 00272 00273 if (strlen (price) == 0) 00274 { 00275 // invalid row (no price given) 00276 // no fix possible -> delete row 00277 valid = gtk_list_store_remove (store, &iter); 00278 row_deleted = TRUE; 00279 g_string_append_printf (info, 00280 _("ROW %d DELETED, PRICE_NOT_SET: id=%s\n"), 00281 row, id); 00282 } 00283 else if (strlen (quantity) == 0) 00284 { 00285 // invalid row (no quantity given) 00286 // no fix possible -> delete row 00287 valid = gtk_list_store_remove (store, &iter); 00288 row_deleted = TRUE; 00289 g_string_append_printf (info, _("ROW %d DELETED, QTY_NOT_SET: id=%s\n"), 00290 row, id); 00291 } 00292 else 00293 { 00294 if (strlen (id) == 0) 00295 { 00296 // no invoice id specified 00297 if (prev_id->len == 0) 00298 { 00299 // cannot fix -> delete row 00300 valid = gtk_list_store_remove (store, &iter); 00301 row_deleted = TRUE; 00302 g_string_append_printf (info, 00303 _("ROW %d DELETED, ID_NOT_SET\n"), row); 00304 } 00305 else 00306 { 00307 // this is a fixable multi line invoice 00308 gtk_list_store_set (store, &iter, ID, prev_id->str, -1); 00309 row_fixed = TRUE; 00310 } 00311 } 00312 else 00313 { 00314 // remember invoice id (to be able to fix multi line invoices) 00315 g_string_assign (prev_id, id); 00316 // new invoice => reset all other fixable entries 00317 g_string_assign (prev_date_opened, ""); 00318 g_string_assign (prev_date_posted, ""); 00319 g_string_assign (prev_owner_id, ""); 00320 g_string_assign (prev_date, ""); 00321 } 00322 } 00323 00324 if (!row_deleted) 00325 { 00326 // the row is valid (price and id are valid) 00327 00328 if (strlen (date_opened) == 0) 00329 { 00330 if (prev_date_opened->len == 0) 00331 { 00332 // fix this by using the current date (why is this so complicated?) 00333 gchar temp[20]; 00334 GDate *date; 00335 time_t secs; 00336 struct tm now; 00337 time (&secs); 00338 localtime_r (&secs, &now); 00339 date = 00340 g_date_new_dmy (now.tm_mday, now.tm_mon + 1, 00341 now.tm_year + 1900); 00342 g_date_strftime (temp, 20, "%x", date); // create a locale specific date string 00343 g_string_assign (prev_date_opened, temp); 00344 g_date_free (date); 00345 } 00346 // fix this by using the previous date_opened value (multi line invoice) 00347 gtk_list_store_set (store, &iter, DATE_OPENED, 00348 prev_date_opened->str, -1); 00349 row_fixed = TRUE; 00350 } 00351 else 00352 { 00353 // remember date_opened (to be able to fix multi line invoices) 00354 g_string_assign (prev_date_opened, date_opened); 00355 } 00356 00357 // date_opened is valid 00358 00359 if (strlen (date_posted) == 0) 00360 { 00361 if (prev_date_posted->len == 0) 00362 { 00363 // this invoice will have to get posted manually 00364 } 00365 else 00366 { 00367 // multi line invoice => fix it 00368 gtk_list_store_set (store, &iter, DATE_POSTED, 00369 prev_date_posted->str, -1); 00370 row_fixed = TRUE; 00371 } 00372 } 00373 else 00374 { 00375 // remember date_opened (to be able to fix multi line invoices) 00376 g_string_assign (prev_date_posted, date_posted); 00377 } 00378 00379 // date_posted is valid 00380 00381 if (strlen (quantity) == 0) 00382 { 00383 // quantity is unset => set to 1 00384 gtk_list_store_set (store, &iter, QUANTITY, "1", -1); 00385 row_fixed = TRUE; 00386 } 00387 00388 // quantity is valid 00389 00390 if (strlen (owner_id) == 0) 00391 { 00392 if (prev_owner_id->len == 0) 00393 { 00394 // no customer given and not fixable => delete row 00395 valid = gtk_list_store_remove (store, &iter); 00396 row_deleted = TRUE; 00397 g_string_append_printf (info, 00398 _("ROW %d DELETED, OWNER_NOT_SET: id=%s\n"), 00399 row, id); 00400 } 00401 else 00402 { 00403 gtk_list_store_set (store, &iter, owner_id, 00404 prev_owner_id->str, -1); 00405 row_fixed = TRUE; 00406 } 00407 } 00408 else 00409 { 00410 // remember owner_id 00411 g_string_assign (prev_owner_id, owner_id); 00412 } 00413 if (g_ascii_strcasecmp (type, "BILL") == 0) 00414 { 00415 // BILL: check, if vendor exists 00416 if (!gnc_search_vendor_on_id 00417 (gnc_get_current_book (), prev_owner_id->str)) 00418 { 00419 // vendor not found => delete row 00420 valid = gtk_list_store_remove (store, &iter); 00421 row_deleted = TRUE; 00422 g_string_append_printf (info, 00423 _("ROW %d DELETED, VENDOR_DOES_NOT_EXIST: id=%s\n"), 00424 row, id); 00425 } 00426 } 00427 else if (g_ascii_strcasecmp (type, "INVOICE") == 0) 00428 { 00429 // INVOICE: check, if customer exists 00430 if (!gnc_search_customer_on_id 00431 (gnc_get_current_book (), prev_owner_id->str)) 00432 { 00433 // customer not found => delete row 00434 valid = gtk_list_store_remove (store, &iter); 00435 row_deleted = TRUE; 00436 g_string_append_printf (info, 00437 _("ROW %d DELETED, CUSTOMER_DOES_NOT_EXIST: id=%s\n"), 00438 row, id); 00439 } 00440 } 00441 00442 // owner_id is valid 00443 } 00444 00445 g_free (id); 00446 g_free (date_opened); 00447 g_free (date_posted); 00448 g_free (owner_id); 00449 g_free (date); 00450 g_free (quantity); 00451 g_free (price); 00452 if (row_deleted) 00453 { 00454 (*deleted)++; 00455 // reset all remembered values 00456 g_string_assign (prev_id, ""); 00457 g_string_assign (prev_date_opened, ""); 00458 g_string_assign (prev_date_posted, ""); 00459 g_string_assign (prev_owner_id, ""); 00460 g_string_assign (prev_date, ""); 00461 } 00462 else if (row_fixed) 00463 (*fixed)++; 00464 00465 if (!row_deleted) 00466 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); 00467 00468 row++; 00469 } 00470 00471 // deallocate strings 00472 g_string_free (prev_id, TRUE); 00473 g_string_free (prev_date_opened, TRUE); 00474 g_string_free (prev_date_posted, TRUE); 00475 g_string_free (prev_owner_id, TRUE); 00476 g_string_free (prev_date, TRUE); 00477 00478 if (info && (info->len > 0)) 00479 { 00480 g_string_prepend (info, "\n\n"); 00481 g_string_prepend (info, _("These rows were deleted:")); 00482 } 00483 } 00484 00485 00486 /*********************************************************************** 00487 * @todo Maybe invoice checking should be done in gnc_bi_import_fix_bis (...) 00488 * rather than in here? But that is more concerned with ensuring the csv is consistent. 00489 * @param GtkListStore *store 00490 * @param guint *n_invoices_created 00491 * @param guint *n_invoices_updated 00492 * @return void 00493 ***********************************************************************/ 00494 void 00495 gnc_bi_import_create_bis (GtkListStore * store, QofBook * book, 00496 guint * n_invoices_created, 00497 guint * n_invoices_updated, 00498 gchar * type, gchar * open_mode ) 00499 { 00500 gboolean valid; 00501 GtkTreeIter iter; 00502 gchar *id, *date_opened, *owner_id, *billing_id, *notes; 00503 gchar *date, *desc, *action, *account, *quantity, *price, *disc_type, 00504 *disc_how, *discount, *taxable, *taxincluded, *tax_table; 00505 gchar *date_posted, *due_date, *account_posted, *memo_posted, 00506 *accumulatesplits; 00507 guint dummy; 00508 GncInvoice *invoice; 00509 GncOrder *order; 00510 GncEntry *entry; 00511 gint day, month, year; 00512 gnc_numeric n; 00513 GncOwner *owner; 00514 Account *acc; 00515 enum update {YES = GTK_RESPONSE_YES, NO = GTK_RESPONSE_NO} update; 00516 GtkWidget *dialog; 00517 Timespec today; 00518 GncPluginPage *new_page; 00519 InvoiceWindow *iw; 00520 00521 // these arguments are needed 00522 g_return_if_fail (store && book); 00523 00524 // allow to call this function without statistics 00525 if (!n_invoices_created) 00526 n_invoices_created = &dummy; 00527 if (!n_invoices_updated) 00528 n_invoices_updated = &dummy; 00529 *n_invoices_created = 0; 00530 *n_invoices_updated = 0; 00531 00532 invoice = NULL; 00533 order = NULL; 00534 update = NO; 00535 00536 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); 00537 while (valid) 00538 { 00539 // Walk through the list, reading each row 00540 gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, ID, &id, DATE_OPENED, &date_opened, DATE_POSTED, &date_posted, // if autoposting requested 00541 DUE_DATE, &due_date, // if autoposting requested 00542 ACCOUNT_POSTED, &account_posted, // if autoposting requested 00543 MEMO_POSTED, &memo_posted, // if autoposting requested 00544 ACCU_SPLITS, &accumulatesplits, // if autoposting requested 00545 OWNER_ID, &owner_id, 00546 BILLING_ID, &billing_id, 00547 NOTES, ¬es, 00548 DATE, &date, 00549 DESC, &desc, 00550 ACTION, &action, 00551 ACCOUNT, &account, 00552 QUANTITY, &quantity, 00553 PRICE, &price, 00554 DISC_TYPE, &disc_type, 00555 DISC_HOW, &disc_how, 00556 DISCOUNT, &discount, 00557 TAXABLE, &taxable, 00558 TAXINCLUDED, &taxincluded, 00559 TAX_TABLE, &tax_table, -1); 00560 00561 // TODO: Assign a new invoice number if one is absent. BUT we don't want to assign a new invoice for every line!! 00562 // so we'd have to flag this up somehow or add an option in the import GUI. The former implies that we make 00563 // an assumption about what the importer (person) wants to do. It seems resonable that a CSV file full of items with 00564 // If an invoice exists then we add to it in this current schema. 00565 // no predefined invoice number is a new invoice that's in need of a new number. 00566 // This was not designed to satisfy the need for repeat invoices however, so maybe we need a another method for this, after all 00567 // It should be easier to copy an invoice with a new ID than to go through all this malarky. 00568 if (g_ascii_strcasecmp (type, "BILL") == 0) 00569 invoice = gnc_search_bill_on_id (book, id); 00570 else if (g_ascii_strcasecmp (type, "INVOICE") == 0) 00571 invoice = gnc_search_invoice_on_id (book, id); 00572 00573 if (!invoice) 00574 { 00575 // new invoice 00576 invoice = gncInvoiceCreate (book); 00577 gncInvoiceSetID (invoice, id); 00578 owner = gncOwnerNew (); 00579 if (g_ascii_strcasecmp (type, "BILL") == 0) 00580 gncOwnerInitVendor (owner, 00581 gnc_search_vendor_on_id (book, owner_id)); 00582 else if (g_ascii_strcasecmp (type, "INVOICE") == 0) 00583 gncOwnerInitCustomer (owner, 00584 gnc_search_customer_on_id (book, owner_id)); 00585 gncInvoiceSetOwner (invoice, owner); 00586 gncInvoiceSetCurrency (invoice, gncOwnerGetCurrency (owner)); // Set the invoice currency based on the owner 00587 if (strlen (date_opened) != 0) // If a date is specified in CSV 00588 { 00589 qof_scan_date (date_opened, &day, &month, &year); 00590 gncInvoiceSetDateOpened (invoice, 00591 gnc_dmy2timespec (day, month, year)); 00592 } 00593 else // If no date in CSV 00594 { 00595 time_t now = time (NULL); 00596 Timespec now_timespec; 00597 timespecFromTime_t (&now_timespec, now); 00598 gncInvoiceSetDateOpened (invoice, now_timespec); 00599 } 00600 gncInvoiceSetBillingID (invoice, billing_id ? billing_id : ""); 00601 gncInvoiceSetNotes (invoice, notes ? notes : ""); 00602 gncInvoiceSetActive (invoice, TRUE); 00603 //if (g_ascii_strcasecmp(type,"INVOICE"))gncInvoiceSetBillTo( invoice, billto ); 00604 (*n_invoices_created)++; 00605 update = YES; 00606 00607 // open new bill / invoice in a tab, if requested 00608 if (g_ascii_strcasecmp(open_mode, "ALL") == 0 00609 || (g_ascii_strcasecmp(open_mode, "NOT_POSTED") == 0 00610 && strlen(date_posted) == 0)) 00611 { 00612 iw = gnc_ui_invoice_edit (invoice); 00613 new_page = gnc_plugin_page_invoice_new (iw); 00614 } 00615 } 00616 // I want to warn the user that an existing billvoice exists, but not every 00617 // time. 00618 // An import can contain many lines usually referring to the same invoice. 00619 // NB: Posted invoices are NEVER updated. 00620 else // if invoice exists 00621 { 00622 if (gncInvoiceIsPosted (invoice)) // Is it already posted? 00623 { 00624 valid = 00625 gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); 00626 continue; // If already posted then never import 00627 } 00628 if (update != YES) // Pop up a dialog to ask if updates are the expected action 00629 { 00630 dialog = gtk_message_dialog_new (NULL, 00631 GTK_DIALOG_MODAL, 00632 GTK_MESSAGE_ERROR, 00633 GTK_BUTTONS_YES_NO, 00634 "%s", 00635 _("Are you sure you have bills/invoices to update?")); 00636 update = gtk_dialog_run (GTK_DIALOG (dialog)); 00637 gtk_widget_destroy (dialog); 00638 if (update == NO) 00639 { 00640 // Cleanup and leave 00641 g_free (id); 00642 g_free (date_opened); 00643 g_free (owner_id); 00644 g_free (billing_id); 00645 g_free (notes); 00646 g_free (date); 00647 g_free (desc); 00648 g_free (action); 00649 g_free (account); 00650 g_free (quantity); 00651 g_free (price); 00652 g_free (disc_type); 00653 g_free (disc_how); 00654 g_free (discount); 00655 g_free (taxable); 00656 g_free (taxincluded); 00657 g_free (tax_table); 00658 g_free (date_posted); 00659 g_free (due_date); 00660 g_free (account_posted); 00661 g_free (memo_posted); 00662 g_free (accumulatesplits); 00663 return; 00664 } 00665 } 00666 (*n_invoices_updated)++; 00667 } 00668 00669 00670 // add entry to invoice/bill 00671 entry = gncEntryCreate (book); 00672 qof_scan_date (date, &day, &month, &year); 00673 { 00674 GDate *date = g_date_new_dmy(day, month, year); 00675 gncEntrySetDateGDate (entry, date); 00676 g_date_free (date); 00677 } 00678 timespecFromTime_t (&today, time (NULL)); // set today to the current date 00679 gncEntrySetDateEntered (entry, today); 00680 gncEntrySetDescription (entry, desc); 00681 gncEntrySetAction (entry, action); 00682 00683 n = gnc_numeric_zero (); 00684 gnc_exp_parser_parse (quantity, &n, NULL); 00685 gncEntrySetQuantity (entry, n); 00686 acc = gnc_account_lookup_for_register (gnc_get_current_root_account (), 00687 account); 00688 if (g_ascii_strcasecmp (type, "BILL") == 0) 00689 { 00690 gncEntrySetBillAccount (entry, acc); 00691 n = gnc_numeric_zero (); 00692 gnc_exp_parser_parse (price, &n, NULL); 00693 gncEntrySetBillPrice (entry, n); 00694 gncEntrySetBillTaxable (entry, text2bool (taxable)); 00695 gncEntrySetBillTaxIncluded (entry, text2bool (taxincluded)); 00696 gncEntrySetBillTaxTable (entry, 00697 gncTaxTableLookupByName (book, tax_table)); 00698 n = gnc_numeric_zero (); 00699 gnc_exp_parser_parse (discount, &n, NULL); 00700 gncBillAddEntry (invoice, entry); 00701 } 00702 else if (g_ascii_strcasecmp (type, "INVOICE") == 0) 00703 { 00704 gncEntrySetNotes (entry, notes); 00705 gncEntrySetInvAccount (entry, acc); 00706 n = gnc_numeric_zero (); 00707 gnc_exp_parser_parse (price, &n, NULL); 00708 gncEntrySetInvPrice (entry, n); 00709 gncEntrySetInvTaxable (entry, text2bool (taxable)); 00710 gncEntrySetInvTaxIncluded (entry, text2bool (taxincluded)); 00711 gncEntrySetInvTaxTable (entry, 00712 gncTaxTableLookupByName (book, tax_table)); 00713 n = gnc_numeric_zero (); 00714 gnc_exp_parser_parse (discount, &n, NULL); 00715 gncEntrySetInvDiscount (entry, n); 00716 gncEntrySetInvDiscountType (entry, text2disc_type (disc_type)); 00717 gncEntrySetInvDiscountHow (entry, text2disc_how (disc_how)); 00718 gncInvoiceAddEntry (invoice, entry); 00719 } 00720 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); 00721 00722 // handle auto posting of invoices 00723 { 00724 gchar *new_id = NULL; 00725 Transaction *tnx; 00726 if (valid) 00727 gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, ID, &new_id, -1); 00728 if (g_strcmp0 (id, new_id) != 0) 00729 { 00730 // the next invoice id is different => try to autopost this invoice 00731 if (qof_scan_date (date_posted, &day, &month, &year)) 00732 { 00733 // autopost this invoice 00734 Timespec d1, d2; 00735 d1 = gnc_dmy2timespec (day, month, year); 00736 qof_scan_date (due_date, &day, &month, &year); // obtains the due date, or leaves it at date_posted 00737 d2 = gnc_dmy2timespec (day, month, year); 00738 acc = gnc_account_lookup_for_register 00739 (gnc_get_current_root_account (), account_posted); 00740 tnx = gncInvoicePostToAccount (invoice, acc, &d1, &d2, 00741 memo_posted, 00742 text2bool (accumulatesplits)); 00743 } 00744 } 00745 g_free (new_id); 00746 } 00747 00748 // cleanup 00749 g_free (id); 00750 g_free (date_opened); 00751 g_free (owner_id); 00752 g_free (billing_id); 00753 g_free (notes); 00754 g_free (date); 00755 g_free (desc); 00756 g_free (action); 00757 g_free (account); 00758 g_free (quantity); 00759 g_free (price); 00760 g_free (disc_type); 00761 g_free (disc_how); 00762 g_free (discount); 00763 g_free (taxable); 00764 g_free (taxincluded); 00765 g_free (tax_table); 00766 g_free (date_posted); 00767 g_free (due_date); 00768 g_free (account_posted); 00769 g_free (memo_posted); 00770 g_free (accumulatesplits); 00771 } 00772 }
1.7.4