GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Files | Data Structures | Macros | Typedefs | Enumerations | Functions

Files

file  gncOwner.h
 Business Interface: Object OWNERs.
 

Data Structures

struct  _gncOwner
 
struct  GncOwner
 

Macros

#define GNC_ID_OWNER   "gncOwner"
 
#define OWNER_TYPE   "type"
 
#define OWNER_TYPE_STRING   "type-string"
 
#define OWNER_CUSTOMER   "customer"
 
#define OWNER_JOB   "job"
 
#define OWNER_VENDOR   "vendor"
 
#define OWNER_EMPLOYEE   "employee"
 
#define OWNER_PARENT   "parent"
 
#define OWNER_PARENTG   "parent-guid"
 
#define OWNER_NAME   "name"
 
#define OWNER_FROM_LOT   "owner-from-lot"
 

Typedefs

typedef struct _gncOwner GncOwner
 

Enumerations

enum  GncOwnerType {
  GNC_OWNER_NONE, GNC_OWNER_UNDEFINED, GNC_OWNER_CUSTOMER, GNC_OWNER_JOB,
  GNC_OWNER_VENDOR, GNC_OWNER_EMPLOYEE
}
 

Functions

void gncOwnerCopy (const GncOwner *src, GncOwner *dest)
 
const GncGUIDgncOwnerGetGUID (const GncOwner *owner)
 
GncGUID gncOwnerRetGUID (GncOwner *owner)
 
const GncOwnergncOwnerGetEndOwner (const GncOwner *owner)
 
const GncGUIDgncOwnerGetEndGUID (const GncOwner *owner)
 
void gncOwnerAttachToLot (const GncOwner *owner, GNCLot *lot)
 
gboolean gncOwnerLotMatchOwnerFunc (GNCLot *lot, gpointer user_data)
 
gint gncOwnerLotsSortFunc (GNCLot *lotA, GNCLot *lotB)
 
gboolean gncOwnerGetOwnerFromLot (GNCLot *lot, GncOwner *owner)
 
gboolean gncOwnerGetOwnerFromTypeGuid (QofBook *book, GncOwner *owner, QofIdType type, GncGUID *guid)
 
GNCLotgncOwnerCreatePaymentLot (const GncOwner *owner, Transaction *txn, Account *posted_acc, Account *xfer_acc, gnc_numeric amount, gnc_numeric exch, Timespec date, const char *memo, const char *num)
 
void gncOwnerAutoApplyPaymentsWithLots (const GncOwner *owner, GList *lots)
 
void gncOwnerApplyPayment (const GncOwner *owner, Transaction *txn, GList *lots, Account *posted_acc, Account *xfer_acc, gnc_numeric amount, gnc_numeric exch, Timespec date, const char *memo, const char *num, gboolean auto_pay)
 
SplitgncOwnerFindOffsettingSplit (GNCLot *pay_lot, gnc_numeric target_value)
 
gboolean gncOwnerReduceSplitTo (Split *split, gnc_numeric target_value)
 
void gncOwnerSetLotLinkMemo (Transaction *ll_txn)
 
GList * gncOwnerGetAccountTypesList (const GncOwner *owner)
 
GList * gncOwnerGetCommoditiesList (const GncOwner *owner)
 
gnc_numeric gncOwnerGetBalanceInCurrency (const GncOwner *owner, const gnc_commodity *report_currency)
 
GncOwnergncOwnerNew (void)
 
void gncOwnerFree (GncOwner *owner)
 
void gncOwnerBeginEdit (GncOwner *owner)
 
void gncOwnerCommitEdit (GncOwner *owner)
 
void gncOwnerDestroy (GncOwner *owner)
 

QOF handling

Whilst GncOwner is not a formal QOF object, these functions are still expected to be useful in making GncOwner transparent to QOF as they can be used by objects like GncInvoice.

QofIdTypeConst qofOwnerGetType (const GncOwner *owner)
 
QofInstanceqofOwnerGetOwner (const GncOwner *owner)
 
void qofOwnerSetEntity (GncOwner *owner, QofInstance *ent)
 
gboolean GNC_IS_OWNER (QofInstance *ent)
 
QofIdTypeConst gncOwnerTypeToQofIdType (GncOwnerType t)
 
gboolean gncOwnerRegister (void)
 

Setup routines

void gncOwnerInitUndefined (GncOwner *owner, gpointer obj)
 
void gncOwnerInitCustomer (GncOwner *owner, GncCustomer *customer)
 
void gncOwnerInitJob (GncOwner *owner, GncJob *job)
 
void gncOwnerInitVendor (GncOwner *owner, GncVendor *vendor)
 
void gncOwnerInitEmployee (GncOwner *owner, GncEmployee *employee)
 

Get routines.

GncOwnerType gncOwnerGetType (const GncOwner *owner)
 
gboolean gncOwnerIsValid (const GncOwner *owner)
 
gpointer gncOwnerGetUndefined (const GncOwner *owner)
 
GncCustomergncOwnerGetCustomer (const GncOwner *owner)
 
GncJobgncOwnerGetJob (const GncOwner *owner)
 
GncVendorgncOwnerGetVendor (const GncOwner *owner)
 
GncEmployeegncOwnerGetEmployee (const GncOwner *owner)
 
const char * gncOwnerGetID (const GncOwner *owner)
 
const char * gncOwnerGetName (const GncOwner *owner)
 
GncAddressgncOwnerGetAddr (const GncOwner *owner)
 
gboolean gncOwnerGetActive (const GncOwner *owner)
 
gnc_commoditygncOwnerGetCurrency (const GncOwner *owner)
 

Set routines.

void gncOwnerSetActive (const GncOwner *owner, gboolean active)
 

Comparison routines.

gboolean gncOwnerEqual (const GncOwner *a, const GncOwner *b)
 
int gncOwnerGCompareFunc (const GncOwner *a, const GncOwner *b)
 
int gncOwnerCompare (const GncOwner *a, const GncOwner *b)
 

Detailed Description

Macro Definition Documentation

#define OWNER_TYPE_STRING   "type-string"

Allows the type to be handled externally.

Definition at line 309 of file gncOwner.h.

Function Documentation

gboolean GNC_IS_OWNER ( QofInstance ent)

Check if entity is an owner kind. This function conveniently imitates the various GNC_IS_ checks on the other gnucash objects even though an owner is not really a true object.

Definition at line 330 of file gncOwner.c.

331 {
332  if (!ent)
333  return FALSE;
334 
335  return (GNC_IS_VENDOR(ent) ||
336  GNC_IS_CUSTOMER(ent) ||
337  GNC_IS_EMPLOYEE(ent) ||
338  GNC_IS_JOB(ent));
339 }
void gncOwnerApplyPayment ( const GncOwner owner,
Transaction txn,
GList *  lots,
Account posted_acc,
Account xfer_acc,
gnc_numeric  amount,
gnc_numeric  exch,
Timespec  date,
const char *  memo,
const char *  num,
gboolean  auto_pay 
)

