From a9c624bfad7d98cd95a39788b399914eea01ea7c Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Fri, 11 Nov 2016 14:03:13 +0100 Subject: [PATCH] Business check & repair - correct lot invoice state There have been situations where a lot refered to an invoice while it doesn't actually contain splits for that invoice (any more). The new code corrects this by removing the invoice reference from the lot. Also if the lot and its splits don't agree on the invoice they belong to set the lot invoice to whatever the splits indicate. --- src/engine/ScrubBusiness.c | 45 +++++++++++++++++++++++++++++++++++++- src/engine/gncInvoice.c | 6 ++--- src/engine/gncInvoiceP.h | 4 ++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/engine/ScrubBusiness.c b/src/engine/ScrubBusiness.c index 8ce5667ddc..5212b5bc60 100644 --- a/src/engine/ScrubBusiness.c +++ b/src/engine/ScrubBusiness.c @@ -37,6 +37,7 @@ #include "policy-p.h" #include "Account.h" #include "gncInvoice.h" +#include "gncInvoiceP.h" #include "Scrub2.h" #include "ScrubBusiness.h" #include "Transaction.h" @@ -46,6 +47,41 @@ static QofLogModule log_module = G_LOG_DOMAIN; +static void +gncScrubInvoiceState (GNCLot *lot) +{ + SplitList *ls_iter = NULL; + Transaction *txn = NULL; // ll_txn = "Lot Link Transaction" + GncInvoice *invoice = NULL; + GncInvoice *lot_invoice = gncInvoiceGetInvoiceFromLot (lot); + + for (ls_iter = gnc_lot_get_split_list (lot); ls_iter; ls_iter = ls_iter->next) + { + Split *split = ls_iter->data; + Transaction *txn = NULL; // ll_txn = "Lot Link Transaction" + + if (!split) + continue; // next scrub lot split + + txn = xaccSplitGetParent (split); + invoice = gncInvoiceGetInvoiceFromTxn (txn); + if (invoice) + break; + + } + + if (invoice != lot_invoice) + { + PINFO("Correcting lot invoice associaton. Old invoice: %p, new invoice %p", lot_invoice, invoice); + gncInvoiceDetachFromLot(lot); + + if (invoice) + gncInvoiceAttachToLot (invoice, lot); + else + gncOwnerAttachToLot (gncInvoiceGetOwner(lot_invoice), lot); + } +} + // A helper function that takes two splits. If the splits are of opposite sign // it reduces the biggest split to have the same value (but with opposite sign) // of the smaller split. @@ -214,7 +250,7 @@ scrub_start: // Depending on the type of lots we're comparing, we need different actions // - Two document lots (an invoice and a credit note): // Special treatment - look for all document lots linked via ll_txn - // and update the memo to be of more use to the uses. + // and update the memo to be of more use to the users. // - Two payment lots: // (Part of) the link will be eliminated and instead (part of) // one payment will be added to the other lot to keep the balance. @@ -424,6 +460,13 @@ gncScrubBusinessLot (GNCLot *lot) if (acc) xaccAccountBeginEdit(acc); + /* Check invoice link consistency + * A lot should have both or neither of: + * - one split from an invoice transaction + * - an invoice-guid set + */ + gncScrubInvoiceState (lot); + // Scrub lot links. // They should only remain when two document lots are linked together xaccScrubMergeLotSubSplits (lot, FALSE); diff --git a/src/engine/gncInvoice.c b/src/engine/gncInvoice.c index 9b6c33f629..222553f435 100644 --- a/src/engine/gncInvoice.c +++ b/src/engine/gncInvoice.c @@ -1130,7 +1130,7 @@ qofInvoiceSetJob (GncInvoice *invoice, GncJob *job) invoice->job = job; } -static void +void gncInvoiceDetachFromLot (GNCLot *lot) { KvpFrame *kvp; @@ -1143,7 +1143,7 @@ gncInvoiceDetachFromLot (GNCLot *lot) gnc_lot_commit_edit (lot); } -static void +void gncInvoiceAttachToLot (GncInvoice *invoice, GNCLot *lot) { KvpFrame *kvp; @@ -1182,7 +1182,7 @@ GncInvoice * gncInvoiceGetInvoiceFromLot (GNCLot *lot) return gncInvoiceLookup(book, guid); } -static void +void gncInvoiceAttachToTxn (GncInvoice *invoice, Transaction *txn) { KvpFrame *kvp; diff --git a/src/engine/gncInvoiceP.h b/src/engine/gncInvoiceP.h index 537dc2e453..5b4942a864 100644 --- a/src/engine/gncInvoiceP.h +++ b/src/engine/gncInvoiceP.h @@ -41,5 +41,9 @@ void gncInvoiceSetPostedTxn (GncInvoice *invoice, Transaction *txn); void gncInvoiceSetPostedLot (GncInvoice *invoice, GNCLot *lot); //void gncInvoiceSetPaidTxn (GncInvoice *invoice, Transaction *txn); +void gncInvoiceAttachToLot (GncInvoice *invoice, GNCLot *lot); +void gncInvoiceDetachFromLot (GNCLot *lot); +void gncInvoiceAttachToTxn (GncInvoice *invoice, Transaction *txn); + #define gncInvoiceSetGUID(I,G) qof_instance_set_guid(QOF_INSTANCE(I),(G)) #endif /* GNC_INVOICEP_H_ */