Merge branch 'payment_entry_validations_and_trigger' of https://github.com/deepeshgarg007/erpnext into payment_entry_validations_and_trigger

This commit is contained in:
Deepesh Garg
2021-08-18 15:58:46 +05:30
5 changed files with 62 additions and 17 deletions

View File

@@ -533,7 +533,7 @@ frappe.ui.form.on('Payment Entry', {
source_exchange_rate: function(frm) {
if (frm.doc.paid_amount) {
frm.set_value("base_paid_amount", flt(frm.doc.paid_amount) * flt(frm.doc.source_exchange_rate));
// target exchange rate should always be same as source if both account currencies is same
// target exchange rate should always be same as source if both account currencies are same
if(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
frm.set_value("base_received_amount", frm.doc.base_paid_amount);

View File

@@ -45,7 +45,7 @@ class PaymentEntry(AccountsController):
self.party_account = self.paid_to
self.party_account_currency = self.paid_to_account_currency
def validate(self, on_reference_unlink=False):
def validate(self):
self.setup_party_account_field()
self.set_missing_values()
self.validate_payment_type()
@@ -58,15 +58,16 @@ class PaymentEntry(AccountsController):
self.set_amounts()
self.validate_amounts()
self.apply_taxes()
self.set_amounts_after_tax()
self.clear_unallocated_reference_document_rows()
self.validate_payment_against_negative_invoice()
self.validate_transaction_reference()
self.set_title()
self.set_remarks()
self.validate_duplicate_entry()
if not on_reference_unlink:
self.validate_allocated_amount()
self.validate_paid_invoices()
self.validate_payment_type_with_outstanding()
self.validate_allocated_amount()
self.validate_paid_invoices()
self.ensure_supplier_is_not_blocked()
self.set_status()
@@ -120,6 +121,11 @@ class PaymentEntry(AccountsController):
if not self.get(field):
self.set(field, bank_data.account)
def validate_payment_type_with_outstanding(self):
total_outstanding = sum(d.allocated_amount for d in self.get('references'))
if total_outstanding < 0 and self.party_type == 'Customer' and self.payment_type == 'Receive':
frappe.throw(_("Cannot receive from customer against negative outstanding"), title=_("Incorrect Payment Type"))
def validate_allocated_amount(self):
for d in self.get("references"):
if (flt(d.allocated_amount))> 0:
@@ -472,7 +478,6 @@ class PaymentEntry(AccountsController):
def set_amounts(self):
self.set_received_amount()
self.set_amounts_in_company_currency()
self.set_amounts_after_tax()
self.set_total_allocated_amount()
self.set_unallocated_amount()
self.set_difference_amount()
@@ -487,6 +492,8 @@ class PaymentEntry(AccountsController):
def set_received_amount(self):
self.base_received_amount = self.base_paid_amount
if self.paid_from_account_currency == self.paid_to_account_currency:
self.received_amount = self.paid_amount
def set_amounts_after_tax(self):
applicable_tax = 0
@@ -530,10 +537,8 @@ class PaymentEntry(AccountsController):
base_total_allocated_amount += flt(flt(d.allocated_amount) * flt(d.exchange_rate),
self.precision("base_paid_amount"))
# Do not use absolute values as only credit notes could be allocated
# and total allocated should be negative in that scenario
self.total_allocated_amount = total_allocated_amount
self.base_total_allocated_amount = base_total_allocated_amount
self.total_allocated_amount = abs(total_allocated_amount)
self.base_total_allocated_amount = abs(base_total_allocated_amount)
def set_unallocated_amount(self):
self.unallocated_amount = 0

View File

@@ -107,7 +107,7 @@ class TestPaymentEntry(unittest.TestCase):
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 = 50
pe.source_exchange_rate = 50
pe.insert()
pe.submit()
@@ -154,7 +154,7 @@ class TestPaymentEntry(unittest.TestCase):
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 = 50
pe.source_exchange_rate = 50
pe.insert()
pe.submit()
@@ -491,7 +491,7 @@ class TestPaymentEntry(unittest.TestCase):
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.source_exchange_rate = 55
pe.append("deductions", {
"account": "_Test Exchange Gain/Loss - _TC",

View File

@@ -23,6 +23,7 @@ from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
from erpnext.stock.utils import get_incoming_rate
from erpnext.accounts.utils import PaymentEntryUnlinkError
class TestSalesInvoice(unittest.TestCase):
def make(self):
@@ -133,7 +134,7 @@ class TestSalesInvoice(unittest.TestCase):
pe.paid_to_account_currency = si.currency
pe.source_exchange_rate = 1
pe.target_exchange_rate = 1
pe.paid_amount = si.grand_total
pe.paid_amount = si.outstanding_amount
pe.insert()
pe.submit()
@@ -142,6 +143,42 @@ class TestSalesInvoice(unittest.TestCase):
self.assertRaises(frappe.LinkExistsError, si.cancel)
unlink_payment_on_cancel_of_invoice()
def test_payment_entry_unlink_against_standalone_credit_note(self):
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
si1 = create_sales_invoice(rate=1000)
si2 = create_sales_invoice(rate=300)
si3 = create_sales_invoice(qty=-1, rate=300, is_return=1)
pe = get_payment_entry("Sales Invoice", si1.name, bank_account="_Test Bank - _TC")
pe.append('references', {
'reference_doctype': 'Sales Invoice',
'reference_name': si2.name,
'total_amount': si2.grand_total,
'outstanding_amount': si2.outstanding_amount,
'allocated_amount': si2.outstanding_amount
})
pe.append('references', {
'reference_doctype': 'Sales Invoice',
'reference_name': si3.name,
'total_amount': si3.grand_total,
'outstanding_amount': si3.outstanding_amount,
'allocated_amount': si3.outstanding_amount
})
pe.reference_no = 'Test001'
pe.reference_date = nowdate()
pe.save()
pe.submit()
si2.load_from_db()
si2.cancel()
si1.load_from_db()
self.assertRaises(PaymentEntryUnlinkError, si1.cancel)
def test_sales_invoice_calculation_export_currency(self):
si = frappe.copy_doc(test_records[2])
si.currency = "USD"

View File

@@ -19,6 +19,7 @@ from erpnext.stock import get_warehouse_account_map
class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass
class FiscalYearError(frappe.ValidationError): pass
class PaymentEntryUnlinkError(frappe.ValidationError): pass
@frappe.whitelist()
def get_fiscal_year(date=None, fiscal_year=None, label="Date", verbose=1, company=None, as_dict=False):
@@ -555,12 +556,14 @@ def remove_ref_doc_link_from_pe(ref_type, ref_no):
for pe in linked_pe:
try:
pe_doc = frappe.get_doc("Payment Entry", pe)
pe_doc.validate(on_reference_unlink=True)
pe_doc.set_amounts()
pe_doc.clear_unallocated_reference_document_rows()
pe_doc.validate_payment_type_with_outstanding()
except Exception as e:
msg = _("There were issues unlinking payment entry {0}.").format(pe_doc.name)
msg += '<br>'
msg += _("Please cancel payment entry manually first and then resubmit")
frappe.throw(msg, title=_("Payment Unlink Error"))
msg += _("Please cancel payment entry manually first")
frappe.throw(msg, exc=PaymentEntryUnlinkError, title=_("Payment Unlink Error"))
frappe.db.sql("""update `tabPayment Entry` set total_allocated_amount=%s,
base_total_allocated_amount=%s, unallocated_amount=%s, modified=%s, modified_by=%s