From 866c2959896a7a5075ce0fc8d0826cb49d69f4dd Mon Sep 17 00:00:00 2001 From: Saurabh Date: Tue, 15 Nov 2016 17:18:44 +0530 Subject: [PATCH 1/2] [fix] on jv cancel remove linkings from advance table of Sales/Purchase Invoice --- .../accounts/doctype/journal_entry/journal_entry.py | 13 +++++++++++-- erpnext/utilities/transaction_base.py | 9 +++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 145ed81564..a30fec90b6 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -64,11 +64,20 @@ class JournalEntry(AccountsController): from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries from erpnext.hr.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip unlink_ref_doc_from_payment_entries(self.doctype, self.name) - unlink_ref_doc_from_salary_slip(self.name) + unlink_ref_doc_from_salary_slip(self.name) self.make_gl_entries(1) self.update_advance_paid() self.update_expense_claim() - + self.unlink_advance_entry_reference() + + def unlink_advance_entry_reference(self): + for d in self.get("accounts"): + if d.is_advance and d.reference_type in ("Sales Invoice", "Purchase Invoice"): + doc = frappe.get_doc(d.reference_type, d.reference_name) + doc.delink_advance_entries(self.name) + d.reference_type = '' + d.reference_name = '' + d.db_update() def validate_party(self): for d in self.get("accounts"): diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index 3cc79ef713..28d30efee7 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -125,6 +125,15 @@ class TransactionBase(StatusUpdater): ret = None return ret + + def delink_advance_entries(self, jv): + total_allocated_amount = 0 + for adv in self.advances: + if adv.reference_name == jv: + frappe.db.sql("""delete from `tab{0} Advance` + where name = %s""".format(self.doctype), adv.name) + total_allocated_amount += flt(adv.allocated_amount, adv.precision("allocated_amount")) + self.db_set("total_advance", total_allocated_amount) def delete_events(ref_type, ref_name): frappe.delete_doc("Event", frappe.db.sql_list("""select name from `tabEvent` From 8adbfa8a0995b09faea2cbd5f2af2c7f0d329bf3 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Wed, 16 Nov 2016 13:42:44 +0530 Subject: [PATCH 2/2] [test-case] test cases for delinking advance payments --- .../doctype/journal_entry/journal_entry.py | 2 +- .../purchase_invoice/test_purchase_invoice.py | 32 ++++++++++++++++++ .../sales_invoice/test_sales_invoice.py | 33 +++++++++++++++++++ erpnext/utilities/transaction_base.py | 9 +++-- 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index a30fec90b6..28028351d2 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -69,7 +69,7 @@ class JournalEntry(AccountsController): self.update_advance_paid() self.update_expense_claim() self.unlink_advance_entry_reference() - + def unlink_advance_entry_reference(self): for d in self.get("accounts"): if d.is_advance and d.reference_type in ("Sales Invoice", "Purchase Invoice"): diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index b4b8444e77..e82d55edcd 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -437,6 +437,38 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEquals(frappe.db.get_value("Serial No", pi.get("items")[0].rejected_serial_no, "warehouse"), pi.get("items")[0].rejected_warehouse) + + def test_outstanding_amount_after_advance_jv_cancelation(self): + from erpnext.accounts.doctype.journal_entry.test_journal_entry \ + import test_records as jv_test_records + + jv = frappe.copy_doc(jv_test_records[1]) + jv.insert() + jv.submit() + + pi = frappe.copy_doc(test_records[0]) + pi.append("advances", { + "reference_type": "Journal Entry", + "reference_name": jv.name, + "reference_row": jv.get("accounts")[0].name, + "advance_amount": 400, + "allocated_amount": 300, + "remarks": jv.remark + }) + pi.insert() + pi.submit() + pi.load_from_db() + + #check outstanding after advance allocation + self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance, pi.precision("outstanding_amount"))) + + #added to avoid Document has been modified exception + jv = frappe.get_doc("Journal Entry", jv.name) + jv.cancel() + + pi.load_from_db() + #check outstanding after advance cancellation + self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance, pi.precision("outstanding_amount"))) def unlink_payment_on_cancel_of_invoice(enable=1): accounts_settings = frappe.get_doc("Accounts Settings") diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 0011dfe736..12b90edd10 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -980,6 +980,39 @@ class TestSalesInvoice(unittest.TestCase): pe.submit() self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Active') + + def test_outstanding_amount_after_advance_jv_cancelation(self): + from erpnext.accounts.doctype.journal_entry.test_journal_entry \ + import test_records as jv_test_records + + jv = frappe.copy_doc(jv_test_records[0]) + jv.insert() + jv.submit() + + si = frappe.copy_doc(test_records[0]) + si.append("advances", { + "doctype": "Sales Invoice Advance", + "reference_type": "Journal Entry", + "reference_name": jv.name, + "reference_row": jv.get("accounts")[0].name, + "advance_amount": 400, + "allocated_amount": 300, + "remarks": jv.remark + }) + si.insert() + si.submit() + si.load_from_db() + + #check outstanding after advance allocation + self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount"))) + + #added to avoid Document has been modified exception + jv = frappe.get_doc("Journal Entry", jv.name) + jv.cancel() + + si.load_from_db() + #check outstanding after advance cancellation + self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount"))) def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index 28d30efee7..f85edfd0f4 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -129,11 +129,16 @@ class TransactionBase(StatusUpdater): def delink_advance_entries(self, jv): total_allocated_amount = 0 for adv in self.advances: + consider_for_total_advance = True if adv.reference_name == jv: frappe.db.sql("""delete from `tab{0} Advance` where name = %s""".format(self.doctype), adv.name) - total_allocated_amount += flt(adv.allocated_amount, adv.precision("allocated_amount")) - self.db_set("total_advance", total_allocated_amount) + consider_for_total_advance = False + + if consider_for_total_advance: + total_allocated_amount += flt(adv.allocated_amount, adv.precision("allocated_amount")) + + frappe.db.set_value(self.doctype, self.name, "total_advance", total_allocated_amount, update_modified=False) def delete_events(ref_type, ref_name): frappe.delete_doc("Event", frappe.db.sql_list("""select name from `tabEvent`