PR and PI gl entries fixes for landed cost

This commit is contained in:
nabinhait 2014-07-24 17:42:52 +05:30 committed by Nabin Hait
parent 11594c7927
commit f807cda375
8 changed files with 93 additions and 49 deletions

View File

@ -274,6 +274,8 @@ class PurchaseInvoice(BuyingController):
auto_accounting_for_stock = \ auto_accounting_for_stock = \
cint(frappe.defaults.get_global_default("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 = [] gl_entries = []
# parent's gl entry # parent's gl entry
@ -313,7 +315,7 @@ class PurchaseInvoice(BuyingController):
(tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.tax_amount) (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.tax_amount)
# item gl entries # item gl entries
stock_item_and_auto_accounting_for_stock = False negative_expense_to_be_booked = 0.0
stock_items = self.get_stock_items() stock_items = self.get_stock_items()
for item in self.get("entries"): for item in self.get("entries"):
if flt(item.base_amount): if flt(item.base_amount):
@ -327,55 +329,54 @@ class PurchaseInvoice(BuyingController):
}) })
) )
if auto_accounting_for_stock and item.item_code in stock_items and item.valuation_rate: if auto_accounting_for_stock and item.item_code in stock_items and item.item_tax_amount:
# if auto inventory accounting enabled and stock item, # Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
# then do stock related gl entries stock_rbnb_booked_in_pr = None
# expense will be booked in sales invoice if item.purchase_receipt:
stock_item_and_auto_accounting_for_stock = True 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))
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)
if negative_expense_to_be_booked and valuation_tax:
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"
})
)
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:
# credit valuation tax amount in "Expenses Included In Valuation" # credit valuation tax amount in "Expenses Included In Valuation"
# this will balance out valuation amount included in cost of goods sold # this will balance out valuation amount included in cost of goods sold
expenses_included_in_valuation = \ expenses_included_in_valuation = self.get_company_default("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
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(): 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( gl_entries.append(
self.get_gl_dict({ self.get_gl_dict({
"account": expenses_included_in_valuation, "account": expenses_included_in_valuation,
"cost_center": cost_center, "cost_center": cost_center,
"against": self.credit_to, "against": self.credit_to,
"credit": amount, "credit": applicable_amount,
"remarks": self.remarks or "Accounting Entry for Stock" "remarks": self.remarks or "Accounting Entry for Stock"
}) })
) )
i += 1
# writeoff account includes petty difference in the invoice amount # writeoff account includes petty difference in the invoice amount
# and the amount that is paid # and the amount that is paid
if self.write_off_account and flt(self.write_off_amount): if self.write_off_account and flt(self.write_off_amount):

View File

@ -9,7 +9,8 @@ import frappe.model
import json import json
from frappe.utils import cint from frappe.utils import cint
import frappe.defaults 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_dependencies = ["Item", "Cost Center"]
test_ignore = ["Serial No"] test_ignore = ["Serial No"]
@ -54,6 +55,38 @@ class TestPurchaseInvoice(unittest.TestCase):
order by account asc""", pi.name, as_dict=1) order by account asc""", pi.name, as_dict=1)
self.assertTrue(gl_entries) 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([ expected_values = sorted([
["_Test Supplier - _TC", 0, 720], ["_Test Supplier - _TC", 0, 720],
["Stock Received But Not Billed - _TC", 750.0, 0], ["Stock Received But Not Billed - _TC", 750.0, 0],

View File

@ -138,6 +138,7 @@
} }
], ],
"posting_date": "2013-02-03", "posting_date": "2013-02-03",
"supplier": "_Test Supplier",
"supplier_name": "_Test Supplier" "supplier_name": "_Test Supplier"
}, },
{ {
@ -201,6 +202,7 @@
} }
], ],
"posting_date": "2013-02-03", "posting_date": "2013-02-03",
"supplier": "_Test Supplier",
"supplier_name": "_Test Supplier" "supplier_name": "_Test Supplier"
} }
] ]

View File

@ -11,7 +11,6 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \
class TestLandedCostVoucher(unittest.TestCase): class TestLandedCostVoucher(unittest.TestCase):
def test_landed_cost_voucher(self): def test_landed_cost_voucher(self):
frappe.db.set_default("cost_center", "Main - _TC")
set_perpetual_inventory(1) set_perpetual_inventory(1)
pr = self.submit_pr() pr = self.submit_pr()
self.submit_landed_cost_voucher(pr) self.submit_landed_cost_voucher(pr)
@ -30,8 +29,8 @@ class TestLandedCostVoucher(unittest.TestCase):
expected_values = { expected_values = {
stock_in_hand_account: [400.0, 0.0], stock_in_hand_account: [400.0, 0.0],
fixed_asset_account: [400.0, 0.0], fixed_asset_account: [400.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, 50.0] "Expenses Included In Valuation - _TC": [0.0, 300.0]
} }
for gle in gl_entries: for gle in gl_entries:

