/* * Create a payment of "amount" for the owner and match it with * the set of lots passed in. If not lots were given all open * lots for the owner are considered. */ 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) { GNCLot *payment_lot = NULL; GList *selected_lots = NULL; /* Verify our arguments */ if (!owner || !posted_acc || (!xfer_acc && !gnc_numeric_zero_p (amount)) ) return; g_return_if_fail (owner->owner.undefined); /* If there's a real amount to transfer create a lot for this payment */ if (!gnc_numeric_zero_p (amount)) payment_lot = gncOwnerCreatePaymentLot (owner, txn, posted_acc, xfer_acc, amount, exch, date, memo, num); if (lots) selected_lots = lots; else if (auto_pay) selected_lots = xaccAccountFindOpenLots (posted_acc, gncOwnerLotMatchOwnerFunc, (gpointer)owner, NULL); /* And link the selected lots and the payment lot together as well as possible. * If the payment was bigger than the selected documents/overpayments, only * part of the payment will be used. Similarly if more documents were selected * than the payment value set, not all documents will be marked as paid. */ if (payment_lot) selected_lots = g_list_prepend (selected_lots, payment_lot); gncOwnerAutoApplyPaymentsWithLots (owner, selected_lots); g_list_free (selected_lots); }
/* * Given an owner, extract the open balance from the owner and then * convert it to the desired currency. */ gnc_numeric gncOwnerGetBalanceInCurrency (const GncOwner *owner, const gnc_commodity *report_currency) { gnc_numeric balance = gnc_numeric_zero (); GList *acct_list, *acct_node, *acct_types, *lot_list = NULL, *lot_node; QofBook *book; gnc_commodity *owner_currency; GNCPriceDB *pdb; g_return_val_if_fail (owner, gnc_numeric_zero ()); /* Get account list */ book = qof_instance_get_book (qofOwnerGetOwner (owner)); acct_list = gnc_account_get_descendants (gnc_book_get_root_account (book)); acct_types = gncOwnerGetAccountTypesList (owner); owner_currency = gncOwnerGetCurrency (owner); /* For each account */ for (acct_node = acct_list; acct_node; acct_node = acct_node->next) { Account *account = acct_node->data; /* Check if this account can have lots for the owner, otherwise skip to next */ if (g_list_index (acct_types, (gpointer)xaccAccountGetType (account)) == -1) continue; if (!gnc_commodity_equal (owner_currency, xaccAccountGetCommodity (account))) continue; /* Get a list of open lots for this owner and account */ lot_list = xaccAccountFindOpenLots (account, gncOwnerLotMatchOwnerFunc, (gpointer)owner, NULL); /* For each lot */ for (lot_node = lot_list; lot_node; lot_node = lot_node->next) { GNCLot *lot = lot_node->data; gnc_numeric lot_balance = gnc_lot_get_balance (lot); GncInvoice *invoice = gncInvoiceGetInvoiceFromLot(lot); if (invoice) balance = gnc_numeric_add (balance, lot_balance, gnc_commodity_get_fraction (owner_currency), GNC_HOW_RND_ROUND_HALF_UP); } } pdb = gnc_pricedb_get_db (book); if (report_currency) balance = gnc_pricedb_convert_balance_latest_price ( pdb, balance, owner_currency, report_currency); return balance; }
void gnc_payment_window_fill_docs_list (PaymentWindow *pw) { GtkListStore *store; GList *list = NULL, *node; g_return_if_fail (pw->docs_list_tree_view && GTK_IS_TREE_VIEW(pw->docs_list_tree_view)); /* Get a list of open lots for this owner and post account */ if (pw->owner.owner.undefined) list = xaccAccountFindOpenLots (pw->post_acct, gncOwnerLotMatchOwnerFunc, &pw->owner, NULL); /* Clear the existing list */ store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(pw->docs_list_tree_view))); gtk_list_store_clear(store); /* Add the documents and overpayments to the tree view */ for (node = list; node; node = node->next) { GNCLot *lot = node->data; time64 doc_date_time = 0; const gchar *doc_type_str = NULL; const gchar *doc_id_str = NULL; const gchar *doc_deb_str = NULL; const gchar *doc_cred_str = NULL; GtkTreeIter iter; Timespec doc_date; GncInvoice *document; gnc_numeric value = gnc_numeric_zero(); gnc_numeric debit = gnc_numeric_zero(); gnc_numeric credit = gnc_numeric_zero(); /* Find the lot's document if it exists, * it could also be a prepayment lot. */ document = gncInvoiceGetInvoiceFromLot (lot); /* Find the document's date or pre-payment date */ if (document) doc_date = gncInvoiceGetDatePosted (document); else { /* Calculate the payment date based on the lot splits */ Transaction *trans = xaccSplitGetParent (gnc_lot_get_latest_split (lot)); if (trans) doc_date = xaccTransRetDatePostedTS (trans); else continue; /* No valid split in this lot, skip it */ } doc_date_time = timespecToTime64 (doc_date); /* Find the document type. No type means pre-payment in this case */ if (document) { doc_type_str = gncInvoiceGetTypeString (document); } else doc_type_str = _("Pre-Payment"); /* Find the document id. Empty for pre-payments. */ if (document) { doc_id_str = gncInvoiceGetID (document); } /* Find the debit/credit amount. * Invoices/vendor credit notes are debit (increasing the balance) * Customer credit notes/bills are credit (decreasing the balance) * Pre-payments are debit or credit depending on their sign */ value = gnc_lot_get_balance (lot); if (gnc_numeric_positive_p (value)) debit = value; else credit = gnc_numeric_neg (value); /* Only display non-zero debits/credits */ if (!gnc_numeric_zero_p (debit)) doc_deb_str = xaccPrintAmount (debit, gnc_default_print_info (FALSE)); if (!gnc_numeric_zero_p (credit)) doc_cred_str = xaccPrintAmount (credit, gnc_default_print_info (FALSE)); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, doc_date_time, 1, doc_id_str, 2, doc_type_str, 3, doc_deb_str, 4, doc_cred_str, 5, (gpointer)lot, -1); } g_list_free (list); /* Highlight the preset invoice if it's in the new list */ gnc_payment_dialog_highlight_document (pw); }