2001-11-21 19:23:07 -06:00
|
|
|
/*
|
|
|
|
* gncInvoice.c -- the Core Business Invoice
|
2002-02-03 14:01:08 -06:00
|
|
|
* Copyright (C) 2001,2002 Derek Atkins
|
2001-11-21 19:23:07 -06:00
|
|
|
* Author: Derek Atkins <warlord@MIT.EDU>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
|
|
|
#include "Transaction.h"
|
|
|
|
#include "Account.h"
|
|
|
|
#include "messages.h"
|
|
|
|
#include "gnc-numeric.h"
|
|
|
|
#include "kvp_frame.h"
|
|
|
|
#include "gnc-engine-util.h"
|
2001-11-24 23:34:34 -06:00
|
|
|
#include "gnc-book-p.h"
|
|
|
|
#include "GNCIdP.h"
|
2002-02-03 14:01:08 -06:00
|
|
|
#include "QueryObject.h"
|
2001-11-21 19:23:07 -06:00
|
|
|
|
|
|
|
#include "gncBusiness.h"
|
|
|
|
#include "gncEntry.h"
|
|
|
|
#include "gncEntryP.h"
|
|
|
|
#include "gncInvoice.h"
|
|
|
|
#include "gncInvoiceP.h"
|
2001-12-05 23:46:42 -06:00
|
|
|
#include "gncOwner.h"
|
2001-11-21 19:23:07 -06:00
|
|
|
|
|
|
|
struct _gncInvoice {
|
2001-11-24 23:34:34 -06:00
|
|
|
GNCBook *book;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
|
|
|
GUID guid;
|
|
|
|
char * id;
|
|
|
|
char * notes;
|
2002-01-22 21:58:07 -06:00
|
|
|
char * terms;
|
2002-02-23 22:01:57 -06:00
|
|
|
char * printname;
|
2001-11-21 19:23:07 -06:00
|
|
|
GList * entries;
|
2001-12-05 23:46:42 -06:00
|
|
|
GncOwner owner;
|
2001-11-21 19:23:07 -06:00
|
|
|
Timespec date_opened;
|
2002-02-10 19:59:54 -06:00
|
|
|
Timespec date_posted;
|
2001-11-21 19:23:07 -06:00
|
|
|
Timespec date_due;
|
2002-02-10 19:59:54 -06:00
|
|
|
Timespec date_paid;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
|
|
|
Account * posted_acc;
|
|
|
|
Transaction * posted_txn;
|
2002-02-10 19:59:54 -06:00
|
|
|
Transaction * paid_txn;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
|
|
|
gboolean active;
|
|
|
|
|
|
|
|
gboolean dirty;
|
|
|
|
};
|
|
|
|
|
2002-02-03 14:01:08 -06:00
|
|
|
#define _GNC_MOD_NAME GNC_INVOICE_MODULE_NAME
|
2001-11-24 23:34:34 -06:00
|
|
|
|
2001-11-23 23:35:08 -06:00
|
|
|
#define GNC_INVOICE_ID "gncInvoice"
|
|
|
|
#define GNC_INVOICE_GUID "invoice-guid"
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
#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));
|
|
|
|
|
|
|
|
#define SET_STR(member, str) { \
|
|
|
|
char * tmp; \
|
|
|
|
\
|
|
|
|
if (!safe_strcmp (member, str)) return; \
|
|
|
|
tmp = CACHE_INSERT (str); \
|
|
|
|
CACHE_REMOVE (member); \
|
|
|
|
member = tmp; \
|
|
|
|
}
|
|
|
|
|
2001-11-24 23:34:34 -06:00
|
|
|
static void addObj (GncInvoice *invoice);
|
|
|
|
static void remObj (GncInvoice *invoice);
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
/* Create/Destroy Functions */
|
|
|
|
|
2001-12-05 23:46:42 -06:00
|
|
|
GncInvoice *gncInvoiceCreate (GNCBook *book)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
|
|
|
GncInvoice *invoice;
|
|
|
|
|
2001-11-24 23:34:34 -06:00
|
|
|
if (!book) return NULL;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
|
|
|
invoice = g_new0 (GncInvoice, 1);
|
2001-11-24 23:34:34 -06:00
|
|
|
invoice->book = book;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
|
|
|
invoice->id = CACHE_INSERT ("");
|
|
|
|
invoice->notes = CACHE_INSERT ("");
|
2002-01-22 21:58:07 -06:00
|
|
|
invoice->terms = CACHE_INSERT ("");
|
2001-11-21 19:23:07 -06:00
|
|
|
|
|
|
|
invoice->active = TRUE;
|
|
|
|
|
2001-11-24 23:34:34 -06:00
|
|
|
xaccGUIDNew (&invoice->guid, book);
|
|
|
|
addObj (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
|
|
|
|
return invoice;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gncInvoiceDestroy (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return;
|
|
|
|
|
|
|
|
CACHE_REMOVE (invoice->id);
|
|
|
|
CACHE_REMOVE (invoice->notes);
|
|
|
|
g_list_free (invoice->entries);
|
2001-11-24 23:34:34 -06:00
|
|
|
remObj (invoice);
|
|
|
|
|
2002-02-23 22:01:57 -06:00
|
|
|
if (invoice->printname) g_free (invoice->printname);
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
g_free (invoice);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set Functions */
|
|
|
|
|
|
|
|
void gncInvoiceSetGUID (GncInvoice *invoice, const GUID *guid)
|
|
|
|
{
|
|
|
|
if (!invoice || !guid) return;
|
2001-11-24 23:34:34 -06:00
|
|
|
if (guid_equal (guid, &invoice->guid)) return;
|
|
|
|
|
|
|
|
remObj (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
invoice->guid = *guid;
|
2001-11-24 23:34:34 -06:00
|
|
|
addObj (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void gncInvoiceSetID (GncInvoice *invoice, const char *id)
|
|
|
|
{
|
|
|
|
if (!invoice || !id) return;
|
|
|
|
SET_STR (invoice->id, id);
|
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
2001-12-05 23:46:42 -06:00
|
|
|
void gncInvoiceSetOwner (GncInvoice *invoice, GncOwner *owner)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2001-12-05 23:46:42 -06:00
|
|
|
if (!invoice || !owner) return;
|
|
|
|
gncOwnerCopy (owner, &invoice->owner);
|
2001-11-21 19:23:07 -06:00
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
2002-02-26 17:42:11 -06:00
|
|
|
void gncInvoiceSetDateOpened (GncInvoice *invoice, Timespec date)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2002-02-26 17:42:11 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
invoice->date_opened = date;
|
2001-11-21 19:23:07 -06:00
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
2002-02-26 17:42:11 -06:00
|
|
|
void gncInvoiceSetDatePosted (GncInvoice *invoice, Timespec date)
|
2002-02-10 19:59:54 -06:00
|
|
|
{
|
2002-02-26 17:42:11 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
invoice->date_posted = date;
|
2002-02-10 19:59:54 -06:00
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
2002-02-26 17:42:11 -06:00
|
|
|
void gncInvoiceSetDateDue (GncInvoice *invoice, Timespec date)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2002-02-26 17:42:11 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
invoice->date_due = date;
|
2001-11-21 19:23:07 -06:00
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
2002-02-26 17:42:11 -06:00
|
|
|
void gncInvoiceSetDatePaid (GncInvoice *invoice, Timespec date)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2002-02-26 17:42:11 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
invoice->date_paid = date;
|
2001-11-21 19:23:07 -06:00
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
2002-01-22 21:58:07 -06:00
|
|
|
void gncInvoiceSetTerms (GncInvoice *invoice, const char *terms)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
|
|
|
if (!invoice) return;
|
2002-01-22 21:58:07 -06:00
|
|
|
SET_STR (invoice->terms, terms);
|
2001-11-21 19:23:07 -06:00
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gncInvoiceSetNotes (GncInvoice *invoice, const char *notes)
|
|
|
|
{
|
|
|
|
if (!invoice || !notes) return;
|
|
|
|
SET_STR (invoice->notes, notes);
|
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gncInvoiceSetActive (GncInvoice *invoice, gboolean active)
|
|
|
|
{
|
|
|
|
if (!invoice) return;
|
|
|
|
invoice->active = active;
|
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gncInvoiceSetDirty (GncInvoice *invoice, gboolean dirty)
|
|
|
|
{
|
|
|
|
if (!invoice) return;
|
|
|
|
invoice->dirty = dirty;
|
|
|
|
}
|
|
|
|
|
2001-11-23 23:35:08 -06:00
|
|
|
void gncInvoiceSetPostedTxn (GncInvoice *invoice, Transaction *txn)
|
|
|
|
{
|
|
|
|
if (!invoice) return;
|
|
|
|
|
|
|
|
invoice->posted_txn = txn;
|
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
2002-02-10 19:59:54 -06:00
|
|
|
void gncInvoiceSetPaidTxn (GncInvoice *invoice, Transaction *txn)
|
|
|
|
{
|
|
|
|
if (!invoice) return;
|
|
|
|
|
|
|
|
invoice->paid_txn = txn;
|
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
2001-11-23 23:35:08 -06:00
|
|
|
void gncInvoiceSetPostedAcc (GncInvoice *invoice, Account *acc)
|
|
|
|
{
|
|
|
|
if (!invoice) return;
|
|
|
|
|
|
|
|
invoice->posted_acc = acc;
|
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
void gncInvoiceAddEntry (GncInvoice *invoice, GncEntry *entry)
|
|
|
|
{
|
|
|
|
GncInvoice *old;
|
|
|
|
|
|
|
|
if (!invoice || !entry) return;
|
|
|
|
|
|
|
|
old = gncEntryGetInvoice (entry);
|
|
|
|
if (old == invoice) return; /* I already own this one */
|
|
|
|
if (old) gncInvoiceRemoveEntry (old, entry);
|
|
|
|
|
|
|
|
gncEntrySetInvoice (entry, invoice);
|
|
|
|
invoice->entries = g_list_append (invoice->entries, entry);
|
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gncInvoiceRemoveEntry (GncInvoice *invoice, GncEntry *entry)
|
|
|
|
{
|
|
|
|
if (!invoice || !entry) return;
|
|
|
|
|
|
|
|
gncEntrySetInvoice (entry, NULL);
|
|
|
|
invoice->entries = g_list_remove (invoice->entries, entry);
|
|
|
|
invoice->dirty = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get Functions */
|
|
|
|
|
2001-11-24 23:34:34 -06:00
|
|
|
GNCBook * gncInvoiceGetBook (GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
|
|
|
if (!invoice) return NULL;
|
2001-11-24 23:34:34 -06:00
|
|
|
return invoice->book;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
const GUID * gncInvoiceGetGUID (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return NULL;
|
|
|
|
return &(invoice->guid);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char * gncInvoiceGetID (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->id;
|
|
|
|
}
|
|
|
|
|
2001-12-05 23:46:42 -06:00
|
|
|
GncOwner * gncInvoiceGetOwner (GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
|
|
|
if (!invoice) return NULL;
|
2001-12-05 23:46:42 -06:00
|
|
|
return &invoice->owner;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Timespec gncInvoiceGetDateOpened (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
Timespec ts; ts.tv_sec = 0; ts.tv_nsec = 0;
|
|
|
|
if (!invoice) return ts;
|
|
|
|
return invoice->date_opened;
|
|
|
|
}
|
|
|
|
|
2002-02-10 19:59:54 -06:00
|
|
|
Timespec gncInvoiceGetDatePosted (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
Timespec ts; ts.tv_sec = 0; ts.tv_nsec = 0;
|
|
|
|
if (!invoice) return ts;
|
|
|
|
return invoice->date_posted;
|
|
|
|
}
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
Timespec gncInvoiceGetDateDue (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
Timespec ts; ts.tv_sec = 0; ts.tv_nsec = 0;
|
|
|
|
if (!invoice) return ts;
|
|
|
|
return invoice->date_due;
|
|
|
|
}
|
|
|
|
|
2002-02-10 19:59:54 -06:00
|
|
|
Timespec gncInvoiceGetDatePaid (GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
|
|
|
Timespec ts; ts.tv_sec = 0; ts.tv_nsec = 0;
|
|
|
|
if (!invoice) return ts;
|
2002-02-10 19:59:54 -06:00
|
|
|
return invoice->date_paid;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2002-01-22 21:58:07 -06:00
|
|
|
const char * gncInvoiceGetTerms (GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
|
|
|
if (!invoice) return 0;
|
|
|
|
return invoice->terms;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char * gncInvoiceGetNotes (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->notes;
|
|
|
|
}
|
|
|
|
|
2001-11-23 23:35:08 -06:00
|
|
|
Transaction * gncInvoiceGetPostedTxn (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->posted_txn;
|
|
|
|
}
|
|
|
|
|
2002-02-10 19:59:54 -06:00
|
|
|
Transaction * gncInvoiceGetPaidTxn (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->posted_txn;
|
|
|
|
}
|
|
|
|
|
2001-11-23 23:35:08 -06:00
|
|
|
Account * gncInvoiceGetPostedAcc (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->posted_acc;
|
|
|
|
}
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
gboolean gncInvoiceGetActive (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return FALSE;
|
|
|
|
return invoice->active;
|
|
|
|
}
|
|
|
|
|
|
|
|
GList * gncInvoiceGetEntries (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->entries;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean gncInvoiceIsDirty (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return FALSE;
|
|
|
|
return invoice->dirty;
|
|
|
|
}
|
|
|
|
|
2002-02-10 19:59:54 -06:00
|
|
|
static void
|
|
|
|
gncInvoiceAttachInvoiceToTxn (GncInvoice *invoice, Transaction *txn, char type)
|
2001-11-23 23:35:08 -06:00
|
|
|
{
|
|
|
|
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);
|
2002-02-10 19:59:54 -06:00
|
|
|
xaccTransSetTxnType (txn, type);
|
2001-11-23 23:35:08 -06:00
|
|
|
xaccTransCommitEdit (txn);
|
|
|
|
|
2002-02-10 19:59:54 -06:00
|
|
|
switch (type) {
|
|
|
|
case TXN_TYPE_PAYMENT:
|
|
|
|
gncInvoiceSetPaidTxn (invoice, txn);
|
|
|
|
break;
|
|
|
|
case TXN_TYPE_INVOICE:
|
|
|
|
gncInvoiceSetPostedTxn (invoice, txn);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2001-11-23 23:35:08 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#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,
|
2002-01-22 21:58:07 -06:00
|
|
|
Timespec *date, gboolean reverse)
|
2001-11-23 23:35:08 -06:00
|
|
|
{
|
|
|
|
Transaction *txn;
|
2001-12-07 21:17:51 -06:00
|
|
|
GList *iter;
|
2001-11-23 23:35:08 -06:00
|
|
|
GList *splitinfo = NULL;
|
|
|
|
gnc_numeric total;
|
2002-01-12 22:25:55 -06:00
|
|
|
gnc_commodity *commonCommodity = NULL; /* XXX: FIXME */
|
2001-11-23 23:35:08 -06:00
|
|
|
struct acct_val {
|
|
|
|
Account * acc;
|
|
|
|
gnc_numeric val;
|
|
|
|
} *acc_val;
|
|
|
|
|
|
|
|
if (!invoice || !acc) return NULL;
|
|
|
|
|
2002-02-10 19:59:54 -06:00
|
|
|
/* XXX: Figure out the common currency */
|
|
|
|
|
2001-11-24 23:34:34 -06:00
|
|
|
txn = xaccMallocTransaction (invoice->book);
|
2001-11-23 23:35:08 -06:00
|
|
|
xaccTransBeginEdit (txn);
|
|
|
|
|
|
|
|
/* Set Transaction Description (customer), Num (invoice ID), Currency */
|
|
|
|
xaccTransSetDescription
|
2001-12-05 23:46:42 -06:00
|
|
|
(txn, gncOwnerGetName (gncInvoiceGetOwner (invoice)));
|
2001-11-23 23:35:08 -06:00
|
|
|
|
|
|
|
xaccTransSetNum (txn, gncInvoiceGetID (invoice));
|
|
|
|
xaccTransSetCurrency (txn, commonCommodity);
|
|
|
|
|
|
|
|
/* Entered and Posted at date */
|
|
|
|
if (date) {
|
|
|
|
xaccTransSetDateEnteredTS (txn, date);
|
|
|
|
xaccTransSetDatePostedTS (txn, date);
|
2002-02-26 17:42:11 -06:00
|
|
|
gncInvoiceSetDatePosted (invoice, *date);
|
2001-11-23 23:35:08 -06:00
|
|
|
}
|
|
|
|
|
2002-01-12 22:25:55 -06:00
|
|
|
/* Set the txn due date to be equal to the invoice */
|
|
|
|
{
|
|
|
|
Timespec ddue = gncInvoiceGetDateDue (invoice);
|
|
|
|
xaccTransSetDateDueTS (txn, &ddue);
|
|
|
|
}
|
|
|
|
|
2001-11-23 23:35:08 -06:00
|
|
|
/* 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) {
|
2002-01-12 22:25:55 -06:00
|
|
|
gnc_numeric value, tax;
|
2001-11-23 23:35:08 -06:00
|
|
|
GncEntry * entry = iter->data;
|
2002-01-12 22:25:55 -06:00
|
|
|
Account *this_acc;
|
|
|
|
|
|
|
|
/* Obtain the Entry Value and TaxValue */
|
|
|
|
gncEntryGetValue (entry, &value, &tax);
|
|
|
|
|
|
|
|
/* add the value for the account split */
|
|
|
|
this_acc = gncEntryGetAccount (entry);
|
|
|
|
if (this_acc) {
|
|
|
|
/* 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);
|
2001-11-23 23:35:08 -06:00
|
|
|
|
|
|
|
acc_val->val = gnc_numeric_add_fixed (acc_val->val, value);
|
|
|
|
total = gnc_numeric_add_fixed (total, value);
|
|
|
|
}
|
|
|
|
|
2002-01-12 22:25:55 -06:00
|
|
|
/* Repeat for the TaxValue */
|
2001-11-23 23:35:08 -06:00
|
|
|
this_acc = gncEntryGetTaxAccount (entry);
|
|
|
|
if (this_acc) {
|
|
|
|
|
|
|
|
GET_OR_ADD_ACCVAL (splitinfo, this_acc, acc_val);
|
|
|
|
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;
|
|
|
|
|
2001-11-24 23:34:34 -06:00
|
|
|
split = xaccMallocSplit (invoice->book);
|
2001-11-23 23:35:08 -06:00
|
|
|
/* set action and memo? */
|
|
|
|
|
2002-01-22 21:58:07 -06:00
|
|
|
xaccSplitSetBaseValue (split, (reverse ? gnc_numeric_neg (acc_val->val)
|
|
|
|
: acc_val->val),
|
|
|
|
commonCommodity);
|
2001-11-23 23:35:08 -06:00
|
|
|
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) */
|
|
|
|
{
|
2001-11-24 23:34:34 -06:00
|
|
|
Split *split = xaccMallocSplit (invoice->book);
|
2001-11-23 23:35:08 -06:00
|
|
|
/* Set action/memo */
|
2002-01-22 21:58:07 -06:00
|
|
|
xaccSplitSetBaseValue (split, (reverse ? total : gnc_numeric_neg (total)),
|
|
|
|
commonCommodity);
|
2001-11-23 23:35:08 -06:00
|
|
|
xaccAccountBeginEdit (acc);
|
|
|
|
xaccAccountInsertSplit (acc, split);
|
|
|
|
xaccAccountCommitEdit (acc);
|
|
|
|
xaccTransAppendSplit (txn, split);
|
|
|
|
}
|
|
|
|
|
2002-01-12 22:25:55 -06:00
|
|
|
/* Now attach this invoice to the txn and account */
|
2002-02-10 19:59:54 -06:00
|
|
|
gncInvoiceAttachInvoiceToTxn (invoice, txn, TXN_TYPE_INVOICE);
|
2001-11-23 23:35:08 -06:00
|
|
|
gncInvoiceSetPostedAcc (invoice, acc);
|
|
|
|
|
|
|
|
xaccTransCommitEdit (txn);
|
|
|
|
|
|
|
|
return txn;
|
|
|
|
}
|
|
|
|
|
2002-02-10 19:59:54 -06:00
|
|
|
Transaction *
|
|
|
|
gncInvoicePayToAccount (GncInvoice *invoice, Account *acc,
|
|
|
|
Timespec *paid_date)
|
|
|
|
{
|
|
|
|
Transaction *txn;
|
|
|
|
gnc_numeric total;
|
|
|
|
gnc_commodity *commonCommodity = NULL; /* XXX: FIXME */
|
|
|
|
Account *acct;
|
|
|
|
|
|
|
|
if (!invoice || !acc) return NULL;
|
|
|
|
|
|
|
|
/* Must have posted before you can pay */
|
|
|
|
g_return_val_if_fail (gncInvoiceGetPostedTxn(invoice), NULL);
|
|
|
|
acct = gncInvoiceGetPostedAcc (invoice);
|
|
|
|
g_return_val_if_fail (acct, NULL);
|
|
|
|
|
|
|
|
/* Determine the value for this payment.. Find the split into
|
|
|
|
* the posted account and pull the value out of that.
|
|
|
|
* XXX: Should the payment value be an argument here?
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
GList *l = xaccTransGetSplitList (gncInvoiceGetPostedTxn (invoice));
|
|
|
|
|
|
|
|
for (; l; l=l->next) {
|
|
|
|
Split *s = l->data;
|
|
|
|
|
|
|
|
if (xaccSplitGetAccount (s) == acct) {
|
|
|
|
total = xaccSplitGetValue (s);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure we found the Split */
|
|
|
|
g_return_val_if_fail (l, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: Figure out the common currency */
|
|
|
|
|
|
|
|
txn = xaccMallocTransaction (invoice->book);
|
|
|
|
xaccTransBeginEdit (txn);
|
|
|
|
|
|
|
|
/* Set Transaction Description (customer), Num (invoice ID), Currency */
|
|
|
|
xaccTransSetDescription
|
|
|
|
(txn, gncOwnerGetName (gncInvoiceGetOwner (invoice)));
|
|
|
|
|
|
|
|
xaccTransSetNum (txn, gncInvoiceGetID (invoice));
|
|
|
|
xaccTransSetCurrency (txn, commonCommodity);
|
|
|
|
|
|
|
|
/* Entered and Posted at date */
|
|
|
|
if (paid_date) {
|
|
|
|
xaccTransSetDateEnteredTS (txn, paid_date);
|
|
|
|
xaccTransSetDatePostedTS (txn, paid_date);
|
2002-02-26 17:42:11 -06:00
|
|
|
gncInvoiceSetDatePaid (invoice, *paid_date);
|
2002-02-10 19:59:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* create the split to the payment account */
|
|
|
|
{
|
|
|
|
Split *split = xaccMallocSplit (invoice->book);
|
|
|
|
/* Set action/memo */
|
|
|
|
xaccSplitSetBaseValue (split, total, commonCommodity);
|
|
|
|
xaccAccountBeginEdit (acc);
|
|
|
|
xaccAccountInsertSplit (acc, split);
|
|
|
|
xaccAccountCommitEdit (acc);
|
|
|
|
xaccTransAppendSplit (txn, split);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now create the Payment split for the posted acc, reverse value */
|
|
|
|
{
|
|
|
|
Split *split = xaccMallocSplit (invoice->book);
|
|
|
|
|
|
|
|
/* Set action/memo */
|
|
|
|
xaccSplitSetBaseValue (split, gnc_numeric_neg (total), commonCommodity);
|
|
|
|
xaccAccountBeginEdit (acct);
|
|
|
|
xaccAccountInsertSplit (acct, split);
|
|
|
|
xaccAccountCommitEdit (acct);
|
|
|
|
xaccTransAppendSplit (txn, split);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now attach this invoice to the txn and account */
|
|
|
|
gncInvoiceAttachInvoiceToTxn (invoice, txn, TXN_TYPE_PAYMENT);
|
|
|
|
|
|
|
|
xaccTransCommitEdit (txn);
|
|
|
|
|
|
|
|
return txn;
|
|
|
|
}
|
|
|
|
|
2001-11-23 23:35:08 -06:00
|
|
|
GncInvoice * gncInvoiceGetInvoiceFromTxn (Transaction *txn)
|
|
|
|
{
|
|
|
|
kvp_frame *kvp;
|
|
|
|
kvp_value *value;
|
|
|
|
GUID *guid;
|
2002-01-12 22:25:55 -06:00
|
|
|
GNCBook *book;
|
2001-11-23 23:35:08 -06:00
|
|
|
|
|
|
|
if (!txn) return NULL;
|
|
|
|
|
2002-01-12 22:25:55 -06:00
|
|
|
book = xaccTransGetBook (txn);
|
2001-11-23 23:35:08 -06:00
|
|
|
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);
|
|
|
|
|
2001-11-24 23:34:34 -06:00
|
|
|
return xaccLookupEntity (gnc_book_get_entity_table (book),
|
|
|
|
guid, _GNC_MOD_NAME);
|
|
|
|
}
|
|
|
|
|
2002-02-19 12:23:53 -06:00
|
|
|
static gboolean gncInvoiceDateExists (Timespec *date)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (date, FALSE);
|
|
|
|
if (date->tv_sec || date->tv_nsec) return TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean gncInvoiceIsPosted (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return FALSE;
|
|
|
|
return gncInvoiceDateExists (&(invoice->date_posted));
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean gncInvoiceIsPaid (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return FALSE;
|
|
|
|
return gncInvoiceDateExists (&(invoice->date_paid));
|
|
|
|
}
|
|
|
|
|
2001-11-24 23:34:34 -06:00
|
|
|
GncInvoice * gncInvoiceLookup (GNCBook *book, const GUID *guid)
|
|
|
|
{
|
|
|
|
if (!book || !guid) return NULL;
|
|
|
|
return xaccLookupEntity (gnc_book_get_entity_table (book),
|
|
|
|
guid, _GNC_MOD_NAME);
|
2001-11-23 23:35:08 -06:00
|
|
|
}
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
void gncInvoiceBeginEdit (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return;
|
|
|
|
}
|
|
|
|
void gncInvoiceCommitEdit (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return;
|
|
|
|
}
|
|
|
|
|
2002-02-03 14:01:08 -06:00
|
|
|
int gncInvoiceCompare (GncInvoice *a, GncInvoice *b)
|
|
|
|
{
|
|
|
|
int compare;
|
|
|
|
|
|
|
|
if (a == b) return 0;
|
|
|
|
if (!a && b) return -1;
|
|
|
|
if (a && !b) return 1;
|
|
|
|
|
|
|
|
compare = safe_strcmp (a->id, b->id);
|
|
|
|
if (!compare) return compare;
|
|
|
|
|
|
|
|
compare = timespec_cmp (&(a->date_opened), &(b->date_opened));
|
|
|
|
if (!compare) return compare;
|
|
|
|
|
2002-02-10 19:59:54 -06:00
|
|
|
compare = timespec_cmp (&(a->date_posted), &(b->date_posted));
|
|
|
|
if (!compare) return compare;
|
|
|
|
|
|
|
|
compare = timespec_cmp (&(a->date_paid), &(b->date_paid));
|
2002-02-03 14:01:08 -06:00
|
|
|
if (!compare) return compare;
|
|
|
|
|
|
|
|
return guid_compare (&(a->guid), &(b->guid));
|
|
|
|
}
|
|
|
|
|
2001-11-24 23:34:34 -06:00
|
|
|
/* Package-Private functions */
|
|
|
|
|
|
|
|
static void addObj (GncInvoice *invoice)
|
|
|
|
{
|
2002-02-24 16:12:24 -06:00
|
|
|
gncBusinessAddObject (invoice->book, _GNC_MOD_NAME, invoice, &invoice->guid);
|
2001-11-24 23:34:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void remObj (GncInvoice *invoice)
|
|
|
|
{
|
2002-02-24 16:12:24 -06:00
|
|
|
gncBusinessRemoveObject (invoice->book, _GNC_MOD_NAME, &invoice->guid);
|
2001-11-24 23:34:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void _gncInvoiceCreate (GNCBook *book)
|
|
|
|
{
|
2002-02-24 16:12:24 -06:00
|
|
|
gncBusinessCreate (book, _GNC_MOD_NAME);
|
2001-11-24 23:34:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void _gncInvoiceDestroy (GNCBook *book)
|
|
|
|
{
|
2002-02-24 16:12:24 -06:00
|
|
|
gncBusinessDestroy (book, _GNC_MOD_NAME);
|
|
|
|
}
|
2001-11-24 23:34:34 -06:00
|
|
|
|
2002-02-24 16:12:24 -06:00
|
|
|
static gboolean _gncInvoiceIsDirty (GNCBook *book)
|
|
|
|
{
|
|
|
|
return gncBusinessIsDirty (book, _GNC_MOD_NAME);
|
2001-11-24 23:34:34 -06:00
|
|
|
}
|
|
|
|
|
2002-02-03 14:01:08 -06:00
|
|
|
static void _gncInvoiceForeach (GNCBook *book, foreachObjectCB cb,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
gncBusinessForeach (book, _GNC_MOD_NAME, cb, user_data);
|
|
|
|
}
|
|
|
|
|
2002-02-24 16:12:24 -06:00
|
|
|
static const char * _gncInvoicePrintable (gpointer obj)
|
2002-02-23 22:01:57 -06:00
|
|
|
{
|
2002-02-24 16:12:24 -06:00
|
|
|
GncInvoice *invoice = obj;
|
|
|
|
|
2002-02-23 22:01:57 -06:00
|
|
|
g_return_val_if_fail (invoice, NULL);
|
|
|
|
|
|
|
|
if (invoice->dirty || invoice->printname == NULL) {
|
|
|
|
if (invoice->printname) g_free (invoice->printname);
|
|
|
|
|
|
|
|
invoice->printname =
|
|
|
|
g_strdup_printf ("%s%s%s", invoice->id,
|
2002-02-24 13:15:19 -06:00
|
|
|
gncInvoiceIsPosted (invoice) ? _(" (posted)") : "",
|
2002-02-23 22:01:57 -06:00
|
|
|
gncInvoiceIsPaid (invoice) ? _(" (paid)") : "");
|
|
|
|
}
|
|
|
|
|
|
|
|
return invoice->printname;
|
|
|
|
}
|
|
|
|
|
2002-02-03 14:01:08 -06:00
|
|
|
static GncObject_t gncInvoiceDesc = {
|
|
|
|
GNC_OBJECT_VERSION,
|
2001-11-24 23:34:34 -06:00
|
|
|
_GNC_MOD_NAME,
|
2002-02-19 12:23:53 -06:00
|
|
|
"Invoice",
|
2001-11-24 23:34:34 -06:00
|
|
|
_gncInvoiceCreate,
|
|
|
|
_gncInvoiceDestroy,
|
2002-02-24 16:12:24 -06:00
|
|
|
_gncInvoiceIsDirty,
|
2002-02-03 14:01:08 -06:00
|
|
|
_gncInvoiceForeach,
|
2002-02-23 22:01:57 -06:00
|
|
|
_gncInvoicePrintable,
|
2001-11-21 19:23:07 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
gboolean gncInvoiceRegister (void)
|
|
|
|
{
|
2002-02-03 14:01:08 -06:00
|
|
|
static QueryObjectDef params[] = {
|
2002-02-08 22:18:50 -06:00
|
|
|
{ INVOICE_ID, QUERYCORE_STRING, (QueryAccess)gncInvoiceGetID },
|
|
|
|
{ INVOICE_OWNER, GNC_OWNER_MODULE_NAME, (QueryAccess)gncInvoiceGetOwner },
|
|
|
|
{ INVOICE_OPENED, QUERYCORE_DATE, (QueryAccess)gncInvoiceGetDateOpened },
|
2002-02-10 19:59:54 -06:00
|
|
|
{ INVOICE_POSTED, QUERYCORE_DATE, (QueryAccess)gncInvoiceGetDatePosted },
|
2002-02-08 22:18:50 -06:00
|
|
|
{ INVOICE_DUE, QUERYCORE_DATE, (QueryAccess)gncInvoiceGetDateDue },
|
2002-02-10 19:59:54 -06:00
|
|
|
{ INVOICE_PAID, QUERYCORE_DATE, (QueryAccess)gncInvoiceGetDatePaid },
|
2002-02-19 12:23:53 -06:00
|
|
|
{ INVOICE_IS_POSTED, QUERYCORE_BOOLEAN, (QueryAccess)gncInvoiceIsPosted },
|
|
|
|
{ INVOICE_IS_PAID, QUERYCORE_BOOLEAN, (QueryAccess)gncInvoiceIsPaid },
|
2002-02-08 22:18:50 -06:00
|
|
|
{ INVOICE_NOTES, QUERYCORE_STRING, (QueryAccess)gncInvoiceGetNotes },
|
2002-02-03 19:55:33 -06:00
|
|
|
{ INVOICE_ACC, GNC_ID_ACCOUNT, (QueryAccess)gncInvoiceGetPostedAcc },
|
2002-02-10 19:59:54 -06:00
|
|
|
{ INVOICE_POST_TXN, GNC_ID_TRANS, (QueryAccess)gncInvoiceGetPostedTxn },
|
|
|
|
{ INVOICE_PD_TXN, GNC_ID_TRANS, (QueryAccess)gncInvoiceGetPaidTxn },
|
2002-02-08 22:18:50 -06:00
|
|
|
{ QUERY_PARAM_BOOK, GNC_ID_BOOK, (QueryAccess)gncInvoiceGetBook },
|
2002-02-24 16:12:24 -06:00
|
|
|
{ QUERY_PARAM_GUID, QUERYCORE_GUID, (QueryAccess)gncInvoiceGetGUID },
|
2002-02-03 14:01:08 -06:00
|
|
|
{ NULL },
|
|
|
|
};
|
|
|
|
|
2002-02-03 19:55:33 -06:00
|
|
|
gncQueryObjectRegister (_GNC_MOD_NAME, (QuerySort)gncInvoiceCompare, params);
|
2002-02-03 14:01:08 -06:00
|
|
|
|
|
|
|
return gncObjectRegister (&gncInvoiceDesc);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static gint lastId = 187; /* XXX */
|
|
|
|
|
2001-11-24 23:34:34 -06:00
|
|
|
gint gncInvoiceNextID (GNCBook *book)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
|
|
|
return lastId++;
|
|
|
|
}
|