From d49291946c0e45c69fa3eb82eb61fb42868fbb79 Mon Sep 17 00:00:00 2001 From: Sanket322 Date: Wed, 15 Jan 2025 18:20:42 +0530 Subject: [PATCH 1/5] fix: fetch invoice data on manually generated --- .../client_scripts/e_invoice_actions.js | 25 ++++++------- india_compliance/gst_india/utils/e_invoice.py | 35 ++++++++++++++----- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/india_compliance/gst_india/client_scripts/e_invoice_actions.js b/india_compliance/gst_india/client_scripts/e_invoice_actions.js index fbe167e446..896931d56a 100644 --- a/india_compliance/gst_india/client_scripts/e_invoice_actions.js +++ b/india_compliance/gst_india/client_scripts/e_invoice_actions.js @@ -53,7 +53,7 @@ frappe.ui.form.on("Sales Invoice", { if (r.message?.error_type == "otp_requested") { await india_compliance.authenticate_otp(frm.doc.company_gstin); await frappe.call({ - method: "india_compliance.gst_india.utils.e_invoice.handle_duplicate_irn_error", + method: "india_compliance.gst_india.utils.e_invoice.fetch_irn_details_compare_invoice", args: r.message }); } @@ -212,7 +212,14 @@ function show_mark_e_invoice_as_generated_dialog(frm) { docname: frm.doc.name, values, }, - callback: () => { + callback: async (r) => { + if (r.message?.error_type == "otp_requested") { + await india_compliance.authenticate_otp(frm.doc.company_gstin); + await frappe.call({ + method: "india_compliance.gst_india.utils.e_invoice.fetch_irn_details_compare_invoice", + args: r.message + }); + } d.hide(); frm.refresh(); }, @@ -230,19 +237,7 @@ function get_generated_e_invoice_dialog_fields() { fieldname: "irn", fieldtype: "Data", reqd: 1, - }, - { - label: "Acknowledgement Number", - fieldname: "ack_no", - fieldtype: "Data", - reqd: 1, - }, - { - label: "Acknowledged On", - fieldname: "ack_dt", - fieldtype: "Datetime", - reqd: 1, - }, + } ]; return fields; } diff --git a/india_compliance/gst_india/utils/e_invoice.py b/india_compliance/gst_india/utils/e_invoice.py index d340e2db6c..5089fb4da1 100644 --- a/india_compliance/gst_india/utils/e_invoice.py +++ b/india_compliance/gst_india/utils/e_invoice.py @@ -12,6 +12,7 @@ get_datetime, getdate, random_string, + rounded, ) from india_compliance.exceptions import GSPServerError @@ -137,7 +138,7 @@ def generate_e_invoice(docname, throw=True, force=False): current_gstin = data.get("BuyerDtls").get("Gstin") current_invoice_amount = data.get("ValDtls").get("TotInvVal") - return handle_duplicate_irn_error( + return fetch_irn_details_compare_invoice( irn_data=result.Desc, current_gstin=current_gstin, current_invoice_amount=current_invoice_amount, @@ -184,15 +185,16 @@ def generate_e_invoice(docname, throw=True, force=False): @frappe.whitelist() -def handle_duplicate_irn_error( +def fetch_irn_details_compare_invoice( irn_data, current_gstin, current_invoice_amount, doc=None, docname=None, + message=None, ): """ - Handle Duplicate IRN errors by fetching the IRN details and comparing with the current invoice. + Handle Duplicate IRN errors and Manually Generated by fetching the IRN details and comparing with the current invoice. Steps: 1. Fetch IRN details using the IRN number using e-Invoice API. @@ -206,6 +208,7 @@ def handle_duplicate_irn_error( doc = doc or load_doc("Sales Invoice", docname, "submit") api = EInvoiceAPI(doc) + # TODO: test Taxpayer api call and otp and check that Ack dt/No data is coming or not response = api.get_e_invoice_by_irn(irn_data.Irn) # Handle error 2283: @@ -236,7 +239,12 @@ def handle_duplicate_irn_error( if response.error_code: response = irn_data - return log_and_process_e_invoice_generation(doc, response, api.sandbox_mode) + if irn_data.einvoice_status == "Manually Generated": + response.einvoice_status = "Manually Generated" + + return log_and_process_e_invoice_generation( + doc, response, api.sandbox_mode, message=message + ) def verify_e_invoice_details(current_gstin, current_invoice_amount, signed_data): @@ -389,17 +397,26 @@ def mark_e_invoice_as_generated(doctype, docname, values): doc = load_doc(doctype, docname, "submit") values = frappe.parse_json(values) - result = frappe._dict( + irn_data = frappe._dict( { "Irn": values.irn, - "AckDt": values.ack_dt, - "AckNo": values.ack_no, "einvoice_status": "Manually Generated", } ) - return log_and_process_e_invoice_generation( - doc, result, message="e-Invoice updated successfully" + grand_total_fieldname = ( + "base_grand_total" + if doc.get("disable_rounded_total", 1) + else "base_rounded_total" + ) + grand_total = abs(rounded(doc.get(grand_total_fieldname), 2)) + + return fetch_irn_details_compare_invoice( + irn_data, + doc.billing_address_gstin, + grand_total, + doc, + message="e-Invoice updated successfully", ) From 8a59e0cde5753d7f1343ad016114541668ca13f7 Mon Sep 17 00:00:00 2001 From: Sanket322 Date: Wed, 19 Feb 2025 18:13:46 +0530 Subject: [PATCH 2/5] fix: use taxpayer_api.call to handle otp itself --- .../client_scripts/e_invoice_actions.js | 34 +++++-------------- india_compliance/gst_india/utils/e_invoice.py | 1 - 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/india_compliance/gst_india/client_scripts/e_invoice_actions.js b/india_compliance/gst_india/client_scripts/e_invoice_actions.js index 0c05812371..6be3e6b11b 100644 --- a/india_compliance/gst_india/client_scripts/e_invoice_actions.js +++ b/india_compliance/gst_india/client_scripts/e_invoice_actions.js @@ -45,21 +45,12 @@ frappe.ui.form.on("Sales Invoice", { ) { frm.add_custom_button( __("Generate"), - () => { - frappe.call({ + async () => { + await taxpayer_api.call({ method: "india_compliance.gst_india.utils.e_invoice.generate_e_invoice", args: { docname: frm.doc.name, force: true }, - callback: async (r) => { - if (r.message?.error_type == "otp_requested") { - await india_compliance.authenticate_otp(frm.doc.company_gstin); - await frappe.call({ - method: "india_compliance.gst_india.utils.e_invoice.fetch_irn_details_compare_invoice", - args: r.message - }); - } - frm.refresh(); - }, }); + frm.refresh(); }, "e-Invoice" ); @@ -204,26 +195,17 @@ function show_mark_e_invoice_as_generated_dialog(frm) { title: __("Update e-Invoice Details"), fields: get_generated_e_invoice_dialog_fields(), primary_action_label: __("Update"), - primary_action(values) { - frappe.call({ + async primary_action(values) { + await taxpayer_api.call({ method: "india_compliance.gst_india.utils.e_invoice.mark_e_invoice_as_generated", args: { doctype: frm.doctype, docname: frm.doc.name, values, - }, - callback: async (r) => { - if (r.message?.error_type == "otp_requested") { - await india_compliance.authenticate_otp(frm.doc.company_gstin); - await frappe.call({ - method: "india_compliance.gst_india.utils.e_invoice.fetch_irn_details_compare_invoice", - args: r.message - }); - } - d.hide(); - frm.refresh(); - }, + } }); + d.hide(); + frm.refresh(); }, }); diff --git a/india_compliance/gst_india/utils/e_invoice.py b/india_compliance/gst_india/utils/e_invoice.py index 5089fb4da1..8f979f6e5d 100644 --- a/india_compliance/gst_india/utils/e_invoice.py +++ b/india_compliance/gst_india/utils/e_invoice.py @@ -208,7 +208,6 @@ def fetch_irn_details_compare_invoice( doc = doc or load_doc("Sales Invoice", docname, "submit") api = EInvoiceAPI(doc) - # TODO: test Taxpayer api call and otp and check that Ack dt/No data is coming or not response = api.get_e_invoice_by_irn(irn_data.Irn) # Handle error 2283: From d1227f26b23ad6ae5399a6c1cc577cd8b2e401cf Mon Sep 17 00:00:00 2001 From: Sanket322 Date: Fri, 21 Feb 2025 00:21:13 +0530 Subject: [PATCH 3/5] fix: revert other changes --- .../client_scripts/e_invoice_actions.js | 37 ++++++++++-- india_compliance/gst_india/utils/e_invoice.py | 56 +++++++++---------- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/india_compliance/gst_india/client_scripts/e_invoice_actions.js b/india_compliance/gst_india/client_scripts/e_invoice_actions.js index 6be3e6b11b..2aaaa96e3c 100644 --- a/india_compliance/gst_india/client_scripts/e_invoice_actions.js +++ b/india_compliance/gst_india/client_scripts/e_invoice_actions.js @@ -45,12 +45,21 @@ frappe.ui.form.on("Sales Invoice", { ) { frm.add_custom_button( __("Generate"), - async () => { - await taxpayer_api.call({ + () => { + frappe.call({ method: "india_compliance.gst_india.utils.e_invoice.generate_e_invoice", args: { docname: frm.doc.name, force: true }, + callback: async (r) => { + if (r.message?.error_type == "otp_requested") { + await india_compliance.authenticate_otp(frm.doc.company_gstin); + await frappe.call({ + method: "india_compliance.gst_india.utils.e_invoice.handle_duplicate_irn_error", + args: r.message + }); + } + frm.refresh(); + }, }); - frm.refresh(); }, "e-Invoice" ); @@ -219,7 +228,27 @@ function get_generated_e_invoice_dialog_fields() { fieldname: "irn", fieldtype: "Data", reqd: 1, - } + }, + { + label: "Fetch Invoice Details", + fieldname: "fetch_invoice_details", + fieldtype: "Check", + default: 1, + }, + { + label: "Acknowledgement Number", + fieldname: "ack_no", + fieldtype: "Data", + mandatory_depends_on: "eval: !doc.fetch_invoice_details", + depends_on: "eval: !doc.fetch_invoice_details", + }, + { + label: "Acknowledged On", + fieldname: "ack_dt", + fieldtype: "Datetime", + mandatory_depends_on: "eval: !doc.fetch_invoice_details", + depends_on: "eval: !doc.fetch_invoice_details", + }, ]; return fields; } diff --git a/india_compliance/gst_india/utils/e_invoice.py b/india_compliance/gst_india/utils/e_invoice.py index 8f979f6e5d..6aae6b0e13 100644 --- a/india_compliance/gst_india/utils/e_invoice.py +++ b/india_compliance/gst_india/utils/e_invoice.py @@ -12,11 +12,13 @@ get_datetime, getdate, random_string, - rounded, ) from india_compliance.exceptions import GSPServerError from india_compliance.gst_india.api_classes.e_invoice import EInvoiceAPI +from india_compliance.gst_india.api_classes.taxpayer_base import ( + otp_handler, +) from india_compliance.gst_india.api_classes.taxpayer_e_invoice import ( EInvoiceAPI as TaxpayerEInvoiceAPI, ) @@ -138,7 +140,7 @@ def generate_e_invoice(docname, throw=True, force=False): current_gstin = data.get("BuyerDtls").get("Gstin") current_invoice_amount = data.get("ValDtls").get("TotInvVal") - return fetch_irn_details_compare_invoice( + return handle_duplicate_irn_error( irn_data=result.Desc, current_gstin=current_gstin, current_invoice_amount=current_invoice_amount, @@ -185,16 +187,15 @@ def generate_e_invoice(docname, throw=True, force=False): @frappe.whitelist() -def fetch_irn_details_compare_invoice( +def handle_duplicate_irn_error( irn_data, current_gstin, current_invoice_amount, doc=None, docname=None, - message=None, ): """ - Handle Duplicate IRN errors and Manually Generated by fetching the IRN details and comparing with the current invoice. + Handle Duplicate IRN errors by fetching the IRN details and comparing with the current invoice. Steps: 1. Fetch IRN details using the IRN number using e-Invoice API. @@ -238,12 +239,7 @@ def fetch_irn_details_compare_invoice( if response.error_code: response = irn_data - if irn_data.einvoice_status == "Manually Generated": - response.einvoice_status = "Manually Generated" - - return log_and_process_e_invoice_generation( - doc, response, api.sandbox_mode, message=message - ) + return log_and_process_e_invoice_generation(doc, response, api.sandbox_mode) def verify_e_invoice_details(current_gstin, current_invoice_amount, signed_data): @@ -392,30 +388,32 @@ def log_and_process_e_invoice_cancellation(doc, values, result, message): @frappe.whitelist() +@otp_handler def mark_e_invoice_as_generated(doctype, docname, values): doc = load_doc(doctype, docname, "submit") values = frappe.parse_json(values) - irn_data = frappe._dict( - { - "Irn": values.irn, - "einvoice_status": "Manually Generated", - } - ) + if not values.fetch_invoice_details: + result = frappe._dict( + { + "Irn": values.irn, + "AckDt": values.ack_dt, + "AckNo": values.ack_no, + } + ) + else: + api = EInvoiceAPI(doc) + result = api.get_e_invoice_by_irn(values.irn) - grand_total_fieldname = ( - "base_grand_total" - if doc.get("disable_rounded_total", 1) - else "base_rounded_total" - ) - grand_total = abs(rounded(doc.get(grand_total_fieldname), 2)) + if result.error_code == "2283": + # irn = 22ba0f91f00541e6e9e4915186edbea717cdeb6d54592e38e0dca9d6eaabeb5c + result = TaxpayerEInvoiceAPI(doc).get_irn_details(values.irn) - return fetch_irn_details_compare_invoice( - irn_data, - doc.billing_address_gstin, - grand_total, - doc, - message="e-Invoice updated successfully", + print(result) + + result.einvoice_status = "Manually Generated" + return log_and_process_e_invoice_generation( + doc, result, message="e-Invoice updated successfully" ) From 739112161aadd76fc5c51b8b6d6280de13e1f3b2 Mon Sep 17 00:00:00 2001 From: Sanket322 Date: Fri, 21 Feb 2025 13:14:46 +0530 Subject: [PATCH 4/5] fix: fetch e-invoice details in e-Invoice Log --- .../doctype/e_invoice_log/e_invoice_log.js | 26 +++++++++-- .../doctype/e_invoice_log/e_invoice_log.json | 10 ++++- india_compliance/gst_india/utils/e_invoice.py | 44 ++++++++++++------- 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.js b/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.js index f9cf744010..c1ca50ad56 100644 --- a/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.js +++ b/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.js @@ -1,8 +1,26 @@ // Copyright (c) 2022, Resilient Tech and contributors // For license information, please see license.txt -// frappe.ui.form.on('e-Invoice Log', { -// refresh: function(frm) { +frappe.ui.form.on('e-Invoice Log', { + refresh: function (frm) { }, -// } -// }); + fetch_e_invoice_details: function (frm) { + if (frm.doc.fetch_e_invoice_details) { + frm.add_custom_button(__('Fetch E-Invoice Details'), function () { + frappe.call({ + method: "india_compliance.gst_india.utils.e_invoice.fetch_e_invoice_details", + args: { + "irn": frm.doc.irn, + "docname": frm.doc.reference_name, + }, + callback: function () { + frm.reload_doc(); + } + }); + }) + } + else { + frm.remove_custom_button(__('Fetch E-Invoice Details')); + } + } +}); diff --git a/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.json b/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.json index 0a1f3093ea..d27c036feb 100644 --- a/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.json +++ b/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.json @@ -13,6 +13,7 @@ "column_break_1", "acknowledgement_number", "acknowledged_on", + "fetch_e_invoice_details", "signed_data_section", "invoice_data", "signed_invoice", @@ -131,6 +132,13 @@ "label": "Reference Document Name", "options": "reference_doctype", "read_only": 1 + }, + { + "default": "0", + "depends_on": "eval: !doc.invoice_data", + "fieldname": "fetch_e_invoice_details", + "fieldtype": "Check", + "label": "Fetch E-Invoice Details" } ], "in_create": 1, @@ -140,7 +148,7 @@ "link_fieldname": "irn" } ], - "modified": "2024-09-19 18:59:01.195753", + "modified": "2025-02-21 12:58:02.214762", "modified_by": "Administrator", "module": "GST India", "name": "e-Invoice Log", diff --git a/india_compliance/gst_india/utils/e_invoice.py b/india_compliance/gst_india/utils/e_invoice.py index 6aae6b0e13..bdeca26953 100644 --- a/india_compliance/gst_india/utils/e_invoice.py +++ b/india_compliance/gst_india/utils/e_invoice.py @@ -393,25 +393,37 @@ def mark_e_invoice_as_generated(doctype, docname, values): doc = load_doc(doctype, docname, "submit") values = frappe.parse_json(values) - if not values.fetch_invoice_details: - result = frappe._dict( - { - "Irn": values.irn, - "AckDt": values.ack_dt, - "AckNo": values.ack_no, - } - ) - else: - api = EInvoiceAPI(doc) - result = api.get_e_invoice_by_irn(values.irn) + if values.fetch_invoice_details: + return fetch_e_invoice_details(values.irn, doc=doc) + + result = frappe._dict( + { + "Irn": values.irn, + "AckDt": values.ack_dt, + "AckNo": values.ack_no, + "einvoice_status": "Manually Generated", + } + ) + return log_and_process_e_invoice_generation( + doc, result, message="e-Invoice updated successfully" + ) + + +@frappe.whitelist() +@otp_handler +def fetch_e_invoice_details(irn, docname=None, doc=None): + if not doc: + doc = load_doc("Sales Invoice", docname, "submit") + + api = EInvoiceAPI(doc) + result = api.get_e_invoice_by_irn(irn) - if result.error_code == "2283": - # irn = 22ba0f91f00541e6e9e4915186edbea717cdeb6d54592e38e0dca9d6eaabeb5c - result = TaxpayerEInvoiceAPI(doc).get_irn_details(values.irn) + if result.error_code == "2148": + frappe.throw(_("Requested IRN data is not available")) - print(result) + if result.error_code == "2283": + result = TaxpayerEInvoiceAPI(doc).get_irn_details(irn) - result.einvoice_status = "Manually Generated" return log_and_process_e_invoice_generation( doc, result, message="e-Invoice updated successfully" ) From f187aac0a2ccfd57917bfceea4dfa23c2b928fd6 Mon Sep 17 00:00:00 2001 From: Sanket322 Date: Fri, 28 Feb 2025 19:23:42 +0530 Subject: [PATCH 5/5] fix: removing duplicate code --- .../doctype/e_invoice_log/e_invoice_log.js | 38 +++++++++--------- .../doctype/e_invoice_log/e_invoice_log.json | 10 +---- india_compliance/gst_india/utils/e_invoice.py | 40 ++++++------------- 3 files changed, 32 insertions(+), 56 deletions(-) diff --git a/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.js b/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.js index c1ca50ad56..6adca3d1fd 100644 --- a/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.js +++ b/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.js @@ -2,25 +2,23 @@ // For license information, please see license.txt frappe.ui.form.on('e-Invoice Log', { - refresh: function (frm) { }, - - fetch_e_invoice_details: function (frm) { - if (frm.doc.fetch_e_invoice_details) { - frm.add_custom_button(__('Fetch E-Invoice Details'), function () { - frappe.call({ - method: "india_compliance.gst_india.utils.e_invoice.fetch_e_invoice_details", - args: { - "irn": frm.doc.irn, - "docname": frm.doc.reference_name, - }, - callback: function () { - frm.reload_doc(); - } - }); - }) - } - else { - frm.remove_custom_button(__('Fetch E-Invoice Details')); + refresh: function (frm) { + if (!frm.doc.invoice_data) { + frm.add_custom_button(__('Fetch e-Invoice Details'), () => fetch_e_invoice_details(frm)); } - } + }, }); + +function fetch_e_invoice_details(frm) { + taxpayer_api.call({ + method: "india_compliance.gst_india.utils.e_invoice.mark_e_invoice_as_generated", + args: { + "doctype": frm.doc.reference_doctype, + "docname": frm.doc.reference_name, + "values": {"irn" : frm.doc.irn, "fetch_invoice_details": 1} + }, + callback: function () { + frm.reload_doc(); + } + }); +} diff --git a/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.json b/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.json index d27c036feb..0a1f3093ea 100644 --- a/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.json +++ b/india_compliance/gst_india/doctype/e_invoice_log/e_invoice_log.json @@ -13,7 +13,6 @@ "column_break_1", "acknowledgement_number", "acknowledged_on", - "fetch_e_invoice_details", "signed_data_section", "invoice_data", "signed_invoice", @@ -132,13 +131,6 @@ "label": "Reference Document Name", "options": "reference_doctype", "read_only": 1 - }, - { - "default": "0", - "depends_on": "eval: !doc.invoice_data", - "fieldname": "fetch_e_invoice_details", - "fieldtype": "Check", - "label": "Fetch E-Invoice Details" } ], "in_create": 1, @@ -148,7 +140,7 @@ "link_fieldname": "irn" } ], - "modified": "2025-02-21 12:58:02.214762", + "modified": "2024-09-19 18:59:01.195753", "modified_by": "Administrator", "module": "GST India", "name": "e-Invoice Log", diff --git a/india_compliance/gst_india/utils/e_invoice.py b/india_compliance/gst_india/utils/e_invoice.py index bdeca26953..e556417657 100644 --- a/india_compliance/gst_india/utils/e_invoice.py +++ b/india_compliance/gst_india/utils/e_invoice.py @@ -394,35 +394,21 @@ def mark_e_invoice_as_generated(doctype, docname, values): values = frappe.parse_json(values) if values.fetch_invoice_details: - return fetch_e_invoice_details(values.irn, doc=doc) - - result = frappe._dict( - { - "Irn": values.irn, - "AckDt": values.ack_dt, - "AckNo": values.ack_no, - "einvoice_status": "Manually Generated", - } - ) - return log_and_process_e_invoice_generation( - doc, result, message="e-Invoice updated successfully" - ) - - -@frappe.whitelist() -@otp_handler -def fetch_e_invoice_details(irn, docname=None, doc=None): - if not doc: - doc = load_doc("Sales Invoice", docname, "submit") - - api = EInvoiceAPI(doc) - result = api.get_e_invoice_by_irn(irn) + api = EInvoiceAPI(doc) + result = api.get_e_invoice_by_irn(values.irn) - if result.error_code == "2148": - frappe.throw(_("Requested IRN data is not available")) + if result.error_code == "2283": + result = TaxpayerEInvoiceAPI(doc).get_irn_details(values.irn) - if result.error_code == "2283": - result = TaxpayerEInvoiceAPI(doc).get_irn_details(irn) + else: + result = frappe._dict( + { + "Irn": values.irn, + "AckDt": values.ack_dt, + "AckNo": values.ack_no, + "einvoice_status": "Manually Generated", + } + ) return log_and_process_e_invoice_generation( doc, result, message="e-Invoice updated successfully"