From 7ed724a6c5b1d21de978b0688acff2d4afb7d4ea Mon Sep 17 00:00:00 2001 From: Janusz Dobrowolski Date: Mon, 27 May 2013 19:36:38 +0200 Subject: [PATCH 1/1] Customer Payment, Supplier Payment: payments can be done in any currency and properly allocated to invoices; exchange rate field removes (bank arte calculated automatically) --- js/payalloc.js | 2 +- purchasing/includes/db/supp_payment_db.inc | 78 ++++++++++++++++++ purchasing/supplier_payment.php | 62 +++++++------- sales/customer_payments.php | 95 ++++++++++++---------- sales/includes/db/payment_db.inc | 59 +++++++++----- 5 files changed, 200 insertions(+), 96 deletions(-) diff --git a/js/payalloc.js b/js/payalloc.js index 1bd818c1..a711e603 100644 --- a/js/payalloc.js +++ b/js/payalloc.js @@ -56,7 +56,7 @@ function allocate_none(doc) { var allocations = { '.amount': function(e) { - if(e.name == 'allocated_amount') + if(e.name == 'allocated_amount' || e.name == 'bank_amount') { e.onblur = function() { var dec = this.getAttribute("dec"); diff --git a/purchasing/includes/db/supp_payment_db.inc b/purchasing/includes/db/supp_payment_db.inc index 9628ac76..50ecfe2d 100644 --- a/purchasing/includes/db/supp_payment_db.inc +++ b/purchasing/includes/db/supp_payment_db.inc @@ -9,6 +9,84 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License here . ***********************************************************************/ +function write_supp_payment($trans_no, $supplier_id, $bank_account, + $date_, $ref, $supp_amount, $supp_discount, $memo_, $bank_charge=0, $bank_amount=0) +{ + global $Refs; + + begin_transaction(); + $args = func_get_args(); while (count($args) < 10) $args[] = 0; + $args = (object)array_combine(array('trans_no', 'supplier_id', 'bank_account', 'date_', + 'ref', 'bank_amount', 'supp_amount', 'supp_discount', 'memo_', 'bank_charge'), $args); + $args->trans_no = 0; + hook_db_prewrite( $args, ST_SUPPAYMENT); + + if ($trans_no != 0) { + delete_comments(ST_SUPPAYMENT, $trans_no); + void_bank_trans(ST_SUPPAYMENT, $trans_no, true); + void_gl_trans(ST_SUPPAYMENT, $trans_no, true); + void_cust_allocations(ST_SUPPAYMENT, $trans_no, $date_); + } + + /* Create a supp_trans entry for the supplier payment */ + $payment_id = write_supp_trans(ST_SUPPAYMENT, 0, $supplier_id, $date_, $date_, + $ref, "", -$supp_amount, 0, -$supp_discount); + + // Now debit creditors account with payment + discount + + $total = 0; + $supplier_accounts = get_supplier_accounts($supplier_id); + $total += add_gl_trans_supplier(ST_SUPPAYMENT, $payment_id, $date_, $supplier_accounts["payable_account"], 0, 0, + $supp_amount + $supp_discount, $supplier_id); + + // Now credit discount received account with discounts + if ($supp_discount != 0) + { + $total += add_gl_trans_supplier(ST_SUPPAYMENT, $payment_id, $date_, $supplier_accounts["payment_discount_account"], 0, 0, + -$supp_discount, $supplier_id); + } + + $bank = get_bank_account($bank_account); + + if ($bank_charge != 0) + { + $charge_act = get_company_pref('bank_charge_act'); + $total += add_gl_trans(ST_SUPPAYMENT, $payment_id, $date_, $charge_act, 0, 0, '', + $bank_charge, $bank['bank_curr_code']); + } + + $total += add_gl_trans(ST_SUPPAYMENT, $payment_id, $date_, $bank['account_code'], 0, 0, '', + -($bank_amount + $bank_charge), $bank['bank_curr_code']); + + /*Post a balance post if $total != 0 due to variance in AP and bank posted values*/ + if ($total != 0) + { + $variance_act = get_company_pref('exchange_diff_act'); + add_gl_trans(ST_SUPPAYMENT, $payment_id, $date_, $variance_act, 0, 0, '', + -$total, null, PT_SUPPLIER, $supplier_id); + } + + /*now enter the bank_trans entry */ + add_bank_trans(ST_SUPPAYMENT, $payment_id, $bank_account, $ref, + $date_, -($bank_amount + $bank_charge), PT_SUPPLIER, $supplier_id); + + add_comments(ST_SUPPAYMENT, $payment_id, $date_, $memo_); + + $Refs->save(ST_SUPPAYMENT, $payment_id, $ref); + + $args->trans_no = $payment_id; + hook_db_postwrite($args, ST_SUPPAYMENT); + + commit_transaction(); + + return $payment_id; +} + +//------------------------------------------------------------------------------------------------ +/* + This is legacy code, leaved here to provide compatibility for 2.3 extension modules. + Will be removed in 2.4 due to design issues. +*/ function add_supp_payment($supplier_id, $date_, $bank_account, $amount, $discount, $ref, $memo_, $rate=0, $charge=0) { diff --git a/purchasing/supplier_payment.php b/purchasing/supplier_payment.php index dd2a09d4..6d467deb 100644 --- a/purchasing/supplier_payment.php +++ b/purchasing/supplier_payment.php @@ -143,12 +143,12 @@ function check_inputs() } } - if (isset($_POST['_ex_rate']) && !check_num('_ex_rate', 0.000001)) - { - display_error(_("The exchange rate must be numeric and greater than zero.")); - set_focus('_ex_rate'); - return false; - } +// if (isset($_POST['_ex_rate']) && !check_num('_ex_rate', 0.000001)) +// { +// display_error(_("The exchange rate must be numeric and greater than zero.")); +// set_focus('_ex_rate'); +// return false; +// } if ($_POST['discount'] == "") { @@ -170,6 +170,14 @@ function check_inputs() return false; } + if (isset($_POST['bank_amount']) && input_num('bank_amount')<=0) + { + display_error(_("The entered bank amount is zero or negative.")); + set_focus('bank_amount'); + return false; + } + + if (!is_date($_POST['DatePaid'])) { display_error(_("The entered date is invalid.")); @@ -223,23 +231,24 @@ function handle_add_payment() $supp_currency = get_supplier_currency($_POST['supplier_id']); $bank_currency = get_bank_account_currency($_POST['bank_account']); $comp_currency = get_company_currency(); + if ($comp_currency != $bank_currency && $bank_currency != $supp_currency) $rate = 0; else { $rate = input_num('_ex_rate'); - $supplier_amount = input_num('allocated_amount'); + $supplier_amount = input_num('bank_amount'); if($supplier_amount) $rate = input_num('amount')/$supplier_amount; } - $payment_id = add_supp_payment($_POST['supplier_id'], $_POST['DatePaid'], - $_POST['bank_account'], input_num('amount'), input_num('discount'), - $_POST['ref'], $_POST['memo_'], $rate, input_num('charge')); + $payment_id = write_supp_payment(0, $_POST['supplier_id'], $_POST['bank_account'], + $_POST['DatePaid'], $_POST['ref'], input_num('amount'), input_num('discount'), $_POST['memo_'], + input_num('charge'), input_num('bank_amount', get_post('amount'))); new_doc_date($_POST['DatePaid']); $_SESSION['alloc']->trans_no = $payment_id; $_SESSION['alloc']->write(); - //unset($_POST['supplier_id']); + unset($_POST['bank_account']); unset($_POST['DatePaid']); unset($_POST['currency']); @@ -281,12 +290,9 @@ start_form(); } set_global_supplier($_POST['supplier_id']); - - if (!list_updated('bank_account')) - $_POST['bank_account'] = get_default_supplier_bank_account($_POST['supplier_id']); - + bank_accounts_list_row(_("From Bank Account:"), 'bank_account', null, true); - + bank_balance_row($_POST['bank_account']); table_section(2); @@ -301,30 +307,24 @@ start_form(); $bank_currency = get_bank_account_currency($_POST['bank_account']); if ($bank_currency != $supplier_currency) { - amount_row("Supplier Amount:", 'allocated_amount', null, '', $supplier_currency, 2); + amount_row("Bank Amount:", 'bank_amount', null, '', $bank_currency, 2); } - amount_row(_("Bank Charge:"), 'charge'); + amount_row(_("Bank Charge:"), 'charge', null, '', $bank_currency); - end_outer_table(1); // outer table + end_outer_table(1); - if ($bank_currency == $supplier_currency) { - div_start('alloc_tbl'); - show_allocatable(false); - div_end(); - } + div_start('alloc_tbl'); + display_heading(sprintf(_("Accounts Payable settled in %s:"), $supplier_currency)); + show_allocatable(false); + div_end(); start_table(TABLESTYLE, "width=60%"); - amount_row(_("Amount of Discount:"), 'discount'); - amount_row(_("Amount of Payment:"), 'amount'); + amount_row(_("Amount of Discount:"), 'discount', null, '', $supplier_currency); + amount_row(_("Amount of Payment:"), 'amount', null, '', $supplier_currency); textarea_row(_("Memo:"), 'memo_', null, 22, 4); end_table(1); - - if ($bank_currency != $supplier_currency) - { - display_note(_("The amount and discount are in the bank account's currency."), 0, 1); - } submit_center('ProcessSuppPayment',_("Enter Payment"), true, '', 'default'); diff --git a/sales/customer_payments.php b/sales/customer_payments.php index d0a0ea8b..f983f82b 100644 --- a/sales/customer_payments.php +++ b/sales/customer_payments.php @@ -193,12 +193,12 @@ function can_process() } } - if (isset($_POST['_ex_rate']) && !check_num('_ex_rate', 0.000001)) - { - display_error(_("The exchange rate must be numeric and greater than zero.")); - set_focus('_ex_rate'); - return false; - } +// if (isset($_POST['_ex_rate']) && !check_num('_ex_rate', 0.000001)) +// { +// display_error(_("The exchange rate must be numeric and greater than zero.")); +// set_focus('_ex_rate'); +// return false; +// } if ($_POST['discount'] == "") { @@ -213,10 +213,18 @@ function can_process() //if ((input_num('amount') - input_num('discount') <= 0)) { if (input_num('amount') <= 0) { - display_error(_("The balance of the amount and discout is zero or negative. Please enter valid amounts.")); + display_error(_("The balance of the amount and discount is zero or negative. Please enter valid amounts.")); set_focus('discount'); return false; } + + if (isset($_POST['bank_amount']) && input_num('bank_amount')<=0) + { + display_error(_("The entered payment amount is zero or negative.")); + set_focus('bank_amount'); + return false; + } + if (!db_has_currency_rates(get_customer_currency($_POST['customer_id']), $_POST['DateBanked'], true)) return false; @@ -234,9 +242,9 @@ if (isset($_POST['_customer_id_button'])) { // unset($_POST['branch_id']); $Ajax->activate('BranchID'); } -if (isset($_POST['_DateBanked_changed'])) { - $Ajax->activate('_ex_rate'); -} +//if (isset($_POST['_DateBanked_changed'])) { +// $Ajax->activate('_ex_rate'); +//} //---------------------------------------------------------------------------------------------- @@ -245,10 +253,10 @@ if (get_post('AddPaymentItem') && can_process()) { $cust_currency = get_customer_currency($_POST['customer_id']); $bank_currency = get_bank_account_currency($_POST['bank_account']); $comp_currency = get_company_currency(); - if ($comp_currency != $bank_currency && $bank_currency != $cust_currency) - $rate = 0; - else - $rate = input_num('_ex_rate'); +// if ($comp_currency != $bank_currency && $bank_currency != $cust_currency) +// $rate = 0; +// else +// $rate = input_num('_ex_rate'); new_doc_date($_POST['DateBanked']); @@ -256,14 +264,12 @@ if (get_post('AddPaymentItem') && can_process()) { //Chaitanya : 13-OCT-2011 - To support Edit feature $payment_no = write_customer_payment($_SESSION['alloc']->trans_no, $_POST['customer_id'], $_POST['BranchID'], $_POST['bank_account'], $_POST['DateBanked'], $_POST['ref'], - input_num('amount'), input_num('discount'), $_POST['memo_'], $rate, input_num('charge')); + input_num('amount'), input_num('discount'), $_POST['memo_'], 0, input_num('charge'), input_num('bank_amount', get_post('amount'))); $_SESSION['alloc']->trans_no = $payment_no; $_SESSION['alloc']->write(); unset($_SESSION['alloc']); - //Chaitanya : 13-OCT-2011 - To support Edit feature - //meta_forward($_SERVER['PHP_SELF'], "AddedID=$payment_no"); meta_forward($_SERVER['PHP_SELF'], $new_pmt ? "AddedID=$payment_no" : "UpdatedID=$payment_no"); } @@ -328,8 +334,11 @@ start_form(); hidden('old_ref', $old_ref); start_outer_table(TABLESTYLE2, "width=60%", 5); + table_section(1); + bank_accounts_list_row(_("Into Bank Account:"), 'bank_account', null, true); + if ($new) customer_list_row(_("From Customer:"), 'customer_id', null, false, true); else { @@ -337,18 +346,18 @@ start_form(); hidden('customer_id', $_POST['customer_id']); } - if (list_updated('customer_id') || ($new && list_updated('bank_account'))) { - $_SESSION['alloc']->read(); - $_POST['memo_'] = $_POST['amount'] = $_POST['discount'] = ''; - $Ajax->activate('alloc_tbl'); - } - if (db_customer_has_branches($_POST['customer_id'])) { customer_branches_list_row(_("Branch:"), $_POST['customer_id'], 'BranchID', null, false, true, true); } else { hidden('BranchID', ANY_NUMERIC); } + if (list_updated('customer_id') || ($new && list_updated('bank_account'))) { + $_SESSION['alloc']->read(); + $_POST['memo_'] = $_POST['amount'] = $_POST['discount'] = ''; + $Ajax->activate('alloc_tbl'); + } + read_customer_data(); set_global_customer($_POST['customer_id']); @@ -357,52 +366,48 @@ start_form(); $display_discount_percent = percent_format($_POST['pymt_discount']*100) . "%"; table_section(2); - if (!list_updated('bank_account')) - $_POST['bank_account'] = get_default_customer_bank_account($_POST['customer_id']); - //Chaitanya : 13-OCT-2011 - Is AJAX call really needed ??? - //bank_accounts_list_row(_("Into Bank Account:"), 'bank_account', null, true); - bank_accounts_list_row(_("Into Bank Account:"), 'bank_account', null, false); + date_row(_("Date of Deposit:"), 'DateBanked', '', true, 0, 0, 0, null, true); text_row(_("Reference:"), 'ref', null, 20, 40); table_section(3); - date_row(_("Date of Deposit:"), 'DateBanked', '', true, 0, 0, 0, null, true); - $comp_currency = get_company_currency(); $cust_currency = get_customer_currency($_POST['customer_id']); $bank_currency = get_bank_account_currency($_POST['bank_account']); - if ($cust_currency != $bank_currency) { - exchange_rate_display($bank_currency, $cust_currency, $_POST['DateBanked'], ($bank_currency == $comp_currency)); +// if ($cust_currency != $bank_currency) { +// exchange_rate_display($bank_currency, $cust_currency, $_POST['DateBanked'], ($bank_currency == $comp_currency)); +// } + + if ($cust_currency != $bank_currency) + { + amount_row(_("Payment Amount:"), 'bank_amount', null, '', $bank_currency); + // aproximate value in customer currency: +// label_row(_("Current value:"), price_format(input_num('bank_amount')*$rate).' '.$cust_currency); } - amount_row(_("Bank Charge:"), 'charge'); + amount_row(_("Bank Charge:"), 'charge', null, '', $bank_currency); end_outer_table(1); - if ($cust_currency == $bank_currency) { - div_start('alloc_tbl'); - show_allocatable(false); - div_end(); - } + display_heading(sprintf(_("Accounts Receivable settled in %s:"), $cust_currency)); + div_start('alloc_tbl'); + show_allocatable(false); + div_end(); start_table(TABLESTYLE, "width=60%"); label_row(_("Customer prompt payment discount :"), $display_discount_percent); - amount_row(_("Amount of Discount:"), 'discount'); - amount_row(_("Amount:"), 'amount'); + amount_row(_("Amount of Discount:"), 'discount', null, '', $cust_currency); + + amount_row(_("Amount:"), 'amount', null, '', $cust_currency); textarea_row(_("Memo:"), 'memo_', null, 22, 4); end_table(1); - if ($cust_currency != $bank_currency) - display_note(_("Amount and discount are in customer's currency.")); - - br(); - if ($new) submit_center('AddPaymentItem', _("Update Payment"), true, '', 'default'); else diff --git a/sales/includes/db/payment_db.inc b/sales/includes/db/payment_db.inc index abee06b6..9e0e4b16 100644 --- a/sales/includes/db/payment_db.inc +++ b/sales/includes/db/payment_db.inc @@ -11,22 +11,28 @@ ***********************************************************************/ /* Write/update customer payment. + + Warning: $rate is leaved here for extensions compatibility reasons, will be removed in 2.4 + since 2.3.17 is not used: use $bank_amount instead. + + $amount - in customer currency (ex. discount) + $discount - in customer currency + $bank_amount - in bank currency (before charge) + $charge - in bank currency */ function write_customer_payment($trans_no, $customer_id, $branch_id, $bank_account, - $date_, $ref, $amount, $discount, $memo_, $rate=0, $charge=0) + $date_, $ref, $amount, $discount, $memo_, $rate=0, $charge=0, $bank_amount=0) { global $Refs; begin_transaction(); - $args = func_get_args(); while (count($args) < 11) $args[] = 0; + $args = func_get_args(); while (count($args) < 12) $args[] = 0; $args = (object)array_combine(array('trans_no', 'customer_id', 'branch_id', 'bank_account', - 'date_', 'ref', 'amount', 'discount', 'memo_','rate','charge'), $args); + 'date_', 'ref', 'amount', 'discount', 'memo_','rate','charge', 'bank_amount'), $args); hook_db_prewrite($args, ST_CUSTPAYMENT); $company_record = get_company_prefs(); - - //Chaitanya : 13_OCT_2011 : Voiding Tasks first - //Reason : After modifying the customer trans, it was getting voided later + if ($trans_no != 0) { delete_comments(ST_CUSTPAYMENT, $trans_no); void_bank_trans(ST_CUSTPAYMENT, $trans_no, true); @@ -34,16 +40,26 @@ function write_customer_payment($trans_no, $customer_id, $branch_id, $bank_accou void_cust_allocations(ST_CUSTPAYMENT, $trans_no, $date_); } + $bank = get_bank_account($bank_account); + if (!$rate) + $rate = get_exchange_rate_from_to(get_customer_currency($customer_id), + $bank['bank_curr_code'], $date_ ); + if (!$bank_amount) // backward compatibility workaround + { + + $bank_amount = $amount/$rate; + } + $payment_no = write_customer_trans(ST_CUSTPAYMENT, $trans_no, $customer_id, $branch_id, $date_, $ref, $amount, $discount, 0, 0, 0, 0, 0, 0, "", 0, $rate); - + $bank_gl_account = get_bank_gl_account($bank_account); $total = 0; + /* Bank account entry first */ - $total += add_gl_trans_customer(ST_CUSTPAYMENT, $payment_no, $date_, - $bank_gl_account, 0, 0, $amount - $charge, $customer_id, - "Cannot insert a GL transaction for the bank account debit", $rate); + $total += add_gl_trans(ST_CUSTPAYMENT, $payment_no, $date_, + $bank_gl_account, 0, 0, '', ($bank_amount - $charge), $bank['bank_curr_code'], PT_CUSTOMER, $customer_id); if ($branch_id != ANY_NUMERIC) { @@ -61,29 +77,34 @@ function write_customer_payment($trans_no, $customer_id, $branch_id, $bank_accou /* Now Credit Debtors account with receipts + discounts */ $total += add_gl_trans_customer(ST_CUSTPAYMENT, $payment_no, $date_, $debtors_account, 0, 0, -($discount + $amount), $customer_id, - "Cannot insert a GL transaction for the debtors account credit", $rate); + "Cannot insert a GL transaction for the debtors account credit"); } if ($discount != 0) { /* Now Debit discount account with discounts allowed*/ $total += add_gl_trans_customer(ST_CUSTPAYMENT, $payment_no, $date_, $discount_account, 0, 0, $discount, $customer_id, - "Cannot insert a GL transaction for the payment discount debit", $rate); + "Cannot insert a GL transaction for the payment discount debit"); } if ($charge != 0) { /* Now Debit bank charge account with charges */ $charge_act = get_company_pref('bank_charge_act'); - $total += add_gl_trans_customer(ST_CUSTPAYMENT, $payment_no, $date_, - $charge_act, 0, 0, $charge, $customer_id, - "Cannot insert a GL transaction for the payment bank charge debit", $rate); + $total += add_gl_trans(ST_CUSTPAYMENT, $payment_no, $date_, $charge_act, 0, 0, '', + $charge, $bank['bank_curr_code'], PT_CUSTOMER, $customer_id); + } + + + /*Post a balance post if $total != 0 due to variance in AR and bank posted values*/ + if ($total != 0) + { + $variance_act = get_company_pref('exchange_diff_act'); + add_gl_trans(ST_CUSTPAYMENT, $payment_no, $date_, $variance_act, 0, 0, '', + -$total, null, PT_CUSTOMER, $customer_id); } - /*Post a balance post if $total != 0 */ - add_gl_balance(ST_CUSTPAYMENT, $payment_no, $date_, -$total, PT_CUSTOMER, $customer_id); /*now enter the bank_trans entry */ add_bank_trans(ST_CUSTPAYMENT, $payment_no, $bank_account, $ref, - $date_, $amount - $charge, PT_CUSTOMER, $customer_id, - get_customer_currency($customer_id), "", $rate); + $date_, $bank_amount - $charge, PT_CUSTOMER, $customer_id); add_comments(ST_CUSTPAYMENT, $payment_no, $date_, $memo_); -- 2.30.2