fix: net_amount calculation (#44231)

fix: tax_item_rate calculation
This commit is contained in:
David Arnold
2024-11-23 23:10:33 +01:00
committed by GitHub
parent e9ea9ee57b
commit 2e04eeb661
13 changed files with 85 additions and 41 deletions

View File

@@ -13,6 +13,7 @@
"col_break_1",
"description",
"included_in_paid_amount",
"set_by_item_tax_template",
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
@@ -194,12 +195,22 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"default": "0",
"fieldname": "set_by_item_tax_template",
"fieldtype": "Check",
"hidden": 1,
"label": "Set by Item Tax Template",
"print_hide": 1,
"read_only": 1,
"report_hide": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2024-09-24 06:51:07.417348",
"modified": "2024-11-22 19:16:22.346267",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Taxes and Charges",

View File

@@ -34,6 +34,7 @@ class AdvanceTaxesandCharges(Document):
parenttype: DF.Data
rate: DF.Float
row_id: DF.Data | None
set_by_item_tax_template: DF.Check
tax_amount: DF.Currency
total: DF.Currency
# end: auto-generated types

View File

@@ -157,16 +157,19 @@ class TestPOSInvoiceMergeLog(IntegrationTestCase):
consolidated_invoice = frappe.get_doc("Sales Invoice", inv.consolidated_invoice)
item_wise_tax_detail = json.loads(consolidated_invoice.get("taxes")[0].item_wise_tax_detail)
tax_data = item_wise_tax_detail.get("_Test Item")
self.assertEqual(tax_data.get("tax_rate"), 9)
self.assertEqual(tax_data.get("tax_amount"), 9)
self.assertEqual(tax_data.get("net_amount"), 100)
tax_data = item_wise_tax_detail.get("_Test Item 2")
self.assertEqual(tax_data.get("tax_rate"), 5)
self.assertEqual(tax_data.get("tax_amount"), 5)
self.assertEqual(tax_data.get("net_amount"), 100)
expected_item_wise_tax_detail = {
"_Test Item": {
"tax_rate": 9,
"tax_amount": 9,
"net_amount": 100,
},
"_Test Item 2": {
"tax_rate": 5,
"tax_amount": 5,
"net_amount": 100,
},
}
self.assertEqual(item_wise_tax_detail, expected_item_wise_tax_detail)
finally:
frappe.set_user("Administrator")
frappe.db.sql("delete from `tabPOS Profile`")

View File

@@ -17,6 +17,7 @@
"account_head",
"description",
"is_tax_withholding_account",
"set_by_item_tax_template",
"section_break_10",
"rate",
"accounting_dimensions_section",
@@ -254,12 +255,22 @@
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
},
{
"default": "0",
"fieldname": "set_by_item_tax_template",
"fieldtype": "Check",
"hidden": 1,
"label": "Set by Item Tax Template",
"print_hide": 1,
"read_only": 1,
"report_hide": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-09-24 06:47:25.129901",
"modified": "2024-11-22 19:17:02.377473",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges",

View File

@@ -42,6 +42,7 @@ class PurchaseTaxesandCharges(Document):
parenttype: DF.Data
rate: DF.Float
row_id: DF.Data | None
set_by_item_tax_template: DF.Check
tax_amount: DF.Currency
tax_amount_after_discount_amount: DF.Currency
total: DF.Currency

View File

@@ -13,6 +13,7 @@
"description",
"included_in_print_rate",
"included_in_paid_amount",
"set_by_item_tax_template",
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
@@ -232,13 +233,23 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"default": "0",
"fieldname": "set_by_item_tax_template",
"fieldtype": "Check",
"hidden": 1,
"label": "Set by Item Tax Template",
"print_hide": 1,
"read_only": 1,
"report_hide": 1
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2024-09-24 06:49:32.034074",
"modified": "2024-11-22 19:17:31.898467",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",

View File

@@ -40,6 +40,7 @@ class SalesTaxesandCharges(Document):
parenttype: DF.Data
rate: DF.Float
row_id: DF.Data | None
set_by_item_tax_template: DF.Check
tax_amount: DF.Currency
tax_amount_after_discount_amount: DF.Currency
total: DF.Currency

View File

@@ -961,6 +961,7 @@ class AccountsController(TransactionBase):
"account_head": account_head,
"rate": 0,
"description": account_head,
"set_by_item_tax_template": 1,
},
)
@@ -3176,9 +3177,10 @@ def set_child_tax_template_and_map(item, child_item, parent_doc):
)
child_item.item_tax_template = _get_item_tax_template(ctx, item.taxes)
if child_item.get("item_tax_template"):
child_item.item_tax_rate = get_item_tax_map(
parent_doc.get("company"), child_item.item_tax_template, as_json=True
doc=parent_doc,
tax_template=child_item.item_tax_template,
as_json=True,
)
@@ -3202,6 +3204,7 @@ def add_taxes_from_tax_template(child_item, parent_doc, db_insert=True):
"charge_type": "On Net Total",
"account_head": tax_type,
"rate": tax_rate,
"set_by_item_tax_template": 1,
}
)
if parent_doc.doctype == "Purchase Order":

