[Transaction.c] use heuristics to determine txn->txn_type

This commit is contained in:
Christopher Lam 2022-06-15 19:43:20 +08:00
parent aa43c198c6
commit fd12d3900c
5 changed files with 48 additions and 29 deletions

View File

@ -112,15 +112,6 @@ class TestTransaction(TransactionSession):
self.trans.ClearReadOnly() self.trans.ClearReadOnly()
self.assertEqual( None, self.trans.GetReadOnly() ) self.assertEqual( None, self.trans.GetReadOnly() )
def test_txntype(self):
self.assertEqual( '\x00', self.trans.GetTxnType() )
TYPE = 'I'
self.trans.SetTxnType(TYPE)
self.assertEqual( TYPE, self.trans.GetTxnType() )
TYPE = 'P'
self.trans.SetTxnType(TYPE)
self.assertEqual( TYPE, self.trans.GetTxnType() )
def test_num(self): def test_num(self):
NUM = '5' NUM = '5'
self.assertEqual( '', self.trans.GetNum() ) self.assertEqual( '', self.trans.GetNum() )

View File

@ -279,6 +279,7 @@ gnc_transaction_init(Transaction* trans)
trans->notes = (char*) is_unset; trans->notes = (char*) is_unset;
trans->doclink = (char*) is_unset; trans->doclink = (char*) is_unset;
trans->void_reason = (char*) is_unset; trans->void_reason = (char*) is_unset;
trans->txn_type = TXN_TYPE_UNCACHED;
LEAVE (" "); LEAVE (" ");
} }
@ -1705,6 +1706,7 @@ xaccTransCommitEdit (Transaction *trans)
qof_instance_set_dirty(QOF_INSTANCE(trans)); qof_instance_set_dirty(QOF_INSTANCE(trans));
} }
trans->txn_type = TXN_TYPE_UNCACHED;
qof_commit_edit_part2(QOF_INSTANCE(trans), qof_commit_edit_part2(QOF_INSTANCE(trans),
(void (*) (QofInstance *, QofBackendError)) (void (*) (QofInstance *, QofBackendError))
trans_on_error, trans_on_error,
@ -2551,22 +2553,43 @@ xaccTransRetDateDue(const Transaction *trans)
} }
char char
xaccTransGetTxnType (const Transaction *trans) xaccTransGetTxnType (Transaction *trans)
{ {
const char *s = NULL; gboolean has_nonAPAR_amount = FALSE;
GValue v = G_VALUE_INIT;
char ret = TXN_TYPE_NONE;
if (!trans) return TXN_TYPE_NONE; if (!trans) return TXN_TYPE_NONE;
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_TXN_TYPE_KVP);
if (G_VALUE_HOLDS_STRING (&v)) if (trans->txn_type != TXN_TYPE_UNCACHED)
return trans->txn_type;
trans->txn_type = TXN_TYPE_NONE;
for (GList *n = xaccTransGetSplitList (trans); n; n = g_list_next (n))
{ {
s = g_value_get_string (&v); Account *acc = xaccSplitGetAccount (n->data);
if (s && strlen (s) == 1)
ret = s[0]; if (!acc)
continue;
if (!xaccAccountIsAPARType (xaccAccountGetType (acc)) &&
!gnc_numeric_zero_p (xaccSplitGetValue (n->data)))
has_nonAPAR_amount = TRUE;
else if (trans->txn_type == TXN_TYPE_NONE)
{
GNCLot *lot = xaccSplitGetLot (n->data);
GncInvoice *invoice = gncInvoiceGetInvoiceFromLot (lot);
GncOwner owner;
if (invoice && trans == gncInvoiceGetPostedTxn (invoice))
trans->txn_type = TXN_TYPE_INVOICE;
else if (invoice || gncOwnerGetOwnerFromLot (lot, &owner))
trans->txn_type = TXN_TYPE_PAYMENT;
}
} }
g_value_unset (&v);
return ret; if (!has_nonAPAR_amount && (trans->txn_type == TXN_TYPE_PAYMENT))
trans->txn_type = TXN_TYPE_LINK;
return trans->txn_type;
} }
const char * const char *

