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_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" |
Typedefs | |
| typedef _GncLotClass | GNCLotClass |
Functions | |
| GType | gnc_lot_get_type (void) |
| GNCLot * | gnc_lot_new (QofBook *) |
| void | gnc_lot_destroy (GNCLot *) |
| GNCLot * | gnc_lot_lookup (const GUID *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 *) |
| SplitList * | gnc_lot_get_split_list (const GNCLot *) |
| gint | gnc_lot_count_splits (const GNCLot *) |
| Account * | gnc_lot_get_account (const GNCLot *) |
| 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) |
| 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) |
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 323 of file gnc-lot.c.
00324 { 00325 Account * acc; 00326 if (!lot || !split) return; 00327 00328 ENTER ("(lot=%p, split=%p) %s amt=%s val=%s", lot, split, 00329 gnc_lot_get_title (lot), 00330 gnc_num_dbg_to_string (split->amount), 00331 gnc_num_dbg_to_string (split->value)); 00332 gnc_lot_begin_edit(lot); 00333 acc = xaccSplitGetAccount (split); 00334 qof_instance_set_dirty(QOF_INSTANCE(lot)); 00335 if (NULL == lot->account) 00336 { 00337 xaccAccountInsertLot (acc, lot); 00338 } 00339 else if (lot->account != acc) 00340 { 00341 PERR ("splits from different accounts cannot " 00342 "be added to this lot!\n" 00343 "\tlot account=\'%s\', split account=\'%s\'\n", 00344 xaccAccountGetName(lot->account), xaccAccountGetName (acc)); 00345 gnc_lot_commit_edit(lot); 00346 LEAVE("different accounts"); 00347 return; 00348 } 00349 00350 if (lot == split->lot) { 00351 gnc_lot_commit_edit(lot); 00352 LEAVE("already in lot"); 00353 return; /* handle not-uncommon no-op */ 00354 } 00355 if (split->lot) 00356 { 00357 gnc_lot_remove_split (split->lot, split); 00358 } 00359 split->lot = lot; 00360 00361 lot->splits = g_list_append (lot->splits, split); 00362 00363 /* for recomputation of is-closed */ 00364 lot->is_closed = -1; 00365 gnc_lot_commit_edit(lot); 00366 00367 qof_event_gen (&lot->inst, QOF_EVENT_MODIFY, NULL); 00368 LEAVE("added to lot"); 00369 }
The gnc_lot_get_account() routine returns the account with which this lot is associated.
Definition at line 175 of file gnc-lot.c.
| 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 240 of file gnc-lot.c.
00241 { 00242 GList *node; 00243 gnc_numeric zero = gnc_numeric_zero(); 00244 gnc_numeric baln = zero; 00245 if (!lot) return zero; 00246 00247 if (!lot->splits) 00248 { 00249 lot->is_closed = FALSE; 00250 return zero; 00251 } 00252 00253 /* Sum over splits; because they all belong to same account 00254 * they will have same denominator. 00255 */ 00256 for (node=lot->splits; node; node=node->next) 00257 { 00258 Split *s = node->data; 00259 gnc_numeric amt = xaccSplitGetAmount (s); 00260 baln = gnc_numeric_add_fixed (baln, amt); 00261 } 00262 00263 /* cache a zero balance as a closed lot */ 00264 if (gnc_numeric_equal (baln, zero)) 00265 { 00266 lot->is_closed = TRUE; 00267 } 00268 else 00269 { 00270 lot->is_closed = FALSE; 00271 } 00272 00273 return baln; 00274 }
| void gnc_lot_get_balance_before | ( | const GNCLot * | , | |
| const Split * | , | |||
| gnc_numeric * | , | |||
| gnc_numeric * | ||||
| ) |
The gnc_lot_get_balance_before routines 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 279 of file gnc-lot.c.
00281 { 00282 GList *node; 00283 gnc_numeric zero = gnc_numeric_zero(); 00284 gnc_numeric amt = zero; 00285 gnc_numeric val = zero; 00286 00287 if (lot && lot->splits) 00288 { 00289 Transaction *ta, *tb; 00290 const Split *target; 00291 /* If this is a gains split, find the source of the gains and use 00292 its transaction for the comparison. Gains splits are in separate 00293 transactions that may sort after non-gains transactions. */ 00294 target = xaccSplitGetGainsSourceSplit (split); 00295 if (target == NULL) 00296 target = split; 00297 tb = xaccSplitGetParent (target); 00298 for (node = lot->splits; node; node = node->next) 00299 { 00300 Split *s = node->data; 00301 Split *source = xaccSplitGetGainsSourceSplit (s); 00302 if (source == NULL) 00303 source = s; 00304 ta = xaccSplitGetParent (source); 00305 if ((ta == tb && source != target) || 00306 xaccTransOrder (ta, tb) < 0) 00307 { 00308 gnc_numeric tmpval = xaccSplitGetAmount (s); 00309 amt = gnc_numeric_add_fixed (amt, tmpval); 00310 tmpval = xaccSplitGetValue (s); 00311 val = gnc_numeric_add_fixed (val, tmpval); 00312 } 00313 } 00314 } 00315 00316 *amount = amt; 00317 *value = val; 00318 }
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 396 of file gnc-lot.c.
00397 { 00398 if (! lot->splits) 00399 return NULL; 00400 lot->splits = g_list_sort (lot->splits, (GCompareFunc) xaccSplitOrderDateOnly); 00401 return lot->splits->data; 00402 }
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 405 of file gnc-lot.c.
00406 { 00407 SplitList *node; 00408 00409 if (! lot->splits) 00410 return NULL; 00411 lot->splits = g_list_sort (lot->splits, (GCompareFunc) xaccSplitOrderDateOnly); 00412 00413 for (node = lot->splits; node->next; node = node->next) 00414 ; 00415 00416 return node->data; 00417 }
Every lot has a place to hang kvp data. This routine returns that place.
Definition at line 182 of file gnc-lot.c.
00183 { 00184 return qof_instance_get_slots(QOF_INSTANCE(lot)); 00185 }
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 188 of file gnc-lot.c.
| const char* gnc_lot_get_title | ( | const GNCLot * | ) |
| 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 167 of file gnc-lot.c.
00168 { 00169 if (!lot) return TRUE; 00170 if (0 > lot->is_closed) gnc_lot_get_balance (lot); 00171 return lot->is_closed; 00172 }
XXX: Document?
Definition at line 461 of file gnc-lot.c.
00462 { 00463 GNCLot * lot; 00464 gint64 id; 00465 char buff[200]; 00466 00467 lot = gnc_lot_new (qof_instance_get_book(acc)); 00468 00469 /* Provide a reasonable title for the new lot */ 00470 id = kvp_frame_get_gint64 (xaccAccountGetSlots (acc), "/lot-mgmt/next-id"); 00471 snprintf (buff, 200, ("%s %" G_GINT64_FORMAT), _("Lot"), id); 00472 kvp_frame_set_str (gnc_lot_get_slots (lot), "/title", buff); 00473 id ++; 00474 kvp_frame_set_gint64 (xaccAccountGetSlots (acc), "/lot-mgmt/next-id", id); 00475 00476 return lot; 00477 }
1.5.2