GnuCash  5.6-150-g038405b370+
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 736 of file ScrubBusiness.c.

737 {
738  if (!acc) return;
739  if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;
740 
741  gncScrubBusinessAccountLots (acc, percentagefunc);
742  gncScrubBusinessAccountSplits (acc, percentagefunc);
743 }
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
Definition: Account.cpp:3217
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:4466

◆ 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 620 of file ScrubBusiness.c.

621 {
622  LotList *lots, *node;
623  gint lot_count = 0;
624  gint curr_lot_no = 0;
625  const gchar *str;
626  const char *message = _( "Checking business lots in account %s: %u of %u");
627 
628  if (!acc) return;
629 
630  if (gnc_get_abort_scrub())
631  (percentagefunc)(NULL, -1.0);
632 
633  if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;
634 
635  str = xaccAccountGetName(acc);
636  str = str ? str : "(null)";
637 
638  ENTER ("(acc=%s)", str);
639  PINFO ("Cleaning up superfluous lot links in account %s\n", str);
641 
642  lots = xaccAccountGetLotList(acc);
643  lot_count = g_list_length (lots);
644  for (node = lots; node; node = node->next)
645  {
646  GNCLot *lot = node->data;
647 
648  PINFO("Start processing lot %d of %d",
649  curr_lot_no + 1, lot_count);
650 
651  if (curr_lot_no % 100 == 0)
652  {
653  char *progress_msg = g_strdup_printf (message, str, curr_lot_no, lot_count);
654  (percentagefunc)(progress_msg, (100 * curr_lot_no) / lot_count);
655  g_free (progress_msg);
656  }
657 
658  if (lot)
659  gncScrubBusinessLot (lot);
660 
661  PINFO("Finished processing lot %d of %d",
662  curr_lot_no + 1, lot_count);
663  curr_lot_no++;
664  }
665  g_list_free(lots);
667  (percentagefunc)(NULL, -1.0);
668  LEAVE ("(acc=%s)", str);
669 }
GList LotList
GList of GNCLots.
Definition: gnc-engine.h:205
#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:3217
#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:3918
gboolean xaccAccountIsAPARType(GNCAccountType t)
Convenience function to check if the account is a valid business account type (meaning an Accounts Pa...
Definition: Account.cpp:4466
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:1475
#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:3239
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1516

◆ 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 467 of file ScrubBusiness.c.

468 {
469  gboolean splits_deleted = FALSE;
470  gboolean dangling_payments = FALSE;
471  gboolean dangling_lot_link = FALSE;
472  Account *acc;
473  gchar *lotname=NULL;
474 
475  if (!lot) return FALSE;
476  lotname = g_strdup (gnc_lot_get_title (lot));
477  ENTER ("(lot=%p) %s", lot, lotname ? lotname : "(no lotname)");
478 
479  acc = gnc_lot_get_account (lot);
480  if (acc)
482 
483  /* Check invoice link consistency
484  * A lot should have both or neither of:
485  * - one split from an invoice transaction
486  * - an invoice-guid set
487  */
488  gncScrubInvoiceState (lot);
489 
490  // Scrub lot links.
491  // They should only remain when two document lots are linked together
492  xaccScrubMergeLotSubSplits (lot, FALSE);
493  splits_deleted = gncScrubLotLinks (lot);
494 
495  // Look for dangling payments and repair if found
496  dangling_lot_link = gncScrubLotIsSingleLotLinkSplit (lot);
497  if (dangling_lot_link)
498  {
499  dangling_payments = gncScrubLotDanglingPayments (lot);
500  if (dangling_payments)
501  splits_deleted |= gncScrubLotLinks (lot);
502  else
503  {
504  Split *split = gnc_lot_get_earliest_split (lot);
505  Transaction *trans = xaccSplitGetParent (split);
506  xaccTransDestroy (trans);
507  }
508  }
509 
510  // If lot is empty now, delete it
511  if (0 == gnc_lot_count_splits (lot))
512  {
513  PINFO("All splits were removed from lot, deleting");
514  gnc_lot_destroy (lot);
515  }
516 
517  if (acc)
519 
520  LEAVE ("(lot=%s, deleted=%d, dangling lot link=%d, dangling_payments=%d)",
521  lotname ? lotname : "(no lotname)", splits_deleted, dangling_lot_link,
522  dangling_payments);
523  g_free (lotname);
524 
525  return splits_deleted;
526 }
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.cpp:379
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
STRUCTS.
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)
Convenience routine to identify the earliest date in the lot.
Definition: gnc-lot.cpp:673
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:1475
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Account * gnc_lot_get_account(const GNCLot *lot)
Returns the account with which this lot is associated.
Definition: gnc-lot.cpp:377
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1516

