GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Files | Macros | Typedefs | Enumerations | Functions
Invoice

Files

file  gncInvoice.h
 Business Invoice Interface.
 

Macros

#define GNC_ID_INVOICE   "gncInvoice"
 
#define GNC_TYPE_INVOICE   (gnc_invoice_get_type ())
 
#define GNC_INVOICE(o)   (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_INVOICE, GncInvoice))
 
#define GNC_INVOICE_CLASS(k)   (G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_INVOICE, GncInvoiceClass))
 
#define GNC_IS_INVOICE(o)   (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_INVOICE))
 
#define GNC_IS_INVOICE_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GNC_TYPE_INVOICE))
 
#define GNC_INVOICE_GET_CLASS(o)   (G_TYPE_INSTANCE_GET_CLASS ((o), GNC_TYPE_INVOICE, GncInvoiceClass))
 
#define INVOICE_ID   "id"
 
#define INVOICE_OWNER   "owner"
 
#define INVOICE_OPENED   "date_opened"
 
#define INVOICE_POSTED   "date_posted"
 
#define INVOICE_DUE   "date_due"
 
#define INVOICE_IS_POSTED   "is_posted?"
 
#define INVOICE_IS_PAID   "is_paid?"
 
#define INVOICE_TERMS   "terms"
 
#define INVOICE_BILLINGID   "billing_id"
 
#define INVOICE_NOTES   "notes"
 
#define INVOICE_ACC   "account"
 
#define INVOICE_POST_TXN   "posted_txn"
 
#define INVOICE_POST_LOT   "posted_lot"
 
#define INVOICE_IS_CN   "credit_note"
 
#define INVOICE_TYPE   "type"
 
#define INVOICE_TYPE_STRING   "type_string"
 
#define INVOICE_BILLTO   "bill-to"
 
#define INVOICE_ENTRIES   "list_of_entries"
 
#define INVOICE_JOB   "invoice_job"
 
#define INVOICE_FROM_LOT   "invoice-from-lot"
 
#define INVOICE_FROM_TXN   "invoice-from-txn"
 
#define gncInvoiceGetGUID(x)   qof_instance_get_guid(QOF_INSTANCE(x))
 
#define gncInvoiceRetGUID(x)   (x ? *(qof_instance_get_guid(QOF_INSTANCE(x))) : *(guid_null()))
 

Typedefs

typedef struct _gncInvoice GncInvoice
 
typedef struct _gncInvoiceClass GncInvoiceClass
 
typedef GList GncInvoiceList
 
typedef GList EntryList
 

Enumerations

enum  GncInvoiceType {
  GNC_INVOICE_UNDEFINED, GNC_INVOICE_CUST_INVOICE, GNC_INVOICE_VEND_INVOICE, GNC_INVOICE_EMPL_INVOICE,
  GNC_INVOICE_CUST_CREDIT_NOTE, GNC_INVOICE_VEND_CREDIT_NOTE, GNC_INVOICE_EMPL_CREDIT_NOTE, GNC_INVOICE_NUM_TYPES
}
 

Functions

GType gnc_invoice_get_type (void)
 
void gncInvoiceAddEntry (GncInvoice *invoice, GncEntry *entry)
 
void gncInvoiceRemoveEntry (GncInvoice *invoice, GncEntry *entry)
 
void gncInvoiceAddPrice (GncInvoice *invoice, GNCPrice *price)
 
void gncBillAddEntry (GncInvoice *bill, GncEntry *entry)
 
void gncBillRemoveEntry (GncInvoice *bill, GncEntry *entry)
 
void gncInvoiceSortEntries (GncInvoice *invoice)
 
void gncInvoiceRemoveEntries (GncInvoice *invoice)
 
gnc_numeric gncInvoiceGetTotal (GncInvoice *invoice)
 
gnc_numeric gncInvoiceGetTotalOf (GncInvoice *invoice, GncEntryPaymentType type)
 
gnc_numeric gncInvoiceGetTotalSubtotal (GncInvoice *invoice)
 
gnc_numeric gncInvoiceGetTotalTax (GncInvoice *invoice)
 
EntryList * gncInvoiceGetEntries (GncInvoice *invoice)
 
GNCPricegncInvoiceGetPrice (GncInvoice *invoice, gnc_commodity *commodity)
 
gboolean gncInvoiceAmountPositive (const GncInvoice *invoice)
 
GHashTable * gncInvoiceGetForeignCurrencies (const GncInvoice *invoice)
 
TransactiongncInvoicePostToAccount (GncInvoice *invoice, Account *acc, Timespec *posted_date, Timespec *due_date, const char *memo, gboolean accumulatesplits, gboolean autopay)
 
gboolean gncInvoiceUnpost (GncInvoice *invoice, gboolean reset_tax_tables)
 
void gncInvoiceAutoApplyPayments (GncInvoice *invoice)
 
void gncInvoiceApplyPayment (const GncInvoice *invoice, Transaction *txn, Account *xfer_acc, gnc_numeric amount, gnc_numeric exch, Timespec date, const char *memo, const char *num)
 
GncInvoicegncInvoiceGetInvoiceFromTxn (const Transaction *txn)
 
GncInvoicegncInvoiceGetInvoiceFromLot (GNCLot *lot)
 
void gncInvoiceBeginEdit (GncInvoice *invoice)
 
void gncInvoiceCommitEdit (GncInvoice *invoice)
 
int gncInvoiceCompare (const GncInvoice *a, const GncInvoice *b)
 
gboolean gncInvoiceIsPosted (const GncInvoice *invoice)
 
gboolean gncInvoiceIsPaid (const GncInvoice *invoice)
 
QofBookgncInvoiceGetBook (GncInvoice *x)
 
gboolean gncInvoiceEqual (const GncInvoice *a, const GncInvoice *b)
 

Create/Destroy Functions

GncInvoicegncInvoiceCreate (QofBook *book)
 
void gncInvoiceDestroy (GncInvoice *invoice)
 
GncInvoicegncInvoiceCopy (const GncInvoice *other_invoice)
 

Set Functions

void gncInvoiceSetID (GncInvoice *invoice, const char *id)
 
void gncInvoiceSetOwner (GncInvoice *invoice, GncOwner *owner)
 
void gncInvoiceSetDateOpenedGDate (GncInvoice *invoice, const GDate *date)
 
void gncInvoiceSetDateOpened (GncInvoice *invoice, Timespec date)
 
