Merge pull request #55296 from frappe/mergify/bp/version-15-hotfix/pr-55290

fix: inclusive tax amount not considered while setting LCV from purchase invoice (backport #55290)
This commit is contained in:
rohitwaghchaure
2026-05-26 16:23:13 +05:30
committed by GitHub
2 changed files with 153 additions and 2 deletions

View File

@@ -1250,7 +1250,7 @@ def get_billed_qty_amount_against_purchase_receipt(pr_doc):
.on(parent_table.name == table.parent)
.select(
table.pr_detail,
fn.Sum(table.amount * parent_table.conversion_rate).as_("amount"),
fn.Sum(table.base_net_amount).as_("amount"),
fn.Sum(table.qty).as_("qty"),
)
.where((table.pr_detail.isin(pr_names)) & (table.docstatus == 1))
@@ -1296,7 +1296,7 @@ def get_billed_qty_amount_against_purchase_order(pr_doc):
.select(
table.po_detail,
fn.Sum(table.qty).as_("qty"),
fn.Sum(table.amount * parent_table.conversion_rate).as_("amount"),
fn.Sum(table.base_net_amount).as_("amount"),
)
.where((table.po_detail.isin(po_names)) & (table.docstatus == 1) & (table.pr_detail.isnull()))
.groupby(table.po_detail)

View File

@@ -5170,6 +5170,157 @@ class TestPurchaseReceipt(FrappeTestCase):
"Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", original_value
)
@change_settings(
"Buying Settings", {"set_landed_cost_based_on_purchase_invoice_rate": 1, "maintain_same_rate": 0}
)
def test_srbnb_with_inclusive_tax_and_rate_change_in_pi(self):
"""
When 'Set Landed Cost Based on PI Rate' is enabled and PI has an inclusive tax:
- PR: qty=2, rate=1000 INR → base_net_amount=2000
- PI: rate changed to 2000, 5% tax included in basic rate
→ PI base_net_amount = 2 * 2000 / 1.05 ≈ 3809.52
The system must use PI's base_net_amount (not amount=4000) so that
SRBNB credit on PR = 3809.52, not 4000.
"""
company = "_Test Company with perpetual inventory"
warehouse = "Stores - TCP1"
cost_center = "Main - TCP1"
item_code = make_item(
"Test Item for SRBNB Inclusive Tax Rate Change",
{"is_stock_item": 1},
).name
pr = make_purchase_receipt(
item_code=item_code,
qty=2,
rate=1000,
company=company,
warehouse=warehouse,
cost_center=cost_center,
)
pi = make_purchase_invoice(pr.name)
pi.items[0].rate = 2000
pi.append(
"taxes",
{
"charge_type": "On Net Total",
"account_head": "_Test Account VAT - TCP1",
"category": "Total",
"add_deduct_tax": "Add",
"included_in_print_rate": 1,
"rate": 5,
"description": "Test Inclusive Tax",
"cost_center": cost_center,
},
)
pi.save()
pi.submit()
pr.reload()
# PI base_net_amount = qty * (rate / (1 + tax_rate/100)) = 2 * (2000 / 1.05)
pi_base_net_amount = flt(2 * 2000 / 1.05, 2)
pr_base_net_amount = flt(pr.items[0].amount, 2) # 2 * 1000 = 2000
expected_diff = flt(pi_base_net_amount - pr_base_net_amount, 2)
self.assertAlmostEqual(pr.items[0].amount_difference_with_purchase_invoice, expected_diff, places=2)
# Total SRBNB credit = PR base_net_amount + amount_difference = PI base_net_amount
srbnb_account = "Stock Received But Not Billed - TCP1"
gl_entries = get_gl_entries("Purchase Receipt", pr.name, skip_cancelled=True)
srbnb_credit = sum(flt(row.credit) for row in gl_entries if row.account == srbnb_account)
self.assertAlmostEqual(srbnb_credit, pi_base_net_amount, places=2)
@change_settings(
"Buying Settings", {"set_landed_cost_based_on_purchase_invoice_rate": 1, "maintain_same_rate": 0}
)
def test_srbnb_with_inclusive_tax_and_exchange_rate_change_in_pi(self):
"""
When 'Set Landed Cost Based on PI Rate' is enabled, PI has an inclusive tax, and only
the exchange rate changes on the PI (rate stays the same):
- PR: qty=2, rate=100 USD, conversion_rate=70 → base_net_amount=14000 INR
- PI: same rate=100 USD, conversion_rate changed to 90, 5% tax included in basic rate
→ PI base_net_amount = 2 * (100 / 1.05) * 90 ≈ 17142.86 INR
The system must use PI's base_net_amount (not amount = 2*100*90 = 18000) so that
SRBNB credit on PR = 17142.86, not 18000.
"""
from erpnext.accounts.doctype.account.test_account import create_account
company = "_Test Company with perpetual inventory"
warehouse = "Stores - TCP1"
cost_center = "Main - TCP1"
party_account = create_account(
account_name="USD Payable For SRBNB Exchange Rate Test",
parent_account="Accounts Payable - TCP1",
account_type="Payable",
company=company,
account_currency="USD",
)
supplier = create_supplier(
supplier_name="_Test USD Supplier for SRBNB Exchange Rate",
default_currency="USD",
party_account=party_account,
).name
item_code = make_item(
"Test Item for SRBNB Inclusive Tax Exchange Rate Change",
{"is_stock_item": 1},
).name
pr = make_purchase_receipt(
item_code=item_code,
qty=2,
rate=100,
currency="USD",
conversion_rate=70,
company=company,
warehouse=warehouse,
supplier=supplier,
)
pi = make_purchase_invoice(pr.name)
pi.conversion_rate = 90
pi.append(
"taxes",
{
"charge_type": "On Net Total",
"account_head": "_Test Account VAT - TCP1",
"category": "Total",
"add_deduct_tax": "Add",
"included_in_print_rate": 1,
"rate": 5,
"description": "Test Inclusive Tax",
"cost_center": cost_center,
},
)
pi.save()
pi.submit()
pr.reload()
# PI base_net_amount = qty * (rate / (1 + tax_rate/100)) * new_conversion_rate
# = 2 * (100 / 1.05) * 90 ≈ 17142.86 INR
# PR base_net_amount = qty * rate * pr_conversion_rate = 2 * 100 * 70 = 14000 INR
tax_amount_pr = (200 - flt(200 / 1.05, 2)) * 90
pi_base_net_amount = flt(2 * 100 * 90) - flt(tax_amount_pr)
pr_base_net_amount = flt(2 * 100 * 70)
expected_diff = flt(pi_base_net_amount - pr_base_net_amount)
self.assertAlmostEqual(pr.items[0].amount_difference_with_purchase_invoice, expected_diff, places=2)
# Total SRBNB credit = PR base_net_amount + amount_difference = PI base_net_amount
srbnb_account = "Stock Received But Not Billed - TCP1"
gl_entries = get_gl_entries("Purchase Receipt", pr.name, skip_cancelled=True)
srbnb_credit = sum(flt(row.credit) for row in gl_entries if row.account == srbnb_account)
self.assertAlmostEqual(srbnb_credit, pi_base_net_amount, places=2)
def prepare_data_for_internal_transfer():
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier