mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Merge branch 'maint'
This commit is contained in:
commit
119356752f
@ -1826,7 +1826,7 @@ def gnc_numeric_from_decimal(decimal_value):
|
||||
TEN = int(Decimal(0).radix()) # this is always 10
|
||||
numerator_place_value = 1
|
||||
# add each digit to the final value multiplied by the place value
|
||||
# from least significant to most sigificant
|
||||
# from least significant to most significant
|
||||
for i in range(len(digits)-1,-1,-1):
|
||||
numerator += digits[i] * numerator_place_value
|
||||
numerator_place_value *= TEN
|
||||
|
@ -66,7 +66,7 @@ def gnc_numeric_from_decimal(decimal_value):
|
||||
TEN = int(Decimal(0).radix()) # this is always 10
|
||||
numerator_place_value = 1
|
||||
# add each digit to the final value multiplied by the place value
|
||||
# from least significant to most sigificant
|
||||
# from least significant to most significant
|
||||
for i in range(len(digits)-1,-1,-1):
|
||||
numerator += digits[i] * numerator_place_value
|
||||
numerator_place_value *= TEN
|
||||
|
@ -8,7 +8,7 @@ id,company,name,addr1,addr2,addr3,addr4,phone,fax,email,notes,shipname,shipaddr1
|
||||
#company with the same ID will be UPDATED. This may not be what you want!
|
||||
000099,Average Company,Accounts Dept,50 Poor Avenue,,,,,,,,,,,,,,,
|
||||
,Academy,Academy,Some Street,,,,555-237-6959,,,,,,,,,,shipmail
|
||||
,company,name,addr1,addr2,addr3,addr4,phone,fax,emai,lnotes,shipname,shipaddr1,shipaddr2,shipaddr3,shipaddr4,shipphone,shipfax,shipemail
|
||||
,company,name,addr1,addr2,addr3,addr4,phone,fax,email,notes,shipname,shipaddr1,shipaddr2,shipaddr3,shipaddr4,shipphone,shipfax,shipemail
|
||||
,No Address Company,Accounts,,,,,,,,,,,,,,,,
|
||||
|
||||
#Just another example after a blank line
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -990,7 +990,7 @@ gnc_invoice_post(InvoiceWindow *iw, struct post_invoice_params *post_params)
|
||||
gncInvoiceSetCurrency (invoice, gncOwnerGetCurrency (gncInvoiceGetOwner (invoice)));
|
||||
|
||||
/* Fill in the conversion prices with feedback from the user */
|
||||
text = _("One or more of the entries are for accounts different from the invoice/bill currency. You will be asked a conversion rate for each.");
|
||||
text = _("One or more of the entries are for accounts different from the invoice/bill currency. You will be asked to enter a conversion rate for each.");
|
||||
|
||||
/* Ask the user for conversion rates for all foreign currencies
|
||||
* (relative to the invoice currency) */
|
||||
|
@ -1568,23 +1568,34 @@ gboolean gnc_ui_payment_is_customer_payment(const Transaction *txn)
|
||||
// ///////////////
|
||||
static char *gen_split_desc (Transaction *txn, Split *split)
|
||||
{
|
||||
gnc_numeric value = xaccSplitGetValue(split);
|
||||
gnc_numeric value = xaccSplitGetAmount(split);
|
||||
Account *xfer_acct = xaccSplitGetAccount(split);
|
||||
char *acct_name = gnc_account_get_full_name (xfer_acct);
|
||||
const char *action = gnc_get_action_num (txn, split);
|
||||
const char *memo = xaccSplitGetMemo (split);
|
||||
char rec_state = xaccSplitGetReconcile (split);
|
||||
const char *print_amt = xaccPrintAmount(value, gnc_account_print_info (xfer_acct, TRUE));
|
||||
char *split_str = NULL;
|
||||
char *rec_str = NULL;
|
||||
|
||||
if (rec_state == CREC)
|
||||
rec_str = g_strdup_printf("[%s] ", _("Cleared"));
|
||||
else if (rec_state == YREC)
|
||||
rec_str = g_strdup_printf("[%s] ", _("Reconciled"));
|
||||
else
|
||||
rec_str = g_strdup("");
|
||||
|
||||
if (action && *action && memo && *memo)
|
||||
split_str = g_strdup_printf ("%s: %s (%s, %s)", acct_name, print_amt,
|
||||
split_str = g_strdup_printf ("%s%s: %s (%s, %s)", rec_str, acct_name, print_amt,
|
||||
action, memo);
|
||||
else if((action && *action) || (memo && *memo))
|
||||
split_str = g_strdup_printf ("%s: %s (%s)", acct_name, print_amt,
|
||||
split_str = g_strdup_printf ("%s%s: %s (%s)", rec_str, acct_name, print_amt,
|
||||
action ? action : memo);
|
||||
else
|
||||
split_str = g_strdup_printf ("%s: %s", acct_name, print_amt);
|
||||
split_str = g_strdup_printf ("%s%s: %s", rec_str, acct_name, print_amt);
|
||||
|
||||
g_free (acct_name);
|
||||
g_free (rec_str);
|
||||
|
||||
return split_str;
|
||||
}
|
||||
@ -1621,8 +1632,8 @@ static Split *select_payment_split (GtkWindow *parent, Transaction *txn)
|
||||
GList *node;
|
||||
GtkWidget *first_rb = NULL;
|
||||
int answer = GTK_BUTTONS_OK;
|
||||
const char *message = _("While this transaction has multiple splits that can be considered\nas 'the payment split', gnucash only knows how to handle one.\n"
|
||||
"Please select one, the others will be ignored.\n\n");
|
||||
const char *message = _("While this transaction has multiple splits that can be considered\nas 'the payment split', GnuCash only knows how to handle one.\n"
|
||||
"Please select one, the others will be discarded.\n\n");
|
||||
GtkDialog *dialog = GTK_DIALOG(
|
||||
gtk_dialog_new_with_buttons (_("Warning"),
|
||||
parent,
|
||||
@ -1683,10 +1694,11 @@ static Split *select_payment_split (GtkWindow *parent, Transaction *txn)
|
||||
|
||||
static GList *select_txn_lots (GtkWindow *parent, Transaction *txn, Account **post_acct, gboolean *abort)
|
||||
{
|
||||
gboolean has_no_lot_apar_splits = FALSE;
|
||||
SplitList *post_splits = NULL, *no_lot_post_splits = NULL;
|
||||
SplitList *apar_splits = NULL; /* all spits in txn that are APAR type */
|
||||
SplitList *apar_splits_no_lot = NULL; /* all splits in txn that are APAR type, but not tied to a lot */
|
||||
SplitList *iter;
|
||||
GList *txn_lots = NULL;
|
||||
GList *unique_apar_accts = NULL;
|
||||
|
||||
/* There's no use in continuing if I can't set the post_acct or abort variables */
|
||||
if (!post_acct || !abort)
|
||||
@ -1695,11 +1707,20 @@ static GList *select_txn_lots (GtkWindow *parent, Transaction *txn, Account **po
|
||||
*abort = FALSE;
|
||||
*post_acct = NULL;
|
||||
|
||||
post_splits = xaccTransGetAPARAcctSplitList (txn, FALSE);
|
||||
for (iter = post_splits; iter; iter = iter->next)
|
||||
/* Start by filtering out all APAR splits that have lots. Those are the ones we can
|
||||
display as invoices and pre-payments in the payment window. */
|
||||
apar_splits = xaccTransGetAPARAcctSplitList (txn, FALSE);
|
||||
for (iter = apar_splits; iter; iter = iter->next)
|
||||
{
|
||||
GNCLot *postlot = NULL;
|
||||
Split *post_split = iter->data;
|
||||
Account *apar_acct = xaccSplitGetAccount (post_split);
|
||||
|
||||
/* Store found apar_acct in our list of unique_apar_accts
|
||||
* for later processing */
|
||||
if (!g_list_find (unique_apar_accts, apar_acct))
|
||||
unique_apar_accts = g_list_prepend (unique_apar_accts, apar_acct);
|
||||
|
||||
postlot = xaccSplitGetLot (post_split);
|
||||
if (postlot)
|
||||
{
|
||||
@ -1707,59 +1728,55 @@ static GList *select_txn_lots (GtkWindow *parent, Transaction *txn, Account **po
|
||||
lot_info->lot = postlot;
|
||||
lot_info->amount = xaccSplitGetValue (post_split);
|
||||
txn_lots = g_list_prepend (txn_lots, lot_info);
|
||||
*post_acct = xaccSplitGetAccount (post_split);
|
||||
*post_acct = apar_acct;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make sure not to override post_acct if it was set above from a lot split */
|
||||
if (!*post_acct)
|
||||
*post_acct = xaccSplitGetAccount (post_split);
|
||||
no_lot_post_splits = g_list_prepend (no_lot_post_splits, post_split);
|
||||
has_no_lot_apar_splits = TRUE;
|
||||
}
|
||||
apar_splits_no_lot = g_list_prepend (apar_splits_no_lot, post_split);
|
||||
}
|
||||
g_list_free (apar_splits);
|
||||
|
||||
g_list_free (post_splits);
|
||||
/* If no post_acct was selected from the postlots, fall back to the first apar split's
|
||||
* account if there is one. */
|
||||
if (!*post_acct && apar_splits_no_lot)
|
||||
*post_acct = xaccSplitGetAccount (apar_splits_no_lot->data);
|
||||
g_list_free (apar_splits_no_lot);
|
||||
|
||||
/* If the txn has both APAR splits linked to a business lot and
|
||||
* splits that are not, issue a warning some will be discarded.
|
||||
/* Abort if the txn has splits in more than one APAR account
|
||||
* GnuCash can only handle one post account per payment transaction.
|
||||
*/
|
||||
if (has_no_lot_apar_splits && gnc_list_length_cmp (txn_lots, 0))
|
||||
if (g_list_length (unique_apar_accts) > 1)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
char *split_str = g_strdup ("");
|
||||
for (iter = no_lot_post_splits; iter; iter = iter->next)
|
||||
|
||||
for (iter = unique_apar_accts; iter; iter = iter->next)
|
||||
{
|
||||
Split *post_split = iter->data;
|
||||
char *tmp_str = gen_split_desc (txn, post_split);
|
||||
char *tmp_str2 = g_strconcat(split_str, "• ", tmp_str, "\n", NULL);
|
||||
g_free (tmp_str);
|
||||
Account *acct = iter->data;
|
||||
char *acct_name = gnc_account_get_full_name (acct);
|
||||
char *tmp_str = g_strconcat(split_str, "• ", acct_name, "\n", NULL);
|
||||
g_free (acct_name);
|
||||
g_free (split_str);
|
||||
split_str = tmp_str2;
|
||||
split_str = tmp_str;
|
||||
}
|
||||
|
||||
dialog = gtk_message_dialog_new (parent,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_WARNING,
|
||||
GTK_BUTTONS_CANCEL,
|
||||
_("The transaction has at least one split in a business account that is not part of a business transaction.\n"
|
||||
"If you continue these splits will be ignored:\n\n%s\n"
|
||||
"Do you wish to continue and ignore these splits?"),
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
_("This transaction has splits in multiple business accounts:\n\n%s\n"
|
||||
"GnuCash can only handle transactions that post to a single account.\n\n"
|
||||
"Please correct this manually by editing the transaction directly and then try again."),
|
||||
split_str);
|
||||
gtk_dialog_add_buttons (GTK_DIALOG(dialog),
|
||||
_("Continue"), GTK_BUTTONS_OK, NULL);
|
||||
gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_BUTTONS_CANCEL);
|
||||
if (gtk_dialog_run (GTK_DIALOG(dialog)) != GTK_BUTTONS_OK)
|
||||
{
|
||||
*abort = TRUE;
|
||||
g_list_free_full (txn_lots, g_free);
|
||||
txn_lots = NULL;
|
||||
}
|
||||
gtk_dialog_run (GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
PINFO("Multiple asset accounts in splits of txn \"%s\"; cannot use this for assigning a payment.",
|
||||
xaccTransGetDescription(txn));
|
||||
g_free (split_str);
|
||||
}
|
||||
|
||||
g_list_free (no_lot_post_splits);
|
||||
*abort = TRUE;
|
||||
g_list_free_full (txn_lots, g_free);
|
||||
txn_lots = NULL;
|
||||
}
|
||||
|
||||
return txn_lots;
|
||||
}
|
||||
@ -1808,7 +1825,8 @@ PaymentWindow * gnc_ui_payment_new_with_txn (GtkWindow* parent, GncOwner *owner,
|
||||
GDate txn_date = xaccTransGetDatePostedGDate (txn);
|
||||
gnc_ui_payment_window_set_date(pw, &txn_date);
|
||||
}
|
||||
gnc_ui_payment_window_set_amount(pw, xaccSplitGetValue(payment_split));
|
||||
|
||||
gnc_ui_payment_window_set_amount(pw, xaccSplitConvertAmount (payment_split, post_acct));
|
||||
if (payment_split)
|
||||
gnc_ui_payment_window_set_xferaccount(pw, xaccSplitGetAccount(payment_split));
|
||||
return pw;
|
||||
|
@ -666,7 +666,7 @@
|
||||
|
||||
;; function to count the total number of splits to be iterated
|
||||
(define (gnc:accounts-count-splits accounts)
|
||||
(apply + (map length (map xaccAccountGetSplitList accounts))))
|
||||
(fold (lambda (a b) (+ b (length (xaccAccountGetSplitList a)))) 0 accounts))
|
||||
|
||||
;; Sums up any splits of a certain type affecting a set of accounts.
|
||||
;; the type is an alist '((str "match me") (cased #f) (regexp #f))
|
||||
@ -912,7 +912,7 @@
|
||||
(define (not-APAR? s)
|
||||
(not (xaccAccountIsAPARType (xaccAccountGetType (xaccSplitGetAccount s)))))
|
||||
;; analyse a payment transaction and return a 3-element vector:
|
||||
;; (vector invoices opposing-splits overpayment)
|
||||
;; (vector invoices overpayment opposing-splits)
|
||||
;;
|
||||
;; invoices: a list of (cons invoice inv-APAR-split)
|
||||
;; opposing-splits: a list of (list pmt-APAR-split partial-amount derived?)
|
||||
@ -920,44 +920,49 @@
|
||||
;; amount does not match the transaction amount
|
||||
;; overpayment: a number indicating overpayment amount
|
||||
(define (gnc:payment-txn->payment-info txn)
|
||||
(let lp ((splits (xaccTransGetSplitList txn))
|
||||
(invoices '())
|
||||
(overpayment 0)
|
||||
(opposing-splits '()))
|
||||
(match splits
|
||||
(() (vector invoices opposing-splits overpayment))
|
||||
(((? not-APAR? split) . rest)
|
||||
(lp rest invoices (+ overpayment (xaccSplitGetAmount split))
|
||||
opposing-splits))
|
||||
((split . rest)
|
||||
(let* ((lot (xaccSplitGetLot split))
|
||||
(lot-all-splits (gnc-lot-get-split-list lot)))
|
||||
(define split=? (cut equal? <> split))
|
||||
(match (gncInvoiceGetInvoiceFromLot lot)
|
||||
(() (let lp1 ((lot-splits lot-all-splits)
|
||||
(overpayment overpayment)
|
||||
(opposing-splits opposing-splits))
|
||||
(match lot-splits
|
||||
(() (lp rest invoices overpayment opposing-splits))
|
||||
(((? split=?) . tail) (lp1 tail overpayment opposing-splits))
|
||||
((s . tail)
|
||||
(let* ((lot-bal (gnc-lot-get-balance lot))
|
||||
(lot-bal (if (sign-equal? lot-bal (xaccSplitGetAmount s))
|
||||
0 lot-bal))
|
||||
(derived? (not (zero? lot-bal)))
|
||||
(partial-amount
|
||||
(fold
|
||||
(lambda (a b)
|
||||
(if (equal? s a) b (+ b (xaccSplitGetAmount a))))
|
||||
(- lot-bal) lot-all-splits)))
|
||||
(lp1 tail (+ overpayment partial-amount)
|
||||
(cons (list s partial-amount derived?)
|
||||
opposing-splits)))))))
|
||||
(inv
|
||||
(lp rest
|
||||
(cons (cons inv split) invoices)
|
||||
(+ overpayment (xaccSplitGetAmount split))
|
||||
opposing-splits))))))))
|
||||
(let* ((apar-split (xaccTransGetFirstAPARAcctSplit txn #t))
|
||||
(apar-acct (xaccSplitGetAccount apar-split)))
|
||||
(let lp ((splits (xaccTransGetSplitList txn))
|
||||
(invoices '())
|
||||
(overpayment 0)
|
||||
(opposing-splits '()))
|
||||
(match splits
|
||||
(() (vector invoices opposing-splits overpayment))
|
||||
(((? not-APAR? split) . rest)
|
||||
(gnc:msg "next " (gnc:strify split) " overpayment " (+ overpayment (xaccSplitConvertAmount split apar-acct)))
|
||||
(lp rest invoices (+ overpayment (xaccSplitConvertAmount split apar-acct))
|
||||
opposing-splits))
|
||||
((split . rest)
|
||||
(let* ((lot (xaccSplitGetLot split))
|
||||
(lot-all-splits (gnc-lot-get-split-list lot)))
|
||||
(define split=? (cut equal? <> split))
|
||||
(match (gncInvoiceGetInvoiceFromLot lot)
|
||||
(() (let lp1 ((lot-splits lot-all-splits)
|
||||
(overpayment overpayment)
|
||||
(opposing-splits opposing-splits))
|
||||
(match lot-splits
|
||||
(() (lp rest invoices overpayment opposing-splits))
|
||||
(((? split=?) . tail) (lp1 tail overpayment opposing-splits))
|
||||
((s . tail)
|
||||
(let* ((lot-bal (gnc-lot-get-balance lot))
|
||||
(lot-bal (if (sign-equal? lot-bal (xaccSplitConvertAmount s apar-acct))
|
||||
0 lot-bal))
|
||||
(derived? (not (zero? lot-bal)))
|
||||
(partial-amount
|
||||
(fold
|
||||
(lambda (a b)
|
||||
(if (equal? s a) b (+ b (xaccSplitConvertAmount a apar-acct))))
|
||||
(- lot-bal) lot-all-splits)))
|
||||
(gnc:msg "next " (gnc:strify s) " overpayment " (+ overpayment partial-amount))
|
||||
(lp1 tail (+ overpayment partial-amount)
|
||||
(cons (list s partial-amount derived?)
|
||||
opposing-splits)))))))
|
||||
(inv
|
||||
(gnc:msg "next " (gnc:strify split) " overpayment " (+ overpayment (xaccSplitConvertAmount split apar-acct)))
|
||||
(lp rest
|
||||
(cons (cons inv split) invoices)
|
||||
(+ overpayment (xaccSplitConvertAmount split apar-acct))
|
||||
opposing-splits)))))))))
|
||||
|
||||
;; create a stepped list, then add a date in the infinite future for
|
||||
;; the "current" bucket
|
||||
@ -971,7 +976,7 @@
|
||||
(define-public (gnc:owner-splits->aging-list splits num-buckets
|
||||
to-date date-type receivable?)
|
||||
(gnc:msg "processing " (qof-print-date to-date) " date-type " date-type
|
||||
"receivable? " receivable?)
|
||||
" receivable? " receivable?)
|
||||
(let ((bucket-dates (make-extended-interval-list to-date (- num-buckets 3)))
|
||||
(buckets (make-vector num-buckets 0)))
|
||||
(define (addbucket! idx amt)
|
||||
@ -989,10 +994,11 @@
|
||||
(xaccSplitGetParent (car splits))))
|
||||
(lot (gncInvoiceGetPostedLot invoice))
|
||||
(lot-splits (gnc-lot-get-split-list lot))
|
||||
(apar-acct (gncInvoiceGetPostedAcc invoice))
|
||||
(bal (fold
|
||||
(lambda (a b)
|
||||
(if (<= (xaccTransGetDate (xaccSplitGetParent a)) to-date)
|
||||
(+ (xaccSplitGetAmount a) b)
|
||||
(+ (xaccSplitConvertAmount a apar-acct) b)
|
||||
b))
|
||||
0 lot-splits))
|
||||
(bal (if receivable? bal (- bal)))
|
||||
|
@ -453,6 +453,10 @@
|
||||
44
|
||||
(gnc:accounts-count-splits (list expense income)))
|
||||
|
||||
(test-equal "gnc:accounts-count-splits null"
|
||||
0
|
||||
(gnc:accounts-count-splits '()))
|
||||
|
||||
(let ((account-balances (gnc:get-assoc-account-balances
|
||||
(list bank gbp-bank)
|
||||
(lambda (acct)
|
||||
|
@ -103,7 +103,7 @@
|
||||
* interest only loan), or large enough to fully repay both the interest and
|
||||
* principal during the term of the loan (a fully amoritized loan). Many loans
|
||||
* fall somewhere between, with payments that do not fully cover repayment of
|
||||
* both the principal and interst. These loans require a larger final payment
|
||||
* both the principal and interest. These loans require a larger final payment
|
||||
* (balloon) to complete their amortization. Payments may occur at the
|
||||
* beginning or end of a payment period. If you and your friend had agreed on
|
||||
* monthly repayment of the $800 loan at 12% NAR compounded monthly, twelve
|
||||
@ -220,7 +220,7 @@
|
||||
* compounding Frequency, CF, is simply the number of times per
|
||||
* year, the monies in the financial transaction are compounded. In
|
||||
* the U.S., monies are usually compounded daily on bank deposits,
|
||||
* and monthly on loans. Somtimes Long term deposits are compounded
|
||||
* and monthly on loans. Sometimes Long term deposits are compounded
|
||||
* quarterly or weekly.
|
||||
*
|
||||
* The Payment Frequency, PF, is simply how often during a year
|
||||
@ -596,7 +596,7 @@
|
||||
* T[n] = -i*n*(PV + C) - i*C*n(n+1)/2
|
||||
* T[n] = -i*n*(PV + (C*(n - 1)/2))
|
||||
*
|
||||
* Note: substituing for C = -PV/N, in the equations for PV[n], I[n],
|
||||
* Note: substituting for C = -PV/N, in the equations for PV[n], I[n],
|
||||
* P[n], and T[n] would give the following equations:
|
||||
*
|
||||
* PV[n] = PV*(1 - n/N)
|
||||
@ -739,12 +739,12 @@
|
||||
* 1. The payment *, interest paid, principal paid and remaining PV
|
||||
* for each payment period are computed and displayed. At the end of
|
||||
* each year a summary is computed and displayed and the total
|
||||
* interest paid is diplayed at the end.
|
||||
* interest paid is displayed at the end.
|
||||
*
|
||||
* 2. A summary is computed and displayed for each year. The
|
||||
* interest paid during the year is computed and displayed as well
|
||||
* as the remaining balance at years end. The total interest paid
|
||||
* is diplayed at the end.
|
||||
* is displayed at the end.
|
||||
*
|
||||
* 3. An amortization schedule is computed for a common method of
|
||||
* advanced payment of principal is computed and displayed. In this
|
||||
@ -1016,7 +1016,7 @@
|
||||
* Example 6: Balloon Payment
|
||||
* On long term loans, small changes in the periodic payments can generate
|
||||
* large changes in the future value. If the monthly payment in example 5 is
|
||||
* rounded down to $1125, how much addtional (balloon) payment will be due
|
||||
* rounded down to $1125, how much additional (balloon) payment will be due
|
||||
* with the final regular payment.
|
||||
* <>pmt=-1125
|
||||
* -1,125
|
||||
@ -2035,7 +2035,7 @@ Amortization_Schedule (amort_sched_ptr amortsched)
|
||||
else
|
||||
{
|
||||
/* remaining pv less than advanced principal payment reduce
|
||||
* advanced pricipal payment to remaining pv and set
|
||||
* advanced principal payment to remaining pv and set
|
||||
* remaining pv to fv */
|
||||
adv_pmt = -pv;
|
||||
pv = fv;
|
||||
@ -2138,7 +2138,7 @@ Amortization_Schedule (amort_sched_ptr amortsched)
|
||||
case 'o':
|
||||
/* Constant payment to principal use constant payment equal to
|
||||
* original pv divided by number of periods. constant payment to
|
||||
* pricipal could be amount specified by user. */
|
||||
* principal could be amount specified by user. */
|
||||
amortsched->schedule.first_yr =
|
||||
amortyr = (amort_sched_yr_ptr) calloc (1, sizeof (amort_sched_yr));
|
||||
amortsched->total_periods = n;
|
||||
|
@ -71,7 +71,7 @@ returned.
|
||||
|
||||
Simple/ad-hoc lazy evaluation works well when data dependencies are
|
||||
simple, but it breaks down when there are too many/circular
|
||||
relationships. It becomes all too easy to get trapped in inifinite
|
||||
relationships. It becomes all too easy to get trapped in infinite
|
||||
loops of corrections. The goal of moving to a formal constraint
|
||||
system is to introduce specific, well-defined sync points where
|
||||
constraint checking can be done, without incuring circular
|
||||
|
@ -756,10 +756,12 @@ gncOwnerCreatePaymentLotSecs (const GncOwner *owner, Transaction **preset_txn,
|
||||
QofBook *book;
|
||||
Split *split;
|
||||
const char *name;
|
||||
gnc_commodity *commodity;
|
||||
gnc_commodity *post_comm, *xfer_comm;
|
||||
Split *xfer_split = NULL;
|
||||
Transaction *txn = NULL;
|
||||
GNCLot *payment_lot;
|
||||
gnc_numeric xfer_amount = gnc_numeric_zero();
|
||||
gnc_numeric txn_value = gnc_numeric_zero();
|
||||
|
||||
/* Verify our arguments */
|
||||
if (!owner || !posted_acc || !xfer_acc) return NULL;
|
||||
@ -768,7 +770,9 @@ gncOwnerCreatePaymentLotSecs (const GncOwner *owner, Transaction **preset_txn,
|
||||
/* Compute the ancillary data */
|
||||
book = gnc_account_get_book (posted_acc);
|
||||
name = gncOwnerGetName (gncOwnerGetEndOwner ((GncOwner*)owner));
|
||||
commodity = gncOwnerGetCurrency (owner);
|
||||
post_comm = xaccAccountGetCommodity (posted_acc);
|
||||
xfer_comm = xaccAccountGetCommodity (xfer_acc);
|
||||
|
||||
// reverse = use_reversed_payment_amounts(owner);
|
||||
|
||||
if (preset_txn && *preset_txn)
|
||||
@ -776,110 +780,90 @@ gncOwnerCreatePaymentLotSecs (const GncOwner *owner, Transaction **preset_txn,
|
||||
|
||||
if (txn)
|
||||
{
|
||||
xaccTransSetDescription (txn, name ? name : "");
|
||||
int i = 0;
|
||||
|
||||
/* Pre-existing transaction was specified. We completely clear it,
|
||||
* except for the split in the transfer account, unless the
|
||||
* transaction can't be reused (wrong currency, wrong transfer account).
|
||||
* In that case, the transaction is simply removed and an new
|
||||
* one created. */
|
||||
|
||||
* except for a pre-existing transfer split. We're very conservative
|
||||
* in preserving that one as it may have been reconciled already. */
|
||||
xfer_split = xaccTransFindSplitByAccount(txn, xfer_acc);
|
||||
|
||||
if (xaccTransGetCurrency(txn) != gncOwnerGetCurrency (owner))
|
||||
xaccTransBeginEdit (txn);
|
||||
while (i < xaccTransCountSplits(txn))
|
||||
{
|
||||
PINFO("Uh oh, mismatching currency/commodity between selected transaction and owner. We fall back to manual creation of a new transaction.");
|
||||
xfer_split = NULL;
|
||||
}
|
||||
|
||||
if (!xfer_split)
|
||||
{
|
||||
PINFO("Huh? Asset account not found anymore. Fully deleting old txn and now creating a new one.");
|
||||
|
||||
xaccTransBeginEdit (txn);
|
||||
xaccTransDestroy (txn);
|
||||
xaccTransCommitEdit (txn);
|
||||
|
||||
txn = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
xaccTransBeginEdit (txn);
|
||||
while (i < xaccTransCountSplits(txn))
|
||||
{
|
||||
Split *split = xaccTransGetSplit (txn, i);
|
||||
if (split == xfer_split)
|
||||
{
|
||||
gnc_set_num_action (NULL, split, num, _("Payment"));
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
xaccSplitDestroy(split);
|
||||
}
|
||||
}
|
||||
/* Note: don't commit transaction now - that would insert an imbalance split.*/
|
||||
Split *split = xaccTransGetSplit (txn, i);
|
||||
if (split == xfer_split)
|
||||
++i;
|
||||
else
|
||||
xaccSplitDestroy(split);
|
||||
}
|
||||
/* Note: don't commit transaction now - that would insert an imbalance split.*/
|
||||
}
|
||||
|
||||
/* Create the transaction if we don't have one yet */
|
||||
if (!txn)
|
||||
else
|
||||
{
|
||||
txn = xaccMallocTransaction (book);
|
||||
xaccTransBeginEdit (txn);
|
||||
}
|
||||
|
||||
/* Complete transaction setup */
|
||||
xaccTransSetDescription (txn, name ? name : "");
|
||||
if (!gnc_commodity_equal(xaccTransGetCurrency (txn), post_comm) &&
|
||||
!gnc_commodity_equal (xaccTransGetCurrency (txn), xfer_comm))
|
||||
xaccTransSetCurrency (txn, xfer_comm);
|
||||
|
||||
/* With all commodities involved known, define split amounts and txn value.
|
||||
* - post amount (amount passed in as parameter) is always in post_acct commodity,
|
||||
* - xfer amount requires conversion if the xfer account has a different
|
||||
* commodity than the post account.
|
||||
* - txn value requires conversion if the post account has a different
|
||||
* commodity than the transaction */
|
||||
if (gnc_commodity_equal(post_comm, xfer_comm))
|
||||
xfer_amount = amount;
|
||||
else
|
||||
xfer_amount = gnc_numeric_mul (amount, exch, GNC_DENOM_AUTO,
|
||||
GNC_HOW_RND_ROUND_HALF_UP);
|
||||
|
||||
if (gnc_commodity_equal(post_comm, xaccTransGetCurrency (txn)))
|
||||
txn_value = amount;
|
||||
else
|
||||
txn_value = gnc_numeric_mul (amount, exch, GNC_DENOM_AUTO,
|
||||
GNC_HOW_RND_ROUND_HALF_UP);
|
||||
|
||||
/* Insert a split for the transfer account if we don't have one yet */
|
||||
if (!xfer_split)
|
||||
{
|
||||
|
||||
/* Set up the transaction */
|
||||
xaccTransSetDescription (txn, name ? name : "");
|
||||
/* set per book option */
|
||||
xaccTransSetCurrency (txn, commodity);
|
||||
|
||||
|
||||
/* The split for the transfer account */
|
||||
split = xaccMallocSplit (book);
|
||||
xaccSplitSetMemo (split, memo);
|
||||
xfer_split = xaccMallocSplit (book);
|
||||
xaccSplitSetMemo (xfer_split, memo);
|
||||
/* set per book option */
|
||||
gnc_set_num_action (NULL, split, num, _("Payment"));
|
||||
gnc_set_num_action (NULL, xfer_split, num, _("Payment"));
|
||||
xaccAccountBeginEdit (xfer_acc);
|
||||
xaccAccountInsertSplit (xfer_acc, split);
|
||||
xaccAccountInsertSplit (xfer_acc, xfer_split);
|
||||
xaccAccountCommitEdit (xfer_acc);
|
||||
xaccTransAppendSplit (txn, split);
|
||||
xaccTransAppendSplit (txn, xfer_split);
|
||||
|
||||
if (gnc_commodity_equal(xaccAccountGetCommodity(xfer_acc), commodity))
|
||||
{
|
||||
xaccSplitSetBaseValue (split, amount, commodity);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This will be a multi-currency transaction. The amount passed to this
|
||||
* function is in the owner commodity (also used by the post account).
|
||||
* For the xfer split we also need to value the payment in the xfer account's
|
||||
* commodity.
|
||||
* exch is from post account to xfer account so that can be used directly
|
||||
* to calculate the equivalent amount in the xfer account's commodity. */
|
||||
gnc_numeric xfer_amount = gnc_numeric_mul (amount, exch, GNC_DENOM_AUTO,
|
||||
GNC_HOW_RND_ROUND_HALF_UP);
|
||||
|
||||
xaccSplitSetAmount(split, xfer_amount); /* Payment in xfer account currency */
|
||||
xaccSplitSetValue(split, amount); /* Payment in transaction currency */
|
||||
}
|
||||
xaccSplitSetAmount(xfer_split, xfer_amount); /* Payment in xfer account currency */
|
||||
xaccSplitSetValue(xfer_split, txn_value); /* Payment in transaction currency */
|
||||
}
|
||||
/* For a pre-existing xfer split, let's check if the amount and value
|
||||
* have changed. If so, update them and unreconcile. */
|
||||
else if (!gnc_numeric_equal (xaccSplitGetAmount (xfer_split), xfer_amount) ||
|
||||
!gnc_numeric_equal (xaccSplitGetValue (xfer_split), txn_value))
|
||||
{
|
||||
xaccSplitSetAmount (xfer_split, xfer_amount);
|
||||
xaccSplitSetValue (xfer_split, txn_value);
|
||||
xaccSplitSetReconcile (xfer_split, NREC);
|
||||
}
|
||||
|
||||
/* Add a split in the post account */
|
||||
split = xaccMallocSplit (book);
|
||||
xaccSplitSetMemo (split, memo);
|
||||
/* set per book option */
|
||||
gnc_set_num_action (NULL, split, num, _("Payment"));
|
||||
xaccSplitSetAction (split, _("Payment"));
|
||||
xaccAccountBeginEdit (posted_acc);
|
||||
xaccAccountInsertSplit (posted_acc, split);
|
||||
xaccAccountCommitEdit (posted_acc);
|
||||
xaccTransAppendSplit (txn, split);
|
||||
xaccSplitSetBaseValue (split, gnc_numeric_neg (amount), commodity);
|
||||
xaccSplitSetAmount (split, gnc_numeric_neg (amount));
|
||||
xaccSplitSetValue (split, gnc_numeric_neg (txn_value));
|
||||
|
||||
/* Create a new lot for the payment */
|
||||
payment_lot = gnc_lot_new (book);
|
||||
@ -887,7 +871,7 @@ gncOwnerCreatePaymentLotSecs (const GncOwner *owner, Transaction **preset_txn,
|
||||
gnc_lot_add_split (payment_lot, split);
|
||||
|
||||
/* Mark the transaction as a payment */
|
||||
gnc_set_num_action (txn, NULL, num, _("Payment"));
|
||||
xaccTransSetNum (txn, num);
|
||||
xaccTransSetTxnType (txn, TXN_TYPE_PAYMENT);
|
||||
|
||||
/* Set date for transaction */
|
||||
|
@ -173,7 +173,7 @@ static void qof_instance_class_init(QofInstanceClass *klass)
|
||||
"Object Last Update",
|
||||
"A pointer to the last time this object was "
|
||||
"updated. This value is present for use by "
|
||||
"backends and shouldnot be written by other "
|
||||
"backends and shouldn't be written by other "
|
||||
"code.",
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user