From f807cda375c0a238c694a702524c9f0281c0a846 Mon Sep 17 00:00:00 2001 From: nabinhait Date: Thu, 24 Jul 2014 17:42:52 +0530 Subject: [PATCH] PR and PI gl entries fixes for landed cost --- .../purchase_invoice/purchase_invoice.py | 69 ++++++++++--------- .../purchase_invoice/test_purchase_invoice.py | 35 +++++++++- .../purchase_invoice/test_records.json | 2 + .../test_landed_cost_voucher.py | 5 +- .../purchase_receipt/purchase_receipt.py | 6 +- .../purchase_receipt/test_purchase_receipt.py | 4 +- .../purchase_receipt/test_records.json | 18 +++-- .../utilities/doctype/address/test_address.py | 3 + 8 files changed, 93 insertions(+), 49 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 27f2064bef..e465e2c973 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -273,6 +273,8 @@ class PurchaseInvoice(BuyingController): def make_gl_entries(self): auto_accounting_for_stock = \ cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) + + stock_received_but_not_billed = self.get_company_default("stock_received_but_not_billed") gl_entries = [] @@ -313,7 +315,7 @@ class PurchaseInvoice(BuyingController): (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.tax_amount) # item gl entries - stock_item_and_auto_accounting_for_stock = False + negative_expense_to_be_booked = 0.0 stock_items = self.get_stock_items() for item in self.get("entries"): if flt(item.base_amount): @@ -327,54 +329,53 @@ class PurchaseInvoice(BuyingController): }) ) - if auto_accounting_for_stock and item.item_code in stock_items and item.valuation_rate: - # if auto inventory accounting enabled and stock item, - # then do stock related gl entries - # expense will be booked in sales invoice - stock_item_and_auto_accounting_for_stock = True - + if auto_accounting_for_stock and item.item_code in stock_items and item.item_tax_amount: + # Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt + stock_rbnb_booked_in_pr = None + if item.purchase_receipt: + stock_rbnb_booked_in_pr = frappe.db.sql("""select name from `tabGL Entry` + where voucher_type='Purchase Receipt' and voucher_no=%s and account=%s""", + (item.purchase_receipt, stock_received_but_not_billed)) - - gl_entries.append( - self.get_gl_dict({ - "account": item.expense_account, - "against": self.credit_to, - "debit": valuation_amt, - "remarks": self.remarks or "Accounting Entry for Stock" - }) - ) + if stock_rbnb_booked_in_pr: + gl_entries.append( + self.get_gl_dict({ + "account": stock_received_but_not_billed, + "against": self.credit_to, + "debit": flt(item.item_tax_amount), + "remarks": self.remarks or "Accounting Entry for Stock" + }) + ) + + negative_expense_to_be_booked += flt(item.item_tax_amount) - elif flt(item.base_amount): - # if not a stock item or auto inventory accounting disabled, book the expense - gl_entries.append( - self.get_gl_dict({ - "account": item.expense_account, - "against": self.credit_to, - "debit": item.base_amount, - "remarks": self.remarks, - "cost_center": item.cost_center - }) - ) - if stock_item_and_auto_accounting_for_stock and valuation_tax: + if negative_expense_to_be_booked and valuation_tax: # credit valuation tax amount in "Expenses Included In Valuation" # this will balance out valuation amount included in cost of goods sold - expenses_included_in_valuation = \ - self.get_company_default("expenses_included_in_valuation") - - # Backward compatibility: - # Post expenses_included_in_valuation only if it is not booked in Purchase Receipt + expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") + total_valuation_amount = sum(valuation_tax.values()) + amount_including_divisional_loss = negative_expense_to_be_booked + i = 1 for cost_center, amount in valuation_tax.items(): + 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 + gl_entries.append( self.get_gl_dict({ "account": expenses_included_in_valuation, "cost_center": cost_center, "against": self.credit_to, - "credit": amount, + "credit": applicable_amount, "remarks": self.remarks or "Accounting Entry for Stock" }) ) + + i += 1 # writeoff account includes petty difference in the invoice amount # and the amount that is paid diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index ca73518bd9..5eb5f0103b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -9,7 +9,8 @@ import frappe.model import json from frappe.utils import cint import frappe.defaults -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \ + test_records as pr_test_records test_dependencies = ["Item", "Cost Center"] test_ignore = ["Serial No"] @@ -54,6 +55,38 @@ class TestPurchaseInvoice(unittest.TestCase): order by account asc""", pi.name, as_dict=1) self.assertTrue(gl_entries) + expected_values = sorted([ + ["_Test Supplier - _TC", 0, 720], + ["Stock Received But Not Billed - _TC", 500.0, 0], + ["_Test Account Shipping Charges - _TC", 100.0, 0], + ["_Test Account VAT - _TC", 120.0, 0], + ]) + + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_values[i][0], gle.account) + self.assertEquals(expected_values[i][1], gle.debit) + self.assertEquals(expected_values[i][2], gle.credit) + + set_perpetual_inventory(0) + + def test_gl_entries_with_auto_accounting_for_stock_against_pr(self): + set_perpetual_inventory(1) + self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1) + + pr = frappe.copy_doc(pr_test_records[0]) + pr.submit() + + pi = frappe.copy_doc(test_records[1]) + for d in pi.get("entries"): + d.purchase_receipt = pr.name + pi.insert() + pi.submit() + + gl_entries = frappe.db.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s + order by account asc""", pi.name, as_dict=1) + self.assertTrue(gl_entries) + expected_values = sorted([ ["_Test Supplier - _TC", 0, 720], ["Stock Received But Not Billed - _TC", 750.0, 0], diff --git a/erpnext/accounts/doctype/purchase_invoice/test_records.json b/erpnext/accounts/doctype/purchase_invoice/test_records.json index 48fb45d4d0..3ddbcc76e1 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_records.json +++ b/erpnext/accounts/doctype/purchase_invoice/test_records.json @@ -138,6 +138,7 @@ } ], "posting_date": "2013-02-03", + "supplier": "_Test Supplier", "supplier_name": "_Test Supplier" }, { @@ -201,6 +202,7 @@ } ], "posting_date": "2013-02-03", + "supplier": "_Test Supplier", "supplier_name": "_Test Supplier" } ] 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 6abf2f5d53..ca16b4493b 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 @@ -11,7 +11,6 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \ class TestLandedCostVoucher(unittest.TestCase): def test_landed_cost_voucher(self): - frappe.db.set_default("cost_center", "Main - _TC") set_perpetual_inventory(1) pr = self.submit_pr() self.submit_landed_cost_voucher(pr) @@ -30,8 +29,8 @@ class TestLandedCostVoucher(unittest.TestCase): expected_values = { stock_in_hand_account: [400.0, 0.0], fixed_asset_account: [400.0, 0.0], - "Stock Received But Not Billed - _TC": [0.0, 750.0], - "Expenses Included In Valuation - _TC": [0.0, 50.0] + "Stock Received But Not Billed - _TC": [0.0, 500.0], + "Expenses Included In Valuation - _TC": [0.0, 300.0] } for gle in gl_entries: diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 1f02f361b8..cb24c8e211 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -354,12 +354,12 @@ class PurchaseReceipt(BuyingController): # and charges added via Landed Cost Voucher, # post valuation related charges on "Stock Received But Not Billed" - pi_exists = frappe.db.sql("""select name from `tabPurchase Invoice Item` pi + stock_rbnb_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)) + and voucher_no=pi.parent and account=%s)""", (self.name, stock_rbnb)) - if pi_exists: + if stock_rbnb_booked_in_pi: expenses_included_in_valuation = stock_rbnb # Expense included in valuation diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 77de44d021..9b76a14381 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -55,7 +55,6 @@ class TestPurchaseReceipt(unittest.TestCase): set_perpetual_inventory() self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1) - pr = frappe.copy_doc(test_records[0]) pr.insert() pr.submit() @@ -72,7 +71,8 @@ class TestPurchaseReceipt(unittest.TestCase): expected_values = { stock_in_hand_account: [375.0, 0.0], fixed_asset_account: [375.0, 0.0], - "Stock Received But Not Billed - _TC": [0.0, 750.0] + "Stock Received But Not Billed - _TC": [0.0, 500.0], + "Expenses Included In Valuation - _TC": [0.0, 250.0] } for gle in gl_entries: diff --git a/erpnext/stock/doctype/purchase_receipt/test_records.json b/erpnext/stock/doctype/purchase_receipt/test_records.json index 7dd4f7f739..4b9b3aecf2 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_records.json +++ b/erpnext/stock/doctype/purchase_receipt/test_records.json @@ -19,7 +19,8 @@ "doctype": "Purchase Taxes and Charges", "parentfield": "other_charges", "rate": 100.0, - "tax_amount": 100.0 + "tax_amount": 100.0, + "cost_center": "Main - _TC" }, { "account_head": "_Test Account VAT - _TC", @@ -30,7 +31,8 @@ "doctype": "Purchase Taxes and Charges", "parentfield": "other_charges", "rate": 120.0, - "tax_amount": 120.0 + "tax_amount": 120.0, + "cost_center": "Main - _TC" }, { "account_head": "_Test Account Customs Duty - _TC", @@ -41,7 +43,8 @@ "doctype": "Purchase Taxes and Charges", "parentfield": "other_charges", "rate": 150.0, - "tax_amount": 150.0 + "tax_amount": 150.0, + "cost_center": "Main - _TC" } ], "posting_date": "2013-02-12", @@ -61,7 +64,8 @@ "rejected_qty": 0.0, "stock_uom": "Nos", "uom": "_Test UOM", - "warehouse": "_Test Warehouse - _TC" + "warehouse": "_Test Warehouse - _TC", + "cost_center": "Main - _TC" }, { "base_amount": 250.0, @@ -77,7 +81,8 @@ "rejected_qty": 0.0, "stock_uom": "Nos", "uom": "_Test UOM", - "warehouse": "_Test Warehouse 1 - _TC" + "warehouse": "_Test Warehouse 1 - _TC", + "cost_center": "Main - _TC" } ], "supplier": "_Test Supplier" @@ -109,7 +114,8 @@ "rejected_qty": 0.0, "stock_uom": "Nos", "uom": "_Test UOM", - "warehouse": "_Test Warehouse - _TC" + "warehouse": "_Test Warehouse - _TC", + "cost_center": "Main - _TC" } ], "supplier": "_Test Supplier", diff --git a/erpnext/utilities/doctype/address/test_address.py b/erpnext/utilities/doctype/address/test_address.py index 1e36a4438c..11f67b17e4 100644 --- a/erpnext/utilities/doctype/address/test_address.py +++ b/erpnext/utilities/doctype/address/test_address.py @@ -16,3 +16,6 @@ class TestAddress(unittest.TestCase): address = frappe.get_list("Address")[0].name display = get_address_display(frappe.get_doc("Address", address).as_dict()) self.assertTrue(display) + + +test_dependencies = ["Address Template"]