View File

@ -121,6 +121,7 @@ GType gnc_transaction_get_type(void);
/** @name Transaction Type field values /** @name Transaction Type field values
@{ @{
*/ */
#define TXN_TYPE_UNCACHED '?' /** Transaction type not yet cached */
#define TXN_TYPE_NONE '\0' /**< No transaction type */ #define TXN_TYPE_NONE '\0' /**< No transaction type */
#define TXN_TYPE_INVOICE 'I' /**< Transaction is an invoice */ #define TXN_TYPE_INVOICE 'I' /**< Transaction is an invoice */
#define TXN_TYPE_PAYMENT 'P' /**< Transaction is a payment */ #define TXN_TYPE_PAYMENT 'P' /**< Transaction is a payment */
@ -302,14 +303,21 @@ gboolean xaccTransUseTradingAccounts(const Transaction *trans);
*/ */
void xaccTransSortSplits (Transaction *trans); void xaccTransSortSplits (Transaction *trans);
/** Set the Transaction Type /** Set the Transaction Type: note the type will be saved into the
* Transaction kvp property as a backward compatibility measure, for
* previous GnuCash versions whose xaccTransGetTxnType reads from the
* kvp slots.
* *
* See #TXN_TYPE_NONE, #TXN_TYPE_INVOICE and #TXN_TYPE_PAYMENT */ * See #TXN_TYPE_NONE, #TXN_TYPE_INVOICE and #TXN_TYPE_PAYMENT */
void xaccTransSetTxnType (Transaction *trans, char type); void xaccTransSetTxnType (Transaction *trans, char type);
/** Returns the Transaction Type
/** Returns the Transaction Type: note this type will be derived from
* the transaction splits, returning #TXN_TYPE_NONE,
* #TXN_TYPE_INVOICE, #TXN_TYPE_LINK, or #TXN_TYPE_PAYMENT according
* to heuristics. It does not query the transaction kvp slots.
* *
* See #TXN_TYPE_NONE, #TXN_TYPE_INVOICE and #TXN_TYPE_PAYMENT */ * See #TXN_TYPE_NONE, #TXN_TYPE_INVOICE and #TXN_TYPE_PAYMENT */
char xaccTransGetTxnType (const Transaction *trans); char xaccTransGetTxnType (Transaction *trans);
/** Sets the transaction Number (or ID) field; rather than use this function /** Sets the transaction Number (or ID) field; rather than use this function
* directly, see 'gnc_set_num_action' in engine/engine-helpers.c & .h which * directly, see 'gnc_set_num_action' in engine/engine-helpers.c & .h which

View File

@ -122,6 +122,8 @@ struct transaction_s
char * void_reason; char * void_reason;
char * notes; char * notes;
char txn_type;
/* Cached bool value to indicate whether this is a closing txn. This is /* Cached bool value to indicate whether this is a closing txn. This is
* cached from the KVP value because it is queried a lot. Tri-state value: -1 * cached from the KVP value because it is queried a lot. Tri-state value: -1
* = uninitialized; 0 = FALSE, 1 = TRUE. */ * = uninitialized; 0 = FALSE, 1 = TRUE. */

View File

@ -1838,13 +1838,8 @@ test_xaccTransGetReadOnly (Fixture *fixture, gconstpointer pData)
static void static void
test_xaccTransGetTxnType (Fixture *fixture, gconstpointer pData) test_xaccTransGetTxnType (Fixture *fixture, gconstpointer pData)
{ {
const char i = 'I';
const char p = 'P';
auto txn = fixture->txn; auto txn = fixture->txn;
xaccTransSetTxnType(txn, i); g_assert_cmpint (TXN_TYPE_NONE, ==, xaccTransGetTxnType(txn));
g_assert_cmpint (i, ==, xaccTransGetTxnType(txn));
xaccTransSetTxnType(txn, p);
g_assert_cmpint (p, ==, xaccTransGetTxnType(txn));
} }
/* xaccTransGetReadOnly C: 7 in 5 Local: 1:0:0 /* xaccTransGetReadOnly C: 7 in 5 Local: 1:0:0