Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: item wise tax details and net amounts #43372

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
"rate",
"section_break_9",
"currency",
"net_amount",
"tax_amount",
"total",
"allocated_amount",
"column_break_13",
"base_tax_amount",
"base_net_amount",
"base_total"
],
"fields": [
Expand Down Expand Up @@ -174,12 +176,29 @@
"label": "Account Currency",
"options": "Currency",
"read_only": 1
},
{
"columns": 2,
"fieldname": "net_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Net Amount",
"options": "currency"
},
{
"fieldname": "base_net_amount",
"fieldtype": "Currency",
"label": "Net Amount (Company Currency)",
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2024-03-27 13:05:58.437605",
"modified": "2024-09-24 06:51:07.417348",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Taxes and Charges",
Expand All @@ -188,4 +207,4 @@
"sort_field": "creation",
"sort_order": "ASC",
"states": []
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class AdvanceTaxesandCharges(Document):
account_head: DF.Link
add_deduct_tax: DF.Literal["Add", "Deduct"]
allocated_amount: DF.Currency
base_net_amount: DF.Currency
base_tax_amount: DF.Currency
base_total: DF.Currency
charge_type: DF.Literal[
Expand All @@ -27,6 +28,7 @@ class AdvanceTaxesandCharges(Document):
currency: DF.Link | None
description: DF.SmallText
included_in_paid_amount: DF.Check
net_amount: DF.Currency
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,13 @@ def update_item_wise_tax_detail(consolidate_tax_row, tax_row):
if consolidated_tax_detail.get(item_code):
consolidated_tax_data = consolidated_tax_detail.get(item_code)
consolidated_tax_detail.update(
{item_code: [consolidated_tax_data[0], consolidated_tax_data[1] + tax_data[1]]}
{
item_code: [
consolidated_tax_data[0],
consolidated_tax_data[1] + tax_data[1],
consolidated_tax_data[2] + tax_data[2],
]
}
)
else:
consolidated_tax_detail.update({item_code: [tax_data[0], tax_data[1]]})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,15 @@ def test_consolidated_invoice_item_taxes(self):
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_rate, amount = item_wise_tax_detail.get("_Test Item")
tax_rate, amount, net_amount = item_wise_tax_detail.get("_Test Item")
self.assertEqual(tax_rate, 9)
self.assertEqual(amount, 9)
self.assertEqual(net_amount, 100)

tax_rate2, amount2 = item_wise_tax_detail.get("_Test Item 2")
tax_rate2, amount2, net_amount2 = item_wise_tax_detail.get("_Test Item 2")
self.assertEqual(tax_rate2, 5)
self.assertEqual(amount2, 5)
self.assertEqual(net_amount2, 100)
finally:
frappe.set_user("Administrator")
frappe.db.sql("delete from `tabPOS Profile`")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@
"dimension_col_break",
"section_break_9",
"account_currency",
"net_amount",
"tax_amount",
"tax_amount_after_discount_amount",
"total",
"column_break_14",
"base_net_amount",
"base_tax_amount",
"base_total",
"base_tax_amount_after_discount_amount",
Expand Down Expand Up @@ -233,12 +235,30 @@
"fieldtype": "Check",
"label": "Is Tax Withholding Account",
"read_only": 1
},
{
"columns": 2,
"fieldname": "net_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Net Amount",
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
"options": "currency"
},
{
"fieldname": "base_net_amount",
"fieldtype": "Currency",
"label": "Net Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-04-08 19:51:36.678551",
"modified": "2024-09-24 06:47:25.129901",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class PurchaseTaxesandCharges(Document):
account_currency: DF.Link | None
account_head: DF.Link
add_deduct_tax: DF.Literal["Add", "Deduct"]
base_net_amount: DF.Currency
base_tax_amount: DF.Currency
base_tax_amount_after_discount_amount: DF.Currency
base_total: DF.Currency
Expand All @@ -35,6 +36,7 @@ class PurchaseTaxesandCharges(Document):
included_in_print_rate: DF.Check
is_tax_withholding_account: DF.Check
item_wise_tax_detail: DF.Code | None
net_amount: DF.Currency
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
"rate",
"section_break_9",
"account_currency",
"net_amount",
"tax_amount",
"total",
"tax_amount_after_discount_amount",
"column_break_13",
"base_net_amount",
"base_tax_amount",
"base_total",
"base_tax_amount_after_discount_amount",
Expand Down Expand Up @@ -212,13 +214,30 @@
"label": "Account Currency",
"options": "Currency",
"read_only": 1
},
{
"columns": 2,
"fieldname": "net_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Net Amount",
"options": "currency"
},
{
"fieldname": "base_net_amount",
"fieldtype": "Currency",
"label": "Net Amount (Company Currency)",
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"read_only": 1
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2024-03-27 13:10:38.190993",
"modified": "2024-09-24 06:49:32.034074",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class SalesTaxesandCharges(Document):

account_currency: DF.Link | None
account_head: DF.Link
base_net_amount: DF.Currency
base_tax_amount: DF.Currency
base_tax_amount_after_discount_amount: DF.Currency
base_total: DF.Currency
Expand All @@ -33,6 +34,7 @@ class SalesTaxesandCharges(Document):
included_in_paid_amount: DF.Check
included_in_print_rate: DF.Check
item_wise_tax_detail: DF.Code | None
net_amount: DF.Currency
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data
Expand Down
53 changes: 37 additions & 16 deletions erpnext/controllers/taxes_and_totals.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ def initialize_taxes(self):
tax.item_wise_tax_detail = {}

tax_fields = [
"net_amount",
"total",
"tax_amount_after_discount_amount",
"tax_amount_for_current_item",
Expand Down Expand Up @@ -380,9 +381,12 @@ def calculate_taxes(self):
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
for i, tax in enumerate(self.doc.get("taxes")):
# tax_amount represents the amount of tax for the current step
current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map)
current_net_amount, current_tax_amount = self.get_current_tax_and_net_amount(
item, tax, item_tax_map
)
if frappe.flags.round_row_wise_tax:
current_tax_amount = flt(current_tax_amount, tax.precision("tax_amount"))
current_net_amount = flt(current_net_amount, tax.precision("net_amount"))

# Adjust divisional loss to the last item
if tax.charge_type == "Actual":
Expand All @@ -395,6 +399,7 @@ def calculate_taxes(self):
self.discount_amount_applied and self.doc.apply_discount_on == "Grand Total"
):
tax.tax_amount += current_tax_amount
tax.net_amount += current_net_amount

# store tax_amount for current item as it will be used for
# charge type = 'On Previous Row Amount'
Expand All @@ -419,7 +424,9 @@ def calculate_taxes(self):
# set precision in the last item iteration
if n == len(self._items) - 1:
self.round_off_totals(tax)
self._set_in_company_currency(tax, ["tax_amount", "tax_amount_after_discount_amount"])
self._set_in_company_currency(
tax, ["tax_amount", "tax_amount_after_discount_amount", "net_amount"]
)

self.round_off_base_values(tax)
self.set_cumulative_total(i, tax)
Expand Down Expand Up @@ -462,9 +469,10 @@ def set_cumulative_total(self, row_idx, tax):
else:
tax.total = flt(self.doc.get("taxes")[row_idx - 1].total + tax_amount, tax.precision("total"))

def get_current_tax_amount(self, item, tax, item_tax_map):
def get_current_tax_and_net_amount(self, item, tax, item_tax_map):
tax_rate = self._get_tax_rate(tax, item_tax_map)
current_tax_amount = 0.0
current_net_amount = 0.0

if tax.charge_type == "Actual":
# distribute the tax amount proportionally to each item row
Expand All @@ -473,55 +481,68 @@ def get_current_tax_amount(self, item, tax, item_tax_map):
if tax.get("is_tax_withholding_account") and item.meta.get_field("apply_tds"):
if not item.get("apply_tds") or not self.doc.tax_withholding_net_total:
current_tax_amount = 0.0
current_net_amount = 0.0
else:
current_tax_amount = item.net_amount * actual / self.doc.tax_withholding_net_total
current_net_amount = item.net_amount
current_tax_amount = current_net_amount * actual / self.doc.tax_withholding_net_total
else:
current_net_amount = item.net_amount
current_tax_amount = (
item.net_amount * actual / self.doc.net_total if self.doc.net_total else 0.0
current_net_amount * actual / self.doc.net_total if self.doc.net_total else 0.0
)

elif tax.charge_type == "On Net Total":
current_tax_amount = (tax_rate / 100.0) * item.net_amount
current_net_amount = item.net_amount
current_tax_amount = (tax_rate / 100.0) * current_net_amount
elif tax.charge_type == "On Previous Row Amount":
current_tax_amount = (tax_rate / 100.0) * self.doc.get("taxes")[
cint(tax.row_id) - 1
].tax_amount_for_current_item
current_net_amount = self.doc.get("taxes")[cint(tax.row_id) - 1].tax_amount_for_current_item
current_tax_amount = (tax_rate / 100.0) * current_net_amount
elif tax.charge_type == "On Previous Row Total":
current_tax_amount = (tax_rate / 100.0) * self.doc.get("taxes")[
cint(tax.row_id) - 1
].grand_total_for_current_item
current_net_amount = self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item
current_tax_amount = (tax_rate / 100.0) * current_net_amount
elif tax.charge_type == "On Item Quantity":
# don't sum current net amount due to the field being a currency field
current_tax_amount = tax_rate * item.qty

if not (self.doc.get("is_consolidated") or tax.get("dont_recompute_tax")):
self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount)
self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount, current_net_amount)

