From 87c6718d90de2648918e9ef28a7674e67ce9e1c3 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 18 Nov 2019 12:34:30 +0530 Subject: [PATCH] fix: Book valuation expense in specified account rather than expense included in valuation account (#19590) * fix: Book valuation expense in specified accout rather than expense included in valuation account * fix: Remove undefined variable * fix: Test cases * fix: Test Case --- .../purchase_invoice/purchase_invoice.py | 60 ++++++++++--------- .../purchase_invoice/test_purchase_invoice.py | 29 +++++++-- .../test_landed_cost_voucher.py | 5 +- .../purchase_receipt/purchase_receipt.py | 47 ++++++++------- .../purchase_receipt/test_purchase_receipt.py | 5 +- 5 files changed, 88 insertions(+), 58 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 4fbf9a1009..5c53d26ad1 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -714,14 +714,14 @@ class PurchaseInvoice(BuyingController): if account_currency==self.company_currency \ else tax.tax_amount_after_discount_amount, "cost_center": tax.cost_center - }, account_currency) + }, account_currency, item=tax) ) # accumulate valuation tax if self.is_opening == "No" and tax.category in ("Valuation", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount): if self.auto_accounting_for_stock and not tax.cost_center: frappe.throw(_("Cost Center is required in row {0} in Taxes table for type {1}").format(tax.idx, _(tax.category))) - valuation_tax.setdefault(tax.cost_center, 0) - valuation_tax[tax.cost_center] += \ + valuation_tax.setdefault(tax.name, 0) + valuation_tax[tax.name] += \ (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.base_tax_amount_after_discount_amount) if self.is_opening == "No" and self.negative_expense_to_be_booked and valuation_tax: @@ -731,36 +731,38 @@ class PurchaseInvoice(BuyingController): total_valuation_amount = sum(valuation_tax.values()) amount_including_divisional_loss = self.negative_expense_to_be_booked i = 1 - for cost_center, amount in iteritems(valuation_tax): - if i == len(valuation_tax): - applicable_amount = amount_including_divisional_loss - else: - applicable_amount = self.negative_expense_to_be_booked * (amount / total_valuation_amount) - amount_including_divisional_loss -= applicable_amount + for tax in self.get("taxes"): + if valuation_tax.get(tax.name): + if i == len(valuation_tax): + applicable_amount = amount_including_divisional_loss + else: + applicable_amount = self.negative_expense_to_be_booked * (valuation_tax[tax.name] / total_valuation_amount) + amount_including_divisional_loss -= applicable_amount - gl_entries.append( - self.get_gl_dict({ - "account": self.expenses_included_in_valuation, - "cost_center": cost_center, - "against": self.supplier, - "credit": applicable_amount, - "remarks": self.remarks or "Accounting Entry for Stock" - }) - ) + gl_entries.append( + self.get_gl_dict({ + "account": tax.account_head, + "cost_center": tax.cost_center, + "against": self.supplier, + "credit": applicable_amount, + "remarks": self.remarks or _("Accounting Entry for Stock"), + }, item=tax) + ) - i += 1 + i += 1 if self.auto_accounting_for_stock and self.update_stock and valuation_tax: - for cost_center, amount in iteritems(valuation_tax): - gl_entries.append( - self.get_gl_dict({ - "account": self.expenses_included_in_valuation, - "cost_center": cost_center, - "against": self.supplier, - "credit": amount, - "remarks": self.remarks or "Accounting Entry for Stock" - }) - ) + for tax in self.get("taxes"): + if valuation_tax.get(tax.name): + gl_entries.append( + self.get_gl_dict({ + "account": tax.account_head, + "cost_center": tax.cost_center, + "against": self.supplier, + "credit": valuation_tax[tax.name], + "remarks": self.remarks or "Accounting Entry for Stock" + }, item=tax) + ) def make_payment_gl_entries(self, gl_entries): # Make Cash GL Entries diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index b2ad4f4d51..85b1166790 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -204,19 +204,40 @@ class TestPurchaseInvoice(unittest.TestCase): pi.insert() pi.submit() - self.check_gle_for_pi(pi.name) + self.check_gle_for_pi_against_pr(pi.name) def check_gle_for_pi(self, pi): - gl_entries = frappe.db.sql("""select account, debit, credit + gl_entries = frappe.db.sql("""select account, sum(debit) as debit, sum(credit) as credit from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s - order by account asc""", pi, as_dict=1) + group by account""", pi, as_dict=1) + self.assertTrue(gl_entries) expected_values = dict((d[0], d) for d in [ ["Creditors - TCP1", 0, 720], ["Stock Received But Not Billed - TCP1", 500.0, 0], - ["_Test Account Shipping Charges - TCP1", 100.0, 0], + ["_Test Account Shipping Charges - TCP1", 100.0, 0.0], + ["_Test Account VAT - TCP1", 120.0, 0] + ]) + + for i, gle in enumerate(gl_entries): + self.assertEqual(expected_values[gle.account][0], gle.account) + self.assertEqual(expected_values[gle.account][1], gle.debit) + self.assertEqual(expected_values[gle.account][2], gle.credit) + + def check_gle_for_pi_against_pr(self, pi): + gl_entries = frappe.db.sql("""select account, sum(debit) as debit, sum(credit) as credit + from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s + group by account""", pi, as_dict=1) + + self.assertTrue(gl_entries) + + expected_values = dict((d[0], d) for d in [ + ["Creditors - TCP1", 0, 720], + ["Stock Received But Not Billed - TCP1", 750.0, 0], + ["_Test Account Shipping Charges - TCP1", 100.0, 100.0], ["_Test Account VAT - TCP1", 120.0, 0], + ["_Test Account Customs Duty - TCP1", 0, 150] ]) for i, gle in enumerate(gl_entries): diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py index fe5d3ed6df..988cf52ed0 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py @@ -54,9 +54,10 @@ class TestLandedCostVoucher(unittest.TestCase): expected_values = { stock_in_hand_account: [800.0, 0.0], "Stock Received But Not Billed - TCP1": [0.0, 500.0], - "Expenses Included In Valuation - TCP1": [0.0, 300.0] + "Expenses Included In Valuation - TCP1": [0.0, 50.0], + "_Test Account Customs Duty - TCP1": [0.0, 150], + "_Test Account Shipping Charges - TCP1": [0.0, 100.00] } - else: expected_values = { stock_in_hand_account: [400.0, 0.0], diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 56fd47e1bc..0cb21d73f9 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -288,8 +288,8 @@ class PurchaseReceipt(BuyingController): if tax.category in ("Valuation", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount): if not tax.cost_center: frappe.throw(_("Cost Center is required in row {0} in Taxes table for type {1}").format(tax.idx, _(tax.category))) - valuation_tax.setdefault(tax.cost_center, 0) - valuation_tax[tax.cost_center] += \ + valuation_tax.setdefault(tax.name, 0) + valuation_tax[tax.name] += \ (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.base_tax_amount_after_discount_amount) if negative_expense_to_be_booked and valuation_tax: @@ -297,37 +297,42 @@ class PurchaseReceipt(BuyingController): # If expenses_included_in_valuation account has been credited in against PI # and charges added via Landed Cost Voucher, # post valuation related charges on "Stock Received But Not Billed" + # introduced in 2014 for backward compatibility of expenses already booked in expenses_included_in_valuation account negative_expense_booked_in_pi = frappe.db.sql("""select name from `tabPurchase Invoice Item` pi where docstatus = 1 and purchase_receipt=%s and exists(select name from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=pi.parent and account=%s)""", (self.name, expenses_included_in_valuation)) - if negative_expense_booked_in_pi: - expenses_included_in_valuation = stock_rbnb - against_account = ", ".join([d.account for d in gl_entries if flt(d.debit) > 0]) total_valuation_amount = sum(valuation_tax.values()) amount_including_divisional_loss = negative_expense_to_be_booked i = 1 - for cost_center, amount in iteritems(valuation_tax): - if i == len(valuation_tax): - applicable_amount = amount_including_divisional_loss - else: - applicable_amount = negative_expense_to_be_booked * (amount / total_valuation_amount) - amount_including_divisional_loss -= applicable_amount + for tax in self.get("taxes"): + if valuation_tax.get(tax.name): - gl_entries.append( - self.get_gl_dict({ - "account": expenses_included_in_valuation, - "cost_center": cost_center, - "credit": applicable_amount, - "remarks": self.remarks or _("Accounting Entry for Stock"), - "against": against_account - }) - ) + if negative_expense_booked_in_pi: + account = stock_rbnb + else: + account = tax.account_head - i += 1 + if i == len(valuation_tax): + applicable_amount = amount_including_divisional_loss + else: + applicable_amount = negative_expense_to_be_booked * (valuation_tax[tax.name] / total_valuation_amount) + amount_including_divisional_loss -= applicable_amount + + gl_entries.append( + self.get_gl_dict({ + "account": account, + "cost_center": tax.cost_center, + "credit": applicable_amount, + "remarks": self.remarks or _("Accounting Entry for Stock"), + "against": against_account + }, item=tax) + ) + + i += 1 if warehouse_with_no_account: frappe.msgprint(_("No accounting entries for the following warehouses") + ": \n" + diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 2afb69353f..c80b9bd04b 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -66,14 +66,15 @@ class TestPurchaseReceipt(unittest.TestCase): expected_values = { stock_in_hand_account: [750.0, 0.0], "Stock Received But Not Billed - TCP1": [0.0, 500.0], - "Expenses Included In Valuation - TCP1": [0.0, 250.0] + "_Test Account Shipping Charges - TCP1": [0.0, 100.0], + "_Test Account Customs Duty - TCP1": [0.0, 150.0] } else: expected_values = { stock_in_hand_account: [375.0, 0.0], fixed_asset_account: [375.0, 0.0], "Stock Received But Not Billed - TCP1": [0.0, 500.0], - "Expenses Included In Valuation - TCP1": [0.0, 250.0] + "_Test Account Shipping Charges - TCP1": [0.0, 250.0] } for gle in gl_entries: self.assertEqual(expected_values[gle.account][0], gle.debit)