◆ 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 529 of file ScrubBusiness.c.

530 {
531  Transaction *txn;
532  gboolean deleted_split = FALSE;
533 
534  if (!split) return FALSE;
535  ENTER ("(split=%p)", split);
536 
537  txn = xaccSplitGetParent (split);
538  if (txn)
539  {
540  gchar txntype = xaccTransGetTxnType (txn);
541  const gchar *read_only = xaccTransGetReadOnly (txn);
542  gboolean is_void = xaccTransGetVoidStatus (txn);
543  GNCLot *lot = xaccSplitGetLot (split);
544  GncInvoice *invoice = gncInvoiceGetInvoiceFromTxn (txn);
545  Transaction *posted_txn = gncInvoiceGetPostedTxn (invoice);
546 
547  /* Look for transactions as a result of double posting an invoice or bill
548  * Refer to https://bugs.gnucash.org/show_bug.cgi?id=754209
549  * to learn how this could have happened in the past.
550  * Characteristics of such transaction are:
551  * - read only
552  * - not voided (to ensure read only is set by the business functions)
553  * - transaction type is none (should be type invoice for proper post transactions)
554  * - assigned to a lot
555  */
556  if ((txntype == TXN_TYPE_NONE) && read_only && !is_void && lot)
557  {
558  const gchar *memo = _("Please delete this transaction. Explanation at https://wiki.gnucash.org/wiki/Business_Features_Issues#Double_posting");
559  gchar *txn_date = qof_print_date (xaccTransGetDateEntered (txn));
560  xaccTransClearReadOnly (txn);
561  xaccSplitSetMemo (split, memo);
562  gnc_lot_remove_split (lot, split);
563  PWARN("Cleared double post status of transaction \"%s\", dated %s. "
564  "Please delete transaction and verify balance.",
566  txn_date);
567  g_free (txn_date);
568  }
569  /* Next check for transactions which claim to be the posted transaction of
570  * an invoice but the invoice disagrees. In that case
571  */
572  else if (invoice && (txn != posted_txn))
573  {
574  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");
575  gchar *txn_date = qof_print_date (xaccTransGetDateEntered (txn));
576  xaccTransClearReadOnly (txn);
578  xaccSplitSetMemo (split, memo);
579  if (lot)
580  {
581  gnc_lot_remove_split (lot, split);
582  gncInvoiceDetachFromLot (lot);
583  gncOwnerAttachToLot (gncInvoiceGetOwner(invoice), lot);
584  }
585  PWARN("Cleared double post status of transaction \"%s\", dated %s. "
586  "Please delete transaction and verify balance.",
588  txn_date);
589  g_free (txn_date);
590  }
591  /* Next delete any empty splits that aren't part of an invoice transaction
592  * Such splits may be the result of scrubbing the business lots, which can
593  * merge splits together while reducing superfluous lot links
594  */
595  else if (gnc_numeric_zero_p (xaccSplitGetAmount(split)) && !gncInvoiceGetInvoiceFromTxn (txn) && !is_void)
596  {
597  GNCLot *lot = xaccSplitGetLot (split);
598  time64 pdate = xaccTransGetDate (txn);
599  gchar *pdatestr = gnc_ctime (&pdate);
600  PINFO ("Destroying empty split %p from transaction %s (%s)", split, pdatestr, xaccTransGetDescription(txn));
601  xaccSplitDestroy (split);
602  g_free (pdatestr);
603 
604  // Also delete the lot containing this split if it was the last split in that lot
605  if (lot && (gnc_lot_count_splits (lot) == 0))
606  gnc_lot_destroy (lot);
607 
608  deleted_split = TRUE;
609  }
610 
611  }
612 
613  LEAVE ("(split=%p)", split);
614  return deleted_split;
615 }
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
char xaccTransGetTxnType(Transaction *trans)
Returns the Transaction Type: note this type will be derived from the transaction splits...
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
gboolean xaccSplitDestroy(Split *split)
Destructor.
Definition: Split.cpp:1471
const char * xaccTransGetReadOnly(Transaction *trans)
Returns a non-NULL value if this Transaction was marked as read-only with some specific "reason" text...
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:1326
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
void xaccTransSetTxnType(Transaction *trans, char type)
Set the Transaction Type: note the type will be saved into the Transaction kvp property as a backward...
#define TXN_TYPE_NONE
No transaction type.
Definition: Transaction.h:125
char * qof_print_date(time64 secs)
Convenience; calls through to qof_print_date_dmy_buff().
Definition: gnc-date.cpp:609
void xaccSplitSetMemo(Split *split, const char *memo)
The memo is an arbitrary string associated with a split.
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:622
void gnc_lot_remove_split(GNCLot *lot, Split *split)
Adds a split from this lot.
Definition: gnc-lot.cpp:646
time64 xaccTransGetDateEntered(const Transaction *trans)
Retrieve the date of when the transaction was entered.
gboolean xaccTransGetVoidStatus(const Transaction *trans)
Retrieve information on whether or not a transaction has been voided.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
char * gnc_ctime(const time64 *secs)
Return a string representation of a date from a 64-bit time value.
Definition: gnc-date.cpp:255
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.cpp:1882
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 59 of file Scrub2.cpp.

