Skip to content
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
2 changes: 2 additions & 0 deletions india_compliance/gst_india/constants/e_waybill.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
}
PERMITTED_DOCTYPES = list(ADDRESS_FIELDS.keys())

BUYING_DOCTYPES = {doctype for doctype, address in ADDRESS_FIELDS.items() if address is buying_address}

CANCEL_REASON_CODES = {
"Duplicate": "1",
"Order Cancelled": "2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def test_get_address_details(self):
"city": "Test City",
"pincode": 380015,
"country_code": None,
"gst_category": "Registered Regular",
},
)

Expand Down
29 changes: 18 additions & 11 deletions india_compliance/gst_india/utils/e_waybill.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
)
from india_compliance.gst_india.constants.e_waybill import (
ADDRESS_FIELDS,
BUYING_DOCTYPES,
CANCEL_REASON_CODES,
CONSIGNMENT_STATUS,
EXTEND_VALIDITY_REASON_CODES,
Expand Down Expand Up @@ -1657,10 +1658,16 @@ def set_party_address_details(self):
self.bill_from = self.get_address_details(address.bill_from)

# Defaults
# billing state is changed for SEZ, hence copy()
self.ship_to = self.bill_to.copy()
self.ship_from = self.bill_from.copy()

# for SEZ, e-Waybill API expects billing state as 96 - Other Countries
# only billing state (fromStateCode/toStateCode), not shipping (actFromStateCode/actToStateCode)
# ERROR CODE: 641, 642
for side in (self.bill_from, self.bill_to):
if side.gst_category == "SEZ":
side.state_number = 96

if has_different_to_address and has_different_from_address:
transaction_type = 4
self.ship_to = self.get_address_details(address.ship_to)
Expand All @@ -1679,11 +1686,7 @@ def set_party_address_details(self):
to_party = self.transaction_details.party_name
from_party = self.transaction_details.company_name

if self.doc.doctype in (
"Purchase Invoice",
"Purchase Receipt",
"Subcontracting Receipt",
):
if self.doc.doctype in BUYING_DOCTYPES:
to_party, from_party = from_party, to_party

if self.doc.get("is_return"):
Expand All @@ -1692,9 +1695,6 @@ def set_party_address_details(self):
self.bill_to.legal_name = to_party or self.bill_to.address_title
self.bill_from.legal_name = from_party or self.bill_from.address_title

if self.doc.gst_category == "SEZ":
self.bill_to.state_number = 96

def get_address_details(self, *args, **kwargs):
address_details = super().get_address_details(*args, **kwargs)
address_details.state_number = int(address_details.state_number)
Expand Down Expand Up @@ -1728,6 +1728,7 @@ def get_transaction_data(self):
if self.sandbox_mode:
REGISTERED_GSTIN = "05AAACG2115R1ZN"
OTHER_GSTIN = "05AAACG2140A1ZL"
SEZ_GSTIN = "27AAJCS5738D1Z6"

self.transaction_details.update(
{
Expand Down Expand Up @@ -1766,12 +1767,18 @@ def _get_sandbox_gstin(address, key):
if address.gstin == "URP":
return address.gstin

return sandbox_gstin.get((self.doc.doctype, self.doc.get("is_return") or 0))[key]
gstin = sandbox_gstin.get((self.doc.doctype, self.doc.get("is_return") or 0))[key]

# SEZ party (non-company side) needs a different GSTIN
if address.gst_category == "SEZ" and gstin == OTHER_GSTIN:
return SEZ_GSTIN

return gstin

self.bill_from.gstin = _get_sandbox_gstin(self.bill_from, 0)
self.bill_to.gstin = _get_sandbox_gstin(self.bill_to, 1)

if self.doc.get("is_return"):
if self.doc.get("is_return") or self.bill_to.gst_category == "SEZ":
to_state_code = self.bill_to.state_number
else:
to_state_code = int(self.transaction_details.pos_state_code)
Expand Down
111 changes: 111 additions & 0 deletions india_compliance/gst_india/utils/test_e_waybill.py
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,117 @@ def test_e_waybill_for_inter_state_sales_return(self):
self.assertEqual(e_waybill_data.get("supplyType"), "I")
self.assertEqual(e_waybill_data.get("subSupplyType"), 7)

@change_settings("GST Settings", {"enable_overseas_transactions": 1})
def test_e_waybill_for_sez_outward_invoice(self):
si = create_sales_invoice(
vehicle_no="GJ07DL9009",
company_address="_Test Indian Registered Company-Billing",
customer_address="_Test Registered Customer-Billing-1",
is_out_state=1,
is_export_with_gst=1,
)

e_waybill_data = EWaybillData(si).get_data()

self.assertEqual(e_waybill_data.get("toStateCode"), 96)
self.assertEqual(e_waybill_data.get("fromStateCode"), 24)

@change_settings("GST Settings", {"enable_overseas_transactions": 1})
def test_e_waybill_for_sez_sales_return(self):
si = create_sales_invoice(
vehicle_no="GJ07DL9009",
company_address="_Test Indian Registered Company-Billing",
customer_address="_Test Registered Customer-Billing-1",
is_out_state=1,
is_export_with_gst=1,
)

credit_note = make_return_doc("Sales Invoice", si.name)
credit_note.vehicle_no = "GJ07DL9009"
credit_note.save()
credit_note.submit()

e_waybill_data = EWaybillData(credit_note).get_data()

self.assertEqual(e_waybill_data.get("fromStateCode"), 96)
self.assertEqual(e_waybill_data.get("toStateCode"), 24)

@change_settings("GST Settings", {"enable_e_waybill_for_sc": 1})
def test_e_waybill_for_sez_stock_entry(self):
se = create_transaction(
doctype="Stock Entry",
stock_entry_type="Send to Subcontractor",
purpose="Send to Subcontractor",
bill_from_address="_Test Indian Registered Company-Billing",
bill_to_address="_Test Registered Customer-Billing-1",
vehicle_no="GJ07DL9009",
items=[
{
"item_code": "_Test Trading Goods 1",
"qty": 1,
"gst_hsn_code": "61149090",
"s_warehouse": "Finished Goods - _TIRC",
"t_warehouse": "Goods In Transit - _TIRC",
"amount": 100,
"taxable_value": 100,
}
],
company="_Test Indian Registered Company",
base_grand_total=100,
)

# reload to trigger onload which sets company_gstin, supplier_gstin
se = load_doc("Stock Entry", se.name, "submit")

e_waybill_data = EWaybillData(se).get_data()

self.assertEqual(e_waybill_data.get("toStateCode"), 96)
self.assertEqual(e_waybill_data.get("fromStateCode"), 24)
self.assertEqual(e_waybill_data.get("actToStateCode"), 24)

@change_settings(
"GST Settings",
{"enable_e_waybill_from_pi": 1, "enable_overseas_transactions": 1},
)
def test_e_waybill_for_sez_purchase_invoice(self):
pi = create_purchase_invoice(
vehicle_no="GJ07DL9009",
supplier_address="_Test Registered Supplier-Billing-2",
billing_address="_Test Indian Registered Company-Billing",
is_out_state=1,
)

e_waybill_data = EWaybillData(pi).get_data()

# bill_from = supplier (SEZ), bill_to = company
self.assertEqual(e_waybill_data.get("fromStateCode"), 96)
self.assertEqual(e_waybill_data.get("toStateCode"), 24)
self.assertEqual(e_waybill_data.get("actFromStateCode"), 24)

@change_settings(
"GST Settings",
{"enable_e_waybill_from_pi": 1, "enable_overseas_transactions": 1},
)
def test_e_waybill_for_sez_purchase_return(self):
pi = create_purchase_invoice(
vehicle_no="GJ07DL9009",
supplier_address="_Test Registered Supplier-Billing-2",
billing_address="_Test Indian Registered Company-Billing",
is_out_state=1,
)

debit_note = make_return_doc("Purchase Invoice", pi.name)
debit_note.vehicle_no = "GJ07DL9009"
debit_note.save()
debit_note.submit()

e_waybill_data = EWaybillData(debit_note).get_data()

# return swaps from/to: bill_from = company, bill_to = supplier (SEZ)
self.assertEqual(e_waybill_data.get("fromStateCode"), 24)
self.assertEqual(e_waybill_data.get("toStateCode"), 96)
self.assertEqual(e_waybill_data.get("actToStateCode"), 24)

# helper functions
def _generate_e_waybill(self, docname=None, doctype="Sales Invoice", test_data=None, force=False):
"""
Expand Down
2 changes: 2 additions & 0 deletions india_compliance/gst_india/utils/transaction_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ def get_address_details(self, address_name, validate_gstin=False):
"country",
"gstin",
"gst_state_number",
"gst_category",
),
as_dict=True,
)
Expand Down Expand Up @@ -434,6 +435,7 @@ def get_address_details(self, address_name, validate_gstin=False):
),
"pincode": int(address.pincode),
"country_code": get_validated_country_code(address.country),
"gst_category": address.gst_category,
}
)

Expand Down
17 changes: 17 additions & 0 deletions india_compliance/tests/test_records.json
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,23 @@
}
]
},
{
"name": "_Test Registered Supplier-Billing-2",
"address_type": "Billing",
"address_line1": "Test Address - 7",
"city": "Test City",
"state": "Gujarat",
"pincode": "380015",
"country": "India",
"gstin": "24AABCR6898M1ZN",
"gst_category": "SEZ",
"links": [
{
"link_doctype": "Supplier",
"link_name": "_Test Registered Supplier"
}
]
},
{
"name": "_Test Registered Composition Supplier-Billing",
"address_type": "Billing",
Expand Down
Loading