/* for each entry, check the tax tables. If the tax tables are * grandchildren, then fix them to point to the most senior child */ static void taxtable_scrub_entries (QofInstance * entry_p, gpointer ht_p) { GHashTable *ht = ht_p; GncEntry *entry = GNC_ENTRY(entry_p); GncTaxTable *table, *new_tt; gint32 count; table = gncEntryGetInvTaxTable(entry); if (table) { if (taxtable_is_grandchild(table)) { PINFO("Fixing i-taxtable on entry %s\n", guid_to_string(qof_instance_get_guid(QOF_INSTANCE(entry)))); new_tt = taxtable_find_senior(table); gncEntryBeginEdit(entry); gncEntrySetInvTaxTable(entry, new_tt); gncEntryCommitEdit(entry); table = new_tt; } if (table) { count = GPOINTER_TO_INT(g_hash_table_lookup(ht, table)); count++; g_hash_table_insert(ht, table, GINT_TO_POINTER(count)); } } table = gncEntryGetBillTaxTable(entry); if (table) { if (taxtable_is_grandchild(table)) { PINFO("Fixing b-taxtable on entry %s\n", guid_to_string(qof_instance_get_guid(QOF_INSTANCE(entry)))); new_tt = taxtable_find_senior(table); gncEntryBeginEdit(entry); gncEntrySetBillTaxTable(entry, new_tt); gncEntryCommitEdit(entry); table = new_tt; } if (table) { count = GPOINTER_TO_INT(g_hash_table_lookup(ht, table)); count++; g_hash_table_insert(ht, table, GINT_TO_POINTER(count)); } } }
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 gboolean gnc_entry_ledger_auto_completion (GncEntryLedger *ledger, gncTableTraversalDir dir, VirtualLocation *p_new_virt_loc) { GncEntry *entry; GncEntry *blank_entry; GncEntry *auto_entry; const char* cell_name; const char *desc; BasicCell *cell = NULL; char *account_name = NULL; char *new_value = NULL; g_assert(ledger); g_assert(ledger->table); blank_entry = gnc_entry_ledger_get_blank_entry (ledger); /* auto-completion is only triggered by a tab out */ if (dir != GNC_TABLE_TRAVERSE_RIGHT) return FALSE; entry = gnc_entry_ledger_get_current_entry (ledger); if (entry == NULL) return FALSE; cell_name = gnc_table_get_current_cell_name (ledger->table); /* Auto-completion is done only in an entry ledger */ switch (ledger->type) { case GNCENTRY_ORDER_ENTRY: case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_BILL_ENTRY: case GNCENTRY_EXPVOUCHER_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: case GNCENTRY_VEND_CREDIT_NOTE_ENTRY: case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY: break; default: return FALSE; } /* Further conditions before we actually do auto-completion: */ /* There must be a blank entry */ if (blank_entry == NULL) return FALSE; /* we must be on the blank entry */ if (entry != blank_entry) return FALSE; /* and leaving the description cell */ if (!gnc_cell_name_equal (cell_name, ENTRY_DESC_CELL)) return FALSE; /* nothing but the date and description should be changed */ /* FIXME, this should be refactored. */ if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_ACTN_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_QTY_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_PRIC_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DISC_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DISTYPE_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DISHOW_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_IACCT_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_BACCT_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXABLE_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXINCLUDED_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXTABLE_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_VALUE_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXVAL_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_BILLABLE_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_PAYMENT_CELL, TRUE)) return FALSE; /* and the description should indeed be changed */ if (!gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DESC_CELL, TRUE)) return FALSE; /* to a non-empty value */ desc = gnc_table_layout_get_cell_value (ledger->table->layout, ENTRY_DESC_CELL); if ((desc == NULL) || (*desc == '\0')) return FALSE; /* Ok, we are sure we want to trigger auto-completion. Now find an * entry to copy the values from. FIXME: Currently we only use * the entries from the current invoice/bill, but it would be * better to draw this from a larger set of entries. */ auto_entry = /* Use this for book-wide auto-completion of the invoice entries */ find_entry_in_book_by_desc(ledger, desc); /* #else */ /* gnc_find_entry_in_reg_by_desc(ledger, desc); */ /* #endif */ if (auto_entry == NULL) return FALSE; /* now perform the completion */ gnc_suspend_gui_refresh (); /* Auto-complete the action field */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_ACTN_CELL); set_value_combo_cell (cell, gncEntryGetAction (auto_entry)); /* Auto-complete the account field */ switch (ledger->type) { case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_IACCT_CELL); account_name = gnc_get_account_name_for_register (gncEntryGetInvAccount(auto_entry)); break; case GNCENTRY_EXPVOUCHER_ENTRY: case GNCENTRY_BILL_ENTRY: case GNCENTRY_VEND_CREDIT_NOTE_ENTRY: case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY: cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_BACCT_CELL); account_name = gnc_get_account_name_for_register (gncEntryGetBillAccount(auto_entry)); break; case GNCENTRY_ORDER_ENTRY: default: cell = NULL; account_name = NULL; break; } set_value_combo_cell (cell, account_name); g_free (account_name); /* Auto-complete quantity cell * Note: we always autofill a positive quantity value. This allows us to * - reuse invoice entries on credit note ledgers, meaning you can credit * some invoice entry via autofill without having to manually fix the sign * on the credit note. * - autofill credit note entries on other credit note entries (without having * to juggle sign reversals internally) * - autofill credit note entries on invoice ledgers * * Disadvantage: invoice entries with explicitly set negative quantities will * be autofilled to positive quantities in later uses. But it seems less common * to me to require a negative entry again next time. */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_QTY_CELL); set_value_price_cell (cell, gnc_numeric_abs(gncEntryGetQuantity (auto_entry))); /* Auto-complete price cell */ { gnc_numeric price; switch (ledger->type) { case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: price = gncEntryGetInvPrice (auto_entry); break; default: price = gncEntryGetBillPrice (auto_entry); } /* Auto-complete price cell */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_PRIC_CELL); set_value_price_cell (cell, price); } /* We intentionally skip the discount column */ /* Taxable?, Tax-include?, Tax table */ { gboolean taxable, taxincluded; GncTaxTable *taxtable; switch (ledger->type) { case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: taxable = gncEntryGetInvTaxable (auto_entry); taxincluded = gncEntryGetInvTaxIncluded (auto_entry); taxtable = gncEntryGetInvTaxTable (auto_entry); break; default: taxable = gncEntryGetBillTaxable (auto_entry); taxincluded = gncEntryGetBillTaxIncluded (auto_entry); taxtable = gncEntryGetBillTaxTable (auto_entry); } /* Taxable? cell */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXABLE_CELL); gnc_checkbox_cell_set_flag ((CheckboxCell *) cell, taxable); gnc_basic_cell_set_changed (cell, TRUE); /* taxincluded? cell */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXINCLUDED_CELL); gnc_checkbox_cell_set_flag ((CheckboxCell *) cell, taxincluded); gnc_basic_cell_set_changed (cell, TRUE); /* Taxable? cell */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXTABLE_CELL); set_value_combo_cell(cell, gncTaxTableGetName (taxtable)); } gnc_resume_gui_refresh (); /* now move to the non-empty amount column unless config setting says not */ if ( !gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, "tab_includes_transfer_on_memorised", NULL) ) { VirtualLocation new_virt_loc; const char *cell_name = ENTRY_QTY_CELL; if (gnc_table_get_current_cell_location (ledger->table, cell_name, &new_virt_loc)) *p_new_virt_loc = new_virt_loc; } return TRUE; }