diff --git a/india_compliance/gst_india/client_scripts/e_waybill_actions.js b/india_compliance/gst_india/client_scripts/e_waybill_actions.js index 473581f98..166bb2757 100644 --- a/india_compliance/gst_india/client_scripts/e_waybill_actions.js +++ b/india_compliance/gst_india/client_scripts/e_waybill_actions.js @@ -295,7 +295,7 @@ function show_generate_e_waybill_dialog(frm) { ); d.show(); - set_gst_transporter_id_status(d); + validate_gst_transporter_id(d); //Alert if E-waybill cannot be generated using api if (!is_e_waybill_generatable(frm)) { @@ -374,7 +374,7 @@ function get_generate_e_waybill_dialog(opts, frm) { frm.doc.gst_transporter_id?.length == 15 ? frm.doc.gst_transporter_id : "", - onchange: () => set_gst_transporter_id_status(d), + onchange: () => validate_gst_transporter_id(d), }, // Sub Supply Type will be visible here for Delivery Note @@ -814,7 +814,7 @@ function show_update_transporter_dialog(frm) { frm.doc.gst_transporter_id.length == 15 ? frm.doc.gst_transporter_id : "", - onchange: () => set_gst_transporter_id_status(d), + onchange: () => validate_gst_transporter_id(d), }, { label: "Update e-Waybill Print/Data", @@ -841,7 +841,7 @@ function show_update_transporter_dialog(frm) { // To prevent triggering of change event on input twice frappe.ui.form.ControlData.trigger_change_on_input_event = true; d.show(); - set_gst_transporter_id_status(d); + validate_gst_transporter_id(d); } async function show_extend_validity_dialog(frm) { @@ -1161,10 +1161,8 @@ async function update_gst_tranporter_id(dialog) { dialog.set_value("gst_transporter_id", response.gst_transporter_id); } -function set_gst_transporter_id_status(dialog) { - const gst_transporter_id_field = dialog.get_field("gst_transporter_id"); - - india_compliance.set_gstin_status(gst_transporter_id_field); +function validate_gst_transporter_id(dialog) { + india_compliance.validate_gst_transporter_id(dialog.get_value("gst_transporter_id")); } function update_generation_dialog(dialog, doc) { diff --git a/india_compliance/gst_india/client_scripts/supplier.js b/india_compliance/gst_india/client_scripts/supplier.js index 05a0bfa11..750423c8e 100644 --- a/india_compliance/gst_india/client_scripts/supplier.js +++ b/india_compliance/gst_india/client_scripts/supplier.js @@ -23,13 +23,6 @@ frappe.ui.form.on(DOCTYPE, { }, gst_transporter_id(frm) { - if ( - !frm.doc.gst_transporter_id || - frm.doc.gst_transporter_id.length < 15 - ) - return; - - gst_transporter_id_field = frm.get_field("gst_transporter_id"); - india_compliance.set_gstin_status(gst_transporter_id_field); + india_compliance.validate_gst_transporter_id(frm.doc.gst_transporter_id); }, }); diff --git a/india_compliance/gst_india/doctype/gst_settings/gst_settings.py b/india_compliance/gst_india/doctype/gst_settings/gst_settings.py index a25bf4864..70fe08289 100644 --- a/india_compliance/gst_india/doctype/gst_settings/gst_settings.py +++ b/india_compliance/gst_india/doctype/gst_settings/gst_settings.py @@ -90,6 +90,26 @@ def update_retry_e_invoice_e_waybill_scheduled_job(self): not self.enable_retry_einv_ewb_generation, ) + def get_gstin_with_credentials(self, service=None): + if not service: + return + + if service == "Returns" and not self: + return + + if service == "e-Waybill" and not self.enable_e_waybill: + return + + if service == "e-Invoice" and not self.enable_e_invoice: + return + + if service in ["e-Invoice", "e-Waybill"]: + service = "e-Waybill / e-Invoice" + + for row in self.credentials: + if row.service == service: + return row.gstin + def validate_gst_accounts(self): account_list = [] company_wise_account_types = {} diff --git a/india_compliance/gst_india/doctype/gstin/gstin.js b/india_compliance/gst_india/doctype/gstin/gstin.js index 2abed01b8..b5c68b1b1 100644 --- a/india_compliance/gst_india/doctype/gstin/gstin.js +++ b/india_compliance/gst_india/doctype/gstin/gstin.js @@ -5,8 +5,12 @@ frappe.ui.form.on("GSTIN", { refresh(frm) { frm.disable_form(); - frm.add_custom_button(__("Refresh Now"), () => { + frm.add_custom_button(__("Refresh GSTIN Status"), () => { frm.call("update_gstin_status"); }); + + frm.add_custom_button(__("Refresh Transporter ID Status"), () => { + frm.call("update_transporter_id_status"); + }); }, }); diff --git a/india_compliance/gst_india/doctype/gstin/gstin.json b/india_compliance/gst_india/doctype/gstin/gstin.json index 234b1382c..a5acf0c6f 100644 --- a/india_compliance/gst_india/doctype/gstin/gstin.json +++ b/india_compliance/gst_india/doctype/gstin/gstin.json @@ -9,10 +9,11 @@ "gstin", "registration_date", "status", - "is_blocked", + "transporter_id_status", "column_break_nrjd", "last_updated_on", "cancelled_date", + "is_blocked", "section_break_ttzc", "gstr_1_filed_upto" ], @@ -30,8 +31,7 @@ "fieldtype": "Data", "in_list_view": 1, "in_standard_filter": 1, - "label": "Status", - "reqd": 1 + "label": "GSTIN Status" }, { "fieldname": "registration_date", @@ -62,6 +62,12 @@ "in_standard_filter": 1, "label": "Is Blocked" }, + { + "fieldname": "transporter_id_status", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Transporter ID Status" + }, { "fieldname": "section_break_ttzc", "fieldtype": "Section Break" @@ -76,7 +82,7 @@ "in_create": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2024-05-17 15:38:05.867522", + "modified": "2024-06-14 13:59:53.998262", "modified_by": "Administrator", "module": "GST India", "name": "GSTIN", @@ -100,9 +106,15 @@ "report": 1, "role": "Accounts Manager", "share": 1 + }, + { + "export": 1, + "read": 1, + "report": 1, + "role": "Accounts User" } ], - "sort_field": "modified", + "sort_field": "creation", "sort_order": "DESC", "states": [], "title_field": "gstin" diff --git a/india_compliance/gst_india/doctype/gstin/gstin.py b/india_compliance/gst_india/doctype/gstin/gstin.py index 96a5f7160..283ae0ff0 100644 --- a/india_compliance/gst_india/doctype/gstin/gstin.py +++ b/india_compliance/gst_india/doctype/gstin/gstin.py @@ -6,13 +6,10 @@ from frappe.model.document import Document from frappe.utils import date_diff, format_date, get_datetime -from india_compliance.gst_india.api_classes.e_invoice import EInvoiceAPI -from india_compliance.gst_india.api_classes.e_waybill import EWaybillAPI -from india_compliance.gst_india.api_classes.public import PublicAPI -from india_compliance.gst_india.utils import ( - is_api_enabled, - parse_datetime, - validate_gstin, +from india_compliance.gst_india.utils import is_api_enabled, validate_gstin_check_digit +from india_compliance.gst_india.utils.gstin_info import ( + fetch_gstin_status, + fetch_transporter_id_status, ) GSTIN_STATUS = { @@ -40,47 +37,22 @@ def update_gstin_status(self): """ Permission check not required as GSTIN details are public and user has access to doc. """ - create_or_update_gstin_status(self.gstin) + # hard refresh will always use public API + create_or_update_gstin_status(self.gstin, throw=True) + @frappe.whitelist() + def update_transporter_id_status(self): + """ + Permission check not required as GSTIN details are public and user has access to doc. + """ + create_or_update_gstin_status(self.gstin, is_transporter_id=True) -@frappe.whitelist() -def get_gstin_status( - gstin, transaction_date=None, is_request_from_ui=0, force_update=0 -): - """ - Permission check not required as GSTIN details are public where GSTIN is known. - """ + +def get_gstr_1_filed_upto(gstin): if not gstin: return - if not int(force_update) and not is_status_refresh_required( - gstin, transaction_date - ): - if not frappe.db.exists("GSTIN", gstin): - return - - return frappe.get_doc("GSTIN", gstin) - - return get_updated_gstin(gstin, transaction_date, is_request_from_ui) - - -def get_updated_gstin(gstin, transaction_date=None, is_request_from_ui=0): - if is_request_from_ui: - return create_or_update_gstin_status(gstin) - - if gstin[:2] == "88": - callback = _validate_gst_transporter_id_info - else: - callback = _validate_gstin_info - - frappe.enqueue( - create_or_update_gstin_status, - enqueue_after_commit=True, - queue="short", - gstin=gstin, - transaction_date=transaction_date, - callback=callback, - ) + return frappe.db.get_value("GSTIN", gstin, "gstr_1_filed_upto") def create_or_update_gstin_status( @@ -88,16 +60,19 @@ def create_or_update_gstin_status( response=None, transaction_date=None, callback=None, + is_transporter_id=False, + throw=False, ): doctype = "GSTIN" - if gstin and gstin[:2] == "88": - response = get_transporter_id_info(gstin) - else: - response = _get_gstin_info(gstin=gstin, response=response) - if not response: - return + if is_transporter_id: + response = fetch_transporter_id_status(gstin, throw=throw) + else: + response = fetch_gstin_status(gstin=gstin, throw=throw) + + if not response: + return if frappe.db.exists(doctype, response.get("gstin")): doc = frappe.get_doc(doctype, response.pop("gstin")) @@ -113,42 +88,55 @@ def create_or_update_gstin_status( return doc -def _get_gstin_info(*, gstin=None, response=None): - if response: - return get_formatted_response(response) +### GSTIN Status Validation ### - validate_gstin(gstin) - try: - company_gstin = get_company_gstin() - - if not company_gstin: - response = PublicAPI().get_gstin_info(gstin) - return get_formatted_response(response) - - response = EInvoiceAPI(company_gstin=company_gstin).get_gstin_info(gstin) - return frappe._dict( - { - "gstin": gstin, - "registration_date": parse_datetime(response.DtReg, throw=False), - "cancelled_date": parse_datetime(response.DtDReg, throw=False), - "status": response.Status, - "is_blocked": response.BlkStatus, - } - ) +def get_and_validate_gstin_status(gstin, transaction_date): + """ + Get and validate GSTIN status. + Enqueues fetching GSTIN status if required and hence best suited for Backend use. + """ + if not gstin: + return + + if not is_status_refresh_required(gstin, transaction_date): + if not frappe.db.exists("GSTIN", gstin): + return - except Exception: - frappe.log_error( - title=_("Error fetching GSTIN status"), - message=frappe.get_traceback(), + doc = frappe.get_doc("GSTIN", gstin) + validate_gstin_status(doc, transaction_date, throw=True) + + else: + # Don't delay the response if API is required + frappe.enqueue( + create_or_update_gstin_status, + enqueue_after_commit=True, + queue="short", + gstin=gstin, + transaction_date=transaction_date, + callback=validate_gstin_status, ) - frappe.clear_last_message() - finally: - frappe.cache().set_value(gstin, True, expires_in_sec=180) + +@frappe.whitelist() +def get_gstin_status(gstin, transaction_date=None, force_update=False): + """ + Get GSTIN status. Responds immediately, and best suited for Frontend use. + Permission check not required as GSTIN details are public where GSTIN is known. + """ + if not gstin: + return + + if not force_update and not is_status_refresh_required(gstin, transaction_date): + if not frappe.db.exists("GSTIN", gstin): + return + + return frappe.get_doc("GSTIN", gstin) + + return create_or_update_gstin_status(gstin, throw=force_update) -def _validate_gstin_info(gstin_doc, transaction_date=None, throw=False): +def validate_gstin_status(gstin_doc, transaction_date=None, throw=False): if not (gstin_doc and transaction_date): return @@ -197,41 +185,6 @@ def _throw(message): ) -def _validate_gst_transporter_id_info(transporter_id_info, **kwargs): - if not transporter_id_info: - return - - throw = kwargs.get("throw", False) - - def _throw(message): - if throw: - frappe.throw(message) - - else: - frappe.log_error( - title=_("Invalid Transporter ID"), - message=message, - ) - - if transporter_id_info.status != "Active": - return _throw( - _( - "Transporter ID {0} is not Active. Please make sure that transporter ID is valid." - ).format(transporter_id_info.gstin) - ) - - -def get_company_gstin(): - gst_settings = frappe.get_cached_doc("GST Settings") - - if not gst_settings.enable_e_invoice: - return - - for row in gst_settings.credentials: - if row.service == "e-Waybill / e-Invoice": - return row.gstin - - def is_status_refresh_required(gstin, transaction_date): settings = frappe.get_cached_doc("GST Settings") @@ -239,7 +192,6 @@ def is_status_refresh_required(gstin, transaction_date): not settings.validate_gstin_status or not is_api_enabled(settings) or settings.sandbox_mode - or frappe.cache().get_value(gstin) ): return @@ -250,11 +202,6 @@ def is_status_refresh_required(gstin, transaction_date): if not doc: return True - # Transporter ID status is never cancelled - is_transporter_id = gstin[:2] == "88" - if is_transporter_id: - return False - if not transaction_date: # not from transactions return False @@ -265,49 +212,65 @@ def is_status_refresh_required(gstin, transaction_date): return days_since_last_update >= settings.gstin_status_refresh_interval -def get_formatted_response(response): - """ - Format response from Public API +### GST Transporter ID Validation ### + + +@frappe.whitelist() +def validate_gst_transporter_id(transporter_id): """ - return frappe._dict( - { - "gstin": response.gstin, - "registration_date": parse_datetime( - response.rgdt, day_first=True, throw=False - ), - "cancelled_date": parse_datetime( - response.cxdt, day_first=True, throw=False - ), - "status": response.sts, - } - ) + Validates GST Transporter ID and warns user if transporter_id is not Active. + Just suggestive and not enforced. + Only for Frontend use. -def get_transporter_id_info(transporter_id): - if not frappe.get_cached_value("GST Settings", None, "enable_e_waybill"): + Args: + transporter_id (str): GST Transporter ID + """ + if not transporter_id: return - company_gstin = get_company_gstin() - if not company_gstin: + gstin = None + + # Check if GSTIN doc exists + if frappe.db.exists("GSTIN", transporter_id): + gstin = frappe.get_doc("GSTIN", transporter_id) + + # Check if transporter_id starts with 88 or is not valid GSTIN and use Transporter ID API + elif transporter_id[:2] == "88" or has_gstin_check_digit_failed(transporter_id): + gstin = create_or_update_gstin_status( + transporter_id, + is_transporter_id=True, + ) + + # Use GSTIN API + else: + gstin = create_or_update_gstin_status(transporter_id) + + if not gstin: return - response = EWaybillAPI(company_gstin=company_gstin).get_transporter_details( - transporter_id - ) + # If GSTIN status is not Active and transporter_id_status is None, use Transporter ID API + if gstin.status != "Active" and not gstin.transporter_id_status: + gstin = create_or_update_gstin_status( + transporter_id, + is_transporter_id=True, + ) - if not response: + # Return if GSTIN or transporter_id_status is Active + if gstin.status == "Active" or gstin.transporter_id_status == "Active": return - return frappe._dict( - { - "gstin": transporter_id, - "status": "Active" if response.transin else "Invalid", - } + frappe.msgprint( + _("GST Transporter ID {0} seems to be Invalid").format(transporter_id), + indicator="orange", ) -def get_gstr_1_filed_upto(gstin): - if not gstin: - return +def has_gstin_check_digit_failed(gstin): + try: + validate_gstin_check_digit(gstin) - return frappe.db.get_value("GSTIN", gstin, "gstr_1_filed_upto") + except frappe.ValidationError: + return True + + return False diff --git a/india_compliance/gst_india/doctype/gstin/test_gstin.py b/india_compliance/gst_india/doctype/gstin/test_gstin.py index e948c983e..d9b495641 100644 --- a/india_compliance/gst_india/doctype/gstin/test_gstin.py +++ b/india_compliance/gst_india/doctype/gstin/test_gstin.py @@ -1,48 +1,44 @@ # Copyright (c) 2023, Resilient Tech and Contributors # See license.txt -import re +import responses +from responses import matchers -import frappe from frappe.tests.utils import FrappeTestCase, change_settings -from frappe.utils import now -from india_compliance.gst_india.utils.tests import create_transaction +from india_compliance.gst_india.doctype.gstin.gstin import validate_gst_transporter_id + +TEST_GSTIN = "24AANFA2641L1ZK" + +TRANSPORTER_ID_API_RESPONSE = { + "success": True, + "message": "Transporter details are fetched successfully", + "result": { + "transin": TEST_GSTIN, + "tradeName": "_Test Transporter ID Comapany", + "legalName": "_Test Transporter ID Comapany", + "address1": "address 1", + "address2": "address 2", + "stateCode": "24", + "pinCode": "390020", + }, +} class TestGSTIN(FrappeTestCase): + @responses.activate @change_settings("GST Settings", {"validate_gstin_status": 1, "sandbox_mode": 0}) - def test_validate_gst_transporter_id_info(self): - # customer gstin - frappe.get_doc( - { - "doctype": "GSTIN", - "gstin": "24AANFA2641L1ZF", - "registration_date": "2021-01-01", - "status": "Active", - "last_updated_on": now(), - } - ).insert(ignore_if_duplicate=True) - - # gst transporter id - frappe.get_doc( - { - "doctype": "GSTIN", - "gstin": "88AABCM9407D1ZS", - "status": "Invalid", - "last_updated_on": now(), - } - ).insert(ignore_if_duplicate=True) - - si = create_transaction( - doctype="Sales Invoice", - gst_transporter_id="88AABCM9407D1ZS", - do_not_save=True, - ) + def test_validate_gst_transporter_id(self): + self.mock_get_transporter_details_response() + + validate_gst_transporter_id(TEST_GSTIN) + + def mock_get_transporter_details_response(self): + url = "https://asp.resilient.tech/ewb/Master/GetTransporterDetails" - self.assertRaisesRegex( - frappe.ValidationError, - re.compile( - r"^(.*is not Active. Please make sure that transporter ID is valid.*)$" - ), - si.save, + responses.add( + responses.GET, + url, + json=TRANSPORTER_ID_API_RESPONSE, + match=[matchers.query_param_matcher({"trn_no": TEST_GSTIN})], + status=200, ) diff --git a/india_compliance/gst_india/overrides/transaction.py b/india_compliance/gst_india/overrides/transaction.py index 1a810efd6..6b79178d9 100644 --- a/india_compliance/gst_india/overrides/transaction.py +++ b/india_compliance/gst_india/overrides/transaction.py @@ -20,11 +20,7 @@ from india_compliance.gst_india.doctype.gst_settings.gst_settings import ( restrict_gstr_1_transaction_for, ) -from india_compliance.gst_india.doctype.gstin.gstin import ( - _validate_gst_transporter_id_info, - _validate_gstin_info, - get_gstin_status, -) +from india_compliance.gst_india.doctype.gstin.gstin import get_and_validate_gstin_status from india_compliance.gst_india.utils import ( get_all_gst_accounts, get_gst_accounts_by_tax_type, @@ -1427,33 +1423,17 @@ def validate_gstin_status(gstin, transaction_date): if not settings.validate_gstin_status: return - gstin_doc = get_gstin_status(gstin, transaction_date) - - if not gstin_doc: - return - - _validate_gstin_info(gstin_doc, transaction_date, throw=True) + get_and_validate_gstin_status(gstin, transaction_date) def validate_gst_transporter_id(doc): if not doc.get("gst_transporter_id"): return - settings = frappe.get_cached_doc("GST Settings") - if not settings.validate_gstin_status: - return - doc.gst_transporter_id = validate_gstin( doc.gst_transporter_id, label="GST Transporter ID", is_transporter_id=True ) - gstin_doc = get_gstin_status(doc.gst_transporter_id) - - if not gstin_doc: - return - - _validate_gst_transporter_id_info(gstin_doc, throw=True) - def validate_company_address_field(doc): if doc.doctype not in DOCTYPES_WITH_GST_DETAIL: diff --git a/india_compliance/gst_india/utils/__init__.py b/india_compliance/gst_india/utils/__init__.py index 0609e897a..ad310859b 100644 --- a/india_compliance/gst_india/utils/__init__.py +++ b/india_compliance/gst_india/utils/__init__.py @@ -171,6 +171,7 @@ def validate_gstin( title=_("Invalid {0}").format(label), ) + # eg: 29AAFCA7488L1Z0 invalid check digit for valid transporter id if not is_transporter_id: validate_gstin_check_digit(gstin, label) diff --git a/india_compliance/gst_india/utils/gstin_info.py b/india_compliance/gst_india/utils/gstin_info.py index 5c9ffdc4e..24611bfe5 100644 --- a/india_compliance/gst_india/utils/gstin_info.py +++ b/india_compliance/gst_india/utils/gstin_info.py @@ -6,12 +6,15 @@ from frappe import _ from frappe.utils import getdate +from india_compliance.exceptions import GSPServerError from india_compliance.gst_india.api_classes.base import BASE_URL +from india_compliance.gst_india.api_classes.e_invoice import EInvoiceAPI +from india_compliance.gst_india.api_classes.e_waybill import EWaybillAPI from india_compliance.gst_india.api_classes.public import PublicAPI from india_compliance.gst_india.doctype.gstr_1_log.gstr_1_log import ( process_gstr_1_returns_info, ) -from india_compliance.gst_india.utils import titlecase, validate_gstin +from india_compliance.gst_india.utils import parse_datetime, titlecase, validate_gstin GST_CATEGORIES = { "Regular": "Registered Regular", @@ -46,13 +49,19 @@ def _get_gstin_info(gstin, *, throw_error=True): if not response: try: + if frappe.cache().get_value("gst_server_error"): + return + response = PublicAPI().get_gstin_info(gstin) frappe.enqueue( "india_compliance.gst_india.doctype.gstin.gstin.create_or_update_gstin_status", queue="long", - response=response, + response=get_formatted_response_for_status(response), ) except Exception as exc: + if isinstance(exc, GSPServerError): + frappe.cache().set_value("gst_server_error", True, expires_in_sec=60) + if throw_error: raise exc @@ -168,6 +177,111 @@ def _extract_address_lines(address): return address_line1, address_line2 +def fetch_gstin_status(*, gstin=None, throw=True): + """ + Fetch GSTIN status from E-Invoice API or Public API + + Uses Public API if credentials are not available or its a user initiated request + + :param gstin: GSTIN to fetch status for + :param throw: Raise exception if error occurs (used for user initiated requests) + """ + validate_gstin(gstin) + + try: + if not throw and frappe.cache().get_value("gst_server_error"): + return + + gst_settings = frappe.get_cached_doc("GST Settings", None) + company_gstin = gst_settings.get_gstin_with_credentials(service="e-Invoice") + + if throw or not company_gstin: + response = PublicAPI().get_gstin_info(gstin) + return get_formatted_response_for_status(response) + + response = EInvoiceAPI(company_gstin=company_gstin).get_gstin_info(gstin) + return frappe._dict( + { + "gstin": gstin, + "registration_date": parse_datetime(response.DtReg, throw=False), + "cancelled_date": parse_datetime(response.DtDReg, throw=False), + "status": response.Status, + "is_blocked": response.BlkStatus, + } + ) + + except Exception as e: + if throw: + raise e + + if isinstance(e, GSPServerError): + frappe.cache().set_value("gst_server_error", True, expires_in_sec=60) + + frappe.log_error( + title=_("Error fetching GSTIN status"), + message=frappe.get_traceback(), + ) + frappe.clear_last_message() + + +def get_formatted_response_for_status(response): + """ + Format response from Public API + """ + return frappe._dict( + { + "gstin": response.gstin, + "registration_date": parse_datetime( + response.rgdt, day_first=True, throw=False + ), + "cancelled_date": parse_datetime( + response.cxdt, day_first=True, throw=False + ), + "status": response.sts, + } + ) + + +def fetch_transporter_id_status(transporter_id, throw=True): + """ + Fetch Transporter ID status from E-Waybill API + + :param transporter_id: GSTIN of the transporter + :param throw: Raise exception if error occurs (used for user initiated requests) + """ + if not frappe.get_cached_value("GST Settings", None, "enable_e_waybill"): + return + + gst_settings = frappe.get_cached_doc("GST Settings", None) + company_gstin = gst_settings.get_gstin_with_credentials(service="e-Waybill") + + if not company_gstin: + return + + try: + response = EWaybillAPI(company_gstin=company_gstin).get_transporter_details( + transporter_id + ) + + except Exception as e: + if throw: + raise e + + frappe.log_error( + title=_("Error fetching Transporter ID status"), + message=frappe.get_traceback(), + ) + frappe.clear_last_message() + return + + return frappe._dict( + { + "gstin": transporter_id, + "transporter_id_status": "Active" if response.transin else "Invalid", + } + ) + + # ####### SAMPLE DATA for GST_CATEGORIES ######## # "Composition" 36AASFP8573D2ZN # "Input Service Distributor (ISD)" 29AABCF8078M2ZW Flipkart diff --git a/india_compliance/public/js/transaction.js b/india_compliance/public/js/transaction.js index 580c1b7f9..57909384a 100644 --- a/india_compliance/public/js/transaction.js +++ b/india_compliance/public/js/transaction.js @@ -181,7 +181,7 @@ function set_and_validate_gstin_status(doctype) { }, gst_transporter_id(frm) { - _set_and_validate_gstin_status(frm, "gst_transporter_id"); + india_compliance.validate_gst_transporter_id(frm.doc.gst_transporter_id); }, posting_date(frm) { diff --git a/india_compliance/public/js/utils.js b/india_compliance/public/js/utils.js index 7f1dc236a..8dd170e7f 100644 --- a/india_compliance/public/js/utils.js +++ b/india_compliance/public/js/utils.js @@ -87,18 +87,13 @@ Object.assign(india_compliance, { return in_list(frappe.boot.sales_doctypes, doctype) ? "Customer" : "Supplier"; }, - async set_gstin_status(field, transaction_date, force_update = 0) { + async set_gstin_status(field, transaction_date, force_update) { const gstin = field.value; if (!gstin || gstin.length !== 15) return field.set_description(""); const { message } = await frappe.call({ method: "india_compliance.gst_india.doctype.gstin.gstin.get_gstin_status", - args: { - gstin, - transaction_date, - is_request_from_ui: 1, - force_update, - }, + args: { gstin, transaction_date, force_update }, }); if (!message) return field.set_description(""); @@ -115,6 +110,15 @@ Object.assign(india_compliance, { return message; }, + validate_gst_transporter_id(transporter_id) { + if (!transporter_id || transporter_id.length !== 15) return; + + frappe.call({ + method: "india_compliance.gst_india.doctype.gstin.gstin.validate_gst_transporter_id", + args: { transporter_id }, + }); + }, + get_gstin_status_desc(status, datetime) { if (!status) return; const user_date = frappe.datetime.str_to_user(datetime); @@ -147,7 +151,7 @@ Object.assign(india_compliance, { `).appendTo(field.$wrapper.find(".gstin-last-updated")); refresh_btn.on("click", async function () { - const force_update = 1; + const force_update = true; await india_compliance.set_gstin_status( field, transaction_date,