static void xml_add_entry (QofInstance * entry_p, gpointer out_p) { xmlNodePtr node; GncEntry *entry = (GncEntry *) entry_p; FILE *out = out_p; if (ferror(out)) return; /* Don't save non-attached entries! */ if (!(gncEntryGetOrder (entry) || gncEntryGetInvoice (entry) || gncEntryGetBill (entry))) return; node = entry_dom_tree_create (entry); xmlElemDump(out, NULL, node); xmlFreeNode (node); if (ferror(out) || fprintf(out, "\n") < 0) return; }
static CellIOFlags get_inv_io_flags (VirtualLocation virt_loc, gpointer user_data) { GncEntryLedger *ledger = user_data; switch (ledger->type) { case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: { /* This cell should be immutable IFF this entry is attached to * a bill, order, or something else. */ GncEntry * entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc); if ((gncEntryGetOrder (entry) != NULL) || (gncEntryGetBill (entry) != NULL)) return XACC_CELL_ALLOW_ALL | XACC_CELL_ALLOW_EXACT_ONLY; } /* FALL THROUGH */ default: return XACC_CELL_ALLOW_SHADOW; } }
static xmlNodePtr entry_dom_tree_create (GncEntry *entry) { xmlNodePtr ret; Timespec ts; Account *acc; GncTaxTable *taxtable; GncOrder *order; GncInvoice *invoice; kvp_frame *kf; ret = xmlNewNode(NULL, BAD_CAST gnc_entry_string); xmlSetProp(ret, BAD_CAST "version", BAD_CAST entry_version_string); xmlAddChild(ret, guid_to_dom_tree(entry_guid_string, qof_instance_get_guid(QOF_INSTANCE(entry)))); ts = gncEntryGetDate (entry); xmlAddChild(ret, timespec_to_dom_tree (entry_date_string, &ts)); ts = gncEntryGetDateEntered (entry); xmlAddChild(ret, timespec_to_dom_tree (entry_dateentered_string, &ts)); maybe_add_string (ret, entry_description_string, gncEntryGetDescription (entry)); maybe_add_string (ret, entry_action_string, gncEntryGetAction (entry)); maybe_add_string (ret, entry_notes_string, gncEntryGetNotes (entry)); maybe_add_numeric (ret, entry_qty_string, gncEntryGetQuantity (entry)); /* cust invoice */ acc = gncEntryGetInvAccount (entry); if (acc) xmlAddChild (ret, guid_to_dom_tree (entry_invacct_string, qof_instance_get_guid(QOF_INSTANCE(acc)))); maybe_add_numeric (ret, entry_iprice_string, gncEntryGetInvPrice (entry)); maybe_add_numeric (ret, entry_idiscount_string, gncEntryGetInvDiscount (entry)); invoice = gncEntryGetInvoice (entry); if (invoice) { xmlAddChild (ret, guid_to_dom_tree (entry_invoice_string, qof_instance_get_guid(QOF_INSTANCE(invoice)))); xmlAddChild(ret, text_to_dom_tree(entry_idisctype_string, gncAmountTypeToString ( gncEntryGetInvDiscountType (entry)))); xmlAddChild(ret, text_to_dom_tree(entry_idischow_string, gncEntryDiscountHowToString ( gncEntryGetInvDiscountHow (entry)))); xmlAddChild(ret, int_to_dom_tree(entry_itaxable_string, gncEntryGetInvTaxable (entry))); xmlAddChild(ret, int_to_dom_tree(entry_itaxincluded_string, gncEntryGetInvTaxIncluded (entry))); } taxtable = gncEntryGetInvTaxTable (entry); if (taxtable) xmlAddChild (ret, guid_to_dom_tree (entry_itaxtable_string, qof_instance_get_guid (QOF_INSTANCE(taxtable)))); /* vendor bills */ acc = gncEntryGetBillAccount (entry); if (acc) xmlAddChild (ret, guid_to_dom_tree (entry_billacct_string, qof_instance_get_guid (QOF_INSTANCE(acc)))); maybe_add_numeric (ret, entry_bprice_string, gncEntryGetBillPrice (entry)); invoice = gncEntryGetBill (entry); if (invoice) { GncOwner *owner; xmlAddChild (ret, guid_to_dom_tree (entry_bill_string, qof_instance_get_guid(QOF_INSTANCE(invoice)))); xmlAddChild(ret, int_to_dom_tree(entry_billable_string, gncEntryGetBillable (entry))); owner = gncEntryGetBillTo (entry); if (owner && owner->owner.undefined != NULL) xmlAddChild (ret, gnc_owner_to_dom_tree (entry_billto_string, owner)); xmlAddChild(ret, int_to_dom_tree(entry_btaxable_string, gncEntryGetBillTaxable (entry))); xmlAddChild(ret, int_to_dom_tree(entry_btaxincluded_string, gncEntryGetBillTaxIncluded (entry))); maybe_add_string (ret, entry_billpayment_string, gncEntryPaymentTypeToString (gncEntryGetBillPayment (entry))); } taxtable = gncEntryGetBillTaxTable (entry); if (taxtable) xmlAddChild (ret, guid_to_dom_tree (entry_btaxtable_string, qof_instance_get_guid (QOF_INSTANCE(taxtable)))); /* Other stuff */ order = gncEntryGetOrder (entry); if (order) xmlAddChild (ret, guid_to_dom_tree (entry_order_string, qof_instance_get_guid(QOF_INSTANCE (order)))); kf = qof_instance_get_slots (QOF_INSTANCE(entry)); if (kf) { xmlNodePtr kvpnode = kvp_frame_to_dom_tree(entry_slots_string, kf); if (kvpnode) { xmlAddChild(ret, kvpnode); } } return ret; }
static void gnc_entry_ledger_save_cells (gpointer save_data, gpointer user_data) { GncEntryLedger *ledger = user_data; GncEntry *entry = save_data; g_return_if_fail (entry != NULL); /* copy the contents from the cursor to the split */ if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_IACCT_CELL, TRUE)) { Account *acc; acc = gnc_entry_ledger_get_account (ledger, ENTRY_IACCT_CELL); if (acc != NULL) gncEntrySetInvAccount (entry, acc); } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_BACCT_CELL, TRUE)) { Account *acc; acc = gnc_entry_ledger_get_account (ledger, ENTRY_BACCT_CELL); if (acc != NULL) gncEntrySetBillAccount (entry, acc); } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_ACTN_CELL, TRUE)) { const char *value; value = gnc_table_layout_get_cell_value (ledger->table->layout, ENTRY_ACTN_CELL); gncEntrySetAction (entry, value); } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DATE_CELL, TRUE)) { BasicCell *cell; GDate date; cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_DATE_CELL); /* commit any pending changes */ gnc_date_cell_commit ((DateCell *) cell); gnc_date_cell_get_date_gdate ((DateCell *) cell, &date); gncEntrySetDateGDate (entry, &date); } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DESC_CELL, TRUE)) { const char *value; value = gnc_table_layout_get_cell_value (ledger->table->layout, ENTRY_DESC_CELL); gncEntrySetDescription (entry, value); } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DISC_CELL, TRUE)) { gnc_numeric amount; if (gnc_entry_ledger_get_numeric (ledger, ENTRY_DISC_CELL, &amount)) gncEntrySetInvDiscount (entry, amount); } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DISTYPE_CELL, TRUE)) { gint type; type = gnc_entry_ledger_get_type (ledger, ENTRY_DISTYPE_CELL); if (type != -1) gncEntrySetInvDiscountType (entry, type); } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DISHOW_CELL, TRUE)) { gint type; type = gnc_entry_ledger_get_type (ledger, ENTRY_DISHOW_CELL); if (type != -1) gncEntrySetInvDiscountHow (entry, type); } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_QTY_CELL, TRUE)) { gnc_numeric amount; if (gnc_entry_ledger_get_numeric (ledger, ENTRY_QTY_CELL, &amount)) { gncEntrySetDocQuantity (entry, amount, ledger->is_credit_note); } } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_BILLABLE_CELL, TRUE)) { gboolean billable; billable = gnc_entry_ledger_get_checkmark (ledger, ENTRY_BILLABLE_CELL); gncEntrySetBillable (entry, billable); } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_PAYMENT_CELL, TRUE)) { const char *value; value = gnc_table_layout_get_cell_value (ledger->table->layout, ENTRY_PAYMENT_CELL); if (!g_strcmp0 (value, _("Cash"))) gncEntrySetBillPayment (entry, GNC_PAYMENT_CASH); else if (!g_strcmp0 (value, _("Charge"))) gncEntrySetBillPayment (entry, GNC_PAYMENT_CARD); else g_warning ("Invalid Payment cell: %s", value ? value : "(null)"); } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_PRIC_CELL, TRUE)) { gnc_numeric amount; if (gnc_entry_ledger_get_numeric (ledger, ENTRY_PRIC_CELL, &amount)) { if (ledger->is_cust_doc) gncEntrySetInvPrice (entry, amount); else gncEntrySetBillPrice (entry, amount); } } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXABLE_CELL, TRUE)) { gboolean taxable; taxable = gnc_entry_ledger_get_checkmark (ledger, ENTRY_TAXABLE_CELL); if (ledger->is_cust_doc) gncEntrySetInvTaxable (entry, taxable); else gncEntrySetBillTaxable (entry, taxable); } /* XXX: Only (re-set) these if taxable is TRUE? */ if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXTABLE_CELL, TRUE)) { GncTaxTable *table; table = gnc_entry_ledger_get_taxtable (ledger, ENTRY_TAXTABLE_CELL); if (table) { if (ledger->is_cust_doc) gncEntrySetInvTaxTable (entry, table); else gncEntrySetBillTaxTable (entry, table); } } if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXINCLUDED_CELL, TRUE)) { gboolean taxincluded; taxincluded = gnc_entry_ledger_get_checkmark (ledger, ENTRY_TAXINCLUDED_CELL); if (ledger->is_cust_doc) gncEntrySetInvTaxIncluded (entry, taxincluded); else gncEntrySetBillTaxIncluded (entry, taxincluded); } if (ledger->type == GNCENTRY_INVOICE_ENTRY || ledger->type == GNCENTRY_CUST_CREDIT_NOTE_ENTRY) { gboolean inv_value; inv_value = gnc_entry_ledger_get_checkmark (ledger, ENTRY_INV_CELL); if (inv_value) { /* Add this to the invoice (if it's not already attached) */ if (gncEntryGetInvoice (entry) == NULL) gncInvoiceAddEntry (ledger->invoice, entry); } else { /* Remove from the invoice iff we're attached to an order or bill */ if ((gncEntryGetOrder (entry) != NULL) || (gncEntryGetBill (entry) != NULL)) gncInvoiceRemoveEntry (ledger->invoice, entry); } } }
static gboolean gnc_entry_ledger_traverse (VirtualLocation *p_new_virt_loc, gncTableTraversalDir dir, gpointer user_data) { GncEntryLedger *ledger = user_data; GncEntry *entry, *new_entry; gint response; VirtualLocation virt_loc; int changed; char const *cell_name; gboolean exact_traversal; if (!ledger) return FALSE; exact_traversal = (dir == GNC_TABLE_TRAVERSE_POINTER); entry = gnc_entry_ledger_get_current_entry (ledger); if (!entry) return FALSE; /* no changes, make sure we aren't going off the end */ changed = gnc_table_current_cursor_changed (ledger->table, FALSE); if (!changed) return FALSE; virt_loc = *p_new_virt_loc; cell_name = gnc_table_get_current_cell_name (ledger->table); /* See if we are leaving the account field */ do { ComboCell *cell; char *name; char *cell_name = NULL; switch (ledger->type) { case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_INVOICE_VIEWER: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_VIEWER: cell_name = ENTRY_IACCT_CELL; break; case GNCENTRY_BILL_ENTRY: case GNCENTRY_BILL_VIEWER: case GNCENTRY_EXPVOUCHER_ENTRY: case GNCENTRY_EXPVOUCHER_VIEWER: case GNCENTRY_VEND_CREDIT_NOTE_ENTRY: case GNCENTRY_VEND_CREDIT_NOTE_VIEWER: case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY: case GNCENTRY_EMPL_CREDIT_NOTE_VIEWER: cell_name = ENTRY_BACCT_CELL; break; default: g_warning ("Unhandled ledger type"); break; } if (!cell_name) break; if (!gnc_cell_name_equal (cell_name, cell_name)) break; if (!gnc_table_layout_get_cell_changed (ledger->table->layout, cell_name, FALSE)) break; cell = (ComboCell *) gnc_table_layout_get_cell (ledger->table->layout, cell_name); if (!cell) break; name = cell->cell.value; if (!name || *name == '\0') break; /* Create the account if necessary. Also checks for a placeholder */ if (!gnc_entry_ledger_get_account_by_name (ledger, (BasicCell *) cell, cell->cell.value, &ledger->full_refresh)) return TRUE; } while (FALSE); /* See if we are leaving the TaxTable field */ do { ComboCell *cell; GncTaxTable *table; char *name; if (!gnc_cell_name_equal (cell_name, ENTRY_TAXTABLE_CELL)) break; if (!gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXTABLE_CELL, FALSE)) break; cell = (ComboCell *) gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXTABLE_CELL); if (!cell) break; name = cell->cell.value; if (!name || *name == '\0') break; table = gncTaxTableLookupByName (ledger->book, cell->cell.value); if (table) break; { const char *format = _("The tax table %s does not exist. " "Would you like to create it?"); if (!gnc_verify_dialog (ledger->parent, TRUE, format, name)) break; } ledger->full_refresh = FALSE; table = gnc_ui_tax_table_new_from_name (ledger->book, name); if (!table) break; ledger->full_refresh = TRUE; name = (char *)gncTaxTableGetName (table); gnc_combo_cell_set_value (cell, name); gnc_basic_cell_set_changed (&cell->cell, TRUE); } while (FALSE); /* See if we are tabbing off the end of the very last line * (i.e. the blank entry) */ do { VirtualLocation virt_loc; if (!changed && !ledger->blank_entry_edited) break; if (dir != GNC_TABLE_TRAVERSE_RIGHT) break; virt_loc = ledger->table->current_cursor_loc; if (gnc_table_move_vertical_position (ledger->table, &virt_loc, 1)) break; virt_loc = ledger->table->current_cursor_loc; if (gnc_table_move_tab (ledger->table, &virt_loc, TRUE)) break; *p_new_virt_loc = ledger->table->current_cursor_loc; /* Yep, we're trying to leave the blank entry -- make sure * we are allowed to do so by verifying the current cursor. * If the current cursor is ok, then move on! */ /* Verify that the cursor is ok. If we can't save the cell, don't move! */ if (!gnc_entry_ledger_verify_can_save (ledger)) { return TRUE; } (p_new_virt_loc->vcell_loc.virt_row)++; p_new_virt_loc->phys_row_offset = 0; p_new_virt_loc->phys_col_offset = 0; ledger->traverse_to_new = TRUE; /* If we're here, we're tabbing off the end of the 'blank entry' */ return FALSE; } while (FALSE); /* Now see if we are changing cursors. If not, we may be able to * auto-complete. */ if (!gnc_table_virtual_cell_out_of_bounds (ledger->table, virt_loc.vcell_loc)) { if (gnc_entry_ledger_auto_completion (ledger, dir, p_new_virt_loc)) return FALSE; } /* Check for going off the end */ gnc_table_find_close_valid_cell (ledger->table, &virt_loc, exact_traversal); /* Same entry, no problem -- we're just moving backwards in the cursor */ new_entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc); if (entry == new_entry) { *p_new_virt_loc = virt_loc; return FALSE; } /* If we are here, then we are trying to leave the cursor. Make sure * the cursor we are leaving is valid. If so, ask the user if the * changes should be recorded. If not, don't go anywhere. */ /* Verify this cursor -- if it's not valid, don't let them move on */ if (!gnc_entry_ledger_verify_can_save (ledger)) { *p_new_virt_loc = ledger->table->current_cursor_loc; return TRUE; } /* * XXX GNCENTRY_INVOICE_EDIT processing to be added: * 1) check if the qty field changed. * 2) if so, check if this entry is part of an order. * 3) if so, ask if they want to change the entry or * split the entry into two parts. */ /* Ok, we are changing lines and the current entry has * changed. We only ask them what they want to do in * limited cases -- usually just let the change go through. */ { GtkWidget *dialog; const char *title = _("Save the current entry?"); const char *message = _("The current entry has been changed. However, this entry is " "part of an existing order. Would you like to record the change " "and effectively change your order?"); switch (ledger->type) { case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: if (gncEntryGetOrder (entry) != NULL) { dialog = gtk_message_dialog_new(GTK_WINDOW(ledger->parent), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", title); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", message); gtk_dialog_add_buttons(GTK_DIALOG(dialog), _("_Don't Record"), GTK_RESPONSE_REJECT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("_Record"), GTK_RESPONSE_ACCEPT, NULL); response = gnc_dialog_run(GTK_DIALOG(dialog), "invoice_entry_changed"); gtk_widget_destroy(dialog); break; } /* FALL THROUGH */ default: response = GTK_RESPONSE_ACCEPT; break; } } switch (response) { case GTK_RESPONSE_ACCEPT: break; case GTK_RESPONSE_REJECT: { VirtualCellLocation vcell_loc; GncEntry *new_entry; new_entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc); gnc_entry_ledger_cancel_cursor_changes (ledger); if (gnc_entry_ledger_find_entry (ledger, new_entry, &vcell_loc)) virt_loc.vcell_loc = vcell_loc; gnc_table_find_close_valid_cell (ledger->table, &virt_loc, exact_traversal); *p_new_virt_loc = virt_loc; } break; case GTK_RESPONSE_CANCEL: default: return TRUE; } return FALSE; }