Skip to content

Commit bc53581

Browse files
committed
backend/fix: Morth Integration for Rc
1 parent 51bb159 commit bc53581

9 files changed

Lines changed: 331 additions & 8 deletions

File tree

lib/mobility-core/mobility-core.cabal

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,12 +315,15 @@ library
315315
Kernel.External.Verification.Interface.HyperVerge
316316
Kernel.External.Verification.Interface.Idfy
317317
Kernel.External.Verification.Interface.InternalScripts
318+
Kernel.External.Verification.Interface.Morth
318319
Kernel.External.Verification.Interface.SafetyPortal
319320
Kernel.External.Verification.Interface.Tten
320321
Kernel.External.Verification.Interface.Types
321322
Kernel.External.Verification.InternalScripts.Error
322323
Kernel.External.Verification.InternalScripts.FaceVerification
323324
Kernel.External.Verification.InternalScripts.Types
325+
Kernel.External.Verification.Morth.Flow
326+
Kernel.External.Verification.Morth.Types
324327
Kernel.External.Verification.SafetyPortal.API
325328
Kernel.External.Verification.SafetyPortal.Client
326329
Kernel.External.Verification.SafetyPortal.Config

lib/mobility-core/src/Kernel/External/Verification/Interface.hs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ module Kernel.External.Verification.Interface
3939
fetchAndExtractVerifiedPan,
4040
fetchAndExtractVerifiedAadhaar,
4141
getVerifiedAadhaarXML,
42+
verifyRCMorth,
4243
)
4344
where
4445

@@ -56,6 +57,7 @@ import qualified Kernel.External.Verification.Interface.Digilocker as DigiLocker
5657
import qualified Kernel.External.Verification.Interface.HyperVerge as HyperVerge
5758
import qualified Kernel.External.Verification.Interface.Idfy as Idfy
5859
import qualified Kernel.External.Verification.Interface.InternalScripts as IS
60+
import qualified Kernel.External.Verification.Interface.Morth as Morth
5961
import qualified Kernel.External.Verification.Interface.SafetyPortal as SafetyPortal
6062
import qualified Kernel.External.Verification.Interface.Tten as Tten
6163
import Kernel.External.Verification.Interface.Types as Reexport
@@ -84,6 +86,7 @@ verifyDLAsync serviceConfig req = case serviceConfig of
8486
HyperVergeVerificationConfigRCDL cfg -> HyperVerge.verifyDLAsync cfg req
8587
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
8688
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
89+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
8790

