33 #include <glib/gi18n.h>
34 #include <qofinstance-p.h>
38 #include "gncBillTermP.h"
40 #include "gncEntryP.h"
44 #include "gncInvoiceP.h"
45 #include "gncOwnerP.h"
46 #include "engine-helpers.h"
83 #define _GNC_MOD_NAME GNC_ID_INVOICE
85 #define GNC_INVOICE_IS_CN "credit-note"
87 #define SET_STR(obj, member, str) { \
90 if (!g_strcmp0 (member, str)) return; \
91 gncInvoiceBeginEdit (obj); \
92 tmp = CACHE_INSERT (str); \
93 CACHE_REMOVE (member); \
97 static void mark_invoice (
GncInvoice *invoice);
101 qof_instance_set_dirty(&invoice->inst);
134 G_DEFINE_TYPE(
GncInvoice, gnc_invoice, QOF_TYPE_INSTANCE);
142 gnc_invoice_dispose(GObject *invp)
144 G_OBJECT_CLASS(gnc_invoice_parent_class)->dispose(invp);
148 gnc_invoice_finalize(GObject* invp)
150 G_OBJECT_CLASS(gnc_invoice_parent_class)->finalize(invp);
154 gnc_invoice_get_property (GObject *
object,
161 g_return_if_fail(GNC_IS_INVOICE(
object));
163 inv = GNC_INVOICE(
object);
167 g_value_set_string(value, inv->notes);
170 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, prop_id, pspec);
176 gnc_invoice_set_property (GObject *
object,
183 g_return_if_fail(GNC_IS_INVOICE(
object));
185 inv = GNC_INVOICE(
object);
186 g_assert (qof_instance_get_editlevel(inv));
191 gncInvoiceSetNotes(inv, g_value_get_string(value));
194 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, prop_id, pspec);
207 g_return_val_if_fail(inst != NULL, FALSE);
208 g_return_val_if_fail(GNC_IS_INVOICE(inst), FALSE);
210 inv = GNC_INVOICE(inst);
217 s = g_strdup_printf(
"Invoice %s (%s)", inv->id, display_name);
218 g_free(display_name);
222 s = g_strdup_printf(
"Invoice %s", inv->id);
234 g_return_val_if_fail(inst != NULL, FALSE);
235 g_return_val_if_fail(GNC_IS_INVOICE(inst), FALSE);
237 inv = GNC_INVOICE(inst);
239 if (GNC_IS_BILLTERM(ref))
241 return (inv->terms == GNC_BILLTERM(ref));
243 else if (GNC_IS_JOB(ref))
245 return (inv->job == GNC_JOB(ref));
247 else if (GNC_IS_COMMODITY(ref))
249 return (inv->currency == GNC_COMMODITY(ref));
251 else if (GNC_IS_ACCOUNT(ref))
253 return (inv->posted_acc == GNC_ACCOUNT(ref));
255 else if (GNC_IS_TRANSACTION(ref))
257 return (inv->posted_txn == GNC_TRANSACTION(ref));
259 else if (GNC_IS_LOT(ref))
261 return (inv->posted_lot == GNC_LOT(ref));
276 if (!GNC_IS_BILLTERM(ref) && !GNC_IS_JOB(ref) && !GNC_IS_COMMODITY(ref) && !GNC_IS_ACCOUNT(ref)
277 && !GNC_IS_TRANSACTION(ref) && !GNC_IS_LOT(ref))
288 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
291 gobject_class->dispose = gnc_invoice_dispose;
292 gobject_class->finalize = gnc_invoice_finalize;
293 gobject_class->set_property = gnc_invoice_set_property;
294 gobject_class->get_property = gnc_invoice_get_property;
296 qof_class->get_display_name = impl_get_display_name;
297 qof_class->refers_to_object = impl_refers_to_object;
298 qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
300 g_object_class_install_property
303 g_param_spec_string (
"notes",
305 "The invoice notes is an arbitrary string "
306 "assigned by the user to provide notes regarding "
317 if (!book)
return NULL;
319 invoice = g_object_new (GNC_TYPE_INVOICE, NULL);
322 invoice->id = CACHE_INSERT (
"");
323 invoice->notes = CACHE_INSERT (
"");
324 invoice->billing_id = CACHE_INSERT (
"");
326 invoice->billto.type = GNC_OWNER_CUSTOMER;
327 invoice->active = TRUE;
329 invoice->to_charge_amount = gnc_numeric_zero();
347 invoice = g_object_new (GNC_TYPE_INVOICE, NULL);
350 gncInvoiceBeginEdit(invoice);
352 invoice->id = CACHE_INSERT (from->id);
353 invoice->notes = CACHE_INSERT (from->notes);
354 invoice->billing_id = CACHE_INSERT (from->billing_id);
355 invoice->active = from->active;
357 is_cn = kvp_frame_get_gint64(from->inst.kvp_data, GNC_INVOICE_IS_CN);
360 invoice->terms = from->terms;
361 gncBillTermIncRef (invoice->terms);
363 gncOwnerCopy(&from->billto, &invoice->billto);
364 gncOwnerCopy(&from->owner, &invoice->owner);
365 invoice->job = from->job;
367 invoice->to_charge_amount = from->to_charge_amount;
368 invoice->date_opened = from->date_opened;
371 invoice->currency = from->currency;
374 for (node = from->entries; node; node = node->next)
377 GncEntry *to_entry = gncEntryCreate(book);
378 gncEntryCopy(from_entry, to_entry, FALSE);
380 switch (gncInvoiceGetOwnerType (invoice))
382 case GNC_OWNER_VENDOR:
383 case GNC_OWNER_EMPLOYEE:
387 case GNC_OWNER_CUSTOMER:
390 gncInvoiceAddEntry(invoice, to_entry);
399 mark_invoice (invoice);
400 gncInvoiceCommitEdit(invoice);
407 if (!invoice)
return;
408 qof_instance_set_destroying(invoice, TRUE);
409 gncInvoiceCommitEdit (invoice);
412 static void gncInvoiceFree (
GncInvoice *invoice)
414 if (!invoice)
return;
418 CACHE_REMOVE (invoice->id);
419 CACHE_REMOVE (invoice->notes);
420 CACHE_REMOVE (invoice->billing_id);
421 g_list_free (invoice->entries);
422 g_list_free (invoice->prices);
424 if (invoice->printname) g_free (invoice->printname);
427 gncBillTermDecRef (invoice->terms);
430 g_object_unref (invoice);
436 void gncInvoiceSetID (
GncInvoice *invoice,
const char *
id)
438 if (!invoice || !
id)
return;
439 SET_STR (invoice, invoice->id,
id);
440 mark_invoice (invoice);
441 gncInvoiceCommitEdit (invoice);
446 if (!invoice || !owner)
return;
448 gncInvoiceBeginEdit (invoice);
449 gncOwnerCopy (owner, &invoice->owner);
450 mark_invoice (invoice);
451 gncInvoiceCommitEdit (invoice);
457 if (!invoice || !ent)
461 gncInvoiceBeginEdit (invoice);
463 mark_invoice (invoice);
464 gncInvoiceCommitEdit (invoice);
470 if (!invoice || !ent)
474 gncInvoiceBeginEdit (invoice);
476 mark_invoice (invoice);
477 gncInvoiceCommitEdit (invoice);
488 if (!invoice)
return;
490 gncInvoiceBeginEdit (invoice);
491 invoice->date_opened = date;
492 mark_invoice (invoice);
493 gncInvoiceCommitEdit (invoice);
498 if (!invoice)
return;
500 gncInvoiceBeginEdit (invoice);
501 invoice->date_posted = date;
502 mark_invoice (invoice);
503 gncInvoiceCommitEdit (invoice);
508 if (!invoice)
return;
509 if (invoice->terms == terms)
return;
510 gncInvoiceBeginEdit (invoice);
512 gncBillTermDecRef (invoice->terms);
513 invoice->terms = terms;
515 gncBillTermIncRef (invoice->terms);
516 mark_invoice (invoice);
517 gncInvoiceCommitEdit (invoice);
520 void gncInvoiceSetBillingID (
GncInvoice *invoice,
const char *billing_id)
522 if (!invoice)
return;
523 SET_STR (invoice, invoice->billing_id, billing_id);
524 mark_invoice (invoice);
525 gncInvoiceCommitEdit (invoice);
528 void gncInvoiceSetNotes (
GncInvoice *invoice,
const char *notes)
530 if (!invoice || !notes)
return;
531 SET_STR (invoice, invoice->notes, notes);
532 mark_invoice (invoice);
533 gncInvoiceCommitEdit (invoice);
536 void gncInvoiceSetActive (
GncInvoice *invoice, gboolean active)
538 if (!invoice)
return;
539 if (invoice->active == active)
return;
540 gncInvoiceBeginEdit (invoice);
541 invoice->active = active;
542 mark_invoice (invoice);
543 gncInvoiceCommitEdit (invoice);
546 void gncInvoiceSetIsCreditNote (
GncInvoice *invoice, gboolean credit_note)
548 if (!invoice)
return;
549 gncInvoiceBeginEdit (invoice);
551 credit_note ? 1 : 0);
552 mark_invoice (invoice);
553 gncInvoiceCommitEdit (invoice);
564 if (!invoice || !currency)
return;
565 if (invoice->currency &&
568 gncInvoiceBeginEdit (invoice);
569 invoice->currency = currency;
570 mark_invoice (invoice);
571 gncInvoiceCommitEdit (invoice);
576 if (!invoice || !billto)
return;
579 gncInvoiceBeginEdit (invoice);
580 gncOwnerCopy (billto, &invoice->billto);
581 mark_invoice (invoice);
582 gncInvoiceCommitEdit (invoice);
587 if (!invoice)
return;
589 gncInvoiceBeginEdit (invoice);
590 invoice->to_charge_amount = amount;
591 mark_invoice (invoice);
592 gncInvoiceCommitEdit (invoice);
597 if (!invoice)
return;
598 g_return_if_fail (invoice->posted_txn == NULL);
600 gncInvoiceBeginEdit (invoice);
601 invoice->posted_txn = txn;
602 mark_invoice (invoice);
603 gncInvoiceCommitEdit (invoice);
608 if (!invoice)
return;
609 g_return_if_fail (invoice->posted_lot == NULL);
611 gncInvoiceBeginEdit (invoice);
612 invoice->posted_lot = lot;
613 mark_invoice (invoice);
614 gncInvoiceCommitEdit (invoice);
619 if (!invoice)
return;
620 g_return_if_fail (invoice->posted_acc == NULL);
622 gncInvoiceBeginEdit (invoice);
623 invoice->posted_acc = acc;
624 mark_invoice (invoice);
625 gncInvoiceCommitEdit (invoice);
634 if (!invoice || !entry)
return;
636 old = gncEntryGetInvoice (entry);
637 if (old == invoice)
return;
638 if (old) gncInvoiceRemoveEntry (old, entry);
640 gncInvoiceBeginEdit (invoice);
641 gncEntrySetInvoice (entry, invoice);
642 invoice->entries = g_list_insert_sorted (invoice->entries, entry,
643 (GCompareFunc)gncEntryCompare);
644 mark_invoice (invoice);
645 gncInvoiceCommitEdit (invoice);
650 if (!invoice || !entry)
return;
652 gncInvoiceBeginEdit (invoice);
653 gncEntrySetInvoice (entry, NULL);
654 invoice->entries = g_list_remove (invoice->entries, entry);
655 mark_invoice (invoice);
656 gncInvoiceCommitEdit (invoice);
664 if (!invoice || !price)
return;
668 node = g_list_first(invoice->prices);
669 commodity = gnc_price_get_commodity (price);
675 node = g_list_next (node);
678 gncInvoiceBeginEdit (invoice);
680 invoice->prices = g_list_delete_link (invoice->prices, node);
681 invoice->prices = g_list_prepend(invoice->prices, price);
682 mark_invoice (invoice);
683 gncInvoiceCommitEdit (invoice);
692 if (!bill || !entry)
return;
694 old = gncEntryGetBill (entry);
695 if (old == bill)
return;
696 if (old) gncBillRemoveEntry (old, entry);
698 gncInvoiceBeginEdit (bill);
699 gncEntrySetBill (entry, bill);
700 bill->entries = g_list_insert_sorted (bill->entries, entry,
701 (GCompareFunc)gncEntryCompare);
703 gncInvoiceCommitEdit (bill);
708 if (!bill || !entry)
return;
710 gncInvoiceBeginEdit (bill);
711 gncEntrySetBill (entry, NULL);
712 bill->entries = g_list_remove (bill->entries, entry);
714 gncInvoiceCommitEdit (bill);
719 if (!invoice)
return;
720 invoice->entries = g_list_sort(invoice->entries,
721 (GCompareFunc)gncEntryCompare);
722 gncInvoiceBeginEdit (invoice);
723 mark_invoice(invoice);
724 gncInvoiceCommitEdit (invoice);
731 if (!invoice)
return;
733 for (node = invoice->entries; node; node = node->next)
737 switch (gncInvoiceGetOwnerType (invoice))
739 case GNC_OWNER_VENDOR:
740 case GNC_OWNER_EMPLOYEE:
742 gncBillRemoveEntry (invoice, entry);
744 case GNC_OWNER_CUSTOMER:
747 gncInvoiceRemoveEntry (invoice, entry);
754 if (!(gncEntryGetInvoice (entry) ||
755 gncEntryGetBill (entry) ||
756 gncEntryGetOrder (entry)))
758 gncEntryBeginEdit (entry);
759 gncEntryDestroy (entry);
767 const char * gncInvoiceGetID (
const GncInvoice *invoice)
769 if (!invoice)
return NULL;
775 if (!invoice)
return NULL;
776 return &invoice->owner;
788 owner = &invoice->owner;
789 return QOF_INSTANCE(owner);
801 billto = &invoice->billto;
802 return QOF_INSTANCE(billto);
810 if (!invoice)
return ts;
811 return invoice->date_opened;
819 if (!invoice)
return ts;
820 return invoice->date_posted;
829 if (!invoice)
return ts;
830 txn = gncInvoiceGetPostedTxn (invoice);
837 if (!invoice)
return NULL;
838 return invoice->terms;
841 const char * gncInvoiceGetBillingID (
const GncInvoice *invoice)
843 if (!invoice)
return NULL;
844 return invoice->billing_id;
847 const char * gncInvoiceGetNotes (
const GncInvoice *invoice)
849 if (!invoice)
return NULL;
850 return invoice->notes;
853 GncOwnerType gncInvoiceGetOwnerType (
const GncInvoice *invoice)
856 g_return_val_if_fail (invoice, GNC_OWNER_NONE);
863 gncInvoiceGetTotalInternal (
GncInvoice *invoice, gboolean use_value,
865 gboolean use_payment_type, GncEntryPaymentType type)
869 gboolean is_cust_doc, is_cn;
871 g_return_val_if_fail (invoice, total);
876 is_cust_doc = (gncInvoiceGetOwnerType (invoice) == GNC_OWNER_CUSTOMER);
877 is_cn = gncInvoiceGetIsCreditNote (invoice);
879 for (node = gncInvoiceGetEntries(invoice); node; node = node->next)
884 if (use_payment_type && gncEntryGetBillPayment (entry) != type)
887 value = gncEntryGetDocValue (entry, FALSE, is_cust_doc, is_cn);
894 g_warning (
"bad value in our entry");
898 tax = gncEntryGetDocTaxValue (entry, FALSE, is_cust_doc, is_cn);
902 g_warning (
"bad tax-value in our entry");
910 if (!invoice)
return gnc_numeric_zero();
911 return gncInvoiceGetTotalInternal(invoice, TRUE, TRUE, FALSE, 0);
916 if (!invoice)
return gnc_numeric_zero();
917 return gncInvoiceGetTotalInternal(invoice, TRUE, FALSE, FALSE, 0);
922 if (!invoice)
return gnc_numeric_zero();
923 return gncInvoiceGetTotalInternal(invoice, FALSE, TRUE, FALSE, 0);
928 if (!invoice)
return gnc_numeric_zero();
929 return gncInvoiceGetTotalInternal(invoice, TRUE, TRUE, TRUE, type);
932 GList * gncInvoiceGetTypeListForOwnerType (GncOwnerType type)
934 GList *type_list = NULL;
937 case GNC_OWNER_CUSTOMER:
938 type_list = g_list_append (type_list, GINT_TO_POINTER(GNC_INVOICE_CUST_INVOICE));
939 type_list = g_list_append (type_list, GINT_TO_POINTER(GNC_INVOICE_CUST_CREDIT_NOTE));
941 case GNC_OWNER_VENDOR:
942 type_list = g_list_append (type_list, GINT_TO_POINTER(GNC_INVOICE_VEND_INVOICE));
943 type_list = g_list_append (type_list, GINT_TO_POINTER(GNC_INVOICE_VEND_CREDIT_NOTE));
945 case GNC_OWNER_EMPLOYEE:
946 type_list = g_list_append (type_list, GINT_TO_POINTER(GNC_INVOICE_EMPL_INVOICE));
947 type_list = g_list_append (type_list, GINT_TO_POINTER(GNC_INVOICE_EMPL_CREDIT_NOTE));
955 GncInvoiceType gncInvoiceGetType (
const GncInvoice *invoice)
957 if (!invoice)
return GNC_INVOICE_UNDEFINED;
958 switch (gncInvoiceGetOwnerType (invoice))
960 case GNC_OWNER_CUSTOMER:
961 return (gncInvoiceGetIsCreditNote(invoice) ?
962 GNC_INVOICE_CUST_CREDIT_NOTE :
963 GNC_INVOICE_CUST_INVOICE);
964 case GNC_OWNER_VENDOR:
965 return (gncInvoiceGetIsCreditNote(invoice) ?
966 GNC_INVOICE_VEND_CREDIT_NOTE :
967 GNC_INVOICE_VEND_INVOICE);
968 case GNC_OWNER_EMPLOYEE:
969 return (gncInvoiceGetIsCreditNote(invoice) ?
970 GNC_INVOICE_EMPL_CREDIT_NOTE :
971 GNC_INVOICE_EMPL_INVOICE);
973 PWARN (
"No invoice types defined for owner %d",
974 gncInvoiceGetOwnerType (invoice));
975 return GNC_INVOICE_UNDEFINED;
979 const char * gncInvoiceGetTypeString (
const GncInvoice *invoice)
981 GncInvoiceType type = gncInvoiceGetType(invoice);
984 case GNC_INVOICE_CUST_INVOICE:
986 case GNC_INVOICE_VEND_INVOICE:
988 case GNC_INVOICE_EMPL_INVOICE:
990 case GNC_INVOICE_CUST_CREDIT_NOTE:
991 case GNC_INVOICE_VEND_CREDIT_NOTE:
992 case GNC_INVOICE_EMPL_CREDIT_NOTE:
993 return _(
"Credit Note");
995 PWARN(
"Unknown invoice type");
1002 if (!invoice)
return NULL;
1003 return invoice->currency;
1008 if (!invoice)
return NULL;
1009 return &invoice->billto;
1014 if (!invoice)
return NULL;
1015 return invoice->posted_lot;
1020 if (!invoice)
return NULL;
1021 return invoice->posted_txn;
1026 if (!invoice)
return NULL;
1027 return invoice->posted_acc;
1030 gboolean gncInvoiceGetActive (
const GncInvoice *invoice)
1032 if (!invoice)
return FALSE;
1033 return invoice->active;
1036 gboolean gncInvoiceGetIsCreditNote (
const GncInvoice *invoice)
1038 if (!invoice)
return FALSE;
1039 if (kvp_frame_get_gint64(invoice->inst.kvp_data, GNC_INVOICE_IS_CN))
1048 if (!invoice)
return gnc_numeric_zero();
1049 return invoice->to_charge_amount;
1052 EntryList * gncInvoiceGetEntries (
GncInvoice *invoice)
1054 if (!invoice)
return NULL;
1055 return invoice->entries;
1060 GList *node = g_list_first(invoice->prices);
1062 while (node != NULL)
1069 node = g_list_next(node);
1075 static QofCollection*
1078 QofCollection *entry_coll;
1083 for (list = gncInvoiceGetEntries(invoice); list != NULL; list = list->next)
1085 entry = QOF_INSTANCE(list->data);
1092 qofInvoiceEntryCB (
QofInstance *ent, gpointer user_data)
1097 if (!invoice || !ent)
1101 switch (gncInvoiceGetOwnerType (invoice))
1103 case GNC_OWNER_VENDOR:
1110 gncInvoiceAddEntry(invoice, (
GncEntry*)ent);
1117 qofInvoiceSetEntries(
GncInvoice *invoice, QofCollection *entry_coll)
1136 return invoice->job;
1150 gncInvoiceDetachFromLot (
GNCLot *lot)
1154 gnc_lot_begin_edit (lot);
1156 gnc_lot_commit_edit (lot);
1163 if (!invoice || !lot)
1166 if (invoice->posted_lot)
return;
1168 gnc_lot_begin_edit (lot);
1170 gnc_lot_commit_edit (lot);
1171 gncInvoiceSetPostedLot (invoice, lot);
1179 if (!lot)
return NULL;
1181 book = gnc_lot_get_book (lot);
1183 return gncInvoiceLookup(book, guid);
1189 if (!invoice || !txn)
1192 if (invoice->posted_txn)
return;
1199 gncInvoiceSetPostedTxn (invoice, txn);
1208 if (!txn)
return NULL;
1212 return gncInvoiceLookup(book, guid);
1217 switch (gncInvoiceGetType (invoice))
1219 case GNC_INVOICE_CUST_INVOICE:
1220 case GNC_INVOICE_VEND_CREDIT_NOTE:
1221 case GNC_INVOICE_EMPL_CREDIT_NOTE:
1223 case GNC_INVOICE_CUST_CREDIT_NOTE:
1224 case GNC_INVOICE_VEND_INVOICE:
1225 case GNC_INVOICE_EMPL_INVOICE:
1227 case GNC_INVOICE_UNDEFINED:
1231 g_assert_not_reached();
1238 EntryList *entries_iter;
1239 gboolean is_cust_doc = (gncInvoiceGetOwnerType (invoice) == GNC_OWNER_CUSTOMER);
1240 gboolean is_cn = gncInvoiceGetIsCreditNote (invoice);
1241 GHashTable *amt_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal,
1244 for (entries_iter = invoice->entries; entries_iter != NULL; entries_iter = g_list_next(entries_iter))
1249 AccountValueList *tt_amts = NULL, *tt_iter;
1252 this_acc = (is_cust_doc ? gncEntryGetInvAccount (entry) :
1253 gncEntryGetBillAccount (entry));
1261 *entry_amt = gncEntryGetDocValue (entry, FALSE, is_cust_doc, is_cn);
1264 g_hash_table_insert (amt_hash, account_currency, entry_amt);
1274 for (tt_iter = tt_amts; tt_iter != NULL; tt_iter = g_list_next(tt_iter))
1277 Account *tt_acc = tt_amt_val->account;
1285 *tt_acc_amt = tt_amt_val->value;
1288 g_hash_table_insert (amt_hash, tt_acc_currency, tt_acc_amt);
1296 static gboolean gncInvoicePostAddSplit (
QofBook *book,
1311 gnc_set_num_action (NULL, split, gncInvoiceGetID(invoice), type);
1365 const char * memo, gboolean accumulatesplits,
1372 GList *splitinfo = NULL;
1374 gboolean is_cust_doc;
1376 const char *name, *type;
1381 if (!invoice || !acc)
return NULL;
1383 gncInvoiceBeginEdit (invoice);
1388 gncInvoiceSetTerms (invoice,
1389 gncBillTermReturnChild (invoice->terms, TRUE));
1392 is_cust_doc = (gncInvoiceGetOwnerType (invoice) == GNC_OWNER_CUSTOMER);
1393 is_cn = gncInvoiceGetIsCreditNote (invoice);
1397 if (gncInvoiceGetOwnerType (invoice) == GNC_OWNER_EMPLOYEE)
1401 lot = gnc_lot_new (book);
1402 gnc_lot_begin_edit (lot);
1404 type = gncInvoiceGetTypeString (invoice);
1407 lot_title = g_strdup_printf (
"%s %s", type, gncInvoiceGetID (invoice));
1408 gnc_lot_set_title (lot, lot_title);
1420 gnc_set_num_action (txn, NULL, gncInvoiceGetID (invoice), type);
1428 gncInvoiceSetDatePosted (invoice, *post_date);
1437 total = gnc_numeric_zero();
1438 for (iter = gncInvoiceGetEntries(invoice); iter; iter = iter->next)
1446 gncEntryBeginEdit (entry);
1448 gncEntrySetInvTaxTable
1449 (entry, gncTaxTableReturnChild (gncEntryGetInvTaxTable (entry), TRUE));
1452 gncEntrySetBillTaxTable
1453 (entry, gncTaxTableReturnChild (gncEntryGetBillTaxTable (entry), TRUE));
1456 if (gncEntryGetBillable (entry))
1457 gncEntrySetInvPrice (entry, gncEntryGetBillPrice (entry));
1459 gncEntryCommitEdit (entry);
1462 value = gncEntryGetBalValue (entry, FALSE, is_cust_doc);
1463 tax = gncEntryGetBalTaxValue (entry, FALSE, is_cust_doc);
1467 this_acc = (is_cust_doc ? gncEntryGetInvAccount (entry) :
1468 gncEntryGetBillAccount (entry));
1473 if (accumulatesplits)
1475 else if (!gncInvoicePostAddSplit (book, this_acc, txn, value,
1476 gncEntryGetDescription (entry),
1495 if (ccard_acct && gncEntryGetBillPayment (entry) == GNC_PAYMENT_CARD)
1502 gnc_set_num_action (NULL, split, gncInvoiceGetID (invoice), type);
1516 g_warning (
"bad value in our entry");
1526 g_warning (
"bad tax in our entry");
1532 for (iter = splitinfo; iter; iter = iter->next)
1535 if (!gncInvoicePostAddSplit (book, acc_val->account, txn, acc_val->value,
1536 memo, type, invoice))
1556 : invoice->to_charge_amount);
1561 gnc_set_num_action (NULL, split, gncInvoiceGetID (invoice), type);
1581 gnc_set_num_action (NULL, split, gncInvoiceGetID (invoice), type);
1595 gncInvoiceAttachToLot (invoice, lot);
1596 gncInvoiceAttachToTxn (invoice, txn);
1597 gncInvoiceSetPostedAcc (invoice, acc);
1604 gnc_lot_commit_edit (lot);
1607 DEBUG(
"Committing Invoice %s", invoice->id);
1608 mark_invoice (invoice);
1609 gncInvoiceCommitEdit (invoice);
1625 GList *lot_split_list, *lot_split_iter;
1627 if (!invoice)
return FALSE;
1628 if (!gncInvoiceIsPosted (invoice))
return FALSE;
1630 txn = gncInvoiceGetPostedTxn (invoice);
1631 g_return_val_if_fail (txn, FALSE);
1633 lot = gncInvoiceGetPostedLot (invoice);
1634 g_return_val_if_fail (lot, FALSE);
1637 xaccTransClearReadOnly (txn);
1643 gncInvoiceDetachFromLot (lot);
1661 for (lot_split_iter = lot_split_list; lot_split_iter; lot_split_iter = lot_split_iter->next)
1663 Split *split = lot_split_iter->data;
1664 GList *other_split_list, *list_iter;
1666 GList *lot_list = NULL;
1675 for (list_iter = other_split_list; list_iter; list_iter = list_iter->next)
1677 Split *other_split = list_iter->data;
1681 if (other_lot == lot)
1684 lot_list = g_list_prepend (lot_list, other_lot);
1687 lot_list = g_list_reverse (lot_list);
1690 xaccTransClearReadOnly (other_txn);
1701 for (list_iter = lot_list; list_iter; list_iter = list_iter->next)
1703 GNCLot *other_lot = list_iter->data;
1706 if (!gnc_lot_count_splits (other_lot))
1707 gnc_lot_destroy (other_lot);
1708 else if (other_invoice)
1709 qof_event_gen (QOF_INSTANCE(other_invoice), QOF_EVENT_MODIFY, NULL);
1712 g_list_free (lot_split_list);
1715 if (!gnc_lot_count_splits (lot))
1716 gnc_lot_destroy (lot);
1719 gncInvoiceBeginEdit (invoice);
1721 invoice->posted_acc = NULL;
1722 invoice->posted_txn = NULL;
1723 invoice->posted_lot = NULL;
1724 invoice->date_posted.tv_sec = invoice->date_posted.tv_nsec = 0;
1727 if (reset_tax_tables)
1729 gboolean is_cust_doc = (gncInvoiceGetOwnerType(invoice) == GNC_OWNER_CUSTOMER);
1732 for (iter = gncInvoiceGetEntries(invoice); iter; iter = iter->next)
1736 gncEntryBeginEdit(entry);
1738 gncEntrySetInvTaxTable(entry,
1739 gncTaxTableGetParent(gncEntryGetInvTaxTable(entry)));
1741 gncEntrySetBillTaxTable(entry,
1742 gncTaxTableGetParent(gncEntryGetBillTaxTable(entry)));
1743 gncEntryCommitEdit(entry);
1747 mark_invoice (invoice);
1748 gncInvoiceCommitEdit (invoice);
1756 gboolean positive_balance;
1760 gnc_lot_match_owner_balancing (
GNCLot *lot, gpointer user_data)
1802 g_return_if_fail (invoice);
1803 g_return_if_fail (invoice->posted_lot);
1805 inv_lot = invoice->posted_lot;
1806 acct = invoice->posted_acc;
1820 lot_list = g_list_prepend (lot_list, inv_lot);
1822 g_list_free (lot_list);
1833 const char *memo,
const char *num)
1836 GList *selected_lots = NULL;
1840 if (!invoice || !gncInvoiceIsPosted (invoice) || !xfer_acc)
return;
1843 g_return_if_fail (owner->owner.undefined);
1847 amount, exch, date, memo, num);
1850 selected_lots = g_list_prepend (selected_lots, invoice->posted_lot);
1854 selected_lots = g_list_prepend (selected_lots, payment_lot);
1858 static gboolean gncInvoiceDateExists (
const Timespec *date)
1860 g_return_val_if_fail (date, FALSE);
1861 if (date->tv_sec || date->tv_nsec)
return TRUE;
1865 gboolean gncInvoiceIsPosted (
const GncInvoice *invoice)
1867 if (!invoice)
return FALSE;
1868 return gncInvoiceDateExists (&(invoice->date_posted));
1871 gboolean gncInvoiceIsPaid (
const GncInvoice *invoice)
1873 if (!invoice)
return FALSE;
1874 if (!invoice->posted_lot)
return FALSE;
1880 void gncInvoiceBeginEdit (
GncInvoice *invoice)
1887 PERR(
"Invoice QofBackend Failure: %d", errcode);
1888 gnc_engine_signal_commit_error( errcode );
1891 static void gncInvoiceOnDone (
QofInstance *invoice) { }
1896 gncInvoiceFree (invoice);
1899 void gncInvoiceCommitEdit (
GncInvoice *invoice)
1903 gncInvoiceOnDone, invoice_free);
1910 if (a == b)
return 0;
1914 compare = g_strcmp0 (a->id, b->id);
1915 if (compare)
return compare;
1917 compare =
timespec_cmp (&(a->date_opened), &(b->date_opened));
1918 if (compare)
return compare;
1920 compare =
timespec_cmp (&(a->date_posted), &(b->date_posted));
1921 if (compare)
return compare;
1928 if (a == NULL && b == NULL)
return TRUE;
1929 if (a == NULL || b == NULL)
return FALSE;
1931 g_return_val_if_fail(GNC_IS_INVOICE(a), FALSE);
1932 g_return_val_if_fail(GNC_IS_INVOICE(b), FALSE);
1934 if (g_strcmp0(a->id, b->id) != 0)
1936 PWARN(
"IDs differ: %s vs %s", a->id, b->id);
1940 if (g_strcmp0(a->notes, b->notes) != 0)
1942 PWARN(
"Notes differ: %s vs %s", a->notes, b->notes);
1946 if (g_strcmp0(a->billing_id, b->billing_id) != 0)
1948 PWARN(
"Billing IDs differ: %s vs %s", a->billing_id, b->billing_id);
1952 if (g_strcmp0(a->printname, b->printname) != 0)
1954 PWARN(
"Printnames differ: %s vs %s", a->printname, b->printname);
1958 if (a->active != b->active)
1960 PWARN(
"Active flags differ");
1966 PWARN(
"Billterms differ");
1970 if (!gncJobEqual(a->job, b->job))
1972 PWARN(
"Jobs differ");
1978 PWARN(
"Currencies differ");
1984 PWARN(
"Posted accounts differ");
1988 if (!
xaccTransEqual(a->posted_txn, b->posted_txn, TRUE, TRUE, TRUE, FALSE))
1990 PWARN(
"Posted tx differ");
1995 if (!gncLotEqual(a->posted_lot, b->posted_lot))
1997 PWARN(
"Posted lots differ");
2020 static const char * _gncInvoicePrintable (gpointer obj)
2024 g_return_val_if_fail (invoice, NULL);
2028 if (invoice->printname) g_free (invoice->printname);
2030 invoice->printname =
2031 g_strdup_printf (
"%s%s", invoice->id,
2032 gncInvoiceIsPosted (invoice) ? _(
" (posted)") :
"");
2035 return invoice->printname;
2039 destroy_invoice_on_book_close(
QofInstance *ent, gpointer data)
2043 gncInvoiceBeginEdit(invoice);
2044 gncInvoiceDestroy(invoice);
2048 gnc_invoice_book_end(
QofBook* book)
2059 DI(.e_type = ) _GNC_MOD_NAME,
2060 DI(.type_label = ) "Invoice",
2061 DI(.create = ) (gpointer)gncInvoiceCreate,
2062 DI(.book_begin = ) NULL,
2063 DI(.book_end = ) gnc_invoice_book_end,
2067 DI(.printable = ) _gncInvoicePrintable,
2077 INVOICE_FROM_LOT, _GNC_MOD_NAME,
2092 INVOICE_FROM_TXN, _GNC_MOD_NAME,
2101 gboolean gncInvoiceRegister (
void)
2106 { INVOICE_OWNER, GNC_ID_OWNER, (
QofAccessFunc)gncInvoiceGetOwner, NULL },
2108 { INVOICE_DUE, QOF_TYPE_DATE, (
QofAccessFunc)gncInvoiceGetDateDue, NULL },
2110 { INVOICE_IS_POSTED, QOF_TYPE_BOOLEAN, (
QofAccessFunc)gncInvoiceIsPosted, NULL },
2111 { INVOICE_IS_PAID, QOF_TYPE_BOOLEAN, (
QofAccessFunc)gncInvoiceIsPaid, NULL },
2116 { INVOICE_POST_LOT, GNC_ID_LOT, (
QofAccessFunc)gncInvoiceGetPostedLot, NULL },
2117 { INVOICE_TYPE, QOF_TYPE_INT32, (
QofAccessFunc)gncInvoiceGetType, NULL },
2118 { INVOICE_TYPE_STRING, QOF_TYPE_STRING, (
QofAccessFunc)gncInvoiceGetTypeString, NULL },
2120 { INVOICE_BILLTO, GNC_ID_OWNER, (
QofAccessFunc)gncInvoiceGetBillTo, NULL },
2137 qofInvoiceSetEntries(NULL, NULL);
2138 qofInvoiceGetEntries(NULL);
2139 qofInvoiceSetOwner(NULL, NULL);
2140 qofInvoiceGetOwner(NULL);
2141 qofInvoiceSetBillTo(NULL, NULL);
2142 qofInvoiceGetBillTo(NULL);
2156 case GNC_OWNER_CUSTOMER:
2159 case GNC_OWNER_VENDOR:
2162 case GNC_OWNER_EMPLOYEE:
void xaccSplitSetValue(Split *s, gnc_numeric amt)
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
#define xaccTransAppendSplit(t, s)
Transaction * xaccMallocTransaction(QofBook *book)
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
void xaccSplitSetBaseValue(Split *s, gnc_numeric value, const gnc_commodity *base_currency)
char xaccTransGetTxnType(const Transaction *trans)
const GncGUID * qof_instance_get_guid(gconstpointer)
void qof_instance_get(const QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_get.
QofBook * qof_instance_get_book(gconstpointer)
gboolean qof_collection_is_dirty(const QofCollection *col)
QofBackendError
The errors that can be reported to the GUI & other front-end users.
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Timespec timespecCanonicalDayTime(Timespec t)
gchar * qof_book_increment_and_format_counter(QofBook *book, const char *counter_name)
GList * qof_instance_get_referring_object_list_from_collection(const QofCollection *coll, const QofInstance *ref)
#define DEBUG(format, args...)
void qof_instance_set(QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_set Group setting multiple parameters in a single begin/commit/rollback.
void gnc_features_set_used(QofBook *book, const gchar *feature)
AccountValueList * gncEntryGetDocTaxValues(GncEntry *entry, gboolean is_cust_doc, gboolean is_cn)
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_fcn, const QofParam *params)
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
gboolean timespec_equal(const Timespec *ta, const Timespec *tb)
void gnc_lot_add_split(GNCLot *lot, Split *split)
void xaccTransSetDescription(Transaction *trans, const char *desc)
gboolean gncOwnerEqual(const GncOwner *a, const GncOwner *b)
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Use a 64-bit unsigned int timespec.
void gncInvoiceRemoveEntries(GncInvoice *invoice)
void kvp_frame_set_gint64(KvpFrame *frame, const gchar *path, gint64 ival)
gboolean gnc_numeric_zero_p(gnc_numeric a)
Transaction * xaccSplitGetParent(const Split *split)
QofCollection * qof_instance_get_collection(gconstpointer inst)
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
GHashTable * gncInvoiceGetForeignCurrencies(const GncInvoice *invoice)
void gncInvoiceSortEntries(GncInvoice *invoice)
#define QOF_OBJECT_VERSION
gboolean qof_commit_edit(QofInstance *inst)
#define PERR(format, args...)
gnc_numeric gncInvoiceGetTotal(GncInvoice *invoice)
void qof_collection_foreach(const QofCollection *, QofInstanceForeachCB, gpointer user_data)
gboolean gncBillTermEqual(const GncBillTerm *a, const GncBillTerm *b)
QofInstance * qofOwnerGetOwner(const GncOwner *owner)
void gncInvoiceAutoApplyPayments(GncInvoice *invoice)
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
void gncOwnerAutoApplyPaymentsWithLots(const GncOwner *owner, GList *lots)
GncInvoice * gncInvoiceGetInvoiceFromTxn(const Transaction *txn)
void xaccTransDestroy(Transaction *trans)
#define PWARN(format, args...)
void qof_instance_init_data(QofInstance *, QofIdType, QofBook *)
gint timespec_cmp(const Timespec *ta, const Timespec *tb)
gboolean qof_begin_edit(QofInstance *inst)
void xaccTransSetTxnType(Transaction *trans, char type)
gdouble gnc_numeric_to_double(gnc_numeric n)
void xaccSplitSetAmount(Split *s, gnc_numeric amt)
gboolean xaccTransEqual(const Transaction *ta, const Transaction *tb, gboolean check_guids, gboolean check_splits, gboolean check_balances, gboolean assume_ordered)
Account handling public routines.
AccountValueList * gncEntryGetBalTaxValues(GncEntry *entry, gboolean is_cust_doc)
void gncInvoiceApplyPayment(const GncInvoice *invoice, Transaction *txn, Account *xfer_acc, gnc_numeric amount, gnc_numeric exch, Timespec date, const char *memo, const char *num)
void xaccTransSetReadOnly(Transaction *trans, const char *reason)
void xaccSplitSetMemo(Split *split, const char *memo)
gboolean qof_instance_get_dirty_flag(gconstpointer ptr)
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
void gncBillAddEntry(GncInvoice *bill, GncEntry *entry)
gboolean qof_choice_create(char *type)
Set an object as using QOF_TYPE_CHOICE.
void qofOwnerSetEntity(GncOwner *owner, QofInstance *ent)
Timespec xaccTransRetDateDueTS(const Transaction *trans)
int(* QofSortFunc)(gconstpointer, gconstpointer)
void gncOwnerAttachToLot(const GncOwner *owner, GNCLot *lot)
gboolean qof_commit_edit_part2(QofInstance *inst, void(*on_error)(QofInstance *, QofBackendError), void(*on_done)(QofInstance *), void(*on_free)(QofInstance *))
gboolean gncOwnerGetOwnerFromLot(GNCLot *lot, GncOwner *owner)
#define xaccTransGetBook(X)
void qof_collection_mark_clean(QofCollection *)
void xaccTransCommitEdit(Transaction *trans)
gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y, gint64 denom, gint how)
void gncAccountValueDestroy(GList *list)
gboolean xaccAccountEqual(const Account *aa, const Account *ab, gboolean check_guids)
void xaccTransBeginEdit(Transaction *trans)
gboolean gnc_numeric_positive_p(gnc_numeric a)
Split * xaccMallocSplit(QofBook *book)
Transaction * gncInvoicePostToAccount(GncInvoice *invoice, Account *acc, Timespec *post_date, Timespec *due_date, const char *memo, gboolean accumulatesplits, gboolean autopay)
void gncInvoiceSetDateOpenedGDate(GncInvoice *invoice, const GDate *date)
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
GncOwnerType gncOwnerGetType(const GncOwner *owner)
const GncOwner * gncOwnerGetEndOwner(const GncOwner *owner)
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Business Invoice Interface.
QofIdType qof_collection_get_type(const QofCollection *)
gboolean gncInvoiceUnpost(GncInvoice *invoice, gboolean reset_tax_tables)
GNCLot * gncOwnerCreatePaymentLot(const GncOwner *owner, Transaction *txn, Account *posted_acc, Account *xfer_acc, gnc_numeric amount, gnc_numeric exch, Timespec date, const char *memo, const char *num)
gboolean qof_collection_add_entity(QofCollection *coll, QofInstance *ent)
Add an entity to a QOF_TYPE_COLLECT.
gboolean gnc_lot_is_closed(GNCLot *lot)
void xaccAccountBeginEdit(Account *acc)
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
#define xaccAccountInsertSplit(acc, s)
gint qof_instance_guid_compare(const gconstpointer ptr1, const gconstpointer ptr2)
void xaccTransSetDateDueTS(Transaction *trans, const Timespec *ts)
GList * gncAccountValueAddList(GList *l1, GList *l2)
void(* QofSetterFunc)(gpointer, gpointer)
time64 gnc_time(time64 *tbuf)
get the current local time
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
QofCollection * qof_book_get_collection(const QofBook *, QofIdType)
Timespec gdate_to_timespec(GDate d)
gboolean qof_object_register(const QofObject *object)
GList * gncAccountValueAdd(GList *list, Account *acc, gnc_numeric value)
LotList * xaccAccountFindOpenLots(const Account *acc, gboolean(*match_func)(GNCLot *lot, gpointer user_data), gpointer user_data, GCompareFunc sort_func)
Business Entry Interface.
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
gboolean gncInvoiceEqual(const GncInvoice *a, const GncInvoice *b)
void qof_event_gen(QofInstance *entity, QofEventId event_type, gpointer event_data)
Invoke all registered event handlers using the given arguments.
GncEmployee * gncOwnerGetEmployee(const GncOwner *owner)
API for Transactions and Splits (journal entries)
GncInvoice * gncInvoiceCopy(const GncInvoice *from)
void xaccAccountCommitEdit(Account *acc)
SplitList * xaccTransGetSplitList(const Transaction *trans)
gboolean gncInvoiceAmountPositive(const GncInvoice *invoice)
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
GNCLot * xaccSplitGetLot(const Split *split)
const gchar * QofLogModule
void xaccTransSetDatePostedTS(Transaction *trans, const Timespec *ts)
QofCollection * qof_collection_new(QofIdType type)
gchar * qof_instance_get_display_name(const QofInstance *inst)
Utility functions for file access.