|
GnuCash 2.3.0
|
Files | |
| file | gncInvoice.h |
Business Invoice Interface. | |
Defines | |
| #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())) |
| #define | gncInvoiceLookupDirect(G, B) gncInvoiceLookup((B),&(G)) |
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) |
| 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) |
| GNCPrice * | gncInvoiceGetPrice (GncInvoice *invoice, gnc_commodity *commodity) |
| gboolean | gncInvoiceAmountPositive (const GncInvoice *invoice) |
| Transaction * | gncInvoicePostToAccount (GncInvoice *invoice, Account *acc, Timespec *posted_date, Timespec *due_date, const char *memo, gboolean accumulatesplits) |
| gboolean | gncInvoiceUnpost (GncInvoice *invoice, gboolean reset_tax_tables) |
| GncInvoice * | gncInvoiceGetInvoiceFromTxn (const Transaction *txn) |
| GncInvoice * | gncInvoiceGetInvoiceFromLot (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) |
| QofBook * | gncInvoiceGetBook (GncInvoice *x) |
| gboolean | gncInvoiceEqual (const GncInvoice *a, const GncInvoice *b) |
Create/Destroy Functions | |
| GncInvoice * | gncInvoiceCreate (QofBook *book) |
| void | gncInvoiceDestroy (GncInvoice *invoice) |
| GncInvoice * | gncInvoiceCopy (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 GncOwner * | gncInvoiceGetOwner (const GncInvoice *invoice) |
| Timespec | gncInvoiceGetDateOpened (const GncInvoice *invoice) |
| Timespec | gncInvoiceGetDatePosted (const GncInvoice *invoice) |
| Timespec | gncInvoiceGetDateDue (const GncInvoice *invoice) |
| GncBillTerm * | gncInvoiceGetTerms (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_commodity * | gncInvoiceGetCurrency (const GncInvoice *invoice) |
| GncOwner * | gncInvoiceGetBillTo (GncInvoice *invoice) |
| gnc_numeric | gncInvoiceGetToChargeAmount (const GncInvoice *invoice) |
| gboolean | gncInvoiceGetActive (const GncInvoice *invoice) |
| gboolean | gncInvoiceGetIsCreditNote (const GncInvoice *invoice) |
| GNCLot * | gncInvoiceGetPostedLot (const GncInvoice *invoice) |
| Transaction * | gncInvoiceGetPostedTxn (const GncInvoice *invoice) |
| Account * | gncInvoiceGetPostedAcc (const GncInvoice *invoice) |
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.
| #define gncInvoiceGetGUID | ( | x | ) | qof_instance_get_guid(QOF_INSTANCE(x)) |
deprecated functions
Definition at line 248 of file gncInvoice.h.
| void gncBillAddEntry | ( | GncInvoice * | bill, |
| GncEntry * | entry | ||
| ) |
Call this function when adding an entry to a bill instead of an invoice
Definition at line 639 of file gncInvoice.c.
{
GncInvoice *old;
g_assert(bill);
g_assert(entry);
if (!bill || !entry) return;
old = gncEntryGetBill (entry);
if (old == bill) return; /* I already own this one */
if (old) gncBillRemoveEntry (old, entry);
gncEntrySetBill (entry, bill);
bill->entries = g_list_insert_sorted (bill->entries, entry,
(GCompareFunc)gncEntryCompare);
mark_invoice (bill);
}
| 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 1153 of file gncInvoice.c.
{
switch (gncInvoiceGetType (invoice))
{
case GNC_INVOICE_CUST_INVOICE:
case GNC_INVOICE_VEND_CREDIT_NOTE:
case GNC_INVOICE_EMPL_CREDIT_NOTE:
return TRUE;
case GNC_INVOICE_CUST_CREDIT_NOTE:
case GNC_INVOICE_VEND_INVOICE:
case GNC_INVOICE_EMPL_INVOICE:
return FALSE;
case GNC_INVOICE_UNDEFINED:
default:
/* Should never be reached.
* If it is, perhaps a new value is added to GncInvoiceType ? */
g_assert_not_reached();
return FALSE;
}
}
| 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 318 of file gncInvoice.c.
{
GncInvoice *invoice;
QofBook* book;
GList *node;
gint64 is_cn;
g_assert(from);
book = qof_instance_get_book(from);
g_assert(book);
invoice = g_object_new (GNC_TYPE_INVOICE, NULL);
qof_instance_init_data (&invoice->inst, _GNC_MOD_NAME, book);
gncInvoiceBeginEdit(invoice);
invoice->id = CACHE_INSERT (from->id);
invoice->notes = CACHE_INSERT (from->notes);
invoice->billing_id = CACHE_INSERT (from->billing_id);
invoice->active = from->active;
is_cn = kvp_frame_get_gint64(from->inst.kvp_data, GNC_INVOICE_IS_CN);
kvp_frame_set_gint64(invoice->inst.kvp_data, GNC_INVOICE_IS_CN, is_cn);
invoice->terms = from->terms;
gncBillTermIncRef (invoice->terms);
gncOwnerCopy(&from->billto, &invoice->billto);
gncOwnerCopy(&from->owner, &invoice->owner);
invoice->job = from->job; // FIXME: Need IncRef or similar here?!?
invoice->to_charge_amount = from->to_charge_amount;
invoice->date_opened = from->date_opened;
// Oops. Do not forget to copy the pointer to the correct currency here.
invoice->currency = from->currency;
// Copy all invoice->entries
for (node = from->entries; node; node = node->next)
{
GncEntry *from_entry = node->data;
GncEntry *to_entry = gncEntryCreate(book);
gncEntryCopy(from_entry, to_entry);
switch (gncInvoiceGetOwnerType (invoice))
{
case GNC_OWNER_VENDOR:
case GNC_OWNER_EMPLOYEE:
// this is a vendor bill, or an expense voucher
gncBillAddEntry(invoice, to_entry);
break;
case GNC_OWNER_CUSTOMER:
default:
// this is an invoice
gncInvoiceAddEntry(invoice, to_entry);
break;
}
}
// FIXME: The prices are not (yet) copied; is this a problem?
// Posted-date and the posted Txn is intentionally not copied; the
// copy isn't "posted" but needs to be posted by the user.
gncInvoiceCommitEdit(invoice);
return invoice;
}
| gboolean gncInvoiceEqual | ( | const GncInvoice * | a, |
| const GncInvoice * | b | ||
| ) |
Test support function used by test-dbi-business-stuff.c
Definition at line 1742 of file gncInvoice.c.
{
if (a == NULL && b == NULL) return TRUE;
if (a == NULL || b == NULL) return FALSE;
g_return_val_if_fail(GNC_IS_INVOICE(a), FALSE);
g_return_val_if_fail(GNC_IS_INVOICE(b), FALSE);
if (safe_strcmp(a->id, b->id) != 0)
{
PWARN("IDs differ: %s vs %s", a->id, b->id);
return FALSE;
}
if (safe_strcmp(a->notes, b->notes) != 0)
{
PWARN("Notes differ: %s vs %s", a->notes, b->notes);
return FALSE;
}
if (safe_strcmp(a->billing_id, b->billing_id) != 0)
{
PWARN("Billing IDs differ: %s vs %s", a->billing_id, b->billing_id);
return FALSE;
}
if (safe_strcmp(a->printname, b->printname) != 0)
{
PWARN("Printnames differ: %s vs %s", a->printname, b->printname);
return FALSE;
}
if (a->active != b->active)
{
PWARN("Active flags differ");
return FALSE;
}
if (!gncBillTermEqual(a->terms, b->terms))
{
PWARN("Billterms differ");
return FALSE;
}
if (!gncJobEqual(a->job, b->job))
{
PWARN("Jobs differ");
return FALSE;
}
if (!gnc_commodity_equal(a->currency, b->currency))
{
PWARN("Currencies differ");
return FALSE;
}
if (!xaccAccountEqual(a->posted_acc, b->posted_acc, TRUE))
{
PWARN("Posted accounts differ");
return FALSE;
}
if (!xaccTransEqual(a->posted_txn, b->posted_txn, TRUE, TRUE, TRUE, FALSE))
{
PWARN("Posted tx differ");
return FALSE;
}
#if 0
if (!gncLotEqual(a->posted_lot, b->posted_lot))
{
PWARN("Posted lots differ");
return FALSE;
}
#endif
/* FIXME: Need real checks */
#if 0
GList *entries;
GList *prices;
GncOwner owner;
GncOwner billto;
Timespec date_opened;
Timespec date_posted;
gnc_numeric to_charge_amount;
#endif
return TRUE;
}
| GncInvoice* gncInvoiceGetInvoiceFromLot | ( | GNCLot * | lot | ) |
Given a LOT, find and return the Invoice attached to the lot
Definition at line 1095 of file gncInvoice.c.
{
KvpFrame *kvp;
KvpValue *value;
GncGUID *guid;
QofBook *book;
if (!lot) return NULL;
book = gnc_lot_get_book (lot);
kvp = gnc_lot_get_slots (lot);
value = kvp_frame_get_slot_path (kvp, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
if (!value) return NULL;
guid = kvp_value_get_guid (value);
return gncInvoiceLookup(book, guid);
}
| GncInvoice* gncInvoiceGetInvoiceFromTxn | ( | const Transaction * | txn | ) |
Given a transaction, find and return the Invoice
Definition at line 1135 of file gncInvoice.c.
{
KvpFrame *kvp;
KvpValue *value;
GncGUID *guid;
QofBook *book;
if (!txn) return NULL;
book = xaccTransGetBook (txn);
kvp = xaccTransGetSlots (txn);
value = kvp_frame_get_slot_path (kvp, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
if (!value) return NULL;
guid = kvp_value_get_guid (value);
return gncInvoiceLookup(book, guid);
}
| gnc_numeric gncInvoiceGetTotal | ( | GncInvoice * | invoice | ) |
return the "total" amount of the invoice
Definition at line 817 of file gncInvoice.c.
{
if (!invoice) return gnc_numeric_zero();
return gncInvoiceGetTotalInternal(invoice, TRUE, TRUE, FALSE, 0);
}
| Transaction* gncInvoicePostToAccount | ( | GncInvoice * | invoice, |
| Account * | acc, | ||
| Timespec * | posted_date, | ||
| Timespec * | due_date, | ||
| const char * | memo, | ||
| gboolean | accumulatesplits | ||
| ) |
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.
Definition at line 1205 of file gncInvoice.c.
{
Transaction *txn;
QofBook *book;
GNCLot *lot = NULL;
GList *iter;
GList *splitinfo = NULL;
gnc_numeric total;
gboolean positive_balance;
gboolean is_cust_doc;
const char *name, *type;
char *lot_title;
Account *ccard_acct = NULL;
const GncOwner *owner;
if (!invoice || !acc) return NULL;
gncInvoiceBeginEdit (invoice);
book = qof_instance_get_book(invoice);
/* Stabilize the Billing Terms of this invoice */
if (invoice->terms)
gncInvoiceSetTerms (invoice,
gncBillTermReturnChild (invoice->terms, TRUE));
/* Does the invoice/credit note have a positive effect on the balance ? Note that
* payments for such invoices by definition then have a negative effect on the balance.
* This is used to determine which open lots can be considered when posting the invoice. */
positive_balance = gncInvoiceAmountPositive (invoice);
/* GncEntry functions need to know if the invoice/credit note is for a customer or a vendor/employee. */
is_cust_doc = (gncInvoiceGetOwnerType (invoice) == GNC_OWNER_CUSTOMER);
/* Figure out if we need to separate out "credit-card" items */
owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice));
if (gncInvoiceGetOwnerType (invoice) == GNC_OWNER_EMPLOYEE)
ccard_acct = gncEmployeeGetCCard (gncOwnerGetEmployee (owner));
/* Find an existing payment-lot for this owner */
{
LotList *lot_list;
struct lotmatch lm;
lm.positive_balance = positive_balance;
lm.owner = owner;
lot_list = xaccAccountFindOpenLots (acc, gnc_lot_match_owner_payment,
&lm, NULL);
if (lot_list)
lot = lot_list->data;
g_list_free (lot_list);
}
/* Create a new lot for this invoice, if we need to do so */
if (!lot)
lot = gnc_lot_new (book);
gnc_lot_begin_edit (lot);
type = gncInvoiceGetTypeString (invoice);
/* Set the lot title */
lot_title = g_strdup_printf ("%s %s", type, gncInvoiceGetID (invoice));
gnc_lot_set_title (lot, lot_title);
g_free (lot_title);
/* Create a new transaction */
txn = xaccMallocTransaction (book);
xaccTransBeginEdit (txn);
name = gncOwnerGetName (gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice)));
/* Set Transaction Description (Owner Name) , Num (invoice ID), Currency */
xaccTransSetDescription (txn, name ? name : "");
xaccTransSetNum (txn, gncInvoiceGetID (invoice));
xaccTransSetCurrency (txn, invoice->currency);
/* Entered and Posted at date */
xaccTransSetDateEnteredSecs (txn, time(NULL));
if (post_date)
{
xaccTransSetDatePostedTS (txn, post_date);
gncInvoiceSetDatePosted (invoice, *post_date);
}
if (due_date)
xaccTransSetDateDueTS (txn, due_date);
/* Iterate through the entries; sum up everything for each account.
* then create the appropriate splits in this txn.
*/
total = gnc_numeric_zero();
for (iter = gncInvoiceGetEntries(invoice); iter; iter = iter->next)
{
gnc_numeric value, tax;
GList *taxes;
GncEntry * entry = iter->data;
Account *this_acc;
/* Stabilize the TaxTable in this entry */
gncEntryBeginEdit (entry);
if (is_cust_doc)
gncEntrySetInvTaxTable
(entry, gncTaxTableReturnChild (gncEntryGetInvTaxTable (entry), TRUE));
else
{
gncEntrySetBillTaxTable
(entry, gncTaxTableReturnChild (gncEntryGetBillTaxTable (entry), TRUE));
/* If this is a bill, and the entry is billable, copy the price */
if (gncEntryGetBillable (entry))
gncEntrySetInvPrice (entry, gncEntryGetBillPrice (entry));
}
gncEntryCommitEdit (entry);
/* Obtain the Entry's Value and TaxValues */
gncEntryGetValue (entry, is_cust_doc, &value, NULL, &tax, &taxes);
/* add the value for the account split */
this_acc = (is_cust_doc ? gncEntryGetInvAccount (entry) :
gncEntryGetBillAccount (entry));
if (this_acc)
{
if (gnc_numeric_check (value) == GNC_ERROR_OK)
{
if (accumulatesplits)
{
splitinfo = gncAccountValueAdd (splitinfo, this_acc, value);
}
else
{
Split *split;
split = xaccMallocSplit (book);
/* set action and memo? */
xaccSplitSetMemo (split, gncEntryGetDescription (entry));
xaccSplitSetAction (split, type);
/* Need to insert this split into the account AND txn before
* we set the Base Value. Otherwise SetBaseValue complains
* that we don't have an account and fails to set the value.
*/
xaccAccountBeginEdit (this_acc);
xaccAccountInsertSplit (this_acc, split);
xaccAccountCommitEdit (this_acc);
xaccTransAppendSplit (txn, split);
/* General note on the split creations below:
* Invoice and bill amounts are always stored as positive values in entries
* So to convert them to proper splits, the amounts may have to be reverted
* to have the proper effect on the account balance.
* Credit notes have the opposite effect of invoices/bills, but their amounts
* are stored as negative values as well. So to convert them into splits
* they can be treated exactly the same as their invoice/bill counter parts.
* The net effect is that the owner type is sufficient to determine whether a
* value has to be reverted when converting an invoice/bill/cn amount to a split.
*/
if (gnc_commodity_equal(xaccAccountGetCommodity(this_acc), invoice->currency))
{
xaccSplitSetBaseValue (split, (is_cust_doc ? gnc_numeric_neg (value)
: value),
invoice->currency);
}
else
{
/*need to do conversion */
GNCPrice *price = gncInvoiceGetPrice(invoice, xaccAccountGetCommodity(this_acc));
if (price == NULL)
{
/*This is an error, which shouldn't even be able to happen.
We can't really do anything sensible about it, and this is
a user-interface free zone so we can't try asking the user
again either, have to return NULL*/
return NULL;
}
else
{
gnc_numeric converted_amount;
xaccSplitSetValue(split, (is_cust_doc ? gnc_numeric_neg(value) : value));
converted_amount = gnc_numeric_div(value, gnc_price_get_value(price), GNC_DENOM_AUTO, GNC_HOW_RND_ROUND_HALF_UP);
DEBUG("converting from %f to %f\n", gnc_numeric_to_double(value), gnc_numeric_to_double(converted_amount));
xaccSplitSetAmount(split, is_cust_doc ? gnc_numeric_neg(converted_amount) : converted_amount);
}
}
}
/* If there is a credit-card account, and this is a CCard
* payment type, the don't add it to the total, and instead
* create a split to the CC Acct with a memo of the entry
* description instead of the provided memo. Note that the
* value reversal is the same as the post account.
*
* Note: we don't have to worry about the tax values --
* expense vouchers don't have them.
*/
if (ccard_acct && gncEntryGetBillPayment (entry) == GNC_PAYMENT_CARD)
{
Split *split;
split = xaccMallocSplit (book);
/* set action? */
xaccSplitSetMemo (split, gncEntryGetDescription (entry));
xaccSplitSetAction (split, type);
xaccAccountBeginEdit (ccard_acct);
xaccAccountInsertSplit (ccard_acct, split);
xaccAccountCommitEdit (ccard_acct);
xaccTransAppendSplit (txn, split);
xaccSplitSetBaseValue (split, (is_cust_doc ? value : gnc_numeric_neg (value)),
invoice->currency);
}
else
total = gnc_numeric_add (total, value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
}
else
g_warning ("bad value in our entry");
}
/* now merge in the TaxValues */
splitinfo = gncAccountValueAddList (splitinfo, taxes);
/* ... and add the tax total */
if (gnc_numeric_check (tax) == GNC_ERROR_OK)
total = gnc_numeric_add (total, tax, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
else
g_warning ("bad tax in our entry");
} /* for */
/* Iterate through the splitinfo list and generate the splits */
for (iter = splitinfo; iter; iter = iter->next)
{
Split *split;
GncAccountValue *acc_val = iter->data;
split = xaccMallocSplit (book);
/* set action and memo? */
xaccSplitSetMemo (split, memo);
xaccSplitSetAction (split, type);
xaccAccountBeginEdit (acc_val->account);
xaccAccountInsertSplit (acc_val->account, split);
xaccAccountCommitEdit (acc_val->account);
xaccTransAppendSplit (txn, split);
if (gnc_commodity_equal(xaccAccountGetCommodity(acc_val->account), invoice->currency))
{
xaccSplitSetBaseValue (split, (is_cust_doc ? gnc_numeric_neg (acc_val->value)
: acc_val->value),
invoice->currency);
}
else
{
/*need to do conversion */
GNCPrice *price = gncInvoiceGetPrice(invoice, xaccAccountGetCommodity(acc_val->account));
if (price == NULL)
{
/*This is an error, which shouldn't even be able to happen.
We can't really do anything sensible about it, and this is
a user-interface free zone so we can't try asking the user
again either, have to return NULL*/
return NULL;
}
else
{
gnc_numeric converted_amount;
xaccSplitSetValue(split, (is_cust_doc ? gnc_numeric_neg(acc_val->value) : acc_val->value));
converted_amount = gnc_numeric_div(acc_val->value, gnc_price_get_value(price), GNC_DENOM_AUTO, GNC_HOW_RND_ROUND_HALF_UP);
DEBUG("converting from %f to %f\n", gnc_numeric_to_double(acc_val->value), gnc_numeric_to_double(converted_amount));
xaccSplitSetAmount(split, is_cust_doc ? gnc_numeric_neg(converted_amount) : converted_amount);
}
}
}
/* If there is a ccard account, we may have an additional "to_card" payment.
* we should make that now..
*/
if (ccard_acct && !gnc_numeric_zero_p (invoice->to_charge_amount))
{
Split *split = xaccMallocSplit (book);
/* Set memo. action? */
xaccSplitSetMemo (split, _("Extra to Charge Card"));
xaccSplitSetAction (split, type);
xaccAccountBeginEdit (ccard_acct);
xaccAccountInsertSplit (ccard_acct, split);
xaccAccountCommitEdit (ccard_acct);
xaccTransAppendSplit (txn, split);
xaccSplitSetBaseValue (split, (is_cust_doc ? invoice->to_charge_amount :
gnc_numeric_neg(invoice->to_charge_amount)),
invoice->currency);
total = gnc_numeric_sub (total, invoice->to_charge_amount,
GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
}
/* Now create the Posted split (which is the opposite sign of the above splits) */
{
Split *split = xaccMallocSplit (book);
/* Set action/memo */
xaccSplitSetMemo (split, memo);
xaccSplitSetAction (split, type);
xaccAccountBeginEdit (acc);
xaccAccountInsertSplit (acc, split);
xaccAccountCommitEdit (acc);
xaccTransAppendSplit (txn, split);
xaccSplitSetBaseValue (split, (is_cust_doc ? total : gnc_numeric_neg (total)),
invoice->currency);
/* add this split to the lot */
gnc_lot_add_split (lot, split);
}
/* Now attach this invoice to the txn, lot, and account */
gncInvoiceAttachToLot (invoice, lot);
gncInvoiceAttachToTxn (invoice, txn);
gncInvoiceSetPostedAcc (invoice, acc);
xaccTransSetReadOnly (txn, _("Generated from an invoice. Try unposting the invoice."));
xaccTransCommitEdit (txn);
gncAccountValueDestroy (splitinfo);
/* check the lot -- if we still look like a payment lot, then that
* means we need to create a balancing split and create a new payment
* lot for the next invoice
*
* we're looking for a positive balance for bill/AP, and a negative balance
* for invoice/AR.
* (because bill payments debit AP accounts and invoice payments
* credit AR accounts)
*/
total = gnc_lot_get_balance (lot);
if ( (gnc_numeric_negative_p (total) && positive_balance) ||
(gnc_numeric_positive_p (total) && !positive_balance) )
{
Transaction *t2;
GNCLot *lot2;
Split *split;
/* Translators: This is the memo of an auto-created split */
char *memo2 = _("Automatic Payment Forward");
char *action2 = _("Auto Split");
t2 = xaccMallocTransaction (book);
lot2 = gnc_lot_new (book);
gnc_lot_begin_edit (lot2);
gncOwnerAttachToLot (gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice)),
lot2);
xaccTransBeginEdit (t2);
xaccAccountBeginEdit (acc);
/* Set Transaction Description (Owner Name), Currency */
xaccTransSetDescription (t2, name ? name : "");
xaccTransSetCurrency (t2, invoice->currency);
/* Entered and Posted at date */
xaccTransSetDateEnteredSecs (t2, time(NULL));
if (post_date)
xaccTransSetDatePostedTS (t2, post_date);
/* Balance out this lot */
split = xaccMallocSplit (book);
xaccSplitSetMemo (split, memo2);
xaccSplitSetAction (split, action2);
xaccAccountInsertSplit (acc, split);
xaccTransAppendSplit (t2, split);
// the value of total used here is correct for both bill/AP and
// invoice/AR. See the comment before this if block
xaccSplitSetBaseValue (split, gnc_numeric_neg (total),
invoice->currency);
gnc_lot_add_split (lot, split);
/* And apply the pre-payment to a new lot */
split = xaccMallocSplit (book);
xaccSplitSetMemo (split, memo2);
xaccSplitSetAction (split, action2);
xaccAccountInsertSplit (acc, split);
xaccTransAppendSplit (t2, split);
xaccSplitSetBaseValue (split, total, invoice->currency);
gnc_lot_add_split (lot2, split);
gnc_lot_commit_edit (lot2);
xaccTransCommitEdit (t2);
xaccAccountCommitEdit (acc);
}
gnc_lot_commit_edit (lot);
gncInvoiceCommitEdit (invoice);
return txn;
}
| 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 462 of file gncInvoice.c.
{
g_assert (date);
gncInvoiceSetDateOpened(invoice, timespecCanonicalDayTime(gdate_to_timespec(*date)));
}
| 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 666 of file gncInvoice.c.
{
if (!invoice) return;
invoice->entries = g_list_sort(invoice->entries,
(GCompareFunc)gncEntryCompare);
mark_invoice(invoice);
}
| 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 1611 of file gncInvoice.c.
{
Transaction *txn;
GNCLot *lot;
if (!invoice) return FALSE;
if (!gncInvoiceIsPosted (invoice)) return FALSE;
txn = gncInvoiceGetPostedTxn (invoice);
g_return_val_if_fail (txn, FALSE);
lot = gncInvoiceGetPostedLot (invoice);
g_return_val_if_fail (lot, FALSE);
/* Destroy the Posted Transaction */
xaccTransClearReadOnly (txn);
xaccTransBeginEdit (txn);
xaccTransDestroy (txn);
xaccTransCommitEdit (txn);
/* Disconnect the lot from the invoice; re-attach to the invoice owner */
gncInvoiceDetachFromLot (lot);
gncOwnerAttachToLot (&invoice->owner, lot);
/* If the lot has no splits, then destroy it */
if (!gnc_lot_count_splits (lot))
gnc_lot_destroy (lot);
/* Clear out the invoice posted information */
gncInvoiceBeginEdit (invoice);
invoice->posted_acc = NULL;
invoice->posted_txn = NULL;
invoice->posted_lot = NULL;
invoice->date_posted.tv_sec = invoice->date_posted.tv_nsec = 0;
/* if we've been asked to reset the tax tables, then do so */
if (reset_tax_tables)
{
gboolean is_cust_doc = (gncInvoiceGetOwnerType(invoice) == GNC_OWNER_CUSTOMER);
GList *iter;
for (iter = gncInvoiceGetEntries(invoice); iter; iter = iter->next)
{
GncEntry *entry = iter->data;
gncEntryBeginEdit(entry);
if (is_cust_doc)
gncEntrySetInvTaxTable(entry,
gncTaxTableGetParent(gncEntryGetInvTaxTable(entry)));
else
gncEntrySetBillTaxTable(entry,
gncTaxTableGetParent(gncEntryGetBillTaxTable(entry)));
gncEntryCommitEdit(entry);
}
}
mark_invoice (invoice);
gncInvoiceCommitEdit (invoice);
return TRUE;
}
1.7.4