Editable unallocated amount in pe (#13130)

* editable unallocated amount in payment entry to handle multi currency

* set unallocated amount on server side

* some minor fixes

* Fixes in territory patch

* removed print

* minor fixes
This commit is contained in:
Nabin Hait 2018-03-01 13:14:14 +05:30 committed by GitHub
parent 4badb45ee5
commit c10bbd6aa7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 167 additions and 60 deletions

View File

@ -145,13 +145,13 @@ frappe.ui.form.on('Payment Entry', {
frm.doc.paid_amount : frm.doc.received_amount;
frm.toggle_display("write_off_difference_amount", (frm.doc.difference_amount && frm.doc.party &&
(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) &&
(frm.doc.total_allocated_amount > party_amount)));
frm.toggle_display("set_exchange_gain_loss",
(frm.doc.paid_amount && frm.doc.received_amount && frm.doc.difference_amount &&
(frm.doc.paid_from_account_currency != company_currency ||
frm.doc.paid_to_account_currency != company_currency)));
((frm.doc.paid_from_account_currency != company_currency ||
frm.doc.paid_to_account_currency != company_currency) &&
frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency)));
frm.refresh_fields();
},
@ -300,7 +300,15 @@ frappe.ui.form.on('Payment Entry', {
if(frm.doc.payment_type == "Pay") {
frm.events.get_outstanding_documents(frm);
} else if (frm.doc.payment_type == "Receive") {
frm.events.received_amount(frm);
if(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
if(frm.doc.source_exchange_rate) {
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
}
frm.set_value("received_amount", frm.doc.paid_amount);
} else {
frm.events.received_amount(frm);
}
}
}
);
@ -317,26 +325,31 @@ frappe.ui.form.on('Payment Entry', {
},
callback: function(r, rt) {
if(r.message) {
frm.set_value(currency_field, r.message['account_currency']);
frm.set_value(balance_field, r.message['account_balance']);
frappe.run_serially([
() => frm.set_value(currency_field, r.message['account_currency']),
() => {
frm.set_value(balance_field, r.message['account_balance']);
if(frm.doc.payment_type=="Receive" && currency_field=="paid_to_account_currency") {
frm.toggle_reqd(["reference_no", "reference_date"],
(r.message['account_type'] == "Bank" ? 1 : 0));
if(!frm.doc.received_amount && frm.doc.paid_amount)
frm.events.paid_amount(frm);
} else if(frm.doc.payment_type=="Pay" && currency_field=="paid_from_account_currency") {
frm.toggle_reqd(["reference_no", "reference_date"],
(r.message['account_type'] == "Bank" ? 1 : 0));
if(frm.doc.payment_type=="Receive" && currency_field=="paid_to_account_currency") {
frm.toggle_reqd(["reference_no", "reference_date"],
(r.message['account_type'] == "Bank" ? 1 : 0));
if(!frm.doc.received_amount && frm.doc.paid_amount)
frm.events.paid_amount(frm);
} else if(frm.doc.payment_type=="Pay" && currency_field=="paid_from_account_currency") {
frm.toggle_reqd(["reference_no", "reference_date"],
(r.message['account_type'] == "Bank" ? 1 : 0));
if(!frm.doc.paid_amount && frm.doc.received_amount)
frm.events.received_amount(frm);
}
if(!frm.doc.paid_amount && frm.doc.received_amount)
frm.events.received_amount(frm);
}
},
() => {
if(callback_function) callback_function(frm);
if(callback_function) callback_function(frm);
frm.events.hide_unhide_fields(frm);
frm.events.set_dynamic_labels(frm);
frm.events.hide_unhide_fields(frm);
frm.events.set_dynamic_labels(frm);
}
]);
}
}
});
@ -405,7 +418,7 @@ frappe.ui.form.on('Payment Entry', {
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
}
frm.events.set_difference_amount(frm);
frm.events.set_unallocated_amount(frm);
}
// Make read only if Accounts Settings doesn't allow stale rates
@ -425,7 +438,7 @@ frappe.ui.form.on('Payment Entry', {
frm.set_value("base_paid_amount", frm.doc.base_received_amount);
}
frm.events.set_difference_amount(frm);
frm.events.set_unallocated_amount(frm);
}
frm.set_paid_amount_based_on_received_amount = false;
@ -456,7 +469,7 @@ frappe.ui.form.on('Payment Entry', {
if(frm.doc.payment_type == "Pay")
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
else
frm.events.set_difference_amount(frm);
frm.events.set_unallocated_amount(frm);
frm.set_paid_amount_based_on_received_amount = false;
},
@ -476,7 +489,7 @@ frappe.ui.form.on('Payment Entry', {
if(frm.doc.payment_type == "Receive")
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount);
else
frm.events.set_difference_amount(frm);
frm.events.set_unallocated_amount(frm);
},
get_outstanding_documents: function(frm) {
@ -565,8 +578,11 @@ frappe.ui.form.on('Payment Entry', {
if(frm.doc.references.length == 0){
frm.events.get_outstanding_documents(frm);
}
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
if(frm.doc.payment_type == 'Internal Transfer') {
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount);
} else {
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
}
},
allocate_party_amount_against_ref_docs: function(frm, paid_amount) {
@ -651,10 +667,10 @@ frappe.ui.form.on('Payment Entry', {
frm.set_value("total_allocated_amount", Math.abs(total_allocated_amount));
frm.set_value("base_total_allocated_amount", Math.abs(base_total_allocated_amount));
frm.events.set_difference_amount(frm);
frm.events.set_unallocated_amount(frm);
},
set_difference_amount: function(frm) {
set_unallocated_amount: function(frm) {
var unallocated_amount = 0;
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
function(d) { return flt(d.amount) }));
@ -662,17 +678,34 @@ frappe.ui.form.on('Payment Entry', {
if(frm.doc.party) {
var party_amount = frm.doc.payment_type=="Receive" ?
frm.doc.paid_amount : frm.doc.received_amount;
var company_currency = frm.doc.company? frappe.get_doc(":Company", frm.doc.company).default_currency: "";
if(frm.doc.total_allocated_amount < party_amount) {
if(frm.doc.payment_type == "Receive") {
if (frm.doc.party_account_currency == company_currency) {
if(frm.doc.payment_type == "Receive" && frm.doc.total_allocated_amount <= party_amount + total_deductions) {
unallocated_amount = party_amount - (frm.doc.total_allocated_amount - total_deductions);
} else {
} else if (frm.doc.payment_type == "Pay" && frm.doc.total_allocated_amount <= party_amount - total_deductions) {
unallocated_amount = party_amount - (frm.doc.total_allocated_amount + total_deductions);
}
} else {
if(frm.doc.payment_type == "Receive"
&& frm.doc.base_total_allocated_amount <= frm.doc.base_received_amount + total_deductions
&& frm.doc.total_allocated_amount < frm.doc.paid_amount) {
unallocated_amount = (frm.doc.base_received_amount + total_deductions
- frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate;
} else if (frm.doc.payment_type == "Pay"
&& frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions
&& frm.doc.total_allocated_amount < frm.doc.received_amount) {
unallocated_amount = (frm.doc.base_paid_amount - (total_deductions
+ frm.doc.base_total_allocated_amount)) / frm.doc.target_exchange_rate;
}
}
}
frm.set_value("unallocated_amount", unallocated_amount);
frm.trigger("set_difference_amount");
},
set_difference_amount: function(frm) {
var difference_amount = 0;
var base_unallocated_amount = flt(frm.doc.unallocated_amount) *
(frm.doc.payment_type=="Receive" ? frm.doc.source_exchange_rate : frm.doc.target_exchange_rate);
@ -687,11 +720,18 @@ frappe.ui.form.on('Payment Entry', {
difference_amount = flt(frm.doc.base_paid_amount) - flt(frm.doc.base_received_amount);
}
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
function(d) { return flt(d.amount) }));
frm.set_value("difference_amount", difference_amount - total_deductions);
frm.events.hide_unhide_fields(frm);
},
unallocated_amount: function(frm) {
frm.trigger("set_difference_amount");
},
check_mandatory_to_fetch: function(frm) {
$.each(["Company", "Party Type", "Party", "payment_type"], function(i, field) {
if(!frm.doc[frappe.model.scrub(field)]) {
@ -771,7 +811,7 @@ frappe.ui.form.on('Payment Entry', {
row.amount = flt(row.amount) + flt(frm.doc.difference_amount);
refresh_field("deductions");
frm.events.set_difference_amount(frm);
frm.events.set_unallocated_amount(frm);
}
}
})
@ -818,10 +858,10 @@ frappe.ui.form.on('Payment Entry Reference', {
frappe.ui.form.on('Payment Entry Deduction', {
amount: function(frm) {
frm.events.set_difference_amount(frm);
frm.events.set_unallocated_amount(frm);
},
deductions_remove: function(frm) {
frm.events.set_difference_amount(frm);
frm.events.set_unallocated_amount(frm);
}
})

View File

@ -40,6 +40,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -71,6 +72,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 1,
"translatable": 0,
"unique": 0
},
{
@ -102,6 +104,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -131,6 +134,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -162,6 +166,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -193,6 +198,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -224,6 +230,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -255,6 +262,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -288,6 +296,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -320,6 +329,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -349,6 +359,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -381,6 +392,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -411,6 +423,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -442,6 +455,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -474,6 +488,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -506,6 +521,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -538,6 +554,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -567,6 +584,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -599,6 +617,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -631,6 +650,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -663,6 +683,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -695,6 +716,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -727,6 +749,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -758,6 +781,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -790,6 +814,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -819,6 +844,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -851,6 +877,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -882,6 +909,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -914,6 +942,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -946,6 +975,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -978,6 +1008,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1010,6 +1041,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1041,6 +1073,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1072,6 +1105,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1104,6 +1138,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1134,6 +1169,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1163,6 +1199,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1188,12 +1225,13 @@
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1226,6 +1264,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1257,6 +1296,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1289,6 +1329,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1320,6 +1361,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1350,6 +1392,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1381,6 +1424,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1410,6 +1454,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1441,6 +1486,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1472,6 +1518,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1504,6 +1551,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1536,6 +1584,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1566,6 +1615,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1595,6 +1645,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1626,6 +1677,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1657,6 +1709,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1687,6 +1740,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1718,6 +1772,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1748,6 +1803,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1778,6 +1834,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
@ -1791,7 +1848,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-08-31 11:20:37.578469",
"modified": "2018-02-19 16:58:23.899015",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",

View File

@ -286,17 +286,30 @@ class PaymentEntry(AccountsController):
self.base_total_allocated_amount = abs(base_total_allocated_amount)
def set_unallocated_amount(self):
self.unallocated_amount = 0;
self.unallocated_amount = 0
if self.party:
party_amount = self.paid_amount if self.payment_type=="Receive" else self.received_amount
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
if self.total_allocated_amount < party_amount:
if self.payment_type == "Receive":
self.unallocated_amount = party_amount - (self.total_allocated_amount - total_deductions)
else:
self.unallocated_amount = party_amount - (self.total_allocated_amount + total_deductions)
if self.party_account_currency == self.company_currency:
if self.payment_type == "Receive" \
and self.total_allocated_amount <= self.paid_amount + total_deductions:
self.unallocated_amount = self.paid_amount - \
(self.total_allocated_amount - total_deductions)
elif self.payment_type == "Pay" \
and self.total_allocated_amount <= self.received_amount - total_deductions:
self.unallocated_amount = self.received_amount - \
(self.total_allocated_amount + total_deductions)
else:
if self.payment_type == "Receive" \
and self.base_total_allocated_amount <= self.base_received_amount + total_deductions \
and self.total_allocated_amount < self.paid_amount:
self.unallocated_amount = (self.base_received_amount + total_deductions -
self.base_total_allocated_amount) / self.source_exchange_rate
elif self.payment_type == "Pay" \
and self.base_total_allocated_amount < (self.base_paid_amount - total_deductions) \
and self.total_allocated_amount < self.received_amount:
self.unallocated_amount = (self.base_paid_amount - (total_deductions +
self.base_total_allocated_amount)) / self.target_exchange_rate
def set_difference_amount(self):
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)

View File

@ -141,7 +141,6 @@ class TestPaymentEntry(unittest.TestCase):
def test_payment_entry_retrieves_last_exchange_rate(self):
from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records, save_new_records
test_records = test_records
save_new_records(test_records)
pe = frappe.new_doc("Payment Entry")
@ -151,6 +150,7 @@ class TestPaymentEntry(unittest.TestCase):
pe.paid_from = "_Test Bank USD - _TC"
pe.paid_to = "_Test Bank - _TC"
pe.paid_amount = 100
pe.received_amount = 100
pe.reference_no = "3"
pe.reference_date = "2016-01-10"
pe.party_type = "Supplier"

View File

@ -98,7 +98,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-07-11 03:28:03.420683",
"modified": "2018-02-21 03:28:03.420683",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry Deduction",

View File

@ -61,13 +61,11 @@ class TestPaymentRequest(unittest.TestCase):
self.assertEquals(pr.currency, "USD")
def test_payment_entry(self):
frappe.db.set_value("Company", "_Test Company",
frappe.db.set_value("Company", "_Test Company",
"exchange_gain_loss_account", "_Test Exchange Gain/Loss - _TC")
frappe.db.set_value("Company", "_Test Company",
"write_off_account", "_Test Write Off - _TC")
frappe.db.set_value("Company", "_Test Company",
"cost_center", "_Test Cost Center - _TC")
frappe.db.set_value("Company", "_Test Company", "write_off_account", "_Test Write Off - _TC")
frappe.db.set_value("Company", "_Test Company", "cost_center", "_Test Cost Center - _TC")
so_inr = make_sales_order(currency="INR")
pr = make_payment_request(dt="Sales Order", dn=so_inr.name, recipient_id="saurabh@erpnext.com",
mute_email=1, submit_doc=1, return_doc=1)
@ -82,15 +80,15 @@ class TestPaymentRequest(unittest.TestCase):
pr = make_payment_request(dt="Sales Invoice", dn=si_usd.name, recipient_id="saurabh@erpnext.com",
mute_email=1, payment_gateway="_Test Gateway - USD", submit_doc=1, return_doc=1)
pe = pr.set_as_paid()
expected_gle = dict((d[0], d) for d in [
["_Test Receivable USD - _TC", 0, 5000, si_usd.name],
[pr.payment_account, 6290.0, 0, None],
["_Test Exchange Gain/Loss - _TC", 0, 1290, None]
])
gl_entries = frappe.db.sql("""select account, debit, credit, against_voucher
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
order by account asc""", pe.name, as_dict=1)

View File

@ -21,8 +21,8 @@ def execute():
'''.format(
master_fieldname=d["master_fieldname"],
linked_to_fieldname=d["linked_to_fieldname"],
docname=frappe.db.escape(customer.name).encode("utf-8"),
value=frappe.db.escape(customer.get(source_fieldname)).encode("utf-8")))
docname=frappe.db.escape(frappe.as_unicode(customer.name)),
value=frappe.db.escape(frappe.as_unicode(customer.get(source_fieldname)))))
frappe.db.sql("""
update

View File

@ -80,7 +80,6 @@ class TestItem(unittest.TestCase):
}
make_test_objects("Item Price")
print(frappe.get_all("Item Price"))
details = get_item_details({
"item_code": "_Test Item",