|
GnuCash 2.4.99
|
00001 /* 00002 * gncEntryLedgerLoad.c -- a Ledger widget for entering GncEntry objects 00003 * Copyright (C) 2001, 2002, 2003 Derek Atkins 00004 * Author: Derek Atkins <warlord@MIT.EDU> 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License as 00008 * published by the Free Software Foundation; either version 2 of 00009 * the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, contact: 00018 * 00019 * Free Software Foundation Voice: +1-617-542-5942 00020 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 00021 * Boston, MA 02110-1301, USA gnu@gnu.org 00022 */ 00023 00024 #include "config.h" 00025 00026 #include <glib.h> 00027 #include <glib/gi18n.h> 00028 #include <libguile.h> 00029 00030 #include "Account.h" 00031 #include "account-quickfill.h" 00032 #include "combocell.h" 00033 #include "gnc-component-manager.h" 00034 #include "gnc-gconf-utils.h" 00035 #include "gnc-ui-util.h" 00036 #include "recncell.h" 00037 00038 #include "business-options.h" 00039 00040 #include "gncEntry.h" 00041 #include "gncEntryLedger.h" 00042 #include "gncEntryLedgerP.h" 00043 #include "quickfillcell.h" 00044 #include "app-utils/gnc-entry-quickfill.h" 00045 00046 00047 /* XXX: This should go elsewhere */ 00048 const char * gnc_entry_ledger_type_string_getter (char flag) 00049 { 00050 switch (flag) 00051 { 00052 case '1': 00053 return _("$"); 00054 case '2': 00055 return _("%"); 00056 default: 00057 return "?"; 00058 }; 00059 } 00060 00061 const char * gnc_entry_ledger_how_string_getter (char flag) 00062 { 00063 switch (flag) 00064 { 00065 case '1': 00066 return _("<"); 00067 case '2': 00068 return _("="); 00069 case '3': 00070 return _(">"); 00071 default: 00072 return "?"; 00073 }; 00074 } 00075 00076 static void load_discount_type_cells (GncEntryLedger *ledger) 00077 { 00078 RecnCell *cell; 00079 00080 if (!ledger) return; 00081 00082 cell = (RecnCell *) 00083 gnc_table_layout_get_cell (ledger->table->layout, ENTRY_DISTYPE_CELL); 00084 00085 if (!cell) return; 00086 00087 gnc_recn_cell_set_valid_flags (cell, "12", '2'); 00088 gnc_recn_cell_set_flag_order (cell, "21"); 00089 gnc_recn_cell_set_string_getter (cell, gnc_entry_ledger_type_string_getter); 00090 } 00091 00092 static void load_discount_how_cells (GncEntryLedger *ledger) 00093 { 00094 RecnCell *cell; 00095 00096 if (!ledger) return; 00097 00098 cell = (RecnCell *) 00099 gnc_table_layout_get_cell (ledger->table->layout, ENTRY_DISHOW_CELL); 00100 00101 if (!cell) return; 00102 00103 gnc_recn_cell_set_valid_flags (cell, "123", '1'); 00104 gnc_recn_cell_set_flag_order (cell, "123"); 00105 gnc_recn_cell_set_string_getter (cell, gnc_entry_ledger_how_string_getter); 00106 } 00107 00108 static void load_payment_type_cells (GncEntryLedger *ledger) 00109 { 00110 ComboCell *cell; 00111 const GncOwner *owner; 00112 GncEmployee *employee; 00113 00114 cell = (ComboCell *) gnc_table_layout_get_cell (ledger->table->layout, 00115 ENTRY_PAYMENT_CELL); 00116 if (!cell) return; 00117 00118 if (!ledger->invoice) return; 00119 00120 owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (ledger->invoice)); 00121 if (gncOwnerGetType (owner) != GNC_OWNER_EMPLOYEE) 00122 return; 00123 00124 employee = gncOwnerGetEmployee (owner); 00125 g_return_if_fail (employee); 00126 00127 gnc_combo_cell_clear_menu (cell); 00128 gnc_combo_cell_add_menu_item (cell, _("Cash")); 00129 00130 if (gncEmployeeGetCCard (employee)) 00131 gnc_combo_cell_add_menu_item (cell, _("Charge")); 00132 } 00133 00134 /* ==================================================================== */ 00135 /* Return TRUE if we don't want to add this account to the xfer menu */ 00136 00137 static gboolean 00138 skip_expense_acct_cb (Account *account, gpointer user_data) 00139 { 00140 GNCAccountType type; 00141 00142 /* Don't add A/R, A/P, Bank, Cash, or Equity accounts */ 00143 type = xaccAccountGetType (account); 00144 if (type == ACCT_TYPE_PAYABLE || type == ACCT_TYPE_RECEIVABLE || 00145 type == ACCT_TYPE_CASH || type == ACCT_TYPE_BANK || 00146 type == ACCT_TYPE_EQUITY || type == ACCT_TYPE_TRADING) 00147 { 00148 return TRUE; 00149 } 00150 00151 /* If this is an ORDER or INVOICE, then leave out the expenses. */ 00152 if (type == ACCT_TYPE_EXPENSE) return TRUE; 00153 00154 /* Don't add placeholder accounts */ 00155 if (xaccAccountGetPlaceholder (account)) return TRUE; 00156 00157 return FALSE; 00158 } 00159 00160 static gboolean 00161 skip_income_acct_cb (Account *account, gpointer user_data) 00162 { 00163 GNCAccountType type; 00164 00165 /* Don't add A/R, A/P, Bank, Cash, or Equity accounts */ 00166 type = xaccAccountGetType (account); 00167 if (type == ACCT_TYPE_PAYABLE || type == ACCT_TYPE_RECEIVABLE || 00168 type == ACCT_TYPE_CASH || type == ACCT_TYPE_BANK || 00169 type == ACCT_TYPE_EQUITY || type == ACCT_TYPE_TRADING) 00170 { 00171 return TRUE; 00172 } 00173 00174 /* If this is a BILL, then leave out the incomes */ 00175 if (type == ACCT_TYPE_INCOME) return TRUE; 00176 00177 /* Don't add placeholder accounts */ 00178 if (xaccAccountGetPlaceholder (account)) return TRUE; 00179 00180 return FALSE; 00181 } 00182 00183 /* ===================================================================== */ 00184 /* Splat the account name into the transfer cell combobox menu */ 00185 00186 #define EKEY "Expense Business entry quickfill" 00187 #define IKEY "Income Business entry quickfill" 00188 00189 static void 00190 load_xfer_type_cells (GncEntryLedger *ledger) 00191 { 00192 Account *root; 00193 ComboCell *cell; 00194 QuickFill *qf = NULL; 00195 GtkListStore *store = NULL; 00196 00197 root = gnc_book_get_root_account (ledger->book); 00198 if (root == NULL) return; 00199 00200 /* Use a common, shared quickfill. For the ORDER or INVOICE, 00201 * ledgers, we don't want expense-type accounts in the menu. 00202 * For BILL, etc. then leave out the income types. 00203 */ 00204 switch (ledger->type) 00205 { 00206 case GNCENTRY_ORDER_ENTRY: 00207 case GNCENTRY_ORDER_VIEWER: 00208 case GNCENTRY_INVOICE_ENTRY: 00209 case GNCENTRY_INVOICE_VIEWER: 00210 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: 00211 case GNCENTRY_CUST_CREDIT_NOTE_VIEWER: 00212 qf = gnc_get_shared_account_name_quickfill (root, IKEY, 00213 skip_expense_acct_cb, NULL); 00214 store = gnc_get_shared_account_name_list_store (root, IKEY, 00215 skip_expense_acct_cb, NULL); 00216 break; 00217 00218 case GNCENTRY_BILL_ENTRY: 00219 case GNCENTRY_BILL_VIEWER: 00220 case GNCENTRY_EXPVOUCHER_ENTRY: 00221 case GNCENTRY_EXPVOUCHER_VIEWER: 00222 case GNCENTRY_VEND_CREDIT_NOTE_ENTRY: 00223 case GNCENTRY_VEND_CREDIT_NOTE_VIEWER: 00224 case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY: 00225 case GNCENTRY_EMPL_CREDIT_NOTE_VIEWER: 00226 case GNCENTRY_NUM_REGISTER_TYPES: 00227 qf = gnc_get_shared_account_name_quickfill (root, EKEY, 00228 skip_income_acct_cb, NULL); 00229 store = gnc_get_shared_account_name_list_store (root, EKEY, 00230 skip_income_acct_cb, NULL); 00231 break; 00232 } 00233 00234 cell = (ComboCell *) 00235 gnc_table_layout_get_cell (ledger->table->layout, ENTRY_IACCT_CELL); 00236 gnc_combo_cell_use_quickfill_cache (cell, qf); 00237 gnc_combo_cell_use_list_store_cache (cell, store); 00238 00239 cell = (ComboCell *) 00240 gnc_table_layout_get_cell (ledger->table->layout, ENTRY_BACCT_CELL); 00241 gnc_combo_cell_use_quickfill_cache (cell, qf); 00242 gnc_combo_cell_use_list_store_cache (cell, store); 00243 } 00244 00245 /* ===================================================================== */ 00246 00247 static void load_taxtable_type_cells (GncEntryLedger *ledger) 00248 { 00249 GList *list; 00250 ComboCell *cell; 00251 00252 cell = (ComboCell *) 00253 gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXTABLE_CELL); 00254 gnc_combo_cell_clear_menu (cell); 00255 00256 list = gncTaxTableGetTables (ledger->book); 00257 for ( ; list ; list = list->next ) 00258 { 00259 GncTaxTable *table = list->data; 00260 const char *name = gncTaxTableGetName (table); 00261 if (name != NULL) 00262 gnc_combo_cell_add_menu_item (cell, (char*)name); 00263 } 00264 } 00265 00266 static void 00267 gnc_entry_ledger_show_entry (GncEntryLedger *ledger, 00268 VirtualCellLocation start_loc) 00269 { 00270 VirtualCellLocation end_loc; 00271 int v_row; 00272 00273 end_loc = start_loc; 00274 v_row = end_loc.virt_row + 1; 00275 end_loc.virt_row = MIN (v_row, ledger->table->num_virt_rows - 1); 00276 00277 gnc_table_show_range (ledger->table, start_loc, end_loc); 00278 } 00279 00280 #define DESC_QF_KEY_INVOICES "ENTRY_DESC_CELL_QF_INVOICES" 00281 #define DESC_QF_KEY_BILLS "ENTRY_DESC_CELL_QF_BILLS" 00282 00283 static void 00284 load_description_cell (GncEntryLedger *ledger) 00285 { 00286 QuickFill *shared_quickfill; 00287 QuickFillCell *cell; 00288 00289 switch (ledger->type) 00290 { 00291 case GNCENTRY_INVOICE_ENTRY: 00292 case GNCENTRY_INVOICE_VIEWER: 00293 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: 00294 case GNCENTRY_CUST_CREDIT_NOTE_VIEWER: 00295 shared_quickfill = gnc_get_shared_entry_desc_quickfill(ledger->book, DESC_QF_KEY_INVOICES, TRUE); 00296 break; 00297 default: 00298 shared_quickfill = gnc_get_shared_entry_desc_quickfill(ledger->book, DESC_QF_KEY_BILLS, FALSE); 00299 }; 00300 00301 cell = (QuickFillCell *) 00302 gnc_table_layout_get_cell (ledger->table->layout, ENTRY_DESC_CELL); 00303 gnc_quickfill_cell_use_quickfill_cache (cell, shared_quickfill); 00304 } 00305 00306 void gnc_entry_ledger_load_xfer_cells (GncEntryLedger *ledger) 00307 { 00308 load_xfer_type_cells (ledger); 00309 load_taxtable_type_cells (ledger); 00310 load_payment_type_cells (ledger); 00311 load_description_cell (ledger); 00312 } 00313 00314 /* XXX (FIXME): This should be in a config file! */ 00315 /* Copy GncEntry information from the list to the rows of the Ledger. */ 00316 /* XXX This code is a cut-n-paste job from the SplitRegister code; 00317 * the split-register should be generalized to the point where a cut-n-paste 00318 * like this isn't required, and this should be trashed. 00319 */ 00320 void gnc_entry_ledger_load (GncEntryLedger *ledger, GList *entry_list) 00321 { 00322 GncEntry *blank_entry, *find_entry; 00323 CursorBuffer *cursor_buffer; 00324 Table *table; 00325 00326 GList *node; 00327 CellBlock *cursor_header, *cursor; 00328 VirtualCellLocation vcell_loc; 00329 VirtualLocation save_loc; 00330 time_t present; 00331 gboolean start_primary_color = TRUE; 00332 00333 int new_entry_row = -1; 00334 00335 if (!ledger) return; 00336 00337 /* Load up cells */ 00338 load_discount_type_cells (ledger); 00339 load_discount_how_cells (ledger); 00340 gnc_entry_ledger_load_xfer_cells (ledger); 00341 00342 blank_entry = gnc_entry_ledger_get_blank_entry (ledger); 00343 00344 if (blank_entry == NULL && ledger->invoice == NULL && entry_list == NULL) 00345 return; 00346 00347 if (blank_entry == NULL && ledger->invoice) 00348 { 00349 switch (ledger->type) 00350 { 00351 case GNCENTRY_ORDER_ENTRY: 00352 case GNCENTRY_INVOICE_ENTRY: 00353 case GNCENTRY_BILL_ENTRY: 00354 case GNCENTRY_EXPVOUCHER_ENTRY: 00355 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: 00356 case GNCENTRY_VEND_CREDIT_NOTE_ENTRY: 00357 case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY: 00358 00359 gnc_suspend_gui_refresh (); 00360 00361 blank_entry = gncEntryCreate (ledger->book); 00362 gncEntrySetDateGDate (blank_entry, &ledger->last_date_entered); 00363 ledger->blank_entry_guid = *gncEntryGetGUID (blank_entry); 00364 00365 gnc_resume_gui_refresh (); 00366 00367 /* The rest of this does not apply to expense vouchers */ 00368 if (ledger->type != GNCENTRY_EXPVOUCHER_ENTRY) 00369 { 00370 const GncOwner *owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (ledger->invoice)); 00371 GncTaxTable *table = NULL; 00372 GncTaxIncluded taxincluded_p = GNC_TAXINCLUDED_USEGLOBAL; 00373 gboolean taxincluded = FALSE; 00374 gnc_numeric discount = gnc_numeric_zero (); 00375 GNCOptionDB *odb; 00376 00377 /* Determine the TaxIncluded and Discount values */ 00378 switch (gncOwnerGetType (owner)) 00379 { 00380 case GNC_OWNER_CUSTOMER: 00381 taxincluded_p = gncCustomerGetTaxIncluded (owner->owner.customer); 00382 discount = gncCustomerGetDiscount (owner->owner.customer); 00383 break; 00384 case GNC_OWNER_VENDOR: 00385 taxincluded_p = gncVendorGetTaxIncluded (owner->owner.vendor); 00386 break; 00387 default: 00388 break; 00389 } 00390 00391 /* Compute the default taxincluded */ 00392 switch (taxincluded_p) 00393 { 00394 case GNC_TAXINCLUDED_YES: 00395 taxincluded = TRUE; 00396 break; 00397 case GNC_TAXINCLUDED_NO: 00398 taxincluded = FALSE; 00399 break; 00400 case GNC_TAXINCLUDED_USEGLOBAL: 00401 if (ledger->gconf_section) 00402 { 00403 taxincluded = gnc_gconf_get_bool(ledger->gconf_section, "tax_included", NULL); 00404 } 00405 else 00406 { 00407 taxincluded = FALSE; 00408 } 00409 break; 00410 } 00411 00412 /* Compute the proper taxtable */ 00413 odb = gnc_option_db_new_for_type (GNC_ID_BOOK); 00414 gnc_option_db_load_from_kvp (odb, qof_book_get_slots (ledger->book)); 00415 00416 switch (gncOwnerGetType (owner)) 00417 { 00418 case GNC_OWNER_CUSTOMER: 00419 table = gnc_option_db_lookup_taxtable_option (odb, 00420 "Business", 00421 "Default Customer TaxTable", 00422 NULL); 00423 00424 if (gncCustomerGetTaxTableOverride (owner->owner.customer)) 00425 table = gncCustomerGetTaxTable (owner->owner.customer); 00426 break; 00427 00428 case GNC_OWNER_VENDOR: 00429 table = gnc_option_db_lookup_taxtable_option (odb, 00430 "Business", 00431 "Default Vendor TaxTable", 00432 NULL); 00433 00434 if (gncVendorGetTaxTableOverride (owner->owner.vendor)) 00435 table = gncVendorGetTaxTable (owner->owner.vendor); 00436 break; 00437 00438 default: 00439 break; 00440 } 00441 00442 gnc_option_db_destroy (odb); 00443 00444 if (ledger->is_cust_doc) 00445 { 00446 gncEntrySetInvTaxTable (blank_entry, table); 00447 gncEntrySetInvTaxIncluded (blank_entry, taxincluded); 00448 gncEntrySetInvDiscount (blank_entry, discount); 00449 } 00450 else 00451 { 00452 gncEntrySetBillTaxTable (blank_entry, table); 00453 gncEntrySetBillTaxIncluded (blank_entry, taxincluded); 00454 } 00455 } 00456 00457 break; 00458 default: 00459 ledger->blank_entry_guid = *guid_null (); 00460 break; 00461 } 00462 ledger->blank_entry_edited = FALSE; 00463 } 00464 00465 table = ledger->table; 00466 00467 gnc_table_leave_update (table, table->current_cursor_loc); 00468 save_loc = table->current_cursor_loc; 00469 00470 /* Figure out where we are going to */ 00471 if (ledger->traverse_to_new) 00472 { 00473 find_entry = blank_entry; 00474 } 00475 else if (ledger->hint_entry) 00476 { 00477 find_entry = ledger->hint_entry; 00478 } 00479 else 00480 { 00481 find_entry = gnc_entry_ledger_get_current_entry(ledger); 00482 /* XXX: get current entry (cursor_hint_xxx) */ 00483 } 00484 00485 /* If the current cursor has changed we save the values for later 00486 * possible restoration. */ 00487 if (gnc_table_current_cursor_changed (table, TRUE) && 00488 (find_entry == gnc_entry_ledger_get_current_entry (ledger))) 00489 { 00490 cursor_buffer = gnc_cursor_buffer_new (); 00491 gnc_table_save_current_cursor (table, cursor_buffer); 00492 } 00493 else 00494 cursor_buffer = NULL; 00495 00496 /* disable move callback -- we don't want the cascade of 00497 * callbacks while we are fiddling with loading the register */ 00498 gnc_table_control_allow_move (table->control, FALSE); 00499 00500 /* invalidate the cursor */ 00501 { 00502 VirtualLocation virt_loc; 00503 00504 virt_loc.vcell_loc.virt_row = -1; 00505 virt_loc.vcell_loc.virt_col = -1; 00506 virt_loc.phys_row_offset = -1; 00507 virt_loc.phys_col_offset = -1; 00508 00509 gnc_table_move_cursor_gui (table, virt_loc); 00510 } 00511 00512 /* make sure that the header is loaded */ 00513 vcell_loc.virt_row = 0; 00514 vcell_loc.virt_col = 0; 00515 cursor_header = gnc_table_layout_get_cursor (table->layout, CURSOR_HEADER); 00516 gnc_table_set_vcell (table, cursor_header, NULL, TRUE, TRUE, vcell_loc); 00517 vcell_loc.virt_row++; 00518 00519 /* get the current time and reset the dividing row */ 00520 present = gnc_timet_get_today_end (); 00521 table->model->dividing_row_upper = -1; 00522 table->model->dividing_row = -1; 00523 cursor = gnc_table_layout_get_cursor (table->layout, "cursor"); 00524 00525 /* Populate the table */ 00526 for (node = entry_list; node; node = node->next) 00527 { 00528 GncEntry *entry = node->data; 00529 00530 /* Don't load the blank entry */ 00531 if (entry == blank_entry) 00532 continue; 00533 00534 /* If this is the first load of the ledger, fill the quickfill cells */ 00535 { 00536 /* XXX */ 00537 } 00538 00539 if (entry == find_entry) 00540 new_entry_row = vcell_loc.virt_row; 00541 00542 gnc_table_set_vcell (table, cursor, gncEntryGetGUID (entry), 00543 TRUE, start_primary_color, vcell_loc); 00544 vcell_loc.virt_row++; 00545 00546 /* Flip color for the next guy */ 00547 start_primary_color = !start_primary_color; 00548 } 00549 00550 /* Add the blank entry at the end. */ 00551 if (blank_entry) 00552 { 00553 gnc_table_set_vcell (table, cursor, gncEntryGetGUID (blank_entry), 00554 TRUE, start_primary_color, vcell_loc); 00555 00556 if (find_entry == blank_entry) 00557 new_entry_row = vcell_loc.virt_row; 00558 00559 vcell_loc.virt_row++; 00560 } 00561 00562 /* Resize the table */ 00563 gnc_table_set_size (table, vcell_loc.virt_row, 1); 00564 00565 /* Restore the cursor to its rightful position */ 00566 if (new_entry_row > 0) 00567 save_loc.vcell_loc.virt_row = new_entry_row; 00568 00569 if (gnc_table_find_close_valid_cell (table, &save_loc, FALSE)) 00570 { 00571 gnc_table_move_cursor_gui (table, save_loc); 00572 00573 if (find_entry == gnc_entry_ledger_get_current_entry (ledger)) 00574 gnc_table_restore_current_cursor (table, cursor_buffer); 00575 } 00576 00577 gnc_cursor_buffer_destroy (cursor_buffer); 00578 cursor_buffer = NULL; 00579 00580 /* Reset the ledger */ 00581 ledger->traverse_to_new = FALSE; 00582 ledger->hint_entry = NULL; 00583 00584 /* Set the cell fractions */ 00585 00586 00587 gnc_table_refresh_gui (table, TRUE); 00588 gnc_entry_ledger_show_entry (ledger, table->current_cursor_loc.vcell_loc); 00589 00590 /* Set completion character */ 00591 gnc_combo_cell_set_complete_char 00592 ((ComboCell *) 00593 gnc_table_layout_get_cell (table->layout, ENTRY_IACCT_CELL), 00594 gnc_get_account_separator ()); 00595 00596 gnc_combo_cell_set_complete_char 00597 ((ComboCell *) 00598 gnc_table_layout_get_cell (table->layout, ENTRY_BACCT_CELL), 00599 gnc_get_account_separator ()); 00600 00601 /* enable callback for cursor user-driven moves */ 00602 gnc_table_control_allow_move (table->control, TRUE); 00603 } 00604 00605 /* =========================== END OF FILE ========================== */
1.7.4