GnuCash  5.6-150-g038405b370+
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 
45 static const char * get_iacct_label (VirtualLocation virt_loc, gpointer data)
46 {
47  return _("Income Account");
48 }
49 
50 static const char * get_bacct_label (VirtualLocation virt_loc, gpointer data)
51 {
52  return _("Expense Account");
53 }
54 
55 static const char * get_actn_label (VirtualLocation virt_loc, gpointer data)
56 {
57  return _("Action");
58 }
59 
60 static const char * get_date_label (VirtualLocation virt_loc, gpointer data)
61 {
62  return _("Date");
63 }
64 
65 static const char * get_desc_label (VirtualLocation virt_loc, gpointer data)
66 {
67  return _("Description");
68 }
69 
70 static const char * get_disc_label (VirtualLocation virt_loc, gpointer data)
71 {
72  return _("Discount");
73 }
74 
75 static const char * get_distype_label (VirtualLocation virt_loc, gpointer data)
76 {
77  return _("Discount Type");
78 }
79 
80 static const char * get_dishow_label (VirtualLocation virt_loc, gpointer data)
81 {
82  return _("Discount How");
83 }
84 
85 static const char * get_pric_label (VirtualLocation virt_loc, gpointer data)
86 {
87  return _("Unit Price");
88 }
89 
90 static const char * get_qty_label (VirtualLocation virt_loc, gpointer data)
91 {
92  return _("Quantity");
93 }
94 
95 static const char * get_taxtable_label (VirtualLocation virt_loc, gpointer data)
96 {
97  return _("Tax Table");
98 }
99 
100 static const char * get_taxable_label (VirtualLocation virt_loc, gpointer data)
101 {
102  return _("Taxable?");
103 }
104 
105 static const char * get_taxincluded_label (VirtualLocation virt_loc, gpointer data)
106 {
107  return _("Tax Included?");
108 }
109 
110 static const char * get_inv_label (VirtualLocation virt_loc, gpointer data)
111 {
112  return _("Invoiced?");
113 }
114 
115 static const char * get_value_label (VirtualLocation virt_loc, gpointer data)
116 {
117  return _("Subtotal");
118 }
119 
120 static const char * get_taxval_label (VirtualLocation virt_loc, gpointer data)
121 {
122  return _("Tax");
123 }
124 
125 static const char * get_billable_label (VirtualLocation virt_loc, gpointer data)
126 {
127  return _("Billable?");
128 }
129 
130 static const char * get_payment_label (VirtualLocation virt_loc, gpointer data)
131 {
132  return _("Payment");
133 }
134 
135 /* GET_ENTRY */
136 
137 static 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 
154 static 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 
171 static 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 
183 static 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 
197 static 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 
209 static 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 
226 static 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 
251 static 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 
276 static 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 
302 static 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 
320 static 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 
338 static gboolean
339 gnc_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 
362 static 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 
391 static 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 
419 static 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 
438 static 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 
471 static 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 
504 static 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 
516 static 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 
546 static 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 
559 static 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 
571 static 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 
585 static 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 
597 static 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  {
607  case GNC_AMT_TYPE_VALUE:
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 
621 static 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  {
631  case GNC_AMT_TYPE_VALUE:
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 
644 static 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 
670 static 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 
682 static 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 
694 static 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 
706 static 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 
715 static 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 
724 static 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 
760 static 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 
772 static 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 
784 static 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 
793 static 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 
804 static 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 
830 static 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 
837 static 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 
862 static CellIOFlags get_value_io_flags (VirtualLocation virt_loc,
863  gpointer user_data)
864 {
865  return XACC_CELL_ALLOW_SHADOW;
866 }
867 
868 static 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 
884 static 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 
893 static 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 
915 static guint32
916 gnc_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 
954 static guint32
955 gnc_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 
968 static 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  {
1133  GncTaxTable *table;
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 
1184 static 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 
1263 TableModel * 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 }
utility functions for the GnuCash UI
STRUCTS.
holds information about each virtual cell.
Definition: table-allgui.h:132
TableModel * gnc_entry_ledger_model_new(GncEntryLedgerType type)
Public Interface.
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
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. ...
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
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
tax is a number
Definition: gncTaxTable.h:80
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 ...
Account handling public routines.
VirtualCell * gnc_table_get_virtual_cell(Table *table, VirtualCellLocation vcell_loc)
returns the virtual cell associated with a particular virtual location.
Definition: table-allgui.c:227
void gnc_date_cell_get_date(DateCell *cell, time64 *time, gboolean warn)
Set a time64 to the value in the DateCell.
void gnc_date_cell_commit(DateCell *cell)
Commits any pending changes to the value of the cell.
char * gnc_print_time64(time64 time, const char *format)
print a time64 as a date string per format
Definition: gnc-date.cpp:368
tax is a percentage
Definition: gncTaxTable.h:81
unsigned int start_primary_color
visible in the GUI
Definition: table-allgui.h:139
#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
void gncEntrySetDate(GncEntry *entry, time64 date)
DEPRECATED - use gncEntrySetDateGDate() instead! (Because the time-of-day is a misleading extra infor...
Definition: gncEntry.c:482
The DateCell object implements a date handling cell.
Definition: datecell.h:91
time64 time64CanonicalDayTime(time64 t)
convert a time64 on a certain day (localtime) to the time64 representing midday on that day...
Definition: gnc-date.cpp:402
GncEntry * gnc_entry_ledger_get_blank_entry(GncEntryLedger *ledger)
Exported Functions.
size_t qof_print_date_buff(char *buff, size_t buflen, time64 secs)
Convenience: calls through to qof_print_date_dmy_buff().
Definition: gnc-date.cpp:572
gnc_numeric gncEntryGetDocQuantity(const GncEntry *entry, gboolean is_cn)
Get the quantity as on the physical document.
Definition: gncEntry.c:952
modtime is the internal date of the last modtime See libgnucash/engine/TaxTableBillTermImmutability.txt for an explanation of the following Code that handles refcount, parent, child, invisible and children is identical to that in ::GncBillTerm