A convenience function to apply a payment to the owner. It creates a lot for a payment, optionally based on an existing transaction and then tries to balance it with the list of document/payment lots passed in. If not lots were given, all open lots for the owner are considered.

This code is actually a convenience wrapper around gncOwnerCreatePaymentLot and gncOwnerAutoApplyPaymentsWithLots. See their descriptions for more details on what happens exactly.

Definition at line 1348 of file gncOwner.c.

1352 {
1353  GNCLot *payment_lot = NULL;
1354  GList *selected_lots = NULL;
1355 
1356  /* Verify our arguments */
1357  if (!owner || !posted_acc
1358  || (!xfer_acc && !gnc_numeric_zero_p (amount)) ) return;
1359  g_return_if_fail (owner->owner.undefined);
1360 
1361  /* If there's a real amount to transfer create a lot for this payment */
1362  if (!gnc_numeric_zero_p (amount))
1363  payment_lot = gncOwnerCreatePaymentLot (owner, txn, posted_acc, xfer_acc,
1364  amount, exch, date, memo, num);
1365 
1366  if (lots)
1367  selected_lots = lots;
1368  else if (auto_pay)
1369  selected_lots = xaccAccountFindOpenLots (posted_acc, gncOwnerLotMatchOwnerFunc,
1370  (gpointer)owner, NULL);
1371 
1372  /* And link the selected lots and the payment lot together as well as possible.
1373  * If the payment was bigger than the selected documents/overpayments, only
1374  * part of the payment will be used. Similarly if more documents were selected
1375  * than the payment value set, not all documents will be marked as paid. */
1376  if (payment_lot)
1377  selected_lots = g_list_prepend (selected_lots, payment_lot);
1378  gncOwnerAutoApplyPaymentsWithLots (owner, selected_lots);
1379  g_list_free (selected_lots);
1380 }
gboolean gnc_numeric_zero_p(gnc_numeric a)
void gncOwnerAutoApplyPaymentsWithLots(const GncOwner *owner, GList *lots)
Definition: gncOwner.c:1199
GNCLot * gncOwnerCreatePaymentLot(const GncOwner *owner, Transaction *txn, Account *posted_acc, Account *xfer_acc, gnc_numeric amount, gnc_numeric exch, Timespec date, const char *memo, const char *num)
Definition: gncOwner.c:701
gboolean gncOwnerLotMatchOwnerFunc(GNCLot *lot, gpointer user_data)
Definition: gncOwner.c:657
LotList * xaccAccountFindOpenLots(const Account *acc, gboolean(*match_func)(GNCLot *lot, gpointer user_data), gpointer user_data, GCompareFunc sort_func)
Definition: Account.c:3751
void gncOwnerAttachToLot ( const GncOwner owner,
GNCLot lot 
)

Attach an owner to a lot

Definition at line 600 of file gncOwner.c.