void gncInvoiceSetDatePosted (GncInvoice *invoice, Timespec date)
 
void gncInvoiceSetTerms (GncInvoice *invoice, GncBillTerm *terms)
 
void gncInvoiceSetBillingID (GncInvoice *invoice, const char *billing_id)
 
void gncInvoiceSetNotes (GncInvoice *invoice, const char *notes)
 
void gncInvoiceSetCurrency (GncInvoice *invoice, gnc_commodity *currency)
 
void gncInvoiceSetActive (GncInvoice *invoice, gboolean active)
 
void gncInvoiceSetIsCreditNote (GncInvoice *invoice, gboolean credit_note)
 
void gncInvoiceSetBillTo (GncInvoice *invoice, GncOwner *billto)
 
void gncInvoiceSetToChargeAmount (GncInvoice *invoice, gnc_numeric amount)
 

Get Functions

const char * gncInvoiceGetID (const GncInvoice *invoice)
 
const GncOwnergncInvoiceGetOwner (const GncInvoice *invoice)
 
Timespec gncInvoiceGetDateOpened (const GncInvoice *invoice)
 
Timespec gncInvoiceGetDatePosted (const GncInvoice *invoice)
 
Timespec gncInvoiceGetDateDue (const GncInvoice *invoice)
 
GncBillTermgncInvoiceGetTerms (const GncInvoice *invoice)
 
const char * gncInvoiceGetBillingID (const GncInvoice *invoice)
 
const char * gncInvoiceGetNotes (const GncInvoice *invoice)
 
GncOwnerType gncInvoiceGetOwnerType (const GncInvoice *invoice)
 
GList * gncInvoiceGetTypeListForOwnerType (const GncOwnerType type)
 
GncInvoiceType gncInvoiceGetType (const GncInvoice *invoice)
 
const char * gncInvoiceGetTypeString (const GncInvoice *invoice)
 
gnc_commoditygncInvoiceGetCurrency (const GncInvoice *invoice)
 
GncOwnergncInvoiceGetBillTo (GncInvoice *invoice)
 
gnc_numeric gncInvoiceGetToChargeAmount (const GncInvoice *invoice)
 
gboolean gncInvoiceGetActive (const GncInvoice *invoice)
 
gboolean gncInvoiceGetIsCreditNote (const GncInvoice *invoice)
 
GNCLotgncInvoiceGetPostedLot (const GncInvoice *invoice)
 
TransactiongncInvoiceGetPostedTxn (const GncInvoice *invoice)
 
AccountgncInvoiceGetPostedAcc (const GncInvoice *invoice)
 

Detailed Description

An invoice holds a list of entries, a pointer to the customer, and the job, the dates entered and posted, as well as the account, transaction and lot for the posted invoice.

Macro Definition Documentation

#define gncInvoiceGetGUID (   x)    qof_instance_get_guid(QOF_INSTANCE(x))

deprecated functions

Definition at line 307 of file gncInvoice.h.

Function Documentation

void gncBillAddEntry ( GncInvoice bill,
GncEntry entry 
)

Call this function when adding an entry to a bill instead of an invoice

Definition at line 686 of file gncInvoice.c.

687 {
688  GncInvoice *old;
689 
690  g_assert(bill);
691  g_assert(entry);
692  if (!bill || !entry) return;
693 
694  old = gncEntryGetBill (entry);
695  if (old == bill) return; /* I already own this one */
696  if (old) gncBillRemoveEntry (old, entry);
697 
698  gncInvoiceBeginEdit (bill);
699  gncEntrySetBill (entry, bill);
700  bill->entries = g_list_insert_sorted (bill->entries, entry,
701  (GCompareFunc)gncEntryCompare);
702  mark_invoice (bill);
703  gncInvoiceCommitEdit (bill);
704 }
gboolean gncInvoiceAmountPositive ( const GncInvoice invoice)

Depending on the invoice type, invoices have a different effect on the balance. Customer invoices increase the balance, while vendor bills decrease the balance. Credit notes have the opposite effect.

Returns TRUE if the invoice will increase the balance or FALSE otherwise.

Definition at line 1215 of file gncInvoice.c.

1216 {
1217  switch (gncInvoiceGetType (invoice))
1218  {
1219  case GNC_INVOICE_CUST_INVOICE:
1220  case GNC_INVOICE_VEND_CREDIT_NOTE:
1221  case GNC_INVOICE_EMPL_CREDIT_NOTE:
1222  return TRUE;
1223  case GNC_INVOICE_CUST_CREDIT_NOTE:
1224  case GNC_INVOICE_VEND_INVOICE:
1225  case GNC_INVOICE_EMPL_INVOICE:
1226  return FALSE;
1227  case GNC_INVOICE_UNDEFINED:
1228  default:
1229  /* Should never be reached.
1230  * If it is, perhaps a new value is added to GncInvoiceType ? */
1231  g_assert_not_reached();
1232  return FALSE;
1233  }
1234 }
void gncInvoiceApplyPayment ( const GncInvoice invoice,
Transaction txn,
Account xfer_acc,
gnc_numeric  amount,
gnc_numeric  exch,
Timespec  date,
const char *  memo,
const char *  num 
)

A convenience function to apply a payment to an invoice. It creates a lot for a payment optionally based on an existing transaction and then tries to balance it with the given invoice. Contrary to gncOwnerApplyPayment, no other open documents or payments for the owner will be considered to balance the payment.

This code is actually a convenience wrapper around gncOwnerCreatePaymentLot and gncOwnerAutoApplyPaymentsWithLots. See their descriptions for more details on what happens exactly.

Definition at line 1830 of file gncInvoice.c.

1834 {
1835  GNCLot *payment_lot;
1836  GList *selected_lots = NULL;
1837  const GncOwner *owner;
1838 
1839  /* Verify our arguments */
1840  if (!invoice || !gncInvoiceIsPosted (invoice) || !xfer_acc) return;
1841 
1842  owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice));
1843  g_return_if_fail (owner->owner.undefined);
1844 
1845  /* Create a lot for this payment */
1846  payment_lot = gncOwnerCreatePaymentLot (owner, txn, invoice->posted_acc, xfer_acc,
1847  amount, exch, date, memo, num);
1848 
1849  /* Select the invoice as only payment candidate */
1850  selected_lots = g_list_prepend (selected_lots, invoice->posted_lot);
1851 
1852  /* And link the invoice lot and the payment lot together as well as possible. */
1853  if (payment_lot)
1854  selected_lots = g_list_prepend (selected_lots, payment_lot);
1855  gncOwnerAutoApplyPaymentsWithLots (owner, selected_lots);
1856 }
void gncOwnerAutoApplyPaymentsWithLots(const GncOwner *owner, GList *lots)
Definition: gncOwner.c:1199
const GncOwner * gncOwnerGetEndOwner(const GncOwner *owner)
Definition: gncOwner.c:550
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)
Definition: gncOwner.c:701
void gncInvoiceAutoApplyPayments ( GncInvoice invoice)

