Apply GST based on Origin and Place of supply GST Code (#14288)

* Add new gst field in Taxes and Charges template - is_inter_state

* Add a patch

* Add a regional function to fetch taxes on the basis of GSTin

* Add regional function to hooks.py

* Fetch taxes for Purchase Invoice on the basis of Supplier GSTIN

* Fixes in the setup.py for India region

* Set is_inter_state field

For the existing Taxes and Charges templates, if an account_head with igst account (which is set in GST Settings) is found, set the checkbox and also check if it doesn't have a cgst account.

* Fix as per review comment
This commit is contained in:
Shreya Shah
2018-06-05 11:27:53 +05:30
committed by Nabin Hait
parent 5103454642
commit 4fa600a8dd
6 changed files with 133 additions and 24 deletions

View File

@@ -113,10 +113,10 @@ def make_custom_fields():
purchase_invoice_gst_fields = [
dict(fieldname='supplier_gstin', label='Supplier GSTIN',
fieldtype='Data', insert_after='supplier_address',
options='supplier_address.gstin', print_hide=1),
fetch_from='supplier_address.gstin', print_hide=1),
dict(fieldname='company_gstin', label='Company GSTIN',
fieldtype='Data', insert_after='shipping_address',
options='shipping_address.gstin', print_hide=1),
fieldtype='Data', insert_after='shipping_address_display',
fetch_from='shipping_address.gstin', print_hide=1),
dict(fieldname='place_of_supply', label='Place of Supply',
fieldtype='Data', insert_after='shipping_address',
print_hide=1, read_only=0),
@@ -136,16 +136,16 @@ def make_custom_fields():
sales_invoice_gst_fields = [
dict(fieldname='billing_address_gstin', label='Billing Address GSTIN',
fieldtype='Data', insert_after='customer_address',
options='customer_address.gstin', print_hide=1),
fetch_from='customer_address.gstin', print_hide=1),
dict(fieldname='customer_gstin', label='Customer GSTIN',
fieldtype='Data', insert_after='shipping_address',
options='shipping_address_name.gstin', print_hide=1),
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=0),
dict(fieldname='company_gstin', label='Company GSTIN',
fieldtype='Data', insert_after='company_address',
options='company_address.gstin', print_hide=1),
fetch_from='company_address.gstin', print_hide=1),
dict(fieldname='port_code', label='Port Code',
fieldtype='Data', insert_after='reason_for_issuing_document', print_hide=1,
depends_on="eval:doc.invoice_type=='Export' "),
@@ -157,6 +157,11 @@ def make_custom_fields():
depends_on="eval:doc.invoice_type=='Export' ")
]
inter_state_gst_field = [
dict(fieldname='is_inter_state', label='Is Inter State',
fieldtype='Check', insert_after='disabled', print_hide=1)
]
custom_fields = {
'Address': [
dict(fieldname='gstin', label='Party GSTIN', fieldtype='Data',
@@ -168,7 +173,9 @@ def make_custom_fields():
],
'Purchase Invoice': invoice_gst_fields + purchase_invoice_gst_fields,
'Sales Invoice': invoice_gst_fields + sales_invoice_gst_fields,
"Delivery Note": sales_invoice_gst_fields,
'Delivery Note': sales_invoice_gst_fields,
'Sales Taxes and Charges Template': inter_state_gst_field,
'Purchase Taxes and Charges Template': inter_state_gst_field,
'Item': [
dict(fieldname='gst_hsn_code', label='HSN/SAC',
fieldtype='Link', options='GST HSN Code', insert_after='item_group'),

View File

@@ -3,6 +3,7 @@ from frappe import _
from frappe.utils import cstr
from erpnext.regional.india import states, state_numbers
from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_taxable_amount
from erpnext.controllers.accounts_controller import get_taxes_and_charges
def validate_gstin_for_india(doc, method):
if not hasattr(doc, 'gstin'):
@@ -61,19 +62,48 @@ def get_itemised_tax_breakup_data(doc):
return hsn_tax, hsn_taxable_amount
def set_place_of_supply(doc, method):
if not frappe.get_meta('Address').has_field('gst_state'): return
if doc.doctype in ("Sales Invoice", "Delivery Note"):
address_name = doc.shipping_address_name or doc.customer_address
elif doc.doctype == "Purchase Invoice":
address_name = doc.shipping_address or doc.supplier_address
if address_name:
address = frappe.db.get_value("Address", address_name, ["gst_state", "gst_state_number"], as_dict=1)
doc.place_of_supply = cstr(address.gst_state_number) + "-" + cstr(address.gst_state)
def set_place_of_supply(doc, method=None):
doc.place_of_supply = get_place_of_supply(doc, doc.doctype)
# don't remove this function it is used in tests
def test_method():
'''test function'''
return 'overridden'
def get_place_of_supply(out, doctype):
if not frappe.get_meta('Address').has_field('gst_state'): return
if doctype in ("Sales Invoice", "Delivery Note"):
address_name = out.shipping_address_name or out.customer_address
elif doctype == "Purchase Invoice":
address_name = out.shipping_address or out.supplier_address
if address_name:
address = frappe.db.get_value("Address", address_name, ["gst_state", "gst_state_number"], as_dict=1)
return cstr(address.gst_state_number) + "-" + cstr(address.gst_state)
def get_regional_address_details(out, doctype, company):
out.place_of_supply = get_place_of_supply(out, doctype)
if not out.place_of_supply: return
if doctype in ("Sales Invoice", "Delivery Note"):
master_doctype = "Sales Taxes and Charges Template"
if not (out.company_gstin or out.place_of_supply):
return
else:
master_doctype = "Purchase Taxes and Charges Template"
if not (out.supplier_gstin or out.place_of_supply):
return
if doctype in ("Sales Invoice", "Delivery Note") and out.company_gstin[:2] != out.place_of_supply[:2]\
or (doctype == "Purchase Invoice" and out.supplier_gstin[:2] != out.place_of_supply[:2]):
default_tax = frappe.db.get_value(master_doctype, {"company": company, "is_inter_state":1, "disabled":0})
else:
default_tax = frappe.db.get_value(master_doctype, {"company": company, "disabled":0, "is_default": 1})
if not default_tax:
return
out["taxes_and_charges"] = default_tax
out.taxes = get_taxes_and_charges(master_doctype, default_tax)