60 {
61  if (!acc) return;
62 
63  ENTER ("acc=%s", xaccAccountGetName(acc));
65 
66 restart_loop:
67  for (auto split : xaccAccountGetSplits (acc))
68  {
69  /* If already in lot, then no-op */
70  if (split->lot) continue;
71 
72  /* Skip voided transactions */
73  if (gnc_numeric_zero_p (split->amount) &&
74  xaccTransGetVoidStatus(split->parent)) continue;
75 
76  if (xaccSplitAssign (split)) goto restart_loop;
77  }
79  LEAVE ("acc=%s", xaccAccountGetName(acc));
80 }
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
gboolean xaccTransGetVoidStatus(const Transaction *trans)
Retrieve information on whether or not a transaction has been voided.
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.cpp:426
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1475
#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:3239
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1516

◆ xaccAccountScrubCommodity()

void xaccAccountScrubCommodity ( Account account)

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

Definition at line 1222 of file Scrub.cpp.

1223 {
1224  gnc_commodity *commodity;
1225 
1226  if (!account) return;
1227  if (xaccAccountGetType(account) == ACCT_TYPE_ROOT) return;
1228 
1229  commodity = xaccAccountGetCommodity (account);
1230  if (commodity) return;
1231 
1232  /* Use the 'obsolete' routines to try to figure out what the
1233  * account commodity should have been. */
1234  commodity = xaccAccountGetCommodity (account);
1235  if (commodity)
1236  {
1237  xaccAccountSetCommodity (account, commodity);
1238  return;
1239  }
1240 
1241  commodity = DxaccAccountGetCurrency (account);
1242  if (commodity)
1243  {
1244  xaccAccountSetCommodity (account, commodity);
1245  return;
1246  }
1247 
1248  PERR ("Account \"%s\" does not have a commodity!",
1249  xaccAccountGetName(account));
1250 }
gnc_commodity * DxaccAccountGetCurrency(const Account *acc)
Definition: Account.cpp:3347
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
Definition: Account.cpp:3217
#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:3359
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition: Account.cpp:3239
The hidden root account of an account tree.
Definition: Account.h:153
void xaccAccountSetCommodity(Account *acc, gnc_commodity *com)
Set the account's commodity.
Definition: Account.cpp:2629

