2003-10-16 23:32:04 -05:00
|
|
|
/********************************************************************\
|
|
|
|
* gncInvoice.c -- the Core Business Invoice *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or *
|
|
|
|
* modify it under the terms of the GNU General Public License as *
|
|
|
|
* published by the Free Software Foundation; either version 2 of *
|
|
|
|
* the License, or (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License*
|
|
|
|
* along with this program; if not, contact: *
|
|
|
|
* *
|
|
|
|
* Free Software Foundation Voice: +1-617-542-5942 *
|
2005-11-16 23:35:02 -06:00
|
|
|
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
|
|
|
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
2003-10-16 23:32:04 -05:00
|
|
|
* *
|
|
|
|
\********************************************************************/
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
/*
|
2006-02-26 23:42:45 -06:00
|
|
|
* Copyright (C) 2001,2002,2006 Derek Atkins
|
2003-10-21 21:02:45 -05:00
|
|
|
* Copyright (C) 2003 Linas Vepstas <linas@linas.org>
|
2005-11-01 21:32:36 -06:00
|
|
|
* Copyright (c) 2005 Neil Williams <linux@codehelp.co.uk>
|
2001-11-21 19:23:07 -06:00
|
|
|
* Author: Derek Atkins <warlord@MIT.EDU>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <glib.h>
|
2005-11-19 17:53:34 -06:00
|
|
|
#include <glib/gi18n.h>
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2003-10-21 21:02:45 -05:00
|
|
|
#include "Transaction.h"
|
|
|
|
#include "Account.h"
|
|
|
|
#include "gncBillTermP.h"
|
2001-11-21 19:23:07 -06:00
|
|
|
#include "gncEntry.h"
|
|
|
|
#include "gncEntryP.h"
|
2003-10-21 21:02:45 -05:00
|
|
|
#include "gncJobP.h"
|
2001-11-21 19:23:07 -06:00
|
|
|
#include "gncInvoice.h"
|
|
|
|
#include "gncInvoiceP.h"
|
2003-10-21 21:02:45 -05:00
|
|
|
#include "gncOwnerP.h"
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
struct _gncInvoice
|
|
|
|
{
|
|
|
|
QofInstance inst;
|
|
|
|
|
|
|
|
char *id;
|
|
|
|
char *notes;
|
|
|
|
gboolean active;
|
|
|
|
|
|
|
|
char *billing_id;
|
|
|
|
char *printname;
|
|
|
|
GncBillTerm *terms;
|
|
|
|
GList *entries;
|
|
|
|
GList *prices;
|
|
|
|
GncOwner owner;
|
|
|
|
GncOwner billto;
|
|
|
|
GncJob *job;
|
|
|
|
Timespec date_opened;
|
|
|
|
Timespec date_posted;
|
|
|
|
|
|
|
|
gnc_numeric to_charge_amount;
|
|
|
|
|
|
|
|
gnc_commodity * currency;
|
|
|
|
|
|
|
|
Account *posted_acc;
|
|
|
|
Transaction *posted_txn;
|
|
|
|
GNCLot *posted_lot;
|
2001-11-21 19:23:07 -06:00
|
|
|
};
|
|
|
|
|
2007-04-04 21:44:01 -05:00
|
|
|
struct _gncInvoiceClass
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
QofInstanceClass parent_class;
|
2007-04-04 21:44:01 -05:00
|
|
|
};
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
static QofLogModule log_module = GNC_MOD_BUSINESS;
|
2002-11-03 14:21:42 -06:00
|
|
|
|
2003-10-19 00:13:59 -05:00
|
|
|
#define _GNC_MOD_NAME GNC_ID_INVOICE
|
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"
|
|
|
|
|
2002-11-03 18:41:01 -06:00
|
|
|
#define SET_STR(obj, member, str) { \
|
2001-11-21 19:23:07 -06:00
|
|
|
char * tmp; \
|
|
|
|
\
|
|
|
|
if (!safe_strcmp (member, str)) return; \
|
2002-11-03 18:41:01 -06:00
|
|
|
gncInvoiceBeginEdit (obj); \
|
2001-11-21 19:23:07 -06:00
|
|
|
tmp = CACHE_INSERT (str); \
|
|
|
|
CACHE_REMOVE (member); \
|
|
|
|
member = tmp; \
|
|
|
|
}
|
|
|
|
|
2002-06-21 14:00:34 -05:00
|
|
|
static void mark_invoice (GncInvoice *invoice);
|
|
|
|
static void
|
2002-03-02 12:55:01 -06:00
|
|
|
mark_invoice (GncInvoice *invoice)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
qof_instance_set_dirty(&invoice->inst);
|
|
|
|
qof_event_gen (&invoice->inst, QOF_EVENT_MODIFY, NULL);
|
2002-03-02 12:55:01 -06:00
|
|
|
}
|
|
|
|
|
2006-10-15 14:02:05 -05:00
|
|
|
QofBook * gncInvoiceGetBook(GncInvoice *x)
|
|
|
|
{
|
|
|
|
return qof_instance_get_book(QOF_INSTANCE(x));
|
|
|
|
}
|
|
|
|
|
2003-10-21 21:02:45 -05:00
|
|
|
/* ================================================================== */
|
2010-02-28 13:15:46 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
enum
|
|
|
|
{
|
2010-02-28 13:15:46 -06:00
|
|
|
PROP_0,
|
2010-03-02 15:41:05 -06:00
|
|
|
PROP_NOTES
|
2010-02-28 13:15:46 -06:00
|
|
|
};
|
|
|
|
|
2007-04-04 21:44:01 -05:00
|
|
|
/* GObject Initialization */
|
2010-02-28 13:15:46 -06:00
|
|
|
G_DEFINE_TYPE(GncInvoice, gnc_invoice, QOF_TYPE_INSTANCE);
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2007-04-04 21:44:01 -05:00
|
|
|
static void
|
|
|
|
gnc_invoice_init(GncInvoice* inv)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2007-04-04 22:10:26 -05:00
|
|
|
static void
|
2010-02-28 13:15:46 -06:00
|
|
|
gnc_invoice_dispose(GObject *invp)
|
|
|
|
{
|
|
|
|
G_OBJECT_CLASS(gnc_invoice_parent_class)->dispose(invp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gnc_invoice_finalize(GObject* invp)
|
|
|
|
{
|
|
|
|
G_OBJECT_CLASS(gnc_invoice_parent_class)->finalize(invp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gnc_invoice_get_property (GObject *object,
|
2010-03-02 15:41:05 -06:00
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2010-02-28 13:15:46 -06:00
|
|
|
{
|
|
|
|
GncInvoice *inv;
|
|
|
|
|
|
|
|
g_return_if_fail(GNC_IS_INVOICE(object));
|
|
|
|
|
|
|
|
inv = GNC_INVOICE(object);
|
2010-03-02 15:41:05 -06:00
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_NOTES:
|
|
|
|
g_value_set_string(value, inv->notes);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
|
|
break;
|
2010-02-28 13:15:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gnc_invoice_set_property (GObject *object,
|
2010-03-02 15:41:05 -06:00
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2007-04-04 22:10:26 -05:00
|
|
|
{
|
2010-02-28 13:15:46 -06:00
|
|
|
GncInvoice *inv;
|
|
|
|
|
|
|
|
g_return_if_fail(GNC_IS_INVOICE(object));
|
|
|
|
|
|
|
|
inv = GNC_INVOICE(object);
|
2010-03-02 15:41:05 -06:00
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_NOTES:
|
|
|
|
gncInvoiceSetNotes(inv, g_value_get_string(value));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
|
|
break;
|
2010-02-28 13:15:46 -06:00
|
|
|
}
|
2007-04-04 22:10:26 -05:00
|
|
|
}
|
|
|
|
|
2010-03-12 04:16:16 -06:00
|
|
|
/** Returns a string representing this object */
|
|
|
|
static gchar*
|
|
|
|
impl_get_display_name(const QofInstance* inst)
|
|
|
|
{
|
|
|
|
GncInvoice* inv;
|
|
|
|
QofInstance* owner;
|
|
|
|
gchar* s;
|
|
|
|
|
|
|
|
g_return_val_if_fail(inst != NULL, FALSE);
|
|
|
|
g_return_val_if_fail(GNC_IS_INVOICE(inst), FALSE);
|
|
|
|
|
|
|
|
inv = GNC_INVOICE(inst);
|
|
|
|
owner = qofOwnerGetOwner(&inv->owner);
|
|
|
|
if (owner != NULL)
|
|
|
|
{
|
|
|
|
gchar* display_name;
|
|
|
|
|
|
|
|
display_name = qof_instance_get_display_name(owner);
|
|
|
|
s = g_strdup_printf("Invoice %s (%s)", inv->id, display_name);
|
|
|
|
g_free(display_name);
|
|
|
|
}
|
2010-03-27 16:01:56 -05:00
|
|
|
else
|
|
|
|
{
|
2010-03-12 04:16:16 -06:00
|
|
|
s = g_strdup_printf("Invoice %s", inv->id);
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Does this object refer to a specific object */
|
|
|
|
static gboolean
|
|
|
|
impl_refers_to_object(const QofInstance* inst, const QofInstance* ref)
|
|
|
|
{
|
|
|
|
GncInvoice* inv;
|
|
|
|
|
|
|
|
g_return_val_if_fail(inst != NULL, FALSE);
|
|
|
|
g_return_val_if_fail(GNC_IS_INVOICE(inst), FALSE);
|
|
|
|
|
|
|
|
inv = GNC_INVOICE(inst);
|
|
|
|
|
|
|
|
if (GNC_IS_BILLTERM(ref))
|
|
|
|
{
|
|
|
|
return (inv->terms == GNC_BILLTERM(ref));
|
|
|
|
}
|
|
|
|
else if (GNC_IS_JOB(ref))
|
|
|
|
{
|
|
|
|
return (inv->job == GNC_JOB(ref));
|
|
|
|
}
|
|
|
|
else if (GNC_IS_COMMODITY(ref))
|
|
|
|
{
|
|
|
|
return (inv->currency == GNC_COMMODITY(ref));
|
|
|
|
}
|
|
|
|
else if (GNC_IS_ACCOUNT(ref))
|
|
|
|
{
|
|
|
|
return (inv->posted_acc == GNC_ACCOUNT(ref));
|
|
|
|
}
|
|
|
|
else if (GNC_IS_TRANSACTION(ref))
|
|
|
|
{
|
|
|
|
return (inv->posted_txn == GNC_TRANSACTION(ref));
|
|
|
|
}
|
|
|
|
else if (GNC_IS_LOT(ref))
|
|
|
|
{
|
|
|
|
return (inv->posted_lot == GNC_LOT(ref));
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns a list of my type of object which refers to an object. For example, when called as
|
|
|
|
qof_instance_get_typed_referring_object_list(taxtable, account);
|
|
|
|
it will return the list of taxtables which refer to a specific account. The result should be the
|
|
|
|
same regardless of which taxtable object is used. The list must be freed by the caller but the
|
|
|
|
objects on the list must not.
|
|
|
|
*/
|
|
|
|
static GList*
|
|
|
|
impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
|
|
|
|
{
|
|
|
|
if (!GNC_IS_BILLTERM(ref) && !GNC_IS_JOB(ref) && !GNC_IS_COMMODITY(ref) && !GNC_IS_ACCOUNT(ref)
|
|
|
|
&& !GNC_IS_TRANSACTION(ref) && !GNC_IS_LOT(ref))
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return qof_instance_get_referring_object_list_from_collection(qof_instance_get_collection(inst), ref);
|
|
|
|
}
|
|
|
|
|
2007-04-04 21:44:01 -05:00
|
|
|
static void
|
2010-02-28 13:15:46 -06:00
|
|
|
gnc_invoice_class_init (GncInvoiceClass *klass)
|
2007-04-04 21:44:01 -05:00
|
|
|
{
|
2010-02-28 13:15:46 -06:00
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
2010-03-12 04:16:16 -06:00
|
|
|
QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
|
2010-03-02 15:41:05 -06:00
|
|
|
|
2010-02-28 13:15:46 -06:00
|
|
|
gobject_class->dispose = gnc_invoice_dispose;
|
|
|
|
gobject_class->finalize = gnc_invoice_finalize;
|
|
|
|
gobject_class->set_property = gnc_invoice_set_property;
|
|
|
|
gobject_class->get_property = gnc_invoice_get_property;
|
|
|
|
|
2010-03-12 04:16:16 -06:00
|
|
|
qof_class->get_display_name = impl_get_display_name;
|
|
|
|
qof_class->refers_to_object = impl_refers_to_object;
|
|
|
|
qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
|
|
|
|
|
2010-02-28 13:15:46 -06:00
|
|
|
g_object_class_install_property
|
2010-03-02 15:41:05 -06:00
|
|
|
(gobject_class,
|
|
|
|
PROP_NOTES,
|
|
|
|
g_param_spec_string ("notes",
|
|
|
|
"Invoice Notes",
|
|
|
|
"The invoice notes is an arbitrary string "
|
|
|
|
"assigned by the user to provide notes regarding "
|
|
|
|
"this invoice.",
|
|
|
|
NULL,
|
|
|
|
G_PARAM_READWRITE));
|
2007-04-04 21:44:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Create/Destroy Functions */
|
2003-06-26 22:05:25 -05:00
|
|
|
GncInvoice *gncInvoiceCreate (QofBook *book)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncInvoice *invoice;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!book) return NULL;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice = g_object_new (GNC_TYPE_INVOICE, NULL);
|
|
|
|
qof_instance_init_data (&invoice->inst, _GNC_MOD_NAME, book);
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->id = CACHE_INSERT ("");
|
|
|
|
invoice->notes = CACHE_INSERT ("");
|
|
|
|
invoice->billing_id = CACHE_INSERT ("");
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->billto.type = GNC_OWNER_CUSTOMER;
|
|
|
|
invoice->active = TRUE;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->to_charge_amount = gnc_numeric_zero();
|
2003-04-01 15:15:22 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
qof_event_gen (&invoice->inst, QOF_EVENT_CREATE, NULL);
|
2002-03-02 12:55:01 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
return invoice;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void gncInvoiceDestroy (GncInvoice *invoice)
|
2002-11-03 14:21:42 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
qof_instance_set_destroying(invoice, TRUE);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2002-11-03 14:21:42 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void gncInvoiceFree (GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
qof_event_gen (&invoice->inst, QOF_EVENT_DESTROY, NULL);
|
2002-03-02 12:55:01 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
CACHE_REMOVE (invoice->id);
|
|
|
|
CACHE_REMOVE (invoice->notes);
|
|
|
|
CACHE_REMOVE (invoice->billing_id);
|
|
|
|
g_list_free (invoice->entries);
|
|
|
|
g_list_free (invoice->prices);
|
2001-11-24 23:34:34 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (invoice->printname) g_free (invoice->printname);
|
2002-02-23 22:01:57 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (invoice->terms)
|
|
|
|
gncBillTermDecRef (invoice->terms);
|
2003-06-14 00:17:07 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* qof_instance_release (&invoice->inst); */
|
|
|
|
g_object_unref (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2003-10-21 21:02:45 -05:00
|
|
|
GncInvoice *
|
|
|
|
gncCloneInvoice (GncInvoice *from, QofBook *book)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GList *node;
|
|
|
|
GncInvoice *invoice;
|
2003-10-21 21:02:45 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!book) return NULL;
|
2003-10-21 21:02:45 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice = g_object_new (GNC_TYPE_INVOICE, NULL);
|
|
|
|
qof_instance_init_data (&invoice->inst, _GNC_MOD_NAME, book);
|
2003-10-21 21:02:45 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->id = CACHE_INSERT (from->id);
|
|
|
|
invoice->notes = CACHE_INSERT (from->notes);
|
|
|
|
invoice->billing_id = CACHE_INSERT (from->billing_id);
|
|
|
|
invoice->active = from->active;
|
2003-10-21 21:02:45 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->billto = gncCloneOwner (&from->billto, book);
|
|
|
|
invoice->owner = gncCloneOwner (&from->owner, book);
|
|
|
|
invoice->job = (GncJob*)gncJobObtainTwin (from->job, book);
|
|
|
|
invoice->terms = gncBillTermObtainTwin (from->terms, book);
|
|
|
|
gncBillTermIncRef (invoice->terms);
|
2003-10-21 21:02:45 -05:00
|
|
|
|
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->to_charge_amount = from->to_charge_amount;
|
|
|
|
invoice->printname = NULL; /* that's right, NULL. See below. */
|
|
|
|
invoice->date_opened = from->date_opened;
|
|
|
|
invoice->date_posted = from->date_posted;
|
2003-10-21 21:02:45 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->currency = gnc_commodity_obtain_twin (from->currency, book);
|
2003-10-21 21:02:45 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->entries = NULL;
|
|
|
|
for (node = g_list_last(from->entries); node; node = node->next)
|
|
|
|
{
|
|
|
|
GncEntry *entry = node->data;
|
|
|
|
entry = gncEntryObtainTwin (entry, book);
|
|
|
|
invoice->entries = g_list_prepend (invoice->entries, entry);
|
|
|
|
}
|
2003-10-21 21:02:45 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->prices = NULL;
|
|
|
|
for (node = g_list_last(from->prices); node; node = node->next)
|
|
|
|
{
|
|
|
|
GNCPrice *price = node->data;
|
|
|
|
price = gnc_price_clone(price, book);
|
|
|
|
invoice->prices = g_list_prepend (invoice->prices, price);
|
|
|
|
}
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* XXX should probably be obtain-twin not lookup-twin */
|
|
|
|
invoice->posted_acc =
|
|
|
|
GNC_ACCOUNT(qof_instance_lookup_twin(QOF_INSTANCE(from->posted_acc), book));
|
2003-10-21 21:02:45 -05:00
|
|
|
#if 0
|
2010-03-02 15:41:05 -06:00
|
|
|
XXX not done * /
|
|
|
|
Transaction * posted_txn;
|
|
|
|
GNCLot * posted_lot;
|
2003-10-21 21:02:45 -05:00
|
|
|
#endif
|
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
qof_event_gen (&invoice->inst, QOF_EVENT_CREATE, NULL);
|
2003-10-21 21:02:45 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
return invoice;
|
2003-10-21 21:02:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
GncInvoice *
|
|
|
|
gncInvoiceObtainTwin (GncInvoice *from, QofBook *book)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncInvoice *invoice;
|
|
|
|
if (!book) return NULL;
|
2003-10-21 21:02:45 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice = (GncInvoice *) qof_instance_lookup_twin (QOF_INSTANCE(from), book);
|
|
|
|
if (!invoice)
|
|
|
|
{
|
|
|
|
invoice = gncCloneInvoice (from, book);
|
|
|
|
}
|
2003-10-21 21:02:45 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
return invoice;
|
2003-10-21 21:02:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ================================================================== */
|
2003-10-16 23:32:04 -05:00
|
|
|
/* Set Functions */
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
void gncInvoiceSetID (GncInvoice *invoice, const char *id)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !id) return;
|
|
|
|
SET_STR (invoice, invoice->id, id);
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2001-12-05 23:46:42 -06:00
|
|
|
void gncInvoiceSetOwner (GncInvoice *invoice, GncOwner *owner)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !owner) return;
|
|
|
|
if (gncOwnerEqual (&invoice->owner, owner)) return;
|
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
gncOwnerCopy (owner, &invoice->owner);
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
static void
|
2007-04-01 17:18:50 -05:00
|
|
|
qofInvoiceSetOwner (GncInvoice *invoice, QofInstance *ent)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !ent)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
qofOwnerSetEntity(&invoice->owner, ent);
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-04-01 17:18:50 -05:00
|
|
|
qofInvoiceSetBillTo (GncInvoice *invoice, QofInstance *ent)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !ent)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
qofOwnerSetEntity(&invoice->billto, ent);
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2002-02-26 17:42:11 -06:00
|
|
|
void gncInvoiceSetDateOpened (GncInvoice *invoice, Timespec date)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
if (timespec_equal (&invoice->date_opened, &date)) return;
|
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
invoice->date_opened = date;
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2002-02-26 17:42:11 -06:00
|
|
|
void gncInvoiceSetDatePosted (GncInvoice *invoice, Timespec date)
|
2002-02-10 19:59:54 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
if (timespec_equal (&invoice->date_posted, &date)) return;
|
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
invoice->date_posted = date;
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2002-02-10 19:59:54 -06:00
|
|
|
}
|
|
|
|
|
2002-06-21 21:38:13 -05:00
|
|
|
void gncInvoiceSetTerms (GncInvoice *invoice, GncBillTerm *terms)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
if (invoice->terms == terms) return;
|
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
if (invoice->terms)
|
|
|
|
gncBillTermDecRef (invoice->terms);
|
|
|
|
invoice->terms = terms;
|
|
|
|
if (invoice->terms)
|
|
|
|
gncBillTermIncRef (invoice->terms);
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2002-05-08 15:42:38 -05:00
|
|
|
void gncInvoiceSetBillingID (GncInvoice *invoice, const char *billing_id)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
SET_STR (invoice, invoice->billing_id, billing_id);
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void gncInvoiceSetNotes (GncInvoice *invoice, const char *notes)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !notes) return;
|
|
|
|
SET_STR (invoice, invoice->notes, notes);
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void gncInvoiceSetActive (GncInvoice *invoice, gboolean active)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
if (invoice->active == active) return;
|
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
invoice->active = active;
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2003-01-12 16:07:33 -06:00
|
|
|
void gncInvoiceSetCurrency (GncInvoice *invoice, gnc_commodity *currency)
|
2002-03-04 13:34:52 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !currency) return;
|
|
|
|
if (invoice->currency &&
|
|
|
|
gnc_commodity_equal (invoice->currency, currency))
|
|
|
|
return;
|
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
invoice->currency = currency;
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2002-03-04 13:34:52 -06:00
|
|
|
}
|
|
|
|
|
2002-07-10 16:07:46 -05:00
|
|
|
void gncInvoiceSetBillTo (GncInvoice *invoice, GncOwner *billto)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !billto) return;
|
|
|
|
if (gncOwnerEqual (&invoice->billto, billto)) return;
|
2002-07-10 16:07:46 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
gncOwnerCopy (billto, &invoice->billto);
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2002-07-10 16:07:46 -05:00
|
|
|
}
|
|
|
|
|
2003-04-01 15:15:22 -06:00
|
|
|
void gncInvoiceSetToChargeAmount (GncInvoice *invoice, gnc_numeric amount)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
if (gnc_numeric_equal (invoice->to_charge_amount, amount)) return;
|
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
invoice->to_charge_amount = amount;
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2003-04-01 15:15:22 -06:00
|
|
|
}
|
|
|
|
|
2001-11-23 23:35:08 -06:00
|
|
|
void gncInvoiceSetPostedTxn (GncInvoice *invoice, Transaction *txn)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
g_return_if_fail (invoice->posted_txn == NULL);
|
2001-11-23 23:35:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
invoice->posted_txn = txn;
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2001-11-23 23:35:08 -06:00
|
|
|
}
|
|
|
|
|
2002-06-24 17:30:36 -05:00
|
|
|
void gncInvoiceSetPostedLot (GncInvoice *invoice, GNCLot *lot)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
g_return_if_fail (invoice->posted_lot == NULL);
|
2002-06-24 17:30:36 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
invoice->posted_lot = lot;
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2002-06-24 17:30:36 -05:00
|
|
|
}
|
|
|
|
|
2001-11-23 23:35:08 -06:00
|
|
|
void gncInvoiceSetPostedAcc (GncInvoice *invoice, Account *acc)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
g_return_if_fail (invoice->posted_acc == NULL);
|
2001-11-23 23:35:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
invoice->posted_acc = acc;
|
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2001-11-23 23:35:08 -06:00
|
|
|
}
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
void gncInvoiceAddEntry (GncInvoice *invoice, GncEntry *entry)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncInvoice *old;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !entry) return;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
old = gncEntryGetInvoice (entry);
|
|
|
|
if (old == invoice) return; /* I already own this one */
|
|
|
|
if (old) gncInvoiceRemoveEntry (old, entry);
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
gncEntrySetInvoice (entry, invoice);
|
|
|
|
invoice->entries = g_list_insert_sorted (invoice->entries, entry,
|
|
|
|
(GCompareFunc)gncEntryCompare);
|
|
|
|
mark_invoice (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void gncInvoiceRemoveEntry (GncInvoice *invoice, GncEntry *entry)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !entry) return;
|
2001-11-21 19:23:07 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
gncEntrySetInvoice (entry, NULL);
|
|
|
|
invoice->entries = g_list_remove (invoice->entries, entry);
|
|
|
|
mark_invoice (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2008-11-26 07:06:44 -06:00
|
|
|
void gncInvoiceAddPrice (GncInvoice *invoice, GNCPrice *price)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !price) return;
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->prices = g_list_prepend(invoice->prices, price);
|
|
|
|
mark_invoice (invoice);
|
2008-11-26 07:06:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void gncInvoiceRemovePrice (GncInvoice *invoice, GNCPrice *price)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !price) return;
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->prices = g_list_remove (invoice->prices, price);
|
|
|
|
mark_invoice (invoice);
|
2008-11-26 07:06:44 -06:00
|
|
|
}
|
|
|
|
|
2002-07-09 23:12:19 -05:00
|
|
|
void gncBillAddEntry (GncInvoice *bill, GncEntry *entry)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncInvoice *old;
|
2002-07-09 23:12:19 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!bill || !entry) return;
|
2002-07-09 23:12:19 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
old = gncEntryGetBill (entry);
|
|
|
|
if (old == bill) return; /* I already own this one */
|
|
|
|
if (old) gncBillRemoveEntry (old, entry);
|
2002-07-09 23:12:19 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
gncEntrySetBill (entry, bill);
|
|
|
|
bill->entries = g_list_insert_sorted (bill->entries, entry,
|
|
|
|
(GCompareFunc)gncEntryCompare);
|
|
|
|
mark_invoice (bill);
|
2002-07-09 23:12:19 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void gncBillRemoveEntry (GncInvoice *bill, GncEntry *entry)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!bill || !entry) return;
|
2002-07-09 23:12:19 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
gncEntrySetBill (entry, NULL);
|
|
|
|
bill->entries = g_list_remove (bill->entries, entry);
|
|
|
|
mark_invoice (bill);
|
2002-07-09 23:12:19 -05:00
|
|
|
}
|
|
|
|
|
2008-11-26 07:06:44 -06:00
|
|
|
void gncBillAddPrice (GncInvoice *bill, GNCPrice *price)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!bill || !price) return;
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
bill->prices = g_list_prepend(bill->prices, price);
|
|
|
|
mark_invoice (bill);
|
2008-11-26 07:06:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void gncBillRemovePrice (GncInvoice *bill, GNCPrice *price)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!bill || !price) return;
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
bill->prices = g_list_remove (bill->prices, price);
|
|
|
|
mark_invoice (bill);
|
2008-11-26 07:06:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-01 15:49:06 -06:00
|
|
|
void gncInvoiceSortEntries (GncInvoice *invoice)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return;
|
|
|
|
invoice->entries = g_list_sort(invoice->entries,
|
|
|
|
(GCompareFunc)gncEntryCompare);
|
|
|
|
mark_invoice(invoice);
|
2006-02-01 15:49:06 -06:00
|
|
|
}
|
|
|
|
|
2003-10-21 21:02:45 -05:00
|
|
|
/* ================================================================== */
|
2001-11-21 19:23:07 -06:00
|
|
|
/* Get Functions */
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
const char * gncInvoiceGetID (const GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->id;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2001-12-05 23:46:42 -06:00
|
|
|
GncOwner * gncInvoiceGetOwner (GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return &invoice->owner;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2007-04-01 17:18:50 -05:00
|
|
|
static QofInstance*
|
2005-11-01 21:32:36 -06:00
|
|
|
qofInvoiceGetOwner (GncInvoice *invoice)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncOwner *owner;
|
2007-04-07 13:24:53 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
owner = &invoice->owner;
|
|
|
|
return QOF_INSTANCE(owner);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2007-04-01 17:18:50 -05:00
|
|
|
static QofInstance*
|
2005-11-01 21:32:36 -06:00
|
|
|
qofInvoiceGetBillTo (GncInvoice *invoice)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncOwner *billto;
|
2007-04-07 13:24:53 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
billto = &invoice->billto;
|
|
|
|
return QOF_INSTANCE(billto);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
Timespec gncInvoiceGetDateOpened (const GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
Timespec ts;
|
|
|
|
ts.tv_sec = 0;
|
|
|
|
ts.tv_nsec = 0;
|
|
|
|
if (!invoice) return ts;
|
|
|
|
return invoice->date_opened;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
Timespec gncInvoiceGetDatePosted (const GncInvoice *invoice)
|
2002-02-10 19:59:54 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
Timespec ts;
|
|
|
|
ts.tv_sec = 0;
|
|
|
|
ts.tv_nsec = 0;
|
|
|
|
if (!invoice) return ts;
|
|
|
|
return invoice->date_posted;
|
2002-02-10 19:59:54 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
Timespec gncInvoiceGetDateDue (const GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
Transaction *txn;
|
|
|
|
Timespec ts;
|
|
|
|
ts.tv_sec = 0;
|
|
|
|
ts.tv_nsec = 0;
|
|
|
|
if (!invoice) return ts;
|
|
|
|
txn = gncInvoiceGetPostedTxn (invoice);
|
|
|
|
if (!txn) return ts;
|
|
|
|
return xaccTransRetDateDueTS (txn);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
GncBillTerm * gncInvoiceGetTerms (const GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->terms;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
const char * gncInvoiceGetBillingID (const GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->billing_id;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
const char * gncInvoiceGetNotes (const GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->notes;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2008-11-26 07:06:44 -06:00
|
|
|
GncOwnerType gncInvoiceGetOwnerType (GncInvoice *invoice)
|
2002-05-16 17:45:50 -05:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncOwner *owner;
|
|
|
|
g_return_val_if_fail (invoice, GNC_OWNER_NONE);
|
2002-05-16 17:45:50 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice));
|
|
|
|
return (gncOwnerGetType (owner));
|
2002-05-16 17:45:50 -05:00
|
|
|
}
|
|
|
|
|
2003-05-29 11:21:38 -05:00
|
|
|
static gnc_numeric
|
|
|
|
gncInvoiceGetTotalInternal (GncInvoice *invoice, gboolean use_value,
|
2010-03-02 15:41:05 -06:00
|
|
|
gboolean use_tax,
|
|
|
|
gboolean use_payment_type, GncEntryPaymentType type)
|
2002-10-27 20:23:08 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GList *node;
|
|
|
|
gnc_numeric total = gnc_numeric_zero();
|
|
|
|
gboolean reverse;
|
2002-10-27 20:23:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
g_return_val_if_fail (invoice, total);
|
2002-10-27 20:23:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
reverse = (gncInvoiceGetOwnerType (invoice) == GNC_OWNER_CUSTOMER);
|
2002-10-27 20:23:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
for (node = gncInvoiceGetEntries(invoice); node; node = node->next)
|
|
|
|
{
|
|
|
|
GncEntry *entry = node->data;
|
|
|
|
gnc_numeric value, tax;
|
2002-10-27 20:23:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (use_payment_type && gncEntryGetBillPayment (entry) != type)
|
|
|
|
continue;
|
2003-05-29 11:21:38 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
gncEntryGetValue (entry, reverse, &value, NULL, &tax, NULL);
|
2002-10-27 20:23:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (gnc_numeric_check (value) == GNC_ERROR_OK)
|
|
|
|
{
|
|
|
|
if (use_value)
|
2010-08-26 12:22:06 -05:00
|
|
|
total = gnc_numeric_add (total, value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
|
2010-03-02 15:41:05 -06:00
|
|
|
}
|
|
|
|
else
|
|
|
|
g_warning ("bad value in our entry");
|
|
|
|
|
|
|
|
if (gnc_numeric_check (tax) == GNC_ERROR_OK)
|
|
|
|
{
|
|
|
|
if (use_tax)
|
2010-08-26 12:22:06 -05:00
|
|
|
total = gnc_numeric_add (total, tax, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
|
2010-03-02 15:41:05 -06:00
|
|
|
}
|
|
|
|
else
|
|
|
|
g_warning ("bad tax-value in our entry");
|
|
|
|
}
|
|
|
|
return total;
|
2002-10-27 20:23:08 -06:00
|
|
|
}
|
|
|
|
|
2003-05-29 11:21:38 -05:00
|
|
|
gnc_numeric gncInvoiceGetTotal (GncInvoice *invoice)
|
2003-04-01 15:15:22 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return gnc_numeric_zero();
|
|
|
|
return gncInvoiceGetTotalInternal(invoice, TRUE, TRUE, FALSE, 0);
|
2003-05-29 11:21:38 -05:00
|
|
|
}
|
2003-04-01 15:15:22 -06:00
|
|
|
|
2003-05-29 11:21:38 -05:00
|
|
|
gnc_numeric gncInvoiceGetTotalSubtotal (GncInvoice *invoice)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return gnc_numeric_zero();
|
|
|
|
return gncInvoiceGetTotalInternal(invoice, TRUE, FALSE, FALSE, 0);
|
2003-05-29 11:21:38 -05:00
|
|
|
}
|
2003-04-01 15:15:22 -06:00
|
|
|
|
2003-05-29 11:21:38 -05:00
|
|
|
gnc_numeric gncInvoiceGetTotalTax (GncInvoice *invoice)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return gnc_numeric_zero();
|
|
|
|
return gncInvoiceGetTotalInternal(invoice, FALSE, TRUE, FALSE, 0);
|
2003-05-29 11:21:38 -05:00
|
|
|
}
|
2003-04-01 15:15:22 -06:00
|
|
|
|
2003-05-29 11:21:38 -05:00
|
|
|
gnc_numeric gncInvoiceGetTotalOf (GncInvoice *invoice, GncEntryPaymentType type)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return gnc_numeric_zero();
|
|
|
|
return gncInvoiceGetTotalInternal(invoice, TRUE, TRUE, TRUE, type);
|
2003-04-01 15:15:22 -06:00
|
|
|
}
|
|
|
|
|
2010-05-06 10:15:36 -05:00
|
|
|
const char * gncInvoiceGetTypeFromOwnerType (GncOwnerType type)
|
2002-05-16 17:45:50 -05:00
|
|
|
{
|
2010-05-06 10:15:36 -05:00
|
|
|
switch (type)
|
2010-03-02 15:41:05 -06:00
|
|
|
{
|
|
|
|
case GNC_OWNER_CUSTOMER:
|
|
|
|
return _("Invoice");
|
|
|
|
case GNC_OWNER_VENDOR:
|
|
|
|
return _("Bill");
|
|
|
|
case GNC_OWNER_EMPLOYEE:
|
|
|
|
return _("Expense");
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-05-06 10:15:36 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const char * gncInvoiceGetType (GncInvoice *invoice)
|
|
|
|
{
|
|
|
|
if (!invoice) return NULL;
|
|
|
|
return gncInvoiceGetTypeFromOwnerType (gncInvoiceGetOwnerType (invoice));
|
2002-05-16 17:45:50 -05:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
gnc_commodity * gncInvoiceGetCurrency (const GncInvoice *invoice)
|
2002-03-04 13:34:52 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->currency;
|
2002-03-04 13:34:52 -06:00
|
|
|
}
|
|
|
|
|
2002-07-10 16:07:46 -05:00
|
|
|
GncOwner * gncInvoiceGetBillTo (GncInvoice *invoice)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return &invoice->billto;
|
2002-07-10 16:07:46 -05:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
GNCLot * gncInvoiceGetPostedLot (const GncInvoice *invoice)
|
2002-06-25 10:08:50 -05:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->posted_lot;
|
2002-06-25 10:08:50 -05:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
Transaction * gncInvoiceGetPostedTxn (const GncInvoice *invoice)
|
2001-11-23 23:35:08 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->posted_txn;
|
2001-11-23 23:35:08 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
Account * gncInvoiceGetPostedAcc (const GncInvoice *invoice)
|
2001-11-23 23:35:08 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->posted_acc;
|
2001-11-23 23:35:08 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
gboolean gncInvoiceGetActive (const GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return FALSE;
|
|
|
|
return invoice->active;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2004-10-15 21:49:29 -05:00
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
gnc_numeric gncInvoiceGetToChargeAmount (const GncInvoice *invoice)
|
2003-04-01 15:15:22 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return gnc_numeric_zero();
|
|
|
|
return invoice->to_charge_amount;
|
2003-04-01 15:15:22 -06:00
|
|
|
}
|
|
|
|
|
2006-10-15 14:02:05 -05:00
|
|
|
EntryList * gncInvoiceGetEntries (GncInvoice *invoice)
|
2001-11-21 19:23:07 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->entries;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2008-11-26 07:06:44 -06:00
|
|
|
GList * gncInvoiceGetPrices(GncInvoice *invoice)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return NULL;
|
|
|
|
return invoice->prices;
|
2008-11-26 07:06:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
GNCPrice * gncInvoiceGetPrice(GncInvoice *invoice, gnc_commodity *commodity)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GList *node = g_list_first(invoice->prices);
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
while (node != NULL)
|
|
|
|
{
|
|
|
|
GNCPrice *curr = (GNCPrice*)node->data;
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (gnc_commodity_equal(commodity, gnc_price_get_commodity(curr)))
|
|
|
|
return curr;
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
node = g_list_next(node);
|
|
|
|
}
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
return NULL;
|
2008-11-26 07:06:44 -06:00
|
|
|
}
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
static QofCollection*
|
|
|
|
qofInvoiceGetEntries (GncInvoice *invoice)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
QofCollection *entry_coll;
|
|
|
|
GList *list;
|
|
|
|
QofInstance *entry;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
entry_coll = qof_collection_new(GNC_ID_ENTRY);
|
|
|
|
for (list = gncInvoiceGetEntries(invoice); list != NULL; list = list->next)
|
|
|
|
{
|
|
|
|
entry = QOF_INSTANCE(list->data);
|
|
|
|
qof_collection_add_entity(entry_coll, entry);
|
|
|
|
}
|
|
|
|
return entry_coll;
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-04-01 17:18:50 -05:00
|
|
|
qofInvoiceEntryCB (QofInstance *ent, gpointer user_data)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncInvoice *invoice;
|
|
|
|
|
|
|
|
invoice = (GncInvoice*)user_data;
|
|
|
|
if (!invoice || !ent)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (gncInvoiceGetOwnerType (invoice))
|
|
|
|
{
|
|
|
|
case GNC_OWNER_VENDOR:
|
|
|
|
{
|
|
|
|
gncBillAddEntry (invoice, (GncEntry*) ent);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default :
|
|
|
|
{
|
|
|
|
gncInvoiceAddEntry(invoice, (GncEntry*)ent);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
static void
|
2005-11-01 21:32:36 -06:00
|
|
|
qofInvoiceSetEntries(GncInvoice *invoice, QofCollection *entry_coll)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!entry_coll)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (0 == safe_strcmp(qof_collection_get_type(entry_coll), GNC_ID_ENTRY))
|
|
|
|
{
|
|
|
|
qof_collection_foreach(entry_coll, qofInvoiceEntryCB, invoice);
|
|
|
|
}
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static GncJob*
|
2008-08-01 11:02:07 -05:00
|
|
|
qofInvoiceGetJob (const GncInvoice *invoice)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return invoice->job;
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
static void
|
2005-11-01 21:32:36 -06:00
|
|
|
qofInvoiceSetJob (GncInvoice *invoice, GncJob *job)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
invoice->job = job;
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2002-06-24 17:30:36 -05:00
|
|
|
static void
|
2003-01-01 22:07:58 -06:00
|
|
|
gncInvoiceDetachFromLot (GNCLot *lot)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
KvpFrame *kvp;
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!lot) return;
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
kvp = gnc_lot_get_slots (lot);
|
|
|
|
kvp_frame_set_slot_path (kvp, NULL, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
|
2003-01-01 22:07:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gncInvoiceAttachToLot (GncInvoice *invoice, GNCLot *lot)
|
2002-06-24 17:30:36 -05:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
KvpFrame *kvp;
|
|
|
|
KvpValue *value;
|
|
|
|
|
|
|
|
if (!invoice || !lot)
|
|
|
|
return;
|
2002-06-24 17:30:36 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (invoice->posted_lot) return; /* Cannot reset invoice's lot */
|
2002-06-24 17:30:36 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
kvp = gnc_lot_get_slots (lot);
|
|
|
|
value = kvp_value_new_guid (qof_instance_get_guid (QOF_INSTANCE(invoice)));
|
|
|
|
kvp_frame_set_slot_path (kvp, value, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
|
|
|
|
kvp_value_delete (value);
|
|
|
|
gncInvoiceSetPostedLot (invoice, lot);
|
2002-06-24 17:30:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
GncInvoice * gncInvoiceGetInvoiceFromLot (GNCLot *lot)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
KvpFrame *kvp;
|
|
|
|
KvpValue *value;
|
2010-03-27 16:01:21 -05:00
|
|
|
GncGUID *guid;
|
2010-03-02 15:41:05 -06:00
|
|
|
QofBook *book;
|
2002-06-24 17:30:36 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!lot) return NULL;
|
2002-06-24 17:30:36 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
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;
|
2002-06-24 17:30:36 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
guid = kvp_value_get_guid (value);
|
|
|
|
return gncInvoiceLookup(book, guid);
|
2002-06-24 17:30:36 -05:00
|
|
|
}
|
|
|
|
|
2002-02-10 19:59:54 -06:00
|
|
|
static void
|
2003-01-01 22:07:58 -06:00
|
|
|
gncInvoiceAttachToTxn (GncInvoice *invoice, Transaction *txn)
|
2001-11-23 23:35:08 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
KvpFrame *kvp;
|
|
|
|
KvpValue *value;
|
2001-11-23 23:35:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !txn)
|
|
|
|
return;
|
2001-11-23 23:35:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (invoice->posted_txn) return; /* Cannot reset invoice's txn */
|
|
|
|
|
|
|
|
xaccTransBeginEdit (txn);
|
|
|
|
kvp = xaccTransGetSlots (txn);
|
|
|
|
value = kvp_value_new_guid (qof_instance_get_guid(QOF_INSTANCE(invoice)));
|
|
|
|
kvp_frame_set_slot_path (kvp, value, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
|
|
|
|
kvp_value_delete (value);
|
|
|
|
xaccTransSetTxnType (txn, TXN_TYPE_INVOICE);
|
|
|
|
xaccTransCommitEdit (txn);
|
|
|
|
gncInvoiceSetPostedTxn (invoice, txn);
|
2001-11-23 23:35:08 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
GncInvoice *
|
2008-08-01 11:02:07 -05:00
|
|
|
gncInvoiceGetInvoiceFromTxn (const Transaction *txn)
|
2002-06-24 17:30:36 -05:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
KvpFrame *kvp;
|
|
|
|
KvpValue *value;
|
2010-03-27 16:01:21 -05:00
|
|
|
GncGUID *guid;
|
2010-03-02 15:41:05 -06:00
|
|
|
QofBook *book;
|
2002-06-24 17:30:36 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!txn) return NULL;
|
2002-06-24 17:30:36 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
book = xaccTransGetBook (txn);
|
|
|
|
kvp = xaccTransGetSlots (txn);
|
|
|
|
value = kvp_frame_get_slot_path (kvp, GNC_INVOICE_ID, GNC_INVOICE_GUID, NULL);
|
|
|
|
if (!value) return NULL;
|
2002-06-24 17:30:36 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
guid = kvp_value_get_guid (value);
|
|
|
|
return gncInvoiceLookup(book, guid);
|
2002-06-24 17:30:36 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
struct lotmatch
|
|
|
|
{
|
|
|
|
GncOwner *owner;
|
|
|
|
gboolean reverse;
|
2002-06-25 10:08:50 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gnc_lot_match_owner_payment (GNCLot *lot, gpointer user_data)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
struct lotmatch *lm = user_data;
|
|
|
|
GncOwner owner_def, *owner;
|
|
|
|
gnc_numeric balance = gnc_lot_get_balance (lot);
|
2002-06-25 10:08:50 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Is this a payment lot */
|
|
|
|
if (gnc_numeric_positive_p (lm->reverse ? balance :
|
|
|
|
gnc_numeric_neg (balance)))
|
|
|
|
return FALSE;
|
2002-06-25 10:08:50 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Is there an invoice attached? */
|
|
|
|
if (gncInvoiceGetInvoiceFromLot (lot))
|
|
|
|
return FALSE;
|
2002-06-25 10:08:50 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Is it ours? */
|
|
|
|
if (!gncOwnerGetOwnerFromLot (lot, &owner_def))
|
|
|
|
return FALSE;
|
|
|
|
owner = gncOwnerGetEndOwner (&owner_def);
|
2002-06-25 10:08:50 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
return gncOwnerEqual (owner, lm->owner);
|
2002-06-25 10:08:50 -05:00
|
|
|
}
|
|
|
|
|
2001-11-23 23:35:08 -06:00
|
|
|
Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
|
2010-03-02 15:41:05 -06:00
|
|
|
Timespec *post_date, Timespec *due_date,
|
|
|
|
const char * memo, gboolean accumulatesplits)
|
|
|
|
{
|
|
|
|
Transaction *txn;
|
|
|
|
QofBook *book;
|
|
|
|
GNCLot *lot = NULL;
|
|
|
|
GList *iter;
|
|
|
|
GList *splitinfo = NULL;
|
|
|
|
gnc_numeric total;
|
|
|
|
gboolean reverse;
|
|
|
|
const char *name, *type;
|
|
|
|
char *lot_title;
|
|
|
|
Account *ccard_acct = NULL;
|
|
|
|
GncOwner *owner;
|
2003-03-10 23:59:51 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice || !acc) return NULL;
|
2001-11-23 23:35:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
gncInvoiceBeginEdit (invoice);
|
|
|
|
book = qof_instance_get_book(invoice);
|
2002-06-16 00:11:33 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Stabilize the Billing Terms of this invoice */
|
|
|
|
if (invoice->terms)
|
|
|
|
gncInvoiceSetTerms (invoice,
|
|
|
|
gncBillTermReturnChild (invoice->terms, TRUE));
|
2001-11-23 23:35:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Figure out if we need to "reverse" the numbers. */
|
|
|
|
reverse = (gncInvoiceGetOwnerType (invoice) == GNC_OWNER_CUSTOMER);
|
2001-11-23 23:35:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* 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));
|
2001-11-23 23:35:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Find an existing payment-lot for this owner */
|
|
|
|
{
|
|
|
|
LotList *lot_list;
|
|
|
|
struct lotmatch lm;
|
2001-11-23 23:35:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
lm.reverse = reverse;
|
|
|
|
lm.owner = owner;
|
2002-05-11 23:39:49 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
lot_list = xaccAccountFindOpenLots (acc, gnc_lot_match_owner_payment,
|
|
|
|
&lm, NULL);
|
|
|
|
if (lot_list)
|
|
|
|
lot = lot_list->data;
|
|
|
|
|
|
|
|
g_list_free (lot_list);
|
|
|
|
}
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* 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 = gncInvoiceGetType (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)
|
2008-11-26 07:06:44 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
xaccTransSetDatePostedTS (txn, post_date);
|
|
|
|
gncInvoiceSetDatePosted (invoice, *post_date);
|
2008-11-26 07:06:44 -06:00
|
|
|
}
|
2010-03-02 15:41:05 -06:00
|
|
|
|
|
|
|
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)
|
2008-11-26 07:06:44 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
gnc_numeric value, tax;
|
|
|
|
GList *taxes;
|
|
|
|
GncEntry * entry = iter->data;
|
|
|
|
Account *this_acc;
|
|
|
|
|
|
|
|
/* Stabilize the TaxTable in this entry */
|
|
|
|
gncEntryBeginEdit (entry);
|
|
|
|
if (reverse)
|
|
|
|
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, reverse, &value, NULL, &tax, &taxes);
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* add the value for the account split */
|
|
|
|
this_acc = (reverse ? gncEntryGetInvAccount (entry) :
|
|
|
|
gncEntryGetBillAccount (entry));
|
|
|
|
if (this_acc)
|
2008-11-26 07:06:44 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
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);
|
|
|
|
|
|
|
|
if (gnc_commodity_equal(xaccAccountGetCommodity(this_acc), invoice->currency))
|
|
|
|
{
|
|
|
|
xaccSplitSetBaseValue (split, (reverse ? 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, (reverse ? gnc_numeric_neg(value) : value));
|
2010-10-23 05:38:48 -05:00
|
|
|
converted_amount = gnc_numeric_div(value, gnc_price_get_value(price), GNC_DENOM_AUTO, GNC_HOW_RND_ROUND_HALF_UP);
|
2010-03-02 15:41:05 -06:00
|
|
|
printf("converting from %f to %f\n", gnc_numeric_to_double(value), gnc_numeric_to_double(converted_amount));
|
|
|
|
xaccSplitSetAmount(split, reverse ? 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, (reverse ? value : gnc_numeric_neg (value)),
|
|
|
|
invoice->currency);
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
2010-08-26 12:22:06 -05:00
|
|
|
total = gnc_numeric_add (total, value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
|
2010-03-02 15:41:05 -06:00
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
g_warning ("bad value in our entry");
|
2008-11-26 07:06:44 -06:00
|
|
|
}
|
2010-03-02 15:41:05 -06:00
|
|
|
|
|
|
|
/* now merge in the TaxValues */
|
|
|
|
splitinfo = gncAccountValueAddList (splitinfo, taxes);
|
|
|
|
|
|
|
|
/* ... and add the tax total */
|
|
|
|
if (gnc_numeric_check (tax) == GNC_ERROR_OK)
|
2010-08-26 12:22:06 -05:00
|
|
|
total = gnc_numeric_add (total, tax, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
|
2008-11-26 07:06:44 -06:00
|
|
|
else
|
2010-03-02 15:41:05 -06:00
|
|
|
g_warning ("bad tax in our entry");
|
|
|
|
|
|
|
|
} /* for */
|
2008-11-26 07:06:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* 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, (reverse ? 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, (reverse ? gnc_numeric_neg(acc_val->value) : acc_val->value));
|
2010-10-23 05:38:48 -05:00
|
|
|
converted_amount = gnc_numeric_div(acc_val->value, gnc_price_get_value(price), GNC_DENOM_AUTO, GNC_HOW_RND_ROUND_HALF_UP);
|
2010-03-02 15:41:05 -06:00
|
|
|
printf("converting from %f to %f\n", gnc_numeric_to_double(acc_val->value), gnc_numeric_to_double(converted_amount));
|
|
|
|
|
|
|
|
xaccSplitSetAmount(split, reverse ? gnc_numeric_neg(converted_amount) : converted_amount);
|
|
|
|
}
|
2008-11-26 07:06:44 -06:00
|
|
|
}
|
|
|
|
}
|
2003-04-01 15:15:22 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* 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, (reverse ? invoice->to_charge_amount :
|
|
|
|
gnc_numeric_neg(invoice->to_charge_amount)),
|
|
|
|
invoice->currency);
|
2003-04-01 15:15:22 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
total = gnc_numeric_sub (total, invoice->to_charge_amount,
|
2010-08-26 12:22:06 -05:00
|
|
|
GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
|
2010-03-02 15:41:05 -06:00
|
|
|
}
|
2002-05-10 19:35:43 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Now create the Posted split (which is negative -- it's a credit) */
|
|
|
|
{
|
|
|
|
Split *split = xaccMallocSplit (book);
|
2002-06-25 10:08:50 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Set action/memo */
|
|
|
|
xaccSplitSetMemo (split, memo);
|
|
|
|
xaccSplitSetAction (split, type);
|
2002-06-25 10:08:50 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
xaccAccountBeginEdit (acc);
|
|
|
|
xaccAccountInsertSplit (acc, split);
|
|
|
|
xaccAccountCommitEdit (acc);
|
|
|
|
xaccTransAppendSplit (txn, split);
|
|
|
|
xaccSplitSetBaseValue (split, (reverse ? 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);
|
2002-06-25 10:08:50 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* 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);
|
2002-06-25 10:08:50 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if ( (gnc_numeric_negative_p (total) && reverse) ||
|
|
|
|
(gnc_numeric_positive_p (total) && !reverse) )
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2002-11-03 18:41:01 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
gnc_lot_commit_edit (lot);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
|
|
|
|
|
|
|
return txn;
|
2001-11-23 23:35:08 -06:00
|
|
|
}
|
|
|
|
|
2003-01-01 22:07:58 -06:00
|
|
|
gboolean
|
2003-05-28 22:02:11 -05:00
|
|
|
gncInvoiceUnpost (GncInvoice *invoice, gboolean reset_tax_tables)
|
2003-01-01 22:07:58 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
Transaction *txn;
|
|
|
|
GNCLot *lot;
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return FALSE;
|
|
|
|
if (!gncInvoiceIsPosted (invoice)) return FALSE;
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
txn = gncInvoiceGetPostedTxn (invoice);
|
|
|
|
g_return_val_if_fail (txn, FALSE);
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
lot = gncInvoiceGetPostedLot (invoice);
|
|
|
|
g_return_val_if_fail (lot, FALSE);
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Destroy the Posted Transaction */
|
|
|
|
xaccTransClearReadOnly (txn);
|
|
|
|
xaccTransBeginEdit (txn);
|
|
|
|
xaccTransDestroy (txn);
|
|
|
|
xaccTransCommitEdit (txn);
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Disconnect the lot from the invoice; re-attach to the invoice owner */
|
|
|
|
gncInvoiceDetachFromLot (lot);
|
|
|
|
gncOwnerAttachToLot (&invoice->owner, lot);
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* If the lot has no splits, then destroy it */
|
|
|
|
if (!gnc_lot_count_splits (lot))
|
|
|
|
gnc_lot_destroy (lot);
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Clear out the invoice posted information */
|
|
|
|
gncInvoiceBeginEdit (invoice);
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->posted_acc = NULL;
|
|
|
|
invoice->posted_txn = NULL;
|
|
|
|
invoice->posted_lot = NULL;
|
|
|
|
invoice->date_posted.tv_sec = invoice->date_posted.tv_nsec = 0;
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* if we've been asked to reset the tax tables, then do so */
|
|
|
|
if (reset_tax_tables)
|
|
|
|
{
|
|
|
|
gboolean reverse = (gncInvoiceGetOwnerType(invoice) == GNC_OWNER_CUSTOMER);
|
|
|
|
GList *iter;
|
2003-05-28 22:02:11 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
for (iter = gncInvoiceGetEntries(invoice); iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
GncEntry *entry = iter->data;
|
|
|
|
|
|
|
|
gncEntryBeginEdit(entry);
|
|
|
|
if (reverse)
|
|
|
|
gncEntrySetInvTaxTable(entry,
|
|
|
|
gncTaxTableGetParent(gncEntryGetInvTaxTable(entry)));
|
|
|
|
else
|
|
|
|
gncEntrySetBillTaxTable(entry,
|
|
|
|
gncTaxTableGetParent(gncEntryGetBillTaxTable(entry)));
|
|
|
|
gncEntryCommitEdit(entry);
|
|
|
|
}
|
2003-05-28 22:02:11 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
mark_invoice (invoice);
|
|
|
|
gncInvoiceCommitEdit (invoice);
|
2003-01-01 22:07:58 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
return TRUE;
|
2003-01-01 22:07:58 -06:00
|
|
|
}
|
|
|
|
|
2003-01-01 20:30:44 -06:00
|
|
|
static gboolean
|
|
|
|
gnc_lot_match_invoice_owner (GNCLot *lot, gpointer user_data)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncOwner owner_def, *owner, *this_owner = user_data;
|
|
|
|
GncInvoice *invoice;
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* If this lot is not for this owner, then ignore it */
|
|
|
|
invoice = gncInvoiceGetInvoiceFromLot (lot);
|
|
|
|
if (invoice)
|
|
|
|
{
|
|
|
|
owner = gncInvoiceGetOwner (invoice);
|
|
|
|
owner = gncOwnerGetEndOwner (owner);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!gncOwnerGetOwnerFromLot (lot, &owner_def))
|
|
|
|
return FALSE;
|
|
|
|
owner = gncOwnerGetEndOwner (&owner_def);
|
|
|
|
}
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
return gncOwnerEqual (owner, this_owner);
|
2003-01-01 20:30:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
gnc_lot_sort_func (GNCLot *a, GNCLot *b)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncInvoice *ia, *ib;
|
|
|
|
Timespec da, db;
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
ia = gncInvoiceGetInvoiceFromLot (a);
|
|
|
|
ib = gncInvoiceGetInvoiceFromLot (b);
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
da = gncInvoiceGetDateDue (ia);
|
|
|
|
db = gncInvoiceGetDateDue (ib);
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
return timespec_cmp (&da, &db);
|
2003-01-01 20:30:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Apply a payment of "amount" for the owner, between the xfer_account
|
|
|
|
* (bank or other asset) and the posted_account (A/R or A/P).
|
|
|
|
*
|
|
|
|
* XXX: yes, this should be in gncOwner, but all the other logic is
|
|
|
|
* in gncInvoice...
|
|
|
|
*/
|
|
|
|
Transaction *
|
2006-02-26 23:42:45 -06:00
|
|
|
gncOwnerApplyPayment (GncOwner *owner, GncInvoice* invoice,
|
2010-03-02 15:41:05 -06:00
|
|
|
Account *posted_acc, Account *xfer_acc,
|
|
|
|
gnc_numeric amount, gnc_numeric exch, Timespec date,
|
|
|
|
const char *memo, const char *num)
|
|
|
|
{
|
|
|
|
QofBook *book;
|
|
|
|
Account *inv_posted_acc;
|
|
|
|
Transaction *txn;
|
|
|
|
Split *split;
|
|
|
|
GList *lot_list, *fifo = NULL;
|
|
|
|
GNCLot *lot, *inv_posted_lot = NULL, *prepay_lot = NULL;
|
|
|
|
GncInvoice *this_invoice;
|
|
|
|
const char *name;
|
|
|
|
gnc_commodity *commodity;
|
|
|
|
gnc_numeric split_amt;
|
|
|
|
gboolean reverse, inv_passed = TRUE;
|
|
|
|
gnc_numeric payment_value = amount;
|
|
|
|
|
|
|
|
/* Verify our arguments */
|
|
|
|
if (!owner || !posted_acc || !xfer_acc) return NULL;
|
|
|
|
g_return_val_if_fail (owner->owner.undefined != NULL, NULL);
|
|
|
|
|
|
|
|
/* Compute the ancillary data */
|
|
|
|
book = gnc_account_get_book (posted_acc);
|
|
|
|
name = gncOwnerGetName (gncOwnerGetEndOwner (owner));
|
|
|
|
commodity = gncOwnerGetCurrency (owner);
|
|
|
|
reverse = (gncOwnerGetType (owner) == GNC_OWNER_CUSTOMER);
|
|
|
|
|
|
|
|
txn = xaccMallocTransaction (book);
|
|
|
|
xaccTransBeginEdit (txn);
|
|
|
|
|
|
|
|
/* Set up the transaction */
|
|
|
|
xaccTransSetDescription (txn, name ? name : "");
|
|
|
|
xaccTransSetNum (txn, num);
|
|
|
|
xaccTransSetCurrency (txn, commodity);
|
|
|
|
xaccTransSetDateEnteredSecs (txn, time(NULL));
|
|
|
|
xaccTransSetDatePostedTS (txn, &date);
|
|
|
|
xaccTransSetTxnType (txn, TXN_TYPE_PAYMENT);
|
|
|
|
|
|
|
|
|
|
|
|
/* The split for the transfer account */
|
|
|
|
split = xaccMallocSplit (book);
|
|
|
|
xaccSplitSetMemo (split, memo);
|
|
|
|
xaccSplitSetAction (split, _("Payment"));
|
|
|
|
xaccAccountBeginEdit (xfer_acc);
|
|
|
|
xaccAccountInsertSplit (xfer_acc, split);
|
|
|
|
xaccAccountCommitEdit (xfer_acc);
|
|
|
|
xaccTransAppendSplit (txn, split);
|
|
|
|
|
|
|
|
if (gnc_commodity_equal(xaccAccountGetCommodity(xfer_acc), commodity))
|
|
|
|
{
|
|
|
|
xaccSplitSetBaseValue (split, reverse ? amount :
|
|
|
|
gnc_numeric_neg (amount), commodity);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Need to value the payment in terms of the owner commodity */
|
|
|
|
xaccSplitSetAmount(split, reverse ? amount : gnc_numeric_neg (amount));
|
2010-10-23 05:38:48 -05:00
|
|
|
payment_value = gnc_numeric_mul(amount, exch, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND_HALF_UP);
|
2010-03-02 15:41:05 -06:00
|
|
|
xaccSplitSetValue(split, reverse ? payment_value : gnc_numeric_neg(payment_value));
|
2006-02-26 23:42:45 -06:00
|
|
|
}
|
|
|
|
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Now, find all "open" lots in the posting account for this
|
|
|
|
* company and apply the payment on a FIFO basis. Create
|
|
|
|
* a new split for each open lot until the payment is gone.
|
|
|
|
*/
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
fifo = xaccAccountFindOpenLots (posted_acc, gnc_lot_match_invoice_owner,
|
|
|
|
owner,
|
|
|
|
(GCompareFunc)gnc_lot_sort_func);
|
2006-02-26 23:42:45 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Check if an invoice was passed in, and if so, does it match the
|
|
|
|
* account, and is it an open lot? If so, put it at the beginning
|
|
|
|
* of the lot list fifo so we post to this invoice's lot first.
|
2006-02-26 23:42:45 -06:00
|
|
|
*/
|
2010-03-02 15:41:05 -06:00
|
|
|
if (invoice)
|
|
|
|
{
|
|
|
|
inv_posted_acc = gncInvoiceGetPostedAcc(invoice);
|
|
|
|
inv_posted_lot = gncInvoiceGetPostedLot(invoice);
|
|
|
|
if (inv_posted_acc && inv_posted_lot &&
|
|
|
|
guid_equal(xaccAccountGetGUID(inv_posted_acc),
|
|
|
|
xaccAccountGetGUID(posted_acc)) &&
|
|
|
|
!gnc_lot_is_closed(inv_posted_lot))
|
|
|
|
{
|
|
|
|
/* Put this invoice at the beginning of the FIFO */
|
|
|
|
fifo = g_list_prepend (fifo, inv_posted_lot);
|
|
|
|
inv_passed = FALSE;
|
|
|
|
}
|
2006-02-26 23:42:45 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
xaccAccountBeginEdit (posted_acc);
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Now iterate over the fifo until the payment is fully applied
|
|
|
|
* (or all the lots are paid)
|
2003-01-01 20:30:44 -06:00
|
|
|
*/
|
2010-03-02 15:41:05 -06:00
|
|
|
for (lot_list = fifo; lot_list; lot_list = lot_list->next)
|
|
|
|
{
|
|
|
|
gnc_numeric balance;
|
|
|
|
|
|
|
|
lot = lot_list->data;
|
|
|
|
|
|
|
|
/* Skip this lot if it matches the invoice that was passed in and
|
|
|
|
* we've seen it already. This way we post to it the first time
|
|
|
|
* (from the beginning of the lot-list) but not when we reach it
|
|
|
|
* the second time.
|
|
|
|
*/
|
|
|
|
if (inv_posted_lot &&
|
|
|
|
guid_equal(qof_instance_get_guid(QOF_INSTANCE(lot)),
|
|
|
|
qof_instance_get_guid(QOF_INSTANCE(inv_posted_lot))))
|
|
|
|
{
|
|
|
|
if (inv_passed)
|
|
|
|
continue;
|
|
|
|
else
|
|
|
|
inv_passed = TRUE;
|
|
|
|
}
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
balance = gnc_lot_get_balance (lot);
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!reverse)
|
|
|
|
balance = gnc_numeric_neg (balance);
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* If the balance is "negative" then skip this lot.
|
|
|
|
* (just save the pre-payment lot for later)
|
|
|
|
*/
|
|
|
|
if (gnc_numeric_negative_p (balance))
|
|
|
|
{
|
|
|
|
if (prepay_lot)
|
|
|
|
{
|
|
|
|
g_warning ("Multiple pre-payment lots are found. Skipping.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prepay_lot = lot;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the payment_value <= the balance; we're done -- apply the payment_value.
|
|
|
|
* Otherwise, apply the balance, subtract that from the payment_value,
|
|
|
|
* and move on to the next one.
|
|
|
|
*/
|
|
|
|
if (gnc_numeric_compare (payment_value, balance) <= 0)
|
|
|
|
{
|
|
|
|
/* payment_value <= balance */
|
|
|
|
split_amt = payment_value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* payment_value > balance */
|
|
|
|
split_amt = balance;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reduce the payment_value by split_amt */
|
2010-08-26 12:22:06 -05:00
|
|
|
payment_value = gnc_numeric_sub (payment_value, split_amt, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
|
2010-03-02 15:41:05 -06:00
|
|
|
|
|
|
|
/* Create the split for this lot in the post account */
|
|
|
|
split = xaccMallocSplit (book);
|
|
|
|
xaccSplitSetMemo (split, memo);
|
|
|
|
xaccSplitSetAction (split, _("Payment"));
|
|
|
|
xaccAccountInsertSplit (posted_acc, split);
|
|
|
|
xaccTransAppendSplit (txn, split);
|
|
|
|
xaccSplitSetBaseValue (split, reverse ? gnc_numeric_neg (split_amt) :
|
|
|
|
split_amt, commodity);
|
|
|
|
gnc_lot_add_split (lot, split);
|
|
|
|
|
|
|
|
/* Now send an event for the invoice so it gets updated as paid */
|
|
|
|
this_invoice = gncInvoiceGetInvoiceFromLot(lot);
|
|
|
|
if (this_invoice)
|
|
|
|
qof_event_gen (&this_invoice->inst, QOF_EVENT_MODIFY, NULL);
|
|
|
|
|
|
|
|
if (gnc_numeric_zero_p (payment_value))
|
|
|
|
break;
|
2003-01-01 20:30:44 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
g_list_free (fifo);
|
|
|
|
|
|
|
|
/* If there is still money left here, then create a pre-payment lot */
|
|
|
|
if (gnc_numeric_positive_p (payment_value))
|
|
|
|
{
|
|
|
|
if (prepay_lot == NULL)
|
|
|
|
{
|
|
|
|
prepay_lot = gnc_lot_new (book);
|
|
|
|
gncOwnerAttachToLot (owner, prepay_lot);
|
|
|
|
}
|
|
|
|
|
|
|
|
split = xaccMallocSplit (book);
|
|
|
|
xaccSplitSetMemo (split, memo);
|
|
|
|
xaccSplitSetAction (split, _("Pre-Payment"));
|
|
|
|
xaccAccountInsertSplit (posted_acc, split);
|
|
|
|
xaccTransAppendSplit (txn, split);
|
|
|
|
xaccSplitSetBaseValue (split, reverse ? gnc_numeric_neg (payment_value) :
|
|
|
|
payment_value, commodity);
|
|
|
|
gnc_lot_add_split (prepay_lot, split);
|
|
|
|
}
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
xaccAccountCommitEdit (posted_acc);
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
/* Commit this new transaction */
|
|
|
|
xaccTransCommitEdit (txn);
|
2003-01-01 20:30:44 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
return txn;
|
2003-01-01 20:30:44 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
static gboolean gncInvoiceDateExists (const Timespec *date)
|
2002-02-19 12:23:53 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
g_return_val_if_fail (date, FALSE);
|
|
|
|
if (date->tv_sec || date->tv_nsec) return TRUE;
|
|
|
|
return FALSE;
|
2002-02-19 12:23:53 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
gboolean gncInvoiceIsPosted (const GncInvoice *invoice)
|
2002-02-19 12:23:53 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return FALSE;
|
|
|
|
return gncInvoiceDateExists (&(invoice->date_posted));
|
2002-02-19 12:23:53 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
gboolean gncInvoiceIsPaid (const GncInvoice *invoice)
|
2003-05-12 21:07:15 -05:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!invoice) return FALSE;
|
|
|
|
if (!invoice->posted_lot) return FALSE;
|
|
|
|
return gnc_lot_is_closed(invoice->posted_lot);
|
2003-05-12 21:07:15 -05:00
|
|
|
}
|
|
|
|
|
2003-10-21 21:02:45 -05:00
|
|
|
/* ================================================================== */
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
void gncInvoiceBeginEdit (GncInvoice *invoice)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
qof_begin_edit(&invoice->inst);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
2002-11-03 14:21:42 -06:00
|
|
|
|
2006-11-29 09:13:02 -06:00
|
|
|
static void gncInvoiceOnError (QofInstance *inst, QofBackendError errcode)
|
2002-11-03 14:21:42 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
PERR("Invoice QofBackend Failure: %d", errcode);
|
|
|
|
gnc_engine_signal_commit_error( errcode );
|
2002-11-03 14:21:42 -06:00
|
|
|
}
|
|
|
|
|
2006-11-29 09:13:02 -06:00
|
|
|
static void gncInvoiceOnDone (QofInstance *invoice) { }
|
2003-10-14 16:20:55 -05:00
|
|
|
|
2006-11-29 09:13:02 -06:00
|
|
|
static void invoice_free (QofInstance *inst)
|
2003-10-14 16:20:55 -05:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncInvoice *invoice = (GncInvoice *) inst;
|
|
|
|
gncInvoiceFree (invoice);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2002-11-03 14:21:42 -06:00
|
|
|
void gncInvoiceCommitEdit (GncInvoice *invoice)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
if (!qof_commit_edit (QOF_INSTANCE(invoice))) return;
|
|
|
|
qof_commit_edit_part2 (&invoice->inst, gncInvoiceOnError,
|
|
|
|
gncInvoiceOnDone, invoice_free);
|
2002-11-03 14:21:42 -06:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
int gncInvoiceCompare (const GncInvoice *a, const GncInvoice *b)
|
2002-02-03 14:01:08 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
int compare;
|
2002-02-03 14:01:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (a == b) return 0;
|
|
|
|
if (!a && b) return -1;
|
|
|
|
if (a && !b) return 1;
|
2002-02-03 14:01:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
compare = safe_strcmp (a->id, b->id);
|
|
|
|
if (compare) return compare;
|
2002-02-03 14:01:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
compare = timespec_cmp (&(a->date_opened), &(b->date_opened));
|
|
|
|
if (compare) return compare;
|
2002-02-03 14:01:08 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
compare = timespec_cmp (&(a->date_posted), &(b->date_posted));
|
|
|
|
if (compare) return compare;
|
2002-02-10 19:59:54 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
return qof_instance_guid_compare(a, b);
|
2002-02-03 14:01:08 -06:00
|
|
|
}
|
|
|
|
|
2010-04-17 12:00:18 -05:00
|
|
|
gboolean gncInvoiceEqual(const GncInvoice *a, const GncInvoice *b)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2003-10-19 00:13:59 -05:00
|
|
|
/* ============================================================= */
|
2001-11-24 23:34:34 -06:00
|
|
|
/* Package-Private functions */
|
|
|
|
|
2002-02-24 16:12:24 -06:00
|
|
|
static const char * _gncInvoicePrintable (gpointer obj)
|
2002-02-23 22:01:57 -06:00
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
GncInvoice *invoice = obj;
|
2002-02-24 16:12:24 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
g_return_val_if_fail (invoice, NULL);
|
2002-02-23 22:01:57 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
if (qof_instance_get_dirty_flag(invoice) || invoice->printname == NULL)
|
|
|
|
{
|
|
|
|
if (invoice->printname) g_free (invoice->printname);
|
2002-02-23 22:01:57 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
invoice->printname =
|
|
|
|
g_strdup_printf ("%s%s", invoice->id,
|
|
|
|
gncInvoiceIsPosted (invoice) ? _(" (posted)") : "");
|
|
|
|
}
|
2002-02-23 22:01:57 -06:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
return invoice->printname;
|
2002-02-23 22:01:57 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
static QofObject gncInvoiceDesc =
|
2003-10-19 00:13:59 -05:00
|
|
|
{
|
2010-03-27 16:01:56 -05:00
|
|
|
DI(.interface_version = ) QOF_OBJECT_VERSION,
|
|
|
|
DI(.e_type = ) _GNC_MOD_NAME,
|
|
|
|
DI(.type_label = ) "Invoice",
|
|
|
|
DI(.create = ) (gpointer)gncInvoiceCreate,
|
|
|
|
DI(.book_begin = ) NULL,
|
|
|
|
DI(.book_end = ) NULL,
|
|
|
|
DI(.is_dirty = ) qof_collection_is_dirty,
|
|
|
|
DI(.mark_clean = ) qof_collection_mark_clean,
|
|
|
|
DI(.foreach = ) qof_collection_foreach,
|
|
|
|
DI(.printable = ) _gncInvoicePrintable,
|
|
|
|
DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
|
2001-11-21 19:23:07 -06:00
|
|
|
};
|
|
|
|
|
2002-06-27 23:39:18 -05:00
|
|
|
static void
|
|
|
|
reg_lot (void)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
static QofParam params[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
INVOICE_FROM_LOT, _GNC_MOD_NAME,
|
|
|
|
(QofAccessFunc)gncInvoiceGetInvoiceFromLot, NULL
|
|
|
|
},
|
|
|
|
{ NULL },
|
|
|
|
};
|
2002-06-27 23:39:18 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
qof_class_register (GNC_ID_LOT, NULL, params);
|
2002-06-27 23:39:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
reg_txn (void)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
static QofParam params[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
INVOICE_FROM_TXN, _GNC_MOD_NAME,
|
|
|
|
(QofAccessFunc)gncInvoiceGetInvoiceFromTxn, NULL
|
|
|
|
},
|
|
|
|
{ NULL },
|
|
|
|
};
|
2002-06-27 23:39:18 -05:00
|
|
|
|
2010-03-02 15:41:05 -06:00
|
|
|
qof_class_register (GNC_ID_TRANS, NULL, params);
|
2002-06-27 23:39:18 -05:00
|
|
|
}
|
|
|
|
|
2001-11-21 19:23:07 -06:00
|
|
|
gboolean gncInvoiceRegister (void)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
static QofParam params[] =
|
|
|
|
{
|
|
|
|
{ INVOICE_ID, QOF_TYPE_STRING, (QofAccessFunc)gncInvoiceGetID, (QofSetterFunc)gncInvoiceSetID },
|
|
|
|
{ INVOICE_OWNER, GNC_ID_OWNER, (QofAccessFunc)gncInvoiceGetOwner, NULL },
|
|
|
|
{ INVOICE_OPENED, QOF_TYPE_DATE, (QofAccessFunc)gncInvoiceGetDateOpened, (QofSetterFunc)gncInvoiceSetDateOpened },
|
|
|
|
{ INVOICE_DUE, QOF_TYPE_DATE, (QofAccessFunc)gncInvoiceGetDateDue, NULL },
|
|
|
|
{ INVOICE_POSTED, QOF_TYPE_DATE, (QofAccessFunc)gncInvoiceGetDatePosted, (QofSetterFunc)gncInvoiceSetDatePosted },
|
|
|
|
{ INVOICE_IS_POSTED, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncInvoiceIsPosted, NULL },
|
|
|
|
{ INVOICE_IS_PAID, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncInvoiceIsPaid, NULL },
|
|
|
|
{ INVOICE_BILLINGID, QOF_TYPE_STRING, (QofAccessFunc)gncInvoiceGetBillingID, (QofSetterFunc)gncInvoiceSetBillingID },
|
|
|
|
{ INVOICE_NOTES, QOF_TYPE_STRING, (QofAccessFunc)gncInvoiceGetNotes, (QofSetterFunc)gncInvoiceSetNotes },
|
|
|
|
{ INVOICE_ACC, GNC_ID_ACCOUNT, (QofAccessFunc)gncInvoiceGetPostedAcc, (QofSetterFunc)gncInvoiceSetPostedAcc },
|
|
|
|
{ INVOICE_POST_TXN, GNC_ID_TRANS, (QofAccessFunc)gncInvoiceGetPostedTxn, (QofSetterFunc)gncInvoiceSetPostedTxn },
|
|
|
|
{ INVOICE_POST_LOT, GNC_ID_LOT, (QofAccessFunc)gncInvoiceGetPostedLot, NULL/*(QofSetterFunc)gncInvoiceSetPostedLot*/ },
|
|
|
|
{ INVOICE_TYPE, QOF_TYPE_STRING, (QofAccessFunc)gncInvoiceGetType, NULL },
|
|
|
|
{ INVOICE_TERMS, GNC_ID_BILLTERM, (QofAccessFunc)gncInvoiceGetTerms, (QofSetterFunc)gncInvoiceSetTerms },
|
|
|
|
{ INVOICE_BILLTO, GNC_ID_OWNER, (QofAccessFunc)gncInvoiceGetBillTo, NULL },
|
|
|
|
{ INVOICE_ENTRIES, QOF_TYPE_COLLECT, (QofAccessFunc)qofInvoiceGetEntries, (QofSetterFunc)qofInvoiceSetEntries },
|
|
|
|
{ INVOICE_JOB, GNC_ID_JOB, (QofAccessFunc)qofInvoiceGetJob, (QofSetterFunc)qofInvoiceSetJob },
|
|
|
|
{ QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncInvoiceGetActive, (QofSetterFunc)gncInvoiceSetActive },
|
|
|
|
{ QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
|
|
|
|
{ QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
|
|
|
|
{ NULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncInvoiceCompare, params);
|
|
|
|
reg_lot ();
|
|
|
|
reg_txn ();
|
|
|
|
|
|
|
|
/* Make the compiler happy... */
|
|
|
|
if (0)
|
|
|
|
{
|
|
|
|
qofInvoiceSetEntries(NULL, NULL);
|
|
|
|
qofInvoiceGetEntries(NULL);
|
|
|
|
qofInvoiceSetOwner(NULL, NULL);
|
|
|
|
qofInvoiceGetOwner(NULL);
|
|
|
|
qofInvoiceSetBillTo(NULL, NULL);
|
|
|
|
qofInvoiceGetBillTo(NULL);
|
|
|
|
}
|
|
|
|
if (!qof_choice_create(GNC_ID_INVOICE))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return qof_object_register (&gncInvoiceDesc);
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|
|
|
|
|
2007-12-25 10:56:35 -06:00
|
|
|
gint64 gncInvoiceNextID (QofBook *book, GncOwner *owner)
|
|
|
|
{
|
2010-03-02 15:41:05 -06:00
|
|
|
gint64 nextID;
|
|
|
|
switch (gncOwnerGetType(gncOwnerGetEndOwner(owner)))
|
|
|
|
{
|
2007-12-25 10:56:35 -06:00
|
|
|
case GNC_OWNER_CUSTOMER:
|
|
|
|
nextID = qof_book_get_counter (book, "gncInvoice");
|
|
|
|
break;
|
|
|
|
case GNC_OWNER_VENDOR:
|
2010-03-02 15:41:05 -06:00
|
|
|
nextID = qof_book_get_counter (book, "gncBill");
|
|
|
|
break;
|
2007-12-25 10:56:35 -06:00
|
|
|
case GNC_OWNER_EMPLOYEE:
|
2010-03-02 15:41:05 -06:00
|
|
|
nextID = qof_book_get_counter (book, "gncExpVoucher");
|
|
|
|
break;
|
2007-12-25 10:56:35 -06:00
|
|
|
default:
|
2010-03-02 15:41:05 -06:00
|
|
|
nextID = qof_book_get_counter (book, _GNC_MOD_NAME);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return nextID;
|
2001-11-21 19:23:07 -06:00
|
|
|
}
|