Lots: Core Function for AR/AP, Inventory, Stock Lots, Cap Gains
[GnuCash Engine: Core, Non-GUI Accounting Functions]


Detailed Description

One often needs to know that the item 'bought' in one transaction is the same one as the item 'sold' in a different transaction. Lots are used to make this association. One Lot holds all of the splits that involve the same item. A lot is typically formed when the item is bought, and is closed when the item is sold out. A lot need not be a single item, it can be a quantity of the same thing e.g. 500 gallons of paint (sold off a few gallons at a time).

Lots are required to correctly implement invoices, inventory, depreciation and stock market investment gains. See the file src/doc/lots.txt for a detailed implementation overview.

A lot is "closed" when the number of items in the lot has gone to zero. It is very easy to compute the gains/losses for a closed lot: it is the sum-total of the values of the items put into/taken out of the lot. (Realized) Gains on still-open lots can be computed by pro-rating the purchase prices.

Lots are nothing more than a collection or grouping of splits in an account. All of the splits in a lot must belong to the same account; there's no mix-n-match. Thus, in this sense, a lot belongs to an accunt as well.

Lots have an implicit "opening date": the date of the earliest split in the lot. The "close date" is the date of the split that brought the lot item balance down to zero.


Files

file  gnc-lot.h

Defines

#define gnc_lot_get_guid(X)   qof_entity_get_guid(QOF_ENTITY(X))
#define LOT_IS_CLOSED   "is-closed?"
#define LOT_BALANCE   "balance"
#define LOT_TITLE   "lot-title"
#define LOT_NOTES   "notes"

Functions

GNCLotgnc_lot_new (QofBook *)
void gnc_lot_destroy (GNCLot *)
GNCLotgnc_lot_lookup (const GUID *guid, QofBook *book)
QofBookgnc_lot_get_book (GNCLot *)
void gnc_lot_add_split (GNCLot *, Split *)
void gnc_lot_remove_split (GNCLot *, Split *)
SplitListgnc_lot_get_split_list (GNCLot *)
gint gnc_lot_count_splits (GNCLot *)
Accountgnc_lot_get_account (GNCLot *)
gnc_numeric gnc_lot_get_balance (GNCLot *)
gboolean gnc_lot_is_closed (GNCLot *)
Splitgnc_lot_get_earliest_split (GNCLot *lot)
Splitgnc_lot_get_latest_split (GNCLot *lot)
const char * gnc_lot_get_title (GNCLot *)
const char * gnc_lot_get_notes (GNCLot *)
void gnc_lot_set_title (GNCLot *, const char *)
void gnc_lot_set_notes (GNCLot *, const char *)
KvpFramegnc_lot_get_slots (GNCLot *)


Function Documentation

void gnc_lot_add_split GNCLot ,
Split
 

The gnc_lot_add_split() routine adds a split to this lot. Note that *all* splits in a lot must also be in the same account. Note that this routine adds the split unconditionally, with no regard for the accounting policy. To enforce a particular accounting polciy, use the xaccSplitAssignToLot() routine instead.

Definition at line 243 of file gnc-lot.c.

00244 {
00245    Account * acc;
00246    if (!lot || !split) return;
00247 
00248    ENTER ("(lot=%p, split=%p) %s amt=%s val=%s", lot, split,
00249         gnc_lot_get_title (lot), 
00250         gnc_num_dbg_to_string (split->amount),
00251         gnc_num_dbg_to_string (split->value));
00252    acc = xaccSplitGetAccount (split);
00253    if (NULL == lot->account)
00254    {
00255       xaccAccountInsertLot (acc, lot);
00256    }
00257    else if (lot->account != acc)
00258    {
00259       PERR ("splits from different accounts cannot "
00260             "be added to this lot!\n"
00261             "\tlot account=\'%s\', split account=\'%s\'\n",
00262             xaccAccountGetName(lot->account), xaccAccountGetName (acc));
00263       return;
00264    }
00265 
00266    if (lot == split->lot) return; /* handle not-uncommon no-op */
00267    if (split->lot)
00268    {
00269       gnc_lot_remove_split (split->lot, split);
00270    }
00271    split->lot = lot;
00272 
00273    lot->splits = g_list_append (lot->splits, split);
00274 
00275     /* for recomputation of is-closed */
00276    lot->is_closed = -1;
00277 
00278    gnc_engine_gen_event (&lot->entity, GNC_EVENT_MODIFY);
00279 }

Account* gnc_lot_get_account GNCLot  ) 
 

The gnc_lot_get_account() routine returns the account with which this lot is associated.

Definition at line 144 of file gnc-lot.c.

00145 {
00146    if (!lot) return NULL;
00147    return lot->account;
00148 }

gnc_numeric gnc_lot_get_balance GNCLot  ) 
 

The gnc_lot_get_balance() routine returns the balance of the lot. The commodity in which this balance is expressed is the commodity of the account.

Definition at line 204 of file gnc-lot.c.