Attempt to pay the invoice using open payment lots and lots for documents of the opposite sign (credit notes versus invoices).

Definition at line 1786 of file gncInvoice.c.

1787 {
1788  GNCLot *inv_lot;
1789  Account *acct;
1790  const GncOwner *owner;
1791  GList *lot_list;
1792  struct lotmatch lm;
1793 
1794  /* General note: "paying" in this context means balancing
1795  * a lot, by linking opposite signed lots together. So below the term
1796  * "payment" can both mean a true payment or it can mean a document of
1797  * the opposite sign (invoice vs credit note). It just
1798  * depends on what type of document was given as parameter
1799  * to this function. */
1800 
1801  /* Payments can only be applied to posted invoices */
1802  g_return_if_fail (invoice);
1803  g_return_if_fail (invoice->posted_lot);
1804 
1805  inv_lot = invoice->posted_lot;
1806  acct = invoice->posted_acc;
1807  owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice));
1808 
1809  /* Find all lots whose balance (or part of their balance) could be
1810  * used to close this lot.
1811  * To be eligible, the lots have to have an opposite signed balance
1812  * and be for the same owner.
1813  * For example, for an invoice lot, payment lots and credit note lots
1814  * could be used. */
1815  lm.positive_balance = gnc_numeric_positive_p (gnc_lot_get_balance (inv_lot));
1816  lm.owner = owner;
1817  lot_list = xaccAccountFindOpenLots (acct, gnc_lot_match_owner_balancing,
1818  &lm, NULL);
1819 
1820  lot_list = g_list_prepend (lot_list, inv_lot);
1821  gncOwnerAutoApplyPaymentsWithLots (owner, lot_list);
1822  g_list_free (lot_list);
1823 }
void gncOwnerAutoApplyPaymentsWithLots(const GncOwner *owner, GList *lots)
Definition: gncOwner.c:1199
gboolean gnc_numeric_positive_p(gnc_numeric a)
const GncOwner * gncOwnerGetEndOwner(const GncOwner *owner)
Definition: gncOwner.c:550
LotList * xaccAccountFindOpenLots(const Account *acc, gboolean(*match_func)(GNCLot *lot, gpointer user_data), gpointer user_data, GCompareFunc sort_func)
Definition: Account.c:3751
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
Definition: gnc-lot.c:477
GncInvoice* gncInvoiceCopy ( const GncInvoice other_invoice)

Create a new GncInvoice object as a deep copy of the given other invoice.

The returned new invoice has everything copied from the other invoice, including the ID string field. All GncEntries are newly allocated copies of the original invoice's entries.

Definition at line 336 of file gncInvoice.c.

337 {
338  GncInvoice *invoice;
339  QofBook* book;
340  GList *node;
341  gint64 is_cn;
342 
343  g_assert(from);
344  book = qof_instance_get_book(from);
345  g_assert(book);
346 
347  invoice = g_object_new (GNC_TYPE_INVOICE, NULL);
348  qof_instance_init_data (&invoice->inst, _GNC_MOD_NAME, book);
349 
350  gncInvoiceBeginEdit(invoice);
351 
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;
356 
357  is_cn = kvp_frame_get_gint64(from->inst.kvp_data, GNC_INVOICE_IS_CN);
358  kvp_frame_set_gint64(invoice->inst.kvp_data, GNC_INVOICE_IS_CN, is_cn);
359 
360  invoice->terms = from->terms;
361  gncBillTermIncRef (invoice->terms);
362 
363  gncOwnerCopy(&from->billto, &invoice->billto);
364  gncOwnerCopy(&from->owner, &invoice->owner);
365  invoice->job = from->job; // FIXME: Need IncRef or similar here?!?
366 
367  invoice->to_charge_amount = from->to_charge_amount;
368  invoice->date_opened = from->date_opened;
369 
370  // Oops. Do not forget to copy the pointer to the correct currency here.
371  invoice->currency = from->currency;
372 
373  // Copy all invoice->entries
374  for (node = from->entries; node; node = node->next)
375  {
376  GncEntry *from_entry = node->data;
377  GncEntry *to_entry = gncEntryCreate(book);
378  gncEntryCopy(from_entry, to_entry, FALSE);
379 
380  switch (gncInvoiceGetOwnerType (invoice))
381  {
382  case GNC_OWNER_VENDOR:
383  case GNC_OWNER_EMPLOYEE:
384  // this is a vendor bill, or an expense voucher
385  gncBillAddEntry(invoice, to_entry);
386  break;
387  case GNC_OWNER_CUSTOMER:
388  default:
389  // this is an invoice
390  gncInvoiceAddEntry(invoice, to_entry);
391  break;
392  }
393  }
394 
395  // FIXME: The prices are not (yet) copied; is this a problem?
396 
397  // Posted-date and the posted Txn is intentionally not copied; the
398  // copy isn't "posted" but needs to be posted by the user.
399  mark_invoice (invoice);
400  gncInvoiceCommitEdit(invoice);
401 
402  return invoice;
403 }
QofBook * qof_instance_get_book(gconstpointer)
void kvp_frame_set_gint64(KvpFrame *frame, const gchar *path, gint64 ival)
void qof_instance_init_data(QofInstance *, QofIdType, QofBook *)
void gncBillAddEntry(GncInvoice *bill, GncEntry *entry)
Definition: gncInvoice.c:686
gboolean gncInvoiceEqual ( const GncInvoice a,
const GncInvoice b 
)

Test support function used by test-dbi-business-stuff.c

Definition at line 1926 of file gncInvoice.c.

