GnuCash c935c2f+
Loading...
Searching...
No Matches
gncEntryLedgerModel.c
1/*
2 * gncEntryLedgerModel.c -- Model for GncEntry ledger
3 * Copyright (C) 2001, 2002, 2003 Derek Atkins
4 * Author: Derek Atkins <warlord@MIT.EDU>
5 * Copyright (C) 2017 Aaron Laws
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, contact:
19 *
20 * Free Software Foundation Voice: +1-617-542-5942
21 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
22 * Boston, MA 02110-1301, USA gnu@gnu.org
23 */
24
25#include <config.h>
26
27#include <glib.h>
28#include <glib/gi18n.h>
29
30#include "Account.h"
31#include "gnc-ui-util.h"
32#include "qof.h" /* for g_strcmp0 */
33
34#include "datecell.h"
35#include "checkboxcell.h"
36
37#include "gncEntryLedgerP.h"
38#include "gncEntryLedgerModel.h"
39
40
43/* GET_LABEL */
44
45static const char * get_iacct_label (VirtualLocation virt_loc, gpointer data)
46{
47 return _("Income Account");
48}
49
50static const char * get_bacct_label (VirtualLocation virt_loc, gpointer data)
51{
52 return _("Expense Account");
53}
54
55static const char * get_actn_label (VirtualLocation virt_loc, gpointer data)
56{
57 return _("Action");
58}
59
60static const char * get_date_label (VirtualLocation virt_loc, gpointer data)
61{
62 return _("Date");
63}
64
65static const char * get_desc_label (VirtualLocation virt_loc, gpointer data)
66{
67 return _("Description");
68}
69
70static const char * get_disc_label (VirtualLocation virt_loc, gpointer data)
71{
72 return _("Discount");
73}
74
75static const char * get_distype_label (VirtualLocation virt_loc, gpointer data)
76{
77 return _("Discount Type");
78}
79
80static const char * get_dishow_label (VirtualLocation virt_loc, gpointer data)
81{
82 return _("Discount How");
83}
84
85static const char * get_pric_label (VirtualLocation virt_loc, gpointer data)
86{
87 return _("Unit Price");
88}
89
90static const char * get_qty_label (VirtualLocation virt_loc, gpointer data)
91{
92 return _("Quantity");
93}
94
95static const char * get_taxtable_label (VirtualLocation virt_loc, gpointer data)
96{
97 return _("Tax Table");
98}
99
100static const char * get_taxable_label (VirtualLocation virt_loc, gpointer data)
101{
102 return _("Taxable?");
103}
104
105static const char * get_taxincluded_label (VirtualLocation virt_loc, gpointer data)
106{
107 return _("Tax Included?");
108}
109
110static const char * get_inv_label (VirtualLocation virt_loc, gpointer data)
111{
112 return _("Invoiced?");
113}
114
115static const char * get_value_label (VirtualLocation virt_loc, gpointer data)
116{
117 return _("Subtotal");
118}
119
120static const char * get_taxval_label (VirtualLocation virt_loc, gpointer data)
121{
122 return _("Tax");
123}
124
125static const char * get_billable_label (VirtualLocation virt_loc, gpointer data)
126{
127 return _("Billable?");
128}
129
130static const char * get_payment_label (VirtualLocation virt_loc, gpointer data)
131{
132 return _("Payment");
133}
134
135/* GET_ENTRY */
136
137static const char * get_iacct_entry (VirtualLocation virt_loc,
138 gboolean translate,
139 gboolean *conditionally_changed,
140 gpointer user_data)
141{
142 static char *name = NULL;
143
144 GncEntryLedger *ledger = user_data;
145 GncEntry *entry;
146
147 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
148
149 g_free (name);
150 name = gnc_get_account_name_for_register (gncEntryGetInvAccount (entry));
151 return name;
152}
153
154static const char * get_bacct_entry (VirtualLocation virt_loc,
155 gboolean translate,
156 gboolean *conditionally_changed,
157 gpointer user_data)
158{
159 static char *name = NULL;
160
161 GncEntryLedger *ledger = user_data;
162 GncEntry *entry;
163
164 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
165
166 g_free (name);
167 name = gnc_get_account_name_for_register (gncEntryGetBillAccount (entry));
168 return name;
169}
170
171static const char * get_actn_entry (VirtualLocation virt_loc,
172 gboolean translate,
173 gboolean *conditionally_changed,
174 gpointer user_data)
175{
176 GncEntryLedger *ledger = user_data;
177 GncEntry *entry;
178
179 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
180 return gncEntryGetAction (entry);
181}
182
183static const char * get_date_entry (VirtualLocation virt_loc,
184 gboolean translate,
185 gboolean *conditionally_changed,
186 gpointer user_data)
187{
188 GncEntryLedger *ledger = user_data;
189 GncEntry *entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
190 time64 time = gncEntryGetDate (entry);
191 static gchar dateBuff [MAX_DATE_LENGTH+1];
192 memset (dateBuff, 0, sizeof (dateBuff));
193 qof_print_date_buff (dateBuff, MAX_DATE_LENGTH, time);
194 return dateBuff;
195}
196
197static const char * get_desc_entry (VirtualLocation virt_loc,
198 gboolean translate,
199 gboolean *conditionally_changed,
200 gpointer user_data)
201{
202 GncEntryLedger *ledger = user_data;
203 GncEntry *entry;
204
205 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
206 return gncEntryGetDescription (entry);
207}
208
209static const char * get_disc_entry (VirtualLocation virt_loc,
210 gboolean translate,
211 gboolean *conditionally_changed,
212 gpointer user_data)
213{
214 GncEntryLedger *ledger = user_data;
215 GncEntry *entry;
216 gnc_numeric discount;
217
218 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
219 discount = gncEntryGetInvDiscount (entry);
220 if (gnc_numeric_zero_p (discount))
221 return NULL;
222
223 return xaccPrintAmount (discount, gnc_default_print_info (FALSE));
224}
225
226static const char * get_distype_entry (VirtualLocation virt_loc,
227 gboolean translate,
228 gboolean *conditionally_changed,
229 gpointer user_data)
230{
231 GncEntryLedger *ledger = user_data;
232 GncEntry *entry;
233 char type;
234
235 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
236 type = gncEntryGetInvDiscountType (entry);
237
238 if (translate)
239 {
240 return gnc_entry_ledger_type_string_getter (type + '0');
241 }
242 else
243 {
244 static char s[2];
245 s[0] = '0' + type;
246 s[1] = '\0';
247 return s;
248 }
249}
250
251static const char * get_dishow_entry (VirtualLocation virt_loc,
252 gboolean translate,
253 gboolean *conditionally_changed,
254 gpointer user_data)
255{
256 GncEntryLedger *ledger = user_data;
257 GncEntry *entry;
258 char type;
259
260 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
261 type = gncEntryGetInvDiscountHow (entry);
262
263 if (translate)
264 {
265 return gnc_entry_ledger_how_string_getter (type + '0');
266 }
267 else
268 {
269 static char s[2];
270 s[0] = '0' + type;
271 s[1] = '\0';
272 return s;
273 }
274}
275
276static const char * get_pric_entry (VirtualLocation virt_loc,
277 gboolean translate,
278 gboolean *conditionally_changed,
279 gpointer user_data)
280{
281 GncEntryLedger *ledger = user_data;
282 GncEntry *entry;
283 gnc_numeric price;
284 gnc_commodity *curr;
285 GNCPrintAmountInfo print_info;
286
287 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
288 if (ledger->is_cust_doc)
289 price = gncEntryGetInvPrice (entry);
290 else
291 price = gncEntryGetBillPrice (entry);
292
293 if (gnc_numeric_zero_p (price))
294 return NULL;
295
296 curr = gncInvoiceGetCurrency (ledger->invoice);
297 print_info = gnc_default_price_print_info (curr);
298
299 return xaccPrintAmount (price, print_info);
300}
301
302static const char * get_qty_entry (VirtualLocation virt_loc,
303 gboolean translate,
304 gboolean *conditionally_changed,
305 gpointer user_data)
306{
307 GncEntryLedger *ledger = user_data;
308 GncEntry *entry;
309 gnc_numeric qty;
310
311 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
312 qty = gncEntryGetDocQuantity (entry, ledger->is_credit_note);
313
314 if (gnc_numeric_zero_p (qty))
315 return NULL;
316
317 return xaccPrintAmount (qty, gnc_default_print_info (FALSE));
318}
319
320static const char * get_taxable_entry (VirtualLocation virt_loc,
321 gboolean translate,
322 gboolean *conditionally_changed,
323 gpointer user_data)
324{
325 GncEntryLedger *ledger = user_data;
326 GncEntry *entry;
327 gboolean taxable;
328
329 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
330 if (ledger->is_cust_doc)
331 taxable = gncEntryGetInvTaxable (entry);
332 else
333 taxable = gncEntryGetBillTaxable (entry);
334
335 return gnc_checkbox_cell_get_string (taxable);
336}
337
338static gboolean
339gnc_entry_ledger_get_taxable_value (VirtualLocation virt_loc,
340 gboolean translate,
341 gboolean *conditionally_changed,
342 gpointer user_data)
343{
344 GncEntryLedger *ledger = user_data;
345 gboolean is_current;
346
347 is_current = virt_cell_loc_equal(ledger->table->current_cursor_loc.vcell_loc,
348 virt_loc.vcell_loc);
349 if (is_current)
350 return gnc_entry_ledger_get_checkmark (ledger, ENTRY_TAXABLE_CELL);
351 else
352 {
353 const char *valstr =
354 get_taxable_entry (virt_loc, translate, conditionally_changed,
355 user_data);
356 if (valstr && *valstr != ' ')
357 return TRUE;
358 }
359 return FALSE;
360}
361
362static const char * get_taxtable_entry (VirtualLocation virt_loc,
363 gboolean translate,
364 gboolean *conditionally_changed,
365 gpointer user_data)
366{
367 GncEntryLedger *ledger = user_data;
368 GncEntry *entry;
370 gboolean taxable;
371
372 /* load the cell properly; just shadow the value */
373 if (!conditionally_changed)
374 {
375 taxable = gnc_entry_ledger_get_taxable_value (virt_loc, translate,
376 conditionally_changed,
377 user_data);
378 if (!taxable)
379 return NULL;
380 }
381
382 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
383 if (ledger->is_cust_doc)
384 table = gncEntryGetInvTaxTable (entry);
385 else
386 table = gncEntryGetBillTaxTable (entry);
387
388 return gncTaxTableGetName (table);
389}
390
391static const char * get_taxincluded_entry (VirtualLocation virt_loc,
392 gboolean translate,
393 gboolean *conditionally_changed,
394 gpointer user_data)
395{
396 GncEntryLedger *ledger = user_data;
397 GncEntry *entry;
398 gboolean taxable, taxincluded;
399
400 /* load the cell properly; just shadow the value */
401 if (!conditionally_changed)
402 {
403 taxable = gnc_entry_ledger_get_taxable_value (virt_loc, translate,
404 conditionally_changed,
405 user_data);
406 if (!taxable)
407 return NULL;
408 }
409
410 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
411 if (ledger->is_cust_doc)
412 taxincluded = gncEntryGetInvTaxIncluded (entry);
413 else
414 taxincluded = gncEntryGetBillTaxIncluded (entry);
415
416 return gnc_checkbox_cell_get_string (taxincluded);
417}
418
419static const char * get_inv_entry (VirtualLocation virt_loc,
420 gboolean translate,
421 gboolean *conditionally_changed,
422 gpointer user_data)
423{
424 GncEntryLedger *ledger = user_data;
425 GncEntry *entry;
426
427 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
428
429 return gnc_checkbox_cell_get_string (gncEntryGetInvoice (entry) != NULL);
430
431 /* XXX: what if this entry doesn't belong to this invoice?
432 * Or, better question, what if this is the blank_entry on
433 * an invoice page? For the latter, don't worry about it;
434 * it will be added automatically during the Save operation
435 */
436}
437
438static const char * get_value_entry (VirtualLocation virt_loc,
439 gboolean translate,
440 gboolean *conditionally_changed,
441 gpointer user_data)
442{
443 GncEntryLedger *ledger = user_data;
444 gnc_numeric value;
445
446 /* Check if this is the current cursor */
447 if (virt_cell_loc_equal (ledger->table->current_cursor_loc.vcell_loc,
448 virt_loc.vcell_loc))
449 {
450 /* Sign attention: this function works with values as seen
451 * on-screen in the ledger, so they are always in the proper sign.
452 */
453 gnc_entry_ledger_compute_value (ledger, &value, NULL);
454 }
455 else
456 {
457 GncEntry *entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
458
459 if (entry == gnc_entry_ledger_get_blank_entry (ledger))
460 return NULL;
461
462 /* Ledger should display values with the same sign as on the document
463 * so get the document value instead of the internal value here.
464 */
465 value = gncEntryGetDocValue (entry, TRUE, ledger->is_cust_doc, ledger->is_credit_note);
466 }
467
468 return xaccPrintAmount (value, gnc_default_print_info (FALSE));
469}
470
471static const char * get_taxval_entry (VirtualLocation virt_loc,
472 gboolean translate,
473 gboolean *conditionally_changed,
474 gpointer user_data)
475{
476 GncEntryLedger *ledger = user_data;
477 gnc_numeric value;
478
479 /* Check if this is the current cursor */
480 if (virt_cell_loc_equal (ledger->table->current_cursor_loc.vcell_loc,
481 virt_loc.vcell_loc))
482 {
483 /* Sign attention: this function works with values as seen
484 * on-screen in the ledger, so they are always in the proper sign.
485 */
486 gnc_entry_ledger_compute_value (ledger, NULL, &value);
487 }
488 else
489 {
490 GncEntry *entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
491
492 if (entry == gnc_entry_ledger_get_blank_entry (ledger))
493 return NULL;
494
495 /* Ledger should display values with the same sign as on the document
496 * so get the document value instead of the internal value here.
497 */
498 value = gncEntryGetDocTaxValue (entry, TRUE, ledger->is_cust_doc, ledger->is_credit_note);
499 }
500
501 return xaccPrintAmount (value, gnc_default_print_info (FALSE));
502}
503
504static const char * get_billable_entry (VirtualLocation virt_loc,
505 gboolean translate,
506 gboolean *conditionally_changed,
507 gpointer user_data)
508{
509 GncEntryLedger *ledger = user_data;
510 GncEntry *entry;
511
512 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
513 return gnc_checkbox_cell_get_string (gncEntryGetBillable (entry));
514}
515
516static const char * get_payment_entry (VirtualLocation virt_loc,
517 gboolean translate,
518 gboolean *conditionally_changed,
519 gpointer user_data)
520{
521 GncEntryLedger *ledger = user_data;
522 GncEntry *entry;
523 GncEntryPaymentType type;
524
525 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
526
527 if (!entry)
528 return "";
529
530 type = gncEntryGetBillPayment (entry);
531
532 switch (type)
533 {
534 case GNC_PAYMENT_CASH:
535 return _("Cash");
536 case GNC_PAYMENT_CARD:
537 return _("Charge");
538 default:
539 g_warning ("Invalid payment type: %d", type);
540 return "";
541 }
542}
543
544/* GET_HELP */
545
546static char * get_acct_help (VirtualLocation virt_loc, gpointer user_data)
547{
548 const char *help;
549 GncEntryLedger *ledger = user_data;
550
551 help = gnc_table_get_entry (ledger->table, virt_loc);
552 if (!help || *help == '\0')
553 help = _("Enter the income/expense account for the Entry, "
554 "or choose one from the list");
555
556 return g_strdup (help);
557}
558
559static char * get_actn_help (VirtualLocation virt_loc, gpointer user_data)
560{
561 GncEntryLedger *ledger = user_data;
562 const char *help;
563
564 help = gnc_table_get_entry (ledger->table, virt_loc);
565 if (!help || *help == '\0')
566 help = _("Enter the type of Entry");
567
568 return g_strdup (help);
569}
570
571static char * get_date_help (VirtualLocation virt_loc, gpointer user_data)
572{
573 GncEntryLedger *ledger = user_data;
574 BasicCell *cell;
575 time64 cell_time;
576
577 cell = gnc_table_get_cell (ledger->table, virt_loc);
578 if (!cell || !cell->value || *cell->value == '\0')
579 return NULL;
580
581 gnc_date_cell_get_date ((DateCell *) cell, &cell_time, FALSE);
582 return gnc_print_time64 (cell_time, _("%A %d %B %Y"));
583}
584
585static char * get_desc_help (VirtualLocation virt_loc, gpointer user_data)
586{
587 GncEntryLedger *ledger = user_data;
588 const char *help;
589
590 help = gnc_table_get_entry (ledger->table, virt_loc);
591 if (!help || *help == '\0')
592 help = _("Enter the Entry Description");
593
594 return g_strdup (help);
595}
596
597static char * get_disc_help (VirtualLocation virt_loc, gpointer user_data)
598{
599 GncEntryLedger *ledger = user_data;
600 const char *help;
601 gint type;
602
603 type = gnc_entry_ledger_get_type (ledger, ENTRY_DISTYPE_CELL);
604
605 switch (type)
606 {
608 help = _("Enter the Discount Amount");
609 break;
611 help = _("Enter the Discount Percent");
612 break;
613 default:
614 help = _("Enter the Discount … unknown type");
615 break;
616 }
617
618 return g_strdup (help);
619}
620
621static char * get_distype_help (VirtualLocation virt_loc, gpointer user_data)
622{
623 GncEntryLedger *ledger = user_data;
624 const char *help;
625 gint type;
626
627 type = gnc_entry_ledger_get_type (ledger, ENTRY_DISTYPE_CELL);
628
629 switch (type)
630 {
632 help = _("Discount Type: Monetary Value");
633 break;
635 help = _("Discount Type: Percent");
636 break;
637 default:
638 help = _("Select the Discount Type");
639 break;
640 }
641 return g_strdup (help);
642}
643
644static char * get_dishow_help (VirtualLocation virt_loc, gpointer user_data)
645{
646 GncEntryLedger *ledger = user_data;
647 const char *help;
648 gint type;
649
650 type = gnc_entry_ledger_get_type (ledger, ENTRY_DISHOW_CELL);
651
652 switch (type)
653 {
654 case GNC_DISC_PRETAX:
655 help = _("Tax computed after discount is applied");
656 break;
657 case GNC_DISC_SAMETIME:
658 help = _("Discount and tax both applied on pretax value");
659 break;
660 case GNC_DISC_POSTTAX:
661 help = _("Discount computed after tax is applied");
662 break;
663 default:
664 help = _("Select how to compute the Discount and Taxes");
665 break;
666 }
667 return g_strdup (help);
668}
669
670static char * get_pric_help (VirtualLocation virt_loc, gpointer user_data)
671{
672 GncEntryLedger *ledger = user_data;
673 const char *help;
674
675 help = gnc_table_get_entry (ledger->table, virt_loc);
676 if (!help || *help == '\0')
677 help = _("Enter the unit-Price for this Entry");
678
679 return g_strdup (help);
680}
681
682static char * get_qty_help (VirtualLocation virt_loc, gpointer user_data)
683{
684 GncEntryLedger *ledger = user_data;
685 const char *help;
686
687 help = gnc_table_get_entry (ledger->table, virt_loc);
688 if (!help || *help == '\0')
689 help = _("Enter the Quantity of units for this Entry");
690
691 return g_strdup (help);
692}
693
694static char * get_taxtable_help (VirtualLocation virt_loc, gpointer user_data)
695{
696 GncEntryLedger *ledger = user_data;
697 const char *help;
698
699 help = gnc_table_get_entry (ledger->table, virt_loc);
700 if (!help || *help == '\0')
701 help = _("Enter the Tax Table to apply to this entry");
702
703 return g_strdup (help);
704}
705
706static char * get_taxable_help (VirtualLocation virt_loc, gpointer user_data)
707{
708 const char *help;
709
710 help = _("Is this entry taxable?");
711
712 return g_strdup (help);
713}
714
715static char * get_taxincluded_help (VirtualLocation virt_loc, gpointer user_data)
716{
717 const char *help;
718
719 help = _("Is the tax already included in the price of this entry?");
720
721 return g_strdup (help);
722}
723
724static char * get_inv_help (VirtualLocation virt_loc, gpointer user_data)
725{
726 GncEntryLedger *ledger = user_data;
727 const char *help;
728
729 switch (ledger->type)
730 {
731 case GNCENTRY_ORDER_ENTRY:
732 case GNCENTRY_ORDER_VIEWER:
733 case GNCENTRY_BILL_ENTRY:
734 case GNCENTRY_BILL_VIEWER:
735 case GNCENTRY_EXPVOUCHER_ENTRY:
736 case GNCENTRY_EXPVOUCHER_VIEWER:
737 help = _("Is this entry invoiced?");
738 break;
739 case GNCENTRY_VEND_CREDIT_NOTE_ENTRY:
740 case GNCENTRY_VEND_CREDIT_NOTE_VIEWER:
741 case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY:
742 case GNCENTRY_EMPL_CREDIT_NOTE_VIEWER:
743 help = _("Is this entry credited?");
744 break;
745 case GNCENTRY_INVOICE_ENTRY:
746 case GNCENTRY_INVOICE_VIEWER:
747 help = _("Include this entry on this invoice?");
748 break;
749 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
750 case GNCENTRY_CUST_CREDIT_NOTE_VIEWER:
751 help = _("Include this entry on this credit note?");
752 break;
753 default:
754 help = _("Unknown EntryLedger Type");
755 }
756
757 return g_strdup (help);
758}
759
760static char * get_value_help (VirtualLocation virt_loc, gpointer user_data)
761{
762 GncEntryLedger *ledger = user_data;
763 const char *help;
764
765 help = gnc_table_get_entry (ledger->table, virt_loc);
766 if (!help || *help == '\0')
767 help = _("The subtotal value of this entry");
768
769 return g_strdup (help);
770}
771
772static char * get_taxval_help (VirtualLocation virt_loc, gpointer user_data)
773{
774 GncEntryLedger *ledger = user_data;
775 const char *help;
776
777 help = gnc_table_get_entry (ledger->table, virt_loc);
778 if (!help || *help == '\0')
779 help = _("The total tax of this entry ");
780
781 return g_strdup (help);
782}
783
784static char * get_billable_help (VirtualLocation virt_loc, gpointer user_data)
785{
786 const char *help;
787
788 help = _("Is this entry billable to a customer or job?");
789
790 return g_strdup (help);
791}
792
793static char * get_payment_help (VirtualLocation virt_loc, gpointer user_data)
794{
795 const char *help;
796
797 help = _("How did you pay for this item?");
798
799 return g_strdup (help);
800}
801
802/* GET_IO_FLAGS */
803
804static CellIOFlags get_standard_io_flags (VirtualLocation virt_loc,
805 gpointer user_data)
806{
807 GncEntryLedger *ledger = user_data;
808 switch (ledger->type)
809 {
810 case GNCENTRY_ORDER_ENTRY:
811 case GNCENTRY_BILL_ENTRY:
812 case GNCENTRY_EXPVOUCHER_ENTRY:
813 {
814 GncEntry *entry =
815 gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
816
817 /*
818 * If the type is an order_entry and the entry was invoiced,
819 * make the entry immutable
820 */
821 if (gncEntryGetInvoice (entry) != NULL)
822 return XACC_CELL_ALLOW_SHADOW;
823 }
824 /* FALL THROUGH */
825 default:
826 return XACC_CELL_ALLOW_ALL;
827 }
828}
829
830static CellIOFlags get_typecell_io_flags (VirtualLocation virt_loc,
831 gpointer user_data)
832{
833 return (get_standard_io_flags (virt_loc, user_data) |
834 XACC_CELL_ALLOW_EXACT_ONLY);
835}
836
837static CellIOFlags get_inv_io_flags (VirtualLocation virt_loc,
838 gpointer user_data)
839{
840 GncEntryLedger *ledger = user_data;
841
842 switch (ledger->type)
843 {
844 case GNCENTRY_INVOICE_ENTRY:
845 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
846 {
847 /* This cell should be immutable IFF this entry is attached to
848 * a bill, order, or something else.
849 */
850 GncEntry * entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
851
852 if ((gncEntryGetOrder (entry) != NULL) || (gncEntryGetBill (entry) != NULL))
853 return XACC_CELL_ALLOW_ALL | XACC_CELL_ALLOW_EXACT_ONLY;
854
855 }
856 /* FALL THROUGH */
857 default:
858 return XACC_CELL_ALLOW_SHADOW;
859 }
860}
861
862static CellIOFlags get_value_io_flags (VirtualLocation virt_loc,
863 gpointer user_data)
864{
865 return XACC_CELL_ALLOW_SHADOW;
866}
867
868static CellIOFlags get_tax_io_flags (VirtualLocation virt_loc,
869 gpointer user_data)
870{
871 GncEntryLedger *ledger = user_data;
872 gboolean taxable;
873
874 taxable = gnc_entry_ledger_get_checkmark (ledger, ENTRY_TAXABLE_CELL);
875
876 /* Only print the taxtable and taxincluded cells if taxable is true */
877 if (taxable)
878 return get_standard_io_flags (virt_loc, user_data);
879
880 /* Shadow the value, so the cell is loaded properly */
881 return XACC_CELL_ALLOW_SHADOW;
882}
883
884static CellIOFlags get_taxincluded_io_flags (VirtualLocation virt_loc,
885 gpointer user_data)
886{
887 CellIOFlags flags = get_tax_io_flags (virt_loc, user_data);
888 if (flags == XACC_CELL_ALLOW_SHADOW)
889 return flags;
890 return flags | XACC_CELL_ALLOW_EXACT_ONLY;
891}
892
893static CellIOFlags get_qty_io_flags (VirtualLocation virt_loc, gpointer user_data)
894{
895 GncEntryLedger *ledger = user_data;
896 GncEntry *entry;
897 CellIOFlags flags = get_standard_io_flags (virt_loc, user_data);
898
899 /* If this isn't an invoice, or the flags are already read-only ... */
900 if (!ledger->is_cust_doc || flags == XACC_CELL_ALLOW_SHADOW)
901 return flags;
902
903 /* ok, if this is an invoice ledger AND this entry is attached to a
904 * bill (i.e. it's billable), freeze the quantity
905 */
906 entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
907 if (gncEntryGetBillable (entry))
908 return XACC_CELL_ALLOW_SHADOW;
909
910 return flags;
911}
912
913/* GET COLORS */
914
915static guint32
916gnc_entry_ledger_get_cell_color_internal (VirtualLocation virt_loc,
917 GncEntryLedger *ledger)
918{
919 VirtualCell *vcell;
920 gboolean is_current;
921 guint32 colorbase = 0;
922
923 /* a bit of enum arithmetic */
924
925 // There are negative numbers
926
927 if (!ledger)
928 return (colorbase + COLOR_UNDEFINED);
929
930 if (gnc_table_virtual_location_in_header (ledger->table, virt_loc))
931 return (colorbase + COLOR_HEADER);
932
933 vcell = gnc_table_get_virtual_cell (ledger->table, virt_loc.vcell_loc);
934 if (!vcell || !vcell->cellblock)
935 return (colorbase + COLOR_UNDEFINED);
936
937 if ((virt_loc.phys_col_offset < vcell->cellblock->start_col) ||
938 (virt_loc.phys_col_offset > vcell->cellblock->stop_col))
939 return (colorbase + COLOR_UNDEFINED);
940
941 is_current = virt_cell_loc_equal (ledger->table->current_cursor_loc.vcell_loc,
942 virt_loc.vcell_loc);
943
944 if (is_current)
945 return vcell->start_primary_color ?
946 (colorbase + COLOR_PRIMARY_ACTIVE) :
947 (colorbase + COLOR_SECONDARY_ACTIVE);
948
949 return vcell->start_primary_color ?
950 (colorbase + COLOR_PRIMARY) : (colorbase + COLOR_SECONDARY);
951
952}
953
954static guint32
955gnc_entry_ledger_get_cell_color (VirtualLocation virt_loc,
956 gboolean *hatching, gpointer user_data)
957{
958 GncEntryLedger *ledger = user_data;
959
960 if (hatching)
961 *hatching = FALSE;
962
963 return gnc_entry_ledger_get_cell_color_internal (virt_loc, ledger);
964}
965
966/* SAVE CELLS */
967
968static void gnc_entry_ledger_save_cells (gpointer save_data,
969 gpointer user_data)
970{
971 GncEntryLedger *ledger = user_data;
972 GncEntry *entry = save_data;
973
974 g_return_if_fail (entry != NULL);
975
976 /* copy the contents from the cursor to the split */
977
978 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
979 ENTRY_IACCT_CELL, TRUE))
980 {
981 Account *acc;
982
983 acc = gnc_entry_ledger_get_account (ledger, ENTRY_IACCT_CELL);
984
985 if (acc != NULL)
986 gncEntrySetInvAccount (entry, acc);
987 }
988
989 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
990 ENTRY_BACCT_CELL, TRUE))
991 {
992 Account *acc;
993
994 acc = gnc_entry_ledger_get_account (ledger, ENTRY_BACCT_CELL);
995
996 if (acc != NULL)
997 gncEntrySetBillAccount (entry, acc);
998 }
999
1000 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1001 ENTRY_ACTN_CELL, TRUE))
1002 {
1003 const char *value;
1004
1005 value = gnc_table_layout_get_cell_value (ledger->table->layout,
1006 ENTRY_ACTN_CELL);
1007 gncEntrySetAction (entry, value);
1008 }
1009
1010 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1011 ENTRY_DATE_CELL, TRUE))
1012 {
1013 BasicCell *cell;
1014 time64 cell_time;
1015
1016 cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_DATE_CELL);
1017
1018 gnc_date_cell_get_date ((DateCell *) cell, &cell_time, TRUE);
1019
1020 /* commit any pending changes */
1021 gnc_date_cell_commit ((DateCell *) cell);
1022
1023 /* Note use of time64CanonicalDayTime to set time part to midday */
1024 gncEntrySetDate (entry, time64CanonicalDayTime(cell_time));
1025 }
1026
1027 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1028 ENTRY_DESC_CELL, TRUE))
1029 {
1030 const char *value;
1031
1032 value = gnc_table_layout_get_cell_value (ledger->table->layout,
1033 ENTRY_DESC_CELL);
1034 gncEntrySetDescription (entry, value);
1035 }
1036
1037 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1038 ENTRY_DISC_CELL, TRUE))
1039 {
1040 gnc_numeric amount;
1041
1042 if (gnc_entry_ledger_get_numeric (ledger, ENTRY_DISC_CELL, &amount))
1043 gncEntrySetInvDiscount (entry, amount);
1044 }
1045
1046 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1047 ENTRY_DISTYPE_CELL, TRUE))
1048 {
1049 gint type;
1050
1051 type = gnc_entry_ledger_get_type (ledger, ENTRY_DISTYPE_CELL);
1052
1053 if (type != -1)
1054 gncEntrySetInvDiscountType (entry, type);
1055 }
1056
1057 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1058 ENTRY_DISHOW_CELL, TRUE))
1059 {
1060 gint type;
1061
1062 type = gnc_entry_ledger_get_type (ledger, ENTRY_DISHOW_CELL);
1063
1064 if (type != -1)
1065 gncEntrySetInvDiscountHow (entry, type);
1066 }
1067
1068 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1069 ENTRY_QTY_CELL, TRUE))
1070 {
1071 gnc_numeric amount;
1072
1073 if (gnc_entry_ledger_get_numeric (ledger, ENTRY_QTY_CELL, &amount))
1074 {
1075 gncEntrySetDocQuantity (entry, amount, ledger->is_credit_note);
1076 }
1077 }
1078
1079 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1080 ENTRY_BILLABLE_CELL, TRUE))
1081 {
1082 gboolean billable;
1083
1084 billable = gnc_entry_ledger_get_checkmark (ledger, ENTRY_BILLABLE_CELL);
1085 gncEntrySetBillable (entry, billable);
1086 }
1087
1088 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1089 ENTRY_PAYMENT_CELL, TRUE))
1090 {
1091 const char *value;
1092
1093 value = gnc_table_layout_get_cell_value (ledger->table->layout,
1094 ENTRY_PAYMENT_CELL);
1095 if (!g_strcmp0 (value, _("Cash")))
1096 gncEntrySetBillPayment (entry, GNC_PAYMENT_CASH);
1097 else if (!g_strcmp0 (value, _("Charge")))
1098 gncEntrySetBillPayment (entry, GNC_PAYMENT_CARD);
1099 else
1100 g_warning ("Invalid Payment cell: %s", value ? value : "(null)");
1101 }
1102
1103 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1104 ENTRY_PRIC_CELL, TRUE))
1105 {
1106 gnc_numeric amount;
1107
1108 if (gnc_entry_ledger_get_numeric (ledger, ENTRY_PRIC_CELL, &amount))
1109 {
1110 if (ledger->is_cust_doc)
1111 gncEntrySetInvPrice (entry, amount);
1112 else
1113 gncEntrySetBillPrice (entry, amount);
1114 }
1115 }
1116
1117 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1118 ENTRY_TAXABLE_CELL, TRUE))
1119 {
1120 gboolean taxable;
1121
1122 taxable = gnc_entry_ledger_get_checkmark (ledger, ENTRY_TAXABLE_CELL);
1123 if (ledger->is_cust_doc)
1124 gncEntrySetInvTaxable (entry, taxable);
1125 else
1126 gncEntrySetBillTaxable (entry, taxable);
1127 }
1128
1129 /* XXX: Only (re-set) these if taxable is TRUE? */
1130 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1131 ENTRY_TAXTABLE_CELL, TRUE))
1132 {
1134
1135 table = gnc_entry_ledger_get_taxtable (ledger, ENTRY_TAXTABLE_CELL);
1136 if (table)
1137 {
1138 if (ledger->is_cust_doc)
1139 gncEntrySetInvTaxTable (entry, table);
1140 else
1141 gncEntrySetBillTaxTable (entry, table);
1142 }
1143 }
1144
1145 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1146 ENTRY_TAXINCLUDED_CELL, TRUE))
1147 {
1148 gboolean taxincluded;
1149
1150 taxincluded = gnc_entry_ledger_get_checkmark (ledger,
1151 ENTRY_TAXINCLUDED_CELL);
1152 if (ledger->is_cust_doc)
1153 gncEntrySetInvTaxIncluded (entry, taxincluded);
1154 else
1155 gncEntrySetBillTaxIncluded (entry, taxincluded);
1156 }
1157
1158 if (ledger->type == GNCENTRY_INVOICE_ENTRY ||
1159 ledger->type == GNCENTRY_CUST_CREDIT_NOTE_ENTRY)
1160 {
1161 gboolean inv_value;
1162
1163 inv_value = gnc_entry_ledger_get_checkmark (ledger, ENTRY_INV_CELL);
1164
1165 if (inv_value)
1166 {
1167 /* Add this to the invoice (if it's not already attached) */
1168 if (gncEntryGetInvoice (entry) == NULL)
1169 gncInvoiceAddEntry (ledger->invoice, entry);
1170
1171 }
1172 else
1173 {
1174 /* Remove from the invoice iff we're attached to an order or bill */
1175 if ((gncEntryGetOrder (entry) != NULL) ||
1176 (gncEntryGetBill (entry) != NULL))
1177 gncInvoiceRemoveEntry (ledger->invoice, entry);
1178 }
1179 }
1180}
1181
1182/* Set Cell Handlers */
1183
1184static void gnc_entry_ledger_model_new_handlers (TableModel *model,
1185 GncEntryLedgerType type)
1186{
1187 struct model_desc
1188 {
1189 const char * cell;
1190 gpointer entry_handler;
1191 gpointer label_handler;
1192 gpointer help_handler;
1193 gpointer io_flags_handler;
1194 } models[] =
1195 {
1196 { ENTRY_IACCT_CELL, get_iacct_entry, get_iacct_label, get_acct_help, get_standard_io_flags },
1197 { ENTRY_BACCT_CELL, get_bacct_entry, get_bacct_label, get_acct_help, get_standard_io_flags },
1198 { ENTRY_ACTN_CELL, get_actn_entry, get_actn_label, get_actn_help, get_standard_io_flags },
1199 { ENTRY_DATE_CELL, get_date_entry, get_date_label, get_date_help, get_standard_io_flags },
1200 { ENTRY_DESC_CELL, get_desc_entry, get_desc_label, get_desc_help, get_standard_io_flags },
1201 { ENTRY_DISC_CELL, get_disc_entry, get_disc_label, get_disc_help, get_standard_io_flags },
1202 { ENTRY_DISTYPE_CELL, get_distype_entry, get_distype_label, get_distype_help, get_typecell_io_flags },
1203 { ENTRY_DISHOW_CELL, get_dishow_entry, get_dishow_label, get_dishow_help, get_typecell_io_flags },
1204 { ENTRY_PRIC_CELL, get_pric_entry, get_pric_label, get_pric_help, get_standard_io_flags },
1205 { ENTRY_QTY_CELL, get_qty_entry, get_qty_label, get_qty_help, get_qty_io_flags },
1206 { ENTRY_TAXABLE_CELL, get_taxable_entry, get_taxable_label, get_taxable_help, get_typecell_io_flags },
1207 { ENTRY_TAXTABLE_CELL, get_taxtable_entry, get_taxtable_label, get_taxtable_help, get_tax_io_flags },
1208 { ENTRY_TAXINCLUDED_CELL, get_taxincluded_entry, get_taxincluded_label, get_taxincluded_help, get_taxincluded_io_flags },
1209 { ENTRY_INV_CELL, get_inv_entry, get_inv_label, get_inv_help, get_inv_io_flags },
1210 { ENTRY_VALUE_CELL, get_value_entry, get_value_label, get_value_help, get_value_io_flags },
1211 { ENTRY_TAXVAL_CELL, get_taxval_entry, get_taxval_label, get_taxval_help, get_value_io_flags },
1212 { ENTRY_BILLABLE_CELL, get_billable_entry, get_billable_label, get_billable_help, get_typecell_io_flags },
1213 { ENTRY_PAYMENT_CELL, get_payment_entry, get_payment_label, get_payment_help, get_standard_io_flags },
1214 };
1215 unsigned int i;
1216
1217 // Set the cell color handler
1218 gnc_table_model_set_default_cell_color_handler (model, gnc_entry_ledger_get_cell_color);
1219
1220 for (i = 0; i < (sizeof(models) / sizeof(*models)); i++)
1221 {
1222 if (models[i].entry_handler)
1223 gnc_table_model_set_entry_handler (model, models[i].entry_handler,
1224 models[i].cell);
1225 if (models[i].label_handler)
1226 gnc_table_model_set_label_handler (model, models[i].label_handler,
1227 models[i].cell);
1228 if (models[i].help_handler)
1229 gnc_table_model_set_help_handler (model, models[i].help_handler,
1230 models[i].cell);
1231 if (models[i].io_flags_handler)
1232 gnc_table_model_set_io_flags_handler (model, models[i].io_flags_handler,
1233 models[i].cell);
1234 } /* for */
1235
1236 /*
1237 model->cell_data_allocator = ;
1238 model->cell_data_deallocator = ;
1239 model->cell_data_copy = ;
1240 */
1241
1242 gnc_table_model_set_post_save_handler (model, gnc_entry_ledger_save_cells);
1243
1244 switch (type)
1245 {
1246 case GNCENTRY_ORDER_VIEWER:
1247 case GNCENTRY_INVOICE_VIEWER:
1248 case GNCENTRY_BILL_VIEWER:
1249 case GNCENTRY_EXPVOUCHER_VIEWER:
1250 case GNCENTRY_CUST_CREDIT_NOTE_VIEWER:
1251 case GNCENTRY_VEND_CREDIT_NOTE_VIEWER:
1252 case GNCENTRY_EMPL_CREDIT_NOTE_VIEWER:
1253 /* make this table read-only */
1254 gnc_table_model_set_read_only (model, TRUE);
1255 break;
1256 default:
1257 break;
1258 }
1259}
1260
1263TableModel * gnc_entry_ledger_model_new (GncEntryLedgerType type)
1264{
1265 TableModel * model;
1266
1267 model = gnc_table_model_new ();
1268 gnc_entry_ledger_model_new_handlers (model, type);
1269
1270 return model;
1271}
Account handling public routines.
utility functions for the GnuCash UI
TableModel * gnc_entry_ledger_model_new(GncEntryLedgerType type)
Public Interface.
GncEntry * gnc_entry_ledger_get_entry(GncEntryLedger *ledger, VirtualCellLocation vcell_loc)
Returns the GncEntry at the given location, or NULL if the location is not valid.
GncEntry * gnc_entry_ledger_get_blank_entry(GncEntryLedger *ledger)
Exported Functions.
void gnc_date_cell_commit(DateCell *cell)
Commits any pending changes to the value of the cell.
void gnc_date_cell_get_date(DateCell *cell, time64 *time, gboolean warn)
Set a time64 to the value in the DateCell.
#define MAX_DATE_LENGTH
The maximum length of a string created by the date printers.
Definition gnc-date.h:108
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition gnc-date.h:87
size_t qof_print_date_buff(char *buff, const size_t len, time64 t)
Convenience: calls through to qof_print_date_dmy_buff().
Definition gnc-date.cpp:574
char * gnc_print_time64(time64 time, const char *format)
print a time64 as a date string per format
Definition gnc-date.cpp:370
time64 time64CanonicalDayTime(time64 t)
convert a time64 on a certain day (localtime) to the time64 representing midday on that day.
Definition gnc-date.cpp:404
void gncEntrySetDocQuantity(GncEntry *entry, gnc_numeric quantity, gboolean is_cn)
Set the internal quantity converting from the quantity as visible on the physical document.
Definition gncEntry.c:562
time64 gncEntryGetDate(const GncEntry *entry)
DEPRECATED - use gncEntryGetDateGDate() instead! (Because the time-of-day is a misleading extra infor...
Definition gncEntry.c:913
gnc_numeric gncEntryGetDocQuantity(const GncEntry *entry, gboolean is_cn)
Get the quantity as on the physical document.
Definition gncEntry.c:952
void gncEntrySetDate(GncEntry *entry, time64 date)
DEPRECATED - use gncEntrySetDateGDate() instead! (Because the time-of-day is a misleading extra infor...
Definition gncEntry.c:482
char * gnc_get_account_name_for_register(const Account *account)
Get either the full name of the account or the simple name, depending on the configuration parameter ...
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
VirtualCell * gnc_table_get_virtual_cell(Table *table, VirtualCellLocation vcell_loc)
returns the virtual cell associated with a particular virtual location.
@ GNC_AMT_TYPE_VALUE
tax is a number
Definition gncTaxTable.h:80
@ GNC_AMT_TYPE_PERCENT
tax is a percentage
Definition gncTaxTable.h:81
STRUCTS.
The DateCell object implements a date handling cell.
Definition datecell.h:92
modtime is the internal date of the last modtime See libgnucash/engine/TaxTableBillTermImmutability....
holds information about each virtual cell.
unsigned int start_primary_color
visible in the GUI