GnuCash  2.6.16
Files | Data Structures | Macros | Functions
Lots: Core Function for AR/AP, Inventory, Stock Lots, Cap Gains

Files

file  gnc-lot.h
 

Data Structures

struct  GncLotClass
 

Macros

#define GNCLotClass   GncLotClass
 
#define GNC_TYPE_LOT   (gnc_lot_get_type ())
 
#define GNC_LOT(o)   (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_LOT, GNCLot))
 
#define GNC_LOT_CLASS(k)   (G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_LOT, GNCLotClass))
 
#define GNC_IS_LOT(o)   (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_LOT))
 
#define GNC_IS_LOT_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GNC_TYPE_LOT))
 
#define GNC_LOT_GET_CLASS(o)   (G_TYPE_INSTANCE_GET_CLASS ((o), GNC_TYPE_LOT, GNCLotClass))
 
#define gnc_lot_get_guid(X)   qof_entity_get_guid(QOF_INSTANCE(X))
 
#define LOT_IS_CLOSED   "is-closed?"
 
#define LOT_BALANCE   "balance"
 
#define LOT_TITLE   "lot-title"
 
#define LOT_NOTES   "notes"
 

Functions

GType gnc_lot_get_type (void)
 
GNCLot * gnc_lot_new (QofBook *)
 
void gnc_lot_destroy (GNCLot *)
 
GNCLot * gnc_lot_lookup (const GncGUID *guid, QofBook *book)
 
QofBook * gnc_lot_get_book (GNCLot *)
 
void gnc_lot_begin_edit (GNCLot *lot)
 
void gnc_lot_commit_edit (GNCLot *lot)
 
void gnc_lot_add_split (GNCLot *, Split *)
 
void gnc_lot_remove_split (GNCLot *, Split *)
 
SplitListgnc_lot_get_split_list (const GNCLot *)
 
gint gnc_lot_count_splits (const GNCLot *)
 
Accountgnc_lot_get_account (const GNCLot *)
 
void gnc_lot_set_account (GNCLot *, Account *)
 
gnc_numeric gnc_lot_get_balance (GNCLot *)
 
void gnc_lot_get_balance_before (const GNCLot *, const Split *, gnc_numeric *, gnc_numeric *)
 
gboolean gnc_lot_is_closed (GNCLot *)
 
Split * gnc_lot_get_earliest_split (GNCLot *lot)
 
Split * gnc_lot_get_latest_split (GNCLot *lot)
 
void gnc_lot_set_closed_unknown (GNCLot *)
 
const char * gnc_lot_get_title (const GNCLot *)
 
const char * gnc_lot_get_notes (const GNCLot *)
 
void gnc_lot_set_title (GNCLot *, const char *)
 
void gnc_lot_set_notes (GNCLot *, const char *)
 
KvpFrame * gnc_lot_get_slots (const GNCLot *)
 
GNCLot * gnc_lot_make_default (Account *acc)
 

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 account 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.

Function Documentation

◆ gnc_lot_add_split()

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 policy, use the xaccSplitAssignToLot() routine instead.

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

496 {
497  LotPrivate* priv;
498  Account * acc;
499  if (!lot || !split) return;
500  priv = GET_PRIVATE(lot);
501 
502  ENTER ("(lot=%p, split=%p) %s amt=%s val=%s", lot, split,
503  gnc_lot_get_title (lot),
504  gnc_num_dbg_to_string (split->amount),
505  gnc_num_dbg_to_string (split->value));
506  gnc_lot_begin_edit(lot);
507  acc = xaccSplitGetAccount (split);
508  qof_instance_set_dirty(QOF_INSTANCE(lot));
509  if (NULL == priv->account)
510  {
511  xaccAccountInsertLot (acc, lot);
512  }
513  else if (priv->account != acc)
514  {
515  PERR ("splits from different accounts cannot "
516  "be added to this lot!\n"
517  "\tlot account=\'%s\', split account=\'%s\'\n",
518  xaccAccountGetName(priv->account), xaccAccountGetName (acc));
519  gnc_lot_commit_edit(lot);
520  LEAVE("different accounts");
521  return;
522  }
523 
524  if (lot == split->lot)
525  {
526  gnc_lot_commit_edit(lot);
527  LEAVE("already in lot");
528  return; /* handle not-uncommon no-op */
529  }
530  if (split->lot)
531  {
532  gnc_lot_remove_split (split->lot, split);
533  }
534  xaccSplitSetLot(split, lot);
535 
536  priv->splits = g_list_append (priv->splits, split);
537 
538  /* for recomputation of is-closed */
539  priv->is_closed = LOT_CLOSED_UNKNOWN;
540  gnc_lot_commit_edit(lot);
541 
542  qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_MODIFY, NULL);
543  LEAVE("added to lot");
544 }
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Definition: gnc-numeric.c:1383
void xaccAccountInsertLot(Account *acc, GNCLot *lot)
Definition: Account.c:1783
void qof_instance_set_dirty(QofInstance *inst)
Set the dirty flag.
Definition: qofinstance.c:723
#define PERR(format, args...)
Definition: qoflog.h:232
#define ENTER(format, args...)
Definition: qoflog.h:256
const char * gnc_lot_get_title(const GNCLot *lot)
Definition: gnc-lot.c:368
void xaccSplitSetLot(Split *split, GNCLot *lot)
Definition: Split.c:1714
Account * xaccSplitGetAccount(const Split *s)
Definition: Split.c:732
#define LEAVE(format, args...)
Definition: qoflog.h:266
const char * xaccAccountGetName(const Account *acc)
Definition: Account.c:2906
void qof_event_gen(QofInstance *entity, QofEventId event_id, gpointer event_data)
Invoke all registered event handlers using the given arguments.
Definition: qofevent.c:230

