@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`")
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -79,7 +79,7 @@ class TestTaxesAndTotals(FrappeTestCase):
|
||||
"rate": 50,
|
||||
},
|
||||
)
|
||||
|
||||
self.doc.set_missing_item_details()
|
||||
calculate_taxes_and_totals(self.doc)
|
||||
|
||||
expected_values = {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user