fix: skip stock expense GL entries for non-stock items (#57518)

* fix: skip stock expense gl entries for non stock items

(cherry picked from commit 747f4df778dca45cf044c02f0e933d3b230b8334)

* test: use a leaf expense account for the service item invoice
This commit is contained in:
rohitwaghchaure
2026-07-28 13:00:41 +05:30
committed by GitHub
parent 7eb0eb77aa
commit 861c50e727
3 changed files with 52 additions and 0 deletions

View File

@@ -356,7 +356,14 @@ class BuyingController(SubcontractingController):
if self.doctype == "Purchase Invoice" and not self.update_stock:
return
stock_items = self.get_stock_items()
for row in self.items:
# A service item holds no stock value, so there is nothing to book against it - and it
# must not make the expense accounts mandatory either.
if row.item_code not in stock_items:
continue
details = self.get_validated_purchase_expense_details(row.item_code)
if not details:
continue
@@ -365,6 +372,10 @@ class BuyingController(SubcontractingController):
if row.landed_cost_voucher_amount:
amount -= flt(row.landed_cost_voucher_amount, row.precision("base_amount"))
if not amount:
# GL Entry rejects a row with neither a debit nor a credit.
continue
self.add_gl_entry(
gl_entries=gl_entries,
account=details.purchase_expense_account,

View File

@@ -897,6 +897,12 @@ class StockController(AccountsController):
self.append_expenses_added_to_stock_pair(gl_list, item_code, amount, item_row)
def append_expenses_added_to_stock_pair(self, gl_list, item_code, amount, item_row):
# A service item holds no stock value, so there is nothing to book against it - and it must
# not make the expense accounts mandatory either. A zero pair would be rejected by GL Entry
# anyway, which needs a debit or a credit on every row.
if not amount or not frappe.get_cached_value("Item", item_code, "is_stock_item"):
return
fields = ("expenses_added_to_stock_account", "expenses_added_to_stock_contra_account")
details = get_expenses_added_to_stock_accounts(item_code, self.company)

View File

@@ -174,3 +174,38 @@ class TestExpensesAddedToStock(ERPNextTestSuite):
rate=100,
company=COMPANY,
)
def test_service_item_books_nothing_on_purchase_invoice_with_update_stock(self):
"""A service item carries no stock value, so booking it produced a GL row with neither a
debit nor a credit, which GL Entry rejects outright."""
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
service_item = make_item(properties={"is_stock_item": 0}).name
pi = make_purchase_invoice(
company=COMPANY,
warehouse=WAREHOUSE,
item_code=service_item,
qty=1,
rate=500,
update_stock=1,
expense_account="Cost of Goods Sold - TCP1",
cost_center="Main - TCP1",
)
self.assertEqual(pi.docstatus, 1)
_balances, debits, credits = self.get_gl_balances("Purchase Invoice", pi.name)
self.assertEqual(debits[self.eats_account], 0)
self.assertEqual(credits[self.eats_contra_account], 0)
booked = frappe.get_all(
"GL Entry",
filters={
"voucher_type": "Purchase Invoice",
"voucher_no": pi.name,
"is_cancelled": 0,
"account": self.purchase_expense_account,
},
)
self.assertFalse(booked)