◆ gnc_lot_get_account()

Account* gnc_lot_get_account ( const GNCLot *  )

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

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

312 {
313  LotPrivate* priv;
314  if (!lot) return NULL;
315  priv = GET_PRIVATE(lot);
316  return priv->account;
317 }

◆ gnc_lot_get_balance()

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 404 of file gnc-lot.c.

405 {
406  LotPrivate* priv;
407  GList *node;
408  gnc_numeric zero = gnc_numeric_zero();
409  gnc_numeric baln = zero;
410  if (!lot) return zero;
411 
412  priv = GET_PRIVATE(lot);
413  if (!priv->splits)
414  {
415  priv->is_closed = FALSE;
416  return zero;
417  }
418 
419  /* Sum over splits; because they all belong to same account
420  * they will have same denominator.
421  */
422  for (node = priv->splits; node; node = node->next)
423  {
424  Split *s = node->data;
425  gnc_numeric amt = xaccSplitGetAmount (s);
426  baln = gnc_numeric_add_fixed (baln, amt);
427  }
428 
429  /* cache a zero balance as a closed lot */
430  if (gnc_numeric_equal (baln, zero))
431  {
432  priv->is_closed = TRUE;
433  }
434  else
435  {
436  priv->is_closed = FALSE;
437  }
438 
439  return baln;
440 }
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Definition: gnc-numeric.c:304
gnc_numeric xaccSplitGetAmount(const Split *split)
Definition: Split.c:1742

◆ gnc_lot_get_balance_before()

void gnc_lot_get_balance_before ( const GNCLot *  ,
const Split *  ,
gnc_numeric *  ,
gnc_numeric *   
)

The gnc_lot_get_balance_before routine computes both the balance and value in the lot considering only splits in transactions prior to the one containing the given split or other splits in the same transaction. The first return value is the amount and the second is the value.

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

447 {
448  LotPrivate* priv;
449  GList *node;
450  gnc_numeric zero = gnc_numeric_zero();
451  gnc_numeric amt = zero;
452  gnc_numeric val = zero;
453 
454  *amount = amt;
455  *value = val;
456  if (lot == NULL) return;
457 
458  priv = GET_PRIVATE(lot);
459  if (priv->splits)
460  {
461  Transaction *ta, *tb;
462  const Split *target;
463  /* If this is a gains split, find the source of the gains and use
464  its transaction for the comparison. Gains splits are in separate
465  transactions that may sort after non-gains transactions. */
466  target = xaccSplitGetGainsSourceSplit (split);
467  if (target == NULL)
468  target = split;
469  tb = xaccSplitGetParent (target);
470  for (node = priv->splits; node; node = node->next)
471  {
472  Split *s = node->data;
473  Split *source = xaccSplitGetGainsSourceSplit (s);
474  if (source == NULL)
475  source = s;
476  ta = xaccSplitGetParent (source);
477  if ((ta == tb && source != target) ||
478  xaccTransOrder (ta, tb) < 0)
479  {
480  gnc_numeric tmpval = xaccSplitGetAmount (s);
481  amt = gnc_numeric_add_fixed (amt, tmpval);
482  tmpval = xaccSplitGetValue (s);
483  val = gnc_numeric_add_fixed (val, tmpval);
484  }
485  }
486  }
487 
488  *amount = amt;
489  *value = val;
490 }
Split * xaccSplitGetGainsSourceSplit(const Split *split)
Definition: cap-gains.c:657
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1658
gnc_numeric xaccSplitGetValue(const Split *split)
Definition: Split.c:1748
int xaccTransOrder(const Transaction *ta, const Transaction *tb)
Definition: Transaction.c:1803
gnc_numeric xaccSplitGetAmount(const Split *split)
Definition: Split.c:1742

