GnuCash  5.6-150-g038405b370+
gncEntry.c
1 /********************************************************************\
2  * gncEntry.c -- the Core Business Entry Interface *
3  * *
4  * This program is free software; you can redistribute it and/or *
5  * modify it under the terms of the GNU General Public License as *
6  * published by the Free Software Foundation; either version 2 of *
7  * the License, or (at your option) any later version. *
8  * *
9  * This program is distributed in the hope that it will be useful, *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12  * GNU General Public License for more details. *
13  * *
14  * You should have received a copy of the GNU General Public License*
15  * along with this program; if not, contact: *
16  * *
17  * Free Software Foundation Voice: +1-617-542-5942 *
18  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19  * Boston, MA 02110-1301, USA gnu@gnu.org *
20  * *
21 \********************************************************************/
22 
23 /*
24  * Copyright (C) 2001,2002 Derek Atkins
25  * Author: Derek Atkins <warlord@MIT.EDU>
26  */
27 
28 #include <config.h>
29 
30 #include <glib.h>
31 #include <qofinstance-p.h>
32 #include <inttypes.h>
33 
34 #include "gnc-commodity.h"
35 
36 #include "gncEntry.h"
37 #include "gncEntryP.h"
38 #include "gnc-features.h"
39 #include "gncInvoice.h"
40 #include "gncOrder.h"
41 
42 struct _gncEntry
43 {
44  QofInstance inst;
45 
46  time64 date;
47  time64 date_entered;
48  const char * desc;
49  const char * action;
50  const char * notes;
51  gnc_numeric quantity;
52 
53  /* customer invoice data */
54  Account * i_account;
55  gnc_numeric i_price;
56  gboolean i_taxable;
57  gboolean i_taxincluded;
58  GncTaxTable * i_tax_table;
59  gnc_numeric i_discount;
60  GncAmountType i_disc_type;
61  GncDiscountHow i_disc_how;
62 
63  /* vendor bill data */
64  Account * b_account;
65  gnc_numeric b_price;
66  gboolean b_taxable;
67  gboolean b_taxincluded;
68  GncTaxTable * b_tax_table;
69  gboolean billable;
70  GncOwner billto;
71 
72  /* employee bill data */
73  GncEntryPaymentType b_payment;
74 
75  /* my parent(s) */
76  GncOrder * order;
77  GncInvoice * invoice;
78  GncInvoice * bill;
79 
80  /* CACHED VALUES */
81  gboolean values_dirty;
82 
83  /* customer invoice */
84  gnc_numeric i_value;
85  gnc_numeric i_value_rounded;
86  GList * i_tax_values;
87  gnc_numeric i_tax_value;
88  gnc_numeric i_tax_value_rounded;
89  gnc_numeric i_disc_value;
90  gnc_numeric i_disc_value_rounded;
91  time64 i_taxtable_modtime;
92 
93  /* vendor bill */
94  gnc_numeric b_value;
95  gnc_numeric b_value_rounded;
96  GList * b_tax_values;
97  gnc_numeric b_tax_value;
98  gnc_numeric b_tax_value_rounded;
99  time64 b_taxtable_modtime;
100 };
101 
103 {
104  QofInstanceClass parent_class;
105 };
106 
107 static QofLogModule log_module = GNC_MOD_BUSINESS;
108 
109 
110 /* You must edit the functions in this block in tandem.
111  * KEEP THIS FUNCTION IN SYNC with the one below! */
112 const char *
113 gncEntryDiscountHowToString (GncDiscountHow how)
114 {
115  switch (how)
116  {
117  case (GNC_DISC_PRETAX):
118  return "PRETAX";
119  case (GNC_DISC_SAMETIME):
120  return "SAMETIME";
121  case (GNC_DISC_POSTTAX):
122  return "POSTTAX";
123  default:
124  PWARN ("asked to translate unknown discount-how %d.\n", how);
125  break;
126  }
127  return NULL;
128 }
129 
130 /* You must edit the functions in this block in tandem.
131  * KEEP THIS FUNCTION IN SYNC with the one above! */
132 gboolean gncEntryDiscountStringToHow (const char *str, GncDiscountHow *how)
133 {
134  if (g_strcmp0 ("PRETAX", str) == 0)
135  {
136  *how = GNC_DISC_PRETAX;
137  return TRUE;
138  }
139  if (g_strcmp0 ("SAMETIME", str) == 0)
140  {
141  *how = GNC_DISC_SAMETIME;
142  return TRUE;
143  }
144  if (g_strcmp0 ("POSTTAX", str) == 0)
145  {
146  *how = GNC_DISC_POSTTAX;
147  return TRUE;
148  }
149  PWARN ("asked to translate unknown discount-how string %s.\n",
150  str ? str : "(null)");
151 
152  return FALSE;
153 }
154 
155 /* You must edit the functions in this block in tandem.
156  * KEEP THIS FUNCTION IN SYNC with the one below! */
157 const char * gncEntryPaymentTypeToString (GncEntryPaymentType type)
158 {
159  switch (type)
160  {
161  case (GNC_PAYMENT_CASH):
162  return "CASH";
163  case (GNC_PAYMENT_CARD):
164  return "CARD";
165  default:
166  PWARN ("asked to translate unknown payment type %d.\n", type);
167  break;
168  }
169  return NULL ;
170 }
171 
172 /* You must edit the functions in this block in tandem.
173  * KEEP THIS FUNCTION IN SYNC with the one above! */
174 gboolean gncEntryPaymentStringToType (const char *str, GncEntryPaymentType *type)
175 {
176  if (g_strcmp0 ("CASH", str) == 0)
177  {
178  *type = GNC_PAYMENT_CASH;
179  return TRUE;
180  }
181  if (g_strcmp0 ("CARD", str) == 0)
182  {
183  *type = GNC_PAYMENT_CARD;
184  return TRUE;
185  }
186  PWARN ("asked to translate unknown discount-how string %s.\n",
187  str ? str : "(null)");
188 
189  return FALSE;
190 }
191 
192 #define _GNC_MOD_NAME GNC_ID_ENTRY
193 
194 #define SET_STR(obj, member, str) { \
195  if (!g_strcmp0 (member, str)) return; \
196  gncEntryBeginEdit (obj); \
197  CACHE_REPLACE (member, str); \
198  }
199 
200 static inline void mark_entry (GncEntry *entry);
201 void mark_entry (GncEntry *entry)
202 {
203  qof_instance_set_dirty(&entry->inst);
204  qof_event_gen (&entry->inst, QOF_EVENT_MODIFY, NULL);
205 }
206 
207 /* ================================================================ */
208 
209 enum
210 {
211  PROP_0,
212 // PROP_DATE, /* Table */
213 // PROP_DATE_ENTERED, /* Table */
214  PROP_DESCRIPTION, /* Table */
215 // PROP_ACTION, /* Table */
216 // PROP_NOTES, /* Table */
217 // PROP_QUANTITY, /* Table (numeric) */
218 // PROP_I_ACCT, /* Table */
219 // PROP_I_PRICE, /* Table (numeric) */
220 // PROP_I_DISCOUNT, /* Table (numeric) */
221 // PROP_INVOICE, /* Table */
222 // PROP_I_DISC_TYPE, /* Table */
223 // PROP_I_DISC_HOW, /* Table */
224 // PROP_I_TAXABLE, /* Table */
225 // PROP_I_TAX_INCL, /* Table */
226 // PROP_I_TAXTABLE, /* Table */
227 // PROP_B_ACCT, /* Table */
228 // PROP_B_PRICE, /* Table (numeric) */
229 // PROP_BILL, /* Table */
230 // PROP_B_TAXTABLE_1, /* Table */
231 // PROP_B_TAX_INCL, /* Table */
232 // PROP_B_TAXTABLE, /* Table */
233 // PROP_B_PAYTYPE, /* Table */
234 // PROP_BILLABLE, /* Table */
235 // PROP_BILLTO_TYPE, /* Table */
236 // PROP_BILLTO, /* Table */
237 // PROP_ORDER, /* Table */
238 };
239 
240 /* GObject Initialization */
241 G_DEFINE_TYPE(GncEntry, gnc_entry, QOF_TYPE_INSTANCE)
242 
243 static void
244 gnc_entry_init(GncEntry* entry)
245 {
246 }
247 
248 static void
249 gnc_entry_dispose(GObject *entryp)
250 {
251  G_OBJECT_CLASS(gnc_entry_parent_class)->dispose(entryp);
252 }
253 
254 static void
255 gnc_entry_finalize(GObject* entryp)
256 {
257  G_OBJECT_CLASS(gnc_entry_parent_class)->finalize(entryp);
258 }
259 
260 static void
261 gnc_entry_get_property (GObject *object,
262  guint prop_id,
263  GValue *value,
264  GParamSpec *pspec)
265 {
266  GncEntry *entry;
267 
268  g_return_if_fail(GNC_IS_ENTRY(object));
269 
270  entry = GNC_ENTRY(object);
271  switch (prop_id)
272  {
273  case PROP_DESCRIPTION:
274  g_value_set_string(value, entry->desc);
275  break;
276  default:
277  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
278  break;
279  }
280 }
281 
282 static void
283 gnc_entry_set_property (GObject *object,
284  guint prop_id,
285  const GValue *value,
286  GParamSpec *pspec)
287 {
288  GncEntry *entry;
289 
290  g_return_if_fail(GNC_IS_ENTRY(object));
291 
292  entry = GNC_ENTRY(object);
293  g_assert (qof_instance_get_editlevel(entry));
294 
295  switch (prop_id)
296  {
297  case PROP_DESCRIPTION:
298  gncEntrySetDescription(entry, g_value_get_string(value));
299  break;
300  default:
301  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
302  break;
303  }
304 }
305 
307 static gchar*
308 impl_get_display_name(const QofInstance* inst)
309 {
310  GncEntry* entry;
311  gchar* display_name;
312  gchar* s;
313 
314  g_return_val_if_fail(inst != NULL, FALSE);
315  g_return_val_if_fail(GNC_IS_ENTRY(inst), FALSE);
316 
317  entry = GNC_ENTRY(inst);
318  if (entry->order != NULL)
319  {
320  display_name = qof_instance_get_display_name(QOF_INSTANCE(entry->order));
321  s = g_strdup_printf("Entry in %s", display_name);
322  g_free(display_name);
323  return s;
324  }
325  if (entry->invoice != NULL)
326  {
327  display_name = qof_instance_get_display_name(QOF_INSTANCE(entry->invoice));
328  s = g_strdup_printf("Entry in %s", display_name);
329  g_free(display_name);
330  return s;
331  }
332  if (entry->bill != NULL)
333  {
334  display_name = qof_instance_get_display_name(QOF_INSTANCE(entry->bill));
335  s = g_strdup_printf("Entry in %s", display_name);
336  g_free(display_name);
337  return s;
338  }
339 
340  return g_strdup_printf("Entry %p", inst);
341 }
342 
344 static gboolean
345 impl_refers_to_object(const QofInstance* inst, const QofInstance* ref)
346 {
347  GncEntry* entry;
348 
349  g_return_val_if_fail(inst != NULL, FALSE);
350  g_return_val_if_fail(GNC_IS_ENTRY(inst), FALSE);
351 
352  entry = GNC_ENTRY(inst);
353 
354  if (GNC_IS_ACCOUNT(ref))
355  {
356  Account* acc = GNC_ACCOUNT(ref);
357  return (entry->i_account == acc || entry->b_account == acc);
358  }
359  else if (GNC_IS_TAXTABLE(ref))
360  {
361  GncTaxTable* tt = GNC_TAXTABLE(ref);
362  return (entry->i_tax_table == tt || entry->b_tax_table == tt);
363  }
364 
365  return FALSE;
366 }
367 
374 static GList*
375 impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
376 {
377  if (!GNC_IS_ACCOUNT(ref) && !GNC_IS_TAXTABLE(ref))
378  {
379  return NULL;
380  }
381 
383 }
384 
385 static void
386 gnc_entry_class_init (GncEntryClass *klass)
387 {
388  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
389  QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
390 
391  gobject_class->dispose = gnc_entry_dispose;
392  gobject_class->finalize = gnc_entry_finalize;
393  gobject_class->set_property = gnc_entry_set_property;
394  gobject_class->get_property = gnc_entry_get_property;
395 
396  qof_class->get_display_name = impl_get_display_name;
397  qof_class->refers_to_object = impl_refers_to_object;
398  qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
399 
400  g_object_class_install_property
401  (gobject_class,
402  PROP_DESCRIPTION,
403  g_param_spec_string ("description",
404  "Entry Description",
405  "The description is an arbitrary string "
406  "assigned by the user. It provides identification "
407  "for this entry.",
408  NULL,
409  G_PARAM_READWRITE));
410 }
411 
412 /* Create/Destroy Functions */
413 GncEntry *gncEntryCreate (QofBook *book)
414 {
415  GncEntry *entry;
416  gnc_numeric zero = gnc_numeric_zero ();
417 
418  if (!book) return NULL;
419 
420  entry = g_object_new (GNC_TYPE_ENTRY, NULL);
421  qof_instance_init_data (&entry->inst, _GNC_MOD_NAME, book);
422 
423  entry->desc = CACHE_INSERT ("");
424  entry->action = CACHE_INSERT ("");
425  entry->notes = CACHE_INSERT ("");
426  entry->quantity = zero;
427 
428  entry->i_price = zero;
429  entry->i_taxable = TRUE;
430  entry->i_discount = zero;
431  entry->i_disc_type = GNC_AMT_TYPE_PERCENT;
432  entry->i_disc_how = GNC_DISC_PRETAX;
433 
434  entry->b_price = zero;
435  entry->b_taxable = TRUE;
436  entry->billto.type = GNC_OWNER_CUSTOMER;
437  entry->b_payment = GNC_PAYMENT_CASH;
438 
439  entry->values_dirty = TRUE;
440 
441  qof_event_gen (&entry->inst, QOF_EVENT_CREATE, NULL);
442 
443  return entry;
444 }
445 
446 void gncEntryDestroy (GncEntry *entry)
447 {
448  if (!entry) return;
449  qof_instance_set_destroying(entry, TRUE);
450  gncEntryCommitEdit(entry);
451 }
452 
453 static void gncEntryFree (GncEntry *entry)
454 {
455  if (!entry) return;
456 
457  qof_event_gen (&entry->inst, QOF_EVENT_DESTROY, NULL);
458 
459  CACHE_REMOVE (entry->desc);
460  CACHE_REMOVE (entry->action);
461  CACHE_REMOVE (entry->notes);
462  if (entry->i_tax_values)
463  gncAccountValueDestroy (entry->i_tax_values);
464  if (entry->b_tax_values)
465  gncAccountValueDestroy (entry->b_tax_values);
466 
467  if (!qof_book_shutting_down (qof_instance_get_book (QOF_INSTANCE(entry))))
468  {
469  if (entry->i_tax_table)
470  gncTaxTableDecRef (entry->i_tax_table);
471  if (entry->b_tax_table)
472  gncTaxTableDecRef (entry->b_tax_table);
473  }
474 
475  /* qof_instance_release (&entry->inst); */
476  g_object_unref (entry);
477 }
478 
479 /* ================================================================ */
480 /* Set Functions */
481 
482 void gncEntrySetDate (GncEntry *entry, time64 date)
483 {
484  gboolean first_date = FALSE;
485  if (!entry) return;
486  if (entry->date == date) return;
487  if (!entry->date)
488  first_date = TRUE;
489  gncEntryBeginEdit (entry);
490  entry->date = date;
491  mark_entry (entry);
492  gncEntryCommitEdit (entry);
493 
494  /* Don't re-sort the first time we set the date on this entry */
495  if (!first_date)
496  {
497  if (entry->invoice)
498  gncInvoiceSortEntries(entry->invoice);
499  if (entry->bill)
500  gncInvoiceSortEntries(entry->bill);
501  }
502 }
503 
504 void gncEntrySetDateGDate (GncEntry *entry, const GDate* date)
505 {
506  if (!entry || !date || !g_date_valid(date))
507  return;
508 
509  /* Watch out: Here we are deviating from the initial convention that a
510  GDate always converts to the start time of the day. Instead, the GDate is
511  converted to "noon" on the respective date. This is not nice, but this
512  convention was used for the time64 of GncEntry all the time, so we better
513  stick to it.*/
515 }
516 
517 void gncEntrySetDateEntered (GncEntry *entry, time64 date)
518 {
519  if (!entry) return;
520  if (entry->date_entered == date) return;
521  gncEntryBeginEdit (entry);
522  entry->date_entered = date;
523  mark_entry (entry);
524  gncEntryCommitEdit (entry);
525 }
526 
527 void gncEntrySetDescription (GncEntry *entry, const char *desc)
528 {
529  if (!entry || !desc) return;
530  SET_STR (entry, entry->desc, desc);
531  mark_entry (entry);
532  gncEntryCommitEdit (entry);
533 }
534 
535 void gncEntrySetAction (GncEntry *entry, const char *action)
536 {
537  if (!entry || !action) return;
538  SET_STR (entry, entry->action, action);
539  mark_entry (entry);
540  gncEntryCommitEdit (entry);
541 }
542 
543 void gncEntrySetNotes (GncEntry *entry, const char *notes)
544 {
545  if (!entry || !notes) return;
546  SET_STR (entry, entry->notes, notes);
547  mark_entry (entry);
548  gncEntryCommitEdit (entry);
549 }
550 
551 void gncEntrySetQuantity (GncEntry *entry, gnc_numeric quantity)
552 {
553  if (!entry) return;
554  if (gnc_numeric_eq (entry->quantity, quantity)) return;
555  gncEntryBeginEdit (entry);
556  entry->quantity = quantity;
557  entry->values_dirty = TRUE;
558  mark_entry (entry);
559  gncEntryCommitEdit (entry);
560 }
561 
562 void gncEntrySetDocQuantity (GncEntry *entry, gnc_numeric quantity, gboolean is_cn)
563 {
564  if (!entry) return;
565  if (gnc_numeric_eq (entry->quantity, (is_cn ? gnc_numeric_neg (quantity) : quantity))) return;
566  gncEntryBeginEdit (entry);
567  entry->quantity = (is_cn ? gnc_numeric_neg (quantity) : quantity);
568  entry->values_dirty = TRUE;
569  mark_entry (entry);
570  gncEntryCommitEdit (entry);
571 }
572 
573 /* Customer Invoices */
574 
575 void gncEntrySetInvAccount (GncEntry *entry, Account *acc)
576 {
577  if (!entry) return;
578  if (entry->i_account == acc) return;
579  gncEntryBeginEdit (entry);
580  entry->i_account = acc;
581  mark_entry (entry);
582  gncEntryCommitEdit (entry);
583 }
584 
585 void gncEntrySetInvPrice (GncEntry *entry, gnc_numeric price)
586 {
587  if (!entry) return;
588  if (gnc_numeric_eq (entry->i_price, price)) return;
589  gncEntryBeginEdit (entry);
590  entry->i_price = price;
591  entry->values_dirty = TRUE;
592  mark_entry (entry);
593  gncEntryCommitEdit (entry);
594 }
595 
596 void gncEntrySetInvTaxable (GncEntry *entry, gboolean taxable)
597 {
598  if (!entry) return;
599 
600  ENTER ("%d", taxable);
601  if (entry->i_taxable == taxable) {
602  LEAVE ("Value already set");
603  return;
604  }
605  gncEntryBeginEdit (entry);
606  entry->i_taxable = taxable;
607  entry->values_dirty = TRUE;
608  mark_entry (entry);
609  gncEntryCommitEdit (entry);
610  LEAVE ("");
611 }
612 
613 void gncEntrySetInvTaxIncluded (GncEntry *entry, gboolean taxincluded)
614 {
615  if (!entry) return;
616 
617  ENTER ("%d", taxincluded);
618  if (entry->i_taxincluded == taxincluded) {
619  LEAVE ("Value already set");
620  return;
621  }
622  gncEntryBeginEdit (entry);
623  entry->i_taxincluded = taxincluded;
624  entry->values_dirty = TRUE;
625  mark_entry (entry);
626  gncEntryCommitEdit (entry);
627  LEAVE ("");
628 }
629 
630 void gncEntrySetInvTaxTable (GncEntry *entry, GncTaxTable *table)
631 {
632  if (!entry) return;
633 
634  ENTER ("%s", gncTaxTableGetName (table));
635  if (entry->i_tax_table == table) {
636  LEAVE ("Value already set");
637  return;
638  }
639  gncEntryBeginEdit (entry);
640  if (entry->i_tax_table)
641  gncTaxTableDecRef (entry->i_tax_table);
642  if (table)
643  gncTaxTableIncRef (table);
644  entry->i_tax_table = table;
645  entry->values_dirty = TRUE;
646  mark_entry (entry);
647  gncEntryCommitEdit (entry);
648  LEAVE ("");
649 }
650 
651 void gncEntrySetInvDiscount (GncEntry *entry, gnc_numeric discount)
652 {
653  if (!entry) return;
654  if (gnc_numeric_eq (entry->i_discount, discount)) return;
655  gncEntryBeginEdit (entry);
656  entry->i_discount = discount;
657  entry->values_dirty = TRUE;
658  mark_entry (entry);
659  gncEntryCommitEdit (entry);
660 }
661 
662 void gncEntrySetInvDiscountType (GncEntry *entry, GncAmountType type)
663 {
664  if (!entry) return;
665  if (entry->i_disc_type == type) return;
666 
667  gncEntryBeginEdit (entry);
668  entry->i_disc_type = type;
669  entry->values_dirty = TRUE;
670  mark_entry (entry);
671  gncEntryCommitEdit (entry);
672 }
673 
674 void gncEntrySetInvDiscountHow (GncEntry *entry, GncDiscountHow how)
675 {
676  if (!entry) return;
677  if (entry->i_disc_how == how) return;
678 
679  gncEntryBeginEdit (entry);
680  entry->i_disc_how = how;
681  entry->values_dirty = TRUE;
682  mark_entry (entry);
683  gncEntryCommitEdit (entry);
684 }
685 
686 void qofEntrySetInvDiscType (GncEntry *entry, const char *type_string)
687 {
688  GncAmountType type;
689 
690  if (!entry) return;
691  gncAmountStringToType(type_string, &type);
692  if (entry->i_disc_type == type) return;
693  gncEntryBeginEdit (entry);
694  entry->i_disc_type = type;
695  entry->values_dirty = TRUE;
696  mark_entry (entry);
697  gncEntryCommitEdit (entry);
698 
699 }
700 
701 void qofEntrySetInvDiscHow (GncEntry *entry, const char *type)
702 {
703  GncDiscountHow how = GNC_DISC_PRETAX;
704 
705  if (!entry) return;
706  gncEntryBeginEdit (entry);
707  gncEntryDiscountStringToHow(type, &how);
708  if (entry->i_disc_how == how) return;
709  entry->i_disc_how = how;
710  entry->values_dirty = TRUE;
711  mark_entry (entry);
712  gncEntryCommitEdit (entry);
713 }
714 
715 /* Vendor Bills */
716 
717 void gncEntrySetBillAccount (GncEntry *entry, Account *acc)
718 {
719  if (!entry) return;
720  if (entry->b_account == acc) return;
721  gncEntryBeginEdit (entry);
722  entry->b_account = acc;
723  mark_entry (entry);
724  gncEntryCommitEdit (entry);
725 }
726 
727 void gncEntrySetBillPrice (GncEntry *entry, gnc_numeric price)
728 {
729  if (!entry) return;
730  if (gnc_numeric_eq (entry->b_price, price)) return;
731  gncEntryBeginEdit (entry);
732  entry->b_price = price;
733  entry->values_dirty = TRUE;
734  mark_entry (entry);
735  gncEntryCommitEdit (entry);
736 }
737 
738 void gncEntrySetBillTaxable (GncEntry *entry, gboolean taxable)
739 {
740  if (!entry) return;
741 
742  ENTER ("%d", taxable);
743  if (entry->b_taxable == taxable) {
744  LEAVE ("Value already set");
745  return;
746  }
747  gncEntryBeginEdit (entry);
748  entry->b_taxable = taxable;
749  entry->values_dirty = TRUE;
750  mark_entry (entry);
751  gncEntryCommitEdit (entry);
752  LEAVE ("");
753 }
754 
755 void gncEntrySetBillTaxIncluded (GncEntry *entry, gboolean taxincluded)
756 {
757  if (!entry) return;
758 
759  ENTER ("%d", taxincluded);
760  if (entry->b_taxincluded == taxincluded) {
761  LEAVE ("Value already set");
762  return;
763  }
764  gncEntryBeginEdit (entry);
765  entry->b_taxincluded = taxincluded;
766  entry->values_dirty = TRUE;
767  mark_entry (entry);
768  gncEntryCommitEdit (entry);
769  LEAVE ("");
770 }
771 
772 void gncEntrySetBillTaxTable (GncEntry *entry, GncTaxTable *table)
773 {
774  if (!entry) return;
775 
776  ENTER ("%s", gncTaxTableGetName (table));
777  if (entry->b_tax_table == table) {
778  LEAVE ("Value already set");
779  return;
780  }
781  gncEntryBeginEdit (entry);
782  if (entry->b_tax_table)
783  gncTaxTableDecRef (entry->b_tax_table);
784  if (table)
785  gncTaxTableIncRef (table);
786  entry->b_tax_table = table;
787  entry->values_dirty = TRUE;
788  mark_entry (entry);
789  gncEntryCommitEdit (entry);
790  LEAVE ("");
791 }
792 
793 void gncEntrySetBillable (GncEntry *entry, gboolean billable)
794 {
795  if (!entry) return;
796  if (entry->billable == billable) return;
797 
798  gncEntryBeginEdit (entry);
799  entry->billable = billable;
800  mark_entry (entry);
801  gncEntryCommitEdit (entry);
802 }
803 
804 void gncEntrySetBillTo (GncEntry *entry, GncOwner *billto)
805 {
806  if (!entry || !billto) return;
807  if (gncOwnerEqual (&entry->billto, billto)) return;
808 
809  gncEntryBeginEdit (entry);
810  gncOwnerCopy (billto, &entry->billto);
811  mark_entry (entry);
812  gncEntryCommitEdit (entry);
813 }
814 
815 void gncEntrySetBillPayment (GncEntry *entry, GncEntryPaymentType type)
816 {
817  if (!entry) return;
818  if (entry->b_payment == type) return;
819  gncEntryBeginEdit (entry);
820  entry->b_payment = type;
821  mark_entry (entry);
822  gncEntryCommitEdit (entry);
823 }
824 
825 /* Called from gncOrder when we're added to the Order */
826 void gncEntrySetOrder (GncEntry *entry, GncOrder *order)
827 {
828  if (!entry) return;
829  if (entry->order == order) return;
830  gncEntryBeginEdit (entry);
831  entry->order = order;
832  mark_entry (entry);
833  gncEntryCommitEdit (entry);
834 
835 }
836 
837 /* called from gncInvoice when we're added to the Invoice */
838 void gncEntrySetInvoice (GncEntry *entry, GncInvoice *invoice)
839 {
840  if (!entry) return;
841  if (entry->invoice == invoice) return;
842  gncEntryBeginEdit (entry);
843  entry->invoice = invoice;
844  mark_entry (entry);
845  gncEntryCommitEdit (entry);
846 }
847 
848 /* called from gncInvoice when we're added to the Invoice/Bill */
849 void gncEntrySetBill (GncEntry *entry, GncInvoice *bill)
850 {
851  if (!entry) return;
852  if (entry->bill == bill) return;
853  gncEntryBeginEdit (entry);
854  entry->bill = bill;
855  mark_entry (entry);
856  gncEntryCommitEdit (entry);
857 }
858 
859 void gncEntryCopy (const GncEntry *src, GncEntry *dest, gboolean add_entry)
860 {
861  if (!src || !dest) return;
862 
863  gncEntryBeginEdit (dest);
864  dest->date = src->date;
865  dest->date_entered = src->date_entered; /* ??? */
866  gncEntrySetDescription (dest, src->desc);
867  gncEntrySetAction (dest, src->action);
868  gncEntrySetNotes (dest, src->notes);
869  dest->quantity = src->quantity;
870 
871  dest->i_account = src->i_account;
872  dest->i_price = src->i_price;
873  dest->i_taxable = src->i_taxable;
874  dest->i_taxincluded = src->i_taxincluded;
875  dest->i_discount = src->i_discount;
876  dest->i_disc_type = src->i_disc_type;
877  dest->i_disc_how = src->i_disc_how;
878 
879  /* vendor bill data */
880  dest->b_account = src->b_account;
881  dest->b_price = src->b_price;
882  dest->b_taxable = src->b_taxable;
883  dest->b_taxincluded = src->b_taxincluded;
884  dest->billable = src->billable;
885  dest->billto = src->billto;
886 
887  if (src->i_tax_table)
888  gncEntrySetInvTaxTable (dest, src->i_tax_table);
889 
890  if (src->b_tax_table)
891  gncEntrySetBillTaxTable (dest, src->b_tax_table);
892 
893  if (add_entry)
894  {
895  if (src->order)
896  gncOrderAddEntry (src->order, dest);
897 
898  if (src->invoice)
899  gncInvoiceAddEntry (src->invoice, dest);
900 
901  if (src->bill)
902  gncBillAddEntry (src->bill, dest);
903  }
904 
905  dest->values_dirty = TRUE;
906  mark_entry (dest);
907  gncEntryCommitEdit (dest);
908 }
909 
910 /* ================================================================ */
911 /* Get Functions */
912 
913 time64 gncEntryGetDate (const GncEntry *entry)
914 {
915  return entry ? entry->date : 0;
916 }
917 
918 GDate gncEntryGetDateGDate(const GncEntry *entry)
919 {
920  return time64_to_gdate(gncEntryGetDate(entry));
921 }
922 
923 time64 gncEntryGetDateEntered (const GncEntry *entry)
924 {
925  return entry ? entry->date_entered : 0;
926 }
927 
928 const char * gncEntryGetDescription (const GncEntry *entry)
929 {
930  if (!entry) return NULL;
931  return entry->desc;
932 }
933 
934 const char * gncEntryGetAction (const GncEntry *entry)
935 {
936  if (!entry) return NULL;
937  return entry->action;
938 }
939 
940 const char * gncEntryGetNotes (const GncEntry *entry)
941 {
942  if (!entry) return NULL;
943  return entry->notes;
944 }
945 
946 gnc_numeric gncEntryGetQuantity (const GncEntry *entry)
947 {
948  if (!entry) return gnc_numeric_zero();
949  return entry->quantity;
950 }
951 
952 gnc_numeric gncEntryGetDocQuantity (const GncEntry *entry, gboolean is_cn)
953 {
954  gnc_numeric value = gncEntryGetQuantity (entry);
955  return (is_cn ? gnc_numeric_neg (value) : value);
956 }
957 
958 /* Customer Invoice */
959 
960 Account * gncEntryGetInvAccount (const GncEntry *entry)
961 {
962  if (!entry) return NULL;
963  return entry->i_account;
964 }
965 
966 gnc_numeric gncEntryGetInvPrice (const GncEntry *entry)
967 {
968  if (!entry) return gnc_numeric_zero();
969  return entry->i_price;
970 }
971 
972 gnc_numeric gncEntryGetInvDiscount (const GncEntry *entry)
973 {
974  if (!entry) return gnc_numeric_zero();
975  return entry->i_discount;
976 }
977 
978 GncAmountType gncEntryGetInvDiscountType (const GncEntry *entry)
979 {
980  if (!entry) return 0;
981  return entry->i_disc_type;
982 }
983 
984 GncDiscountHow gncEntryGetInvDiscountHow (const GncEntry *entry)
985 {
986  if (!entry) return 0;
987  return entry->i_disc_how;
988 }
989 
990 char* qofEntryGetInvDiscType (const GncEntry *entry)
991 {
992  char *type_string;
993 
994  if (!entry) return 0;
995  type_string = g_strdup(gncAmountTypeToString(entry->i_disc_type));
996  return type_string;
997 }
998 
999 char* qofEntryGetInvDiscHow (const GncEntry *entry)
1000 {
1001  char *type_string;
1002 
1003  if (!entry) return 0;
1004  type_string = g_strdup(gncEntryDiscountHowToString(entry->i_disc_how));
1005  return type_string;
1006 }
1007 
1008 gboolean gncEntryGetInvTaxable (const GncEntry *entry)
1009 {
1010  if (!entry) return FALSE;
1011  return entry->i_taxable;
1012 }
1013 
1014 gboolean gncEntryGetInvTaxIncluded (const GncEntry *entry)
1015 {
1016  if (!entry) return FALSE;
1017  return entry->i_taxincluded;
1018 }
1019 
1020 GncTaxTable * gncEntryGetInvTaxTable (const GncEntry *entry)
1021 {
1022  if (!entry) return NULL;
1023  return entry->i_tax_table;
1024 }
1025 
1026 /* vendor bills */
1027 
1028 Account * gncEntryGetBillAccount (const GncEntry *entry)
1029 {
1030  if (!entry) return NULL;
1031  return entry->b_account;
1032 }
1033 
1034 gnc_numeric gncEntryGetBillPrice (const GncEntry *entry)
1035 {
1036  if (!entry) return gnc_numeric_zero();
1037  return entry->b_price;
1038 }
1039 
1040 gboolean gncEntryGetBillTaxable (const GncEntry *entry)
1041 {
1042  if (!entry) return FALSE;
1043  return entry->b_taxable;
1044 }
1045 
1046 gboolean gncEntryGetBillTaxIncluded (const GncEntry *entry)
1047 {
1048  if (!entry) return FALSE;
1049  return entry->b_taxincluded;
1050 }
1051 
1052 GncTaxTable * gncEntryGetBillTaxTable (const GncEntry *entry)
1053 {
1054  if (!entry) return NULL;
1055  return entry->b_tax_table;
1056 }
1057 
1058 gboolean gncEntryGetBillable (const GncEntry *entry)
1059 {
1060  if (!entry) return FALSE;
1061  return entry->billable;
1062 }
1063 
1064 GncOwner * gncEntryGetBillTo (GncEntry *entry)
1065 {
1066  if (!entry) return NULL;
1067  return &entry->billto;
1068 }
1069 
1070 GncEntryPaymentType gncEntryGetBillPayment (const GncEntry* entry)
1071 {
1072  if (!entry) return 0;
1073  return entry->b_payment;
1074 }
1075 
1076 GncInvoice * gncEntryGetInvoice (const GncEntry *entry)
1077 {
1078  if (!entry) return NULL;
1079  return entry->invoice;
1080 }
1081 
1082 GncInvoice * gncEntryGetBill (const GncEntry *entry)
1083 {
1084  if (!entry) return NULL;
1085  return entry->bill;
1086 }
1087 
1088 GncOrder * gncEntryGetOrder (const GncEntry *entry)
1089 {
1090  if (!entry) return NULL;
1091  return entry->order;
1092 }
1093 
1094 /* ================================================================ */
1095 /*
1096  * This is the logic of computing the total for an Entry, so you know
1097  * what values to put into various Splits or to display in the ledger.
1098  * In other words, we combine the quantity, unit-price, discount and
1099  * taxes together, depending on various flags.
1100  *
1101  * There are four potential ways to combine these numbers:
1102  * Discount: Pre-Tax Post-Tax
1103  * Tax : Included Not-Included
1104  *
1105  * The process is relatively simple:
1106  *
1107  * 1) compute the aggregate price (price*qty)
1108  * 2) if taxincluded, then back-compute the aggregate pre-tax price
1109  * 3) apply discount and taxes in the appropriate order
1110  * 4) return the requested results.
1111  *
1112  * Step 2 can be done with aggregate taxes; no need to compute them all
1113  * unless the caller asked for the tax_value.
1114  *
1115  * Note that the returned "value" is such that
1116  * value + tax == "total to pay"
1117  * which means in the case of tax-included that the returned
1118  * "value" may be less than the aggregate price, even without a
1119  * discount. If you want to display the tax-included value, you need
1120  * to add the value and taxes together. In other words, the value is
1121  * the amount the merchant gets; the taxes are the amount the gov't
1122  * gets, and the customer pays the sum or value + taxes.
1123  *
1124  * The discount return value is just for entertainment -- you may want
1125  * to let a consumer know how much they saved.
1126  *
1127  * Note this function will not do any rounding unless forced to prevent overflow.
1128  * It's the caller's responsibility to round to the proper commodity
1129  * denominator if needed.
1130  */
1131 static void gncEntryComputeValueInt (gnc_numeric qty, gnc_numeric price,
1132  const GncTaxTable *tax_table, gboolean tax_included,
1133  gnc_numeric discount, GncAmountType discount_type,
1134  GncDiscountHow discount_how,
1135  gnc_numeric *value, gnc_numeric *discount_value,
1136  GList **tax_value, gnc_numeric *net_price)
1137 {
1138  gnc_numeric aggregate;
1139  gnc_numeric pretax;
1140  gnc_numeric result;
1141  gnc_numeric tax;
1142  gnc_numeric percent = gnc_numeric_create (100, 1);
1143  gnc_numeric tpercent = gnc_numeric_zero ();
1144  gnc_numeric tvalue = gnc_numeric_zero ();
1145  gnc_numeric i_net_price = price;
1146 
1147  GList * entries = gncTaxTableGetEntries (tax_table);
1148  GList * node;
1149 
1150  ENTER ("");
1151  /* Step 1: compute the aggregate price */
1152 
1154 
1155  PINFO ("Aggregate value %" PRId64 "/%" PRId64, aggregate.num, aggregate.denom);
1156  /* Step 2: compute the pre-tax aggregate */
1157 
1158  /* First, compute the aggregate tpercent and tvalue numbers */
1159  for (node = entries; node; node = node->next)
1160  {
1161  GncTaxTableEntry *entry = node->data;
1162  gnc_numeric amount = gncTaxTableEntryGetAmount (entry);
1163 
1164  switch (gncTaxTableEntryGetType (entry))
1165  {
1166  case GNC_AMT_TYPE_VALUE:
1167  tvalue = gnc_numeric_add (tvalue, amount, GNC_DENOM_AUTO,
1169  break;
1170  case GNC_AMT_TYPE_PERCENT:
1171  tpercent = gnc_numeric_add (tpercent, amount, GNC_DENOM_AUTO,
1173  break;
1174  default:
1175  PWARN ("Unknown tax type: %d", gncTaxTableEntryGetType (entry));
1176  break;
1177  }
1178  }
1179  /* now we need to convert from 5% -> .05 */
1180  tpercent = gnc_numeric_div (tpercent, percent, GNC_DENOM_AUTO,
1182  PINFO("Tax rate %" PRId64 "/%" PRId64, tpercent.num, tpercent.denom);
1183  /* Next, actually compute the pre-tax aggregate value based on the
1184  * taxincluded flag.
1185  */
1186  if (tax_table && tax_included)
1187  {
1188  /* Back-compute the pre-tax aggregate value.
1189  * We know that aggregate = pretax + pretax*tpercent + tvalue, so
1190  * pretax = (aggregate-tvalue)/(1+tpercent)
1191  */
1192  pretax = gnc_numeric_sub (aggregate, tvalue, GNC_DENOM_AUTO,
1194  pretax = gnc_numeric_div (pretax,
1195  gnc_numeric_add (tpercent,
1196  gnc_numeric_create (1, 1),
1199  PINFO ("pretax %" PRId64 "/%" PRId64, pretax.num, pretax.denom);
1200  if (!gnc_numeric_zero_p(qty))
1201  {
1202  i_net_price = gnc_numeric_div (pretax, qty, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE | GNC_HOW_RND_ROUND);
1203  }
1204  PINFO("i_net_price %" PRId64 "/%" PRId64, i_net_price.num, i_net_price.denom);
1205  }
1206  else
1207  {
1208  PINFO ("Tax not included or no tax table, pretax is aggregate");
1209  pretax = aggregate;
1210  }
1211 
1212  /* Step 3: apply discount and taxes in the appropriate order */
1213 
1214  /*
1215  * There are two ways to apply discounts and taxes. In one way, you
1216  * always compute the discount off the pretax number, and compute
1217  * the taxes off of either the pretax value or "pretax-discount"
1218  * value. In the other way, you always compute the tax on "pretax",
1219  * and compute the discount on either "pretax" or "pretax+taxes".
1220  *
1221  * I don't know which is the "correct" way.
1222  */
1223 
1224  /*
1225  * Type: discount tax
1226  * PRETAX pretax pretax-discount
1227  * SAMETIME pretax pretax
1228  * POSTTAX pretax+tax pretax
1229  */
1230 
1231  switch (discount_how)
1232  {
1233  case GNC_DISC_PRETAX:
1234  case GNC_DISC_SAMETIME:
1235  /* compute the discount from pretax */
1236 
1237  if (discount_type == GNC_AMT_TYPE_PERCENT)
1238  {
1239  discount = gnc_numeric_div (discount, percent, GNC_DENOM_AUTO,
1241  discount = gnc_numeric_mul (pretax, discount, GNC_DENOM_AUTO,
1243  }
1244 
1245  result = gnc_numeric_sub (pretax, discount, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
1246 
1247  /* Figure out when to apply the tax, pretax or pretax-discount */
1248  if (discount_how == GNC_DISC_PRETAX)
1249  pretax = result;
1250  break;
1251 
1252  case GNC_DISC_POSTTAX:
1253  /* compute discount on pretax+taxes */
1254 
1255  if (discount_type == GNC_AMT_TYPE_PERCENT)
1256  {
1257  gnc_numeric after_tax;
1258 
1260  after_tax = gnc_numeric_add (pretax, tax, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
1261  after_tax = gnc_numeric_add (after_tax, tvalue, GNC_DENOM_AUTO,
1263  discount = gnc_numeric_div (discount, percent, GNC_DENOM_AUTO,
1265  discount = gnc_numeric_mul (after_tax, discount, GNC_DENOM_AUTO,
1267  }
1268 
1269  result = gnc_numeric_sub (pretax, discount, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
1270  break;
1271 
1272  default:
1273  PWARN ("unknown DiscountHow value: %d", discount_how);
1274  break;
1275  }
1276 
1277  /* Step 4: return the requested results. */
1278 
1279  /* result == amount merchant gets
1280  * discount == amount of discount
1281  * need to compute taxes (based on 'pretax') if the caller wants it.
1282  */
1283 
1284  if (discount_value != NULL)
1285  *discount_value = discount;
1286 
1287  if (value != NULL)
1288  *value = result;
1289 
1290  /* Now... Compute the list of tax values (if the caller wants it) */
1291 
1292  if (tax_value != NULL)
1293  {
1294  GList * taxes = NULL;
1295 
1296  PINFO("Computing tax value list");
1297  for (node = entries; node; node = node->next)
1298  {
1299  GncTaxTableEntry *entry = node->data;
1300  Account *acc = gncTaxTableEntryGetAccount (entry);
1301  gnc_numeric amount = gncTaxTableEntryGetAmount (entry);
1302 
1303  g_return_if_fail (acc);
1304 
1305  switch (gncTaxTableEntryGetType (entry))
1306  {
1307  case GNC_AMT_TYPE_VALUE:
1308  taxes = gncAccountValueAdd (taxes, acc, amount);
1309  break;
1310  case GNC_AMT_TYPE_PERCENT:
1311  amount = gnc_numeric_div (amount, percent, GNC_DENOM_AUTO,
1314  taxes = gncAccountValueAdd (taxes, acc, tax);
1315  break;
1316  default:
1317  break;
1318  }
1319  }
1320  *tax_value = taxes;
1321  }
1322 
1323  if (net_price != NULL)
1324  *net_price = i_net_price;
1325 
1326  LEAVE ("");
1327  return;
1328 }
1329 
1330 void gncEntryComputeValue (gnc_numeric qty, gnc_numeric price,
1331  const GncTaxTable *tax_table, gboolean tax_included,
1332  gnc_numeric discount, GncAmountType discount_type,
1333  GncDiscountHow discount_how, G_GNUC_UNUSED int SCU,
1334  gnc_numeric *value, gnc_numeric *discount_value,
1335  GList **tax_value)
1336 {
1337  gncEntryComputeValueInt (qty, price, tax_table, tax_included, discount, discount_type,
1338  discount_how, value, discount_value, tax_value, NULL);
1339 }
1340 
1341 static int
1342 get_entry_commodity_denom (const GncEntry *entry)
1343 {
1344  gnc_commodity *c;
1345  if (!entry)
1346  return 0;
1347  if (entry->invoice)
1348  {
1349  c = gncInvoiceGetCurrency (entry->invoice);
1350  if (c)
1351  return (gnc_commodity_get_fraction (c));
1352  }
1353  if (entry->bill)
1354  {
1355  c = gncInvoiceGetCurrency (entry->bill);
1356  if (c)
1357  return (gnc_commodity_get_fraction (c));
1358  }
1359  return 100000;
1360 }
1361 
1362 static void
1363 gncEntryRecomputeValues (GncEntry *entry)
1364 {
1365  int denom;
1366  GList *tv_iter;
1367 
1368  ENTER ("");
1369  /* See if either tax table changed since we last computed values */
1370  if (entry->i_tax_table)
1371  {
1372  time64 modtime = gncTaxTableLastModifiedSecs (entry->i_tax_table);
1373  if (entry->i_taxtable_modtime != modtime)
1374  {
1375  PINFO ("Invoice tax table changed since last recompute.");
1376  entry->values_dirty = TRUE;
1377  entry->i_taxtable_modtime = modtime;
1378  }
1379  }
1380  if (entry->b_tax_table)
1381  {
1382  time64 modtime = gncTaxTableLastModifiedSecs (entry->b_tax_table);
1383  if (entry->b_taxtable_modtime != modtime)
1384  {
1385  PINFO ("Bill tax table changed since last recompute.");
1386  entry->values_dirty = TRUE;
1387  entry->b_taxtable_modtime = modtime;
1388  }
1389  }
1390 
1391  if (!entry->values_dirty) {
1392  LEAVE ("No changes");
1393  return;
1394  }
1395 
1396  /* Clear the last-computed tax values */
1397  if (entry->i_tax_values)
1398  {
1399  gncAccountValueDestroy (entry->i_tax_values);
1400  entry->i_tax_values = NULL;
1401  }
1402  if (entry->b_tax_values)
1403  {
1404  gncAccountValueDestroy (entry->b_tax_values);
1405  entry->b_tax_values = NULL;
1406  }
1407 
1408  /* Determine the commodity denominator */
1409  denom = get_entry_commodity_denom (entry);
1410 
1411  /* Compute the invoice values */
1412  DEBUG("Compute Invoice Values.");
1413  gncEntryComputeValue (entry->quantity, entry->i_price,
1414  (entry->i_taxable ? entry->i_tax_table : NULL),
1415  entry->i_taxincluded,
1416  entry->i_discount, entry->i_disc_type,
1417  entry->i_disc_how,
1418  denom,
1419  &(entry->i_value), &(entry->i_disc_value),
1420  &(entry->i_tax_values));
1421 
1422  /* Compute the bill values */
1423  DEBUG("Compute BILL Values.");
1424  gncEntryComputeValue (entry->quantity, entry->b_price,
1425  (entry->b_taxable ? entry->b_tax_table : NULL),
1426  entry->b_taxincluded,
1427  gnc_numeric_zero(), GNC_AMT_TYPE_VALUE, GNC_DISC_PRETAX,
1428  denom,
1429  &(entry->b_value), NULL, &(entry->b_tax_values));
1430 
1431  entry->i_value_rounded = gnc_numeric_convert (entry->i_value, denom,
1433  entry->i_disc_value_rounded = gnc_numeric_convert (entry->i_disc_value, denom,
1435  entry->i_tax_value = gncAccountValueTotal (entry->i_tax_values);
1436  entry->i_tax_value_rounded = gnc_numeric_zero();
1437  for (tv_iter = entry->i_tax_values; tv_iter; tv_iter=tv_iter->next)
1438  {
1439  GncAccountValue *acc_val = tv_iter->data;
1440  entry->i_tax_value_rounded = gnc_numeric_add (entry->i_tax_value_rounded, acc_val->value,
1442  }
1443 
1444  entry->b_value_rounded = gnc_numeric_convert (entry->b_value, denom,
1446  entry->b_tax_value = gncAccountValueTotal (entry->b_tax_values);
1447  entry->b_tax_value_rounded = gnc_numeric_zero();
1448  for (tv_iter = entry->b_tax_values; tv_iter; tv_iter=tv_iter->next)
1449  {
1450  GncAccountValue *acc_val = tv_iter->data;
1451  entry->b_tax_value_rounded = gnc_numeric_add (entry->b_tax_value_rounded, acc_val->value,
1453  }
1454  entry->values_dirty = FALSE;
1455  LEAVE ("");
1456 }
1457 
1458 /* The "Int" functions below are for internal use only.
1459  * Outside this file, use the "Doc" or "Bal" variants found below instead. */
1460 static gnc_numeric gncEntryGetIntValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1461 {
1462  if (!entry) return gnc_numeric_zero();
1463  gncEntryRecomputeValues (entry);
1464  if (round)
1465  return (is_cust_doc ? entry->i_value_rounded : entry->b_value_rounded);
1466  else
1467  return (is_cust_doc ? entry->i_value : entry->b_value);
1468 }
1469 
1470 static gnc_numeric gncEntryGetIntTaxValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1471 {
1472  if (!entry) return gnc_numeric_zero();
1473  gncEntryRecomputeValues (entry);
1474  if (round)
1475  return (is_cust_doc ? entry->i_tax_value_rounded : entry->b_tax_value_rounded);
1476  else
1477  return (is_cust_doc ? entry->i_tax_value : entry->b_tax_value);
1478 }
1479 
1480 /* Careful: the returned list is managed by the entry, and will only be valid for a short time */
1481 static AccountValueList * gncEntryGetIntTaxValues (GncEntry *entry, gboolean is_cust_doc)
1482 {
1483  if (!entry) return NULL;
1484  gncEntryRecomputeValues (entry);
1485  return (is_cust_doc ? entry->i_tax_values : entry->b_tax_values);
1486 }
1487 
1488 static gnc_numeric gncEntryGetIntDiscountValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1489 {
1490  if (!entry) return gnc_numeric_zero();
1491  gncEntryRecomputeValues (entry);
1492  if (round)
1493  return (is_cust_doc ? entry->i_disc_value_rounded : gnc_numeric_zero());
1494  else
1495  return (is_cust_doc ? entry->i_disc_value : gnc_numeric_zero());
1496 }
1497 
1498 /* Note contrary to the GetDoc*Value and GetBal*Value functions below
1499  * this function will always round the net price to the entry's
1500  * currency denominator (being the invoice/bill denom or 100000 if not
1501  * included in a bill or invoice) */
1502 gnc_numeric gncEntryGetPrice (const GncEntry *entry, gboolean cust_doc, gboolean net)
1503 {
1504  gnc_numeric result;
1505  int denom;
1506 
1507  if (!entry) return gnc_numeric_zero();
1508  if (!net) return (cust_doc ? entry->i_price : entry->b_price);
1509 
1510 
1511  /* Compute the net price */
1512  if (cust_doc)
1513  gncEntryComputeValueInt (entry->quantity, entry->i_price,
1514  (entry->i_taxable ? entry->i_tax_table : NULL),
1515  entry->i_taxincluded,
1516  entry->i_discount, entry->i_disc_type,
1517  entry->i_disc_how,
1518  NULL, NULL, NULL, &result);
1519  else
1520  gncEntryComputeValueInt (entry->quantity, entry->b_price,
1521  (entry->b_taxable ? entry->b_tax_table : NULL),
1522  entry->b_taxincluded,
1523  gnc_numeric_zero(), GNC_AMT_TYPE_VALUE, GNC_DISC_PRETAX,
1524  NULL, NULL, NULL, &result);
1525 
1526  /* Determine the commodity denominator */
1527  denom = get_entry_commodity_denom (entry);
1528 
1529  result = gnc_numeric_convert (result, denom,
1531 
1532  return result;
1533 }
1534 
1535 gnc_numeric gncEntryGetDocValue (GncEntry *entry, gboolean round, gboolean is_cust_doc, gboolean is_cn)
1536 {
1537  gnc_numeric value = gncEntryGetIntValue (entry, round, is_cust_doc);
1538  return (is_cn ? gnc_numeric_neg (value) : value);
1539 }
1540 
1541 gnc_numeric gncEntryGetDocTaxValue (GncEntry *entry, gboolean round, gboolean is_cust_doc, gboolean is_cn)
1542 {
1543  gnc_numeric value = gncEntryGetIntTaxValue (entry, round, is_cust_doc);
1544  return (is_cn ? gnc_numeric_neg (value) : value);
1545 }
1546 
1547 /* Careful: the returned list is NOT owned by the entry and should be freed by the caller */
1548 AccountValueList * gncEntryGetDocTaxValues (GncEntry *entry, gboolean is_cust_doc, gboolean is_cn)
1549 {
1550  AccountValueList *int_values = gncEntryGetIntTaxValues (entry, is_cust_doc);
1551  AccountValueList *values = NULL, *node;
1552 
1553  /* Make a copy of the list with negated values if necessary. */
1554  for (node = int_values; node; node = node->next)
1555  {
1556  GncAccountValue *acct_val = node->data;
1557  values = gncAccountValueAdd (values, acct_val->account,
1558  (is_cn ? gnc_numeric_neg (acct_val->value)
1559  : acct_val->value));
1560  }
1561 
1562  return values;
1563 }
1564 
1565 gnc_numeric gncEntryGetDocDiscountValue (GncEntry *entry, gboolean round, gboolean is_cust_doc, gboolean is_cn)
1566 {
1567  gnc_numeric value = gncEntryGetIntDiscountValue (entry, round, is_cust_doc);
1568  return (is_cn ? gnc_numeric_neg (value) : value);
1569 }
1570 
1571 gnc_numeric gncEntryGetBalValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1572 {
1573  gnc_numeric value = gncEntryGetIntValue (entry, round, is_cust_doc);
1574  return (is_cust_doc ? gnc_numeric_neg (value) : value);
1575 }
1576 
1577 gnc_numeric gncEntryGetBalTaxValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1578 {
1579  gnc_numeric value = gncEntryGetIntTaxValue (entry, round, is_cust_doc);
1580  return (is_cust_doc ? gnc_numeric_neg (value) : value);
1581 }
1582 
1583 /* Careful: the returned list is NOT owned by the entry and should be freed by the caller */
1584 AccountValueList * gncEntryGetBalTaxValues (GncEntry *entry, gboolean is_cust_doc)
1585 {
1586  AccountValueList *int_values = gncEntryGetIntTaxValues (entry, is_cust_doc);
1587  AccountValueList *values = NULL, *node;
1588 
1589  /* Make a copy of the list with negated values if necessary. */
1590  for (node = int_values; node; node = node->next)
1591  {
1592  GncAccountValue *acct_val = node->data;
1593  values = gncAccountValueAdd (values, acct_val->account,
1594  (is_cust_doc ? gnc_numeric_neg (acct_val->value)
1595  : acct_val->value));
1596  }
1597 
1598  return values;
1599 }
1600 
1601 gnc_numeric gncEntryGetBalDiscountValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1602 {
1603  gnc_numeric value = gncEntryGetIntDiscountValue (entry, round, is_cust_doc);
1604  return (is_cust_doc ? gnc_numeric_neg (value) : value);
1605 }
1606 
1607 /* XXX this existence of this routine is just wrong */
1608 gboolean gncEntryIsOpen (const GncEntry *entry)
1609 {
1610  if (!entry) return FALSE;
1611  return (qof_instance_get_editlevel(entry) > 0);
1612 }
1613 
1614 /* ================================================================ */
1615 
1616 void gncEntryBeginEdit (GncEntry *entry)
1617 {
1618  qof_begin_edit(&entry->inst);
1619 }
1620 
1621 static void gncEntryOnError (QofInstance *entry, QofBackendError errcode)
1622 {
1623  PERR("Entry QofBackend Failure: %d", errcode);
1624  gnc_engine_signal_commit_error( errcode );
1625 }
1626 
1627 static void gncEntryOnDone (QofInstance *inst) {}
1628 
1629 static void entry_free (QofInstance *inst)
1630 {
1631  GncEntry *entry = (GncEntry *)inst;
1632  gncEntryFree (entry);
1633 }
1634 
1635 void gncEntryCommitEdit (GncEntry *entry)
1636 {
1637  /* GnuCash 2.6.3 and earlier didn't handle entry kvp's... */
1638  if (qof_instance_has_kvp(QOF_INSTANCE(entry)))
1639  gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (entry)),
1640  GNC_FEATURE_KVP_EXTRA_DATA);
1641 
1642  if (!qof_commit_edit (QOF_INSTANCE(entry))) return;
1643  qof_commit_edit_part2 (&entry->inst, gncEntryOnError,
1644  gncEntryOnDone, entry_free);
1645 }
1646 
1647 int gncEntryCompare (const GncEntry *a, const GncEntry *b)
1648 {
1649  int compare;
1650 
1651  if (a == b) return 0;
1652  if (!a && b) return -1;
1653  if (a && !b) return 1;
1654  g_assert (a && b); /* Silence a static analysis warning. */
1655  if (a->date != b->date) return a->date - b->date;
1656  if (a->date_entered != b->date_entered) return a->date_entered - b->date_entered;
1657 
1658  compare = g_strcmp0 (a->desc, b->desc);
1659  if (compare) return compare;
1660 
1661  compare = g_strcmp0 (a->action, b->action);
1662  if (compare) return compare;
1663 
1664  return qof_instance_guid_compare(a, b);
1665 }
1666 
1667 #define CHECK_STRING(X, Y, FIELD) \
1668  if (g_strcmp0((X)->FIELD, (Y)->FIELD) != 0) \
1669  { \
1670  PWARN("%s differ: %s vs %s", #FIELD, (X)->FIELD, (Y)->FIELD); \
1671  return FALSE; \
1672  }
1673 
1674 #define CHECK_ACCOUNT(X, Y, FIELD) \
1675  if (!xaccAccountEqual((X)->FIELD, (Y)->FIELD, TRUE)) \
1676  { \
1677  PWARN("%s differ", #FIELD); \
1678  return FALSE; \
1679  }
1680 
1681 #define CHECK_NUMERIC(X, Y, FIELD) \
1682  if (!gnc_numeric_equal((X)->FIELD, (Y)->FIELD)) \
1683  { \
1684  PWARN("%s differ", #FIELD); \
1685  return FALSE; \
1686  }
1687 
1688 #define CHECK_VALUE(X, Y, FIELD) \
1689  if ((X)->FIELD != (Y)->FIELD) \
1690  { \
1691  PWARN("%s differ", #FIELD); \
1692  return FALSE; \
1693  }
1694 
1695 
1696 /* ============================================================= */
1697 /* Object declaration */
1698 
1699 static void
1700 destroy_entry_on_book_close(QofInstance *ent, gpointer data)
1701 {
1702  GncEntry* entry = GNC_ENTRY(ent);
1703 
1704  gncEntryBeginEdit(entry);
1705  gncEntryDestroy(entry);
1706 }
1707 
1712 static void
1713 gnc_entry_book_end(QofBook* book)
1714 {
1715  QofCollection *col;
1716 
1717  col = qof_book_get_collection(book, GNC_ID_ENTRY);
1718  qof_collection_foreach(col, destroy_entry_on_book_close, NULL);
1719 }
1720 
1721 static QofObject gncEntryDesc =
1722 {
1723  DI(.interface_version = ) QOF_OBJECT_VERSION,
1724  DI(.e_type = ) _GNC_MOD_NAME,
1725  DI(.type_label = ) "Order/Invoice/Bill Entry",
1726  DI(.create = ) (gpointer)gncEntryCreate,
1727  DI(.book_begin = ) NULL,
1728  DI(.book_end = ) gnc_entry_book_end,
1729  DI(.is_dirty = ) qof_collection_is_dirty,
1730  DI(.mark_clean = ) qof_collection_mark_clean,
1731  DI(.foreach = ) qof_collection_foreach,
1732  DI(.printable = ) NULL,
1733  DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
1734 };
1735 
1736 gboolean gncEntryRegister (void)
1737 {
1738  static QofParam params[] =
1739  {
1740  { ENTRY_DATE, QOF_TYPE_DATE, (QofAccessFunc)gncEntryGetDate, (QofSetterFunc)gncEntrySetDate },
1741  { ENTRY_DATE_ENTERED, QOF_TYPE_DATE, (QofAccessFunc)gncEntryGetDateEntered, (QofSetterFunc)gncEntrySetDateEntered },
1742  { ENTRY_DESC, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetDescription, (QofSetterFunc)gncEntrySetDescription },
1743  { ENTRY_ACTION, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetAction, (QofSetterFunc)gncEntrySetAction },
1744  { ENTRY_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetNotes, (QofSetterFunc)gncEntrySetNotes },
1745  { ENTRY_QTY, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetQuantity, (QofSetterFunc)gncEntrySetQuantity },
1746  { ENTRY_IPRICE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetInvPrice, (QofSetterFunc)gncEntrySetInvPrice },
1747  { ENTRY_BPRICE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetBillPrice, (QofSetterFunc)gncEntrySetBillPrice },
1748  { ENTRY_INVOICE, GNC_ID_INVOICE, (QofAccessFunc)gncEntryGetInvoice, NULL },
1749  { ENTRY_IACCT, GNC_ID_ACCOUNT, (QofAccessFunc)gncEntryGetInvAccount, (QofSetterFunc)gncEntrySetInvAccount },
1750  { ENTRY_BACCT, GNC_ID_ACCOUNT, (QofAccessFunc)gncEntryGetBillAccount, (QofSetterFunc)gncEntrySetBillAccount },
1751  { ENTRY_BILL, GNC_ID_INVOICE, (QofAccessFunc)gncEntryGetBill, NULL },
1752  {
1753  ENTRY_INV_DISC_TYPE, QOF_TYPE_STRING, (QofAccessFunc)qofEntryGetInvDiscType,
1754  (QofSetterFunc)qofEntrySetInvDiscType
1755  },
1756  {
1757  ENTRY_INV_DISC_HOW, QOF_TYPE_STRING, (QofAccessFunc)qofEntryGetInvDiscHow,
1758  (QofSetterFunc)qofEntrySetInvDiscHow
1759  },
1760  {
1761  ENTRY_INV_TAXABLE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetInvTaxable,
1762  (QofSetterFunc)gncEntrySetInvTaxable
1763  },
1764  {
1765  ENTRY_INV_TAX_INC, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetInvTaxIncluded,
1766  (QofSetterFunc)gncEntrySetInvTaxIncluded
1767  },
1768  {
1769  ENTRY_BILL_TAXABLE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetBillTaxable,
1770  (QofSetterFunc)gncEntrySetBillTaxable
1771  },
1772  {
1773  ENTRY_BILL_TAX_INC, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetBillTaxIncluded,
1774  (QofSetterFunc)gncEntrySetBillTaxIncluded
1775  },
1776  { ENTRY_BILLABLE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetBillable, (QofSetterFunc)gncEntrySetBillable },
1777  { ENTRY_BILLTO, GNC_ID_OWNER, (QofAccessFunc)gncEntryGetBillTo, (QofSetterFunc)gncEntrySetBillTo },
1778  { ENTRY_ORDER, GNC_ID_ORDER, (QofAccessFunc)gncEntryGetOrder, NULL },
1779  { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
1780  { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
1781  { NULL },
1782  };
1783 
1784  qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncEntryCompare, params);
1785 
1786  return qof_object_register (&gncEntryDesc);
1787 }
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
Compare two instances, based on their last update times.
Never round at all, and signal an error if there is a fractional result in a computation.
Definition: gnc-numeric.h:177
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
void gncEntrySetQuantity(GncEntry *entry, gnc_numeric quantity)
Set the internal quantity without any conversion.
Definition: gncEntry.c:551
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
gboolean qof_collection_is_dirty(const QofCollection *col)
Return value of &#39;dirty&#39; flag on collection.
Definition: qofid.cpp:255
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
QofBackendError
The errors that can be reported to the GUI & other front-end users.
Definition: qofbackend.h:57
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value...
STRUCTS.
GList * qof_instance_get_referring_object_list_from_collection(const QofCollection *coll, const QofInstance *ref)
Returns a list of objects from the collection which refer to the specific object. ...
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
void gnc_features_set_used(QofBook *book, const gchar *feature)
Indicate that the current book uses the given feature.
AccountValueList * gncEntryGetDocTaxValues(GncEntry *entry, gboolean is_cust_doc, gboolean is_cn)
Careful: the returned list is NOT owned by the entry and should be freed by the caller.
Definition: gncEntry.c:1548
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_function, const QofParam *params)
This function registers a new object class with the Qof subsystem.
Definition: qofclass.cpp:86
gboolean gncOwnerEqual(const GncOwner *a, const GncOwner *b)
Assess equality by checking.
Definition: gncOwner.c:404
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a+b.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
GDate time64_to_gdate(time64 t)
Returns the GDate in which the time64 occurs.
Definition: gnc-date.cpp:1210
QofCollection * qof_instance_get_collection(gconstpointer ptr)
Return the collection this instance belongs to.
gnc_numeric gncAccountValueTotal(GList *list)
return the total for this list
Definition: gncTaxTable.c:984
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:188
int(* QofSortFunc)(gconstpointer, gconstpointer)
This function is the default sort function for a particular object type.
Definition: qofclass.h:223
void gncInvoiceSortEntries(GncInvoice *invoice)
Call this function when an Entry is changed and you want to re-sort the list of entries.
Definition: gncInvoice.c:751
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
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
Definition: qofobject.h:63
gboolean qof_commit_edit(QofInstance *inst)
commit_edit helpers
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
#define QOF_PARAM_BOOK
"Known" Object Parameters – all objects must support these
Definition: qofquery.h:108
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
Definition: qofclass.h:185
time64 gncEntryGetDate(const GncEntry *entry)
DEPRECATED - use gncEntryGetDateGDate() instead! (Because the time-of-day is a misleading extra infor...
Definition: gncEntry.c:913
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
tax is a number
Definition: gncTaxTable.h:80
void qof_instance_init_data(QofInstance *inst, QofIdType type, QofBook *book)
Initialise the settings associated with an instance.
gboolean qof_begin_edit(QofInstance *inst)
begin_edit
gnc_numeric gnc_numeric_convert(gnc_numeric n, gint64 denom, gint how)
Change the denominator of a gnc_numeric value to the specified denominator under standard arguments &#39;...
Find the least common multiple of the arguments&#39; denominators and use that as the denominator of the ...
Definition: gnc-numeric.h:200
AccountValueList * gncEntryGetBalTaxValues(GncEntry *entry, gboolean is_cust_doc)
Careful: the returned list is NOT owned by the entry and should be freed by the caller.
Definition: gncEntry.c:1584
Reduce the result value by common factor elimination, using the smallest possible value for the denom...
Definition: gnc-numeric.h:195
void gncEntryComputeValue(gnc_numeric qty, gnc_numeric price, const GncTaxTable *tax_table, gboolean tax_included, gnc_numeric discount, GncAmountType discount_type, GncDiscountHow discount_how, int SCU, gnc_numeric *value, gnc_numeric *discount_value, GList **tax_values)
Compute the Entry value, tax_value, and discount_value, based on the quantity, price, discount, tax_-table, and types.
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Multiply a times b, returning the product.
void gncBillAddEntry(GncInvoice *bill, GncEntry *entry)
Call this function when adding an entry to a bill instead of an invoice.
Definition: gncInvoice.c:720
GDate gncEntryGetDateGDate(const GncEntry *entry)
Returns the day of this entry.
Definition: gncEntry.c:918
tax is a percentage
Definition: gncTaxTable.h:81
time64 gdate_to_time64(GDate d)
Turns a GDate into a time64, returning the first second of the day.
Definition: gnc-date.cpp:1252
gboolean qof_commit_edit_part2(QofInstance *inst, void(*on_error)(QofInstance *, QofBackendError), void(*on_done)(QofInstance *), void(*on_free)(QofInstance *))
part2 – deal with the backend
void gncEntrySetDateGDate(GncEntry *entry, const GDate *date)
Set the date of this entry.
Definition: gncEntry.c:504
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
Definition: qofclass.h:178
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
Definition: qofid.cpp:261
gnc_numeric gnc_numeric_div(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Division.
void gncAccountValueDestroy(GList *list)
Destroy a list of accountvalues.
Definition: gncTaxTable.c:997
gboolean gnc_numeric_eq(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b are exactly the same (have the same numerator and ...
const char * gncEntryDiscountHowToString(GncDiscountHow how)
How to apply the discount and taxes.
Definition: gncEntry.c:113
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a-b.
Business Invoice Interface.
gint qof_instance_guid_compare(gconstpointer ptr1, gconstpointer ptr2)
Compare the GncGUID values of two instances.
gnc_numeric gncEntryGetQuantity(const GncEntry *entry)
Get the quantity as stored internally.
Definition: gncEntry.c:946
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
Definition: gnc-numeric.h:165
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition: qofbook.cpp:521
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
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
Definition: qofobject.cpp:299
GList * gncAccountValueAdd(GList *list, Account *acc, gnc_numeric value)
This will add value to the account-value for acc, creating a new list object if necessary.
Definition: gncTaxTable.c:942
Use unbiased ("banker&#39;s") rounding.
Definition: gnc-numeric.h:172
Business Entry Interface.
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
gboolean qof_instance_has_kvp(QofInstance *inst)
Report whether a QofInstance has anything stored in KVP.
gboolean qof_book_shutting_down(const QofBook *book)
Is the book shutting down?
Definition: qofbook.cpp:447
void qof_event_gen(QofInstance *entity, QofEventId event_id, gpointer event_data)
Invoke all registered event handlers using the given arguments.
Definition: qofevent.cpp:231
#define GNC_DENOM_AUTO
Values that can be passed as the &#39;denom&#39; argument.
Definition: gnc-numeric.h:245
GncAmountType
How to interpret the amount.
Definition: gncTaxTable.h:78
gnc_numeric gncEntryGetDocQuantity(const GncEntry *entry, gboolean is_cn)
Get the quantity as on the physical document.
Definition: gncEntry.c:952
Commodity handling public routines.
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
gchar * qof_instance_get_display_name(const QofInstance *inst)
Returns a displayable name for this object.
Utility functions for file access.