Merge pull request #10426 from nabinhait/payment_entry_deductions
Unallocated and difference amount calculation in Payment Entry
This commit is contained in:
commit
ec46e51ed4
@ -644,16 +644,9 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
if(frm.doc.party) {
|
if(frm.doc.party) {
|
||||||
var party_amount = frm.doc.payment_type=="Receive" ?
|
var party_amount = frm.doc.payment_type=="Receive" ?
|
||||||
frm.doc.paid_amount : frm.doc.received_amount;
|
frm.doc.paid_amount : frm.doc.received_amount;
|
||||||
|
|
||||||
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
|
|
||||||
function(d) { return flt(d.amount) }));
|
|
||||||
|
|
||||||
if(frm.doc.total_allocated_amount < party_amount) {
|
if(frm.doc.total_allocated_amount < party_amount) {
|
||||||
if(frm.doc.payment_type == "Receive") {
|
unallocated_amount = party_amount - frm.doc.total_allocated_amount;
|
||||||
unallocated_amount = party_amount - (frm.doc.total_allocated_amount - total_deductions);
|
|
||||||
} else {
|
|
||||||
unallocated_amount = party_amount - (frm.doc.total_allocated_amount + total_deductions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frm.set_value("unallocated_amount", unallocated_amount);
|
frm.set_value("unallocated_amount", unallocated_amount);
|
||||||
@ -672,11 +665,10 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
difference_amount = flt(frm.doc.base_paid_amount) - flt(frm.doc.base_received_amount);
|
difference_amount = flt(frm.doc.base_paid_amount) - flt(frm.doc.base_received_amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
$.each(frm.doc.deductions || [], function(i, d) {
|
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
|
||||||
if(d.amount) difference_amount -= flt(d.amount);
|
function(d) { return flt(d.amount) }));
|
||||||
})
|
|
||||||
|
|
||||||
frm.set_value("difference_amount", difference_amount);
|
frm.set_value("difference_amount", difference_amount - total_deductions);
|
||||||
|
|
||||||
frm.events.hide_unhide_fields(frm);
|
frm.events.hide_unhide_fields(frm);
|
||||||
},
|
},
|
||||||
|
@ -281,13 +281,8 @@ class PaymentEntry(AccountsController):
|
|||||||
if self.party:
|
if self.party:
|
||||||
party_amount = self.paid_amount if self.payment_type=="Receive" else self.received_amount
|
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.total_allocated_amount < party_amount:
|
||||||
if self.payment_type == "Receive":
|
self.unallocated_amount = party_amount - self.total_allocated_amount
|
||||||
self.unallocated_amount = party_amount - (self.total_allocated_amount - total_deductions)
|
|
||||||
else:
|
|
||||||
self.unallocated_amount = party_amount - (self.total_allocated_amount + total_deductions)
|
|
||||||
|
|
||||||
def set_difference_amount(self):
|
def set_difference_amount(self):
|
||||||
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)
|
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)
|
||||||
@ -302,11 +297,10 @@ class PaymentEntry(AccountsController):
|
|||||||
else:
|
else:
|
||||||
self.difference_amount = self.base_paid_amount - flt(self.base_received_amount)
|
self.difference_amount = self.base_paid_amount - flt(self.base_received_amount)
|
||||||
|
|
||||||
for d in self.get("deductions"):
|
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
|
||||||
if d.amount:
|
|
||||||
self.difference_amount -= flt(d.amount)
|
|
||||||
|
|
||||||
self.difference_amount = flt(self.difference_amount, self.precision("difference_amount"))
|
self.difference_amount = flt(self.difference_amount - total_deductions,
|
||||||
|
self.precision("difference_amount"))
|
||||||
|
|
||||||
def clear_unallocated_reference_document_rows(self):
|
def clear_unallocated_reference_document_rows(self):
|
||||||
self.set("references", self.get("references", {"allocated_amount": ["not in", [0, None, ""]]}))
|
self.set("references", self.get("references", {"allocated_amount": ["not in", [0, None, ""]]}))
|
||||||
|
@ -267,3 +267,65 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
return frappe.db.sql("""select account, debit, credit, against_voucher
|
return frappe.db.sql("""select account, debit, credit, against_voucher
|
||||||
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
|
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
|
||||||
order by account asc""", voucher_no, as_dict=1)
|
order by account asc""", voucher_no, as_dict=1)
|
||||||
|
|
||||||
|
def test_payment_entry_write_off_difference(self):
|
||||||
|
si = create_sales_invoice()
|
||||||
|
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Cash - _TC")
|
||||||
|
pe.reference_no = "1"
|
||||||
|
pe.reference_date = "2016-01-01"
|
||||||
|
pe.received_amount = pe.paid_amount = 110
|
||||||
|
pe.insert()
|
||||||
|
|
||||||
|
self.assertEqual(pe.unallocated_amount, 10)
|
||||||
|
|
||||||
|
pe.received_amount = pe.paid_amount = 95
|
||||||
|
pe.append("deductions", {
|
||||||
|
"account": "_Test Write Off - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"amount": 5
|
||||||
|
})
|
||||||
|
pe.save()
|
||||||
|
|
||||||
|
self.assertEqual(pe.unallocated_amount, 0)
|
||||||
|
self.assertEqual(pe.difference_amount, 0)
|
||||||
|
|
||||||
|
pe.submit()
|
||||||
|
|
||||||
|
expected_gle = dict((d[0], d) for d in [
|
||||||
|
["Debtors - _TC", 0, 100, si.name],
|
||||||
|
["_Test Cash - _TC", 95, 0, None],
|
||||||
|
["_Test Write Off - _TC", 5, 0, None]
|
||||||
|
])
|
||||||
|
|
||||||
|
self.validate_gl_entries(pe.name, expected_gle)
|
||||||
|
|
||||||
|
def test_payment_entry_exchange_gain_loss(self):
|
||||||
|
si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
|
||||||
|
currency="USD", conversion_rate=50)
|
||||||
|
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC")
|
||||||
|
pe.reference_no = "1"
|
||||||
|
pe.reference_date = "2016-01-01"
|
||||||
|
pe.target_exchange_rate = 55
|
||||||
|
|
||||||
|
pe.append("deductions", {
|
||||||
|
"account": "_Test Exchange Gain/Loss - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"amount": -500
|
||||||
|
})
|
||||||
|
pe.save()
|
||||||
|
|
||||||
|
self.assertEqual(pe.unallocated_amount, 0)
|
||||||
|
self.assertEqual(pe.difference_amount, 0)
|
||||||
|
|
||||||
|
pe.submit()
|
||||||
|
|
||||||
|
expected_gle = dict((d[0], d) for d in [
|
||||||
|
["_Test Receivable USD - _TC", 0, 5000, si.name],
|
||||||
|
["_Test Bank USD - _TC", 5500, 0, None],
|
||||||
|
["_Test Exchange Gain/Loss - _TC", 0, 500, None],
|
||||||
|
])
|
||||||
|
|
||||||
|
self.validate_gl_entries(pe.name, expected_gle)
|
||||||
|
|
||||||
|
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
||||||
|
self.assertEqual(outstanding_amount, 0)
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
QUnit.module('Payment Entry');
|
||||||
|
|
||||||
|
QUnit.test("test payment entry", function(assert) {
|
||||||
|
assert.expect(6);
|
||||||
|
let done = assert.async();
|
||||||
|
frappe.run_serially([
|
||||||
|
() => {
|
||||||
|
return frappe.tests.make('Sales Invoice', [
|
||||||
|
{customer: 'Test Customer 1'},
|
||||||
|
{items: [
|
||||||
|
[
|
||||||
|
{'qty': 1},
|
||||||
|
{'rate': 101},
|
||||||
|
{'item_code': 'Test Product 1'},
|
||||||
|
]
|
||||||
|
]}
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
() => cur_frm.save(),
|
||||||
|
() => frappe.tests.click_button('Submit'),
|
||||||
|
() => frappe.tests.click_button('Yes'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => frappe.tests.click_button('Close'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => frappe.click_button('Make'),
|
||||||
|
() => frappe.click_link('Payment', 1),
|
||||||
|
() => frappe.timeout(2),
|
||||||
|
() => {
|
||||||
|
assert.equal(frappe.get_route()[1], 'Payment Entry',
|
||||||
|
'made payment entry');
|
||||||
|
assert.equal(cur_frm.doc.party, 'Test Customer 1',
|
||||||
|
'customer set in payment entry');
|
||||||
|
assert.equal(cur_frm.doc.paid_amount, 101,
|
||||||
|
'paid amount set in payment entry');
|
||||||
|
assert.equal(cur_frm.doc.references[0].allocated_amount, 101,
|
||||||
|
'amount allocated against sales invoice');
|
||||||
|
},
|
||||||
|
() => cur_frm.set_value('paid_amount', 100),
|
||||||
|
() => {
|
||||||
|
cur_frm.doc.references[0].allocated_amount = 101;
|
||||||
|
},
|
||||||
|
() => frappe.click_button('Write Off Difference Amount'),
|
||||||
|
() => {
|
||||||
|
assert.equal(cur_frm.doc.difference_amount, 0,
|
||||||
|
'difference amount is zero');
|
||||||
|
assert.equal(cur_frm.doc.deductions[0].amount, 1,
|
||||||
|
'Write off amount = 1');
|
||||||
|
},
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
});
|
@ -25,5 +25,4 @@ QUnit.test("test payment entry", function(assert) {
|
|||||||
() => frappe.timeout(0.3),
|
() => frappe.timeout(0.3),
|
||||||
() => done()
|
() => done()
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
@ -0,0 +1,67 @@
|
|||||||
|
QUnit.module('Payment Entry');
|
||||||
|
|
||||||
|
QUnit.test("test payment entry", function(assert) {
|
||||||
|
assert.expect(8);
|
||||||
|
let done = assert.async();
|
||||||
|
frappe.run_serially([
|
||||||
|
() => {
|
||||||
|
return frappe.tests.make('Sales Invoice', [
|
||||||
|
{customer: 'Test Customer 1'},
|
||||||
|
{company: '_Test Company'},
|
||||||
|
{currency: 'INR'},
|
||||||
|
{selling_price_list: '_Test Price List'},
|
||||||
|
{items: [
|
||||||
|
[
|
||||||
|
{'qty': 1},
|
||||||
|
{'item_code': 'Test Product 1'},
|
||||||
|
]
|
||||||
|
]}
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => cur_frm.save(),
|
||||||
|
() => frappe.tests.click_button('Submit'),
|
||||||
|
() => frappe.tests.click_button('Yes'),
|
||||||
|
() => frappe.timeout(1.5),
|
||||||
|
() => frappe.click_button('Close'),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => frappe.click_button('Make'),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => frappe.click_link('Payment'),
|
||||||
|
() => frappe.timeout(2),
|
||||||
|
() => cur_frm.set_value("paid_to", "_Test Cash - _TC"),
|
||||||
|
() => frappe.timeout(0.5),
|
||||||
|
() => {
|
||||||
|
assert.equal(frappe.get_route()[1], 'Payment Entry', 'made payment entry');
|
||||||
|
assert.equal(cur_frm.doc.party, 'Test Customer 1', 'customer set in payment entry');
|
||||||
|
assert.equal(cur_frm.doc.paid_from, 'Debtors - _TC', 'customer account set in payment entry');
|
||||||
|
assert.equal(cur_frm.doc.paid_amount, 100, 'paid amount set in payment entry');
|
||||||
|
assert.equal(cur_frm.doc.references[0].allocated_amount, 100,
|
||||||
|
'amount allocated against sales invoice');
|
||||||
|
},
|
||||||
|
() => cur_frm.set_value('paid_amount', 95),
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => {
|
||||||
|
frappe.model.set_value("Payment Entry Reference",
|
||||||
|
cur_frm.doc.references[0].name, "allocated_amount", 100);
|
||||||
|
},
|
||||||
|
() => frappe.timeout(.5),
|
||||||
|
() => {
|
||||||
|
assert.equal(cur_frm.doc.difference_amount, 5, 'difference amount is 5');
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
frappe.db.set_value("Company", "_Test Company", "write_off_account", "_Test Write Off - _TC");
|
||||||
|
frappe.timeout(1);
|
||||||
|
frappe.db.set_value("Company", "_Test Company",
|
||||||
|
"exchange_gain_loss_account", "_Test Exchange Gain/Loss - _TC");
|
||||||
|
},
|
||||||
|
() => frappe.timeout(1),
|
||||||
|
() => frappe.click_button('Write Off Difference Amount'),
|
||||||
|
() => frappe.timeout(2),
|
||||||
|
() => {
|
||||||
|
assert.equal(cur_frm.doc.difference_amount, 0, 'difference amount is zero');
|
||||||
|
assert.equal(cur_frm.doc.deductions[0].amount, 5, 'Write off amount = 5');
|
||||||
|
},
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
});
|
@ -205,6 +205,18 @@ $.extend(frappe.test_data, {
|
|||||||
{title: "Test Term 2"}
|
{title: "Test Term 2"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"Item Price": {
|
||||||
|
"ITEM-PRICE-00001": [
|
||||||
|
{item_code: 'Test Product 1'},
|
||||||
|
{price_list: '_Test Price List'},
|
||||||
|
{price_list_rate: 100}
|
||||||
|
],
|
||||||
|
"ITEM-PRICE-00002": [
|
||||||
|
{item_code: 'Test Product 2'},
|
||||||
|
{price_list: '_Test Price List'},
|
||||||
|
{price_list_rate: 200}
|
||||||
|
]
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -125,4 +125,5 @@ erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer_f
|
|||||||
erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js
|
erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js
|
||||||
erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue_with_serialize_item.js
|
erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue_with_serialize_item.js
|
||||||
erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_repack.js
|
erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_repack.js
|
||||||
erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_serialize_item.js
|
erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_serialize_item.js
|
||||||
|
erpnext/accounts/doctype/payment_entry/tests/test_payment_against_invoice.js
|
||||||
|
Loading…
x
Reference in New Issue
Block a user