GnuCash  4.8a-176-g88ecf8dd1
Files

Data scrubbing, repairing and forward migration routines. More...

Files

file  Scrub.h
 convert single-entry accounts to clean double-entry
 
file  Scrub2.h
 Utilities to Convert Stock Accounts to use Lots.
 
file  Scrub3.h
 High-Level API for imposing Lot constraints.
 
file  ScrubBusiness.h
 Cleanup functions for business objects.
 

Double-Entry Scrubbing

Convert single-entry accounts to clean double-entry

Provides a set of functions and utilities for checking and repairing (formerly called 'scrubbing clean') single-entry accounts so that they can be promoted into self-consistent, clean double-entry accounts. Basically and additionally, this file collects all functions that turn old (deprecated) data structures into the current new data model.

The ScrubOrphans() methods search for transacations that contain splits that do not have a parent account. These "orphaned splits" are placed into an "orphan account" which the user will have to go into and clean up. Kind of like the unix "Lost+Found" directory for orphaned inodes.

void gnc_set_abort_scrub (gboolean abort)
 The gnc_set_abort_scrub () method causes a currently running scrub operation to stop, if abort is TRUE; gnc_set_abort_scrub(FALSE) must be called before any scrubbing operation.
 
gboolean gnc_get_abort_scrub (void)
 
gboolean gnc_get_ongoing_scrub (void)
 The gnc_get_ongoing_scrub () method returns TRUE if a scrub operation is ongoing.
 
void xaccTransScrubOrphans (Transaction *trans)
 The xaccTransScrubOrphans() method scrubs only the splits in the given transaction.
 
void xaccAccountScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
 The xaccAccountScrubOrphans() method performs this scrub only for the indicated account, and not for any of its children.
 
void xaccAccountTreeScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
 The xaccAccountTreeScrubOrphans() method performs this scrub for the indicated account and its children.
 
void xaccSplitScrub (Split *split)
 The xaccSplitScrub method ensures that if this split has the same commodity and currency, then it will have the same amount and value. More...
 
void xaccTransScrubSplits (Transaction *trans)
 The xacc*ScrubSplits() calls xaccSplitScrub() on each split in the respective structure: transaction, account, account & it's children, account-group.
 
void xaccAccountScrubSplits (Account *account)
 
void xaccAccountTreeScrubSplits (Account *account)
 
void xaccTransScrubImbalance (Transaction *trans, Account *root, Account *parent)
 The xaccScrubImbalance() method searches for transactions that do not balance to zero. More...
 
void xaccAccountScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
 
void xaccAccountTreeScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
 
void xaccTransScrubCurrency (Transaction *trans)
 The xaccTransScrubCurrency method fixes transactions without a common_currency by looking for the most commonly used currency among all the splits in the transaction. More...
 
void xaccAccountScrubCommodity (Account *account)
 The xaccAccountScrubCommodity method fixed accounts without a commodity by using the old account currency and security. More...
 
void xaccAccountTreeScrubCommodities (Account *acc)
 The xaccAccountTreeScrubCommodities will scrub the currency/commodity of all accounts & transactions in the specified account or any child account. More...
 
void xaccAccountTreeScrubQuoteSources (Account *root, gnc_commodity_table *table)
 This routine will migrate the information about price quote sources from the account data structures to the commodity data structures. More...
 
void xaccAccountScrubKvp (Account *account)
 Removes empty "notes", "placeholder", and "hbci" KVP slots from Accounts. More...
 
void xaccAccountScrubColorNotSet (QofBook *book)
 Remove color slots that have a "Not Set" value, since 2.4.0, fixed in 3.4 This should only be run once on a book.
 
void xaccTransScrubPostedDate (Transaction *trans)
 Changes Transaction date_posted timestamps from 00:00 local to 11:00 UTC. More...
 

Lot Management Routines

Provides the low-level API for checking and repairing ('scrubbing clean') the usage of Lots and lot balances in stock and commodity accounts.

Broken lots are repaired using a first-in, first-out (FIFO) accounting schedule.

This is a 'low-level' API in the sense that each routine accomplishes only one particular task needed to clean up a Lot. To clean up a Lot as a whole, you almost certainly want to use one of the high-level API routines from the Scrub3.h file.

void xaccAccountAssignLots (Account *acc)
 The xaccAccountAssignLots() routine will walk over all of the splits in an account, and make sure that each belongs to a lot. More...
 