00205 {
00206    GList *node;
00207    gnc_numeric zero = gnc_numeric_zero();
00208    gnc_numeric baln = zero;
00209    if (!lot) return zero;
00210 
00211    if (!lot->splits) 
00212    {
00213       lot->is_closed = FALSE;
00214       return zero;
00215    }
00216 
00217    /* Sum over splits; because they all belong to same account
00218     * they will have same denominator. 
00219     */
00220    for (node=lot->splits; node; node=node->next)
00221    {
00222       Split *s = node->data;
00223       gnc_numeric amt = xaccSplitGetAmount (s);
00224       baln = gnc_numeric_add_fixed (baln, amt);
00225    }
00226 
00227    /* cache a zero balance as a closed lot */
00228    if (gnc_numeric_equal (baln, zero))
00229    {
00230       lot->is_closed = TRUE;
00231    }
00232    else
00233    {
00234       lot->is_closed = FALSE;
00235    }
00236    
00237    return baln;
00238 }

Split* gnc_lot_get_earliest_split GNCLot lot  ) 
 

The gnc_lot_get_earliest_split() routine is a convenience routine that helps identify the date this lot was opened. It simply loops over all of the splits in the lot, and returns the split with the earliest split->transaction->date_posted.

Definition at line 303 of file gnc-lot.c.

00304 {
00305    SplitList *node;
00306    Timespec ts;
00307    Split *earliest = NULL;
00308 
00309    ts.tv_sec = ((long long) LONG_MAX);
00310    ts.tv_nsec = 0;
00311    if (!lot) return NULL;
00312 
00313    for (node=lot->splits; node; node=node->next)
00314    {
00315       Split *s = node->data;
00316       Transaction *trans = s->parent;
00317       if (!trans) continue;
00318       if ((ts.tv_sec > trans->date_posted.tv_sec) ||
00319           ((ts.tv_sec == trans->date_posted.tv_sec) &&
00320            (ts.tv_nsec > trans->date_posted.tv_nsec)))
00321           
00322       {
00323          ts = trans->date_posted;
00324          earliest = s;
00325       }
00326    }
00327 
00328    return earliest;
00329 }

Split* gnc_lot_get_latest_split GNCLot lot  ) 
 

The gnc_lot_get_latest_split() routine is a convenience routine that helps identify the date this lot was closed. It simply loops over all of the splits in the lot, and returns the split with the latest split->transaction->date_posted.

Definition at line 332 of file gnc-lot.c.

00333 {
00334    SplitList *node;
00335    Timespec ts;
00336    Split *latest = NULL;
00337 
00338    ts.tv_sec = -((long long) LONG_MAX);
00339    ts.tv_nsec = 0;
00340    if (!lot) return NULL;
00341 
00342    for (node=lot->splits; node; node=node->next)
00343    {
00344       Split *s = node->data;
00345       Transaction *trans = s->parent;
00346       if (!trans) continue;
00347       if ((ts.tv_sec < trans->date_posted.tv_sec) ||
00348           ((ts.tv_sec == trans->date_posted.tv_sec) &&
00349            (ts.tv_nsec < trans->date_posted.tv_nsec)))
00350           
00351       {
00352          ts = trans->date_posted;
00353          latest = s;
00354       }
00355    }
00356 
00357    return latest;
00358 }

KvpFrame* gnc_lot_get_slots GNCLot  ) 
 

Every lot has a place to hang kvp data. This routine returns that place.

Definition at line 151 of file gnc-lot.c.

00152 {
00153    if (!lot) return NULL;
00154    return lot->kvp_data;
00155 }

SplitList* gnc_lot_get_split_list GNCLot  ) 
 

The gnc_lot_get_split_list() routine returns a GList of all the splits in this lot. Do *not* not free this list when done; it is a pointer straight into the lots intenal list. Do *not* add to or remove from this list directly. Calling either gnc_lot_add_split() or gnc_lot_remove_split() will invalidate the returned pointer.

Definition at line 158 of file gnc-lot.c.

00159 {
00160    if (!lot) return NULL;
00161    return lot->splits;
00162 }

const char* gnc_lot_get_title GNCLot  ) 
 

Get and set the account title, or the account notes.

Definition at line 174 of file gnc-lot.c.

00175 {
00176    if (!lot) return NULL;
00177    return kvp_frame_get_string (lot->kvp_data, "/title");
00178 }

gboolean gnc_lot_is_closed GNCLot  ) 
 

The gnc_lot_is_closed() routine returns a boolean flag: is this lot closed? A lot is closed if its balance is zero. This routine is faster than using gnc_lot_get_balance() because once the balance goes to zero, this fact is cached.

Definition at line 136 of file gnc-lot.c.

00137 {
00138    if (!lot) return TRUE;
00139    if (0 > lot->is_closed) gnc_lot_get_balance (lot);
00140    return lot->is_closed;
00141 }


Generated on Sun Sep 4 18:09:12 2005 for GnuCash by  doxygen 1.4.3-20050530