◆ xaccAccountScrubKvp()

void xaccAccountScrubKvp ( Account account)

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

Definition at line 1368 of file Scrub.cpp.

1369 {
1370  GValue v = G_VALUE_INIT;
1371  gchar *str2;
1372 
1373  if (!account) return;
1374  scrub_depth++;
1375 
1376  qof_instance_get_kvp (QOF_INSTANCE (account), &v, 1, "notes");
1377  if (G_VALUE_HOLDS_STRING (&v))
1378  {
1379  str2 = g_strstrip(g_value_dup_string(&v));
1380  if (strlen(str2) == 0)
1381  qof_instance_slot_delete (QOF_INSTANCE (account), "notes");
1382  g_free(str2);
1383  }
1384 
1385  qof_instance_get_kvp (QOF_INSTANCE (account), &v, 1, "placeholder");
1386  if ((G_VALUE_HOLDS_STRING (&v) &&
1387  strcmp(g_value_get_string (&v), "false") == 0) ||
1388  (G_VALUE_HOLDS_BOOLEAN (&v) && ! g_value_get_boolean (&v)))
1389  qof_instance_slot_delete (QOF_INSTANCE (account), "placeholder");
1390 
1391  g_value_unset (&v);
1392  qof_instance_slot_delete_if_empty (QOF_INSTANCE (account), "hbci");
1393  scrub_depth--;
1394 }
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.cpp.

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 = GNC_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:205
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.cpp:80
void xaccAccountAssignLots(Account *acc)
Loop over all splits, and make sure that every split belongs to some lot.
Definition: Scrub2.cpp:59
#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:3918
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1475
#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.cpp:85
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition: Account.cpp:3239
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1516

◆ 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 1287 of file Scrub.cpp.

1288 {
1289  if (!acc) return;
1290  scrub_depth++;
1291  xaccAccountTreeForEachTransaction (acc, scrub_trans_currency_helper, nullptr);
1292 
1293  scrub_account_commodity_helper (acc, nullptr);
1294  gnc_account_foreach_descendant (acc, scrub_account_commodity_helper, nullptr);
1295  scrub_depth--;
1296 }
int xaccAccountTreeForEachTransaction(Account *acc, TransactionCallback proc, void *data)
Traverse all of the transactions in the given account group.

◆ 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 1345 of file Scrub.cpp.

1346 {
1347  gboolean new_style = FALSE;
1348  ENTER(" ");
1349 
1350  if (!root || !table)
1351  {
1352  LEAVE("Oops");
1353  return;
1354  }
1355  scrub_depth++;
1356  gnc_commodity_table_foreach_commodity (table, check_quote_source, &new_style);
1357 
1358  move_quote_source(root, GINT_TO_POINTER(new_style));
1359  gnc_account_foreach_descendant (root, move_quote_source,
1360  GINT_TO_POINTER(new_style));
1361  LEAVE("Migration done");
1362  scrub_depth--;
1363 }
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.
#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 92 of file Scrub2.cpp.