1927 {
1928  if (a == NULL && b == NULL) return TRUE;
1929  if (a == NULL || b == NULL) return FALSE;
1930 
1931  g_return_val_if_fail(GNC_IS_INVOICE(a), FALSE);
1932  g_return_val_if_fail(GNC_IS_INVOICE(b), FALSE);
1933 
1934  if (g_strcmp0(a->id, b->id) != 0)
1935  {
1936  PWARN("IDs differ: %s vs %s", a->id, b->id);
1937  return FALSE;
1938  }
1939 
1940  if (g_strcmp0(a->notes, b->notes) != 0)
1941  {
1942  PWARN("Notes differ: %s vs %s", a->notes, b->notes);
1943  return FALSE;
1944  }
1945 
1946  if (g_strcmp0(a->billing_id, b->billing_id) != 0)
1947  {
1948  PWARN("Billing IDs differ: %s vs %s", a->billing_id, b->billing_id);
1949  return FALSE;
1950  }
1951 
1952  if (g_strcmp0(a->printname, b->printname) != 0)
1953  {
1954  PWARN("Printnames differ: %s vs %s", a->printname, b->printname);
1955  return FALSE;
1956  }
1957 
1958  if (a->active != b->active)
1959  {
1960  PWARN("Active flags differ");
1961  return FALSE;
1962  }
1963 
1964  if (!gncBillTermEqual(a->terms, b->terms))
1965  {
1966  PWARN("Billterms differ");
1967  return FALSE;
1968  }
1969 
1970  if (!gncJobEqual(a->job, b->job))
1971  {
1972  PWARN("Jobs differ");
1973  return FALSE;
1974  }
1975 
1976  if (!gnc_commodity_equal(a->currency, b->currency))
1977  {
1978  PWARN("Currencies differ");
1979  return FALSE;
1980  }
1981 
1982  if (!xaccAccountEqual(a->posted_acc, b->posted_acc, TRUE))
1983  {
1984  PWARN("Posted accounts differ");
1985  return FALSE;
1986  }
1987 
1988  if (!xaccTransEqual(a->posted_txn, b->posted_txn, TRUE, TRUE, TRUE, FALSE))
1989  {
1990  PWARN("Posted tx differ");
1991  return FALSE;
1992  }
1993 
1994 #if 0
1995  if (!gncLotEqual(a->posted_lot, b->posted_lot))
1996  {
1997  PWARN("Posted lots differ");
1998  return FALSE;
1999  }
2000 #endif
2001 
2002  /* FIXME: Need real checks */
2003 #if 0
2004  GList *entries;
2005  GList *prices;
2006  GncOwner owner;
2007  GncOwner billto;
2008  Timespec date_opened;
2009  Timespec date_posted;
2010 
2011  gnc_numeric to_charge_amount;
2012 #endif
2013 
2014  return TRUE;
2015 }
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
Use a 64-bit unsigned int timespec.
Definition: gnc-date.h:299
gboolean gncBillTermEqual(const GncBillTerm *a, const GncBillTerm *b)
Definition: gncBillTerm.c:647
#define PWARN(format, args...)
Definition: qoflog.h:243
gboolean xaccTransEqual(const Transaction *ta, const Transaction *tb, gboolean check_guids, gboolean check_splits, gboolean check_balances, gboolean assume_ordered)
Definition: Transaction.c:857
gboolean xaccAccountEqual(const Account *aa, const Account *ab, gboolean check_guids)
Definition: Account.c:1475
GHashTable* gncInvoiceGetForeignCurrencies ( const GncInvoice invoice)

Return an overview of amounts on this invoice that will be posted to accounts in currencies that are different from the invoice currency. These accounts can be the accounts referred to in invoice entries or tax tables. This information is returned in the from of a hash table. The keys in the hash table are the foreign currencies, the values are the accumulated amounts in that currency. Drop the reference to the hash table with g_hash_table_unref when no longer needed.

Definition at line 1236 of file gncInvoice.c.

1237 {
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,
1242  NULL, g_free);
1243 
1244  for (entries_iter = invoice->entries; entries_iter != NULL; entries_iter = g_list_next(entries_iter))
1245  {
1246  GncEntry *entry = (GncEntry*)entries_iter->data;
1247  Account *this_acc;
1248  gnc_commodity *account_currency;
1249  AccountValueList *tt_amts = NULL, *tt_iter;
1250 
1251  /* Check entry's account currency */
1252  this_acc = (is_cust_doc ? gncEntryGetInvAccount (entry) :
1253  gncEntryGetBillAccount (entry));
1254  account_currency = xaccAccountGetCommodity (this_acc);
1255 
1256  if (this_acc &&
1257  !gnc_commodity_equal (gncInvoiceGetCurrency (invoice), account_currency))
1258  {
1259  gnc_numeric *curr_amt = (gnc_numeric*) g_hash_table_lookup (amt_hash, account_currency);
1260  gnc_numeric *entry_amt = (gnc_numeric*) g_new0 (gnc_numeric, 1);
1261  *entry_amt = gncEntryGetDocValue (entry, FALSE, is_cust_doc, is_cn);
1262  if (curr_amt)
1263  *entry_amt = gnc_numeric_add (*entry_amt, *curr_amt, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND_HALF_UP);
1264  g_hash_table_insert (amt_hash, account_currency, entry_amt);
1265  }
1266 
1267  /* Check currencies of each account in the tax table linked
1268  * to the current entry */
1269  tt_amts = gncEntryGetDocTaxValues (entry, is_cust_doc, is_cn);
1270 
1271  if (!tt_amts)
1272  continue;
1273 
1274  for (tt_iter = tt_amts; tt_iter != NULL; tt_iter = g_list_next(tt_iter))
1275  {
1276  GncAccountValue *tt_amt_val = (GncAccountValue*)tt_iter->data;
1277  Account *tt_acc = tt_amt_val->account;
1278  gnc_commodity *tt_acc_currency = xaccAccountGetCommodity (tt_acc);
1279 
1280  if (tt_acc &&
1281  !gnc_commodity_equal (gncInvoiceGetCurrency (invoice), tt_acc_currency))
1282  {
1283  gnc_numeric *curr_amt = (gnc_numeric*) g_hash_table_lookup (amt_hash, tt_acc_currency);
1284  gnc_numeric *tt_acc_amt = (gnc_numeric*) g_new0 (gnc_numeric, 1);
1285  *tt_acc_amt = tt_amt_val->value;
1286  if (curr_amt)
1287  *tt_acc_amt = gnc_numeric_add (*tt_acc_amt, *curr_amt, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND_HALF_UP);
1288  g_hash_table_insert (amt_hash, tt_acc_currency, tt_acc_amt);
1289  }
1290  }
1291  gncAccountValueDestroy (tt_amts);
1292  }
1293  return amt_hash;
1294 }
AccountValueList * gncEntryGetDocTaxValues(GncEntry *entry, gboolean is_cust_doc, gboolean is_cn)
Definition: gncEntry.c:1445
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
void gncAccountValueDestroy(GList *list)
Definition: gncTaxTable.c:978
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Definition: Account.c:3148
#define GNC_DENOM_AUTO
Definition: gnc-numeric.h:246
GncInvoice* gncInvoiceGetInvoiceFromLot ( GNCLot lot)

