mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-27 08:54:45 +00:00
fix: Tax breakup based on items, missing GST fields (#27524)
* fix: Tax breakup based on items
* fix: added gst fields,warehouse validation to pos inv,patch
* fix: tax breakup test fix, eway bill hsn fix
Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
(cherry picked from commit d49346ac45)
# Conflicts:
# erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
# erpnext/patches.txt
# erpnext/patches/v13_0/gst_fields_for_pos_invoice.py
# erpnext/regional/india/setup.py
# erpnext/regional/india/utils.py
This commit is contained in:
@@ -1908,8 +1908,27 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
itemised_tax, itemised_taxable_amount = get_itemised_tax_breakup_data(si)
|
itemised_tax, itemised_taxable_amount = get_itemised_tax_breakup_data(si)
|
||||||
|
|
||||||
expected_itemised_tax = {
|
expected_itemised_tax = {
|
||||||
|
<<<<<<< HEAD
|
||||||
"_Test Item": {"Service Tax": {"tax_rate": 10.0, "tax_amount": 1000.0}},
|
"_Test Item": {"Service Tax": {"tax_rate": 10.0, "tax_amount": 1000.0}},
|
||||||
"_Test Item 2": {"Service Tax": {"tax_rate": 10.0, "tax_amount": 500.0}},
|
"_Test Item 2": {"Service Tax": {"tax_rate": 10.0, "tax_amount": 500.0}},
|
||||||
|
=======
|
||||||
|
"_Test Item": {
|
||||||
|
"Service Tax": {
|
||||||
|
"tax_rate": 10.0,
|
||||||
|
"tax_amount": 1000.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"_Test Item 2": {
|
||||||
|
"Service Tax": {
|
||||||
|
"tax_rate": 10.0,
|
||||||
|
"tax_amount": 500.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expected_itemised_taxable_amount = {
|
||||||
|
"_Test Item": 10000.0,
|
||||||
|
"_Test Item 2": 5000.0
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
}
|
}
|
||||||
expected_itemised_taxable_amount = {"_Test Item": 10000.0, "_Test Item 2": 5000.0}
|
expected_itemised_taxable_amount = {"_Test Item": 10000.0, "_Test Item 2": 5000.0}
|
||||||
|
|
||||||
|
|||||||
@@ -315,8 +315,12 @@ erpnext.patches.v13_0.create_website_items #30-09-2021
|
|||||||
erpnext.patches.v13_0.populate_e_commerce_settings
|
erpnext.patches.v13_0.populate_e_commerce_settings
|
||||||
erpnext.patches.v13_0.make_homepage_products_website_items
|
erpnext.patches.v13_0.make_homepage_products_website_items
|
||||||
erpnext.patches.v13_0.update_dates_in_tax_withholding_category
|
erpnext.patches.v13_0.update_dates_in_tax_withholding_category
|
||||||
|
<<<<<<< HEAD
|
||||||
erpnext.patches.v13_0.fix_invoice_statuses
|
erpnext.patches.v13_0.fix_invoice_statuses
|
||||||
erpnext.patches.v13_0.replace_supplier_item_group_with_party_specific_item
|
erpnext.patches.v13_0.replace_supplier_item_group_with_party_specific_item
|
||||||
|
=======
|
||||||
|
erpnext.patches.v14_0.update_opportunity_currency_fields
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
erpnext.patches.v13_0.gst_fields_for_pos_invoice
|
erpnext.patches.v13_0.gst_fields_for_pos_invoice
|
||||||
erpnext.patches.v13_0.create_accounting_dimensions_in_pos_doctypes
|
erpnext.patches.v13_0.create_accounting_dimensions_in_pos_doctypes
|
||||||
erpnext.patches.v13_0.create_custom_field_for_finance_book
|
erpnext.patches.v13_0.create_custom_field_for_finance_book
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
||||||
|
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
|
<<<<<<< HEAD
|
||||||
company = frappe.get_all("Company", filters={"country": "India"}, fields=["name"])
|
company = frappe.get_all("Company", filters={"country": "India"}, fields=["name"])
|
||||||
if not company:
|
if not company:
|
||||||
return
|
return
|
||||||
@@ -85,3 +91,42 @@ def execute():
|
|||||||
}
|
}
|
||||||
|
|
||||||
create_custom_fields(custom_fields, update=True)
|
create_custom_fields(custom_fields, update=True)
|
||||||
|
=======
|
||||||
|
company = frappe.get_all('Company', filters = {'country': 'India'}, fields=['name'])
|
||||||
|
if not company:
|
||||||
|
return
|
||||||
|
|
||||||
|
hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
|
||||||
|
fieldtype='Data', fetch_from='item_code.gst_hsn_code', insert_after='description',
|
||||||
|
allow_on_submit=1, print_hide=1, fetch_if_empty=1)
|
||||||
|
nil_rated_exempt = dict(fieldname='is_nil_exempt', label='Is Nil Rated or Exempted',
|
||||||
|
fieldtype='Check', fetch_from='item_code.is_nil_exempt', insert_after='gst_hsn_code',
|
||||||
|
print_hide=1)
|
||||||
|
is_non_gst = dict(fieldname='is_non_gst', label='Is Non GST',
|
||||||
|
fieldtype='Check', fetch_from='item_code.is_non_gst', insert_after='is_nil_exempt',
|
||||||
|
print_hide=1)
|
||||||
|
taxable_value = dict(fieldname='taxable_value', label='Taxable Value',
|
||||||
|
fieldtype='Currency', insert_after='base_net_amount', hidden=1, options="Company:company:default_currency",
|
||||||
|
print_hide=1)
|
||||||
|
sales_invoice_gst_fields = [
|
||||||
|
dict(fieldname='billing_address_gstin', label='Billing Address GSTIN',
|
||||||
|
fieldtype='Data', insert_after='customer_address', read_only=1,
|
||||||
|
fetch_from='customer_address.gstin', print_hide=1),
|
||||||
|
dict(fieldname='customer_gstin', label='Customer GSTIN',
|
||||||
|
fieldtype='Data', insert_after='shipping_address_name',
|
||||||
|
fetch_from='shipping_address_name.gstin', print_hide=1),
|
||||||
|
dict(fieldname='place_of_supply', label='Place of Supply',
|
||||||
|
fieldtype='Data', insert_after='customer_gstin',
|
||||||
|
print_hide=1, read_only=1),
|
||||||
|
dict(fieldname='company_gstin', label='Company GSTIN',
|
||||||
|
fieldtype='Data', insert_after='company_address',
|
||||||
|
fetch_from='company_address.gstin', print_hide=1, read_only=1),
|
||||||
|
]
|
||||||
|
|
||||||
|
custom_fields = {
|
||||||
|
'POS Invoice': sales_invoice_gst_fields,
|
||||||
|
'POS Invoice Item': [hsn_sac_field, nil_rated_exempt, is_non_gst, taxable_value],
|
||||||
|
}
|
||||||
|
|
||||||
|
create_custom_fields(custom_fields, update=True)
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
|
|||||||
@@ -916,6 +916,7 @@ def get_custom_fields():
|
|||||||
read_only=1,
|
read_only=1,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
<<<<<<< HEAD
|
||||||
"Purchase Invoice": purchase_invoice_gst_category
|
"Purchase Invoice": purchase_invoice_gst_category
|
||||||
+ invoice_gst_fields
|
+ invoice_gst_fields
|
||||||
+ purchase_invoice_itc_fields
|
+ purchase_invoice_itc_fields
|
||||||
@@ -974,6 +975,43 @@ def get_custom_fields():
|
|||||||
insert_after="description",
|
insert_after="description",
|
||||||
options="\nProvident Fund\nAdditional Provident Fund\nProvident Fund Loan\nProfessional Tax",
|
options="\nProvident Fund\nAdditional Provident Fund\nProvident Fund Loan\nProfessional Tax",
|
||||||
depends_on='eval:doc.type == "Deduction"',
|
depends_on='eval:doc.type == "Deduction"',
|
||||||
|
=======
|
||||||
|
'Purchase Invoice': purchase_invoice_gst_category + invoice_gst_fields + purchase_invoice_itc_fields + purchase_invoice_gst_fields,
|
||||||
|
'Purchase Order': purchase_invoice_gst_fields,
|
||||||
|
'Purchase Receipt': purchase_invoice_gst_fields,
|
||||||
|
'Sales Invoice': sales_invoice_gst_category + invoice_gst_fields + sales_invoice_shipping_fields + sales_invoice_gst_fields + si_ewaybill_fields,
|
||||||
|
'POS Invoice': sales_invoice_gst_fields,
|
||||||
|
'Delivery Note': sales_invoice_gst_fields + ewaybill_fields + sales_invoice_shipping_fields + delivery_note_gst_category,
|
||||||
|
'Payment Entry': payment_entry_fields,
|
||||||
|
'Journal Entry': journal_entry_fields,
|
||||||
|
'Sales Order': sales_invoice_gst_fields,
|
||||||
|
'Tax Category': inter_state_gst_field,
|
||||||
|
'Item': [
|
||||||
|
dict(fieldname='gst_hsn_code', label='HSN/SAC',
|
||||||
|
fieldtype='Link', options='GST HSN Code', insert_after='item_group'),
|
||||||
|
dict(fieldname='is_nil_exempt', label='Is Nil Rated or Exempted',
|
||||||
|
fieldtype='Check', insert_after='gst_hsn_code'),
|
||||||
|
dict(fieldname='is_non_gst', label='Is Non GST ',
|
||||||
|
fieldtype='Check', insert_after='is_nil_exempt')
|
||||||
|
],
|
||||||
|
'Quotation Item': [hsn_sac_field, nil_rated_exempt, is_non_gst],
|
||||||
|
'Supplier Quotation Item': [hsn_sac_field, nil_rated_exempt, is_non_gst],
|
||||||
|
'Sales Order Item': [hsn_sac_field, nil_rated_exempt, is_non_gst],
|
||||||
|
'Delivery Note Item': [hsn_sac_field, nil_rated_exempt, is_non_gst],
|
||||||
|
'Sales Invoice Item': [hsn_sac_field, nil_rated_exempt, is_non_gst, taxable_value],
|
||||||
|
'POS Invoice Item': [hsn_sac_field, nil_rated_exempt, is_non_gst, taxable_value],
|
||||||
|
'Purchase Order Item': [hsn_sac_field, nil_rated_exempt, is_non_gst],
|
||||||
|
'Purchase Receipt Item': [hsn_sac_field, nil_rated_exempt, is_non_gst],
|
||||||
|
'Purchase Invoice Item': [hsn_sac_field, nil_rated_exempt, is_non_gst, taxable_value],
|
||||||
|
'Material Request Item': [hsn_sac_field, nil_rated_exempt, is_non_gst],
|
||||||
|
'Salary Component': [
|
||||||
|
dict(fieldname= 'component_type',
|
||||||
|
label= 'Component Type',
|
||||||
|
fieldtype= 'Select',
|
||||||
|
insert_after= 'description',
|
||||||
|
options= "\nProvident Fund\nAdditional Provident Fund\nProvident Fund Loan\nProfessional Tax",
|
||||||
|
depends_on = 'eval:doc.type == "Deduction"'
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
"Employee": [
|
"Employee": [
|
||||||
|
|||||||
@@ -162,7 +162,10 @@ def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
|
|||||||
else:
|
else:
|
||||||
return [_("Item"), _("Taxable Amount")] + tax_accounts
|
return [_("Item"), _("Taxable Amount")] + tax_accounts
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
def get_itemised_tax_breakup_data(doc, account_wise=False, hsn_wise=False):
|
def get_itemised_tax_breakup_data(doc, account_wise=False, hsn_wise=False):
|
||||||
itemised_tax = get_itemised_tax(doc.taxes, with_tax_account=account_wise)
|
itemised_tax = get_itemised_tax(doc.taxes, with_tax_account=account_wise)
|
||||||
|
|
||||||
@@ -171,22 +174,34 @@ def get_itemised_tax_breakup_data(doc, account_wise=False, hsn_wise=False):
|
|||||||
if not frappe.get_meta(doc.doctype + " Item").has_field("gst_hsn_code"):
|
if not frappe.get_meta(doc.doctype + " Item").has_field("gst_hsn_code"):
|
||||||
return itemised_tax, itemised_taxable_amount
|
return itemised_tax, itemised_taxable_amount
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
hsn_wise_in_gst_settings = frappe.db.get_single_value("GST Settings", "hsn_wise_tax_breakup")
|
hsn_wise_in_gst_settings = frappe.db.get_single_value("GST Settings", "hsn_wise_tax_breakup")
|
||||||
|
|
||||||
tax_breakup_hsn_wise = hsn_wise or hsn_wise_in_gst_settings
|
tax_breakup_hsn_wise = hsn_wise or hsn_wise_in_gst_settings
|
||||||
if tax_breakup_hsn_wise:
|
if tax_breakup_hsn_wise:
|
||||||
|
=======
|
||||||
|
if hsn_wise:
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
item_hsn_map = frappe._dict()
|
item_hsn_map = frappe._dict()
|
||||||
for d in doc.items:
|
for d in doc.items:
|
||||||
item_hsn_map.setdefault(d.item_code or d.item_name, d.get("gst_hsn_code"))
|
item_hsn_map.setdefault(d.item_code or d.item_name, d.get("gst_hsn_code"))
|
||||||
|
|
||||||
hsn_tax = {}
|
hsn_tax = {}
|
||||||
for item, taxes in itemised_tax.items():
|
for item, taxes in itemised_tax.items():
|
||||||
|
<<<<<<< HEAD
|
||||||
item_or_hsn = item if not tax_breakup_hsn_wise else item_hsn_map.get(item)
|
item_or_hsn = item if not tax_breakup_hsn_wise else item_hsn_map.get(item)
|
||||||
|
=======
|
||||||
|
item_or_hsn = item if not hsn_wise else item_hsn_map.get(item)
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
hsn_tax.setdefault(item_or_hsn, frappe._dict())
|
hsn_tax.setdefault(item_or_hsn, frappe._dict())
|
||||||
for tax_desc, tax_detail in taxes.items():
|
for tax_desc, tax_detail in taxes.items():
|
||||||
key = tax_desc
|
key = tax_desc
|
||||||
if account_wise:
|
if account_wise:
|
||||||
|
<<<<<<< HEAD
|
||||||
key = tax_detail.get("tax_account")
|
key = tax_detail.get("tax_account")
|
||||||
|
=======
|
||||||
|
key = tax_detail.get('tax_account')
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
hsn_tax[item_or_hsn].setdefault(key, {"tax_rate": 0, "tax_amount": 0})
|
hsn_tax[item_or_hsn].setdefault(key, {"tax_rate": 0, "tax_amount": 0})
|
||||||
hsn_tax[item_or_hsn][key]["tax_rate"] = tax_detail.get("tax_rate")
|
hsn_tax[item_or_hsn][key]["tax_rate"] = tax_detail.get("tax_rate")
|
||||||
hsn_tax[item_or_hsn][key]["tax_amount"] += tax_detail.get("tax_amount")
|
hsn_tax[item_or_hsn][key]["tax_amount"] += tax_detail.get("tax_amount")
|
||||||
@@ -194,7 +209,11 @@ def get_itemised_tax_breakup_data(doc, account_wise=False, hsn_wise=False):
|
|||||||
# set taxable amount
|
# set taxable amount
|
||||||
hsn_taxable_amount = frappe._dict()
|
hsn_taxable_amount = frappe._dict()
|
||||||
for item in itemised_taxable_amount:
|
for item in itemised_taxable_amount:
|
||||||
|
<<<<<<< HEAD
|
||||||
item_or_hsn = item if not tax_breakup_hsn_wise else item_hsn_map.get(item)
|
item_or_hsn = item if not tax_breakup_hsn_wise else item_hsn_map.get(item)
|
||||||
|
=======
|
||||||
|
item_or_hsn = item if not hsn_wise else item_hsn_map.get(item)
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
hsn_taxable_amount.setdefault(item_or_hsn, 0)
|
hsn_taxable_amount.setdefault(item_or_hsn, 0)
|
||||||
hsn_taxable_amount[item_or_hsn] += itemised_taxable_amount.get(item)
|
hsn_taxable_amount[item_or_hsn] += itemised_taxable_amount.get(item)
|
||||||
|
|
||||||
@@ -746,9 +765,14 @@ def get_address_details(data, doc, company_address, billing_address, dispatch_ad
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
def get_item_list(data, doc, hsn_wise=False):
|
def get_item_list(data, doc, hsn_wise=False):
|
||||||
for attr in ["cgstValue", "sgstValue", "igstValue", "cessValue", "OthValue"]:
|
for attr in ["cgstValue", "sgstValue", "igstValue", "cessValue", "OthValue"]:
|
||||||
|
=======
|
||||||
|
def get_item_list(data, doc, hsn_wise=False):
|
||||||
|
for attr in ['cgstValue', 'sgstValue', 'igstValue', 'cessValue', 'OthValue']:
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
data[attr] = 0
|
data[attr] = 0
|
||||||
|
|
||||||
gst_accounts = get_gst_accounts(doc.company, account_wise=True)
|
gst_accounts = get_gst_accounts(doc.company, account_wise=True)
|
||||||
@@ -758,11 +782,17 @@ def get_item_list(data, doc, hsn_wise=False):
|
|||||||
"igst_account": ["igstRate", "igstValue"],
|
"igst_account": ["igstRate", "igstValue"],
|
||||||
"cess_account": ["cessRate", "cessValue"],
|
"cess_account": ["cessRate", "cessValue"],
|
||||||
}
|
}
|
||||||
|
<<<<<<< HEAD
|
||||||
item_data_attrs = ["sgstRate", "cgstRate", "igstRate", "cessRate", "cessNonAdvol"]
|
item_data_attrs = ["sgstRate", "cgstRate", "igstRate", "cessRate", "cessNonAdvol"]
|
||||||
hsn_wise_charges, hsn_taxable_amount = get_itemised_tax_breakup_data(
|
hsn_wise_charges, hsn_taxable_amount = get_itemised_tax_breakup_data(
|
||||||
doc, account_wise=True, hsn_wise=hsn_wise
|
doc, account_wise=True, hsn_wise=hsn_wise
|
||||||
)
|
)
|
||||||
for item_or_hsn, taxable_amount in hsn_taxable_amount.items():
|
for item_or_hsn, taxable_amount in hsn_taxable_amount.items():
|
||||||
|
=======
|
||||||
|
item_data_attrs = ['sgstRate', 'cgstRate', 'igstRate', 'cessRate', 'cessNonAdvol']
|
||||||
|
hsn_wise_charges, hsn_taxable_amount = get_itemised_tax_breakup_data(doc, account_wise=True, hsn_wise=hsn_wise)
|
||||||
|
for hsn_code, taxable_amount in hsn_taxable_amount.items():
|
||||||
|
>>>>>>> d49346ac45 (fix: Tax breakup based on items, missing GST fields (#27524))
|
||||||
item_data = frappe._dict()
|
item_data = frappe._dict()
|
||||||
if not item_or_hsn:
|
if not item_or_hsn:
|
||||||
frappe.throw(_("GST HSN Code does not exist for one or more items"))
|
frappe.throw(_("GST HSN Code does not exist for one or more items"))
|
||||||
|
|||||||
Reference in New Issue
Block a user