return current_tax_amount
return current_net_amount, current_tax_amount

def set_item_wise_tax(self, item, tax, tax_rate, current_tax_amount):
def set_item_wise_tax(self, item, tax, tax_rate, current_tax_amount, current_net_amount):
# store tax breakup for each item
key = item.item_code or item.item_name
item_wise_tax_amount = current_tax_amount * self.doc.conversion_rate
if tax.charge_type != "On Item Quantity":
item_wise_net_amount = current_net_amount * self.doc.conversion_rate
else:
# here, as opposed to above, do record the "net amount" as the json is an untyped datasctructure
item_wise_net_amount = item.qty
if frappe.flags.round_row_wise_tax:
item_wise_tax_amount = flt(item_wise_tax_amount, tax.precision("tax_amount"))
item_wise_net_amount = flt(item_wise_net_amount, tax.precision("net_amount"))
if tax.item_wise_tax_detail.get(key):
item_wise_tax_amount += flt(tax.item_wise_tax_detail[key][1], tax.precision("tax_amount"))
item_wise_net_amount += flt(tax.item_wise_tax_detail[key][2], tax.precision("net_amount"))
tax.item_wise_tax_detail[key] = [
tax_rate,
flt(item_wise_tax_amount, tax.precision("tax_amount")),
flt(item_wise_net_amount, tax.precision("net_amount")),
]
else:
if tax.item_wise_tax_detail.get(key):
item_wise_tax_amount += tax.item_wise_tax_detail[key][1]
item_wise_net_amount += tax.item_wise_tax_detail[key][2]

tax.item_wise_tax_detail[key] = [tax_rate, flt(item_wise_tax_amount)]
tax.item_wise_tax_detail[key] = [tax_rate, item_wise_tax_amount, item_wise_net_amount]

def round_off_totals(self, tax):
if tax.account_head in frappe.flags.round_off_applicable_accounts:
tax.tax_amount = round(tax.tax_amount, 0)
tax.tax_amount_after_discount_amount = round(tax.tax_amount_after_discount_amount, 0)

tax.tax_amount = flt(tax.tax_amount, tax.precision("tax_amount"))
tax.net_amount = flt(tax.net_amount, tax.precision("net_amount"))
tax.tax_amount_after_discount_amount = flt(
tax.tax_amount_after_discount_amount, tax.precision("tax_amount")
)
Expand Down
Loading
Loading