601 {
602  if (!owner || !lot)
603  return;
604 
605  gnc_lot_begin_edit (lot);
606 
607  qof_instance_set (QOF_INSTANCE (lot),
608  GNC_OWNER_TYPE, (gint64)gncOwnerGetType (owner),
609  GNC_OWNER_GUID, gncOwnerGetGUID (owner),
610  NULL);
611  gnc_lot_commit_edit (lot);
612 }
const GncGUID * gncOwnerGetGUID(const GncOwner *owner)
Definition: gncOwner.c:496
void qof_instance_set(QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_set Group setting multiple parameters in a single begin/commit/rollback.
GncOwnerType gncOwnerGetType(const GncOwner *owner)
Definition: gncOwner.c:201
void gncOwnerAutoApplyPaymentsWithLots ( const GncOwner owner,
GList *  lots 
)

Given a list of lots, try to balance as many of them as possible by creating balancing transactions between them. This can be used to automatically link invoices to payments (to "mark" invoices as paid) or to credit notes or the other way around.

The function starts with the first lot in the list and tries to create balancing transactions to the remainder of the lots in the list. If it reaches the end of the list, it will find the next still open lot in the list and tries to balance it with all lots that follow it (the ones that precede it are either already closed or not suitable or they would have been processed in a previous iteration).

By intelligently sorting the list of lots, you can play with the order of precedence in which the lots should be processed. For example, by sorting the oldest invoice lots first, the code will attempt to balance these first.

Some restrictions:

  • the algorithm is lazy: it will create the smallest balancing transaction(s) possible, not the largest ones. Since the process is iterative, you will have balanced the maximum amount possible in the end, but it may be done in several transactions instead of only one big one.
  • the balancing transactions only work within one account. If a balancing lot is from another account than the lot currently being balanced, it will be skipped during balance evaluation. However if there is a mix of lots from two different accounts, the algorithm will still attempt to match all lots per account.
  • the calling function is responsible for the memory management of the lots list. If it created the list, it should properly free it as well.

Definition at line 1199 of file gncOwner.c.

1200 {
1201  GList *left_iter;
1202 
1203  /* General note: in the code below the term "payment" can
1204  * both mean a true payment or a document of
1205  * the opposite sign (invoice vs credit note) relative to
1206  * the lot being processed. In general this function will
1207  * perform a balancing action on a set of lots, so you
1208  * will also find frequent references to balancing instead. */
1209 
1210  /* Payments can only be applied when at least an owner
1211  * and a list of lots to use are given */
1212  if (!owner) return;
1213  if (!lots) return;
1214 
1215  for (left_iter = lots; left_iter; left_iter = left_iter->next)
1216  {
1217  GNCLot *left_lot = left_iter->data;
1218  gnc_numeric left_lot_bal;
1219  gboolean left_lot_has_doc;
1220  gboolean left_modified = FALSE;
1221  Account *acct;
1222  GList *right_iter;
1223 
1224  /* Only attempt to apply payments to open lots.
1225  * Note that due to the iterative nature of this function lots
1226  * in the list may become empty/closed before they are evaluated as
1227  * base lot, so we should check this for each lot. */
1228  if (!left_lot)
1229  continue;
1230  if (gnc_lot_count_splits (left_lot) == 0)
1231  {
1232  gnc_lot_destroy (left_lot);
1233  left_iter->data = NULL;
1234  continue;
1235  }
1236  if (gnc_lot_is_closed (left_lot))
1237  continue;
1238 
1239  acct = gnc_lot_get_account (left_lot);
1240  xaccAccountBeginEdit (acct);
1241 
1242  left_lot_bal = gnc_lot_get_balance (left_lot);
1243  left_lot_has_doc = (gncInvoiceGetInvoiceFromLot (left_lot) != NULL);
1244 
1245  /* Attempt to offset left_lot with any of the remaining lots. To do so
1246  * iterate over the remaining lots adding lot links or moving payments
1247  * around.
1248  */
1249  for (right_iter = left_iter->next; right_iter; right_iter = right_iter->next)
1250  {
1251  GNCLot *right_lot = right_iter->data;
1252  gnc_numeric right_lot_bal;
1253  gboolean right_lot_has_doc;
1254 
1255  /* Only attempt to use open lots to balance the base lot.
1256  * Note that due to the iterative nature of this function lots
1257  * in the list may become empty/closed before they are evaluated as
1258  * base lot, so we should check this for each lot. */
1259  if (!right_lot)
1260  continue;
1261  if (gnc_lot_count_splits (right_lot) == 0)
1262  {
1263  gnc_lot_destroy (right_lot);
1264  right_iter->data = NULL;
1265  continue;
1266  }
1267  if (gnc_lot_is_closed (right_lot))
1268  continue;
1269 
1270  /* Balancing transactions for invoice/payments can only happen
1271  * in the same account. */
1272  if (acct != gnc_lot_get_account (right_lot))
1273  continue;
1274 
1275 
1276  /* Only attempt to balance if the base lot and balancing lot are
1277  * of the opposite sign. (Otherwise we would increase the balance
1278  * of the lot - Duh */
1279  right_lot_bal = gnc_lot_get_balance (right_lot);
1280  if (gnc_numeric_positive_p (left_lot_bal) == gnc_numeric_positive_p (right_lot_bal))
1281  continue;
1282 
1283  /* Ok we found two lots than can (partly) offset each other.
1284  * Depending on the lot types, a different action is needed to accomplish this.
1285  * 1. Both lots are document lots (invoices/credit notes)
1286  * -> Create a lot linking transaction between the lots
1287  * 2. Both lots are payment lots (lots without a document attached)
1288  * -> Use part of the bigger lot to the close the smaller lot
1289  * 3. One document lot with one payment lot
1290  * -> Use (part of) the payment to offset (part of) the document lot,
1291  * Which one will be closed depends on which is the bigger one
1292  */
1293  right_lot_has_doc = (gncInvoiceGetInvoiceFromLot (right_lot) != NULL);
1294  if (left_lot_has_doc && right_lot_has_doc)
1295  gncOwnerCreateLotLink (left_lot, right_lot, owner);
1296  else if (!left_lot_has_doc && !right_lot_has_doc)
1297  {
1298  gint cmp = gnc_numeric_compare (gnc_numeric_abs (left_lot_bal),
1299  gnc_numeric_abs (right_lot_bal));
1300  if (cmp >= 0)
1301  gncOwnerOffsetLots (left_lot, right_lot, owner);
1302  else
1303  gncOwnerOffsetLots (right_lot, left_lot, owner);
1304  }
1305  else
1306  {
1307  GNCLot *doc_lot = left_lot_has_doc ? left_lot : right_lot;
1308  GNCLot *pay_lot = left_lot_has_doc ? right_lot : left_lot;
1309  // Ok, let's try to move a payment from pay_lot to doc_lot
1310  gncOwnerOffsetLots (pay_lot, doc_lot, owner);
1311  }
1312 
1313  /* If we get here, then right_lot was modified
1314  * If the lot has a document, send an event for send an event for it as well
1315  * so it gets potentially updated as paid */
1316 
1317  {
1318  GncInvoice *this_invoice = gncInvoiceGetInvoiceFromLot(right_lot);
1319  if (this_invoice)
1320  qof_event_gen (QOF_INSTANCE(this_invoice), QOF_EVENT_MODIFY, NULL);
1321  }
1322  left_modified = TRUE;
1323  }
1324 
1325  /* If left_lot was modified and the lot has a document,
1326  * send an event for send an event for it as well
1327  * so it gets potentially updated as paid */
1328  if (left_modified)
1329  {
1330  GncInvoice *this_invoice = gncInvoiceGetInvoiceFromLot(left_lot);
1331  if (this_invoice)
1332  qof_event_gen (QOF_INSTANCE(this_invoice), QOF_EVENT_MODIFY, NULL);
1333  }
1334  xaccAccountCommitEdit (acct);
1335 
1336  }
1337 }
gint gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
gnc_numeric gnc_numeric_abs(gnc_numeric a)
gboolean gnc_numeric_positive_p(gnc_numeric a)
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Definition: gncInvoice.c:1174
gboolean gnc_lot_is_closed(GNCLot *lot)
Definition: gnc-lot.c:376
void xaccAccountBeginEdit(Account *acc)
Definition: Account.c:1280
Account * gnc_lot_get_account(const GNCLot *lot)
Definition: gnc-lot.c:386
void qof_event_gen(QofInstance *entity, QofEventId event_type, gpointer event_data)
Invoke all registered event handlers using the given arguments.
void xaccAccountCommitEdit(Account *acc)
Definition: Account.c:1321
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
Definition: gnc-lot.c:477
void gncOwnerBeginEdit ( GncOwner owner)

These are convenience wrappers around gnc{Vender,Customer,Job,Employee}* functions. This allows you to begin edit, destroy commit edit an owner without knowing its type.

Definition at line 73 of file gncOwner.c.

74 {
75  if (!owner) return;
76  switch (owner->type)
77  {
78  case GNC_OWNER_NONE :
79  case GNC_OWNER_UNDEFINED :
80  break;
81  case GNC_OWNER_CUSTOMER :
82  {
83  gncCustomerBeginEdit(owner->owner.customer);
84  break;
85  }
86  case GNC_OWNER_JOB :
87  {
88  gncJobBeginEdit(owner->owner.job);
89  break;
90  }
91  case GNC_OWNER_VENDOR :
92  {
93  gncVendorBeginEdit(owner->owner.vendor);
94  break;
95  }
96  case GNC_OWNER_EMPLOYEE :
97  {
98  gncEmployeeBeginEdit(owner->owner.employee);
99  break;
100  }
101  }
102 }
int gncOwnerCompare ( const GncOwner a,
const GncOwner b 
)

Sort on name

Definition at line 568 of file gncOwner.c.

569 {
570  if (!a && !b) return 0;
571  if (!a && b) return 1;
572  if (a && !b) return -1;
573 
574  if (a->type != b->type)
575  return (a->type - b->type);
576 
577  switch (a->type)
578  {
579  case GNC_OWNER_NONE:
580  case GNC_OWNER_UNDEFINED:
581  default:
582  return 0;
583  case GNC_OWNER_CUSTOMER:
584  return gncCustomerCompare (a->owner.customer, b->owner.customer);
585  case GNC_OWNER_VENDOR:
586  return gncVendorCompare (a->owner.vendor, b->owner.vendor);
587  case GNC_OWNER_EMPLOYEE:
588  return gncEmployeeCompare (a->owner.employee, b->owner.employee);
589  case GNC_OWNER_JOB:
590  return gncJobCompare (a->owner.job, b->owner.job);
591  }
592 }
int gncVendorCompare(const GncVendor *a, const GncVendor *b)
Definition: gncVendor.c:801
GNCLot* gncOwnerCreatePaymentLot ( const GncOwner owner,
Transaction txn,
Account posted_acc,
Account xfer_acc,
gnc_numeric  amount,
gnc_numeric  exch,
Timespec  date,
const char *  memo,
const char *  num 
)

Create a lot for a payment to the owner using the other parameters passed in. If a transaction is set, this transaction will be reused if possible (meaning, if the transaction currency matches the owner's currency and if the transaction has (at least?) one split in the transfer account).

Definition at line 701 of file gncOwner.c.

705 {
706  QofBook *book;
707  Split *split;
708  const char *name;
709  gnc_commodity *commodity;
710  Split *xfer_split = NULL;
711  GNCLot *payment_lot;
712 
713  /* Verify our arguments */
714  if (!owner || !posted_acc || !xfer_acc) return NULL;
715  g_return_val_if_fail (owner->owner.undefined != NULL, NULL);
716 
717  /* Compute the ancillary data */
718  book = gnc_account_get_book (posted_acc);
719  name = gncOwnerGetName (gncOwnerGetEndOwner ((GncOwner*)owner));
720  commodity = gncOwnerGetCurrency (owner);
721 // reverse = use_reversed_payment_amounts(owner);
722 
723  if (txn)
724  {
725  /* Pre-existing transaction was specified. We completely clear it,
726  * except for the split in the transfer account, unless the
727  * transaction can't be reused (wrong currency, wrong transfer account).
728  * In that case, the transaction is simply removed and an new
729  * one created. */
730 
731  xfer_split = xaccTransFindSplitByAccount(txn, xfer_acc);
732 
733  if (xaccTransGetCurrency(txn) != gncOwnerGetCurrency (owner))
734  {
735  g_message("Uh oh, mismatching currency/commodity between selected transaction and owner. We fall back to manual creation of a new transaction.");
736  xfer_split = NULL;
737  }
738 
739  if (!xfer_split)
740  {
741  g_message("Huh? Asset account not found anymore. Fully deleting old txn and now creating a new one.");
742 
743  xaccTransBeginEdit (txn);
744  xaccTransDestroy (txn);
745  xaccTransCommitEdit (txn);
746 
747  txn = NULL;
748  }
749  else
750  {
751  int i = 0;
752  xaccTransBeginEdit (txn);
753  while (i < xaccTransCountSplits(txn))
754  {
755  Split *split = xaccTransGetSplit (txn, i);
756  if (split == xfer_split)
757  {
758  gnc_set_num_action (NULL, split, num, _("Payment"));
759  ++i;
760  }
761  else
762  {
763  xaccSplitDestroy(split);
764  }
765  }
766  /* Note: don't commit transaction now - that would insert an imbalance split.*/
767  }
768  }
769 
770  /* Create the transaction if we don't have one yet */
771  if (!txn)
772  {
773  txn = xaccMallocTransaction (book);
774  xaccTransBeginEdit (txn);
775  }
776 
777  /* Insert a split for the transfer account if we don't have one yet */
778  if (!xfer_split)
779  {
780 
781  /* Set up the transaction */
782  xaccTransSetDescription (txn, name ? name : "");
783  /* set per book option */
784  xaccTransSetCurrency (txn, commodity);
786  xaccTransSetDatePostedTS (txn, &date);
787 
788 
789  /* The split for the transfer account */
790  split = xaccMallocSplit (book);
791  xaccSplitSetMemo (split, memo);
792  /* set per book option */
793  gnc_set_num_action (NULL, split, num, _("Payment"));
794  xaccAccountBeginEdit (xfer_acc);
795  xaccAccountInsertSplit (xfer_acc, split);
796  xaccAccountCommitEdit (xfer_acc);
797  xaccTransAppendSplit (txn, split);
798 
799  if (gnc_commodity_equal(xaccAccountGetCommodity(xfer_acc), commodity))
800  {
801  xaccSplitSetBaseValue (split, amount, commodity);
802  }
803  else
804  {
805  /* Need to value the payment in terms of the owner commodity */
806  gnc_numeric payment_value = gnc_numeric_mul(amount,
808 
809  xaccSplitSetAmount(split, amount);
810  xaccSplitSetValue(split, payment_value);
811  }
812  }
813 
814  /* Add a split in the post account */
815  split = xaccMallocSplit (book);
816  xaccSplitSetMemo (split, memo);
817  /* set per book option */
818  gnc_set_num_action (NULL, split, num, _("Payment"));
819  xaccAccountBeginEdit (posted_acc);
820  xaccAccountInsertSplit (posted_acc, split);
821  xaccAccountCommitEdit (posted_acc);
822  xaccTransAppendSplit (txn, split);
823  xaccSplitSetBaseValue (split, gnc_numeric_neg (amount), commodity);
824 
825  /* Create a new lot for the payment */
826  payment_lot = gnc_lot_new (book);
827  gncOwnerAttachToLot (owner, payment_lot);
828  gnc_lot_add_split (payment_lot, split);
829 
830  /* Mark the transaction as a payment */
831  gnc_set_num_action (txn, NULL, num, _("Payment"));
833 
834  /* Commit this new transaction */
835  xaccTransCommitEdit (txn);
836 
837  return payment_lot;
838 }
void xaccSplitSetValue(Split *s, gnc_numeric amt)
Definition: Split.c:1294
#define xaccTransAppendSplit(t, s)
Definition: Transaction.h:357
Transaction * xaccMallocTransaction(QofBook *book)
Definition: Transaction.c:513
void xaccSplitSetBaseValue(Split *s, gnc_numeric value, const gnc_commodity *base_currency)
Definition: Split.c:1341
Split * xaccTransGetSplit(const Transaction *trans, int i)
Definition: Transaction.c:2144
gboolean xaccSplitDestroy(Split *split)
Definition: Split.c:1492
gnc_numeric gnc_numeric_neg(gnc_numeric a)
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
void gnc_lot_add_split(GNCLot *lot, Split *split)
Definition: gnc-lot.c:569
void xaccTransSetDescription(Transaction *trans, const char *desc)
Definition: Transaction.c:2085
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Definition: Transaction.c:1354
void xaccTransDestroy(Transaction *trans)
Definition: Transaction.c:1402
int xaccTransCountSplits(const Transaction *trans)
Definition: Transaction.c:2170
void xaccTransSetTxnType(Transaction *trans, char type)
Definition: Transaction.c:2016
void xaccSplitSetAmount(Split *s, gnc_numeric amt)
Definition: Split.c:1258
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
void xaccSplitSetMemo(Split *split, const char *memo)
Definition: Split.c:1774
void gncOwnerAttachToLot(const GncOwner *owner, GNCLot *lot)
Definition: gncOwner.c:600
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1579
void xaccTransBeginEdit(Transaction *trans)
Definition: Transaction.c:1380
#define TXN_TYPE_PAYMENT
Definition: Transaction.h:121
Split * xaccMallocSplit(QofBook *book)
Definition: Split.c:582
const GncOwner * gncOwnerGetEndOwner(const GncOwner *owner)
Definition: gncOwner.c:550
Definition: SplitP.h:71
void xaccAccountBeginEdit(Account *acc)
Definition: Account.c:1280
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Definition: Account.c:3148
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Definition: Transaction.c:1348
#define xaccAccountInsertSplit(acc, s)
Definition: Account.h:972
time64 gnc_time(time64 *tbuf)
get the current local time
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
Definition: Transaction.c:1951
#define GNC_DENOM_AUTO
Definition: gnc-numeric.h:246
void xaccAccountCommitEdit(Account *acc)
Definition: Account.c:1321
void xaccTransSetDatePostedTS(Transaction *trans, const Timespec *ts)
Definition: Transaction.c:1970
gboolean gncOwnerEqual ( const GncOwner a,
const GncOwner b 
)

Assess equality by checking

  • if both owner objects refer to the same owner type
  • and if the owner reference points to the same {vendor/customer/employee} in memory

Definition at line 382 of file gncOwner.c.

383 {
384  if (!a || !b) return FALSE;
385  if (gncOwnerGetType (a) != gncOwnerGetType (b)) return FALSE;
386  return (a->owner.undefined == b->owner.undefined);
387 }
GncOwnerType gncOwnerGetType(const GncOwner *owner)
Definition: gncOwner.c:201
Split* gncOwnerFindOffsettingSplit ( GNCLot pay_lot,
gnc_numeric  target_value 
)

Helper function to find a split in lot that best offsets target_value Obviously it should be of opposite sign. If there are more splits of opposite sign the following criteria are used in order of preference:

  1. exact match in abs value is preferred over larger abs value
  2. larger abs value is preferred over smaller abs value
  3. if previous and new candidate are in the same value category, prefer real payment splits over lot link splits
  4. if previous and new candiate are of same split type prefer biggest abs value.

Definition at line 848 of file gncOwner.c.

849 {
850  SplitList *ls_iter = NULL;
851  Split *best_split = NULL;
852  gnc_numeric best_val = { 0, 1};
853  gint best_flags = 0;
854 
855  if (!lot)
856  return NULL;
857 
858  for (ls_iter = gnc_lot_get_split_list (lot); ls_iter; ls_iter = ls_iter->next)
859  {
860  Split *split = ls_iter->data;
861  Transaction *txn;
862  gnc_numeric split_value;
863  gint new_flags = 0;
864  gint val_cmp = 0;
865 
866  if (!split)
867  continue;
868 
869 
870  txn = xaccSplitGetParent (split);
871  if (!txn)
872  {
873  // Ooops - the split doesn't belong to any transaction !
874  // This is not expected so issue a warning and continue with next split
875  PWARN("Encountered a split in a payment lot that's not part of any transaction. "
876  "This is unexpected! Skipping split %p.", split);
877  continue;
878  }
879 
880  // Check if this split has the opposite sign of the target value we want to offset
881  split_value = xaccSplitGetValue (split);
882  if (gnc_numeric_positive_p (target_value) == gnc_numeric_positive_p (split_value))
883  continue;
884 
885  // Ok we have found a split that potentially can offset the target value
886  // Let's see if it's better than what we have found already.
887  val_cmp = gnc_numeric_compare (gnc_numeric_abs (split_value),
888  gnc_numeric_abs (target_value));
889  if (val_cmp == 0)
890  new_flags += is_equal;
891  else if (val_cmp > 0)
892  new_flags += is_more;
893  else
894  new_flags += is_less;
895 
896  if (xaccTransGetTxnType (txn) != TXN_TYPE_LINK)
897  new_flags += is_pay_split;
898 
899  if ((new_flags >= best_flags) &&
900  (gnc_numeric_compare (gnc_numeric_abs (split_value),
901  gnc_numeric_abs (best_val)) > 0))
902  {
903  // The new split is a better match than what we found so far
904  best_split = split;
905  best_flags = new_flags;
906  best_val = split_value;
907  }
908  }
909 
910  return best_split;
911 }
char xaccTransGetTxnType(const Transaction *trans)
Definition: Transaction.c:2302
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
gint gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
#define PWARN(format, args...)
Definition: qoflog.h:243
GList SplitList
Definition: gnc-engine.h:203
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
Definition: gnc-lot.c:417
gnc_numeric gnc_numeric_abs(gnc_numeric a)
#define TXN_TYPE_LINK
Definition: Transaction.h:122
gboolean gnc_numeric_positive_p(gnc_numeric a)
Definition: SplitP.h:71
gnc_numeric xaccSplitGetValue(const Split *split)
Definition: Split.c:1993
int gncOwnerGCompareFunc ( const GncOwner a,
const GncOwner b 
)

Same as gncOwnerEqual, but returns 0 if equal to be used as a GList custom compare function

Definition at line 389 of file gncOwner.c.

390 {
391  if (gncOwnerEqual (a, b))
392  return 0;
393  else
394  return 1;
395 }
gboolean gncOwnerEqual(const GncOwner *a, const GncOwner *b)
Definition: gncOwner.c:382
GList* gncOwnerGetAccountTypesList ( const GncOwner owner)

Returns a GList of account-types based on the owner type

Definition at line 1383 of file gncOwner.c.

1384 {
1385  g_return_val_if_fail (owner, NULL);
1386 
1387  switch (gncOwnerGetType (owner))
1388  {
1389  case GNC_OWNER_CUSTOMER:
1390  return (g_list_prepend (NULL, (gpointer)ACCT_TYPE_RECEIVABLE));
1391  case GNC_OWNER_VENDOR:
1392  case GNC_OWNER_EMPLOYEE:
1393  return (g_list_prepend (NULL, (gpointer)ACCT_TYPE_PAYABLE));
1394  break;
1395  default:
1396  return (g_list_prepend (NULL, (gpointer)ACCT_TYPE_NONE));
1397  }
1398 }
GncOwnerType gncOwnerGetType(const GncOwner *owner)
Definition: gncOwner.c:201
gnc_numeric gncOwnerGetBalanceInCurrency ( const GncOwner owner,
const gnc_commodity report_currency 
)

Given an owner, extract the open balance from the owner and then convert it to the desired currency.

Definition at line 1417 of file gncOwner.c.

1419 {
1420  gnc_numeric balance = gnc_numeric_zero ();
1421  GList *acct_list, *acct_node, *acct_types, *lot_list = NULL, *lot_node;
1422  QofBook *book;
1423  gnc_commodity *owner_currency;
1424  GNCPriceDB *pdb;
1425 
1426  g_return_val_if_fail (owner, gnc_numeric_zero ());
1427 
1428  /* Get account list */
1429  book = qof_instance_get_book (qofOwnerGetOwner (owner));
1430  acct_list = gnc_account_get_descendants (gnc_book_get_root_account (book));
1431  acct_types = gncOwnerGetAccountTypesList (owner);
1432  owner_currency = gncOwnerGetCurrency (owner);
1433 
1434  /* For each account */
1435  for (acct_node = acct_list; acct_node; acct_node = acct_node->next)
1436  {
1437  Account *account = acct_node->data;
1438 
1439  /* Check if this account can have lots for the owner, otherwise skip to next */
1440  if (g_list_index (acct_types, (gpointer)xaccAccountGetType (account))
1441  == -1)
1442  continue;
1443 
1444 
1445  if (!gnc_commodity_equal (owner_currency, xaccAccountGetCommodity (account)))
1446  continue;
1447 
1448  /* Get a list of open lots for this owner and account */
1450  (gpointer)owner, NULL);
1451  /* For each lot */
1452  for (lot_node = lot_list; lot_node; lot_node = lot_node->next)
1453  {
1454  GNCLot *lot = lot_node->data;
1455  gnc_numeric lot_balance = gnc_lot_get_balance (lot);
1456  GncInvoice *invoice = gncInvoiceGetInvoiceFromLot(lot);
1457  if (invoice)
1458  balance = gnc_numeric_add (balance, lot_balance,
1460  }
1461  }
1462 
1463  pdb = gnc_pricedb_get_db (book);
1464 
1465  if (report_currency)
1467  pdb, balance, owner_currency, report_currency);
1468 
1469  return balance;
1470 }
int gnc_commodity_get_fraction(const gnc_commodity *cm)
GList * gncOwnerGetAccountTypesList(const GncOwner *owner)
Definition: gncOwner.c:1383
QofBook * qof_instance_get_book(gconstpointer)
GNCAccountType xaccAccountGetType(const Account *acc)
Definition: Account.c:3009
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
GNCPriceDB * gnc_pricedb_get_db(QofBook *book)
Definition: gnc-pricedb.c:872
QofInstance * qofOwnerGetOwner(const GncOwner *owner)
Definition: gncOwner.c:253
gnc_numeric gnc_pricedb_convert_balance_latest_price(GNCPriceDB *pdb, gnc_numeric balance, const gnc_commodity *balance_currency, const gnc_commodity *new_currency)
Definition: gnc-pricedb.c:2013
GList * gnc_account_get_descendants(const Account *account)
Definition: Account.c:2755
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Definition: gncInvoice.c:1174
gboolean gncOwnerLotMatchOwnerFunc(GNCLot *lot, gpointer user_data)
Definition: gncOwner.c:657
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Definition: Account.c:3148
LotList * xaccAccountFindOpenLots(const Account *acc, gboolean(*match_func)(GNCLot *lot, gpointer user_data), gpointer user_data, GCompareFunc sort_func)
Definition: Account.c:3751
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
Definition: gnc-lot.c:477
GList* gncOwnerGetCommoditiesList ( const GncOwner owner)

Returns a GList of currencies associated with the owner

Definition at line 1401 of file gncOwner.c.

1402 {
1403  g_return_val_if_fail (owner, NULL);
1404  g_return_val_if_fail (gncOwnerGetCurrency(owner), NULL);
1405 
1406  return (g_list_prepend (NULL, gncOwnerGetCurrency(owner)));
1407 }
GncCustomer* gncOwnerGetCustomer ( const GncOwner owner)

If the given owner is of type GNC_OWNER_CUSTOMER, returns the pointer to the customer object. Otherwise returns NULL.

Definition at line 347 of file gncOwner.c.

348 {
349  if (!owner) return NULL;
350  if (owner->type != GNC_OWNER_CUSTOMER) return NULL;
351  return owner->owner.customer;
352 }
GncEmployee* gncOwnerGetEmployee ( const GncOwner owner)

If the given owner is of type GNC_OWNER_EMPLOYEE, returns the pointer to the employee object. Otherwise returns NULL.

Definition at line 368 of file gncOwner.c.

369 {
370  if (!owner) return NULL;
371  if (owner->type != GNC_OWNER_EMPLOYEE) return NULL;
372  return owner->owner.employee;
373 }
const GncOwner* gncOwnerGetEndOwner ( const GncOwner owner)

Get the "parent" Owner or GncGUID thereof. The "parent" owner is the Customer or Vendor, or the Owner of a Job

Definition at line 550 of file gncOwner.c.

551 {
552  if (!owner) return NULL;
553  switch (owner->type)
554  {
555  case GNC_OWNER_NONE:
556  case GNC_OWNER_UNDEFINED:
557  default:
558  return NULL;
559  case GNC_OWNER_CUSTOMER:
560  case GNC_OWNER_VENDOR:
561  case GNC_OWNER_EMPLOYEE:
562  return owner;
563  case GNC_OWNER_JOB:
564  return gncJobGetOwner (owner->owner.job);
565  }
566 }
const GncGUID* gncOwnerGetGUID ( const GncOwner owner)

Get the GncGUID of the immediate owner

Definition at line 496 of file gncOwner.c.

497 {
498  if (!owner) return NULL;
499 
500  switch (owner->type)
501  {
502  case GNC_OWNER_NONE:
503  case GNC_OWNER_UNDEFINED:
504  default:
505  return NULL;
506  case GNC_OWNER_CUSTOMER:
507  return qof_instance_get_guid (QOF_INSTANCE(owner->owner.customer));
508  case GNC_OWNER_JOB:
509  return qof_instance_get_guid (QOF_INSTANCE(owner->owner.job));
510  case GNC_OWNER_VENDOR:
511  return qof_instance_get_guid (QOF_INSTANCE(owner->owner.vendor));
512  case GNC_OWNER_EMPLOYEE:
513  return qof_instance_get_guid (QOF_INSTANCE(owner->owner.employee));
514  }
515 }
const GncGUID * qof_instance_get_guid(gconstpointer)
GncJob* gncOwnerGetJob ( const GncOwner owner)

If the given owner is of type GNC_OWNER_JOB, returns the pointer to the job object. Otherwise returns NULL.

Definition at line 354 of file gncOwner.c.

355 {
356  if (!owner) return NULL;
357  if (owner->type != GNC_OWNER_JOB) return NULL;
358  return owner->owner.job;
359 }
gboolean gncOwnerGetOwnerFromLot ( GNCLot lot,
GncOwner owner 
)

Get the owner from the lot. If an owner is found in the lot, fill in "owner" and return TRUE. Otherwise return FALSE.

Definition at line 614 of file gncOwner.c.

615 {
616  GncGUID *guid = NULL;
617  QofBook *book;
618  GncOwnerType type = GNC_OWNER_NONE;
619  guint64 type64 = 0;
620 
621  if (!lot || !owner) return FALSE;
622 
623  book = gnc_lot_get_book (lot);
624  qof_instance_get (QOF_INSTANCE (lot),
625  GNC_OWNER_TYPE, &type64,
626  GNC_OWNER_GUID, &guid,
627  NULL);
628  type = (GncOwnerType) type64;
629  switch (type)
630  {
631  case GNC_OWNER_CUSTOMER:
632  gncOwnerInitCustomer (owner, gncCustomerLookup (book, guid));
633  break;
634  case GNC_OWNER_VENDOR:
635  gncOwnerInitVendor (owner, gncVendorLookup (book, guid));
636  break;
637  case GNC_OWNER_EMPLOYEE:
638  gncOwnerInitEmployee (owner, gncEmployeeLookup (book, guid));
639  break;
640  case GNC_OWNER_JOB:
641  gncOwnerInitJob (owner, gncJobLookup (book, guid));
642  break;
643  default:
644  return FALSE;
645  }
646 
647  return (owner->owner.undefined != NULL);
648 }
void qof_instance_get(const QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_get.
Definition: guid.h:65
GncOwnerType gncOwnerGetType ( const GncOwner owner)

Returns the GncOwnerType of this owner. (Not to be confused with qofOwnerGetType().)

Definition at line 201 of file gncOwner.c.

202 {
203  if (!owner) return GNC_OWNER_NONE;
204  return owner->type;
205 }
gpointer gncOwnerGetUndefined ( const GncOwner owner)

If the given owner is of type GNC_OWNER_UNDEFINED, returns the undefined pointer, which is usually NULL. Otherwise returns NULL.

Definition at line 340 of file gncOwner.c.

341 {
342  if (!owner) return NULL;
343  if (owner->type != GNC_OWNER_UNDEFINED) return NULL;
344  return owner->owner.undefined;
345 }
GncVendor* gncOwnerGetVendor ( const GncOwner owner)

If the given owner is of type GNC_OWNER_VENDOR, returns the pointer to the vendor object. Otherwise returns NULL.

Definition at line 361 of file gncOwner.c.

362 {
363  if (!owner) return NULL;
364  if (owner->type != GNC_OWNER_VENDOR) return NULL;
365  return owner->owner.vendor;
366 }
gboolean gncOwnerIsValid ( const GncOwner owner)

Returns TRUE if the given owner is one of the valid objects. Returns FALSE if the owner is (still) undefined, or if it is NULL.

Definition at line 650 of file gncOwner.c.

651 {
652  if (!owner) return FALSE;
653  return (owner->owner.undefined != NULL);
654 }
gboolean gncOwnerLotMatchOwnerFunc ( GNCLot lot,
gpointer  user_data 
)

Helper function used to filter a list of lots by owner.

Definition at line 657 of file gncOwner.c.

658 {
659  const GncOwner *req_owner = user_data;
660  GncOwner lot_owner;
661  const GncOwner *end_owner;
662  GncInvoice *invoice = gncInvoiceGetInvoiceFromLot (lot);
663 
664  /* Determine the owner associated to the lot */
665  if (invoice)
666  /* Invoice lots */
667  end_owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice));
668  else if (gncOwnerGetOwnerFromLot (lot, &lot_owner))
669  /* Pre-payment lots */
670  end_owner = gncOwnerGetEndOwner (&lot_owner);
671  else
672  return FALSE;
673 
674  /* Is this a lot for the requested owner ? */
675  return gncOwnerEqual (end_owner, req_owner);
676 }
gboolean gncOwnerEqual(const GncOwner *a, const GncOwner *b)
Definition: gncOwner.c:382
gboolean gncOwnerGetOwnerFromLot(GNCLot *lot, GncOwner *owner)
Definition: gncOwner.c:614
const GncOwner * gncOwnerGetEndOwner(const GncOwner *owner)
Definition: gncOwner.c:550
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Definition: gncInvoice.c:1174
gint gncOwnerLotsSortFunc ( GNCLot lotA,
GNCLot lotB 
)

Helper function used to sort lots by date. If the lot is linked to an invoice, use the invoice posted date, otherwise use the lot's opened date.

Definition at line 679 of file gncOwner.c.

680 {
681  GncInvoice *ia, *ib;
682  Timespec da, db;
683 
684  ia = gncInvoiceGetInvoiceFromLot (lotA);
685  ib = gncInvoiceGetInvoiceFromLot (lotB);
686 
687  if (ia)
688  da = gncInvoiceGetDateDue (ia);
689  else
691 
692  if (ib)
693  db = gncInvoiceGetDateDue (ib);
694  else
696 
697  return timespec_cmp (&da, &db);
698 }
Use a 64-bit unsigned int timespec.
Definition: gnc-date.h:299
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
Split * gnc_lot_get_earliest_split(GNCLot *lot)
Definition: gnc-lot.c:648
gint timespec_cmp(const Timespec *ta, const Timespec *tb)
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Definition: gncInvoice.c:1174
Timespec xaccTransRetDatePostedTS(const Transaction *trans)
Definition: Transaction.c:2243
GncOwner* gncOwnerNew ( void  )

These two functions are mainly for the convenience of scheme code. Normal C code has no need to ever use these two functions, and rather can just use a GncOwner directly and just pass around a pointer to it.

Definition at line 58 of file gncOwner.c.

59 {
60  GncOwner *o;
61 
62  o = g_new0 (GncOwner, 1);
63  o->type = GNC_OWNER_NONE;
64  return o;
65 }
gboolean gncOwnerReduceSplitTo ( Split split,
gnc_numeric  target_value 
)

Helper function to reduce the value of a split to target_value. To make sure the split's parent transaction remains balanced a second split will be created with the remainder. Similarly if the split was part of a (business) lot, the remainder split will be added to the same lot to keep the lot's balance unchanged.

Definition at line 914 of file gncOwner.c.

915 {
916  gnc_numeric split_val = xaccSplitGetValue (split);
917  gnc_numeric rem_val;
918  Split *rem_split;
919  Transaction *txn;
920  GNCLot *lot;
921 
922  if (gnc_numeric_positive_p (split_val) != gnc_numeric_positive_p (target_value))
923  return FALSE; // Split and target value have to be of the same sign
924 
925  if (gnc_numeric_equal (split_val, target_value))
926  return FALSE; // Split already has the target value
927 
928  rem_val = gnc_numeric_sub (split_val, target_value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD); // note: values are of opposite sign
929  rem_split = xaccMallocSplit (xaccSplitGetBook (split));
930  xaccSplitCopyOnto (split, rem_split);
931  xaccSplitSetValue (rem_split, rem_val);
932 
933  txn = xaccSplitGetParent (split);
934  xaccTransBeginEdit (txn);
935  xaccSplitSetValue (split, target_value);
936  xaccSplitSetParent (rem_split, txn);
937  xaccTransCommitEdit (txn);
938 
939  lot = xaccSplitGetLot (split);
940  gnc_lot_add_split (lot, rem_split);
941 
942  return TRUE;
943 }
void xaccSplitSetValue(Split *s, gnc_numeric amt)
Definition: Split.c:1294
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
void xaccSplitCopyOnto(const Split *from_split, Split *to_split)
Definition: Split.c:686
void gnc_lot_add_split(GNCLot *lot, Split *split)
Definition: gnc-lot.c:569
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
QofBook * xaccSplitGetBook(const Split *split)
Definition: Split.c:2042
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1579
void xaccTransBeginEdit(Transaction *trans)
Definition: Transaction.c:1380
gboolean gnc_numeric_positive_p(gnc_numeric a)
Split * xaccMallocSplit(QofBook *book)
Definition: Split.c:582
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Definition: SplitP.h:71
gnc_numeric xaccSplitGetValue(const Split *split)
Definition: Split.c:1993
#define GNC_DENOM_AUTO
Definition: gnc-numeric.h:246
GNCLot * xaccSplitGetLot(const Split *split)
Definition: Split.c:1953
void gncOwnerSetLotLinkMemo ( Transaction ll_txn)

To help a user understand what a lot link transaction does, we set the memo to name all documents involved in the link. The function below calculates this memo and sets it for all splits in the lot link transaction.

Definition at line 946 of file gncOwner.c.

947 {
948  gchar *memo_prefix = _("Offset between documents: ");
949  gchar *new_memo;
950  SplitList *lts_iter;
951  SplitList *splits = NULL, *siter;
952  GList *titles = NULL, *titer;
953 
954  if (!ll_txn)
955  return;
956 
957  if (xaccTransGetTxnType (ll_txn) != TXN_TYPE_LINK)
958  return;
959 
960  // Find all splits in the lot link transaction that are also in a document lot
961  for (lts_iter = xaccTransGetSplitList (ll_txn); lts_iter; lts_iter = lts_iter->next)
962  {
963  Split *split = lts_iter->data;
964  GNCLot *lot;
965  GncInvoice *invoice;
966  gchar *title;
967 
968  if (!split)
969  continue;
970 
971  lot = xaccSplitGetLot (split);
972  if (!lot)
973  continue;
974 
975  invoice = gncInvoiceGetInvoiceFromLot (lot);
976  if (!invoice)
977  continue;
978 
979  title = g_strdup_printf ("%s %s", gncInvoiceGetTypeString (invoice), gncInvoiceGetID (invoice));
980 
981  titles = g_list_insert_sorted (titles, title, (GCompareFunc)g_strcmp0);
982  splits = g_list_prepend (splits, split); // splits don't need to be sorted
983  }
984 
985  if (!titles)
986  return; // We didn't find document lots
987 
988  // Create the memo as we'd want it to be
989  new_memo = g_strconcat (memo_prefix, titles->data, NULL);
990  for (titer = titles->next; titer; titer = titer->next)
991  {
992  gchar *tmp_memo = g_strconcat (new_memo, " - ", titer->data, NULL);
993  g_free (new_memo);
994  new_memo = tmp_memo;
995  }
996  g_list_free_full (titles, g_free);
997 
998  // Update the memos of all the splits we found previously (if needed)
999  for (siter = splits; siter; siter = siter->next)
1000  {
1001  if (g_strcmp0 (xaccSplitGetMemo (siter->data), new_memo) != 0)
1002  xaccSplitSetMemo (siter->data, new_memo);
1003  }
1004 
1005  g_list_free (splits);
1006  g_free (new_memo);
1007 }
char xaccTransGetTxnType(const Transaction *trans)
Definition: Transaction.c:2302
GList SplitList
Definition: gnc-engine.h:203
void xaccSplitSetMemo(Split *split, const char *memo)
Definition: Split.c:1774
#define TXN_TYPE_LINK
Definition: Transaction.h:122
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Definition: gncInvoice.c:1174
Definition: SplitP.h:71
const char * xaccSplitGetMemo(const Split *split)
Definition: Split.c:1968
SplitList * xaccTransGetSplitList(const Transaction *trans)
Definition: Transaction.c:2164
GNCLot * xaccSplitGetLot(const Split *split)
Definition: Split.c:1953
QofIdTypeConst gncOwnerTypeToQofIdType ( GncOwnerType  t)

Returns the QofIdType of the given GncOwnerType, or NULL if no suitable one exists.

Definition at line 213 of file gncOwner.c.

214 {
215  QofIdTypeConst type = NULL;
216  switch (t)
217  {
218  case GNC_OWNER_NONE :
219  {
220  type = NULL;
221  break;
222  }
223  case GNC_OWNER_UNDEFINED :
224  {
225  type = NULL;
226  break;
227  }
228  case GNC_OWNER_CUSTOMER :
229  {
230  type = GNC_ID_CUSTOMER;
231  break;
232  }
233  case GNC_OWNER_JOB :
234  {
235  type = GNC_ID_JOB;
236  break;
237  }
238  case GNC_OWNER_VENDOR :
239  {
240  type = GNC_ID_VENDOR;
241  break;
242  }
243  case GNC_OWNER_EMPLOYEE :
244  {
245  type = GNC_ID_EMPLOYEE;
246  break;
247  }
248  }
249  return type;
250 }
const gchar * QofIdTypeConst
Definition: qofid.h:87
QofInstance* qofOwnerGetOwner ( const GncOwner owner)

return the owner itself as an entity.

Definition at line 253 of file gncOwner.c.

254 {
255  QofInstance *ent;
256 
257  if (!owner)
258  {
259  return NULL;
260  }
261  ent = NULL;
262  switch (owner->type)
263  {
264  case GNC_OWNER_NONE :
265  {
266  break;
267  }
268  case GNC_OWNER_UNDEFINED :
269  {
270  break;
271  }
272  case GNC_OWNER_CUSTOMER :
273  {
274  ent = QOF_INSTANCE(owner->owner.customer);
275  break;
276  }
277  case GNC_OWNER_JOB :
278  {
279  ent = QOF_INSTANCE(owner->owner.job);
280  break;
281  }
282  case GNC_OWNER_VENDOR :
283  {
284  ent = QOF_INSTANCE(owner->owner.vendor);
285  break;
286  }
287  case GNC_OWNER_EMPLOYEE :
288  {
289  ent = QOF_INSTANCE(owner->owner.employee);
290  break;
291  }
292  }
293  return ent;
294 }
QofIdTypeConst qofOwnerGetType ( const GncOwner owner)

return the type for the collection.

Definition at line 208 of file gncOwner.c.

209 {
210  return gncOwnerTypeToQofIdType(owner->type);
211 }
QofIdTypeConst gncOwnerTypeToQofIdType(GncOwnerType t)
Definition: gncOwner.c:213
void qofOwnerSetEntity ( GncOwner owner,
QofInstance ent 
)

set the owner from the entity.

Definition at line 297 of file gncOwner.c.

298 {
299  if (!owner || !ent)
300  {
301  return;
302  }
303  if (0 == g_strcmp0(ent->e_type, GNC_ID_CUSTOMER))
304  {
305  owner->type = GNC_OWNER_CUSTOMER;
306  gncOwnerInitCustomer(owner, (GncCustomer*)ent);
307  }
308  else if (0 == g_strcmp0(ent->e_type, GNC_ID_JOB))
309  {
310  owner->type = GNC_OWNER_JOB;
311  gncOwnerInitJob(owner, (GncJob*)ent);
312  }
313  else if (0 == g_strcmp0(ent->e_type, GNC_ID_VENDOR))
314  {
315  owner->type = GNC_OWNER_VENDOR;
316  gncOwnerInitVendor(owner, (GncVendor*)ent);
317  }
318  else if (0 == g_strcmp0(ent->e_type, GNC_ID_EMPLOYEE))
319  {
320  owner->type = GNC_OWNER_EMPLOYEE;
321  gncOwnerInitEmployee(owner, (GncEmployee*)ent);
322  }
323  else
324  {
325  owner->type = GNC_OWNER_NONE;
326  owner->owner.undefined = NULL;
327  }
328 }
QofIdType e_type
Definition: qofinstance.h:69
Definition: gncJob.c:41