From 100a4390e7bab397689a94bc44e349c4bf2f4f8f Mon Sep 17 00:00:00 2001 From: vickytechkey Date: Sun, 25 Oct 2026 14:49:56 +0530 Subject: [PATCH] feat: add document verification API serializers and views --- verifier/serializers.py | 12 ++++++++++++ verifier/views.py | 33 ++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/verifier/serializers.py b/verifier/serializers.py index 1be2c0b..c45eb8a 100644 --- a/verifier/serializers.py +++ b/verifier/serializers.py @@ -12,6 +12,12 @@ class VerifyDocumentRequestSerializer(serializers.Serializer): required=True, help_text="Document verification attributes (e.g. pan_number, name, dob, etc.)", ) + business_name = serializers.CharField( + required=False, + allow_blank=True, + allow_null=True, + help_text="Optional legal entity or trade name of the business to match against GSTIN.", + ) preferred_vendor = serializers.CharField( required=False, allow_null=True, @@ -39,6 +45,12 @@ class VerifySellerPanGstRequestSerializer(serializers.Serializer): max_length=15, help_text="Optional GSTIN entered by seller to cross-verify against linked GST records.", ) + business_name = serializers.CharField( + required=False, + allow_blank=True, + allow_null=True, + help_text="Optional legal entity or trade name of the business to match against GSTIN.", + ) preferred_vendor = serializers.CharField( required=False, allow_blank=True, diff --git a/verifier/views.py b/verifier/views.py index eb6e356..37427d5 100644 --- a/verifier/views.py +++ b/verifier/views.py @@ -372,6 +372,7 @@ class SellerPanGstVerifyView(APIView): seller_name = serializer.validated_data["seller_name"].strip() pan = serializer.validated_data["pan"].strip().upper() entered_gstin = (serializer.validated_data.get("gstin") or "").strip().upper() + business_name = (serializer.validated_data.get("business_name") or request.data.get("business_name") or "").strip() preferred_vendor = serializer.validated_data.get("preferred_vendor") start_time = time.time() @@ -492,10 +493,8 @@ class SellerPanGstVerifyView(APIView): gstin_matched = True break - # Validate that 15-character GSTIN contains the 10-character PAN at chars 3-12 - if len(target_gstin) == 15 and target_gstin[2:12].upper() != pan.upper(): - gstin_matched = False - gst_error = f"GSTIN '{target_gstin}' does not match the provided PAN card '{pan}'." + # Do not restrict GSTIN to individual PAN. Entities/companies have their own PAN inside their GSTIN. + # Just verify that the GSTIN exists and is active. # Check if matching record has legal_name if matching_gst_record and matching_gst_record.get("legal_name"): @@ -529,13 +528,25 @@ class SellerPanGstVerifyView(APIView): if not verified_gst_name and gstin_matched: verified_gst_name = verified_pan_name - # Compare GST legal name against seller full name and verified PAN name - if verified_gst_name: - gst_name_match = compare_names(seller_name, verified_gst_name) - if not gst_name_match["matched"] and verified_pan_name: - pan_to_gst_match = compare_names(verified_pan_name, verified_gst_name) - if pan_to_gst_match["matched"]: - gst_name_match = pan_to_gst_match + # Compare GST legal name and trade name against business name (as per GST), seller name, and verified PAN name + gst_candidates = [n for n in [verified_gst_name, gst_details.get("legalName"), gst_details.get("tradeName")] if n] + + # 1. Primary: Match against entered business name (as per GST) + if business_name: + for candidate in gst_candidates: + b_match = compare_names(business_name, candidate) + if b_match["matched"]: + gst_name_match = b_match + break + + # 2. Fallback: Match against seller name or verified PAN name + if not gst_name_match.get("matched", False): + if verified_gst_name: + gst_name_match = compare_names(seller_name, verified_gst_name) + if not gst_name_match["matched"] and verified_pan_name: + pan_to_gst_match = compare_names(verified_pan_name, verified_gst_name) + if pan_to_gst_match["matched"]: + gst_name_match = pan_to_gst_match total_latency = (time.time() - start_time) * 1000