93 {
94  Account *acc;
95  Split *split;
96  GNCPolicy *pcy;
97 
98  if (!lot) return;
99  acc = gnc_lot_get_account(lot);
100  pcy = gnc_account_get_policy(acc);
101 
102  ENTER ("(lot=%s, acc=%s)", gnc_lot_get_title(lot), xaccAccountGetName(acc));
103 
104  /* If balance already zero, we have nothing to do. */
105  if (gnc_lot_is_closed (lot))
106  {
107  LEAVE ("Lot Closed (lot=%s, acc=%s)", gnc_lot_get_title(lot),
108  xaccAccountGetName(acc));
109  return;
110  }
111  split = pcy->PolicyGetSplit (pcy, lot);
112  if (!split)
113  {
114  LEAVE ("No Split (lot=%s, acc=%s)", gnc_lot_get_title(lot),
115  xaccAccountGetName(acc));
116  return; /* Handle the common case */
117  }
118 
119  /* Reject voided transactions */
120  if (gnc_numeric_zero_p(split->amount) &&
121  xaccTransGetVoidStatus(split->parent))
122  {
123  LEAVE ("Voided transaction (lot=%s, acc=%s)",
124  gnc_lot_get_title(lot), xaccAccountGetName(acc));
125  return;
126  }
127 
128  xaccAccountBeginEdit (acc);
129 
130  /* Loop until we've filled up the lot, (i.e. till the
131  * balance goes to zero) or there are no splits left. */
132  while (1)
133  {
134  Split *subsplit;
135 
136  subsplit = xaccSplitAssignToLot (split, lot);
137  if (subsplit == split)
138  {
139  PERR ("Accounting Policy gave us a split that "
140  "doesn't fit into this lot\n"
141  "lot baln=%s, isclosed=%d, aplit amt=%s",
143  gnc_lot_is_closed (lot),
144  gnc_num_dbg_to_string (split->amount));
145  break;
146  }
147 
148  if (gnc_lot_is_closed (lot)) break;
149 
150  split = pcy->PolicyGetSplit (pcy, lot);
151  if (!split) break;
152  }
153  xaccAccountCommitEdit (acc);
154  LEAVE ("(lot=%s, acc=%s)", gnc_lot_get_title(lot), xaccAccountGetName(acc));
155 }
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
STRUCTS.
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
Split * xaccSplitAssignToLot(Split *split, GNCLot *lot)
The xaccSplitAssignToLot() routine will fit the indicated split into the indicated lot...
Definition: cap-gains.cpp:219
gboolean xaccTransGetVoidStatus(const Transaction *trans)
Retrieve information on whether or not a transaction has been voided.
gboolean gnc_lot_is_closed(GNCLot *lot)
Returns closed status of the given lot.
Definition: gnc-lot.cpp:367
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1475
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Account * gnc_lot_get_account(const GNCLot *lot)
Returns the account with which this lot is associated.
Definition: gnc-lot.cpp:377
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition: Account.cpp:3239
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1516
GNCPolicy * gnc_account_get_policy(Account *acc)
Get the account's lot order policy.
Definition: Account.cpp:2082
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
Returns the lot balance.
Definition: gnc-lot.cpp:502

◆ 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 160 of file Scrub2.cpp.

