GnuCash  4.12-11-g8193d7f23a+
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  if (entry->i_tax_table)
467  gncTaxTableDecRef (entry->i_tax_table);
468  if (entry->b_tax_table)
469  gncTaxTableDecRef (entry->b_tax_table);
470 
471  /* qof_instance_release (&entry->inst); */
472  g_object_unref (entry);
473 }
474 
475 /* ================================================================ */
476 /* Set Functions */
477 
478 void gncEntrySetDate (GncEntry *entry, time64 date)
479 {
480  gboolean first_date = FALSE;
481  if (!entry) return;
482  if (entry->date == date) return;
483  if (!entry->date)
484  first_date = TRUE;
485  gncEntryBeginEdit (entry);
486  entry->date = date;
487  mark_entry (entry);
488  gncEntryCommitEdit (entry);
489 
490  /* Don't re-sort the first time we set the date on this entry */
491  if (!first_date)
492  {
493  if (entry->invoice)
494  gncInvoiceSortEntries(entry->invoice);
495  if (entry->bill)
496  gncInvoiceSortEntries(entry->bill);
497  }
498 }
499 
500 void gncEntrySetDateGDate (GncEntry *entry, const GDate* date)
501 {
502  if (!entry || !date || !g_date_valid(date))
503  return;
504 
505  /* Watch out: Here we are deviating from the initial convention that a
506  GDate always converts to the start time of the day. Instead, the GDate is
507  converted to "noon" on the respective date. This is not nice, but this
508  convention was used for the time64 of GncEntry all the time, so we better
509  stick to it.*/
511 }
512 
513 void gncEntrySetDateEntered (GncEntry *entry, time64 date)
514 {
515  if (!entry) return;
516  if (entry->date_entered == date) return;
517  gncEntryBeginEdit (entry);
518  entry->date_entered = date;
519  mark_entry (entry);
520  gncEntryCommitEdit (entry);
521 }
522 
523 void gncEntrySetDescription (GncEntry *entry, const char *desc)
524 {
525  if (!entry || !desc) return;
526  SET_STR (entry, entry->desc, desc);
527  mark_entry (entry);
528  gncEntryCommitEdit (entry);
529 }
530 
531 void gncEntrySetAction (GncEntry *entry, const char *action)
532 {
533  if (!entry || !action) return;
534  SET_STR (entry, entry->action, action);
535  mark_entry (entry);
536  gncEntryCommitEdit (entry);
537 }
538 
539 void gncEntrySetNotes (GncEntry *entry, const char *notes)
540 {
541  if (!entry || !notes) return;
542  SET_STR (entry, entry->notes, notes);
543  mark_entry (entry);
544  gncEntryCommitEdit (entry);
545 }
546 
547 void gncEntrySetQuantity (GncEntry *entry, gnc_numeric quantity)
548 {
549  if (!entry) return;
550  if (gnc_numeric_eq (entry->quantity, quantity)) return;
551  gncEntryBeginEdit (entry);
552  entry->quantity = quantity;
553  entry->values_dirty = TRUE;
554  mark_entry (entry);
555  gncEntryCommitEdit (entry);
556 }
557 
558 void gncEntrySetDocQuantity (GncEntry *entry, gnc_numeric quantity, gboolean is_cn)
559 {
560  if (!entry) return;
561  if (gnc_numeric_eq (entry->quantity, (is_cn ? gnc_numeric_neg (quantity) : quantity))) return;
562  gncEntryBeginEdit (entry);
563  entry->quantity = (is_cn ? gnc_numeric_neg (quantity) : quantity);
564  entry->values_dirty = TRUE;
565  mark_entry (entry);
566  gncEntryCommitEdit (entry);
567 }
568 
569 /* Customer Invoices */
570 
571 void gncEntrySetInvAccount (GncEntry *entry, Account *acc)
572 {
573  if (!entry) return;
574  if (entry->i_account == acc) return;
575  gncEntryBeginEdit (entry);
576  entry->i_account = acc;
577  mark_entry (entry);
578  gncEntryCommitEdit (entry);
579 }
580 
581 void gncEntrySetInvPrice (GncEntry *entry, gnc_numeric price)
582 {
583  if (!entry) return;
584  if (gnc_numeric_eq (entry->i_price, price)) return;
585  gncEntryBeginEdit (entry);
586  entry->i_price = price;
587  entry->values_dirty = TRUE;
588  mark_entry (entry);
589  gncEntryCommitEdit (entry);
590 }
591 
592 void gncEntrySetInvTaxable (GncEntry *entry, gboolean taxable)
593 {
594  if (!entry) return;
595 
596  ENTER ("%d", taxable);
597  if (entry->i_taxable == taxable) {
598  LEAVE ("Value already set");
599  return;
600  }
601  gncEntryBeginEdit (entry);
602  entry->i_taxable = taxable;
603  entry->values_dirty = TRUE;
604  mark_entry (entry);
605  gncEntryCommitEdit (entry);
606  LEAVE ("");
607 }
608 
609 void gncEntrySetInvTaxIncluded (GncEntry *entry, gboolean taxincluded)
610 {
611  if (!entry) return;
612 
613  ENTER ("%d", taxincluded);
614  if (entry->i_taxincluded == taxincluded) {
615  LEAVE ("Value already set");
616  return;
617  }
618  gncEntryBeginEdit (entry);
619  entry->i_taxincluded = taxincluded;
620  entry->values_dirty = TRUE;
621  mark_entry (entry);
622  gncEntryCommitEdit (entry);
623  LEAVE ("");
624 }
625 
626 void gncEntrySetInvTaxTable (GncEntry *entry, GncTaxTable *table)
627 {
628  if (!entry) return;
629 
630  ENTER ("%s", gncTaxTableGetName (table));
631  if (entry->i_tax_table == table) {
632  LEAVE ("Value already set");
633  return;
634  }
635  gncEntryBeginEdit (entry);
636  if (entry->i_tax_table)
637  gncTaxTableDecRef (entry->i_tax_table);
638  if (table)
639  gncTaxTableIncRef (table);
640  entry->i_tax_table = table;
641  entry->values_dirty = TRUE;
642  mark_entry (entry);
643  gncEntryCommitEdit (entry);
644  LEAVE ("");
645 }
646 
647 void gncEntrySetInvDiscount (GncEntry *entry, gnc_numeric discount)
648 {
649  if (!entry) return;
650  if (gnc_numeric_eq (entry->i_discount, discount)) return;
651  gncEntryBeginEdit (entry);
652  entry->i_discount = discount;
653  entry->values_dirty = TRUE;
654  mark_entry (entry);
655  gncEntryCommitEdit (entry);
656 }
657 
658 void gncEntrySetInvDiscountType (GncEntry *entry, GncAmountType type)
659 {
660  if (!entry) return;
661  if (entry->i_disc_type == type) return;
662 
663  gncEntryBeginEdit (entry);
664  entry->i_disc_type = type;
665  entry->values_dirty = TRUE;
666  mark_entry (entry);
667  gncEntryCommitEdit (entry);
668 }
669 
670 void gncEntrySetInvDiscountHow (GncEntry *entry, GncDiscountHow how)
671 {
672  if (!entry) return;
673  if (entry->i_disc_how == how) return;
674 
675  gncEntryBeginEdit (entry);
676  entry->i_disc_how = how;
677  entry->values_dirty = TRUE;
678  mark_entry (entry);
679  gncEntryCommitEdit (entry);
680 }
681 
682 void qofEntrySetInvDiscType (GncEntry *entry, const char *type_string)
683 {
684  GncAmountType type;
685 
686  if (!entry) return;
687  gncAmountStringToType(type_string, &type);
688  if (entry->i_disc_type == type) return;
689  gncEntryBeginEdit (entry);
690  entry->i_disc_type = type;
691  entry->values_dirty = TRUE;
692  mark_entry (entry);
693  gncEntryCommitEdit (entry);
694 
695 }
696 
697 void qofEntrySetInvDiscHow (GncEntry *entry, const char *type)
698 {
699  GncDiscountHow how = GNC_DISC_PRETAX;
700 
701  if (!entry) return;
702  gncEntryBeginEdit (entry);
703  gncEntryDiscountStringToHow(type, &how);
704  if (entry->i_disc_how == how) return;
705  entry->i_disc_how = how;
706  entry->values_dirty = TRUE;
707  mark_entry (entry);
708  gncEntryCommitEdit (entry);
709 }
710 
711 /* Vendor Bills */
712 
713 void gncEntrySetBillAccount (GncEntry *entry, Account *acc)
714 {
715  if (!entry) return;
716  if (entry->b_account == acc) return;
717  gncEntryBeginEdit (entry);
718  entry->b_account = acc;
719  mark_entry (entry);
720  gncEntryCommitEdit (entry);
721 }
722 
723 void gncEntrySetBillPrice (GncEntry *entry, gnc_numeric price)
724 {
725  if (!entry) return;
726  if (gnc_numeric_eq (entry->b_price, price)) return;
727  gncEntryBeginEdit (entry);
728  entry->b_price = price;
729  entry->values_dirty = TRUE;
730  mark_entry (entry);
731  gncEntryCommitEdit (entry);
732 }
733 
734 void gncEntrySetBillTaxable (GncEntry *entry, gboolean taxable)
735 {
736  if (!entry) return;
737 
738  ENTER ("%d", taxable);
739  if (entry->b_taxable == taxable) {
740  LEAVE ("Value already set");
741  return;
742  }
743  gncEntryBeginEdit (entry);
744  entry->b_taxable = taxable;
745  entry->values_dirty = TRUE;
746  mark_entry (entry);
747  gncEntryCommitEdit (entry);
748  LEAVE ("");
749 }
750 
751 void gncEntrySetBillTaxIncluded (GncEntry *entry, gboolean taxincluded)
752 {
753  if (!entry) return;
754 
755  ENTER ("%d", taxincluded);
756  if (entry->b_taxincluded == taxincluded) {
757  LEAVE ("Value already set");
758  return;
759  }
760  gncEntryBeginEdit (entry);
761  entry->b_taxincluded = taxincluded;
762  entry->values_dirty = TRUE;
763  mark_entry (entry);
764  gncEntryCommitEdit (entry);
765  LEAVE ("");
766 }
767 
768 void gncEntrySetBillTaxTable (GncEntry *entry, GncTaxTable *table)
769 {
770  if (!entry) return;
771 
772  ENTER ("%s", gncTaxTableGetName (table));
773  if (entry->b_tax_table == table) {
774  LEAVE ("Value already set");
775  return;
776  }
777  gncEntryBeginEdit (entry);
778  if (entry->b_tax_table)
779  gncTaxTableDecRef (entry->b_tax_table);
780  if (table)
781  gncTaxTableIncRef (table);
782  entry->b_tax_table = table;
783  entry->values_dirty = TRUE;
784  mark_entry (entry);
785  gncEntryCommitEdit (entry);
786  LEAVE ("");
787 }
788 
789 void gncEntrySetBillable (GncEntry *entry, gboolean billable)
790 {
791  if (!entry) return;
792  if (entry->billable == billable) return;
793 
794  gncEntryBeginEdit (entry);
795  entry->billable = billable;
796  mark_entry (entry);
797  gncEntryCommitEdit (entry);
798 }
799 
800 void gncEntrySetBillTo (GncEntry *entry, GncOwner *billto)
801 {
802  if (!entry || !billto) return;
803  if (gncOwnerEqual (&entry->billto, billto)) return;
804 
805  gncEntryBeginEdit (entry);
806  gncOwnerCopy (billto, &entry->billto);
807  mark_entry (entry);
808  gncEntryCommitEdit (entry);
809 }
810 
811 void gncEntrySetBillPayment (GncEntry *entry, GncEntryPaymentType type)
812 {
813  if (!entry) return;
814  if (entry->b_payment == type) return;
815  gncEntryBeginEdit (entry);
816  entry->b_payment = type;
817  mark_entry (entry);
818  gncEntryCommitEdit (entry);
819 }
820 
821 /* Called from gncOrder when we're added to the Order */
822 void gncEntrySetOrder (GncEntry *entry, GncOrder *order)
823 {
824  if (!entry) return;
825  if (entry->order == order) return;
826  gncEntryBeginEdit (entry);
827  entry->order = order;
828  mark_entry (entry);
829  gncEntryCommitEdit (entry);
830 
831 }
832 
833 /* called from gncInvoice when we're added to the Invoice */
834 void gncEntrySetInvoice (GncEntry *entry, GncInvoice *invoice)
835 {
836  if (!entry) return;
837  if (entry->invoice == invoice) return;
838  gncEntryBeginEdit (entry);
839  entry->invoice = invoice;
840  mark_entry (entry);
841  gncEntryCommitEdit (entry);
842 }
843 
844 /* called from gncInvoice when we're added to the Invoice/Bill */
845 void gncEntrySetBill (GncEntry *entry, GncInvoice *bill)
846 {
847  if (!entry) return;
848  if (entry->bill == bill) return;
849  gncEntryBeginEdit (entry);
850  entry->bill = bill;
851  mark_entry (entry);
852  gncEntryCommitEdit (entry);
853 }
854 
855 void gncEntryCopy (const GncEntry *src, GncEntry *dest, gboolean add_entry)
856 {
857  if (!src || !dest) return;
858 
859  gncEntryBeginEdit (dest);
860  dest->date = src->date;
861  dest->date_entered = src->date_entered; /* ??? */
862  gncEntrySetDescription (dest, src->desc);
863  gncEntrySetAction (dest, src->action);
864  gncEntrySetNotes (dest, src->notes);
865  dest->quantity = src->quantity;
866 
867  dest->i_account = src->i_account;
868  dest->i_price = src->i_price;
869  dest->i_taxable = src->i_taxable;
870  dest->i_taxincluded = src->i_taxincluded;
871  dest->i_discount = src->i_discount;
872  dest->i_disc_type = src->i_disc_type;
873  dest->i_disc_how = src->i_disc_how;
874 
875  /* vendor bill data */
876  dest->b_account = src->b_account;
877  dest->b_price = src->b_price;
878  dest->b_taxable = src->b_taxable;
879  dest->b_taxincluded = src->b_taxincluded;
880  dest->billable = src->billable;
881  dest->billto = src->billto;
882 
883  if (src->i_tax_table)
884  gncEntrySetInvTaxTable (dest, src->i_tax_table);
885 
886  if (src->b_tax_table)
887  gncEntrySetBillTaxTable (dest, src->b_tax_table);
888 
889  if (add_entry)
890  {
891  if (src->order)
892  gncOrderAddEntry (src->order, dest);
893 
894  if (src->invoice)
895  gncInvoiceAddEntry (src->invoice, dest);
896 
897  if (src->bill)
898  gncBillAddEntry (src->bill, dest);
899  }
900 
901  dest->values_dirty = TRUE;
902  mark_entry (dest);
903  gncEntryCommitEdit (dest);
904 }
905 
906 /* ================================================================ */
907 /* Get Functions */
908 
909 time64 gncEntryGetDate (const GncEntry *entry)
910 {
911  return entry ? entry->date : 0;
912 }
913 
914 GDate gncEntryGetDateGDate(const GncEntry *entry)
915 {
916  return time64_to_gdate(gncEntryGetDate(entry));
917 }
918 
919 time64 gncEntryGetDateEntered (const GncEntry *entry)
920 {
921  return entry ? entry->date_entered : 0;
922 }
923 
924 const char * gncEntryGetDescription (const GncEntry *entry)
925 {
926  if (!entry) return NULL;
927  return entry->desc;
928 }
929 
930 const char * gncEntryGetAction (const GncEntry *entry)
931 {
932  if (!entry) return NULL;
933  return entry->action;
934 }
935 
936 const char * gncEntryGetNotes (const GncEntry *entry)
937 {
938  if (!entry) return NULL;
939  return entry->notes;
940 }
941 
942 gnc_numeric gncEntryGetQuantity (const GncEntry *entry)
943 {
944  if (!entry) return gnc_numeric_zero();
945  return entry->quantity;
946 }
947 
948 gnc_numeric gncEntryGetDocQuantity (const GncEntry *entry, gboolean is_cn)
949 {
950  gnc_numeric value = gncEntryGetQuantity (entry);
951  return (is_cn ? gnc_numeric_neg (value) : value);
952 }
953 
954 /* Customer Invoice */
955 
956 Account * gncEntryGetInvAccount (const GncEntry *entry)
957 {
958  if (!entry) return NULL;
959  return entry->i_account;
960 }
961 
962 gnc_numeric gncEntryGetInvPrice (const GncEntry *entry)
963 {
964  if (!entry) return gnc_numeric_zero();
965  return entry->i_price;
966 }
967 
968 gnc_numeric gncEntryGetInvDiscount (const GncEntry *entry)
969 {
970  if (!entry) return gnc_numeric_zero();
971  return entry->i_discount;
972 }
973 
974 GncAmountType gncEntryGetInvDiscountType (const GncEntry *entry)
975 {
976  if (!entry) return 0;
977  return entry->i_disc_type;
978 }
979 
980 GncDiscountHow gncEntryGetInvDiscountHow (const GncEntry *entry)
981 {
982  if (!entry) return 0;
983  return entry->i_disc_how;
984 }
985 
986 char* qofEntryGetInvDiscType (const GncEntry *entry)
987 {
988  char *type_string;
989 
990  if (!entry) return 0;
991  type_string = g_strdup(gncAmountTypeToString(entry->i_disc_type));
992  return type_string;
993 }
994 
995 char* qofEntryGetInvDiscHow (const GncEntry *entry)
996 {
997  char *type_string;
998 
999  if (!entry) return 0;
1000  type_string = g_strdup(gncEntryDiscountHowToString(entry->i_disc_how));
1001  return type_string;
1002 }
1003 
1004 gboolean gncEntryGetInvTaxable (const GncEntry *entry)
1005 {
1006  if (!entry) return FALSE;
1007  return entry->i_taxable;
1008 }
1009 
1010 gboolean gncEntryGetInvTaxIncluded (const GncEntry *entry)
1011 {
1012  if (!entry) return FALSE;
1013  return entry->i_taxincluded;
1014 }
1015 
1016 GncTaxTable * gncEntryGetInvTaxTable (const GncEntry *entry)
1017 {
1018  if (!entry) return NULL;
1019  return entry->i_tax_table;
1020 }
1021 
1022 /* vendor bills */
1023 
1024 Account * gncEntryGetBillAccount (const GncEntry *entry)
1025 {
1026  if (!entry) return NULL;
1027  return entry->b_account;
1028 }
1029 
1030 gnc_numeric gncEntryGetBillPrice (const GncEntry *entry)
1031 {
1032  if (!entry) return gnc_numeric_zero();
1033  return entry->b_price;
1034 }
1035 
1036 gboolean gncEntryGetBillTaxable (const GncEntry *entry)
1037 {
1038  if (!entry) return FALSE;
1039  return entry->b_taxable;
1040 }
1041 
1042 gboolean gncEntryGetBillTaxIncluded (const GncEntry *entry)
1043 {
1044  if (!entry) return FALSE;
1045  return entry->b_taxincluded;
1046 }
1047 
1048 GncTaxTable * gncEntryGetBillTaxTable (const GncEntry *entry)
1049 {
1050  if (!entry) return NULL;
1051  return entry->b_tax_table;
1052 }
1053 
1054 gboolean gncEntryGetBillable (const GncEntry *entry)
1055 {
1056  if (!entry) return FALSE;
1057  return entry->billable;
1058 }
1059 
1060 GncOwner * gncEntryGetBillTo (GncEntry *entry)
1061 {
1062  if (!entry) return NULL;
1063  return &entry->billto;
1064 }
1065 
1066 GncEntryPaymentType gncEntryGetBillPayment (const GncEntry* entry)
1067 {
1068  if (!entry) return 0;
1069  return entry->b_payment;
1070 }
1071 
1072 GncInvoice * gncEntryGetInvoice (const GncEntry *entry)
1073 {
1074  if (!entry) return NULL;
1075  return entry->invoice;
1076 }
1077 
1078 GncInvoice * gncEntryGetBill (const GncEntry *entry)
1079 {
1080  if (!entry) return NULL;
1081  return entry->bill;
1082 }
1083 
1084 GncOrder * gncEntryGetOrder (const GncEntry *entry)
1085 {
1086  if (!entry) return NULL;
1087  return entry->order;
1088 }
1089 
1090 /* ================================================================ */
1091 /*
1092  * This is the logic of computing the total for an Entry, so you know
1093  * what values to put into various Splits or to display in the ledger.
1094  * In other words, we combine the quantity, unit-price, discount and
1095  * taxes together, depending on various flags.
1096  *
1097  * There are four potential ways to combine these numbers:
1098  * Discount: Pre-Tax Post-Tax
1099  * Tax : Included Not-Included
1100  *
1101  * The process is relatively simple:
1102  *
1103  * 1) compute the aggregate price (price*qty)
1104  * 2) if taxincluded, then back-compute the aggregate pre-tax price
1105  * 3) apply discount and taxes in the appropriate order
1106  * 4) return the requested results.
1107  *
1108  * Step 2 can be done with aggregate taxes; no need to compute them all
1109  * unless the caller asked for the tax_value.
1110  *
1111  * Note that the returned "value" is such that
1112  * value + tax == "total to pay"
1113  * which means in the case of tax-included that the returned
1114  * "value" may be less than the aggregate price, even without a
1115  * discount. If you want to display the tax-included value, you need
1116  * to add the value and taxes together. In other words, the value is
1117  * the amount the merchant gets; the taxes are the amount the gov't
1118  * gets, and the customer pays the sum or value + taxes.
1119  *
1120  * The discount return value is just for entertainment -- you may want
1121  * to let a consumer know how much they saved.
1122  *
1123  * Note this function will not do any rounding unless forced to prevent overflow.
1124  * It's the caller's responsibility to round to the proper commodity
1125  * denominator if needed.
1126  */
1127 static void gncEntryComputeValueInt (gnc_numeric qty, gnc_numeric price,
1128  const GncTaxTable *tax_table, gboolean tax_included,
1129  gnc_numeric discount, GncAmountType discount_type,
1130  GncDiscountHow discount_how,
1131  gnc_numeric *value, gnc_numeric *discount_value,
1132  GList **tax_value, gnc_numeric *net_price)
1133 {
1134  gnc_numeric aggregate;
1135  gnc_numeric pretax;
1136  gnc_numeric result;
1137  gnc_numeric tax;
1138  gnc_numeric percent = gnc_numeric_create (100, 1);
1139  gnc_numeric tpercent = gnc_numeric_zero ();
1140  gnc_numeric tvalue = gnc_numeric_zero ();
1141  gnc_numeric i_net_price = price;
1142 
1143  GList * entries = gncTaxTableGetEntries (tax_table);
1144  GList * node;
1145 
1146  ENTER ("");
1147  /* Step 1: compute the aggregate price */
1148 
1150 
1151  PINFO ("Aggregate value %" PRId64 "/%" PRId64, aggregate.num, aggregate.denom);
1152  /* Step 2: compute the pre-tax aggregate */
1153 
1154  /* First, compute the aggregate tpercent and tvalue numbers */
1155  for (node = entries; node; node = node->next)
1156  {
1157  GncTaxTableEntry *entry = node->data;
1158  gnc_numeric amount = gncTaxTableEntryGetAmount (entry);
1159 
1160  switch (gncTaxTableEntryGetType (entry))
1161  {
1162  case GNC_AMT_TYPE_VALUE:
1163  tvalue = gnc_numeric_add (tvalue, amount, GNC_DENOM_AUTO,
1165  break;
1166  case GNC_AMT_TYPE_PERCENT:
1167  tpercent = gnc_numeric_add (tpercent, amount, GNC_DENOM_AUTO,
1169  break;
1170  default:
1171  PWARN ("Unknown tax type: %d", gncTaxTableEntryGetType (entry));
1172  break;
1173  }
1174  }
1175  /* now we need to convert from 5% -> .05 */
1176  tpercent = gnc_numeric_div (tpercent, percent, GNC_DENOM_AUTO,
1178  PINFO("Tax rate %" PRId64 "/%" PRId64, tpercent.num, tpercent.denom);
1179  /* Next, actually compute the pre-tax aggregate value based on the
1180  * taxincluded flag.
1181  */
1182  if (tax_table && tax_included)
1183  {
1184  /* Back-compute the pre-tax aggregate value.
1185  * We know that aggregate = pretax + pretax*tpercent + tvalue, so
1186  * pretax = (aggregate-tvalue)/(1+tpercent)
1187  */
1188  pretax = gnc_numeric_sub (aggregate, tvalue, GNC_DENOM_AUTO,
1190  pretax = gnc_numeric_div (pretax,
1191  gnc_numeric_add (tpercent,
1192  gnc_numeric_create (1, 1),
1195  PINFO ("pretax %" PRId64 "/%" PRId64, pretax.num, pretax.denom);
1196  if (!gnc_numeric_zero_p(qty))
1197  {
1198  i_net_price = gnc_numeric_div (pretax, qty, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE | GNC_HOW_RND_ROUND);
1199  }
1200  PINFO("i_net_price %" PRId64 "/%" PRId64, i_net_price.num, i_net_price.denom);
1201  }
1202  else
1203  {
1204  PINFO ("Tax not included or no tax table, pretax is aggregate");
1205  pretax = aggregate;
1206  }
1207 
1208  /* Step 3: apply discount and taxes in the appropriate order */
1209 
1210  /*
1211  * There are two ways to apply discounts and taxes. In one way, you
1212  * always compute the discount off the pretax number, and compute
1213  * the taxes off of either the pretax value or "pretax-discount"
1214  * value. In the other way, you always compute the tax on "pretax",
1215  * and compute the discount on either "pretax" or "pretax+taxes".
1216  *
1217  * I don't know which is the "correct" way.
1218  */
1219 
1220  /*
1221  * Type: discount tax
1222  * PRETAX pretax pretax-discount
1223  * SAMETIME pretax pretax
1224  * POSTTAX pretax+tax pretax
1225  */
1226 
1227  switch (discount_how)
1228  {
1229  case GNC_DISC_PRETAX:
1230  case GNC_DISC_SAMETIME:
1231  /* compute the discount from pretax */
1232 
1233  if (discount_type == GNC_AMT_TYPE_PERCENT)
1234  {
1235  discount = gnc_numeric_div (discount, percent, GNC_DENOM_AUTO,
1237  discount = gnc_numeric_mul (pretax, discount, GNC_DENOM_AUTO,
1239  }
1240 
1241  result = gnc_numeric_sub (pretax, discount, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
1242 
1243  /* Figure out when to apply the tax, pretax or pretax-discount */
1244  if (discount_how == GNC_DISC_PRETAX)
1245  pretax = result;
1246  break;
1247 
1248  case GNC_DISC_POSTTAX:
1249  /* compute discount on pretax+taxes */
1250 
1251  if (discount_type == GNC_AMT_TYPE_PERCENT)
1252  {
1253  gnc_numeric after_tax;
1254 
1256  after_tax = gnc_numeric_add (pretax, tax, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
1257  after_tax = gnc_numeric_add (after_tax, tvalue, GNC_DENOM_AUTO,
1259  discount = gnc_numeric_div (discount, percent, GNC_DENOM_AUTO,
1261  discount = gnc_numeric_mul (after_tax, discount, GNC_DENOM_AUTO,
1263  }
1264 
1265  result = gnc_numeric_sub (pretax, discount, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
1266  break;
1267 
1268  default:
1269  PWARN ("unknown DiscountHow value: %d", discount_how);
1270  break;
1271  }
1272 
1273  /* Step 4: return the requested results. */
1274 
1275  /* result == amount merchant gets
1276  * discount == amount of discount
1277  * need to compute taxes (based on 'pretax') if the caller wants it.
1278  */
1279 
1280  if (discount_value != NULL)
1281  *discount_value = discount;
1282 
1283  if (value != NULL)
1284  *value = result;
1285 
1286  /* Now... Compute the list of tax values (if the caller wants it) */
1287 
1288  if (tax_value != NULL)
1289  {
1290  GList * taxes = NULL;
1291 
1292  PINFO("Computing tax value list");
1293  for (node = entries; node; node = node->next)
1294  {
1295  GncTaxTableEntry *entry = node->data;
1296  Account *acc = gncTaxTableEntryGetAccount (entry);
1297  gnc_numeric amount = gncTaxTableEntryGetAmount (entry);
1298 
1299  g_return_if_fail (acc);
1300 
1301  switch (gncTaxTableEntryGetType (entry))
1302  {
1303  case GNC_AMT_TYPE_VALUE:
1304  taxes = gncAccountValueAdd (taxes, acc, amount);
1305  break;
1306  case GNC_AMT_TYPE_PERCENT:
1307  amount = gnc_numeric_div (amount, percent, GNC_DENOM_AUTO,
1310  taxes = gncAccountValueAdd (taxes, acc, tax);
1311  break;
1312  default:
1313  break;
1314  }
1315  }
1316  *tax_value = taxes;
1317  }
1318 
1319  if (net_price != NULL)
1320  *net_price = i_net_price;
1321 
1322  LEAVE ("");
1323  return;
1324 }
1325 
1326 void gncEntryComputeValue (gnc_numeric qty, gnc_numeric price,
1327  const GncTaxTable *tax_table, gboolean tax_included,
1328  gnc_numeric discount, GncAmountType discount_type,
1329  GncDiscountHow discount_how, G_GNUC_UNUSED int SCU,
1330  gnc_numeric *value, gnc_numeric *discount_value,
1331  GList **tax_value)
1332 {
1333  gncEntryComputeValueInt (qty, price, tax_table, tax_included, discount, discount_type,
1334  discount_how, value, discount_value, tax_value, NULL);
1335 }
1336 
1337 static int
1338 get_entry_commodity_denom (const GncEntry *entry)
1339 {
1340  gnc_commodity *c;
1341  if (!entry)
1342  return 0;
1343  if (entry->invoice)
1344  {
1345  c = gncInvoiceGetCurrency (entry->invoice);
1346  if (c)
1347  return (gnc_commodity_get_fraction (c));
1348  }
1349  if (entry->bill)
1350  {
1351  c = gncInvoiceGetCurrency (entry->bill);
1352  if (c)
1353  return (gnc_commodity_get_fraction (c));
1354  }
1355  return 100000;
1356 }
1357 
1358 static void
1359 gncEntryRecomputeValues (GncEntry *entry)
1360 {
1361  int denom;
1362  GList *tv_iter;
1363 
1364  ENTER ("");
1365  /* See if either tax table changed since we last computed values */
1366  if (entry->i_tax_table)
1367  {
1368  time64 modtime = gncTaxTableLastModifiedSecs (entry->i_tax_table);
1369  if (entry->i_taxtable_modtime != modtime)
1370  {
1371  PINFO ("Invoice tax table changed since last recompute.");
1372  entry->values_dirty = TRUE;
1373  entry->i_taxtable_modtime = modtime;
1374  }
1375  }
1376  if (entry->b_tax_table)
1377  {
1378  time64 modtime = gncTaxTableLastModifiedSecs (entry->b_tax_table);
1379  if (entry->b_taxtable_modtime != modtime)
1380  {
1381  PINFO ("Bill tax table changed since last recompute.");
1382  entry->values_dirty = TRUE;
1383  entry->b_taxtable_modtime = modtime;
1384  }
1385  }
1386 
1387  if (!entry->values_dirty) {
1388  LEAVE ("No changes");
1389  return;
1390  }
1391 
1392  /* Clear the last-computed tax values */
1393  if (entry->i_tax_values)
1394  {
1395  gncAccountValueDestroy (entry->i_tax_values);
1396  entry->i_tax_values = NULL;
1397  }
1398  if (entry->b_tax_values)
1399  {
1400  gncAccountValueDestroy (entry->b_tax_values);
1401  entry->b_tax_values = NULL;
1402  }
1403 
1404  /* Determine the commodity denominator */
1405  denom = get_entry_commodity_denom (entry);
1406 
1407  /* Compute the invoice values */
1408  DEBUG("Compute Invoice Values.");
1409  gncEntryComputeValue (entry->quantity, entry->i_price,
1410  (entry->i_taxable ? entry->i_tax_table : NULL),
1411  entry->i_taxincluded,
1412  entry->i_discount, entry->i_disc_type,
1413  entry->i_disc_how,
1414  denom,
1415  &(entry->i_value), &(entry->i_disc_value),
1416  &(entry->i_tax_values));
1417 
1418  /* Compute the bill values */
1419  DEBUG("Compute BILL Values.");
1420  gncEntryComputeValue (entry->quantity, entry->b_price,
1421  (entry->b_taxable ? entry->b_tax_table : NULL),
1422  entry->b_taxincluded,
1423  gnc_numeric_zero(), GNC_AMT_TYPE_VALUE, GNC_DISC_PRETAX,
1424  denom,
1425  &(entry->b_value), NULL, &(entry->b_tax_values));
1426 
1427  entry->i_value_rounded = gnc_numeric_convert (entry->i_value, denom,
1429  entry->i_disc_value_rounded = gnc_numeric_convert (entry->i_disc_value, denom,
1431  entry->i_tax_value = gncAccountValueTotal (entry->i_tax_values);
1432  entry->i_tax_value_rounded = gnc_numeric_zero();
1433  for (tv_iter = entry->i_tax_values; tv_iter; tv_iter=tv_iter->next)
1434  {
1435  GncAccountValue *acc_val = tv_iter->data;
1436  entry->i_tax_value_rounded = gnc_numeric_add (entry->i_tax_value_rounded, acc_val->value,
1438  }
1439 
1440  entry->b_value_rounded = gnc_numeric_convert (entry->b_value, denom,
1442  entry->b_tax_value = gncAccountValueTotal (entry->b_tax_values);
1443  entry->b_tax_value_rounded = gnc_numeric_zero();
1444  for (tv_iter = entry->b_tax_values; tv_iter; tv_iter=tv_iter->next)
1445  {
1446  GncAccountValue *acc_val = tv_iter->data;
1447  entry->b_tax_value_rounded = gnc_numeric_add (entry->b_tax_value_rounded, acc_val->value,
1449  }
1450  entry->values_dirty = FALSE;
1451  LEAVE ("");
1452 }
1453 
1454 /* The "Int" functions below are for internal use only.
1455  * Outside this file, use the "Doc" or "Bal" variants found below instead. */
1456 static gnc_numeric gncEntryGetIntValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1457 {
1458  if (!entry) return gnc_numeric_zero();
1459  gncEntryRecomputeValues (entry);
1460  if (round)
1461  return (is_cust_doc ? entry->i_value_rounded : entry->b_value_rounded);
1462  else
1463  return (is_cust_doc ? entry->i_value : entry->b_value);
1464 }
1465 
1466 static gnc_numeric gncEntryGetIntTaxValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1467 {
1468  if (!entry) return gnc_numeric_zero();
1469  gncEntryRecomputeValues (entry);
1470  if (round)
1471  return (is_cust_doc ? entry->i_tax_value_rounded : entry->b_tax_value_rounded);
1472  else
1473  return (is_cust_doc ? entry->i_tax_value : entry->b_tax_value);
1474 }
1475 
1476 /* Careful: the returned list is managed by the entry, and will only be valid for a short time */
1477 static AccountValueList * gncEntryGetIntTaxValues (GncEntry *entry, gboolean is_cust_doc)
1478 {
1479  if (!entry) return NULL;
1480  gncEntryRecomputeValues (entry);
1481  return (is_cust_doc ? entry->i_tax_values : entry->b_tax_values);
1482 }
1483 
1484 static gnc_numeric gncEntryGetIntDiscountValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1485 {
1486  if (!entry) return gnc_numeric_zero();
1487  gncEntryRecomputeValues (entry);
1488  if (round)
1489  return (is_cust_doc ? entry->i_disc_value_rounded : gnc_numeric_zero());
1490  else
1491  return (is_cust_doc ? entry->i_disc_value : gnc_numeric_zero());
1492 }
1493 
1494 /* Note contrary to the GetDoc*Value and GetBal*Value functions below
1495  * this function will always round the net price to the entry's
1496  * currency denominator (being the invoice/bill denom or 100000 if not
1497  * included in a bill or invoice) */
1498 gnc_numeric gncEntryGetPrice (const GncEntry *entry, gboolean cust_doc, gboolean net)
1499 {
1500  gnc_numeric result;
1501  int denom;
1502 
1503  if (!entry) return gnc_numeric_zero();
1504  if (!net) return (cust_doc ? entry->i_price : entry->b_price);
1505 
1506 
1507  /* Compute the net price */
1508  if (cust_doc)
1509  gncEntryComputeValueInt (entry->quantity, entry->i_price,
1510  (entry->i_taxable ? entry->i_tax_table : NULL),
1511  entry->i_taxincluded,
1512  entry->i_discount, entry->i_disc_type,
1513  entry->i_disc_how,
1514  NULL, NULL, NULL, &result);
1515  else
1516  gncEntryComputeValueInt (entry->quantity, entry->b_price,
1517  (entry->b_taxable ? entry->b_tax_table : NULL),
1518  entry->b_taxincluded,
1519  gnc_numeric_zero(), GNC_AMT_TYPE_VALUE, GNC_DISC_PRETAX,
1520  NULL, NULL, NULL, &result);
1521 
1522  /* Determine the commodity denominator */
1523  denom = get_entry_commodity_denom (entry);
1524 
1525  result = gnc_numeric_convert (result, denom,
1527 
1528  return result;
1529 }
1530 
1531 gnc_numeric gncEntryGetDocValue (GncEntry *entry, gboolean round, gboolean is_cust_doc, gboolean is_cn)
1532 {
1533  gnc_numeric value = gncEntryGetIntValue (entry, round, is_cust_doc);
1534  return (is_cn ? gnc_numeric_neg (value) : value);
1535 }
1536 
1537 gnc_numeric gncEntryGetDocTaxValue (GncEntry *entry, gboolean round, gboolean is_cust_doc, gboolean is_cn)
1538 {
1539  gnc_numeric value = gncEntryGetIntTaxValue (entry, round, is_cust_doc);
1540  return (is_cn ? gnc_numeric_neg (value) : value);
1541 }
1542 
1543 /* Careful: the returned list is NOT owned by the entry and should be freed by the caller */
1544 AccountValueList * gncEntryGetDocTaxValues (GncEntry *entry, gboolean is_cust_doc, gboolean is_cn)
1545 {
1546  AccountValueList *int_values = gncEntryGetIntTaxValues (entry, is_cust_doc);
1547  AccountValueList *values = NULL, *node;
1548 
1549  /* Make a copy of the list with negated values if necessary. */
1550  for (node = int_values; node; node = node->next)
1551  {
1552  GncAccountValue *acct_val = node->data;
1553  values = gncAccountValueAdd (values, acct_val->account,
1554  (is_cn ? gnc_numeric_neg (acct_val->value)
1555  : acct_val->value));
1556  }
1557 
1558  return values;
1559 }
1560 
1561 gnc_numeric gncEntryGetDocDiscountValue (GncEntry *entry, gboolean round, gboolean is_cust_doc, gboolean is_cn)
1562 {
1563  gnc_numeric value = gncEntryGetIntDiscountValue (entry, round, is_cust_doc);
1564  return (is_cn ? gnc_numeric_neg (value) : value);
1565 }
1566 
1567 gnc_numeric gncEntryGetBalValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1568 {
1569  gnc_numeric value = gncEntryGetIntValue (entry, round, is_cust_doc);
1570  return (is_cust_doc ? gnc_numeric_neg (value) : value);
1571 }
1572 
1573 gnc_numeric gncEntryGetBalTaxValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1574 {
1575  gnc_numeric value = gncEntryGetIntTaxValue (entry, round, is_cust_doc);
1576  return (is_cust_doc ? gnc_numeric_neg (value) : value);
1577 }
1578 
1579 /* Careful: the returned list is NOT owned by the entry and should be freed by the caller */
1580 AccountValueList * gncEntryGetBalTaxValues (GncEntry *entry, gboolean is_cust_doc)
1581 {
1582  AccountValueList *int_values = gncEntryGetIntTaxValues (entry, is_cust_doc);
1583  AccountValueList *values = NULL, *node;
1584 
1585  /* Make a copy of the list with negated values if necessary. */
1586  for (node = int_values; node; node = node->next)
1587  {
1588  GncAccountValue *acct_val = node->data;
1589  values = gncAccountValueAdd (values, acct_val->account,
1590  (is_cust_doc ? gnc_numeric_neg (acct_val->value)
1591  : acct_val->value));
1592  }
1593 
1594  return values;
1595 }
1596 
1597 gnc_numeric gncEntryGetBalDiscountValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
1598 {
1599  gnc_numeric value = gncEntryGetIntDiscountValue (entry, round, is_cust_doc);
1600  return (is_cust_doc ? gnc_numeric_neg (value) : value);
1601 }
1602 
1603 /* XXX this existence of this routine is just wrong */
1604 gboolean gncEntryIsOpen (const GncEntry *entry)
1605 {
1606  if (!entry) return FALSE;
1607  return (qof_instance_get_editlevel(entry) > 0);
1608 }
1609 
1610 /* ================================================================ */
1611 
1612 void gncEntryBeginEdit (GncEntry *entry)
1613 {
1614  qof_begin_edit(&entry->inst);
1615 }
1616 
1617 static void gncEntryOnError (QofInstance *entry, QofBackendError errcode)
1618 {
1619  PERR("Entry QofBackend Failure: %d", errcode);
1620  gnc_engine_signal_commit_error( errcode );
1621 }
1622 
1623 static void gncEntryOnDone (QofInstance *inst) {}
1624 
1625 static void entry_free (QofInstance *inst)
1626 {
1627  GncEntry *entry = (GncEntry *)inst;
1628  gncEntryFree (entry);
1629 }
1630 
1631 void gncEntryCommitEdit (GncEntry *entry)
1632 {
1633  /* GnuCash 2.6.3 and earlier didn't handle entry kvp's... */
1634  if (qof_instance_has_kvp(QOF_INSTANCE(entry)))
1635  gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (entry)),
1636  GNC_FEATURE_KVP_EXTRA_DATA);
1637 
1638  if (!qof_commit_edit (QOF_INSTANCE(entry))) return;
1639  qof_commit_edit_part2 (&entry->inst, gncEntryOnError,
1640  gncEntryOnDone, entry_free);
1641 }
1642 
1643 int gncEntryCompare (const GncEntry *a, const GncEntry *b)
1644 {
1645  int compare;
1646 
1647  if (a == b) return 0;
1648  if (!a && b) return -1;
1649  if (a && !b) return 1;
1650  g_assert (a && b); /* Silence a static analysis warning. */
1651  if (a->date != b->date) return a->date - b->date;
1652  if (a->date_entered != b->date_entered) return a->date_entered - b->date_entered;
1653 
1654  compare = g_strcmp0 (a->desc, b->desc);
1655  if (compare) return compare;
1656 
1657  compare = g_strcmp0 (a->action, b->action);
1658  if (compare) return compare;
1659 
1660  return qof_instance_guid_compare(a, b);
1661 }
1662 
1663 #define CHECK_STRING(X, Y, FIELD) \
1664  if (g_strcmp0((X)->FIELD, (Y)->FIELD) != 0) \
1665  { \
1666  PWARN("%s differ: %s vs %s", #FIELD, (X)->FIELD, (Y)->FIELD); \
1667  return FALSE; \
1668  }
1669 
1670 #define CHECK_ACCOUNT(X, Y, FIELD) \
1671  if (!xaccAccountEqual((X)->FIELD, (Y)->FIELD, TRUE)) \
1672  { \
1673  PWARN("%s differ", #FIELD); \
1674  return FALSE; \
1675  }
1676 
1677 #define CHECK_NUMERIC(X, Y, FIELD) \
1678  if (!gnc_numeric_equal((X)->FIELD, (Y)->FIELD)) \
1679  { \
1680  PWARN("%s differ", #FIELD); \
1681  return FALSE; \
1682  }
1683 
1684 #define CHECK_VALUE(X, Y, FIELD) \
1685  if ((X)->FIELD != (Y)->FIELD) \
1686  { \
1687  PWARN("%s differ", #FIELD); \
1688  return FALSE; \
1689  }
1690 
1691 
1692 /* ============================================================= */
1693 /* Object declaration */
1694 
1695 static void
1696 destroy_entry_on_book_close(QofInstance *ent, gpointer data)
1697 {
1698  GncEntry* entry = GNC_ENTRY(ent);
1699 
1700  gncEntryBeginEdit(entry);
1701  gncEntryDestroy(entry);
1702 }
1703 
1708 static void
1709 gnc_entry_book_end(QofBook* book)
1710 {
1711  QofCollection *col;
1712 
1713  col = qof_book_get_collection(book, GNC_ID_ENTRY);
1714  qof_collection_foreach(col, destroy_entry_on_book_close, NULL);
1715 }
1716 
1717 static QofObject gncEntryDesc =
1718 {
1719  DI(.interface_version = ) QOF_OBJECT_VERSION,
1720  DI(.e_type = ) _GNC_MOD_NAME,
1721  DI(.type_label = ) "Order/Invoice/Bill Entry",
1722  DI(.create = ) (gpointer)gncEntryCreate,
1723  DI(.book_begin = ) NULL,
1724  DI(.book_end = ) gnc_entry_book_end,
1725  DI(.is_dirty = ) qof_collection_is_dirty,
1726  DI(.mark_clean = ) qof_collection_mark_clean,
1727  DI(.foreach = ) qof_collection_foreach,
1728  DI(.printable = ) NULL,
1729  DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
1730 };
1731 
1732 gboolean gncEntryRegister (void)
1733 {
1734  static QofParam params[] =
1735  {
1736  { ENTRY_DATE, QOF_TYPE_DATE, (QofAccessFunc)gncEntryGetDate, (QofSetterFunc)gncEntrySetDate },
1737  { ENTRY_DATE_ENTERED, QOF_TYPE_DATE, (QofAccessFunc)gncEntryGetDateEntered, (QofSetterFunc)gncEntrySetDateEntered },
1738  { ENTRY_DESC, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetDescription, (QofSetterFunc)gncEntrySetDescription },
1739  { ENTRY_ACTION, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetAction, (QofSetterFunc)gncEntrySetAction },
1740  { ENTRY_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncEntryGetNotes, (QofSetterFunc)gncEntrySetNotes },
1741  { ENTRY_QTY, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetQuantity, (QofSetterFunc)gncEntrySetQuantity },
1742  { ENTRY_IPRICE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetInvPrice, (QofSetterFunc)gncEntrySetInvPrice },
1743  { ENTRY_BPRICE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEntryGetBillPrice, (QofSetterFunc)gncEntrySetBillPrice },
1744  { ENTRY_INVOICE, GNC_ID_INVOICE, (QofAccessFunc)gncEntryGetInvoice, NULL },
1745  { ENTRY_IACCT, GNC_ID_ACCOUNT, (QofAccessFunc)gncEntryGetInvAccount, (QofSetterFunc)gncEntrySetInvAccount },
1746  { ENTRY_BACCT, GNC_ID_ACCOUNT, (QofAccessFunc)gncEntryGetBillAccount, (QofSetterFunc)gncEntrySetBillAccount },
1747  { ENTRY_BILL, GNC_ID_INVOICE, (QofAccessFunc)gncEntryGetBill, NULL },
1748  {
1749  ENTRY_INV_DISC_TYPE, QOF_TYPE_STRING, (QofAccessFunc)qofEntryGetInvDiscType,
1750  (QofSetterFunc)qofEntrySetInvDiscType
1751  },
1752  {
1753  ENTRY_INV_DISC_HOW, QOF_TYPE_STRING, (QofAccessFunc)qofEntryGetInvDiscHow,
1754  (QofSetterFunc)qofEntrySetInvDiscHow
1755  },
1756  {
1757  ENTRY_INV_TAXABLE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetInvTaxable,
1758  (QofSetterFunc)gncEntrySetInvTaxable
1759  },
1760  {
1761  ENTRY_INV_TAX_INC, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetInvTaxIncluded,
1762  (QofSetterFunc)gncEntrySetInvTaxIncluded
1763  },
1764  {
1765  ENTRY_BILL_TAXABLE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetBillTaxable,
1766  (QofSetterFunc)gncEntrySetBillTaxable
1767  },
1768  {
1769  ENTRY_BILL_TAX_INC, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetBillTaxIncluded,
1770  (QofSetterFunc)gncEntrySetBillTaxIncluded
1771  },
1772  { ENTRY_BILLABLE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEntryGetBillable, (QofSetterFunc)gncEntrySetBillable },
1773  { ENTRY_BILLTO, GNC_ID_OWNER, (QofAccessFunc)gncEntryGetBillTo, (QofSetterFunc)gncEntrySetBillTo },
1774  { ENTRY_ORDER, GNC_ID_ORDER, (QofAccessFunc)gncEntryGetOrder, NULL },
1775  { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
1776  { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
1777  { NULL },
1778  };
1779 
1780  qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncEntryCompare, params);
1781 
1782  return qof_object_register (&gncEntryDesc);
1783 }
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
Compare two instances, based on their last update times.
Reduce the result value by common factor elimination, using the smallest possible value for the denom...
Definition: gnc-numeric.h:196
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:547
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:257
#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...
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.
Definition: gnc-features.c:135
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:1544
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:405
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:1215
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:189
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
int(* QofSortFunc)(gconstpointer, gconstpointer)
This function is the default sort function for a particular object type.
Definition: qofclass.h:222
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:766
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:558
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
Definition: qofobject.h:64
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
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
Definition: gnc-numeric.h:166
#define QOF_PARAM_BOOK
"Known" Object Parameters – all objects must support these
Definition: qofquery.h:109
void qof_collection_foreach(const QofCollection *col, QofInstanceForeachCB cb_func, gpointer user_data)
Call the callback for each entity in the collection.
Definition: qofid.cpp:323
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
Definition: qofclass.h:184
time64 gncEntryGetDate(const GncEntry *entry)
DEPRECATED - use gncEntryGetDateGDate() instead! (Because the time-of-day is a misleading extra infor...
Definition: gncEntry.c:909
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
tax is a number
Definition: gncTaxTable.h:69
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;...
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:1580
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:735
GDate gncEntryGetDateGDate(const GncEntry *entry)
Returns the day of this entry.
Definition: gncEntry.c:914
tax is a percentage
Definition: gncTaxTable.h:70
Use unbiased ("banker&#39;s") rounding.
Definition: gnc-numeric.h:173
time64 gdate_to_time64(GDate d)
Turns a GDate into a time64, returning the first second of the day.
Definition: gnc-date.cpp:1256
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:500
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
Definition: qofclass.h:177
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
Definition: qofid.cpp:263
Find the least common multiple of the arguments&#39; denominators and use that as the denominator of the ...
Definition: gnc-numeric.h:201
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 ...
Never round at all, and signal an error if there is a fractional result in a computation.
Definition: gnc-numeric.h:178
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:942
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition: qofbook.cpp:604
gint64 time64
Many systems, including Microsoft Windows and BSD-derived Unixes like Darwin, are retaining the int-3...
Definition: gnc-date.h:93
void gncEntrySetDate(GncEntry *entry, time64 date)
DEPRECATED - use gncEntrySetDateGDate() instead! (Because the time-of-day is a misleading extra infor...
Definition: gncEntry.c:478
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
Definition: qofobject.cpp:317
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
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:413
gboolean qof_instance_has_kvp(QofInstance *inst)
Report whether a QofInstance has anything stored in KVP.
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:246
GncAmountType
How to interpret the amount.
Definition: gncTaxTable.h:67
gnc_numeric gncEntryGetDocQuantity(const GncEntry *entry, gboolean is_cn)
Get the quantity as on the physical document.
Definition: gncEntry.c:948
Commodity handling public routines.
modtime is the internal date of the last modtime See src/doc/business.txt for an explanation of the f...
gchar * qof_instance_get_display_name(const QofInstance *inst)
Returns a displayable name for this object.
Utility functions for file access.