mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-26 02:40:43 -06:00
e2f8233e1e
- Balancing lots always involves splits in the same account. So the relevant number to use in the calculations is the split amount, not the split value. - Additionally don't assume transactions are single-currency. So if amounts change, recalculate the associated values based on deduced exchange rates. - Finally if the lot balancing resulted in a split to be broken up into two splits use conservative calculations for the new splits' values to avoid introducing imbalances due to rounding errors.
361 lines
14 KiB
C
361 lines
14 KiB
C
/********************************************************************\
|
|
* gncOwner.h -- Business Interface: Object OWNERs *
|
|
* *
|
|
* 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 *
|
|
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
|
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
|
* *
|
|
\********************************************************************/
|
|
/** @addtogroup Business
|
|
@{ */
|
|
/** @addtogroup Owner
|
|
@{ */
|
|
/** @file gncOwner.h
|
|
@brief Business Interface: Object OWNERs
|
|
@author Copyright (C) 2001,2002 Derek Atkins <warlord@MIT.EDU>
|
|
@author Copyright (c) 2005 Neil Williams <linux@codehelp.co.uk>
|
|
@author Copyright (c) 2006 David Hampton <hampton@employees.org>
|
|
*/
|
|
|
|
#ifndef GNC_OWNER_H_
|
|
#define GNC_OWNER_H_
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef struct _gncOwner GncOwner;
|
|
|
|
#define GNC_ID_OWNER "gncOwner"
|
|
|
|
typedef enum
|
|
{
|
|
GNC_OWNER_NONE ,
|
|
GNC_OWNER_UNDEFINED ,
|
|
GNC_OWNER_CUSTOMER ,
|
|
GNC_OWNER_JOB ,
|
|
GNC_OWNER_VENDOR ,
|
|
GNC_OWNER_EMPLOYEE ,
|
|
} GncOwnerType;
|
|
|
|
#include "qof.h"
|
|
#include "gncCustomer.h"
|
|
#include "gncJob.h"
|
|
#include "gncVendor.h"
|
|
#include "gncEmployee.h"
|
|
#include "gncInvoice.h"
|
|
#include "Account.h"
|
|
#include "gnc-lot.h"
|
|
|
|
/** \name QOF handling
|
|
|
|
Whilst GncOwner is not a formal QOF object, these functions
|
|
are still expected to be useful in making GncOwner transparent
|
|
to QOF as they can be used by objects like GncInvoice.
|
|
@{
|
|
*/
|
|
/** return the type for the collection. */
|
|
QofIdTypeConst qofOwnerGetType(const GncOwner *owner);
|
|
/** return the type for the owner as an untranslated string. */
|
|
const char * gncOwnerGetTypeString (const GncOwner *owner);
|
|
/** return the owner itself as an entity. */
|
|
QofInstance* qofOwnerGetOwner (const GncOwner *owner);
|
|
/** set the owner from the entity. */
|
|
void qofOwnerSetEntity (GncOwner *owner, QofInstance *ent);
|
|
/** Check if entity is an owner kind. This function conveniently
|
|
* imitates the various GNC_IS_ checks on the other gnucash
|
|
* objects even though an owner is not really a true object. */
|
|
gboolean GNC_IS_OWNER (QofInstance *ent);
|
|
|
|
/** Returns the QofIdType of the given GncOwnerType, or NULL if no
|
|
* suitable one exists. */
|
|
QofIdTypeConst gncOwnerTypeToQofIdType(GncOwnerType t);
|
|
|
|
gboolean
|
|
gncOwnerRegister(void);
|
|
|
|
/** @} */
|
|
|
|
#ifndef SWIG
|
|
|
|
/** \struct GncOwner */
|
|
struct _gncOwner
|
|
{
|
|
GncOwnerType type; /**< Customer, Job, Vendor, Employee or Undefined. */
|
|
union
|
|
{
|
|
gpointer undefined;
|
|
GncCustomer * customer;
|
|
GncJob * job;
|
|
GncVendor * vendor;
|
|
GncEmployee * employee;
|
|
} owner; /**< holds the pointer to the owner object. */
|
|
gpointer qof_temp; /**< Set type independently of the owner. */
|
|
};
|
|
|
|
#endif /* SWIG */
|
|
|
|
/** \name Setup routines
|
|
@{
|
|
*/
|
|
void gncOwnerInitUndefined (GncOwner *owner, gpointer obj);
|
|
void gncOwnerInitCustomer (GncOwner *owner, GncCustomer *customer);
|
|
void gncOwnerInitJob (GncOwner *owner, GncJob *job);
|
|
void gncOwnerInitVendor (GncOwner *owner, GncVendor *vendor);
|
|
void gncOwnerInitEmployee (GncOwner *owner, GncEmployee *employee);
|
|
/** @} */
|
|
/** \name Get routines.
|
|
@{
|
|
*/
|
|
/** Returns the GncOwnerType of this owner. (Not to be confused with qofOwnerGetType().) */
|
|
GncOwnerType gncOwnerGetType (const GncOwner *owner);
|
|
/** Returns TRUE if the given owner is one of the valid objects.
|
|
* Returns FALSE if the owner is (still) undefined, or if it is NULL. */
|
|
gboolean gncOwnerIsValid (const GncOwner *owner);
|
|
|
|
/** If the given owner is of type GNC_OWNER_UNDEFINED, returns the undefined
|
|
* pointer, which is usually NULL. Otherwise returns NULL. */
|
|
gpointer gncOwnerGetUndefined (const GncOwner *owner);
|
|
/** If the given owner is of type GNC_OWNER_CUSTOMER, returns the pointer
|
|
* to the customer object. Otherwise returns NULL. */
|
|
GncCustomer * gncOwnerGetCustomer (const GncOwner *owner);
|
|
/** If the given owner is of type GNC_OWNER_JOB, returns the pointer
|
|
* to the job object. Otherwise returns NULL. */
|
|
GncJob * gncOwnerGetJob (const GncOwner *owner);
|
|
/** If the given owner is of type GNC_OWNER_VENDOR, returns the pointer
|
|
* to the vendor object. Otherwise returns NULL. */
|
|
GncVendor * gncOwnerGetVendor (const GncOwner *owner);
|
|
/** If the given owner is of type GNC_OWNER_EMPLOYEE, returns the pointer
|
|
* to the employee object. Otherwise returns NULL. */
|
|
GncEmployee * gncOwnerGetEmployee (const GncOwner *owner);
|
|
|
|
const char * gncOwnerGetID (const GncOwner *owner);
|
|
const char * gncOwnerGetName (const GncOwner *owner);
|
|
GncAddress * gncOwnerGetAddr (const GncOwner *owner);
|
|
gboolean gncOwnerGetActive (const GncOwner *owner);
|
|
gnc_commodity * gncOwnerGetCurrency (const GncOwner *owner);
|
|
/** @} */
|
|
|
|
/** \name Set routines.
|
|
@{
|
|
*/
|
|
void gncOwnerSetActive (const GncOwner *owner, gboolean active);
|
|
/** @} */
|
|
|
|
void gncOwnerCopy (const GncOwner *src, GncOwner *dest);
|
|
|
|
/** \name Comparison routines.
|
|
@{
|
|
*/
|
|
/** Assess equality by checking
|
|
* - if both owner objects refer to the same owner type
|
|
* - and if the owner reference points to the same
|
|
* {vendor/customer/employee} in memory */
|
|
gboolean gncOwnerEqual (const GncOwner *a, const GncOwner *b);
|
|
/** Same as gncOwnerEqual, but returns 0 if
|
|
equal to be used as a GList custom compare function */
|
|
int gncOwnerGCompareFunc (const GncOwner *a, const GncOwner *b);
|
|
/** Sort on name */
|
|
int gncOwnerCompare (const GncOwner *a, const GncOwner *b);
|
|
/** @} */
|
|
|
|
/** Get the GncGUID of the immediate owner */
|
|
const GncGUID * gncOwnerGetGUID (const GncOwner *owner);
|
|
GncGUID gncOwnerRetGUID (GncOwner *owner);
|
|
|
|
/**
|
|
* Get the "parent" Owner or GncGUID thereof. The "parent" owner
|
|
* is the Customer or Vendor, or the Owner of a Job
|
|
*/
|
|
const GncOwner * gncOwnerGetEndOwner (const GncOwner *owner);
|
|
const GncGUID * gncOwnerGetEndGUID (const GncOwner *owner);
|
|
|
|
/** Attach an owner to a lot */
|
|
void gncOwnerAttachToLot (const GncOwner *owner, GNCLot *lot);
|
|
|
|
/** Helper function used to filter a list of lots by owner.
|
|
*/
|
|
gboolean gncOwnerLotMatchOwnerFunc (GNCLot *lot, gpointer user_data);
|
|
|
|
/** Helper function used to sort lots by date. If the lot is
|
|
* linked to an invoice, use the invoice posted date, otherwise
|
|
* use the lot's opened date.
|
|
*/
|
|
gint gncOwnerLotsSortFunc (GNCLot *lotA, GNCLot *lotB);
|
|
|
|
/** Get the owner from the lot. If an owner is found in the lot,
|
|
* fill in "owner" and return TRUE. Otherwise return FALSE.
|
|
*/
|
|
gboolean gncOwnerGetOwnerFromLot (GNCLot *lot, GncOwner *owner);
|
|
|
|
/** Convenience function to get the owner from a transaction.
|
|
* Transactions don't really have an owner. What this function will
|
|
* do it figure out whether the transaction is part of a business
|
|
* transaction (either a posted invoice/bill/voucher/credit note or
|
|
* a payment transaction) and use the business object behind it
|
|
* to extract owner information.
|
|
*/
|
|
gboolean gncOwnerGetOwnerFromTxn (Transaction *txn, GncOwner *owner);
|
|
|
|
gboolean gncOwnerGetOwnerFromTypeGuid (QofBook *book, GncOwner *owner, QofIdType type, GncGUID *guid);
|
|
|
|
/**
|
|
* Create a lot for a payment to the owner using the other
|
|
* parameters passed in. If a transaction is set, this transaction will be
|
|
* reused if possible (meaning, if the transaction currency matches
|
|
* the owner's currency and if the transaction has (at least?) one
|
|
* split in the transfer account).
|
|
*/
|
|
GNCLot *
|
|
gncOwnerCreatePaymentLotSecs (const GncOwner *owner, Transaction **preset_txn,
|
|
Account *posted_acc, Account *xfer_acc,
|
|
gnc_numeric amount, gnc_numeric exch, time64 date,
|
|
const char *memo, const char *num);
|
|
|
|
/**
|
|
* Given a list of lots, try to balance as many of them as possible
|
|
* by creating balancing transactions between them. This can be used
|
|
* to automatically link invoices to payments (to "mark" invoices as
|
|
* paid) or to credit notes or the other way around.
|
|
*
|
|
* The function starts with the first lot in the list and tries to
|
|
* create balancing transactions to the remainder of the lots in the
|
|
* list. If it reaches the end of the list, it will find the next
|
|
* still open lot in the list and tries to balance it with all lots
|
|
* that follow it (the ones that precede it are either already closed
|
|
* or not suitable or they would have been processed in a previous
|
|
* iteration).
|
|
*
|
|
* By intelligently sorting the list of lots, you can play with the
|
|
* order of precedence in which the lots should be processed. For
|
|
* example, by sorting the oldest invoice lots first, the code will
|
|
* attempt to balance these first.
|
|
*
|
|
* Some restrictions:
|
|
* - the algorithm is lazy: it will create the smallest balancing
|
|
* transaction(s) possible, not the largest ones. Since the process
|
|
* is iterative, you will have balanced the maximum amount possible
|
|
* in the end, but it may be done in several transactions instead of
|
|
* only one big one.
|
|
* - the balancing transactions only work within one account. If a
|
|
* balancing lot is from another account than the lot currently being
|
|
* balanced, it will be skipped during balance evaluation. However
|
|
* if there is a mix of lots from two different accounts, the algorithm
|
|
* will still attempt to match all lots per account.
|
|
* - the calling function is responsible for the memory management
|
|
* of the lots list. If it created the list, it should properly free
|
|
* it as well.
|
|
*/
|
|
void gncOwnerAutoApplyPaymentsWithLots (const GncOwner *owner, GList *lots);
|
|
|
|
/**
|
|
* A convenience function to apply a payment to the owner.
|
|
* It creates a lot for a payment, optionally based on an existing
|
|
* transaction and then tries to balance it with the list of
|
|
* document/payment lots passed in. If not lots were given,
|
|
* all open lots for the owner are considered.
|
|
*
|
|
* This code is actually a convenience wrapper around gncOwnerCreatePaymentLot
|
|
* and gncOwnerAutoApplyPaymentsWithLots. See their descriptions for more
|
|
* details on what happens exactly.
|
|
*/
|
|
void
|
|
gncOwnerApplyPaymentSecs (const GncOwner *owner, Transaction **preset_txn,
|
|
GList *lots, Account *posted_acc, Account *xfer_acc,
|
|
gnc_numeric amount, gnc_numeric exch, time64 date,
|
|
const char *memo, const char *num, gboolean auto_pay);
|
|
|
|
/** Helper function to find a split in lot that best offsets target_amount
|
|
* Obviously it should be of opposite sign.
|
|
* If there are more splits of opposite sign the following
|
|
* criteria are used in order of preference:
|
|
* 1. exact match in abs amount is preferred over larger abs amount
|
|
* 2. larger abs amount is preferred over smaller abs amount
|
|
* 3. if previous and new candidate are in the same amount category,
|
|
* prefer real payment splits over lot link splits
|
|
* 4. if previous and new candidate are of same split type
|
|
* prefer biggest abs amount.
|
|
*/
|
|
Split* gncOwnerFindOffsettingSplit(GNCLot* lot, gnc_numeric target_amount);
|
|
|
|
/** Helper function to reduce the amount of a split to target_amount. To make
|
|
* sure the split's parent transaction remains balanced a second split
|
|
* will be created with the remainder. Similarly if the split was part of a
|
|
* (business) lot, the remainder split will be added to the same lot to
|
|
* keep the lot's balance unchanged.
|
|
*/
|
|
gboolean gncOwnerReduceSplitTo(Split* split, gnc_numeric target_amount);
|
|
|
|
/** To help a user understand what a lot link transaction does,
|
|
* we set the memo to name all documents involved in the link.
|
|
* The function below calculates this memo and sets it for
|
|
* all splits in the lot link transaction.
|
|
*/
|
|
void gncOwnerSetLotLinkMemo (Transaction *ll_txn);
|
|
|
|
/** Returns a GList of account-types based on the owner type */
|
|
GList * gncOwnerGetAccountTypesList (const GncOwner *owner);
|
|
|
|
/** Returns a GList of currencies associated with the owner */
|
|
GList * gncOwnerGetCommoditiesList (const GncOwner *owner);
|
|
|
|
|
|
/** Given an owner, extract the open balance from the owner and then
|
|
* convert it to the desired currency.
|
|
*/
|
|
gnc_numeric
|
|
gncOwnerGetBalanceInCurrency (const GncOwner *owner,
|
|
const gnc_commodity *report_currency);
|
|
|
|
#define OWNER_TYPE "type"
|
|
#define OWNER_TYPE_STRING "type-string" /**< Allows the type to be handled externally. */
|
|
#define OWNER_CUSTOMER "customer"
|
|
#define OWNER_JOB "job"
|
|
#define OWNER_VENDOR "vendor"
|
|
#define OWNER_EMPLOYEE "employee"
|
|
#define OWNER_PARENT "parent"
|
|
#define OWNER_PARENTG "parent-guid"
|
|
#define OWNER_NAME "name"
|
|
|
|
#define OWNER_FROM_LOT "owner-from-lot"
|
|
|
|
/**
|
|
* These two functions are mainly for the convenience of scheme code.
|
|
* Normal C code has no need to ever use these two functions, and rather
|
|
* can just use a GncOwner directly and just pass around a pointer to it.
|
|
*/
|
|
GncOwner * gncOwnerNew (void);
|
|
void gncOwnerFree (GncOwner *owner);
|
|
|
|
|
|
/**
|
|
* These are convenience wrappers around gnc{Vendor,Customer,Job,Employee}*
|
|
* functions. This allows you to begin edit, destroy commit edit an owner
|
|
* without knowing its type.
|
|
*/
|
|
void gncOwnerBeginEdit (GncOwner *owner);
|
|
void gncOwnerCommitEdit (GncOwner *owner);
|
|
void gncOwnerDestroy (GncOwner *owner);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* GNC_OWNER_H_ */
|
|
/** @} */
|
|
/** @} */
|