/* This routine is actually identical to FIFO... */ G_GNUC_UNUSED static gboolean LIFOPolicyIsOpeningSplit (GNCPolicy *pcy, GNCLot *lot, Split *split) { Split *opening_split; opening_split = gnc_lot_get_earliest_split(lot); return (split == opening_split); }
static gboolean gncScrubLotIsSingleLotLinkSplit (GNCLot *lot) { Split *split = NULL; Transaction *trans = NULL; // Lots with a single split which is also a lot link transaction split // may be sign of a dangling payment. Let's try to fix that // Only works for single split lots... if (1 != gnc_lot_count_splits (lot)) return FALSE; split = gnc_lot_get_earliest_split (lot); trans = xaccSplitGetParent (split); if (!trans) { // Ooops - the split doesn't belong to any transaction ! // This is not expected so issue a warning and continue with next split PWARN("Encountered a split in a business lot that's not part of any transaction. " "This is unexpected! Skipping split %p.", split); return FALSE; } // Only works if single split belongs to a lot link transaction... if (xaccTransGetTxnType (trans) != TXN_TYPE_LINK) return FALSE; return TRUE; }
gboolean gncScrubBusinessLot (GNCLot *lot) { gboolean splits_deleted = FALSE; gboolean dangling_payments = FALSE; gboolean dangling_lot_link = FALSE; Account *acc; gchar *lotname=NULL; if (!lot) return FALSE; lotname = g_strdup (gnc_lot_get_title (lot)); ENTER ("(lot=%p) %s", lot, lotname ? lotname : "(no lotname)"); acc = gnc_lot_get_account (lot); if (acc) xaccAccountBeginEdit(acc); // Scrub lot links. // They should only remain when two document lots are linked together xaccScrubMergeLotSubSplits (lot, FALSE); splits_deleted = gncScrubLotLinks (lot); // Look for dangling payments and repair if found dangling_lot_link = gncScrubLotIsSingleLotLinkSplit (lot); if (dangling_lot_link) { dangling_payments = gncScrubLotDanglingPayments (lot); if (dangling_payments) splits_deleted |= gncScrubLotLinks (lot); else { Split *split = gnc_lot_get_earliest_split (lot); Transaction *trans = xaccSplitGetParent (split); xaccTransDestroy (trans); } } // If lot is empty now, delete it if (0 == gnc_lot_count_splits (lot)) { PINFO("All splits were removed from lot, deleting"); gnc_lot_destroy (lot); } if (acc) xaccAccountCommitEdit(acc); LEAVE ("(lot=%s, deleted=%d, dangling lot link=%d, dangling_payments=%d)", lotname ? lotname : "(no lotname)", splits_deleted, dangling_lot_link, dangling_payments); g_free (lotname); return splits_deleted; }
gint gncOwnerLotsSortFunc (GNCLot *lotA, GNCLot *lotB) { GncInvoice *ia, *ib; Timespec da, db; ia = gncInvoiceGetInvoiceFromLot (lotA); ib = gncInvoiceGetInvoiceFromLot (lotB); if (ia) da = gncInvoiceGetDateDue (ia); else da = xaccTransRetDatePostedTS (xaccSplitGetParent (gnc_lot_get_earliest_split (lotA))); if (ib) db = gncInvoiceGetDateDue (ib); else db = xaccTransRetDatePostedTS (xaccSplitGetParent (gnc_lot_get_earliest_split (lotB))); return timespec_cmp (&da, &db); }
/* This routine is actually identical to FIFO... */ G_GNUC_UNUSED static void LIFOPolicyGetLotOpening (GNCPolicy *pcy, GNCLot *lot, gnc_numeric *ret_amount, gnc_numeric *ret_value, gnc_commodity **ret_currency) { Split *opening_split; opening_split = gnc_lot_get_earliest_split(lot); if (ret_amount) *ret_amount = opening_split->amount; if (ret_value) *ret_value = opening_split->value; if (ret_currency) *ret_currency = opening_split->parent->common_currency; }
static gboolean gncScrubLotDanglingPayments (GNCLot *lot) { SplitList * split_list, *filtered_list = NULL, *match_list = NULL, *node; Split *ll_split = gnc_lot_get_earliest_split (lot); Transaction *ll_trans = xaccSplitGetParent (ll_split); gnc_numeric ll_val = xaccSplitGetValue (ll_split); time64 ll_date = xaccTransGetDate (ll_trans); const char *ll_desc = xaccTransGetDescription (ll_trans); // look for free splits (i.e. not in any lot) which, // compared to the lot link split // - have the same date // - have the same description // - have an opposite sign amount // - free split's abs value is less than or equal to ll split's abs value split_list = xaccAccountGetSplitList(gnc_lot_get_account (lot)); for (node = split_list; node; node = node->next) { Split *free_split = node->data; Transaction *free_trans; gnc_numeric free_val; if (NULL != xaccSplitGetLot(free_split)) continue; free_trans = xaccSplitGetParent (free_split); if (ll_date != xaccTransGetDate (free_trans)) continue; if (0 != g_strcmp0 (ll_desc, xaccTransGetDescription (free_trans))) continue; free_val = xaccSplitGetValue (free_split); if (gnc_numeric_positive_p (ll_val) == gnc_numeric_positive_p (free_val)) continue; if (gnc_numeric_compare (gnc_numeric_abs (free_val), gnc_numeric_abs (ll_val)) > 0) continue; filtered_list = g_list_append(filtered_list, free_split); } match_list = gncSLFindOffsSplits (filtered_list, ll_val); g_list_free (filtered_list); for (node = match_list; node; node = node->next) { Split *match_split = node->data; gnc_lot_add_split (lot, match_split); } if (match_list) { g_list_free (match_list); return TRUE; } else return FALSE; }