Add tax_type and discount_type to GncEntry -- this allows you

to change how the Tax and Discount fields are handled (values
or percentages)

Add code to link a GncInvoice to a Transaction, and to lookup
the GncInvoice from a linked Transaction.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@5989 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Derek Atkins
2001-11-24 05:35:08 +00:00
parent 401d6fe3a5
commit 277282f25c
5 changed files with 273 additions and 0 deletions

View File

@@ -28,7 +28,9 @@ struct _gncEntry {
gnc_numeric quantity;
gnc_numeric price;
gnc_numeric tax;
gint tax_type;
gnc_numeric discount;
gint disc_type;
Account * account;
Account * taxaccount;
@@ -183,6 +185,24 @@ void gncEntrySetInvoice (GncEntry *entry, GncInvoice *invoice)
entry->dirty = TRUE;
}
void gncEntrySetTaxType (GncEntry *entry, gint type)
{
if (!entry) return;
if (type < 0 || type > 3) return;
entry->tax_type = type;
entry->dirty = TRUE;
}
void gncEntrySetDiscountType (GncEntry *entry, gint type)
{
if (!entry) return;
if (type < 0 || type > 3) return;
entry->disc_type = type;
entry->dirty = TRUE;
}
void gncEntrySetDirty (GncEntry *entry, gboolean dirty)
{
if (!entry) return;
@@ -270,6 +290,18 @@ GncOrder * gncEntryGetOrder (GncEntry *entry)
return entry->order;
}
gint gncEntryGetTaxType (GncEntry *entry)
{
if (!entry) return 0;
return entry->tax_type;
}
gint gncEntryGetDiscountType (GncEntry *entry)
{
if (!entry) return 0;
return entry->disc_type;
}
void gncEntryCommitEdit (GncEntry *entry)
{
if (!entry) return;

View File

@@ -16,6 +16,17 @@ typedef struct _gncEntry GncEntry;
#define GNC_ENTRY_MODULE_NAME "gncEntry"
/* How to interpret the Discount and Tax numbers.. You can interpret
* the as a VALUE or a PERCENT. Similarly, you can set the PRETAX
* bit if you want the discount to be applied before a percentage-tax.
*/
#define GNC_ENTRY_INTERP_VALUE 0x00
#define GNC_ENTRY_INTERP_PERCENT 0x01
#define GNC_ENTRY_INTERP_PRETAX 0x02
#define GNC_ENTRY_INTERP_IS_VALUE(x) (((x)&0x01) == GNC_ENTRY_INTERP_VALUE)
#define GNC_ENTRY_INTERP_IS_PERCENT(x) (((x)&0x01) == GNC_ENTRY_INTERP_PERCENT)
/* Create/Destroy Functions */
GncEntry *gncEntryCreate (GncBusiness *business);
@@ -29,7 +40,9 @@ void gncEntrySetAction (GncEntry *entry, const char *action);
void gncEntrySetQuantity (GncEntry *entry, gnc_numeric quantity);
void gncEntrySetPrice (GncEntry *entry, gnc_numeric price);
void gncEntrySetTax (GncEntry *entry, gnc_numeric tax);
void gncEntrySetTaxType (GncEntry *entry, gint type);
void gncEntrySetDiscount (GncEntry *entry, gnc_numeric discount);
void gncEntrySetDiscountType (GncEntry *entry, gint type);
void gncEntrySetAccount (GncEntry *entry, Account *acc);
void gncEntrySetTaxAccount (GncEntry *entry, Account *acc);
@@ -44,7 +57,10 @@ const char * gncEntryGetAction (GncEntry *entry);
gnc_numeric gncEntryGetQuantity (GncEntry *entry);
gnc_numeric gncEntryGetPrice (GncEntry *entry);
gnc_numeric gncEntryGetTax (GncEntry *entry);
gint gncEntryGetTaxType (GncEntry *entry);
gnc_numeric gncEntryGetDiscount (GncEntry *entry);
gint gncEntryGetDiscountType (GncEntry *entry);
Account * gncEntryGetAccount (GncEntry *entry);
Account * gncEntryGetTaxAccount (GncEntry *entry);

View File

@@ -48,6 +48,9 @@ struct _gncInvoice {
gboolean dirty;
};
#define GNC_INVOICE_ID "gncInvoice"
#define GNC_INVOICE_GUID "invoice-guid"
#define CACHE_INSERT(str) g_cache_insert(gnc_engine_get_string_cache(), (gpointer)(str));
#define CACHE_REMOVE(str) g_cache_remove(gnc_engine_get_string_cache(), (str));
@@ -180,6 +183,22 @@ void gncInvoiceSetDirty (GncInvoice *invoice, gboolean dirty)
invoice->dirty = dirty;
}
void gncInvoiceSetPostedTxn (GncInvoice *invoice, Transaction *txn)
{
if (!invoice) return;
invoice->posted_txn = txn;
invoice->dirty = TRUE;
}
void gncInvoiceSetPostedAcc (GncInvoice *invoice, Account *acc)
{
if (!invoice) return;
invoice->posted_acc = acc;
invoice->dirty = TRUE;
}
void gncInvoiceAddEntry (GncInvoice *invoice, GncEntry *entry)
{
GncInvoice *old;
@@ -277,6 +296,18 @@ const char * gncInvoiceGetNotes (GncInvoice *invoice)
return invoice->notes;
}
Transaction * gncInvoiceGetPostedTxn (GncInvoice *invoice)
{
if (!invoice) return NULL;
return invoice->posted_txn;
}
Account * gncInvoiceGetPostedAcc (GncInvoice *invoice)
{
if (!invoice) return NULL;
return invoice->posted_acc;
}
gboolean gncInvoiceGetActive (GncInvoice *invoice)
{
if (!invoice) return FALSE;
@@ -295,6 +326,186 @@ gboolean gncInvoiceIsDirty (GncInvoice *invoice)
return invoice->dirty;
}
void gncInvoiceAttachInvoiceToTxn (GncInvoice *invoice, Transaction *txn)
{
kvp_frame *kvp;
kvp_value *value;
if (!invoice || !txn)
return;
if (invoice->posted_txn) return; /* Cannot reset invoice's txn */
xaccTransBeginEdit (txn);
kvp = xaccTransGetSlots (txn);
value = kvp_value_new_guid (gncInvoiceGetGUID (invoice));
kvp_frame_set_slot_path (kvp, value, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
kvp_value_delete (value);
xaccTransCommitEdit (txn);
gncInvoiceSetPostedTxn (invoice, txn);
}
#define GET_OR_ADD_ACCVAL(list,t_acc,res) { \
GList *li; \
res = NULL; \
for (li = list; li; li = li->next) { \
res = li->data; \
if (res->acc == t_acc) \
break; \
res = NULL; \
} \
if (!res) { \
res = g_new0 (struct acct_val, 1); \
res->acc = t_acc; \
res->val = gnc_numeric_zero (); \
list = g_list_append (list, res); \
} \
}
Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
Timespec *date)
{
Transaction *txn;
GList *item, *iter;
GList *splitinfo = NULL;
GNCSession *session;
gnc_numeric total;
gnc_commodity *commonCommodity = NULL;
struct acct_val {
Account * acc;
gnc_numeric val;
} *acc_val;
if (!invoice || !acc) return NULL;
/* XXX: Need to obtain the session */
txn = xaccMallocTransaction (session);
xaccTransBeginEdit (txn);
/* Figure out the common currency */
/* XXX */
/* Set Transaction Description (customer), Num (invoice ID), Currency */
xaccTransSetDescription
(txn,
((gncInvoiceGetType (invoice) == GNC_INVOICE_CUSTOMER) ?
gncCustomerGetName (gncInvoiceGetCustomer (invoice)) :
gncVendorGetName (gncInvoiceGetVendor (invoice))));
xaccTransSetNum (txn, gncInvoiceGetID (invoice));
xaccTransSetCurrency (txn, commonCommodity);
/* Entered and Posted at date */
if (date) {
xaccTransSetDateEnteredTS (txn, date);
xaccTransSetDatePostedTS (txn, 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) {
GncEntry * entry = iter->data;
Account *this_acc = gncEntryGetAccount (entry);
gnc_numeric disc = gncEntryGetDiscount (entry);
gnc_numeric subtotal = gnc_numeric_mul (gncEntryGetQuantity (entry),
gncEntryGetPrice (entry),
100, /* XXX */
GNC_RND_ROUND);
/* Find the account value for this_acc. If we haven't seen this
* account before, create a new total and add to list
*/
GET_OR_ADD_ACCVAL (splitinfo, this_acc, acc_val);
/* Now compute the split value and add it to the totals */
{
gint disc_type = gncEntryGetDiscountType (entry);
gnc_numeric value;
if (GNC_ENTRY_INTERP_IS_PERCENT (disc_type))
disc = gnc_numeric_mul (subtotal, disc, 100 /* XXX */, GNC_RND_ROUND);
value = gnc_numeric_sub_fixed (subtotal, disc);
if (disc_type & GNC_ENTRY_INTERP_PRETAX)
subtotal = value;
acc_val->val = gnc_numeric_add_fixed (acc_val->val, value);
total = gnc_numeric_add_fixed (total, value);
}
/* Repeat for the Entry Tax */
this_acc = gncEntryGetTaxAccount (entry);
if (this_acc) {
gnc_numeric tax = gncEntryGetTax (entry);
gint tax_type = gncEntryGetTaxType (entry);
GET_OR_ADD_ACCVAL (splitinfo, this_acc, acc_val);
if (GNC_ENTRY_INTERP_IS_PERCENT (tax_type))
tax = gnc_numeric_mul (subtotal, tax, 100 /* XXX */, GNC_RND_ROUND);
acc_val->val = gnc_numeric_add_fixed (acc_val->val, tax);
total = gnc_numeric_add_fixed (total, tax);
}
} /* for */
/* Iterate through the splitinfo list and generate the splits */
for (iter = splitinfo; iter; iter = iter->next) {
Split *split;
acc_val = iter->data;
split = xaccMallocSplit (session);
/* set action and memo? */
xaccSplitSetBaseValue (split, acc_val->val, commonCommodity);
xaccAccountBeginEdit (acc_val->acc);
xaccAccountInsertSplit (acc_val->acc, split);
xaccAccountCommitEdit (acc_val->acc);
xaccTransAppendSplit (txn, split);
}
/* Now create the Posted split (which is negative -- it's a credit) */
{
Split *split = xaccMallocSplit (session);
/* Set action/memo */
xaccSplitSetBaseValue (split, gnc_numeric_neg (total), commonCommodity);
xaccAccountBeginEdit (acc);
xaccAccountInsertSplit (acc, split);
xaccAccountCommitEdit (acc);
xaccTransAppendSplit (txn, split);
}
gncInvoiceSetPostedAcc (invoice, acc);
gncInvoiceSetPostedTxn (invoice, txn);
xaccTransCommitEdit (txn);
return txn;
}
GncInvoice * gncInvoiceGetInvoiceFromTxn (Transaction *txn)
{
kvp_frame *kvp;
kvp_value *value;
GUID *guid;
GncBusiness *business;
if (!txn) return NULL;
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);
/* XXX: Need to get GNCSession from Transaction */
/* XXX: lookup invoice from session/guid */
return gncBusinessLookupGUID (business, GNC_INVOICE_MODULE_NAME, guid);
}
void gncInvoiceBeginEdit (GncInvoice *invoice)
{
if (!invoice) return;

View File

@@ -55,8 +55,21 @@ gint gncInvoiceGetTerms (GncInvoice *invoice);
const char * gncInvoiceGetNotes (GncInvoice *invoice);
gboolean gncInvoiceGetActive (GncInvoice *invoice);
Transaction * gncInvoiceGetPostedTxn (GncInvoice *invoice);
Account * gncInvoiceGetPostedAcc (GncInvoice *invoice);
GList * gncInvoiceGetEntries (GncInvoice *invoice);
/* Post this invoice to an account. Returns the new Transaction
* that is tied to this invoice. The transaction is set with
* the posted date.
*/
Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
Timespec *date);
/* Given a transaction, find and return the Invoice */
GncInvoice * gncInvoiceGetInvoiceFromTxn (Transaction *txn);
gboolean gncInvoiceIsDirty (GncInvoice *invoice);
void gncInvoiceCommitEdit (GncInvoice *invoice);

View File

@@ -18,5 +18,6 @@ void gncInvoiceSetGUID (GncInvoice *invoice, const GUID *guid);
void gncInvoiceSetDirty (GncInvoice *invoice, gboolean dirty);
void gncInvoiceSetPostedAcc (GncInvoice *invoice, Account *acc);
void gncInvoiceSetPostedTxn (GncInvoice *invoice, Transaction *txn);
void gncInvoiceAttachInvoiceToTxn (GncInvoice *invoice, Transaction *txn);
#endif /* GNC_INVOICEP_H_ */