8891
verifyPanAsync ::
8992
( EncFlow m r,
@@ -102,6 +105,7 @@ verifyPanAsync serviceConfig req = case serviceConfig of
102105
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
103106
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
104107
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
108+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
105109

106110
verifyGstAsync ::
107111
( EncFlow m r,
@@ -120,6 +124,7 @@ verifyGstAsync serviceConfig req = case serviceConfig of
120124
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
121125
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
122126
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
127+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
123128

124129
verifyBankAccountAsync ::
125130
( EncFlow m r,
@@ -138,6 +143,7 @@ verifyBankAccountAsync serviceConfig req = case serviceConfig of
138143
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
139144
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
140145
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
146+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
141147

142148
verifyPanAadhaarLinkAsync ::
143149
( EncFlow m r,
@@ -156,6 +162,7 @@ verifyPanAadhaarLinkAsync serviceConfig req = case serviceConfig of
156162
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
157163
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
158164
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
165+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
159166

160167
verifyUdyamAadhaarAsync ::
161168
( EncFlow m r,
@@ -174,6 +181,7 @@ verifyUdyamAadhaarAsync serviceConfig req = case serviceConfig of
174181
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
175182
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
176183
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
184+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
177185

178186
verifyRC ::
179187
( EncFlow m r,
@@ -222,6 +230,7 @@ verifyRC' serviceConfig req = case serviceConfig of
222230
HyperVergeVerificationConfigRCDL cfg -> HyperVerge.verifyRCAsync cfg req
223231
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
224232
TtenVerificationConfig cfg -> Tten.verifyTten cfg req
233+
MorthConfig cfg -> Morth.verifyRCAsync cfg req
225234

226235
validateImage ::
227236
( EncFlow m r,
@@ -240,6 +249,7 @@ validateImage serviceConfig req = case serviceConfig of
240249
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
241250
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
242251
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
252+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
243253

244254
validateFaceImage ::
245255
( CoreMetrics m,
@@ -258,6 +268,7 @@ validateFaceImage serviceConfig req = case serviceConfig of
258268
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
259269
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
260270
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
271+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
261272

262273
extractRCImage ::
263274
( EncFlow m r,
@@ -276,6 +287,7 @@ extractRCImage serviceConfig req = case serviceConfig of
276287
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
277288
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
278289
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
290+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
279291

280292
extractDLImage ::
281293
( EncFlow m r,
@@ -294,6 +306,7 @@ extractDLImage serviceConfig req = case serviceConfig of
294306
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
295307
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
296308
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
309+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
297310

298311
extractPanImage ::
299312
( EncFlow m r,
@@ -312,6 +325,7 @@ extractPanImage serviceConfig req = case serviceConfig of
312325
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
313326
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
314327
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
328+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
315329

316330
extractGSTImage ::
317331
( EncFlow m r,
@@ -330,6 +344,7 @@ extractGSTImage serviceConfig req = case serviceConfig of
330344
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
331345
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
332346
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
347+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
333348

334349
extractUdyogAadhaarAsync ::
335350
( EncFlow m r,
@@ -348,6 +363,7 @@ extractUdyogAadhaarAsync serviceConfig req = case serviceConfig of
348363
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
349364
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
350365
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
366+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
351367

352368
extractAadhaarImage ::
353369
( EncFlow m r,
@@ -366,6 +382,7 @@ extractAadhaarImage serviceConfig req = case serviceConfig of
366382
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
367383
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
368384
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
385+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
369386

370387
nameCompare ::
371388
( EncFlow m r,
@@ -384,6 +401,7 @@ nameCompare serviceConfig req = case serviceConfig of
384401
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
385402
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
386403
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
404+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
387405

388406
searchAgent ::
389407
( EncFlow m r,
@@ -414,6 +432,7 @@ verifySdkResp serviceConfig req = case serviceConfig of
414432
HyperVergeVerificationConfigRCDL _ -> throwError $ InternalError "Not Implemented!"
415433
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
416434
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
435+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
417436

418437
getTask ::
419438
( EncFlow m r,
@@ -433,6 +452,7 @@ getTask serviceConfig req updateResp = case serviceConfig of
433452
HyperVergeVerificationConfigRCDL cfg -> HyperVerge.getVerificationStatus cfg req updateResp
434453
DigiLockerConfig _ -> throwError $ InternalError "Not Implemented!"
435454
TtenVerificationConfig _ -> throwError $ InternalError "Not Implemented!"
455+
MorthConfig _ -> throwError $ InternalError "Not Implemented!"
436456

437457
fetchAndExtractVerifiedDL ::
438458
( EncFlow m r,
@@ -529,3 +549,20 @@ getVerifiedAadhaarXML ::
529549
getVerifiedAadhaarXML serviceConfig req = case serviceConfig of
530550
DigiLockerConfig cfg -> DigiLocker.getVerifiedAadhaarXML cfg req.accessToken
531551
_ -> throwError $ InternalError "Not Implemented!"
552+
553+
-- | Dedicated entry-point for the MoRTH vehicle-RC validity check.
554+
-- Unlike the generic 'verifyRC' / 'verifyRC'' dispatch this function accepts
555+
-- a 'MorthConfig' directly so callers do not need to wire it through the
556+
-- priority-list mechanism.
557+
verifyRCMorth ::
558+
( EncFlow m r,
559+
CoreMetrics m,
560+
HasRequestId r,
561+
MonadReader r m
562+
) =>
563+
VerificationServiceConfig ->
564+
VerifyRCReq ->
565+
m VerifyRCResp
566+
verifyRCMorth serviceConfig req = case serviceConfig of
567+
MorthConfig cfg -> Morth.verifyRCAsync cfg req
568+
_ -> throwError $ InternalError "verifyRCMorth: MorthConfig expected but a different provider was supplied"

lib/mobility-core/src/Kernel/External/Verification/Interface/Idfy.hs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,22 @@ extractRCImage cfg req = do
323323
pure
324324
ExtractRCImageResp
325325
{ extractedRC =
326-
resp.result <&> \result -> do
327-
ExtractedRC {rcNumber = result.extraction_output.registration_number}
326+
resp.result <&> \result ->
327+
let eo = result.extraction_output
328+
in ExtractedRC
329+
{ rcNumber = eo.registration_number,
330+
vehicleClass = eo._class,
331+
manufacturer = eo.manufacturer,
332+
model = eo.model,
333+
fuelType = eo.fuel,
334+
colour = eo.colour,
335+
chassisNumber = eo.chassis_number,
336+
engineNumber = eo.engine_number,
337+
registrationDate = eo.registration_date,
338+
ownerName = eo.owner_name,
339+
manufacturingDate = eo.manufacturing_date,
340+
bodyType = eo.body
341+
}
328342
}
329343

330344
extractUdyogAadhaarAsync ::
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
{-
2+
Copyright 2022-23, Juspay India Pvt Ltd
3+
4+
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License
5+
6+
as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is
7+
8+
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9+
10+
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero
11+
12+
General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
13+
-}
14+
15+
module Kernel.External.Verification.Interface.Morth where
16+
17+
import qualified Data.Text as T
18+
import Data.Time.Calendar (Day)
19+
import Data.Time.Format (defaultTimeLocale, formatTime, parseTimeM)
20+
import Kernel.External.Encryption
21+
import qualified Kernel.External.Verification.Interface.Types as InterfaceTypes
22+
import qualified Kernel.External.Verification.Morth.Flow as MorthFlow
23+
import Kernel.External.Verification.Morth.Types
24+
import qualified Kernel.External.Verification.Types as VT
25+
import Kernel.Prelude
26+
import Kernel.Tools.Metrics.CoreMetrics (CoreMetrics)
27+
import Kernel.Types.Error (GenericError (InternalError))
28+
import Kernel.Utils.Error.Throwing (throwError)
29+
import Kernel.Utils.Servant.Client
30+
31+
-- | Verify vehicle Registration Certificate (RC) validity via the MoRTH
32+
-- Parivahan API.
33+
--
34+
-- The caller must populate the optional fields @engineNumber@, @chassisNumber@,
35+
-- and @applicantMobile@ in 'InterfaceTypes.VerifyRCReq'; if any of them are
36+
-- absent an 'InternalError' is thrown.
37+
verifyRCAsync ::
38+
( EncFlow m r,
39+
CoreMetrics m,
40+
HasRequestId r,
41+
MonadReader r m
42+
) =>
43+
MorthVerificationCfg ->
44+
InterfaceTypes.VerifyRCReq ->
45+
m InterfaceTypes.VerifyRCResp
46+
verifyRCAsync cfg req = do
47+
engNo <- req.engineNumber & maybe (throwError $ InternalError "engineNumber is required for MoRTH RC verification") pure
48+
chasiNo <- req.chassisNumber & maybe (throwError $ InternalError "chassisNumber is required for MoRTH RC verification") pure
49+
let morthReq = makeMorthReq req engNo chasiNo
50+
resp <- MorthFlow.getVehicleValidityInfo cfg morthReq
51+
return . InterfaceTypes.SyncResp $ convertToRCVerificationResponse resp
52+
where
53+
makeMorthReq :: InterfaceTypes.VerifyRCReq -> Text -> Text -> VehicleValidityReq
54+
makeMorthReq InterfaceTypes.VerifyRCReq {..} engNo chasiNo =
55+
VehicleValidityReq
56+
{ regnNo = rcNumber,
57+
applicantMobile = fromMaybe "" applicantMobile,
58+
engNo = engNo,
59+
chasiNo = chasiNo
60+
}
61+
normaliseMorthDate :: Text -> Maybe Text
62+
normaliseMorthDate raw =
63+
fmap (T.pack . formatTime defaultTimeLocale "%Y-%m-%d") $
64+
(parseTimeM True defaultTimeLocale "%d-%b-%Y" (T.unpack raw) :: Maybe Day)
65+
66+
-- Convert the MoRTH response into the common 'VT.RCVerificationResponse'.
67+
convertToRCVerificationResponse :: VehicleValidityResp -> VT.RCVerificationResponse
68+
convertToRCVerificationResponse VehicleValidityResp {..} =
69+
VT.RCVerificationResponse
70+
{ registrationDate = Nothing,
71+
registrationNumber = Just req.rcNumber,
72+
-- Normalise from Morth's "dd-Mon-yyyy" to ISO "yyyy-mm-dd" so that
73+
-- the downstream `convertTextToUTC` can parse it correctly.
74+
fitnessUpto = data_ >>= (.rcValidUpto) >>= normaliseMorthDate,
75+
insuranceValidity = Nothing,
76+
vehicleClass = Nothing,
77+
vehicleCategory = Nothing,
78+
seatingCapacity = Nothing,
79+
manufacturer = Nothing,
80+
permitValidityFrom = Nothing,
81+
permitValidityUpto = Nothing,
82+
pucValidityUpto = Nothing,
83+
manufacturerModel = Nothing,
84+
mYManufacturing = Nothing,
85+
color = Nothing,
86+
fuelType = Nothing,
87+
bodyType = Nothing,
88+
status = data_ >>= (.rcValidity),
89+
grossVehicleWeight = Nothing,
90+
unladdenWeight = Nothing
91+
}

lib/mobility-core/src/Kernel/External/Verification/Interface/Types.hs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ import qualified Kernel.External.Verification.HyperVerge.Types as HyperVergeType
2525
import qualified Kernel.External.Verification.Idfy.Config as Idfy
2626
import qualified Kernel.External.Verification.Idfy.Types.Response as Idfy
2727
import qualified Kernel.External.Verification.InternalScripts.Types as FV
28+
import qualified Kernel.External.Verification.Morth.Types as MorthTypes
2829
import qualified Kernel.External.Verification.SafetyPortal.Config as SafetyPortal
2930
import Kernel.External.Verification.SafetyPortal.Types
3031
import qualified Kernel.External.Verification.Tten.Types as TtenTypes
3132
import qualified Kernel.External.Verification.Types as VT
3233
import Kernel.Prelude
3334

34-
data VerificationServiceConfig = IdfyConfig Idfy.IdfyCfg | FaceVerificationConfig FV.FaceVerificationCfg | GovtDataConfig | HyperVergeVerificationConfig HyperVergeTypes.HyperVergeVerificationCfg | HyperVergeVerificationConfigRCDL HyperVergeTypes.HyperVergeRCDLVerificationConfig | DigiLockerConfig DigiTypes.DigiLockerCfg | TtenVerificationConfig TtenTypes.TtenVerificationCfg
35+
data VerificationServiceConfig = IdfyConfig Idfy.IdfyCfg | FaceVerificationConfig FV.FaceVerificationCfg | GovtDataConfig | HyperVergeVerificationConfig HyperVergeTypes.HyperVergeVerificationCfg | HyperVergeVerificationConfigRCDL HyperVergeTypes.HyperVergeRCDLVerificationConfig | DigiLockerConfig DigiTypes.DigiLockerCfg | TtenVerificationConfig TtenTypes.TtenVerificationCfg | MorthConfig MorthTypes.MorthVerificationCfg
3536
deriving stock (Show, Eq, Generic)
3637
deriving anyclass (FromJSON, ToJSON)
3738

@@ -100,7 +101,13 @@ data VerifyRCReq = VerifyRCReq
100101
{ rcNumber :: Text,
101102
driverId :: Text,
102103
token :: Maybe Text,
103-
udinNo :: Maybe Text
104+
udinNo :: Maybe Text,
105+
-- | Engine number (required for MoRTH RC verification)
106+
engineNumber :: Maybe Text,
107+
-- | Chassis number (required for MoRTH RC verification)
108+
chassisNumber :: Maybe Text,
109+
-- | Applicant's mobile number (used by MoRTH RC verification)
110+
applicantMobile :: Maybe Text
104111
}
105112
deriving stock (Show, Generic)
106113

@@ -198,10 +205,22 @@ newtype ExtractRCImageResp = ExtractRCImageResp
198205
}
199206
deriving stock (Show, Generic)
200207

201-
newtype ExtractedRC = ExtractedRC
202-
{ rcNumber :: Maybe Text
208+
data ExtractedRC = ExtractedRC
209+
{ rcNumber :: Maybe Text,
210+
vehicleClass :: Maybe Text,
211+
manufacturer :: Maybe Text,
212+
model :: Maybe Text,
213+
fuelType :: Maybe Text,
214+
colour :: Maybe Text,
215+
chassisNumber :: Maybe Text,
216+
engineNumber :: Maybe Text,
217+
registrationDate :: Maybe Text,
218+
ownerName :: Maybe Text,
219+
manufacturingDate :: Maybe Text,
220+
bodyType :: Maybe Text
203221
}
204222
deriving stock (Show, Generic)
223+
deriving anyclass (FromJSON, ToJSON)
205224

206225
newtype ExtractDLImageResp = ExtractDLImageResp
207226
{ extractedDL :: Maybe ExtractedDL

0 commit comments

Comments
 (0)