From b99c1f1026e99688c1770f65019b95eb10a26262 Mon Sep 17 00:00:00 2001 From: Utkarsh Pandey1 Date: Thu, 28 Dec 2023 18:26:34 +0530 Subject: [PATCH 1/4] backend/fix/round_collections --- .../CommonAPIs/src/Dashboard/ProviderPlatform/Revenue.hs | 4 ++-- .../Main/src/Domain/Action/Dashboard/Revenue.hs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Backend/app/dashboard/CommonAPIs/src/Dashboard/ProviderPlatform/Revenue.hs b/Backend/app/dashboard/CommonAPIs/src/Dashboard/ProviderPlatform/Revenue.hs index 9155375b9ac..007666b13f2 100644 --- a/Backend/app/dashboard/CommonAPIs/src/Dashboard/ProviderPlatform/Revenue.hs +++ b/Backend/app/dashboard/CommonAPIs/src/Dashboard/ProviderPlatform/Revenue.hs @@ -49,12 +49,12 @@ data AllFees = AllFees { status :: DriverFeeStatus, numRides :: Int, numDrivers :: Int, - totalAmount :: Centesimal + totalAmount :: Int } deriving (Generic, Show, FromJSON, ToJSON, ToSchema) data CollectionListElem = CollectionListElem - { totalAmount :: Centesimal, + { totalAmount :: Int, totalRides :: Int, numDrivers :: Int, date :: Day, diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/Dashboard/Revenue.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/Dashboard/Revenue.hs index a5edfab77c6..008f5dca0c3 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/Dashboard/Revenue.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/Dashboard/Revenue.hs @@ -63,7 +63,7 @@ getAllFeeFromDriverFee Common.DriverFee {..} = do status' <- readMaybe status_ & fromMaybeM (InvalidRequest "Couldn't find fee's status") numRides' <- readMaybe numRides_ & fromMaybeM (InvalidRequest "Couldn't find fee's ride count") numDrivers' <- readMaybe numDrivers_ & fromMaybeM (InvalidRequest "Couldn't find fee's driver count") - pure $ Common.AllFees status' numRides' numDrivers' totalAmount_ + pure $ Common.AllFees status' numRides' numDrivers' (round totalAmount_) _ -> throwError $ InvalidRequest "Couldn't find driver fee" getCollectionHistory :: ShortId DM.Merchant -> Context.City -> Maybe Text -> Maybe Text -> Maybe UTCTime -> Maybe UTCTime -> Flow Common.CollectionList @@ -102,7 +102,7 @@ getCollectionListElem Common.DriverFee {..} = do numRides' <- readMaybe numRides_ & fromMaybeM (InvalidRequest "Couldn't find fee's ride count") numDrivers' <- readMaybe numDrivers_ & fromMaybeM (InvalidRequest "Couldn't find fee's driver count") date' <- readMaybe date_ & fromMaybeM (InvalidRequest "Couldn't find fee's date") - pure $ Common.CollectionListElem totalAmount_ numRides' numDrivers' date' hour_ + pure $ Common.CollectionListElem (round totalAmount_) numRides' numDrivers' date' hour_ _ -> throwError $ InvalidRequest "Couldn't find driver fee" fetchDatetime :: Text -> String From e3f3bbeb79d4c1d966cfeb49700fcfc184b6152d Mon Sep 17 00:00:00 2001 From: Anuragini Paunikar Date: Thu, 28 Dec 2023 22:13:38 +0530 Subject: [PATCH 2/4] backend/fix/invoice_generated_scheduler_reschedule_fix --- .../Allocator/Jobs/Overlay/SendOverlay.hs | 3 +-- .../Main/src/Storage/Queries/DriverFee.hs | 5 ++++- .../Scheduler/JobStorageType/Redis/Queries.hs | 16 ++++++++-------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator/Jobs/Overlay/SendOverlay.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator/Jobs/Overlay/SendOverlay.hs index 9774fa07f50..11dfb8e87f9 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator/Jobs/Overlay/SendOverlay.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator/Jobs/Overlay/SendOverlay.hs @@ -157,8 +157,7 @@ getBatchedDriverIds merchantId jobId condition freeTrialDays timeDiffFromUtc dri startTime = addUTCTime (-1 * driverPaymentCycleDuration) potentialStartToday endTime = addUTCTime 120 potentialStartToday driverFees <- QDF.findWindowsWithFeeTypeAndLimit merchantId startTime endTime (getFeeType paymentMode) overlayBatchSize - let filteredDriverFees = filter (\dueInvoice -> SLDriverFee.roundToHalf (fromIntegral dueInvoice.govtCharges + dueInvoice.platformFee.fee + dueInvoice.platformFee.cgst + dueInvoice.platformFee.sgst) > 0) driverFees - let driverIds = filteredDriverFees <&> (.driverId) + let driverIds = driverFees <&> (.driverId) void $ QDF.updateDriverFeeOverlayScheduled driverIds True startTime endTime return driverIds _ -> do diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/DriverFee.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/DriverFee.hs index 7d51bb057c8..0d2c52b8894 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/DriverFee.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/DriverFee.hs @@ -176,7 +176,10 @@ findWindowsWithFeeTypeAndLimit merchantId from to feeType limit = Se.Is BeamDF.endTime $ Se.LessThanOrEq to, Se.Is BeamDF.feeType $ Se.Eq feeType, Se.Is BeamDF.merchantId $ Se.Eq merchantId.getId, - Se.Is BeamDF.overlaySent $ Se.Eq False + Se.Is BeamDF.overlaySent $ Se.Eq False, + Se.Is BeamDF.platformFee $ Se.Not (Se.Eq 0.0), + Se.Is BeamDF.cgst $ Se.Not (Se.Eq 0.0), + Se.Is BeamDF.sgst $ Se.Not (Se.Eq 0.0) ] ] (Se.Asc BeamDF.createdAt) diff --git a/Backend/lib/scheduler/src/Lib/Scheduler/JobStorageType/Redis/Queries.hs b/Backend/lib/scheduler/src/Lib/Scheduler/JobStorageType/Redis/Queries.hs index f62eb022908..1619d5c2dda 100644 --- a/Backend/lib/scheduler/src/Lib/Scheduler/JobStorageType/Redis/Queries.hs +++ b/Backend/lib/scheduler/src/Lib/Scheduler/JobStorageType/Redis/Queries.hs @@ -79,13 +79,13 @@ getReadyTasks :: getReadyTasks _ = do key <- asks (.streamName) groupName <- asks (.groupName) - let lastEntryId :: Text = "$" + -- let lastEntryId :: Text = "$" version <- asks (.version) let consumerName = version.getDeploymentVersion let nextId :: Text = ">" - isGroupExist <- Hedis.withNonCriticalCrossAppRedis $ Hedis.xInfoGroups key - unless isGroupExist $ do - Hedis.withNonCriticalCrossAppRedis $ Hedis.xGroupCreate key groupName lastEntryId + -- isGroupExist <- Hedis.withNonCriticalCrossAppRedis $ Hedis.xInfoGroups key + -- unless isGroupExist $ do + -- Hedis.withNonCriticalCrossAppRedis $ Hedis.xGroupCreate key groupName lastEntryId result' <- Hedis.withNonCriticalCrossAppRedis $ Hedis.xReadGroup groupName consumerName [(key, nextId)] let result = maybe [] (concatMap (Hedis.extractKeyValuePairs . records)) result' let recordIds = maybe [] (concatMap (Hedis.extractRecordIds . records)) result' @@ -110,16 +110,16 @@ getReadyTask = do key <- asks (.streamName) groupName <- asks (.groupName) consumerId <- asks (.consumerId) - let lastEntryId :: Text = "$" + -- let lastEntryId :: Text = "$" version <- asks (.version) threadId <- L.runIO myThreadId let consumerName = version.getDeploymentVersion <> consumerId <> show threadId let nextId :: Text = ">" block <- asks (.block) readCount <- asks (.readCount) - isGroupExist <- Hedis.withNonCriticalCrossAppRedis $ Hedis.xInfoGroups key - unless isGroupExist $ do - Hedis.withNonCriticalCrossAppRedis $ Hedis.xGroupCreate key groupName lastEntryId + -- isGroupExist <- Hedis.withNonCriticalCrossAppRedis $ Hedis.xInfoGroups key -- TODO: Enable after fixing these hedis stream operations for cluster redis. + -- unless isGroupExist $ do + -- Hedis.withNonCriticalCrossAppRedis $ Hedis.xGroupCreate key groupName lastEntryId result' <- Hedis.withNonCriticalCrossAppRedis $ Hedis.xReadGroupOpts groupName consumerName [(key, nextId)] (Just block) (Just readCount) let result = maybe [] (concatMap (Hedis.extractKeyValuePairs . records)) result' let recordIds = maybe [] (concatMap (Hedis.extractRecordIds . records)) result' From 1eee9700f9c67f3d34704b54255f8d15763ec5eb Mon Sep 17 00:00:00 2001 From: Akhilesh Bhadauriya Date: Fri, 29 Dec 2023 12:31:53 +0530 Subject: [PATCH 3/4] Backend/fix/geofabrik-fix --- Backend/nix/osrm.nix | 2 +- flake.lock | 6 +++--- flake.nix | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Backend/nix/osrm.nix b/Backend/nix/osrm.nix index 661176f3280..34d4716b922 100644 --- a/Backend/nix/osrm.nix +++ b/Backend/nix/osrm.nix @@ -3,7 +3,7 @@ let openStreetDataFile = inputs.osrm-pbf; # NOTE: This *should* match the flake input. - openStreetDataFileName = "southern-zone-231218"; + openStreetDataFileName = "southern-zone-230101"; in { perSystem = { pkgs, lib, ... }: { diff --git a/flake.lock b/flake.lock index 0ef8a281643..bf78a485d1c 100644 --- a/flake.lock +++ b/flake.lock @@ -2492,13 +2492,13 @@ "osrm-pbf": { "flake": false, "locked": { - "narHash": "sha256-T8yMqZwbdZStSKt1W2NiMdziH5H+kUfkUFu/hCRMHEY=", + "narHash": "sha256-KEpT7YUG3UsaEM4V8vtWVmxU4Mz8gl0gyC6X07GVbao=", "type": "file", - "url": "https://download.geofabrik.de/asia/india/southern-zone-231218.osm.pbf" + "url": "https://download.geofabrik.de/asia/india/southern-zone-230101.osm.pbf" }, "original": { "type": "file", - "url": "https://download.geofabrik.de/asia/india/southern-zone-231218.osm.pbf" + "url": "https://download.geofabrik.de/asia/india/southern-zone-230101.osm.pbf" } }, "passetto-hs": { diff --git a/flake.nix b/flake.nix index 4fecef96ff1..5cfaab5054b 100644 --- a/flake.nix +++ b/flake.nix @@ -26,7 +26,7 @@ # over time. NOTE: This file is not permanent, find the available one at # https://download.geofabrik.de/asia/india/ # NOTE: If you change this, also change `openStreetDataFileName` in osrm.nix - osrm-pbf.url = "https://download.geofabrik.de/asia/india/southern-zone-231218.osm.pbf"; + osrm-pbf.url = "https://download.geofabrik.de/asia/india/southern-zone-230101.osm.pbf"; osrm-pbf.flake = false; easy-purescript-nix.url = "github:justinwoo/easy-purescript-nix/a90bd941297497c83205f0a64f30c5188a2a4fda"; From bcfdb14a2daf3816eb3afaac87984b02a83343df Mon Sep 17 00:00:00 2001 From: hkmangla Date: Sun, 31 Dec 2023 14:35:45 +0530 Subject: [PATCH 4/4] [backend/enhace] add retry merchanism for source down issues in document verification --- .../Dashboard/ProviderPlatform/Merchant.hs | 3 + .../Allocator/src/App.hs | 2 + .../Main/dynamic-offer-driver-app.cabal | 1 + .../src/Domain/Action/Dashboard/Merchant.hs | 3 +- .../UI/DriverOnboarding/DriverLicense.hs | 1 + .../Action/UI/DriverOnboarding/IdfyWebhook.hs | 39 ++++++-- .../VehicleRegistrationCertificate.hs | 1 + .../DriverOnboarding/IdfyVerification.hs | 1 + .../Merchant/OnboardingDocumentConfig.hs | 1 + .../Main/src/SharedLogic/Allocator.hs | 11 +++ .../Jobs/Document/VerificationRetry.hs | 90 +++++++++++++++++++ .../Beam/DriverOnboarding/IdfyVerification.hs | 1 + .../Beam/Merchant/OnboardingDocumentConfig.hs | 1 + .../DriverOnboarding/IdfyVerification.hs | 9 ++ .../Merchant/OnboardingDocumentConfig.hs | 3 + .../0332-source-down-retry.sql | 3 + .../dev/dynamic-offer-driver-app.dhall | 4 + 17 files changed, 165 insertions(+), 9 deletions(-) create mode 100644 Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator/Jobs/Document/VerificationRetry.hs create mode 100644 Backend/dev/migrations/dynamic-offer-driver-app/0332-source-down-retry.sql diff --git a/Backend/app/dashboard/CommonAPIs/src/Dashboard/ProviderPlatform/Merchant.hs b/Backend/app/dashboard/CommonAPIs/src/Dashboard/ProviderPlatform/Merchant.hs index 15d17d59131..20ee3e641de 100644 --- a/Backend/app/dashboard/CommonAPIs/src/Dashboard/ProviderPlatform/Merchant.hs +++ b/Backend/app/dashboard/CommonAPIs/src/Dashboard/ProviderPlatform/Merchant.hs @@ -476,6 +476,7 @@ data OnboardingDocumentConfigItem = OnboardingDocumentConfigItem vehicleClassCheckType :: VehicleClassCheckType, rcNumberPrefix :: Text, rcNumberPrefixList :: Maybe [Text], + maxRetryCount :: Int, createdAt :: UTCTime, updatedAt :: UTCTime } @@ -557,6 +558,7 @@ data OnboardingDocumentConfigUpdateReq = OnboardingDocumentConfigUpdateReq supportedVehicleClasses :: Maybe SupportedVehicleClasses, -- value wrapper make no sense for lists and objects rcNumberPrefix :: Maybe (MandatoryValue Text), rcNumberPrefixList :: Maybe (MandatoryValue [Text]), + maxRetryCount :: Maybe (MandatoryValue Int), vehicleClassCheckType :: Maybe (MandatoryValue VehicleClassCheckType) } deriving stock (Show, Generic) @@ -582,6 +584,7 @@ data OnboardingDocumentConfigCreateReq = OnboardingDocumentConfigCreateReq supportedVehicleClasses :: SupportedVehicleClasses, rcNumberPrefix :: Text, rcNumberPrefixList :: Maybe [Text], + maxRetryCount :: Int, vehicleClassCheckType :: VehicleClassCheckType } deriving stock (Show, Generic) diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Allocator/src/App.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Allocator/src/App.hs index 3355732992a..72ba9b4c4f1 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Allocator/src/App.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Allocator/src/App.hs @@ -36,6 +36,7 @@ import Kernel.Utils.Servant.SignatureAuth import Lib.Scheduler import qualified Lib.Scheduler.JobStorageType.SchedulerType as QAllJ import SharedLogic.Allocator +import SharedLogic.Allocator.Jobs.Document.VerificationRetry import SharedLogic.Allocator.Jobs.DriverFeeUpdates.BadDebtCalculationScheduler import SharedLogic.Allocator.Jobs.DriverFeeUpdates.DriverFee import SharedLogic.Allocator.Jobs.Mandate.Execution (startMandateExecutionForDriver) @@ -71,6 +72,7 @@ allocatorHandle flowRt env = & putJobHandlerInList (liftIO . runFlowR flowRt env . notificationAndOrderStatusUpdate) & putJobHandlerInList (liftIO . runFlowR flowRt env . sendOverlayToDriver) & putJobHandlerInList (liftIO . runFlowR flowRt env . badDebtCalculation) + & putJobHandlerInList (liftIO . runFlowR flowRt env . retryDocumentVerificationJob) } runDriverOfferAllocator :: diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/dynamic-offer-driver-app.cabal b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/dynamic-offer-driver-app.cabal index 22d325dd1dd..151f0b968e0 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/dynamic-offer-driver-app.cabal +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/dynamic-offer-driver-app.cabal @@ -287,6 +287,7 @@ library Lib.Mesh Lib.Schema SharedLogic.Allocator + SharedLogic.Allocator.Jobs.Document.VerificationRetry SharedLogic.Allocator.Jobs.DriverFeeUpdates.BadDebtCalculationScheduler SharedLogic.Allocator.Jobs.DriverFeeUpdates.DriverFee SharedLogic.Allocator.Jobs.Mandate.Execution diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/Dashboard/Merchant.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/Dashboard/Merchant.hs index 91bdbc27ceb..cc23923ce37 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/Dashboard/Merchant.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/Dashboard/Merchant.hs @@ -460,7 +460,8 @@ onboardingDocumentConfigUpdate merchantShortId opCity reqDocumentType req = do supportedVehicleClasses = maybe config.supportedVehicleClasses castSupportedVehicleClasses req.supportedVehicleClasses, vehicleClassCheckType = maybe config.vehicleClassCheckType (castVehicleClassCheckType . (.value)) req.vehicleClassCheckType, rcNumberPrefix = maybe config.rcNumberPrefix (.value) req.rcNumberPrefix, - rcNumberPrefixList = maybe config.rcNumberPrefixList (.value) req.rcNumberPrefixList + rcNumberPrefixList = maybe config.rcNumberPrefixList (.value) req.rcNumberPrefixList, + maxRetryCount = maybe config.maxRetryCount (.value) req.maxRetryCount } _ <- CQODC.update updConfig CQODC.clearCache merchantOpCityId diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/DriverLicense.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/DriverLicense.hs index 82d1ff857ff..dcdb3918c20 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/DriverLicense.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/DriverLicense.hs @@ -172,6 +172,7 @@ verifyDLFlow person merchantOpCityId onboardingDocumentConfig dlNumber driverDat idfyResponse = Nothing, multipleRC = Nothing, -- added for backward compatibility dashboardPassedVehicleVariant = Nothing, + retryCount = 0, createdAt = now, updatedAt = now } diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/IdfyWebhook.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/IdfyWebhook.hs index 7c96eff09ed..d3cf38ff1db 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/IdfyWebhook.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/IdfyWebhook.hs @@ -21,9 +21,11 @@ module Domain.Action.UI.DriverOnboarding.IdfyWebhook ) where +import Control.Applicative ((<|>)) import qualified Domain.Action.UI.DriverOnboarding.DriverLicense as DL import qualified Domain.Action.UI.DriverOnboarding.Status as Status import qualified Domain.Action.UI.DriverOnboarding.VehicleRegistrationCertificate as RC +import qualified Domain.Types.DriverOnboarding.IdfyVerification as IV import qualified Domain.Types.Merchant as DM import qualified Domain.Types.Merchant.MerchantServiceConfig as DMSC import Environment @@ -36,6 +38,8 @@ import Kernel.Types.Beckn.Context as Context import Kernel.Types.Error import Kernel.Types.Id import Kernel.Utils.Common +import Lib.Scheduler.JobStorageType.SchedulerType (createJobIn) +import SharedLogic.Allocator import SharedLogic.Merchant (findMerchantByShortId) import qualified Storage.CachedQueries.Merchant.MerchantOperatingCity as CQMOC import qualified Storage.CachedQueries.Merchant.MerchantServiceConfig as CQMSC @@ -111,18 +115,37 @@ idfyWebhookV2Handler merchantShortId opCity secret val = do onVerify :: Idfy.VerificationResponse -> Text -> Flow AckResponse onVerify resp respDump = do verificationReq <- IVQuery.findByRequestId resp.request_id >>= fromMaybeM (InternalError "Verification request not found") - _ <- IVQuery.updateResponse resp.request_id resp.status respDump - - ack_ <- maybe (pure Ack) (verifyDocument verificationReq) resp.result - person <- runInReplica $ QP.findById verificationReq.driverId >>= fromMaybeM (PersonDoesNotExist verificationReq.driverId.getId) - -- running statusHandler to enable Driver - _ <- Status.statusHandler (verificationReq.driverId, person.merchantId, person.merchantOperatingCityId) verificationReq.multipleRC - - return ack_ + IVQuery.updateResponse resp.request_id resp.status respDump + let resultStatus = getResultStatus resp.result + if resultStatus == (Just "source_down") + then do + scheduleRetryVerificationJob verificationReq + return Ack + else do + ack_ <- maybe (pure Ack) (verifyDocument verificationReq) resp.result + person <- runInReplica $ QP.findById verificationReq.driverId >>= fromMaybeM (PersonDoesNotExist verificationReq.driverId.getId) + -- running statusHandler to enable Driver + void $ Status.statusHandler (verificationReq.driverId, person.merchantId, person.merchantOperatingCityId) verificationReq.multipleRC + return ack_ where + getResultStatus mbResult = mbResult >>= (\rslt -> (rslt.extraction_output >>= (.status)) <|> (rslt.source_output >>= (.status))) verifyDocument verificationReq rslt | isJust rslt.extraction_output = maybe (pure Ack) (RC.onVerifyRC verificationReq) rslt.extraction_output | isJust rslt.source_output = maybe (pure Ack) (DL.onVerifyDL verificationReq) rslt.source_output | otherwise = pure Ack + +scheduleRetryVerificationJob :: IV.IdfyVerification -> Flow () +scheduleRetryVerificationJob verificationReq = do + maxShards <- asks (.maxShards) + let scheduleTime = calculateScheduleTime verificationReq.retryCount + createJobIn @_ @'RetryDocumentVerification scheduleTime maxShards $ + RetryDocumentVerificationJobData + { requestId = verificationReq.requestId + } + where + calculateScheduleTime retryCount = do + let retryInterval = 60 * 60 * 1000 -- 1 hour + let retryTime = retryInterval * (3 ^ retryCount) + retryTime diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/VehicleRegistrationCertificate.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/VehicleRegistrationCertificate.hs index 1e09033151b..aebc2b49cba 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/VehicleRegistrationCertificate.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Action/UI/DriverOnboarding/VehicleRegistrationCertificate.hs @@ -243,6 +243,7 @@ verifyRCFlow person merchantOpCityId imageExtraction rcNumber imageId dateOfRegi idfyResponse = Nothing, multipleRC, dashboardPassedVehicleVariant = mbVariant, + retryCount = 0, createdAt = now, updatedAt = now } diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Types/DriverOnboarding/IdfyVerification.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Types/DriverOnboarding/IdfyVerification.hs index a07b73eed17..417fafc75d7 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Types/DriverOnboarding/IdfyVerification.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Types/DriverOnboarding/IdfyVerification.hs @@ -52,6 +52,7 @@ data IdfyVerificationE e = IdfyVerification idfyResponse :: Maybe Text, multipleRC :: Maybe Bool, dashboardPassedVehicleVariant :: Maybe Vehicle.Variant, + retryCount :: Int, createdAt :: UTCTime, updatedAt :: UTCTime } diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Types/Merchant/OnboardingDocumentConfig.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Types/Merchant/OnboardingDocumentConfig.hs index 2105ac78acc..6ea9dcdbfb8 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Types/Merchant/OnboardingDocumentConfig.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Domain/Types/Merchant/OnboardingDocumentConfig.hs @@ -50,6 +50,7 @@ data OnboardingDocumentConfig = OnboardingDocumentConfig vehicleClassCheckType :: VehicleClassCheckType, rcNumberPrefix :: Text, rcNumberPrefixList :: [Text], + maxRetryCount :: Int, createdAt :: UTCTime, updatedAt :: UTCTime } diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator.hs index d6b8594a58f..b357ecfc5ec 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator.hs @@ -42,6 +42,7 @@ data AllocatorJobType | OrderAndNotificationStatusUpdate | SendOverlay | BadDebtCalculation + | RetryDocumentVerification deriving (Generic, FromDhall, Eq, Ord, Show, Read, FromJSON, ToJSON) genSingletons [''AllocatorJobType] @@ -59,6 +60,7 @@ instance JobProcessor AllocatorJobType where restoreAnyJobInfo SOrderAndNotificationStatusUpdate jobData = AnyJobInfo <$> restoreJobInfo SOrderAndNotificationStatusUpdate jobData restoreAnyJobInfo SSendOverlay jobData = AnyJobInfo <$> restoreJobInfo SSendOverlay jobData restoreAnyJobInfo SBadDebtCalculation jobData = AnyJobInfo <$> restoreJobInfo SBadDebtCalculation jobData + restoreAnyJobInfo SRetryDocumentVerification jobData = AnyJobInfo <$> restoreJobInfo SRetryDocumentVerification jobData data SendSearchRequestToDriverJobData = SendSearchRequestToDriverJobData { searchTryId :: Id DST.SearchTry, @@ -142,6 +144,15 @@ instance JobInfoProcessor 'CalculateDriverFees type instance JobContent 'CalculateDriverFees = CalculateDriverFeesJobData +data RetryDocumentVerificationJobData = RetryDocumentVerificationJobData + { requestId :: Text + } + deriving (Generic, Show, Eq, FromJSON, ToJSON) + +instance JobInfoProcessor 'RetryDocumentVerification + +type instance JobContent 'RetryDocumentVerification = RetryDocumentVerificationJobData + data OrderAndNotificationStatusUpdateJobData = OrderAndNotificationStatusUpdateJobData { merchantId :: Id DM.Merchant, merchantOperatingCityId :: Maybe (Id DMOC.MerchantOperatingCity) diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator/Jobs/Document/VerificationRetry.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator/Jobs/Document/VerificationRetry.hs new file mode 100644 index 00000000000..eaf487e49f3 --- /dev/null +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/SharedLogic/Allocator/Jobs/Document/VerificationRetry.hs @@ -0,0 +1,90 @@ +{- + Copyright 2022-23, Juspay India Pvt Ltd + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License + + as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program + + is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of + + the GNU Affero General Public License along with this program. If not, see . +-} + +module SharedLogic.Allocator.Jobs.Document.VerificationRetry + ( retryDocumentVerificationJob, + ) +where + +import Domain.Types.DriverOnboarding.IdfyVerification +import qualified Domain.Types.DriverOnboarding.Image as Image +import qualified Domain.Types.Merchant.OnboardingDocumentConfig as DTO +import Kernel.Beam.Functions as B +import Kernel.External.Encryption (decrypt) +import Kernel.Prelude +import Kernel.Storage.Esqueleto.Config +import Kernel.Types.Error +import Kernel.Utils.Common +import Lib.Scheduler +import SharedLogic.Allocator (AllocatorJobType (..)) +import SharedLogic.GoogleTranslate (TranslateFlow) +import qualified Storage.CachedQueries.Merchant.OnboardingDocumentConfig as QODC +import qualified Storage.Queries.DriverOnboarding.IdfyVerification as IVQuery +import qualified Storage.Queries.Person as QP +import Tools.Error +import qualified Tools.Verification as Verification + +retryDocumentVerificationJob :: + ( TranslateFlow m r, + EsqDBReplicaFlow m r, + CacheFlow m r, + EsqDBFlow m r + ) => + Job 'RetryDocumentVerification -> + m ExecutionResult +retryDocumentVerificationJob Job {id, jobInfo} = withLogTag ("JobId-" <> id.getId) do + let jobData = jobInfo.jobData + verificationReq <- IVQuery.findByRequestId jobData.requestId >>= fromMaybeM (InternalError "Verification request not found") + person <- runInReplica $ QP.findById verificationReq.driverId >>= fromMaybeM (PersonDoesNotExist verificationReq.driverId.getId) + onboardingDocumentConfig <- QODC.findByMerchantOpCityIdAndDocumentType person.merchantOperatingCityId (castDoctype verificationReq.docType) >>= fromMaybeM (OnboardingDocumentConfigNotFound person.merchantOperatingCityId.getId (show verificationReq.docType)) + let maxRetryCount = onboardingDocumentConfig.maxRetryCount + if verificationReq.retryCount <= maxRetryCount + then do + documentNumber <- decrypt verificationReq.documentNumber + IVQuery.updateStatus verificationReq.requestId "source_down_retried" + case verificationReq.docType of + Image.VehicleRegistrationCertificate -> do + verifyRes <- + Verification.verifyRCAsync person.merchantId person.merchantOperatingCityId $ + Verification.VerifyRCAsyncReq {rcNumber = documentNumber, driverId = person.id.getId} + mkNewVerificationEntity verificationReq verifyRes.requestId + Image.DriverLicense -> do + whenJust verificationReq.driverDateOfBirth $ \dob -> do + verifyRes <- + Verification.verifyDLAsync person.merchantId person.merchantOperatingCityId $ + Verification.VerifyDLAsyncReq {dlNumber = documentNumber, dateOfBirth = dob, driverId = person.id.getId} + mkNewVerificationEntity verificationReq verifyRes.requestId + else do + IVQuery.updateStatus verificationReq.requestId "source_down_failed" + return Complete + where + castDoctype :: Image.ImageType -> DTO.DocumentType + castDoctype docType = + case docType of + Image.VehicleRegistrationCertificate -> DTO.RC + Image.DriverLicense -> DTO.DL + + mkNewVerificationEntity verificationReq requestId = do + now <- getCurrentTime + newId <- generateGUID + let newVerificationReq = + verificationReq + { id = newId, + retryCount = verificationReq.retryCount + 1, + status = "source_down_retrying", + requestId, + createdAt = now, + updatedAt = now + } + IVQuery.create newVerificationReq diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Beam/DriverOnboarding/IdfyVerification.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Beam/DriverOnboarding/IdfyVerification.hs index ca84ff0b755..199fbf177b8 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Beam/DriverOnboarding/IdfyVerification.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Beam/DriverOnboarding/IdfyVerification.hs @@ -41,6 +41,7 @@ data IdfyVerificationT f = IdfyVerificationT idfyResponse :: B.C f (Maybe Text), multipleRC :: B.C f (Maybe Bool), dashboardPassedVehicleVariant :: B.C f (Maybe Vehicle.Variant), + retryCount :: B.C f (Maybe Int), createdAt :: B.C f UTCTime, updatedAt :: B.C f UTCTime } diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Beam/Merchant/OnboardingDocumentConfig.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Beam/Merchant/OnboardingDocumentConfig.hs index aa89fd336cc..e8a6b1dce32 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Beam/Merchant/OnboardingDocumentConfig.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Beam/Merchant/OnboardingDocumentConfig.hs @@ -33,6 +33,7 @@ data OnboardingDocumentConfigT f = OnboardingDocumentConfigT supportedVehicleClassesJSON :: B.C f A.Value, rcNumberPrefix :: B.C f Text, rcNumberPrefixList :: B.C f [Text], + maxRetryCount :: B.C f Int, vehicleClassCheckType :: B.C f Domain.VehicleClassCheckType, createdAt :: B.C f UTCTime, updatedAt :: B.C f UTCTime diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/DriverOnboarding/IdfyVerification.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/DriverOnboarding/IdfyVerification.hs index f444901f1c4..5a8f22d182d 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/DriverOnboarding/IdfyVerification.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/DriverOnboarding/IdfyVerification.hs @@ -51,6 +51,13 @@ updateResponse requestId status resp = do [Se.Set BeamIV.status status, Se.Set BeamIV.idfyResponse $ Just resp, Se.Set BeamIV.updatedAt now] [Se.Is BeamIV.requestId (Se.Eq requestId)] +updateStatus :: (MonadFlow m, EsqDBFlow m r, CacheFlow m r) => Text -> Text -> m () +updateStatus requestId status = do + now <- getCurrentTime + updateWithKV + [Se.Set BeamIV.status status, Se.Set BeamIV.updatedAt now] + [Se.Is BeamIV.requestId (Se.Eq requestId)] + updateExtractValidationStatus :: (MonadFlow m, EsqDBFlow m r, CacheFlow m r) => Text -> ImageExtractionValidation -> m () updateExtractValidationStatus requestId status = do now <- getCurrentTime @@ -70,6 +77,7 @@ instance FromTType' BeamIV.IdfyVerification IdfyVerification where documentImageId1 = Id documentImageId1, documentImageId2 = Id <$> documentImageId2, dashboardPassedVehicleVariant = dashboardPassedVehicleVariant, + retryCount = fromMaybe 0 retryCount, driverId = Id driverId, requestId = requestId, docType = docType, @@ -91,6 +99,7 @@ instance ToTType' BeamIV.IdfyVerification IdfyVerification where BeamIV.documentImageId1 = getId documentImageId1, BeamIV.documentImageId2 = getId <$> documentImageId2, BeamIV.dashboardPassedVehicleVariant = dashboardPassedVehicleVariant, + BeamIV.retryCount = Just retryCount, BeamIV.driverId = getId driverId, BeamIV.requestId = requestId, BeamIV.docType = docType, diff --git a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/Merchant/OnboardingDocumentConfig.hs b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/Merchant/OnboardingDocumentConfig.hs index 8870b07c261..fac75b40325 100644 --- a/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/Merchant/OnboardingDocumentConfig.hs +++ b/Backend/app/provider-platform/dynamic-offer-driver-app/Main/src/Storage/Queries/Merchant/OnboardingDocumentConfig.hs @@ -51,6 +51,7 @@ update config = do Se.Set BeamODC.vehicleClassCheckType (config.vehicleClassCheckType), Se.Set BeamODC.rcNumberPrefix (config.rcNumberPrefix), Se.Set BeamODC.rcNumberPrefixList (config.rcNumberPrefixList), + Se.Set BeamODC.maxRetryCount (config.maxRetryCount), Se.Set BeamODC.updatedAt now ] [Se.Is BeamODC.merchantOperatingCityId $ Se.Eq $ getId config.merchantOperatingCityId, Se.Is BeamODC.documentType $ Se.Eq config.documentType] @@ -73,6 +74,7 @@ instance FromTType' BeamODC.OnboardingDocumentConfig OnboardingDocumentConfig wh vehicleClassCheckType = vehicleClassCheckType, rcNumberPrefix = rcNumberPrefix, rcNumberPrefixList = rcNumberPrefixList, + maxRetryCount = maxRetryCount, createdAt = createdAt, updatedAt = updatedAt } @@ -100,6 +102,7 @@ instance ToTType' BeamODC.OnboardingDocumentConfig OnboardingDocumentConfig wher BeamODC.vehicleClassCheckType = vehicleClassCheckType, BeamODC.rcNumberPrefix = rcNumberPrefix, BeamODC.rcNumberPrefixList = rcNumberPrefixList, + BeamODC.maxRetryCount = maxRetryCount, BeamODC.createdAt = createdAt, BeamODC.updatedAt = updatedAt } diff --git a/Backend/dev/migrations/dynamic-offer-driver-app/0332-source-down-retry.sql b/Backend/dev/migrations/dynamic-offer-driver-app/0332-source-down-retry.sql new file mode 100644 index 00000000000..983c956afcd --- /dev/null +++ b/Backend/dev/migrations/dynamic-offer-driver-app/0332-source-down-retry.sql @@ -0,0 +1,3 @@ + +alter table atlas_driver_offer_bpp.onboarding_document_configs add column max_retry_count int not null default 4; +alter table atlas_driver_offer_bpp.idfy_verification add column retry_count int; \ No newline at end of file diff --git a/Backend/dhall-configs/dev/dynamic-offer-driver-app.dhall b/Backend/dhall-configs/dev/dynamic-offer-driver-app.dhall index 22319fbe86d..b69f606f7d9 100644 --- a/Backend/dhall-configs/dev/dynamic-offer-driver-app.dhall +++ b/Backend/dhall-configs/dev/dynamic-offer-driver-app.dhall @@ -187,6 +187,7 @@ let AllocatorJobType = | OrderAndNotificationStatusUpdate | SendOverlay | BadDebtCalculation + | RetryDocumentVerification > let jobInfoMapx = @@ -208,6 +209,9 @@ let jobInfoMapx = } , { mapKey = AllocatorJobType.SendOverlay, mapValue = True } , { mapKey = AllocatorJobType.BadDebtCalculation, mapValue = True } + , { mapKey = AllocatorJobType.RetryDocumentVerification + , mapValue = False + } ] let LocationTrackingeServiceConfig = { url = "http://localhost:8081/" }