Skip to content

Commit

Permalink
Merge pull request #2626 from resilient-tech/version-14-hotfix
Browse files Browse the repository at this point in the history
chore: release v14
  • Loading branch information
ljain112 committed Sep 21, 2024
2 parents 8012f95 + fa02700 commit 28ccad5
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,8 @@ def get_columns(self):
},
{
"label": _("DocType"),
"fieldtype": "Link",
"fieldtype": "Data",
"fieldname": "doctype",
"options": "DocType",
"width": 120,
},
{
Expand All @@ -172,10 +171,9 @@ def get_columns(self):
},
{
"label": _("Party Type"),
"fieldtype": "Link",
"fieldtype": "Data",
"fieldname": "party_type",
"width": 100,
"options": "DocType",
},
{
"label": _("Party Name"),
Expand Down Expand Up @@ -302,9 +300,8 @@ def get_columns(self):
columns = [
{
"label": _("DocType"),
"fieldtype": "Link",
"fieldtype": "Data",
"fieldname": "doctype",
"options": "DocType",
"width": 150,
},
{
Expand Down
54 changes: 54 additions & 0 deletions india_compliance/gst_india/client_scripts/e_invoice_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ frappe.ui.form.on("Sales Invoice", {
},
"e-Invoice"
);

frm.add_custom_button(
__("Mark as Generated"),
() => show_mark_e_invoice_as_generated_dialog(frm),
"e-Invoice"
);
}
if (
frm.doc.irn &&
Expand Down Expand Up @@ -182,6 +188,54 @@ function show_cancel_e_invoice_dialog(frm, callback) {
`).prependTo(d.wrapper);
}

function show_mark_e_invoice_as_generated_dialog(frm) {
const d = new frappe.ui.Dialog({
title: __("Update e-Invoice Details"),
fields: get_generated_e_invoice_dialog_fields(),
primary_action_label: __("Update"),
primary_action(values) {
frappe.call({
method: "india_compliance.gst_india.utils.e_invoice.mark_e_invoice_as_generated",
args: {
doctype: frm.doctype,
docname: frm.doc.name,
values,
},
callback: () => {
d.hide();
frm.refresh();
},
});
},
});

d.show();
}

function get_generated_e_invoice_dialog_fields() {
let fields = [
{
label: "IRN Number",
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;
}

function show_mark_e_invoice_as_cancelled_dialog(frm) {
const d = new frappe.ui.Dialog({
title: __("Update Cancelled e-Invoice Details"),
Expand Down
1 change: 1 addition & 0 deletions india_compliance/gst_india/client_scripts/party.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ async function set_gstin_options(frm) {

frm._gstin_options_set_for = frm.doc.name;
const field = frm.get_field("gstin");
if (!field || field.df.fieldtype != "Autocomplete") return;
field.df.ignore_validation = true;
field.set_data(await india_compliance.get_gstin_options(frm.doc.name, frm.doctype));
}
Expand Down
2 changes: 1 addition & 1 deletion india_compliance/gst_india/constants/custom_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,7 @@
"label": "e-Invoice Status",
"fieldtype": "Select",
"insert_after": "status",
"options": "\nPending\nGenerated\nAuto-Retry\nCancelled\nManually Cancelled\nFailed\nNot Applicable\nPending Cancellation",
"options": "\nPending\nGenerated\nManually Generated\nAuto-Retry\nCancelled\nManually Cancelled\nFailed\nNot Applicable\nPending Cancellation",
"default": None,
"hidden": 1,
"no_copy": 1,
Expand Down
4 changes: 2 additions & 2 deletions india_compliance/gst_india/report/gst_balance/gst_balance.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ frappe.query_reports["GST Balance"] = {
fieldname: "from_date",
label: __("From Date"),
fieldtype: "Date",
default: frappe.defaults.get_user_default("year_start_date"),
default: india_compliance.last_month_start(),
},
{
fieldname: "to_date",
label: __("To Date"),
fieldtype: "Date",
default: frappe.defaults.get_user_default("year_end_date"),
default: india_compliance.last_month_end(),
},
{
fieldname: "show_summary",
Expand Down
20 changes: 6 additions & 14 deletions india_compliance/gst_india/report/gstr_1/gstr_1.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
get_hsn_data,
get_hsn_wise_json_data,
)
from india_compliance.gst_india.utils import get_escaped_name, get_gst_accounts_by_type
from india_compliance.gst_india.utils import (
get_escaped_name,
get_gst_accounts_by_type,
get_gstin_list,
)
from india_compliance.gst_india.utils.exporter import ExcelExporter
from india_compliance.gst_india.utils.gstr_1 import SUPECOM

Expand Down Expand Up @@ -2202,19 +2206,7 @@ def get_company_gstin_number(company, address=None, all_gstins=False):
gstin = frappe.db.get_value("Address", address, "gstin")

if not gstin:
filters = [
["is_your_company_address", "=", 1],
["Dynamic Link", "link_doctype", "=", "Company"],
["Dynamic Link", "link_name", "=", company],
["Dynamic Link", "parenttype", "=", "Address"],
["gstin", "!=", ""],
]
gstin = frappe.get_all(
"Address",
filters=filters,
pluck="gstin",
order_by="is_primary_address desc",
)
gstin = get_gstin_list(company)
if gstin and not all_gstins:
gstin = gstin[0]

Expand Down
140 changes: 132 additions & 8 deletions india_compliance/gst_india/utils/e_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from frappe.utils import (
add_to_date,
cstr,
flt,
format_date,
get_datetime,
getdate,
Expand All @@ -15,6 +16,9 @@

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_e_invoice import (
EInvoiceAPI as TaxpayerEInvoiceAPI,
)
from india_compliance.gst_india.constants import (
CURRENCY_CODES,
EXPORT_TYPES,
Expand Down Expand Up @@ -193,10 +197,112 @@ def generate_e_invoice(docname, throw=True, force=False):
doc.db_set({"einvoice_status": "Failed"})
raise e

return log_and_process_e_invoice_generation(doc, result, api.sandbox_mode)


@frappe.whitelist()
def handle_duplicate_irn_error(
irn_data,
current_gstin,
current_invoice_amount,
doc=None,
docname=None,
):
"""
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.
2. If the IRN details cannot be fetched, fetch the IRN details from the GST Portal.
3. Compare the buyer GSTIN and invoice amount with the current invoice and throw an error if they don't match.
"""

if isinstance(irn_data, str):
irn_data = json.loads(irn_data, object_hook=frappe._dict)
current_invoice_amount = flt(current_invoice_amount)

doc = doc or load_doc("Sales Invoice", docname, "submit")
api = EInvoiceAPI(doc)
response = api.get_e_invoice_by_irn(irn_data.Irn)

# Handle error 2283:
# IRN details cannot be provided as it is generated more than 2 days ago
if (
response.error_code == "2283"
and api.settings.fetch_e_invoice_details_from_gst_portal
):
response = TaxpayerEInvoiceAPI(doc).get_irn_details(irn_data.Irn)

if response.error_type == "otp_requested":
response.update(
{
"irn_data": irn_data,
"current_gstin": current_gstin,
"current_invoice_amount": current_invoice_amount,
"docname": doc.name,
}
)

return response

response = frappe._dict(response.data or response.error)

if signed_data := response.SignedInvoice:
verify_e_invoice_details(current_gstin, current_invoice_amount, signed_data)

if response.error_code:
response = irn_data

return log_and_process_e_invoice_generation(doc, response, api.sandbox_mode)


def verify_e_invoice_details(current_gstin, current_invoice_amount, signed_data):
invoice_data = json.loads(
jwt.decode(signed_data, options={"verify_signature": False})["data"]
)

previous_gstin = invoice_data.get("BuyerDtls").get("Gstin")
previous_invoice_amount = invoice_data.get("ValDtls").get("TotInvVal")

error_message = ""
if previous_gstin != current_gstin:
error_message += _("<li>Customer GSTIN (Previous: {0}).</li>").format(
frappe.bold(previous_gstin)
)

if previous_invoice_amount != current_invoice_amount:
previous_invoice_amount_formatted = frappe.format_value(
previous_invoice_amount, currency=frappe.db.get_default("currency")
)

error_message += _("<li>Invoice amount (Previous: {0}).</li>").format(
frappe.bold(previous_invoice_amount_formatted)
)

if error_message:
frappe.throw(
_(
"An e-Invoice already exists for Invoice No {0}, but with different details compared to the current Invoice:<br>{1}"
"Hence, the IRN number is not updated against current Invoice."
"<br><br>Corrective Steps:<br><br>"
"<li>Generate a new Invoice for the same transaction.</li>"
"<li>Try cancelling e-Invoice from e-Invoice portal if possible. Alternatively, clear/update e-Invoice as posted automatically in GSTR-1.</li>"
).format(
frappe.bold(invoice_data.get("DocDtls").get("No")),
error_message,
),
)


def log_and_process_e_invoice_generation(doc, result, sandbox_mode=False, message=None):
"""
Load and process the e-Invoice generation result.
"""

doc.db_set(
{
"irn": result.Irn,
"einvoice_status": "Generated",
"einvoice_status": result.get("einvoice_status") or "Generated",
}
)

Expand All @@ -213,13 +319,13 @@ def generate_e_invoice(docname, throw=True, force=False):
doc,
{
"irn": doc.irn,
"sales_invoice": docname,
"sales_invoice": doc.name,
"acknowledgement_number": result.AckNo,
"acknowledged_on": parse_datetime(result.AckDt),
"signed_invoice": result.SignedInvoice,
"signed_qr_code": result.SignedQRCode,
"invoice_data": invoice_data,
"is_generated_in_sandbox_mode": api.sandbox_mode,
"is_generated_in_sandbox_mode": sandbox_mode,
},
)

Expand All @@ -229,11 +335,10 @@ def generate_e_invoice(docname, throw=True, force=False):
if not frappe.request:
return

frappe.msgprint(
_("e-Invoice generated successfully"),
indicator="green",
alert=True,
)
if not message:
message = "e-Invoice generated successfully"

frappe.msgprint(_(message), indicator="green", alert=True)

return send_updated_doc(doc)

Expand Down Expand Up @@ -289,6 +394,25 @@ def log_and_process_e_invoice_cancellation(doc, values, result, message):
frappe.msgprint(_(message), indicator="green", alert=True)


@frappe.whitelist()
def mark_e_invoice_as_generated(doctype, docname, values):
doc = load_doc(doctype, docname, "submit")

values = frappe.parse_json(values)
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()
def mark_e_invoice_as_cancelled(doctype, docname, values):
doc = load_doc(doctype, docname, "cancel")
Expand Down
2 changes: 1 addition & 1 deletion india_compliance/patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ execute:import frappe; frappe.delete_doc_if_exists("DocType", "GSTIN")

[post_model_sync]
india_compliance.patches.v14.set_default_for_overridden_accounts_setting
execute:from india_compliance.gst_india.setup import create_custom_fields; create_custom_fields() #51
execute:from india_compliance.gst_india.setup import create_custom_fields; create_custom_fields() #58
execute:from india_compliance.gst_india.setup import create_property_setters; create_property_setters() #7
execute:from india_compliance.income_tax_india.setup import create_custom_fields; create_custom_fields() #1
india_compliance.patches.post_install.remove_old_fields #2
Expand Down

0 comments on commit 28ccad5

Please sign in to comment.