fix: Add warning for invalid GST invoice numbers (#24837)

* fix: Add warning for invalid GST invoice numbers

GST Invoice numbers should be 16 characters alphanumeric with dash(/) or
slash(-) only. Add check for doc.name before saving and warn about
naming series.

* refactor: move regex patterns to global variables

Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
This commit is contained in:
Ankush
2021-03-15 17:58:17 +05:30
committed by GitHub
parent 2e2f3f9578
commit f9f10ed743
2 changed files with 27 additions and 5 deletions

View File

@@ -261,6 +261,9 @@ doc_events = {
('Sales Invoice', 'Sales Order', 'Delivery Note', 'Purchase Invoice', 'Purchase Order', 'Purchase Receipt'): {
'validate': ['erpnext.regional.india.utils.set_place_of_supply']
},
('Sales Invoice', 'Purchase Invoice'): {
'validate': ['erpnext.regional.india.utils.validate_document_name']
},
"Contact": {
"on_trash": "erpnext.support.doctype.issue.issue.update_issue",
"after_insert": "erpnext.communication.doctype.call_log.call_log.set_caller_information",

View File

@@ -2,7 +2,7 @@ from __future__ import unicode_literals
import frappe, re, json
from frappe import _
import erpnext
from frappe.utils import cstr, flt, date_diff, nowdate, round_based_on_smallest_currency_fraction, money_in_words
from frappe.utils import cstr, flt, date_diff, nowdate, round_based_on_smallest_currency_fraction, money_in_words, getdate
from erpnext.regional.india import states, state_numbers
from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_taxable_amount, calculate_outstanding_amount
from erpnext.controllers.accounts_controller import get_taxes_and_charges
@@ -15,6 +15,13 @@ from erpnext.accounts.utils import get_account_currency
from frappe.contacts.doctype.address.address import get_address_display
from frappe.model.utils import get_fetch_values
GST_INVOICE_NUMBER_FORMAT = re.compile(r"^[a-zA-Z0-9\-/]+$") #alphanumeric and - /
GSTIN_FORMAT = re.compile("^[0-9]{2}[A-Z]{4}[0-9A-Z]{1}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}[1-9A-Z]{1}[0-9A-Z]{1}$")
GSTIN_UIN_FORMAT = re.compile("^[0-9]{4}[A-Z]{3}[0-9]{5}[0-9A-Z]{3}")
PAN_NUMBER_FORMAT = re.compile("[A-Z]{5}[0-9]{4}[A-Z]{1}")
def validate_gstin_for_india(doc, method):
if hasattr(doc, 'gst_state') and doc.gst_state:
doc.gst_state_number = state_numbers[doc.gst_state]
@@ -38,12 +45,10 @@ def validate_gstin_for_india(doc, method):
frappe.throw(_("Invalid GSTIN! A GSTIN must have 15 characters."))
if gst_category and gst_category == 'UIN Holders':
p = re.compile("^[0-9]{4}[A-Z]{3}[0-9]{5}[0-9A-Z]{3}")
if not p.match(doc.gstin):
if not GSTIN_UIN_FORMAT.match(doc.gstin):
frappe.throw(_("Invalid GSTIN! The input you've entered doesn't match the GSTIN format for UIN Holders or Non-Resident OIDAR Service Providers"))
else:
p = re.compile("^[0-9]{2}[A-Z]{4}[0-9A-Z]{1}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}[1-9A-Z]{1}[0-9A-Z]{1}$")
if not p.match(doc.gstin):
if not GSTIN_FORMAT.match(doc.gstin):
frappe.throw(_("Invalid GSTIN! The input you've entered doesn't match the format of GSTIN."))
validate_gstin_check_digit(doc.gstin)
@@ -162,6 +167,20 @@ def set_transporter_address(doc, method=None):
doc.transporter_address = transporter_address
doc.transporter_address_display = get_address_display(transporter_address)
def validate_document_name(doc, method=None):
"""Validate GST invoice number requirements."""
country = frappe.get_cached_value("Company", doc.company, "country")
# Date was chosen as start of next FY to avoid irritating current users.
if country != "India" or getdate(doc.posting_date) < getdate("2021-04-01"):
return
if len(doc.name) > 16:
frappe.throw(_("Maximum length of document number should be 16 characters as per GST rules. Please change the naming series."))
if not GST_INVOICE_NUMBER_FORMAT.match(doc.name):
frappe.throw(_("Document name should only contain alphanumeric values, dash(-) and slash(/) characters as per GST rules. Please change the naming series."))
# don't remove this function it is used in tests
def test_method():
'''test function'''