mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-15 23:48:38 +00:00
fix: exclude non-stock item's tax value from stock valuation
(cherry picked from commit 13e1f84eb1)
This commit is contained in:
committed by
Mergify
parent
3243e4237a
commit
3d6c7f4512
@@ -417,20 +417,21 @@ class BuyingController(SubcontractingController):
|
|||||||
stock_and_asset_items_qty, stock_and_asset_items_amount = 0, 0
|
stock_and_asset_items_qty, stock_and_asset_items_amount = 0, 0
|
||||||
last_item_idx = 1
|
last_item_idx = 1
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if d.item_code and d.item_code in stock_and_asset_items:
|
if d.item_code:
|
||||||
stock_and_asset_items_qty += flt(d.qty)
|
stock_and_asset_items_qty += flt(d.qty)
|
||||||
stock_and_asset_items_amount += flt(d.base_net_amount)
|
stock_and_asset_items_amount += flt(d.base_net_amount)
|
||||||
|
|
||||||
last_item_idx = d.idx
|
last_item_idx = d.idx
|
||||||
|
|
||||||
tax_accounts, total_valuation_amount, total_actual_tax_amount = self.get_tax_details()
|
tax_accounts, total_valuation_amount, total_actual_tax_amount = self.get_tax_details()
|
||||||
|
remaining_amount = total_actual_tax_amount
|
||||||
|
|
||||||
for i, item in enumerate(self.get("items")):
|
for i, item in enumerate(self.get("items")):
|
||||||
if item.item_code and (item.qty or item.get("rejected_qty")):
|
if item.item_code and (item.qty or item.get("rejected_qty")):
|
||||||
item_tax_amount, actual_tax_amount = 0.0, 0.0
|
item_tax_amount, actual_tax_amount = 0.0, 0.0
|
||||||
if i == (last_item_idx - 1):
|
if i == (last_item_idx - 1):
|
||||||
item_tax_amount = total_valuation_amount
|
item_tax_amount = total_valuation_amount
|
||||||
actual_tax_amount = total_actual_tax_amount
|
actual_tax_amount = remaining_amount
|
||||||
else:
|
else:
|
||||||
# calculate item tax amount
|
# calculate item tax amount
|
||||||
item_tax_amount = self.get_item_tax_amount(item, tax_accounts)
|
item_tax_amount = self.get_item_tax_amount(item, tax_accounts)
|
||||||
@@ -443,7 +444,8 @@ class BuyingController(SubcontractingController):
|
|||||||
stock_and_asset_items_amount,
|
stock_and_asset_items_amount,
|
||||||
stock_and_asset_items_qty,
|
stock_and_asset_items_qty,
|
||||||
)
|
)
|
||||||
total_actual_tax_amount -= actual_tax_amount
|
|
||||||
|
remaining_amount -= actual_tax_amount
|
||||||
|
|
||||||
# This code is required here to calculate the correct valuation for stock items
|
# This code is required here to calculate the correct valuation for stock items
|
||||||
if item.item_code not in stock_and_asset_items:
|
if item.item_code not in stock_and_asset_items:
|
||||||
|
|||||||
@@ -1333,6 +1333,73 @@ class TestPurchaseReceipt(ERPNextTestSuite):
|
|||||||
|
|
||||||
pr.delete()
|
pr.delete()
|
||||||
|
|
||||||
|
def test_valuation_tax_distribution_with_non_stock_item(self):
|
||||||
|
"""A "Valuation and Total" tax is distributed across all items by net amount, but only
|
||||||
|
stock/asset items can carry valuation. For a document with 2 stock items + 1 service
|
||||||
|
item (each net 100) and a 30 valuation tax, each item's share is 10; only the two stock
|
||||||
|
items capitalize their share (20 total), so the non-stock item's 10 share must not be
|
||||||
|
capitalized onto the stock items."""
|
||||||
|
company = "_Test Company with perpetual inventory"
|
||||||
|
warehouse = "Stores - TCP1"
|
||||||
|
|
||||||
|
stock_item1 = make_item(properties={"is_stock_item": 1}).name
|
||||||
|
stock_item2 = make_item(properties={"is_stock_item": 1}).name
|
||||||
|
service_item = make_item(properties={"is_stock_item": 0}).name
|
||||||
|
|
||||||
|
pr = frappe.new_doc("Purchase Receipt")
|
||||||
|
pr.company = company
|
||||||
|
pr.supplier = "_Test Supplier"
|
||||||
|
pr.currency = "INR"
|
||||||
|
# Order matters: stock, service, stock (service item in the middle)
|
||||||
|
for code in (stock_item1, service_item, stock_item2):
|
||||||
|
pr.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": code,
|
||||||
|
"qty": 1,
|
||||||
|
"rate": 100,
|
||||||
|
"warehouse": warehouse,
|
||||||
|
"cost_center": "Main - TCP1",
|
||||||
|
"expense_account": "Cost of Goods Sold - TCP1",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
pr.append(
|
||||||
|
"taxes",
|
||||||
|
{
|
||||||
|
"charge_type": "Actual",
|
||||||
|
"account_head": "_Test Account Shipping Charges - TCP1",
|
||||||
|
"category": "Valuation and Total",
|
||||||
|
"cost_center": "Main - TCP1",
|
||||||
|
"description": "Valuation Tax",
|
||||||
|
"tax_amount": 30,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
pr.insert()
|
||||||
|
|
||||||
|
# 30 tax / 300 net = 10 per item. The two stock items capitalize 10 each; the service
|
||||||
|
# item's 10 share is excluded from valuation (not dumped onto the stock items).
|
||||||
|
self.assertAlmostEqual(pr.items[0].item_tax_amount, 10.0, places=2)
|
||||||
|
self.assertAlmostEqual(pr.items[1].item_tax_amount, 0.0, places=2)
|
||||||
|
self.assertAlmostEqual(pr.items[2].item_tax_amount, 10.0, places=2)
|
||||||
|
self.assertAlmostEqual(pr.items[0].valuation_rate, 110.0, places=2)
|
||||||
|
self.assertAlmostEqual(pr.items[2].valuation_rate, 110.0, places=2)
|
||||||
|
|
||||||
|
pr.submit()
|
||||||
|
|
||||||
|
gl_entries = get_gl_entries("Purchase Receipt", pr.name, skip_cancelled=True, as_dict=True)
|
||||||
|
gl_map = {row.account: row for row in gl_entries}
|
||||||
|
|
||||||
|
warehouse_account = get_warehouse_account_map(company)
|
||||||
|
stock_account = warehouse_account[warehouse]["account"]
|
||||||
|
|
||||||
|
# Stock asset = 200 (goods) + 20 (stock items' share of the valuation tax)
|
||||||
|
self.assertAlmostEqual(gl_map[stock_account].debit, 220.0, places=2)
|
||||||
|
self.assertAlmostEqual(gl_map["Stock Received But Not Billed - TCP1"].credit, 200.0, places=2)
|
||||||
|
# Only the stock items' share (20) is capitalized; the service item's 10 is excluded
|
||||||
|
self.assertAlmostEqual(gl_map["_Test Account Shipping Charges - TCP1"].credit, 20.0, places=2)
|
||||||
|
|
||||||
def test_po_to_pi_and_po_to_pr_worflow_full(self):
|
def test_po_to_pi_and_po_to_pr_worflow_full(self):
|
||||||
"""Test following behaviour:
|
"""Test following behaviour:
|
||||||
- Create PO
|
- Create PO
|
||||||
|
|||||||
Reference in New Issue
Block a user