From 60826be0c7f052b870b153d7e43c3a2456c13bbe Mon Sep 17 00:00:00 2001 From: Bhushan Barbuddhe Date: Thu, 16 Oct 2025 20:05:13 +0530 Subject: [PATCH] feat: enhance MSG91 settings with OTP template ID and update validation rules --- .../doctype/msg91_settings/msg91_settings.js | 8 + .../msg91_settings/msg91_settings.json | 215 ++++++++++-------- .../doctype/msg91_settings/msg91_settings.py | 4 +- .../msg91_settings/test_msg91_settings.py | 22 ++ .../msg91_integration/utils.py | 3 +- 5 files changed, 155 insertions(+), 97 deletions(-) create mode 100644 frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.js create mode 100644 frappe_msg91_integration/msg91_integration/doctype/msg91_settings/test_msg91_settings.py diff --git a/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.js b/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.js new file mode 100644 index 0000000..adfa0aa --- /dev/null +++ b/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.js @@ -0,0 +1,8 @@ +// Copyright (c) 2025, Dhwani RIS and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("MSG91 Settings", { +// refresh(frm) { + +// }, +// }); diff --git a/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.json b/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.json index 62e0485..b36c092 100644 --- a/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.json +++ b/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.json @@ -1,95 +1,122 @@ { - "allow_rename": 0, - "creation": "2023-05-01 00:00:00.000000", - "doctype": "DocType", - "engine": "InnoDB", - "field_order": [ - "enabled", - "auth_section", - "auth_key", - "sender_id", - "route_section", - "otp_route", - "sms_route", - "template_section", - "templates" - ], - "fields": [ - { - "default": "0", - "fieldname": "enabled", - "fieldtype": "Check", - "label": "Enabled" - }, - { - "fieldname": "auth_section", - "fieldtype": "Section Break", - "label": "Authentication" - }, - { - "fieldname": "auth_key", - "fieldtype": "Password", - "label": "Auth Key", - "reqd": 1 - }, - { - "fieldname": "sender_id", - "fieldtype": "Data", - "label": "Sender ID", - "reqd": 1, - "description": "6 characters sender ID provided by MSG91" - }, - { - "fieldname": "route_section", - "fieldtype": "Section Break", - "label": "API Routes" - }, - { - "default": "https://control.msg91.com/api/v5/otp", - "fieldname": "otp_route", - "fieldtype": "Data", - "label": "OTP API Route", - "reqd": 1 - }, - { - "default": "https://api.msg91.com/api/v5/flow/", - "fieldname": "sms_route", - "fieldtype": "Data", - "label": "SMS API Route", - "reqd": 1 - }, - { - "fieldname": "template_section", - "fieldtype": "Section Break", - "label": "SMS Templates" - }, - { - "fieldname": "templates", - "fieldtype": "Table", - "label": "Templates", - "options": "MSG91 Template" - } - ], - "issingle": 1, - "modified": "2023-05-01 00:00:00.000000", - "module": "MSG91 Integration", - "name": "MSG91 Settings", - "name_case": "Title Case", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "print": 1, - "read": 1, - "role": "System Manager", - "share": 1, - "write": 1 - } - ], - "sort_field": "modified", - "sort_order": "DESC", - "states": [], - "track_changes": 1 -} \ No newline at end of file + "actions": [], + "creation": "2023-05-01 00:00:00", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "enabled", + "auth_section", + "auth_key", + "column_break_meve", + "sender_id", + "route_section", + "otp_route", + "column_break_gbdi", + "otp_template_id", + "column_break_rjtm", + "sms_route", + "template_section", + "templates" + ], + "fields": [ + { + "default": "0", + "fieldname": "enabled", + "fieldtype": "Check", + "label": "Enabled" + }, + { + "fieldname": "auth_section", + "fieldtype": "Section Break", + "label": "Authentication" + }, + { + "fieldname": "auth_key", + "fieldtype": "Password", + "in_list_view": 1, + "label": "Auth Key", + "reqd": 1 + }, + { + "description": "4-6 characters sender ID provided by MSG91", + "fieldname": "sender_id", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Sender ID", + "reqd": 1 + }, + { + "fieldname": "route_section", + "fieldtype": "Section Break", + "label": "API Routes" + }, + { + "default": "https://control.msg91.com/api/v5/otp", + "fieldname": "otp_route", + "fieldtype": "Data", + "in_list_view": 1, + "label": "OTP API Route", + "reqd": 1 + }, + { + "default": "https://api.msg91.com/api/v5/flow/", + "fieldname": "sms_route", + "fieldtype": "Data", + "in_list_view": 1, + "label": "SMS API Route", + "reqd": 1 + }, + { + "fieldname": "template_section", + "fieldtype": "Section Break", + "label": "SMS Templates" + }, + { + "fieldname": "templates", + "fieldtype": "Table", + "label": "Templates", + "options": "MSG91 Template" + }, + { + "fieldname": "column_break_meve", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_gbdi", + "fieldtype": "Column Break" + }, + { + "fieldname": "otp_template_id", + "fieldtype": "Data", + "label": "OTP Template ID" + }, + { + "fieldname": "column_break_rjtm", + "fieldtype": "Column Break" + } + ], + "issingle": 1, + "links": [], + "modified": "2025-10-16 19:57:26.794351", + "modified_by": "Administrator", + "module": "MSG91 Integration", + "name": "MSG91 Settings", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "row_format": "Dynamic", + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "track_changes": 1 +} diff --git a/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.py b/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.py index 22d9061..d920709 100644 --- a/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.py +++ b/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/msg91_settings.py @@ -9,8 +9,8 @@ def validate(self): frappe.throw(_("Auth Key is required when MSG91 is enabled")) if not self.sender_id: frappe.throw(_("Sender ID is required when MSG91 is enabled")) - if len(self.sender_id) != 6: - frappe.throw(_("Sender ID must be exactly 6 characters")) + if len(self.sender_id) < 4: + frappe.throw(_("Sender ID must be at least 4 characters")) # Validate API routes if not self.otp_route: diff --git a/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/test_msg91_settings.py b/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/test_msg91_settings.py new file mode 100644 index 0000000..70e065c --- /dev/null +++ b/frappe_msg91_integration/msg91_integration/doctype/msg91_settings/test_msg91_settings.py @@ -0,0 +1,22 @@ +# Copyright (c) 2025, Dhwani RIS and Contributors +# See license.txt + +# import frappe +from frappe.tests import IntegrationTestCase + + +# On IntegrationTestCase, the doctype test records and all +# link-field test record dependencies are recursively loaded +# Use these module variables to add/remove to/from that list +EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"] +IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"] + + + +class IntegrationTestMSG91Settings(IntegrationTestCase): + """ + Integration tests for MSG91Settings. + Use this class for testing interactions between multiple components. + """ + + pass diff --git a/frappe_msg91_integration/msg91_integration/utils.py b/frappe_msg91_integration/msg91_integration/utils.py index 6d4745e..fad4bae 100644 --- a/frappe_msg91_integration/msg91_integration/utils.py +++ b/frappe_msg91_integration/msg91_integration/utils.py @@ -15,6 +15,7 @@ def get_msg91_settings(): "auth_key": get_decrypted_password('MSG91 Settings','MSG91 Settings','auth_key'), "sender_id": settings.sender_id, "otp_route": settings.otp_route, + "otp_template_id": settings.otp_template_id, "sms_route": settings.sms_route, "templates": {template.template_name: template.template_id for template in settings.templates} } @@ -136,7 +137,7 @@ def send_otp(number, otp_length=6, otp_expiry=5, otp=None): if otp: data["otp"] = otp - template_id = settings["templates"].get("otp_template_id") + template_id = settings["otp_template_id"] if not template_id: frappe.throw(_("Template '{0}' not found in MSG91 Settings").format("otp_template_id"))