161 {
162  gnc_commodity *currency = nullptr;
163  SplitList *snode;
164  GList *node;
165  gnc_numeric zero = gnc_numeric_zero();
166  gnc_numeric value = zero;
167 
168  if (!lot) return;
169 
170  ENTER ("lot=%s", gnc_lot_get_title(lot));
171 
172  for (snode = gnc_lot_get_split_list(lot); snode; snode = snode->next)
173  {
174  Split *s = GNC_SPLIT(snode->data);
175  xaccSplitComputeCapGains (s, nullptr);
176  }
177 
178  /* We double-check only closed lots */
179  if (FALSE == gnc_lot_is_closed (lot))
180  {
181  LEAVE ("lot=%s is closed", gnc_lot_get_title(lot));
182  return;
183  }
184 
185  for (snode = gnc_lot_get_split_list(lot); snode; snode = snode->next)
186  {
187  Split *s = GNC_SPLIT(snode->data);
188  Transaction *trans = s->parent;
189 
190  /* Check to make sure all splits in the lot have a common currency */
191  if (nullptr == currency)
192  {
193  currency = trans->common_currency;
194  }
195  if (FALSE == gnc_commodity_equiv (currency, trans->common_currency))
196  {
197  /* This lot has mixed currencies. Can't double-balance.
198  * Silently punt */
199  PWARN ("Lot with multiple currencies:\n"
200  "\ttrans=%s curr=%s", xaccTransGetDescription(trans),
201  gnc_commodity_get_fullname(trans->common_currency));
202  break;
203  }
204 
205  /* Now, total up the values */
206  value = gnc_numeric_add (value, xaccSplitGetValue (s),
208  PINFO ("Split=%p value=%s Accum Lot value=%s", s,
209  gnc_num_dbg_to_string (s->value),
210  gnc_num_dbg_to_string (value));
211 
212  }
213 
214  if (FALSE == gnc_numeric_equal (value, zero))
215  {
216  /* Unhandled error condition. Not sure what to do here,
217  * Since the ComputeCapGains should have gotten it right.
218  * I suppose there might be small rounding errors, a penny or two,
219  * the ideal thing would to figure out why there's a rounding
220  * error, and fix that.
221  */
222  PERR ("Closed lot fails to double-balance !! lot value=%s",
223  gnc_num_dbg_to_string (value));
224  for (node = gnc_lot_get_split_list(lot); node; node = node->next)
225  {
226  Split *s = GNC_SPLIT(node->data);
227  PERR ("s=%p amt=%s val=%s", s,
228  gnc_num_dbg_to_string(s->amount),
229  gnc_num_dbg_to_string(s->value));
230  }
231  }
232 
233  LEAVE ("lot=%s", gnc_lot_get_title(lot));
234 }
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.cpp:526
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:188
#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
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
GList SplitList
GList of Split.
Definition: gnc-engine.h:207
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
Returns a list of all the splits in this lot.
Definition: gnc-lot.cpp:425
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)
Returns closed status of the given lot.
Definition: gnc-lot.cpp:367
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:245
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.cpp.

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, nullptr, nullptr);
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 = GNC_SPLIT(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, nullptr);
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.cpp:379
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.cpp:92
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
STRUCTS.
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:207
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
Returns a list of all the splits in this lot.
Definition: gnc-lot.cpp:425
void xaccLotScrubDoubleBalance(GNCLot *lot)
The xaccLotScrubDoubleBalance() routine examines the indicated lot.
Definition: Scrub2.cpp:160
void gnc_lot_remove_split(GNCLot *lot, Split *split)
Adds a split from this lot.
Definition: gnc-lot.cpp:646
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:1475
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Account * gnc_lot_get_account(const GNCLot *lot)
Returns the account with which this lot is associated.
Definition: gnc-lot.cpp:377
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1516
GNCPolicy * gnc_account_get_policy(Account *acc)
Get the account's lot order policy.
Definition: Account.cpp:2082
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
Returns the lot balance.
Definition: gnc-lot.cpp:502

◆ 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 318 of file Scrub2.cpp.

319 {
320  gboolean rc = FALSE;
321  Transaction *txn;
322  SplitList *node;
323  GNCLot *lot;
324 
325  if (strict && (FALSE == is_subsplit (split))) return FALSE;
326 
327  txn = split->parent;
328 
329  // Don't mess with splits from an invoice transaction
330  // Those are the responsibility of the business code
331  if (gncInvoiceGetInvoiceFromTxn (txn)) return FALSE;
332 
333  lot = xaccSplitGetLot (split);
334 
335  ENTER ("(Lot=%s)", gnc_lot_get_title(lot));
336 restart:
337  for (node = txn->splits; node; node = node->next)
338  {
339  Split *s = GNC_SPLIT(node->data);
340  if (xaccSplitGetLot (s) != lot) continue;
341  if (s == split) continue;
342  if (qof_instance_get_destroying(s)) continue;
343 
344  // Don't mess with splits from an invoice transaction
345  // Those are the responsibility of the business code
346  if (gncInvoiceGetInvoiceFromTxn (s->parent)) return FALSE;
347 
348  if (strict)
349  {
350  /* OK, this split is in the same lot (and thus same account)
351  * as the indicated split. Make sure it is really a subsplit
352  * of the split we started with. It's possible to have two
353  * splits in the same lot and transaction that are not subsplits
354  * of each other, the test-period test suite does this, for
355  * example. Only worry about adjacent sub-splits. By
356  * repeatedly merging adjacent subsplits, we'll get the non-
357  * adjacent ones too. */
358  if (!xaccSplitIsPeerSplit (split, s))
359  continue;
360  }
361 
362  merge_splits (split, s);
363  rc = TRUE;
364  goto restart;
365  }
366  if (rc && gnc_numeric_zero_p (split->amount))
367  {
368  time64 pdate = xaccTransGetDate (txn);
369  gchar *pdatestr = gnc_ctime (&pdate);
370  PWARN ("Result of merge has zero amt!");
371  PWARN ("Transaction details - posted date %s - description %s", pdatestr, xaccTransGetDescription(txn));
372  g_free (pdatestr);
373  }
374  LEAVE (" splits merged=%d", rc);
375  return rc;
376 }
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:1326
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
GList SplitList
GList of Split.
Definition: gnc-engine.h:207
gboolean xaccSplitIsPeerSplit(const Split *split, const Split *other_split)
Report if a split is a peer of this one.
Definition: Split.cpp:2038
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
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
char * gnc_ctime(const time64 *secs)
Return a string representation of a date from a 64-bit time value.
Definition: gnc-date.cpp:255
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.cpp:1882