Given a LOT, find and return the Invoice attached to the lot

Definition at line 1174 of file gncInvoice.c.

1175 {
1176  GncGUID *guid = NULL;
1177  QofBook *book;
1178 
1179  if (!lot) return NULL;
1180 
1181  book = gnc_lot_get_book (lot);
1182  qof_instance_get (QOF_INSTANCE (lot), "invoice", &guid, NULL);
1183  return gncInvoiceLookup(book, guid);
1184 }
void qof_instance_get(const QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_get.
Definition: guid.h:65
GncInvoice* gncInvoiceGetInvoiceFromTxn ( const Transaction txn)

Given a transaction, find and return the Invoice

Definition at line 1203 of file gncInvoice.c.

1204 {
1205  GncGUID *guid = NULL;
1206  QofBook *book;
1207 
1208  if (!txn) return NULL;
1209 
1210  book = xaccTransGetBook (txn);
1211  qof_instance_get (QOF_INSTANCE (txn), "invoice", &guid, NULL);
1212  return gncInvoiceLookup(book, guid);
1213 }
void qof_instance_get(const QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_get.
Definition: guid.h:65
#define xaccTransGetBook(X)
Definition: Transaction.h:753
gnc_numeric gncInvoiceGetTotal ( GncInvoice invoice)

Return the "total" amount of the invoice as seen on the document (and shown to the user in the reports and invoice ledger).

Definition at line 908 of file gncInvoice.c.

909 {
910  if (!invoice) return gnc_numeric_zero();
911  return gncInvoiceGetTotalInternal(invoice, TRUE, TRUE, FALSE, 0);
912 }
Transaction* gncInvoicePostToAccount ( GncInvoice invoice,
Account acc,
Timespec posted_date,
Timespec due_date,
const char *  memo,
gboolean  accumulatesplits,
gboolean  autopay 
)

Post this invoice to an account. Returns the new Transaction that is tied to this invoice. The transaction is set with the supplied posted date, due date, and memo. The Transaction description is set to the name of the company.

If accumulate splits is TRUE, entries in the same account will be merged into one single split in that account. Otherwise each entry will be posted as a separate split, possibly resulting in multiple splits in one account.

If autopay is TRUE, the code will try to find pre-payments, invoices or credit notes that can reduce the amount due for this invoice, marking the invoice as fully or partially paid, depending on the amounts on all documents involved. If autopay is FALSE, it's the user's responsibility to explicitly pay the invoice.

Definition at line 1363 of file gncInvoice.c.

1367 {
1368  Transaction *txn;
1369  QofBook *book;
1370  GNCLot *lot = NULL;
1371  GList *iter;
1372  GList *splitinfo = NULL;
1373  gnc_numeric total;
1374  gboolean is_cust_doc;
1375  gboolean is_cn;
1376  const char *name, *type;
1377  char *lot_title;
1378  Account *ccard_acct = NULL;
1379  const GncOwner *owner;
1380 
1381  if (!invoice || !acc) return NULL;
1382 
1383  gncInvoiceBeginEdit (invoice);
1384  book = qof_instance_get_book(invoice);
1385 
1386  /* Stabilize the Billing Terms of this invoice */
1387  if (invoice->terms)
1388  gncInvoiceSetTerms (invoice,
1389  gncBillTermReturnChild (invoice->terms, TRUE));
1390 
1391  /* GncEntry functions need to know if the invoice/credit note is for a customer or a vendor/employee. */
1392  is_cust_doc = (gncInvoiceGetOwnerType (invoice) == GNC_OWNER_CUSTOMER);
1393  is_cn = gncInvoiceGetIsCreditNote (invoice);
1394 
1395  /* Figure out if we need to separate out "credit-card" items */
1396  owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice));
1397  if (gncInvoiceGetOwnerType (invoice) == GNC_OWNER_EMPLOYEE)
1398  ccard_acct = gncEmployeeGetCCard (gncOwnerGetEmployee (owner));
1399 
1400  /* Create a new lot for this invoice */
1401  lot = gnc_lot_new (book);
1402  gnc_lot_begin_edit (lot);
1403 
1404  type = gncInvoiceGetTypeString (invoice);
1405 
1406  /* Set the lot title */
1407  lot_title = g_strdup_printf ("%s %s", type, gncInvoiceGetID (invoice));
1408  gnc_lot_set_title (lot, lot_title);
1409  g_free (lot_title);
1410 
1411  /* Create a new transaction */
1412  txn = xaccMallocTransaction (book);
1413  xaccTransBeginEdit (txn);
1414 
1415  name = gncOwnerGetName (gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice)));
1416 
1417  /* Set Transaction Description (Owner Name) , Num (invoice ID or type, based
1418  * on book option), Currency */
1419  xaccTransSetDescription (txn, name ? name : "");
1420  gnc_set_num_action (txn, NULL, gncInvoiceGetID (invoice), type);
1421  xaccTransSetCurrency (txn, invoice->currency);
1422 
1423  /* Entered and Posted at date */
1424  xaccTransSetDateEnteredSecs (txn, gnc_time (NULL));
1425  if (post_date)
1426  {
1427  xaccTransSetDatePostedTS (txn, post_date);
1428  gncInvoiceSetDatePosted (invoice, *post_date);
1429  }
1430 
1431  if (due_date)
1432  xaccTransSetDateDueTS (txn, due_date);
1433 
1434  /* Iterate through the entries; sum up everything for each account.
1435  * then create the appropriate splits in this txn.
1436  */
1437  total = gnc_numeric_zero();
1438  for (iter = gncInvoiceGetEntries(invoice); iter; iter = iter->next)
1439  {
1440  gnc_numeric value, tax;
1441  GList *taxes;
1442  GncEntry * entry = iter->data;
1443  Account *this_acc;
1444 
1445  /* Stabilize the TaxTable in this entry */
1446  gncEntryBeginEdit (entry);
1447  if (is_cust_doc)
1448  gncEntrySetInvTaxTable
1449  (entry, gncTaxTableReturnChild (gncEntryGetInvTaxTable (entry), TRUE));
1450  else
1451  {
1452  gncEntrySetBillTaxTable
1453  (entry, gncTaxTableReturnChild (gncEntryGetBillTaxTable (entry), TRUE));
1454 
1455  /* If this is a bill, and the entry came from an invoice originally, copy the price */
1456  if (gncEntryGetBillable (entry))
1457  gncEntrySetInvPrice (entry, gncEntryGetBillPrice (entry));
1458  }
1459  gncEntryCommitEdit (entry);
1460 
1461  /* Obtain the Entry's Value and TaxValues */
1462  value = gncEntryGetBalValue (entry, FALSE, is_cust_doc);
1463  tax = gncEntryGetBalTaxValue (entry, FALSE, is_cust_doc);
1464  taxes = gncEntryGetBalTaxValues (entry, is_cust_doc);
1465 
1466  /* add the value for the account split */
1467  this_acc = (is_cust_doc ? gncEntryGetInvAccount (entry) :
1468  gncEntryGetBillAccount (entry));
1469  if (this_acc)
1470  {
1471  if (gnc_numeric_check (value) == GNC_ERROR_OK)
1472  {
1473  if (accumulatesplits)
1474  splitinfo = gncAccountValueAdd (splitinfo, this_acc, value);
1475  else if (!gncInvoicePostAddSplit (book, this_acc, txn, value,
1476  gncEntryGetDescription (entry),
1477  type, invoice))
1478  {
1479  /*This is an error, which shouldn't even be able to happen.
1480  We can't really do anything sensible about it, and this is
1481  a user-interface free zone so we can't try asking the user
1482  again either, have to return NULL*/
1483  return NULL;
1484  }
1485 
1486  /* If there is a credit-card account, and this is a CCard
1487  * payment type, the don't add it to the total, and instead
1488  * create a split to the CC Acct with a memo of the entry
1489  * description instead of the provided memo. Note that the
1490  * value reversal is the same as the post account.
1491  *
1492  * Note: we don't have to worry about the tax values --
1493  * expense vouchers don't have them.
1494  */
1495  if (ccard_acct && gncEntryGetBillPayment (entry) == GNC_PAYMENT_CARD)
1496  {
1497  Split *split;
1498 
1499  split = xaccMallocSplit (book);
1500  xaccSplitSetMemo (split, gncEntryGetDescription (entry));
1501  /* set action based on book option */
1502  gnc_set_num_action (NULL, split, gncInvoiceGetID (invoice), type);
1503  xaccAccountBeginEdit (ccard_acct);
1504  xaccAccountInsertSplit (ccard_acct, split);
1505  xaccAccountCommitEdit (ccard_acct);
1506  xaccTransAppendSplit (txn, split);
1507  xaccSplitSetBaseValue (split, gnc_numeric_neg (value),
1508  invoice->currency);
1509 
1510  }
1511  else
1512  total = gnc_numeric_add (total, value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
1513 
1514  }
1515  else
1516  g_warning ("bad value in our entry");
1517  }
1518 
1519  /* now merge in the TaxValues */
1520  splitinfo = gncAccountValueAddList (splitinfo, taxes);
1521 
1522  /* ... and add the tax total */
1523  if (gnc_numeric_check (tax) == GNC_ERROR_OK)
1524  total = gnc_numeric_add (total, tax, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
1525  else
1526  g_warning ("bad tax in our entry");
1527 
1528  gncAccountValueDestroy (taxes);
1529  } /* for */
1530 
1531  /* Iterate through the splitinfo list and generate the splits */
1532  for (iter = splitinfo; iter; iter = iter->next)
1533  {
1534  GncAccountValue *acc_val = iter->data;
1535  if (!gncInvoicePostAddSplit (book, acc_val->account, txn, acc_val->value,
1536  memo, type, invoice))
1537  {
1538  /*This is an error, which shouldn't even be able to happen.
1539  We can't really do anything sensible about it, and this is
1540  a user-interface free zone so we can't try asking the user
1541  again either, have to return NULL*/
1542  return NULL;
1543  }
1544  }
1545 
1546  /* If there is a ccard account, we may have an additional "to_card" payment.
1547  * we should make that now.
1548  */
1549  if (ccard_acct && !gnc_numeric_zero_p (invoice->to_charge_amount))
1550  {
1551  Split *split = xaccMallocSplit (book);
1552 
1553  /* To charge amount is stored in document value. We need balance value here
1554  * so convert if necessary. */
1555  gnc_numeric to_charge_bal_amount = (is_cn ? gnc_numeric_neg (invoice->to_charge_amount)
1556  : invoice->to_charge_amount);
1557 
1558  /* Set memo. */
1559  xaccSplitSetMemo (split, _("Extra to Charge Card"));
1560  /* Set action based on book option */
1561  gnc_set_num_action (NULL, split, gncInvoiceGetID (invoice), type);
1562 
1563  xaccAccountBeginEdit (ccard_acct);
1564  xaccAccountInsertSplit (ccard_acct, split);
1565  xaccAccountCommitEdit (ccard_acct);
1566  xaccTransAppendSplit (txn, split);
1567  xaccSplitSetBaseValue (split, gnc_numeric_neg (to_charge_bal_amount),
1568  invoice->currency);
1569 
1570  total = gnc_numeric_sub (total, to_charge_bal_amount,
1572  }
1573 
1574  /* Now create the Posted split (which is the opposite sign of the above splits) */
1575  {
1576  Split *split = xaccMallocSplit (book);
1577 
1578  /* Set memo */
1579  xaccSplitSetMemo (split, memo);
1580  /* Set action based on book option */
1581  gnc_set_num_action (NULL, split, gncInvoiceGetID (invoice), type);
1582 
1583  xaccAccountBeginEdit (acc);
1584  xaccAccountInsertSplit (acc, split);
1585  xaccAccountCommitEdit (acc);
1586  xaccTransAppendSplit (txn, split);
1587  xaccSplitSetBaseValue (split, gnc_numeric_neg (total),
1588  invoice->currency);
1589 
1590  /* add this split to the lot */
1591  gnc_lot_add_split (lot, split);
1592  }
1593 
1594  /* Now attach this invoice to the txn, lot, and account */
1595  gncInvoiceAttachToLot (invoice, lot);
1596  gncInvoiceAttachToTxn (invoice, txn);
1597  gncInvoiceSetPostedAcc (invoice, acc);
1598 
1599  xaccTransSetReadOnly (txn, _("Generated from an invoice. Try unposting the invoice."));
1600  xaccTransCommitEdit (txn);
1601 
1602  gncAccountValueDestroy (splitinfo);
1603 
1604  gnc_lot_commit_edit (lot);
1605  /* Not strictly necessary, since it was done by the Set calls
1606  * above, but good insurance. */
1607  DEBUG("Committing Invoice %s", invoice->id);
1608  mark_invoice (invoice);
1609  gncInvoiceCommitEdit (invoice);
1610 
1611  /* If requested, attempt to automatically apply open payments
1612  * and reverse documents to this lot to close it (or at least
1613  * reduce its balance) */
1614  if (autopay)
1615  gncInvoiceAutoApplyPayments (invoice);
1616 
1617  return txn;
1618 }
#define xaccTransAppendSplit(t, s)
Definition: Transaction.h:357
Transaction * xaccMallocTransaction(QofBook *book)
Definition: Transaction.c:513
void xaccSplitSetBaseValue(Split *s, gnc_numeric value, const gnc_commodity *base_currency)
Definition: Split.c:1341
QofBook * qof_instance_get_book(gconstpointer)
gnc_numeric gnc_numeric_neg(gnc_numeric a)
#define DEBUG(format, args...)
Definition: qoflog.h:255
void gnc_lot_add_split(GNCLot *lot, Split *split)
Definition: gnc-lot.c:569
void xaccTransSetDescription(Transaction *trans, const char *desc)
Definition: Transaction.c:2085
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
gboolean gnc_numeric_zero_p(gnc_numeric a)
void gncInvoiceAutoApplyPayments(GncInvoice *invoice)
Definition: gncInvoice.c:1786
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Definition: Transaction.c:1354
AccountValueList * gncEntryGetBalTaxValues(GncEntry *entry, gboolean is_cust_doc)
Definition: gncEntry.c:1481
void xaccTransSetReadOnly(Transaction *trans, const char *reason)
Definition: Transaction.c:2039
void xaccSplitSetMemo(Split *split, const char *memo)
Definition: Split.c:1774
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1579
void gncAccountValueDestroy(GList *list)
Definition: gncTaxTable.c:978
void xaccTransBeginEdit(Transaction *trans)
Definition: Transaction.c:1380
Split * xaccMallocSplit(QofBook *book)
Definition: Split.c:582
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
const GncOwner * gncOwnerGetEndOwner(const GncOwner *owner)
Definition: gncOwner.c:550
Definition: SplitP.h:71
void xaccAccountBeginEdit(Account *acc)
Definition: Account.c:1280
#define xaccAccountInsertSplit(acc, s)
Definition: Account.h:972
void xaccTransSetDateDueTS(Transaction *trans, const Timespec *ts)
Definition: Transaction.c:2006
GList * gncAccountValueAddList(GList *l1, GList *l2)
Definition: gncTaxTable.c:951
time64 gnc_time(time64 *tbuf)
get the current local time
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
GList * gncAccountValueAdd(GList *list, Account *acc, gnc_numeric value)
Definition: gncTaxTable.c:923
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
Definition: Transaction.c:1951
GncEmployee * gncOwnerGetEmployee(const GncOwner *owner)
Definition: gncOwner.c:368
#define GNC_DENOM_AUTO
Definition: gnc-numeric.h:246
void xaccAccountCommitEdit(Account *acc)
Definition: Account.c:1321
void xaccTransSetDatePostedTS(Transaction *trans, const Timespec *ts)
Definition: Transaction.c:1970
void gncInvoiceRemoveEntries ( GncInvoice invoice)

Remove all entries from an invoice. To be called before destroying an invoice.

Definition at line 727 of file gncInvoice.c.

728 {
729  GList *node;
730 
731  if (!invoice) return;
732 
733  for (node = invoice->entries; node; node = node->next)
734  {
735  GncEntry *entry = node->data;
736 
737  switch (gncInvoiceGetOwnerType (invoice))
738  {
739  case GNC_OWNER_VENDOR:
740  case GNC_OWNER_EMPLOYEE:
741  // this is a vendor bill, or an expense voucher
742  gncBillRemoveEntry (invoice, entry);
743  break;
744  case GNC_OWNER_CUSTOMER:
745  default:
746  // this is an invoice
747  gncInvoiceRemoveEntry (invoice, entry);
748  break;
749  }
750 
751  /* If the entry is no longer referenced by any document,
752  * remove it.
753  */
754  if (!(gncEntryGetInvoice (entry) ||
755  gncEntryGetBill (entry) ||
756  gncEntryGetOrder (entry)))
757  {
758  gncEntryBeginEdit (entry);
759  gncEntryDestroy (entry);
760  }
761  }
762 }
void gncInvoiceSetDateOpenedGDate ( GncInvoice invoice,
const GDate *  date 
)

Set the DateOpened using a GDate argument. (Note: Internally this stores the date in a Timespec as created through timespecCanonicalDayTime()).

Definition at line 480 of file gncInvoice.c.

481 {
482  g_assert (date);
483  gncInvoiceSetDateOpened(invoice, timespecCanonicalDayTime(gdate_to_timespec(*date)));
484 }
Timespec timespecCanonicalDayTime(Timespec t)
Timespec gdate_to_timespec(GDate d)
void gncInvoiceSortEntries ( GncInvoice invoice)

Call this function when an Entry is changed and you want to re-sort the list of entries

Definition at line 717 of file gncInvoice.c.

718 {
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);
725 }
gboolean gncInvoiceUnpost ( GncInvoice invoice,
gboolean  reset_tax_tables 
)

Unpost this invoice. This will destroy the posted transaction and return the invoice to its unposted state. It may leave empty lots out there. If reset_tax_tables is TRUE, then it will also revert all the Tax Tables to the parent, which will potentially change the total value of the invoice. It may also leave some orphaned Tax Table children.

Returns TRUE if successful, FALSE if there is a problem.

Definition at line 1621 of file gncInvoice.c.

1622 {
1623  Transaction *txn;
1624  GNCLot *lot;
1625  GList *lot_split_list, *lot_split_iter;
1626 
1627  if (!invoice) return FALSE;
1628  if (!gncInvoiceIsPosted (invoice)) return FALSE;
1629 
1630  txn = gncInvoiceGetPostedTxn (invoice);
1631  g_return_val_if_fail (txn, FALSE);
1632 
1633  lot = gncInvoiceGetPostedLot (invoice);
1634  g_return_val_if_fail (lot, FALSE);
1635 
1636  /* Destroy the Posted Transaction */
1637  xaccTransClearReadOnly (txn);
1638  xaccTransBeginEdit (txn);
1639  xaccTransDestroy (txn);
1640  xaccTransCommitEdit (txn);
1641 
1642  /* Disconnect the lot from the invoice; re-attach to the invoice owner */
1643  gncInvoiceDetachFromLot (lot);
1644  gncOwnerAttachToLot (&invoice->owner, lot);
1645 
1646  /* Check if this invoice was linked to other lots (payments/inverse signed
1647  * invoices).
1648  * If this is the case, recreate the link transaction between all the remaining lots.
1649  *
1650  * Note that before GnuCash 2.6 payments were not stored in separate lots, but
1651  * always ended up in invoice lots when matched to an invoice. Over-payments
1652  * were copied to a new lot, to which later an invoice was added again and so on.
1653  * These over-payments were handled with automatic payment forward transactions.
1654  * You could consider these transactions to be links between lots as well, but
1655  * to avoid some unexpected behavior, these will not be altered here.
1656  */
1657 
1658  // Note: make a copy of the lot list here, when splits are deleted from the lot,
1659  // the original list may be destroyed by the lot code.
1660  lot_split_list = g_list_copy (gnc_lot_get_split_list (lot));
1661  for (lot_split_iter = lot_split_list; lot_split_iter; lot_split_iter = lot_split_iter->next)
1662  {
1663  Split *split = lot_split_iter->data;
1664  GList *other_split_list, *list_iter;
1665  Transaction *other_txn = xaccSplitGetParent (split);
1666  GList *lot_list = NULL;
1667 
1668  /* Only work with transactions that link invoices and payments.
1669  * Note: this check also catches the possible case of NULL splits. */
1670  if (xaccTransGetTxnType (other_txn) != TXN_TYPE_LINK)
1671  continue;
1672 
1673  /* Save a list of lots this linking transaction linked to */
1674  other_split_list = xaccTransGetSplitList (other_txn);
1675  for (list_iter = other_split_list; list_iter; list_iter = list_iter->next)
1676  {
1677  Split *other_split = list_iter->data;
1678  GNCLot *other_lot = xaccSplitGetLot (other_split);
1679 
1680  /* Omit the lot we are about to delete */
1681  if (other_lot == lot)
1682  continue;
1683 
1684  lot_list = g_list_prepend (lot_list, other_lot);
1685  }
1686  /* Maintain original split order */
1687  lot_list = g_list_reverse (lot_list);
1688 
1689  /* Now remove this link transaction. */
1690  xaccTransClearReadOnly (other_txn);
1691  xaccTransBeginEdit (other_txn);
1692  xaccTransDestroy (other_txn);
1693  xaccTransCommitEdit (other_txn);
1694 
1695  /* Re-balance the saved lots as well as is possible */
1696  gncOwnerAutoApplyPaymentsWithLots (&invoice->owner, lot_list);
1697 
1698  /* If any of the saved lots has no more splits, then destroy it.
1699  * Otherwise if any has an invoice associated with it,
1700  * send it a modified event to reset its paid status */
1701  for (list_iter = lot_list; list_iter; list_iter = list_iter->next)
1702  {
1703  GNCLot *other_lot = list_iter->data;
1704  GncInvoice *other_invoice = gncInvoiceGetInvoiceFromLot (other_lot);
1705 
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);
1710  }
1711  }
1712  g_list_free (lot_split_list);
1713 
1714  /* If the lot has no splits, then destroy it */
1715  if (!gnc_lot_count_splits (lot))
1716  gnc_lot_destroy (lot);
1717 
1718  /* Clear out the invoice posted information */
1719  gncInvoiceBeginEdit (invoice);
1720 
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;
1725 
1726  /* if we've been asked to reset the tax tables, then do so */
1727  if (reset_tax_tables)
1728  {
1729  gboolean is_cust_doc = (gncInvoiceGetOwnerType(invoice) == GNC_OWNER_CUSTOMER);
1730  GList *iter;
1731 
1732  for (iter = gncInvoiceGetEntries(invoice); iter; iter = iter->next)
1733  {
1734  GncEntry *entry = iter->data;
1735 
1736  gncEntryBeginEdit(entry);
1737  if (is_cust_doc)
1738  gncEntrySetInvTaxTable(entry,
1739  gncTaxTableGetParent(gncEntryGetInvTaxTable(entry)));
1740  else
1741  gncEntrySetBillTaxTable(entry,
1742  gncTaxTableGetParent(gncEntryGetBillTaxTable(entry)));
1743  gncEntryCommitEdit(entry);
1744  }
1745  }
1746 
1747  mark_invoice (invoice);
1748  gncInvoiceCommitEdit (invoice);
1749 
1750  return TRUE;
1751 }
char xaccTransGetTxnType(const Transaction *trans)
Definition: Transaction.c:2302
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
void gncOwnerAutoApplyPaymentsWithLots(const GncOwner *owner, GList *lots)
Definition: gncOwner.c:1199
void xaccTransDestroy(Transaction *trans)
Definition: Transaction.c:1402
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
Definition: gnc-lot.c:417
void gncOwnerAttachToLot(const GncOwner *owner, GNCLot *lot)
Definition: gncOwner.c:600
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1579
#define TXN_TYPE_LINK
Definition: Transaction.h:122
void xaccTransBeginEdit(Transaction *trans)
Definition: Transaction.c:1380
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Definition: gncInvoice.c:1174
Definition: SplitP.h:71
void qof_event_gen(QofInstance *entity, QofEventId event_type, gpointer event_data)
Invoke all registered event handlers using the given arguments.
SplitList * xaccTransGetSplitList(const Transaction *trans)
Definition: Transaction.c:2164
GNCLot * xaccSplitGetLot(const Split *split)
Definition: Split.c:1953