//! \brief helper function // Try to make a valid tm using the user set date format. Return false if it fails. gboolean isDateValid(char * date_string) { char *tmp; const gchar* date_format_string = qof_date_format_get_string (qof_date_format_get()); // Get the user set date format string struct tm time_struct; memset(&time_struct, 0, sizeof(struct tm)); tmp = strptime(date_string, date_format_string, &time_struct); if (tmp == NULL) return FALSE; return TRUE; }
//! \brief try to fix some common errors in the csv representation of invoices //! * corrects the date format //! * corrects ambigous values in multi line invoices //! * ensures customer exists //! * if quantity is unset, set to 1 //! * if price is unset, delete row void gnc_bi_import_fix_bis (GtkListStore * store, guint * fixed, guint * deleted, GString * info, gchar *type) { GtkTreeIter iter; gboolean valid, row_deleted, row_fixed; gchar *id, *date_opened, *date_posted, *due_date, *owner_id, *date, *quantity, *price; GString *prev_id, *prev_date_opened, *prev_date_posted, *prev_owner_id, *prev_date; // needed to fix multi line invoices guint dummy; gint row = 1; const gchar* date_format_string = qof_date_format_get_string (qof_date_format_get()); // Get the user set date format string //date_format_string = qof_date_format_get_string (qof_date_format_get()); DEBUG("date_format_string: %s",date_format_string); // allow the call to this function with only GtkListeStore* specified if (!fixed) fixed = &dummy; if (!deleted) deleted = &dummy; *fixed = 0; *deleted = 0; // init strings prev_id = g_string_new (""); prev_date_opened = g_string_new (""); prev_date_posted = g_string_new (""); prev_owner_id = g_string_new (""); prev_date = g_string_new (""); valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); while (valid) { row_deleted = FALSE; row_fixed = FALSE; // Walk through the list, reading each row gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, ID, &id, DATE_OPENED, &date_opened, DATE_POSTED, &date_posted, DUE_DATE, &due_date, OWNER_ID, &owner_id, DATE, &date, QUANTITY, &quantity, PRICE, &price, -1); if (strlen (price) == 0) { // invalid row (no price given) // no fix possible -> delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, PRICE_NOT_SET: id=%s\n"), row, id); } // TODO: QTY get set to 1 later if field is empty. Delete this section? else if (strlen (quantity) == 0) { // invalid row (no quantity given) // no fix possible -> delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, QTY_NOT_SET: id=%s\n"), row, id); } else { // TODO: If id is empty get the next one in the series. Bug 731105 if (strlen (id) == 0) { // no invoice id specified if (prev_id->len == 0) { // cannot fix -> delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, ID_NOT_SET\n"), row); } else { // this is a fixable multi line invoice gtk_list_store_set (store, &iter, ID, prev_id->str, -1); row_fixed = TRUE; } } else { // remember invoice id (to be able to fix multi line invoices) g_string_assign (prev_id, id); // new invoice => reset all other fixable entries g_string_assign (prev_date_opened, ""); g_string_assign (prev_date_posted, ""); g_string_assign (prev_owner_id, ""); g_string_assign (prev_date, ""); } } if (!row_deleted) { // the row is valid (price and id are valid) if(!isDateValid(date_opened)) { if (prev_date_opened->len == 0) { // fix this by using the current date gchar temp[20]; GDate date; g_date_clear (&date, 1); gnc_gdate_set_today (&date); g_date_strftime (temp, 20, date_format_string, &date); // Create a user specified date string. g_string_assign (prev_date_opened, temp); } // fix this by using the previous date_opened value (multi line invoice) gtk_list_store_set (store, &iter, DATE_OPENED, prev_date_opened->str, -1); row_fixed = TRUE; } else { // remember date_opened (to be able to fix multi line invoices) g_string_assign (prev_date_opened, date_opened); } // date_opened is valid if(!isDateValid(date_posted)) { if (prev_date_posted->len == 0) { // this invoice will have to get posted manually } else { // multi line invoice => fix it gtk_list_store_set (store, &iter, DATE_POSTED, prev_date_posted->str, -1); row_fixed = TRUE; } } else { // remember date_opened (to be able to fix multi line invoices) g_string_assign (prev_date_posted, date_posted); } // date_posted is valid /* // Check if due date is valid. Set it to date_posted if not valid or missing. if(!isDateValid(due_date)) { gtk_list_store_set (store, &iter, DUE_DATE, date_posted, -1); row_fixed = TRUE; } // due_date is valid */ if (strlen (quantity) == 0) { // quantity is unset => set to 1 gtk_list_store_set (store, &iter, QUANTITY, "1", -1); row_fixed = TRUE; } // quantity is valid if (strlen (owner_id) == 0) { if (prev_owner_id->len == 0) { // no customer given and not fixable => delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, OWNER_NOT_SET: id=%s\n"), row, id); } else { gtk_list_store_set (store, &iter, owner_id, prev_owner_id->str, -1); row_fixed = TRUE; } } else { // remember owner_id g_string_assign (prev_owner_id, owner_id); } if (g_ascii_strcasecmp (type, "BILL") == 0) { // BILL: check, if vendor exists if (!gnc_search_vendor_on_id (gnc_get_current_book (), prev_owner_id->str)) { // vendor not found => delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, VENDOR_DOES_NOT_EXIST: id=%s\n"), row, id); } } else if (g_ascii_strcasecmp (type, "INVOICE") == 0) { // INVOICE: check, if customer exists if (!gnc_search_customer_on_id (gnc_get_current_book (), prev_owner_id->str)) { // customer not found => delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, CUSTOMER_DOES_NOT_EXIST: id=%s\n"), row, id); } } // owner_id is valid } g_free (id); g_free (date_opened); g_free (date_posted); g_free (owner_id); g_free (date); g_free (quantity); g_free (price); if (row_deleted) { (*deleted)++; // reset all remembered values g_string_assign (prev_id, ""); g_string_assign (prev_date_opened, ""); g_string_assign (prev_date_posted, ""); g_string_assign (prev_owner_id, ""); g_string_assign (prev_date, ""); } else if (row_fixed) (*fixed)++; if (!row_deleted) valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); row++; } // deallocate strings g_string_free (prev_id, TRUE); g_string_free (prev_date_opened, TRUE); g_string_free (prev_date_posted, TRUE); g_string_free (prev_owner_id, TRUE); g_string_free (prev_date, TRUE); if (info && (info->len > 0)) { g_string_prepend (info, "\n\n"); g_string_prepend (info, _("These rows were deleted:")); } }