◆ 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 424 of file Scrub.cpp.

425 {
426  split_scrub_or_dry_run (split, false);
427 }

◆ 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 1105 of file Scrub.cpp.

1106 {
1107  SplitList *node;
1108  gnc_commodity *currency;
1109 
1110  if (!trans) return;
1111 
1112  /* If there are any orphaned splits in a transaction, then the
1113  * this routine will fail. Therefore, we want to make sure that
1114  * there are no orphans (splits without parent account).
1115  */
1116  xaccTransScrubOrphans (trans);
1117 
1118  currency = xaccTransGetCurrency (trans);
1119  if (currency && gnc_commodity_is_currency(currency)) return;
1120 
1121  currency = xaccTransFindCommonCurrency (trans, qof_instance_get_book(trans));
1122  if (currency)
1123  {
1124  xaccTransBeginEdit (trans);
1125  xaccTransSetCurrency (trans, currency);
1126  xaccTransCommitEdit (trans);
1127  }
1128  else
1129  {
1130  if (nullptr == trans->splits)
1131  {
1132  PWARN ("Transaction \"%s\" has no splits in it!", trans->description);
1133  }
1134  else
1135  {
1136  SplitList *node;
1137  char guid_str[GUID_ENCODING_LENGTH + 1];
1138  guid_to_string_buff(xaccTransGetGUID(trans), guid_str);
1139  PWARN ("no common transaction currency found for trans=\"%s\" (%s);",
1140  trans->description, guid_str);
1141 
1142  for (node = trans->splits; node; node = node->next)
1143  {
1144  Split *split = GNC_SPLIT(node->data);
1145  if (nullptr == split->acc)
1146  {
1147  PWARN (" split=\"%s\" is not in any account!", split->memo);
1148  }
1149  else
1150  {
1151  gnc_commodity *currency = xaccAccountGetCommodity(split->acc);
1152  PWARN ("setting to split=\"%s\" account=\"%s\" commodity=\"%s\"",
1153  split->memo, xaccAccountGetName(split->acc),
1154  gnc_commodity_get_mnemonic(currency));
1155 
1156  xaccTransBeginEdit (trans);
1157  xaccTransSetCurrency (trans, currency);
1158  xaccTransCommitEdit (trans);
1159  return;
1160  }
1161  }
1162  }
1163  return;
1164  }
1165 
1166  for (node = trans->splits; node; node = node->next)
1167  {
1168  Split *sp = GNC_SPLIT(node->data);
1169 
1171  xaccSplitGetValue (sp)))
1172  {
1173  gnc_commodity *acc_currency;
1174 
1175  acc_currency = sp->acc ? xaccAccountGetCommodity(sp->acc) : nullptr;
1176  if (acc_currency == currency)
1177  {
1178  /* This Split needs fixing: The transaction-currency equals
1179  * the account-currency/commodity, but the amount/values are
1180  * inequal i.e. they still correspond to the security
1181  * (amount) and the currency (value). In the new model, the
1182  * value is the amount in the account-commodity -- so it
1183  * needs to be set to equal the amount (since the
1184  * account-currency doesn't exist anymore).
1185  *
1186  * Note: Nevertheless we lose some information here. Namely,
1187  * the information that the 'amount' in 'account-old-security'
1188  * was worth 'value' in 'account-old-currency'. Maybe it would
1189  * be better to store that information in the price database?
1190  * But then, for old currency transactions there is still the
1191  * 'other' transaction, which is going to keep that
1192  * information. So I don't bother with that here. -- cstim,
1193  * 2002/11/20. */
1194 
1195  PWARN ("Adjusted split with mismatched values, desc=\"%s\" memo=\"%s\""
1196  " old amount %s %s, new amount %s",
1197  trans->description, sp->memo,
1199  gnc_commodity_get_mnemonic (currency),
1201  xaccTransBeginEdit (trans);
1203  xaccTransCommitEdit (trans);
1204  }
1205  /*else
1206  {
1207  PINFO ("Ok: Split '%s' Amount %s %s, value %s %s",
1208  xaccSplitGetMemo (sp),
1209  gnc_num_dbg_to_string (amount),
1210  gnc_commodity_get_mnemonic (currency),
1211  gnc_num_dbg_to_string (value),
1212  gnc_commodity_get_mnemonic (acc_currency));
1213  }*/
1214  }
1215  }
1216 
1217 }
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:173
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
GList SplitList
GList of Split.
Definition: gnc-engine.h:207
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.cpp:179
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:788
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:3359
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition: Account.cpp:3239
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 829 of file Scrub.cpp.