void xaccLotFill (GNCLot *lot)
 The xaccLotFill() routine attempts to assign splits to the indicated lot until the lot balance goes to zero, or until there are no suitable (i.e. More...
 
void xaccLotScrubDoubleBalance (GNCLot *lot)
 The xaccLotScrubDoubleBalance() routine examines the indicated lot. More...
 
gboolean xaccScrubMergeSubSplits (Split *split, gboolean strict)
 The xaccScrubMergeSubSplits() routine will merge together all of the splits that were at one time split off from this split, but are no longer needed to be kept separate. More...
 
gboolean xaccScrubMergeLotSubSplits (GNCLot *lot, gboolean strict)
 The xaccScrubMergeLotSubSplits() routine does the same as the xaccScrubMergSubSplits, except that it does it for all of the splits in the lot.
 

High-Level Lot Constraint

Provides the high-level API for checking and repairing ('scrubbing clean') the usage of Lots and Cap Gains transactions in stock and commodity accounts.

gboolean xaccScrubLot (GNCLot *lot)
 The xaccScrubLot() routine makes sure that the indicated lot is self-consistent and properly balanced, and fixes it if its not. More...
 
void xaccAccountScrubLots (Account *acc)
 The xaccAccountScrubLots() routine makes sure that every split in the account is assigned to a lot, and that then, every lot is self-consistent (by calling xaccScrubLot() on each lot). More...
 
void xaccAccountTreeScrubLots (Account *acc)
 

Cleanup functions for business objects

Provides the high-level API for checking and repairing ('scrubbing clean') the various data objects used by the business functions.

gboolean gncScrubBusinessLot (GNCLot *lot)
 The gncScrubBusinessLot() function makes sure that the indicated lot has all the correct properties required for a lot used in the business features. More...
 
gboolean gncScrubBusinessSplit (Split *split)
 The gncScrubBusinessSplit() function will fix all issues found with the given split. More...
 
void gncScrubBusinessAccountLots (Account *acc, QofPercentageFunc percentagefunc)
 The gncScrubBusinessAccountLots() function will call gncScrubBusinessLot() on each lot in the given account. More...
 
void gncScrubBusinessAccountSplits (Account *acc, QofPercentageFunc percentagefunc)
 The gncScrubBusinessAccountSplits() function will call gncScrubBusinessSplit() on each split in the given account.
 
void gncScrubBusinessAccount (Account *acc, QofPercentageFunc percentagefunc)
 The gncScrubBusinessAccount() function will call all scrub functions relevant for a given account on condition the account is a business related account (Accounts Receivable or Accounts Payable type). More...
 
void gncScrubBusinessAccountTree (Account *acc, QofPercentageFunc percentagefunc)
 The gncScrubBusinessAccountTreeLots() function will call gncScrubBusinessAccount() on the given account and its sub accounts.
 

Detailed Description

Data scrubbing, repairing and forward migration routines.

These routines check and repair data, making sure that it is in a format that the current version of the GnuCash Engine likes. These routines serve both to provide backwards compatibility with older versions of GnuCash, and to fix or at least paper over possible current problems.

It is typically expected that the scrub routines are run over newly imported data, as well as during data file input.

In some cases, it is entirely appropriate to invoke these routines from the GUI, to validate that the user input through the GUI is in a format that the system likes. This includes things like balancing individual transactions, or assigning splits to lots, so that capital gains can be computed.

Function Documentation

◆ gncScrubBusinessAccount()

void gncScrubBusinessAccount ( Account acc,
QofPercentageFunc  percentagefunc 
)

The gncScrubBusinessAccount() function will call all scrub functions relevant for a given account on condition the account is a business related account (Accounts Receivable or Accounts Payable type).

This routine is the primary routine for fixing all (known) issues in a business account.

Definition at line 726 of file ScrubBusiness.c.

727 {
728  if (!acc) return;
729  if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;
730 
731  gncScrubBusinessAccountLots (acc, percentagefunc);
732  gncScrubBusinessAccountSplits (acc, percentagefunc);
733 }
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
Definition: Account.cpp:3236
void gncScrubBusinessAccountSplits(Account *acc, QofPercentageFunc percentagefunc)
The gncScrubBusinessAccountSplits() function will call gncScrubBusinessSplit() on each split in the g...
void gncScrubBusinessAccountLots(Account *acc, QofPercentageFunc percentagefunc)
The gncScrubBusinessAccountLots() function will call gncScrubBusinessLot() on each lot in the given a...
gboolean xaccAccountIsAPARType(GNCAccountType t)
Convenience function to check if the account is a valid business account type (meaning an Accounts Pa...
Definition: Account.cpp:4613

◆ gncScrubBusinessAccountLots()

void gncScrubBusinessAccountLots ( Account acc,
QofPercentageFunc  percentagefunc 
)

The gncScrubBusinessAccountLots() function will call gncScrubBusinessLot() on each lot in the given account.

This routine is the primary routine for ensuring that the lot structure of every lot of a business account is in good order.

Definition at line 611 of file ScrubBusiness.c.

612 {
613  LotList *lots, *node;
614  gint lot_count = 0;
615  gint curr_lot_no = 0;
616  const gchar *str;
617  const char *message = _( "Checking business lots in account %s: %u of %u");
618 
619  if (!acc) return;
620 
621  if (gnc_get_abort_scrub())
622  (percentagefunc)(NULL, -1.0);
623 
624  if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;
625 
626  str = xaccAccountGetName(acc);
627  str = str ? str : "(null)";
628 
629  ENTER ("(acc=%s)", str);
630  PINFO ("Cleaning up superfluous lot links in account %s\n", str);
632 
633  lots = xaccAccountGetLotList(acc);
634  lot_count = g_list_length (lots);
635  for (node = lots; node; node = node->next)
636  {
637  GNCLot *lot = node->data;
638 
639  PINFO("Start processing lot %d of %d",
640  curr_lot_no + 1, lot_count);
641 
642  if (curr_lot_no % 100 == 0)
643  {
644  char *progress_msg = g_strdup_printf (message, str, curr_lot_no, lot_count);
645  (percentagefunc)(progress_msg, (100 * curr_lot_no) / lot_count);
646  g_free (progress_msg);
647  }
648 
649  if (lot)
650  gncScrubBusinessLot (lot);
651 
652  PINFO("Finished processing lot %d of %d",
653  curr_lot_no + 1, lot_count);
654  curr_lot_no++;
655  }
656  g_list_free(lots);
658  (percentagefunc)(NULL, -1.0);
659  LEAVE ("(acc=%s)", str);
660 }
GList LotList
GList of GNCLots.
Definition: gnc-engine.h:209
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
Definition: Account.cpp:3236
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
LotList * xaccAccountGetLotList(const Account *acc)
The xaccAccountGetLotList() routine returns a list of all lots in this account.
Definition: Account.cpp:3987
gboolean xaccAccountIsAPARType(GNCAccountType t)
Convenience function to check if the account is a valid business account type (meaning an Accounts Pa...
Definition: Account.cpp:4613
gboolean gncScrubBusinessLot(GNCLot *lot)
The gncScrubBusinessLot() function makes sure that the indicated lot has all the correct properties r...
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1430
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition: Account.cpp:3258
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1471

◆ gncScrubBusinessLot()

gboolean gncScrubBusinessLot ( GNCLot *  lot)

The gncScrubBusinessLot() function makes sure that the indicated lot has all the correct properties required for a lot used in the business features.

Currently this function only does one thing: eliminate lot link transactions between invoice lots and payment lots (which were generated by GnuCash versions 2.6.0-2.6.3). Lot links between invoices and credit notes will still remain.

Scrubbing the lot may cause subsplits to be merged together, i.e. for splits to be deleted. This routine returns true if any splits were modified or deleted.

Definition at line 458 of file ScrubBusiness.c.

459 {
460  gboolean splits_deleted = FALSE;
461  gboolean dangling_payments = FALSE;
462  gboolean dangling_lot_link = FALSE;
463  Account *acc;
464  gchar *lotname=NULL;
465 
466  if (!lot) return FALSE;
467  lotname = g_strdup (gnc_lot_get_title (lot));
468  ENTER ("(lot=%p) %s", lot, lotname ? lotname : "(no lotname)");
469 
470  acc = gnc_lot_get_account (lot);
471  if (acc)
473 
474  /* Check invoice link consistency
475  * A lot should have both or neither of:
476  * - one split from an invoice transaction
477  * - an invoice-guid set
478  */
479  gncScrubInvoiceState (lot);
480 
481  // Scrub lot links.
482  // They should only remain when two document lots are linked together
483  xaccScrubMergeLotSubSplits (lot, FALSE);
484  splits_deleted = gncScrubLotLinks (lot);
485 
486  // Look for dangling payments and repair if found
487  dangling_lot_link = gncScrubLotIsSingleLotLinkSplit (lot);
488  if (dangling_lot_link)
489  {
490  dangling_payments = gncScrubLotDanglingPayments (lot);
491  if (dangling_payments)
492  splits_deleted |= gncScrubLotLinks (lot);
493  else
494  {
495  Split *split = gnc_lot_get_earliest_split (lot);
496  Transaction *trans = xaccSplitGetParent (split);
497  xaccTransDestroy (trans);
498  }
499  }
500 
501  // If lot is empty now, delete it
502  if (0 == gnc_lot_count_splits (lot))
503  {
504  PINFO("All splits were removed from lot, deleting");
505  gnc_lot_destroy (lot);
506  }
507 
508  if (acc)
510 
511  LEAVE ("(lot=%s, deleted=%d, dangling lot link=%d, dangling_payments=%d)",
512  lotname ? lotname : "(no lotname)", splits_deleted, dangling_lot_link,
513  dangling_payments);
514  g_free (lotname);
515 
516  return splits_deleted;
517 }
gboolean xaccScrubMergeLotSubSplits(GNCLot *lot, gboolean strict)
The xaccScrubMergeLotSubSplits() routine does the same as the xaccScrubMergSubSplits, except that it does it for all of the splits in the lot.
Definition: Scrub2.c:383
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
Split * gnc_lot_get_earliest_split(GNCLot *lot)
The gnc_lot_get_earliest_split() routine is a convenience routine that helps identify the earliest da...
Definition: gnc-lot.c:701
const char * gnc_lot_get_title(const GNCLot *lot)
Get and set the account title, or the account notes, or the marker.
Definition: gnc-lot.c:456
void xaccTransDestroy(Transaction *trans)
Destroys a transaction.
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1430
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Account * gnc_lot_get_account(const GNCLot *lot)
The gnc_lot_get_account() routine returns the account with which this lot is associated.
Definition: gnc-lot.c:392
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1471

◆ gncScrubBusinessSplit()

gboolean gncScrubBusinessSplit ( Split *  split)

The gncScrubBusinessSplit() function will fix all issues found with the given split.

Current checks are:

  • check if the split is part of a transaction that was generated as the result of a doubly posted invoice/bill/credit note. Refer to https://bugs.gnucash.org/show_bug.cgi?id=754209 to learn how this could have happened in the past. If such a transaction is found, its read-only status is removed and a warning is written to the trace file. Considering the user may already have added a correcting transaction we leave it up to the user to decide whether to also delete the transaction or not.
  • remove empty splits, on condition they aren't part of an invoice transaction. In this case the function returns true so the caller knows a split was removed.

Definition at line 520 of file ScrubBusiness.c.

521 {
522  Transaction *txn;
523  gboolean deleted_split = FALSE;
524 
525  if (!split) return FALSE;
526  ENTER ("(split=%p)", split);
527 
528  txn = xaccSplitGetParent (split);
529  if (txn)
530  {
531  gchar txntype = xaccTransGetTxnType (txn);
532  const gchar *read_only = xaccTransGetReadOnly (txn);
533  gboolean is_void = xaccTransGetVoidStatus (txn);
534  GNCLot *lot = xaccSplitGetLot (split);
535  GncInvoice *invoice = gncInvoiceGetInvoiceFromTxn (txn);
536  Transaction *posted_txn = gncInvoiceGetPostedTxn (invoice);
537 
538  /* Look for transactions as a result of double posting an invoice or bill
539  * Refer to https://bugs.gnucash.org/show_bug.cgi?id=754209
540  * to learn how this could have happened in the past.
541  * Characteristics of such transaction are:
542  * - read only
543  * - not voided (to ensure read only is set by the business functions)
544  * - transaction type is none (should be type invoice for proper post transactions)
545  * - assigned to a lot
546  */
547  if ((txntype == TXN_TYPE_NONE) && read_only && !is_void && lot)
548  {
549  const gchar *memo = _("Please delete this transaction. Explanation at https://wiki.gnucash.org/wiki/Business_Features_Issues#Double_posting");
550  gchar *txn_date = qof_print_date (xaccTransGetDateEntered (txn));
551  xaccTransClearReadOnly (txn);
552  xaccSplitSetMemo (split, memo);
553  gnc_lot_remove_split (lot, split);
554  PWARN("Cleared double post status of transaction \"%s\", dated %s. "
555  "Please delete transaction and verify balance.",
557  txn_date);
558  g_free (txn_date);
559  }
560  /* Next check for transactions which claim to be the posted transaction of
561  * an invoice but the invoice disagrees. In that case
562  */
563  else if (invoice && (txn != posted_txn))
564  {
565  const gchar *memo = _("Please delete this transaction. Explanation at https://wiki.gnucash.org/wiki/Business_Features_Issues#I_can.27t_delete_a_transaction_of_type_.22I.22_from_the_AR.2FAP_account");
566  gchar *txn_date = qof_print_date (xaccTransGetDateEntered (txn));
567  xaccTransClearReadOnly (txn);
569  xaccSplitSetMemo (split, memo);
570  if (lot)
571  {
572  gnc_lot_remove_split (lot, split);
573  gncInvoiceDetachFromLot (lot);
574  gncOwnerAttachToLot (gncInvoiceGetOwner(invoice), lot);
575  }
576  PWARN("Cleared double post status of transaction \"%s\", dated %s. "
577  "Please delete transaction and verify balance.",
579  txn_date);
580  g_free (txn_date);
581  }
582  /* Next delete any empty splits that aren't part of an invoice transaction
583  * Such splits may be the result of scrubbing the business lots, which can
584  * merge splits together while reducing superfluous lot links
585  */
586  else if (gnc_numeric_zero_p (xaccSplitGetAmount(split)) && !gncInvoiceGetInvoiceFromTxn (txn) && !is_void)
587  {
588  GNCLot *lot = xaccSplitGetLot (split);
589  time64 pdate = xaccTransGetDate (txn);
590  gchar *pdatestr = gnc_ctime (&pdate);
591  PINFO ("Destroying empty split %p from transaction %s (%s)", split, pdatestr, xaccTransGetDescription(txn));
592  xaccSplitDestroy (split);
593  g_free (pdatestr);
594 
595  // Also delete the lot containing this split if it was the last split in that lot
596  if (lot && (gnc_lot_count_splits (lot) == 0))
597  gnc_lot_destroy (lot);
598 
599  deleted_split = TRUE;
600  }
601 
602  }
603 
604  LEAVE ("(split=%p)", split);
605  return deleted_split;
606 }
char xaccTransGetTxnType(const Transaction *trans)
Returns the Transaction Type.
Definition: Transaction.c:2548
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
gboolean xaccSplitDestroy(Split *split)
Destructor.
Definition: Split.c:1470
const char * xaccTransGetReadOnly(Transaction *trans)
Returns a non-NULL value if this Transaction was marked as read-only with some specific "reason" text...
Definition: Transaction.c:2567
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
GncInvoice * gncInvoiceGetInvoiceFromTxn(const Transaction *txn)
Given a transaction, find and return the Invoice.
Definition: gncInvoice.c:1339
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
void xaccTransSetTxnType(Transaction *trans, char type)
Set the Transaction Type.
Definition: Transaction.c:2109
#define TXN_TYPE_NONE
No transaction type.
Definition: Transaction.h:124
char * qof_print_date(time64 secs)
Convenience; calls through to qof_print_date_dmy_buff().
Definition: gnc-date.cpp:617
void xaccSplitSetMemo(Split *split, const char *memo)
The memo is an arbitrary string associated with a split.
Definition: Split.c:1728
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
void gncOwnerAttachToLot(const GncOwner *owner, GNCLot *lot)
Attach an owner to a lot.
Definition: gncOwner.c:623
time64 xaccTransGetDateEntered(const Transaction *trans)
Retrieve the date of when the transaction was entered.
Definition: Transaction.c:2477
gboolean xaccTransGetVoidStatus(const Transaction *trans)
Retrieve information on whether or not a transaction has been voided.
Definition: Transaction.c:2799
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
gint64 time64
Many systems, including Microsoft Windows and BSD-derived Unixes like Darwin, are retaining the int-3...
Definition: gnc-date.h:93
char * gnc_ctime(const time64 *secs)
Return a string representation of a date from a 64-bit time value.
Definition: gnc-date.cpp:267
GNCLot * xaccSplitGetLot(const Split *split)
Returns the pointer to the debited/credited Lot where this split belongs to, or NULL if it doesn't be...
Definition: Split.c:1881
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account's commodity.
Definition: gmock-Split.cpp:69

◆ xaccAccountAssignLots()

void xaccAccountAssignLots ( Account acc)

The xaccAccountAssignLots() routine will walk over all of the splits in an account, and make sure that each belongs to a lot.

Currently, the default (and only implemented) assignment policy is a FIFO policy: Any splits that are not in a lot will be used to close the oldest open lot(s). If there are no open lots, a new lot will be started. By trying to close the oldest lots, this effectively implements a FIFO accounting policy.

The xaccAccountAssignLots() routine will walk over all of the splits in an account, and make sure that each belongs to a lot.

If a split does not belong to any lots, poke it into one.

Definition at line 58 of file Scrub2.c.

59 {
60  SplitList *splits, *node;
61 
62  if (!acc) return;
63 
64  ENTER ("acc=%s", xaccAccountGetName(acc));
66 
67 restart_loop:
68  splits = xaccAccountGetSplitList(acc);
69  for (node = splits; node; node = node->next)
70  {
71  Split * split = node->data;
72 
73  /* If already in lot, then no-op */
74  if (split->lot) continue;
75 
76  /* Skip voided transactions */
77  if (gnc_numeric_zero_p (split->amount) &&
78  xaccTransGetVoidStatus(split->parent)) continue;
79 
80  if (xaccSplitAssign (split)) goto restart_loop;
81  }
83  LEAVE ("acc=%s", xaccAccountGetName(acc));
84 }
SplitList * xaccAccountGetSplitList(const Account *acc)
The xaccAccountGetSplitList() routine returns a pointer to a GList of the splits in the account...
Definition: Account.cpp:3964
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
GList SplitList
GList of Split.
Definition: gnc-engine.h:211
gboolean xaccTransGetVoidStatus(const Transaction *trans)
Retrieve information on whether or not a transaction has been voided.
Definition: Transaction.c:2799
gboolean xaccSplitAssign(Split *split)
The`xaccSplitAssign() routine will take the indicated split and, if it doesn't already belong to a lo...
Definition: cap-gains.c:428
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1430
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition: Account.cpp:3258
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1471

◆ xaccAccountScrubCommodity()

void xaccAccountScrubCommodity ( Account account)

The xaccAccountScrubCommodity method fixed accounts without a commodity by using the old account currency and security.

Definition at line 1187 of file Scrub.c.

1188 {
1189  gnc_commodity *commodity;
1190 
1191  if (!account) return;
1192  if (xaccAccountGetType(account) == ACCT_TYPE_ROOT) return;
1193 
1194  commodity = xaccAccountGetCommodity (account);
1195  if (commodity) return;
1196 
1197  /* Use the 'obsolete' routines to try to figure out what the
1198  * account commodity should have been. */
1199  commodity = xaccAccountGetCommodity (account);
1200  if (commodity)
1201  {
1202  xaccAccountSetCommodity (account, commodity);
1203  return;
1204  }
1205 
1206  commodity = DxaccAccountGetCurrency (account);
1207  if (commodity)
1208  {
1209  xaccAccountSetCommodity (account, commodity);
1210  return;
1211  }
1212 
1213  PERR ("Account \"%s\" does not have a commodity!",
1214  xaccAccountGetName(account));
1215 }
gnc_commodity * DxaccAccountGetCurrency(const Account *acc)
Definition: Account.cpp:3383
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
Definition: Account.cpp:3236
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity.
Definition: Account.cpp:3405
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition: Account.cpp:3258
The hidden root account of an account tree.
Definition: Account.h:156
void xaccAccountSetCommodity(Account *acc, gnc_commodity *com)
Set the account's commodity.
Definition: Account.cpp:2613

◆ xaccAccountScrubKvp()

void xaccAccountScrubKvp ( Account account)

Removes empty "notes", "placeholder", and "hbci" KVP slots from Accounts.

Definition at line 1333 of file Scrub.c.

1334 {
1335  GValue v = G_VALUE_INIT;
1336  gchar *str2;
1337 
1338  if (!account) return;
1339  scrub_depth++;
1340 
1341  qof_instance_get_kvp (QOF_INSTANCE (account), &v, 1, "notes");
1342  if (G_VALUE_HOLDS_STRING (&v))
1343  {
1344  str2 = g_strstrip(g_value_dup_string(&v));
1345  if (strlen(str2) == 0)
1346  qof_instance_slot_delete (QOF_INSTANCE (account), "notes");
1347  g_free(str2);
1348  }
1349 
1350  qof_instance_get_kvp (QOF_INSTANCE (account), &v, 1, "placeholder");
1351  if ((G_VALUE_HOLDS_STRING (&v) &&
1352  strcmp(g_value_get_string (&v), "false") == 0) ||
1353  (G_VALUE_HOLDS_BOOLEAN (&v) && ! g_value_get_boolean (&v)))
1354  qof_instance_slot_delete (QOF_INSTANCE (account), "placeholder");
1355 
1356  g_value_unset (&v);
1357  qof_instance_slot_delete_if_empty (QOF_INSTANCE (account), "hbci");
1358  scrub_depth--;
1359 }
void qof_instance_get_kvp(QofInstance *, GValue *value, unsigned count,...)
Retrieves the contents of a KVP slot into a provided GValue.

◆ xaccAccountScrubLots()

void xaccAccountScrubLots ( Account acc)

The xaccAccountScrubLots() routine makes sure that every split in the account is assigned to a lot, and that then, every lot is self-consistent (by calling xaccScrubLot() on each lot).

This routine is the primary routine for ensuring that the lot structure, and the cap-gains for an account are in good order.

Most GUI routines will want to use one of these xacc[*]ScrubLots() routines, instead of the various component routines, since it will usually makes sense to work only with these high-level routines.

Definition at line 159 of file Scrub3.c.

160 {
161  LotList *lots, *node;
162  if (!acc) return;
163  if (FALSE == xaccAccountHasTrades (acc)) return;
164 
165  ENTER ("(acc=%s)", xaccAccountGetName(acc));
167  xaccAccountAssignLots (acc);
168 
169  lots = xaccAccountGetLotList(acc);
170  for (node = lots; node; node = node->next)
171  {
172  GNCLot *lot = node->data;
173  xaccScrubLot (lot);
174  }
175  g_list_free(lots);
177  LEAVE ("(acc=%s)", xaccAccountGetName(acc));
178 }
GList LotList
GList of GNCLots.
Definition: gnc-engine.h:209
gboolean xaccAccountHasTrades(const Account *acc)
The xaccAccountHasTrades() method checks to see if the indicated account is used in the trading of co...
Definition: cap-gains.c:79
void xaccAccountAssignLots(Account *acc)
Loop over all splits, and make sure that every split belongs to some lot.
Definition: Scrub2.c:58
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
LotList * xaccAccountGetLotList(const Account *acc)
The xaccAccountGetLotList() routine returns a list of all lots in this account.
Definition: Account.cpp:3987
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1430
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
gboolean xaccScrubLot(GNCLot *lot)
The xaccScrubLot() routine makes sure that the indicated lot is self-consistent and properly balanced...
Definition: Scrub3.c:85
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition: Account.cpp:3258
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1471

◆ xaccAccountTreeScrubCommodities()

void xaccAccountTreeScrubCommodities ( Account acc)

The xaccAccountTreeScrubCommodities will scrub the currency/commodity of all accounts & transactions in the specified account or any child account.

Definition at line 1252 of file Scrub.c.

1253 {
1254  if (!acc) return;
1255  scrub_depth++;
1256  xaccAccountTreeForEachTransaction (acc, scrub_trans_currency_helper, NULL);
1257 
1258  scrub_account_commodity_helper (acc, NULL);
1259  gnc_account_foreach_descendant (acc, scrub_account_commodity_helper, NULL);
1260  scrub_depth--;
1261 }
int xaccAccountTreeForEachTransaction(Account *acc, TransactionCallback proc, void *data)
Traverse all of the transactions in the given account group.
void gnc_account_foreach_descendant(const Account *acc, AccountCb thunk, gpointer user_data)
This method will traverse all children of this accounts and their descendants, calling 'func' on each...
Definition: Account.cpp:3202

◆ xaccAccountTreeScrubQuoteSources()

void xaccAccountTreeScrubQuoteSources ( Account root,
gnc_commodity_table *  table 
)

This routine will migrate the information about price quote sources from the account data structures to the commodity data structures.

It first checks to see if this is necessary since, for the time being, the quote information will still be written out as part of the account. Just in case anyone needs to fall back from CVS to a production version of code.

Parameters
rootA pointer to the root account containing all accounts in the current book.
tableA pointer to the commodity table for the current book.

Definition at line 1310 of file Scrub.c.

1311 {
1312  gboolean new_style = FALSE;
1313  ENTER(" ");
1314 
1315  if (!root || !table)
1316  {
1317  LEAVE("Oops");
1318  return;
1319  }
1320  scrub_depth++;
1321  gnc_commodity_table_foreach_commodity (table, check_quote_source, &new_style);
1322 
1323  move_quote_source(root, GINT_TO_POINTER(new_style));
1324  gnc_account_foreach_descendant (root, move_quote_source,
1325  GINT_TO_POINTER(new_style));
1326  LEAVE("Migration done");
1327  scrub_depth--;
1328 }
gboolean gnc_commodity_table_foreach_commodity(const gnc_commodity_table *table, gboolean(*f)(gnc_commodity *cm, gpointer user_data), gpointer user_data)
Call a function once for each commodity in the commodity table.
void gnc_account_foreach_descendant(const Account *acc, AccountCb thunk, gpointer user_data)
This method will traverse all children of this accounts and their descendants, calling 'func' on each...
Definition: Account.cpp:3202
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282

◆ xaccLotFill()

void xaccLotFill ( GNCLot *  lot)

The xaccLotFill() routine attempts to assign splits to the indicated lot until the lot balance goes to zero, or until there are no suitable (i.e.

unassigned) splits left in the account. It uses the default accounting policy to choose the splits to fill out the lot.

Definition at line 96 of file Scrub2.c.

97 {
98  Account *acc;
99  Split *split;
100  GNCPolicy *pcy;
101 
102  if (!lot) return;
103  acc = gnc_lot_get_account(lot);
104  pcy = gnc_account_get_policy(acc);
105 
106  ENTER ("(lot=%s, acc=%s)", gnc_lot_get_title(lot), xaccAccountGetName(acc));
107 
108  /* If balance already zero, we have nothing to do. */
109  if (gnc_lot_is_closed (lot))
110  {
111  LEAVE ("Lot Closed (lot=%s, acc=%s)", gnc_lot_get_title(lot),
112  xaccAccountGetName(acc));
113  return;
114  }
115  split = pcy->PolicyGetSplit (pcy, lot);
116  if (!split)
117  {
118  LEAVE ("No Split (lot=%s, acc=%s)", gnc_lot_get_title(lot),
119  xaccAccountGetName(acc));
120  return; /* Handle the common case */
121  }
122 
123  /* Reject voided transactions */
124  if (gnc_numeric_zero_p(split->amount) &&
125  xaccTransGetVoidStatus(split->parent))
126  {
127  LEAVE ("Voided transaction (lot=%s, acc=%s)",
129  return;
130  }
131 
132  xaccAccountBeginEdit (acc);
133 
134  /* Loop until we've filled up the lot, (i.e. till the
135  * balance goes to zero) or there are no splits left. */
136  while (1)
137  {
138  Split *subsplit;
139 
140  subsplit = xaccSplitAssignToLot (split, lot);
141  if (subsplit == split)
142  {
143  PERR ("Accounting Policy gave us a split that "
144  "doesn't fit into this lot\n"
145  "lot baln=%s, isclosed=%d, aplit amt=%s",
147  gnc_lot_is_closed (lot),
148  gnc_num_dbg_to_string (split->amount));
149  break;
150  }
151 
152  if (gnc_lot_is_closed (lot)) break;
153 
154  split = pcy->PolicyGetSplit (pcy, lot);
155  if (!split) break;
156  }
157  xaccAccountCommitEdit (acc);
158  LEAVE ("(lot=%s, acc=%s)", gnc_lot_get_title(lot), xaccAccountGetName(acc));
159 }
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
const char * gnc_lot_get_title(const GNCLot *lot)
Get and set the account title, or the account notes, or the marker.
Definition: gnc-lot.c:456
Split * xaccSplitAssignToLot(Split *split, GNCLot *lot)
The xaccSplitAssignToLot() routine will fit the indicated split into the indicated lot...
Definition: cap-gains.c:221
gboolean xaccTransGetVoidStatus(const Transaction *trans)
Retrieve information on whether or not a transaction has been voided.
Definition: Transaction.c:2799
gboolean gnc_lot_is_closed(GNCLot *lot)
The gnc_lot_is_closed() routine returns a boolean flag: is this lot closed? A lot is closed if its ba...
Definition: gnc-lot.c:382
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1430
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Account * gnc_lot_get_account(const GNCLot *lot)
The gnc_lot_get_account() routine returns the account with which this lot is associated.
Definition: gnc-lot.c:392
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition: Account.cpp:3258
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1471
GNCPolicy * gnc_account_get_policy(Account *acc)
Get the account's lot order policy.
Definition: Account.cpp:2084
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
The gnc_lot_get_balance() routine returns the balance of the lot.
Definition: gnc-lot.c:530

◆ xaccLotScrubDoubleBalance()

void xaccLotScrubDoubleBalance ( GNCLot *  lot)

The xaccLotScrubDoubleBalance() routine examines the indicated lot.

If it is open, it does nothing. If it is closed, it then verifies that the lot is 'double balanced'. By 'double balance', we mean that both the sum of the split amounts is zero, and that the sum of the split values is zero. If the lot is closed and the sum of the values is not zero, the lot is considered to have a 'realized gain or loss' that hadn't been correctly handled. This routine then creates a balancing transaction to so as to record the realized gain/loss, adds it to the lot, and adds it to a gain/loss account. If there is no default gain/loss account, it creates one.

Definition at line 164 of file Scrub2.c.

165 {
166  gnc_commodity *currency = NULL;
167  SplitList *snode;
168  GList *node;
169  gnc_numeric zero = gnc_numeric_zero();
170  gnc_numeric value = zero;
171 
172  if (!lot) return;
173 
174  ENTER ("lot=%s", gnc_lot_get_title(lot));
175 
176  for (snode = gnc_lot_get_split_list(lot); snode; snode = snode->next)
177  {
178  Split *s = snode->data;
179  xaccSplitComputeCapGains (s, NULL);
180  }
181 
182  /* We double-check only closed lots */
183  if (FALSE == gnc_lot_is_closed (lot))
184  {
185  LEAVE ("lot=%s is closed", gnc_lot_get_title(lot));
186  return;
187  }
188 
189  for (snode = gnc_lot_get_split_list(lot); snode; snode = snode->next)
190  {
191  Split *s = snode->data;
192  Transaction *trans = s->parent;
193 
194  /* Check to make sure all splits in the lot have a common currency */
195  if (NULL == currency)
196  {
197  currency = trans->common_currency;
198  }
199  if (FALSE == gnc_commodity_equiv (currency, trans->common_currency))
200  {
201  /* This lot has mixed currencies. Can't double-balance.
202  * Silently punt */
203  PWARN ("Lot with multiple currencies:\n"
204  "\ttrans=%s curr=%s", xaccTransGetDescription(trans),
205  gnc_commodity_get_fullname(trans->common_currency));
206  break;
207  }
208 
209  /* Now, total up the values */
210  value = gnc_numeric_add (value, xaccSplitGetValue (s),
212  PINFO ("Split=%p value=%s Accum Lot value=%s", s,
213  gnc_num_dbg_to_string (s->value),
214  gnc_num_dbg_to_string (value));
215 
216  }
217 
218  if (FALSE == gnc_numeric_equal (value, zero))
219  {
220  /* Unhandled error condition. Not sure what to do here,
221  * Since the ComputeCapGains should have gotten it right.
222  * I suppose there might be small rounding errors, a penny or two,
223  * the ideal thing would to figure out why there's a rounding
224  * error, and fix that.
225  */
226  PERR ("Closed lot fails to double-balance !! lot value=%s",
227  gnc_num_dbg_to_string (value));
228  for (node = gnc_lot_get_split_list(lot); node; node = node->next)
229  {
230  Split *s = node->data;
231  PERR ("s=%p amt=%s val=%s", s,
232  gnc_num_dbg_to_string(s->amount),
233  gnc_num_dbg_to_string(s->value));
234  }
235  }
236 
237  LEAVE ("lot=%s", gnc_lot_get_title(lot));
238 }
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
void xaccSplitComputeCapGains(Split *split, Account *gain_acc)
The xaccSplitComputeCapGains() routine computes the cap gains or losses for the indicated split...
Definition: cap-gains.c:528
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a+b.
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:189
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
const char * gnc_lot_get_title(const GNCLot *lot)
Get and set the account title, or the account notes, or the marker.
Definition: gnc-lot.c:456
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
GList SplitList
GList of Split.
Definition: gnc-engine.h:211
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
The gnc_lot_get_split_list() routine returns a GList of all the splits in this lot.
Definition: gnc-lot.c:436
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
Retrieve the full name for the specified commodity.
gboolean gnc_lot_is_closed(GNCLot *lot)
The gnc_lot_is_closed() routine returns a boolean flag: is this lot closed? A lot is closed if its ba...
Definition: gnc-lot.c:382
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction's commodity.
Definition: gmock-Split.cpp:84
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.
Definition: gnc-numeric.h:246
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.

◆ xaccScrubLot()

gboolean xaccScrubLot ( GNCLot *  lot)

The xaccScrubLot() routine makes sure that the indicated lot is self-consistent and properly balanced, and fixes it if its not.

This is an important routine to call if the amount of any split in the lot is changed. That's because (obviously) changing split values is guaranteed to throw off lot balances. This routine may end up closing the lot, or at least trying to. It will also cause cap gains to be recomputed.

Scrubbing the lot may cause subsplits to be merged together, i.e. for splits to be deleted. This routine returns true if any splits were deleted.

Definition at line 85 of file Scrub3.c.

86 {
87  gboolean splits_deleted = FALSE;
88  gnc_numeric lot_baln;
89  gboolean opening_baln_is_pos, lot_baln_is_pos;
90  Account *acc;
91  GNCPolicy *pcy;
92 
93  if (!lot) return FALSE;
94  ENTER ("(lot=%p) %s", lot, gnc_lot_get_title(lot));
95 
96  acc = gnc_lot_get_account (lot);
97  pcy = gnc_account_get_policy(acc);
99  xaccScrubMergeLotSubSplits (lot, TRUE);
100 
101  /* If the lot balance is zero, we don't need to rebalance */
102  lot_baln = gnc_lot_get_balance (lot);
103  PINFO ("lot baln=%s for %s", gnc_num_dbg_to_string (lot_baln),
104  gnc_lot_get_title(lot));
105  if (! gnc_numeric_zero_p (lot_baln))
106  {
107  SplitList *node;
108  gnc_numeric opening_baln;
109 
110  /* Get the opening balance for this lot */
111  pcy->PolicyGetLotOpening (pcy, lot, &opening_baln, NULL, NULL);
112  PINFO ("lot opener baln=%s", gnc_num_dbg_to_string (opening_baln));
113 
114  /* If the lot is fat, give the boot to all the non-opening
115  * splits, and refill it */
116  opening_baln_is_pos = gnc_numeric_positive_p(opening_baln);
117  lot_baln_is_pos = gnc_numeric_positive_p(lot_baln);
118  if ((opening_baln_is_pos || lot_baln_is_pos) &&
119  ((!opening_baln_is_pos) || (!lot_baln_is_pos)))
120  {
121 rethin:
122  for (node = gnc_lot_get_split_list(lot); node; node = node->next)
123  {
124  Split *s = node->data;
125  if (pcy->PolicyIsOpeningSplit (pcy, lot, s)) continue;
126  gnc_lot_remove_split (lot, s);
127  goto rethin;
128  }
129  }
130 
131  /* At this point the lot is thin, so try to fill it */
132  xaccLotFill (lot);
133 
134  /* Make sure there are no subsplits. */
135  splits_deleted = xaccScrubMergeLotSubSplits (lot, TRUE);
136  }
137 
138  /* Now re-compute cap gains, and then double-check that.
139  * But we only compute cap-gains if gains are possible;
140  * that is if the lot commodity is not the same as the
141  * currency. That is, one can't possibly have gains
142  * selling dollars for dollars. The business modules
143  * use lots with lot commodity == lot currency.
144  */
145  if (gains_possible (lot))
146  {
147  xaccLotComputeCapGains (lot, NULL);
149  }
151 
152  LEAVE ("(lot=%s, deleted=%d)", gnc_lot_get_title(lot), splits_deleted);
153  return splits_deleted;
154 }
gboolean xaccScrubMergeLotSubSplits(GNCLot *lot, gboolean strict)
The xaccScrubMergeLotSubSplits() routine does the same as the xaccScrubMergSubSplits, except that it does it for all of the splits in the lot.
Definition: Scrub2.c:383
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
void xaccLotFill(GNCLot *lot)
The xaccLotFill() routine attempts to assign splits to the indicated lot until the lot balance goes t...
Definition: Scrub2.c:96
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
const char * gnc_lot_get_title(const GNCLot *lot)
Get and set the account title, or the account notes, or the marker.
Definition: gnc-lot.c:456
GList SplitList
GList of Split.
Definition: gnc-engine.h:211
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
The gnc_lot_get_split_list() routine returns a GList of all the splits in this lot.
Definition: gnc-lot.c:436
void xaccLotScrubDoubleBalance(GNCLot *lot)
The xaccLotScrubDoubleBalance() routine examines the indicated lot.
Definition: Scrub2.c:164
gboolean gnc_numeric_positive_p(gnc_numeric a)
Returns 1 if a > 0, otherwise returns 0.
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1430
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Account * gnc_lot_get_account(const GNCLot *lot)
The gnc_lot_get_account() routine returns the account with which this lot is associated.
Definition: gnc-lot.c:392
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1471
GNCPolicy * gnc_account_get_policy(Account *acc)
Get the account's lot order policy.
Definition: Account.cpp:2084
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
The gnc_lot_get_balance() routine returns the balance of the lot.
Definition: gnc-lot.c:530

◆ xaccScrubMergeSubSplits()

gboolean xaccScrubMergeSubSplits ( Split *  split,
gboolean  strict 
)

The xaccScrubMergeSubSplits() routine will merge together all of the splits that were at one time split off from this split, but are no longer needed to be kept separate.

Splits might be split up if they need to be divided over multiple lots; they can be merged back together if the lots change. In particular, two sub-splits may be merged if they are in the same lot, or in no lot. Note that, by definition, all subsplits belong to the same transaction.

There are two ways to find matching subsplits. The first way will consider splits to be subsplits only if they are explicitly marked as such while splitting the original split. Set strict to TRUE for this matching algorithm.

The second way is more relaxed. It will consider any two splits that happen to be part of the same lot and the same transaction to be subsplits. Set strict to FALSE for this matching algorithm.

The routine returns TRUE if a merger was performed, else it returns FALSE.

Definition at line 322 of file Scrub2.c.

323 {
324  gboolean rc = FALSE;
325  Transaction *txn;
326  SplitList *node;
327  GNCLot *lot;
328 
329  if (strict && (FALSE == is_subsplit (split))) return FALSE;
330 
331  txn = split->parent;
332 
333  // Don't mess with splits from an invoice transaction
334  // Those are the responsibility of the business code
335  if (gncInvoiceGetInvoiceFromTxn (txn)) return FALSE;
336 
337  lot = xaccSplitGetLot (split);
338 
339  ENTER ("(Lot=%s)", gnc_lot_get_title(lot));
340 restart:
341  for (node = txn->splits; node; node = node->next)
342  {
343  Split *s = node->data;
344  if (xaccSplitGetLot (s) != lot) continue;
345  if (s == split) continue;
346  if (qof_instance_get_destroying(s)) continue;
347 
348  // Don't mess with splits from an invoice transaction
349  // Those are the responsibility of the business code
350  if (gncInvoiceGetInvoiceFromTxn (s->parent)) return FALSE;
351 
352  if (strict)
353  {
354  /* OK, this split is in the same lot (and thus same account)
355  * as the indicated split. Make sure it is really a subsplit
356  * of the split we started with. It's possible to have two
357  * splits in the same lot and transaction that are not subsplits
358  * of each other, the test-period test suite does this, for
359  * example. Only worry about adjacent sub-splits. By
360  * repeatedly merging adjacent subsplits, we'll get the non-
361  * adjacent ones too. */
362  if (!xaccSplitIsPeerSplit (split, s))
363  continue;
364  }
365 
366  merge_splits (split, s);
367  rc = TRUE;
368  goto restart;
369  }
370  if (rc && gnc_numeric_zero_p (split->amount))
371  {
372  time64 pdate = xaccTransGetDate (txn);
373  gchar *pdatestr = gnc_ctime (&pdate);
374  PWARN ("Result of merge has zero amt!");
375  PWARN ("Transaction details - posted date %s - description %s", pdatestr, xaccTransGetDescription(txn));
376  g_free (pdatestr);
377  }
378  LEAVE (" splits merged=%d", rc);
379  return rc;
380 }
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
gboolean qof_instance_get_destroying(gconstpointer ptr)
Retrieve the flag that indicates whether or not this object is about to be destroyed.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
GncInvoice * gncInvoiceGetInvoiceFromTxn(const Transaction *txn)
Given a transaction, find and return the Invoice.
Definition: gncInvoice.c:1339
const char * gnc_lot_get_title(const GNCLot *lot)
Get and set the account title, or the account notes, or the marker.
Definition: gnc-lot.c:456
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
GList SplitList
GList of Split.
Definition: gnc-engine.h:211
gboolean xaccSplitIsPeerSplit(const Split *split, const Split *other_split)
Report if a split is a peer of this one.
Definition: Split.c:2044
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
gint64 time64
Many systems, including Microsoft Windows and BSD-derived Unixes like Darwin, are retaining the int-3...
Definition: gnc-date.h:93
char * gnc_ctime(const time64 *secs)
Return a string representation of a date from a 64-bit time value.
Definition: gnc-date.cpp:267
GNCLot * xaccSplitGetLot(const Split *split)
Returns the pointer to the debited/credited Lot where this split belongs to, or NULL if it doesn't be...
Definition: Split.c:1881

◆ xaccSplitScrub()

void xaccSplitScrub ( Split *  split)

The xaccSplitScrub method ensures that if this split has the same commodity and currency, then it will have the same amount and value.

If the commodity is the currency, the split->amount is set to the split value. In addition, if this split is an orphan, that is fixed first. If the split account doesn't have a commodity declared, an attempt is made to fix that first.

Definition at line 235 of file Scrub.c.

236 {
237  Account *account;
238  Transaction *trans;
239  gnc_numeric value, amount;
240  gnc_commodity *currency, *acc_commodity;
241  int scu;
242 
243  if (!split) return;
244  ENTER ("(split=%p)", split);
245 
246  trans = xaccSplitGetParent (split);
247  if (!trans)
248  {
249  LEAVE("no trans");
250  return;
251  }
252 
253  account = xaccSplitGetAccount (split);
254 
255  /* If there's no account, this split is an orphan.
256  * We need to fix that first, before proceeding.
257  */
258  if (!account)
259  {
260  xaccTransScrubOrphans (trans);
261  account = xaccSplitGetAccount (split);
262  }
263 
264  /* Grrr... the register gnc_split_register_load() line 203 of
265  * src/register/ledger-core/split-register-load.c will create
266  * free-floating bogus transactions. Ignore these for now ...
267  */
268  if (!account)
269  {
270  PINFO ("Free Floating Transaction!");
271  LEAVE ("no account");
272  return;
273  }
274 
275  /* Split amounts and values should be valid numbers */
276  value = xaccSplitGetValue (split);
277  if (gnc_numeric_check (value))
278  {
279  value = gnc_numeric_zero();
280  xaccSplitSetValue (split, value);
281  }
282 
283  amount = xaccSplitGetAmount (split);
284  if (gnc_numeric_check (amount))
285  {
286  amount = gnc_numeric_zero();
287  xaccSplitSetAmount (split, amount);
288  }
289 
290  currency = xaccTransGetCurrency (trans);
291 
292  /* If the account doesn't have a commodity,
293  * we should attempt to fix that first.
294  */
295  acc_commodity = xaccAccountGetCommodity(account);
296  if (!acc_commodity)
297  {
298  xaccAccountScrubCommodity (account);
299  }
300  if (!acc_commodity || !gnc_commodity_equiv(acc_commodity, currency))
301  {
302  LEAVE ("(split=%p) inequiv currency", split);
303  return;
304  }
305 
306  scu = MIN (xaccAccountGetCommoditySCU (account),
307  gnc_commodity_get_fraction (currency));
308 
309  if (gnc_numeric_same (amount, value, scu, GNC_HOW_RND_ROUND_HALF_UP))
310  {
311  LEAVE("(split=%p) different values", split);
312  return;
313  }
314 
315  /*
316  * This will be hit every time you answer yes to the dialog "The
317  * current transaction has changed. Would you like to record it.
318  */
319  PINFO ("Adjusted split with mismatched values, desc=\"%s\" memo=\"%s\""
320  " old amount %s %s, new amount %s",
321  trans->description, split->memo,
323  gnc_commodity_get_mnemonic (currency),
325 
326  xaccTransBeginEdit (trans);
327  xaccSplitSetAmount (split, value);
328  xaccTransCommitEdit (trans);
329  LEAVE ("(split=%p)", split);
330 }
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction's commodity.
Definition: gmock-Split.cpp:92
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
void xaccAccountScrubCommodity(Account *account)
The xaccAccountScrubCommodity method fixed accounts without a commodity by using the old account curr...
Definition: Scrub.c:1187
int xaccAccountGetCommoditySCU(const Account *acc)
Return the SCU for the account.
Definition: Account.cpp:2682
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
Definition: gnc-numeric.h:166
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have...
Definition: gmock-Split.cpp:77
void xaccTransScrubOrphans(Transaction *trans)
The xaccTransScrubOrphans() method scrubs only the splits in the given transaction.
Definition: Scrub.c:178
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction's commodity.
Definition: gmock-Split.cpp:84
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
Definition: gmock-Split.cpp:53
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity.
Definition: Account.cpp:3405
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
Definition: Transaction.c:1366
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
int gnc_numeric_same(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Equivalence predicate: Convert both a and b to denom using the specified DENOM and method HOW...
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account's commodity.
Definition: gmock-Split.cpp:69

◆ xaccTransScrubCurrency()

void xaccTransScrubCurrency ( Transaction *  trans)

The xaccTransScrubCurrency method fixes transactions without a common_currency by looking for the most commonly used currency among all the splits in the transaction.

If this fails it falls back to using the old account currency and security fields of the parent accounts of the transaction's splits.

Definition at line 1070 of file Scrub.c.

1071 {
1072  SplitList *node;
1073  gnc_commodity *currency;
1074 
1075  if (!trans) return;
1076 
1077  /* If there are any orphaned splits in a transaction, then the
1078  * this routine will fail. Therefore, we want to make sure that
1079  * there are no orphans (splits without parent account).
1080  */
1081  xaccTransScrubOrphans (trans);
1082 
1083  currency = xaccTransGetCurrency (trans);
1084  if (currency && gnc_commodity_is_currency(currency)) return;
1085 
1086  currency = xaccTransFindCommonCurrency (trans, qof_instance_get_book(trans));
1087  if (currency)
1088  {
1089  xaccTransBeginEdit (trans);
1090  xaccTransSetCurrency (trans, currency);
1091  xaccTransCommitEdit (trans);
1092  }
1093  else
1094  {
1095  if (NULL == trans->splits)
1096  {
1097  PWARN ("Transaction \"%s\" has no splits in it!", trans->description);
1098  }
1099  else
1100  {
1101  SplitList *node;
1102  char guid_str[GUID_ENCODING_LENGTH + 1];
1103  guid_to_string_buff(xaccTransGetGUID(trans), guid_str);
1104  PWARN ("no common transaction currency found for trans=\"%s\" (%s);",
1105  trans->description, guid_str);
1106 
1107  for (node = trans->splits; node; node = node->next)
1108  {
1109  Split *split = node->data;
1110  if (NULL == split->acc)
1111  {
1112  PWARN (" split=\"%s\" is not in any account!", split->memo);
1113  }
1114  else
1115  {
1116  gnc_commodity *currency = xaccAccountGetCommodity(split->acc);
1117  PWARN ("setting to split=\"%s\" account=\"%s\" commodity=\"%s\"",
1118  split->memo, xaccAccountGetName(split->acc),
1119  gnc_commodity_get_mnemonic(currency));
1120 
1121  xaccTransBeginEdit (trans);
1122  xaccTransSetCurrency (trans, currency);
1123  xaccTransCommitEdit (trans);
1124  return;
1125  }
1126  }
1127  }
1128  return;
1129  }
1130 
1131  for (node = trans->splits; node; node = node->next)
1132  {
1133  Split *sp = node->data;
1134 
1136  xaccSplitGetValue (sp)))
1137  {
1138  gnc_commodity *acc_currency;
1139 
1140  acc_currency = sp->acc ? xaccAccountGetCommodity(sp->acc) : NULL;
1141  if (acc_currency == currency)
1142  {
1143  /* This Split needs fixing: The transaction-currency equals
1144  * the account-currency/commodity, but the amount/values are
1145  * inequal i.e. they still correspond to the security
1146  * (amount) and the currency (value). In the new model, the
1147  * value is the amount in the account-commodity -- so it
1148  * needs to be set to equal the amount (since the
1149  * account-currency doesn't exist anymore).
1150  *
1151  * Note: Nevertheless we lose some information here. Namely,
1152  * the information that the 'amount' in 'account-old-security'
1153  * was worth 'value' in 'account-old-currency'. Maybe it would
1154  * be better to store that information in the price database?
1155  * But then, for old currency transactions there is still the
1156  * 'other' transaction, which is going to keep that
1157  * information. So I don't bother with that here. -- cstim,
1158  * 2002/11/20. */
1159 
1160  PWARN ("Adjusted split with mismatched values, desc=\"%s\" memo=\"%s\""
1161  " old amount %s %s, new amount %s",
1162  trans->description, sp->memo,
1164  gnc_commodity_get_mnemonic (currency),
1166  xaccTransBeginEdit (trans);
1168  xaccTransCommitEdit (trans);
1169  }
1170  /*else
1171  {
1172  PINFO ("Ok: Split '%s' Amount %s %s, value %s %s",
1173  xaccSplitGetMemo (sp),
1174  gnc_num_dbg_to_string (amount),
1175  gnc_commodity_get_mnemonic (currency),
1176  gnc_num_dbg_to_string (value),
1177  gnc_commodity_get_mnemonic (acc_currency));
1178  }*/
1179  }
1180  }
1181 
1182 }
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
gboolean gnc_commodity_is_currency(const gnc_commodity *cm)
Checks to see if the specified commodity is an ISO 4217 recognized currency or a legacy currency...
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Definition: guid.cpp:174
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
Definition: Transaction.c:1425
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
GList SplitList
GList of Split.
Definition: gnc-engine.h:211
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have...
Definition: gmock-Split.cpp:77
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
Definition: guid.h:84
void xaccTransScrubOrphans(Transaction *trans)
The xaccTransScrubOrphans() method scrubs only the splits in the given transaction.
Definition: Scrub.c:178
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
#define xaccTransGetGUID(X)
Definition: Transaction.h:785
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction's commodity.
Definition: gmock-Split.cpp:84
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity.
Definition: Account.cpp:3405
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
Definition: Transaction.c:1366
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition: Account.cpp:3258
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account's commodity.
Definition: gmock-Split.cpp:69

◆ xaccTransScrubImbalance()

void xaccTransScrubImbalance ( Transaction *  trans,
Account root,
Account account 
)

The xaccScrubImbalance() method searches for transactions that do not balance to zero.

If any such transactions are found, a split is created to offset this amount and is added to an "imbalance" account.

The xaccScrubImbalance() method searches for transactions that do not balance to zero.

Parameters
transThe Transaction
rootThe (hidden) root account, for the book default currency.
accountThe account whose currency in which to balance.

Definition at line 794 of file Scrub.c.

796 {
797  gnc_numeric imbalance;
798 
799  if (!trans) return;
800 
801  ENTER ("()");
802 
803  /* Must look for orphan splits even if there is no imbalance. */
804  xaccTransScrubSplits (trans);
805 
806  /* Return immediately if things are balanced. */
807  if (xaccTransIsBalanced (trans))
808  {
809  LEAVE ("transaction is balanced");
810  return;
811  }
812 
813  if (! xaccTransUseTradingAccounts (trans))
814  {
815  gnc_transaction_balance_no_trading (trans, root, account);
816  LEAVE ("transaction balanced, no managed trading accounts");
817  return;
818  }
819 
820  xaccTransClearTradingSplits (trans);
821  imbalance = xaccTransGetImbalanceValue (trans);
822  if (! gnc_numeric_zero_p (imbalance))
823  {
824  PINFO ("Value unbalanced transaction");
825 
826  add_balance_split (trans, imbalance, root, account);
827  }
828 
829  gnc_transaction_balance_trading (trans, root);
831  {
832  LEAVE ("()");
833  return;
834  }
835  /* If the transaction is still not balanced, it's probably because there
836  are splits with zero amount and non-zero value. These are usually
837  realized gain/loss splits. Add a reversing split for each of them to
838  balance the value. */
839 
840  gnc_transaction_balance_trading_more_splits (trans, root);
842  PERR("Balancing currencies unbalanced value");
843 
844 }
gboolean xaccTransUseTradingAccounts(const Transaction *trans)
Determine whether this transaction should use commodity trading accounts.
Definition: Transaction.c:1033
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
gboolean xaccTransIsBalanced(const Transaction *trans)
Returns true if the transaction is balanced according to the rules currently in effect.
Definition: Transaction.c:1142
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
gnc_numeric xaccTransGetImbalanceValue(const Transaction *trans)
The xaccTransGetImbalanceValue() method returns the total value of the transaction.
void xaccTransScrubSplits(Transaction *trans)
The xacc*ScrubSplits() calls xaccSplitScrub() on each split in the respective structure: transaction...
Definition: Transaction.c:2924
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282

◆ xaccTransScrubPostedDate()

void xaccTransScrubPostedDate ( Transaction *  trans)

Changes Transaction date_posted timestamps from 00:00 local to 11:00 UTC.

11:00 UTC is the same day local time in almost all timezones, the exceptions being the -12, +13, and +14 timezones along the International Date Line. If Local time is set to one of these timezones then the new date_posted time will be adjusted as needed to ensure that the date doesn't change there. This change was made for v2.6.14 to partially resolve bug 137017.

Definition at line 1491 of file Scrub.c.

1492 {
1493  time64 orig = xaccTransGetDate(trans);
1494  if(orig == INT64_MAX)
1495  {
1496  GDate date = xaccTransGetDatePostedGDate(trans);
1497  time64 time = gdate_to_time64(date);
1498  if(time != INT64_MAX)
1499  {
1500  // xaccTransSetDatePostedSecs handles committing the change.
1501  xaccTransSetDatePostedSecs(trans, time);
1502  }
1503  }
1504 }
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
time64 gdate_to_time64(GDate d)
Turns a GDate into a time64, returning the first second of the day.
Definition: gnc-date.cpp:1256
void xaccTransSetDatePostedSecs(Transaction *trans, time64 secs)
The xaccTransSetDatePostedSecs() method will modify the posted date of the transaction, specified by a time64 (see ctime(3)).
Definition: Transaction.c:2017
gint64 time64
Many systems, including Microsoft Windows and BSD-derived Unixes like Darwin, are retaining the int-3...
Definition: gnc-date.h:93
GDate xaccTransGetDatePostedGDate(const Transaction *trans)
Retrieve the posted date of the transaction.
Definition: Transaction.c:2490