◆ gnc_lot_get_earliest_split()

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 574 of file gnc-lot.c.

575 {
576  LotPrivate* priv;
577  if (!lot) return NULL;
578  priv = GET_PRIVATE(lot);
579  if (! priv->splits) return NULL;
580  priv->splits = g_list_sort (priv->splits, (GCompareFunc) xaccSplitOrderDateOnly);
581  return priv->splits->data;
582 }

◆ gnc_lot_get_latest_split()

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 586 of file gnc-lot.c.

587 {
588  LotPrivate* priv;
589  SplitList *node;
590 
591  if (!lot) return NULL;
592  priv = GET_PRIVATE(lot);
593  if (! priv->splits) return NULL;
594  priv->splits = g_list_sort (priv->splits, (GCompareFunc) xaccSplitOrderDateOnly);
595 
596  for (node = priv->splits; node->next; node = node->next)
597  ;
598 
599  return node->data;
600 }
GList SplitList
Definition: gnc-engine.h:203

◆ gnc_lot_get_slots()

KvpFrame* gnc_lot_get_slots ( const GNCLot *  )

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

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

343 {
344  return qof_instance_get_slots(QOF_INSTANCE(lot));
345 }
KvpFrame * qof_instance_get_slots(const QofInstance *inst)
Definition: qofinstance.c:586

◆ gnc_lot_get_split_list()

SplitList* gnc_lot_get_split_list ( const GNCLot *  )

The gnc_lot_get_split_list() routine returns a GList of all the splits in this lot. Do not free this list when done; it is a pointer straight into the lots internal 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 348 of file gnc-lot.c.

349 {
350  LotPrivate* priv;
351  if (!lot) return NULL;
352  priv = GET_PRIVATE(lot);
353  return priv->splits;
354 }

◆ gnc_lot_get_title()

const char* gnc_lot_get_title ( const GNCLot *  )

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

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

369 {
370  if (!lot) return NULL;
371  return kvp_frame_get_string (gnc_lot_get_slots(lot), "/title");
372 }
KvpFrame * gnc_lot_get_slots(const GNCLot *lot)
Definition: gnc-lot.c:342

◆ gnc_lot_is_closed()

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 301 of file gnc-lot.c.

302 {
303  LotPrivate* priv;
304  if (!lot) return TRUE;
305  priv = GET_PRIVATE(lot);
306  if (0 > priv->is_closed) gnc_lot_get_balance (lot);
307  return priv->is_closed;
308 }
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
Definition: gnc-lot.c:404

◆ gnc_lot_make_default()

GNCLot* gnc_lot_make_default ( Account acc)

XXX: Document?

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

682 {
683  GNCLot * lot;
684  gint64 id;
685  char buff[200];
686 
687  lot = gnc_lot_new (qof_instance_get_book(acc));
688 
689  /* Provide a reasonable title for the new lot */
690  xaccAccountBeginEdit (acc);
691  id = kvp_frame_get_gint64 (xaccAccountGetSlots (acc), "/lot-mgmt/next-id");
692  snprintf (buff, 200, ("%s %" G_GINT64_FORMAT), _("Lot"), id);
693  kvp_frame_set_str (gnc_lot_get_slots (lot), "/title", buff);
694  id ++;
695  kvp_frame_set_gint64 (xaccAccountGetSlots (acc), "/lot-mgmt/next-id", id);
696  qof_instance_set_dirty (QOF_INSTANCE(acc));
697  xaccAccountCommitEdit (acc);
698  return lot;
699 }
QofBook * qof_instance_get_book(gconstpointer inst)
Definition: qofinstance.c:548
void kvp_frame_set_gint64(KvpFrame *frame, const gchar *path, gint64 ival)
void qof_instance_set_dirty(QofInstance *inst)
Set the dirty flag.
Definition: qofinstance.c:723
#define kvp_frame_set_str
Definition: kvp_frame.h:174
void xaccAccountBeginEdit(Account *acc)
Definition: Account.c:1143
KvpFrame * gnc_lot_get_slots(const GNCLot *lot)
Definition: gnc-lot.c:342
void xaccAccountCommitEdit(Account *acc)
Definition: Account.c:1184

◆ gnc_lot_set_closed_unknown()

void gnc_lot_set_closed_unknown ( GNCLot *  )

Reset closed flag so that it will be recalculated.

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

332 {
333  LotPrivate* priv;
334  if (lot != NULL)
335  {
336  priv = GET_PRIVATE(lot);
337  priv->is_closed = LOT_CLOSED_UNKNOWN;
338  }
339 }