View File

@ -354,12 +354,12 @@ class PurchaseReceipt(BuyingController):
# and charges added via Landed Cost Voucher, # and charges added via Landed Cost Voucher,
# post valuation related charges on "Stock Received But Not Billed" # 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 where docstatus = 1 and purchase_receipt=%s
and exists(select name from `tabGL Entry` where voucher_type='Purchase Invoice' 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 expenses_included_in_valuation = stock_rbnb
# Expense included in valuation # Expense included in valuation

View File

@ -55,7 +55,6 @@ class TestPurchaseReceipt(unittest.TestCase):
set_perpetual_inventory() set_perpetual_inventory()
self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1) self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1)
pr = frappe.copy_doc(test_records[0]) pr = frappe.copy_doc(test_records[0])
pr.insert() pr.insert()
pr.submit() pr.submit()
@ -72,7 +71,8 @@ class TestPurchaseReceipt(unittest.TestCase):
expected_values = { expected_values = {
stock_in_hand_account: [375.0, 0.0], stock_in_hand_account: [375.0, 0.0],
fixed_asset_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: for gle in gl_entries:

View File

@ -19,7 +19,8 @@
"doctype": "Purchase Taxes and Charges", "doctype": "Purchase Taxes and Charges",
"parentfield": "other_charges", "parentfield": "other_charges",
"rate": 100.0, "rate": 100.0,
"tax_amount": 100.0 "tax_amount": 100.0,
"cost_center": "Main - _TC"
}, },
{ {
"account_head": "_Test Account VAT - _TC", "account_head": "_Test Account VAT - _TC",
@ -30,7 +31,8 @@
"doctype": "Purchase Taxes and Charges", "doctype": "Purchase Taxes and Charges",
"parentfield": "other_charges", "parentfield": "other_charges",
"rate": 120.0, "rate": 120.0,
"tax_amount": 120.0 "tax_amount": 120.0,
"cost_center": "Main - _TC"
}, },
{ {
"account_head": "_Test Account Customs Duty - _TC", "account_head": "_Test Account Customs Duty - _TC",
@ -41,7 +43,8 @@
"doctype": "Purchase Taxes and Charges", "doctype": "Purchase Taxes and Charges",
"parentfield": "other_charges", "parentfield": "other_charges",
"rate": 150.0, "rate": 150.0,
"tax_amount": 150.0 "tax_amount": 150.0,
"cost_center": "Main - _TC"
} }
], ],
"posting_date": "2013-02-12", "posting_date": "2013-02-12",
@ -61,7 +64,8 @@
"rejected_qty": 0.0, "rejected_qty": 0.0,
"stock_uom": "Nos", "stock_uom": "Nos",
"uom": "_Test UOM", "uom": "_Test UOM",
"warehouse": "_Test Warehouse - _TC" "warehouse": "_Test Warehouse - _TC",
"cost_center": "Main - _TC"
}, },
{ {
"base_amount": 250.0, "base_amount": 250.0,
@ -77,7 +81,8 @@
"rejected_qty": 0.0, "rejected_qty": 0.0,
"stock_uom": "Nos", "stock_uom": "Nos",
"uom": "_Test UOM", "uom": "_Test UOM",
"warehouse": "_Test Warehouse 1 - _TC" "warehouse": "_Test Warehouse 1 - _TC",
"cost_center": "Main - _TC"
} }
], ],
"supplier": "_Test Supplier" "supplier": "_Test Supplier"
@ -109,7 +114,8 @@
"rejected_qty": 0.0, "rejected_qty": 0.0,
"stock_uom": "Nos", "stock_uom": "Nos",
"uom": "_Test UOM", "uom": "_Test UOM",
"warehouse": "_Test Warehouse - _TC" "warehouse": "_Test Warehouse - _TC",
"cost_center": "Main - _TC"
} }
], ],
"supplier": "_Test Supplier", "supplier": "_Test Supplier",

View File

@ -16,3 +16,6 @@ class TestAddress(unittest.TestCase):
address = frappe.get_list("Address")[0].name address = frappe.get_list("Address")[0].name
display = get_address_display(frappe.get_doc("Address", address).as_dict()) display = get_address_display(frappe.get_doc("Address", address).as_dict())
self.assertTrue(display) self.assertTrue(display)
test_dependencies = ["Address Template"]