831 {
832  gnc_numeric imbalance;
833 
834  if (!trans) return;
835 
836  ENTER ("()");
837 
838  /* Must look for orphan splits even if there is no imbalance. */
839  xaccTransScrubSplits (trans);
840 
841  /* Return immediately if things are balanced. */
842  if (xaccTransIsBalanced (trans))
843  {
844  LEAVE ("transaction is balanced");
845  return;
846  }
847 
848  if (! xaccTransUseTradingAccounts (trans))
849  {
850  gnc_transaction_balance_no_trading (trans, root, account);
851  LEAVE ("transaction balanced, no managed trading accounts");
852  return;
853  }
854 
855  xaccTransClearTradingSplits (trans);
856  imbalance = xaccTransGetImbalanceValue (trans);
857  if (! gnc_numeric_zero_p (imbalance))
858  {
859  PINFO ("Value unbalanced transaction");
860 
861  add_balance_split (trans, imbalance, root, account);
862  }
863 
864  gnc_transaction_balance_trading (trans, root);
866  {
867  LEAVE ("()");
868  return;
869  }
870  /* If the transaction is still not balanced, it's probably because there
871  are splits with zero amount and non-zero value. These are usually
872  realized gain/loss splits. Add a reversing split for each of them to
873  balance the value. */
874 
875  gnc_transaction_balance_trading_more_splits (trans, root);
877  PERR("Balancing currencies unbalanced value");
878 
879 }
gboolean xaccTransUseTradingAccounts(const Transaction *trans)
Determine whether this transaction should use commodity trading accounts.
#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.
#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: Scrub.cpp:395
#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 1527 of file Scrub.cpp.

1528 {
1529  time64 orig = xaccTransGetDate(trans);
1530  if(orig == INT64_MAX)
1531  {
1532  GDate date = xaccTransGetDatePostedGDate(trans);
1533  time64 time = gdate_to_time64(date);
1534  if(time != INT64_MAX)
1535  {
1536  // xaccTransSetDatePostedSecs handles committing the change.
1537  xaccTransSetDatePostedSecs(trans, time);
1538  }
1539  }
1540 }
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:1253
void xaccTransSetDatePostedSecs(Transaction *trans, time64 secs)
The xaccTransSetDatePostedSecs() method will modify the posted date of the transaction, specified by a time64 (see ctime(3)).
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
GDate xaccTransGetDatePostedGDate(const Transaction *trans)
Retrieve the posted date of the transaction.