View File

@@ -501,9 +501,7 @@ class calculate_taxes_and_totals:
)
elif tax.charge_type == "On Net Total":
if not item_tax_map:
current_net_amount = item.net_amount
elif tax.account_head in item_tax_map:
if tax.account_head in item_tax_map:
current_net_amount = item.net_amount
current_tax_amount = (tax_rate / 100.0) * item.net_amount
elif tax.charge_type == "On Previous Row Amount":

View File

@@ -79,7 +79,7 @@ class TestTaxesAndTotals(FrappeTestCase):
"rate": 50,
},
)
self.doc.set_missing_item_details()
calculate_taxes_and_totals(self.doc)
expected_values = {

View File

@@ -336,6 +336,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
child.charge_type = "On Net Total";
child.account_head = tax;
child.rate = 0;
child.set_by_item_tax_template = true;
}
});
}

View File

@@ -751,6 +751,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
child.charge_type = "On Net Total";
child.account_head = tax;
child.rate = 0;
child.set_by_item_tax_template = true;
}
});
}
@@ -2076,7 +2077,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
return this.frm.call({
method: "erpnext.stock.get_item_details.get_item_tax_info",
args: {
company: me.frm.doc.company,
doc: me.frm.doc,
tax_category: cstr(me.frm.doc.tax_category),
item_codes: item_codes,
item_rates: item_rates,
@@ -2107,7 +2108,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
return this.frm.call({
method: "erpnext.stock.get_item_details.get_item_tax_map",
args: {
company: me.frm.doc.company,
doc: me.frm.doc,
item_tax_template: item.item_tax_template,
as_json: true
},

View File

@@ -98,8 +98,8 @@ def get_item_details(
get_item_tax_template(ctx, item, out)
out.item_tax_rate = get_item_tax_map(
ctx.company,
out.item_tax_template or ctx.item_tax_template,
doc=doc or ctx,
tax_template=out.item_tax_template or ctx.item_tax_template,
as_json=True,
)
@@ -528,7 +528,7 @@ def get_barcode_data(items_list=None, item_code=None):
@frappe.whitelist()
def get_item_tax_info(company, tax_category, item_codes, item_rates=None, item_tax_templates=None):
def get_item_tax_info(doc, tax_category, item_codes, item_rates=None, item_tax_templates=None):
out = {}
if item_tax_templates is None:
@@ -537,14 +537,10 @@ def get_item_tax_info(company, tax_category, item_codes, item_rates=None, item_t
if item_rates is None:
item_rates = {}
if isinstance(item_codes, str):
item_codes = json.loads(item_codes)
if isinstance(item_rates, str):
item_rates = json.loads(item_rates)
if isinstance(item_tax_templates, str):
item_tax_templates = json.loads(item_tax_templates)
doc = parse_json(doc)
item_codes = parse_json(item_codes)
item_rates = parse_json(item_rates)
item_tax_templates = parse_json(item_tax_templates)
for item_code in item_codes:
if not item_code or item_code[1] in out or not item_tax_templates.get(item_code[1]):
@@ -553,7 +549,7 @@ def get_item_tax_info(company, tax_category, item_codes, item_rates=None, item_t
out[item_code[1]] = ItemDetails()
item = frappe.get_cached_doc("Item", item_code[0])
ctx: ItemDetailsCtx = {
"company": company,
"company": doc.company,
"tax_category": tax_category,
"base_net_rate": item_rates.get(item_code[1]),
}
@@ -563,7 +559,9 @@ def get_item_tax_info(company, tax_category, item_codes, item_rates=None, item_t
get_item_tax_template(ctx, item, out[item_code[1]])
out[item_code[1]]["item_tax_rate"] = get_item_tax_map(
company, out[item_code[1]].get("item_tax_template"), as_json=True
doc=doc,
tax_template=out[item_code[1]].get("item_tax_template"),
as_json=True,
)
return out
@@ -689,12 +687,16 @@ def is_within_valid_range(ctx: ItemDetailsCtx, tax) -> bool:
@frappe.whitelist()
def get_item_tax_map(company, item_tax_template, as_json=True):
def get_item_tax_map(*, doc: str | dict | Document, tax_template: str | None = None, as_json=True):
doc = parse_json(doc)
item_tax_map = {}
if item_tax_template:
template = frappe.get_cached_doc("Item Tax Template", item_tax_template)
for t in (t for t in (doc.get("taxes") or []) if not t.set_by_item_tax_template):
item_tax_map[t.account_head] = t.rate
if tax_template:
template = frappe.get_cached_doc("Item Tax Template", tax_template)
for d in template.taxes:
if frappe.get_cached_value("Account", d.tax_type, "company") == company:
if frappe.get_cached_value("Account", d.tax_type, "company") == doc.get("company"):
item_tax_map[d.tax_type] = d.tax_rate
return json.dumps(item_tax_map) if as_json else item_tax_map