From 693d602e49f0e0698d1d9b91e7fbc9164d54638e Mon Sep 17 00:00:00 2001 From: "s.hajizadeh" Date: Tue, 18 Aug 2026 11:18:33 +0330 Subject: [PATCH] sms template corrected and now fires at the end of the fanavaran stage (Expertise). Docs also added. --- docs/fanavaran/01-write-apis.md | 4 +- docs/fanavaran/04-tenant-matrix.md | 2 +- docs/fanavaran/05-claim-flow.md | 6 +- docs/fanavaran/06-yara-integration.md | 2 +- docs/fanavaran/08-dependencies.md | 2 +- docs/fanavaran/09-error-handling.md | 2 +- .../claim-request-management.service.ts | 59 +++++++++++-------- .../entites/schema/claim-cases.schema.ts | 2 +- src/core/config/fanavaran-client.config.ts | 4 +- .../provider/parsian-template-messages.ts | 2 +- .../sms-orchestration.service.ts | 27 ++++++--- 11 files changed, 68 insertions(+), 44 deletions(-) diff --git a/docs/fanavaran/01-write-apis.md b/docs/fanavaran/01-write-apis.md index 03d837f..5e90042 100644 --- a/docs/fanavaran/01-write-apis.md +++ b/docs/fanavaran/01-write-apis.md @@ -127,8 +127,7 @@ Full shape: see skill reference sample and `buildFanavaranSubmitPayload` / `appl | `Id` | `claimCases.claimId` | | `ClaimNo` | `claimCases.claimNo` | -History: `FANAVARAN_EARLY_AUTO_SUBMIT_SUCCEEDED`. -SMS owner via `SmsOrchestrationService` (deduped `fanavaranSync.baseClaim.smsNotifiedAt`). +History: `FANAVARAN_EARLY_AUTO_SUBMIT_SUCCEEDED`. ### Error handling @@ -309,6 +308,7 @@ Requires `claimId` + `dmgCaseId` (soft-ensures earlier stages). | `Id` | `claimCases.expertiseId` | History: `FANAVARAN_EXPERTISE_AUTO_SUBMIT_SUCCEEDED`. +SMS owner via `SmsOrchestrationService` (deduped `fanavaranSync.expertise.smsNotifiedAt`). Proven Parsian: `expertiseId=403144`, `ClaimExpertId=29`. Manual: `POST /v2/fanavaran/{client}/claim-cases/{id}/expertise/submit`. diff --git a/docs/fanavaran/04-tenant-matrix.md b/docs/fanavaran/04-tenant-matrix.md index b8db556..623c7a8 100644 --- a/docs/fanavaran/04-tenant-matrix.md +++ b/docs/fanavaran/04-tenant-matrix.md @@ -31,7 +31,7 @@ source: fanavaran-module-docs | Validation: FileTypeId ∈ tenant lookup | logic ✅ | allowed ids ✅ | | Business: THIRD_PARTY only | ✅ | ❌ | | Provisional address / dummy licence | ✅ today | may customize later | -| SMS template after base claim | shared orchestration | provider/templates may ✅ | +| SMS template after expertise | shared orchestration | provider/templates may ✅ | | Mongo collections / audit schema | ✅ | ❌ | | Offline inquiry seeds | may exist per client | ✅ | diff --git a/docs/fanavaran/05-claim-flow.md b/docs/fanavaran/05-claim-flow.md index 67a3ed8..ffb35b8 100644 --- a/docs/fanavaran/05-claim-flow.md +++ b/docs/fanavaran/05-claim-flow.md @@ -15,13 +15,13 @@ Start local claim → Validate THIRD_PARTY + data readiness → Auth (cached token) → Policy inquiry (resolve-once PolicyId) - → GEN.03 base claim → store claimId / claimNo → SMS owner + → GEN.03 base claim → store claimId / claimNo → SELECT_OUTER_PARTS → GEN.12 damage case → store dmgCaseId → Upload docs/images locally → GEN.07 attachments (per file, best-effort) → Expert pricing ready - → GEN.08 expertise → store expertiseId + → GEN.08 expertise → store expertiseId → SMS owner → End (local completion independent of Fanavaran success) ``` @@ -56,7 +56,6 @@ sequenceDiagram YARA->>FV: POST third-party-car-financial-claims (GEN.03) FV-->>YARA: Id, ClaimNo YARA->>DB: claimId, claimNo, history SUCCESS - YARA->>YARA: SMS owner (deduped) User->>YARA: SELECT_OUTER_PARTS YARA->>YARA: autoSubmitFanavaranDamageCase... @@ -77,6 +76,7 @@ sequenceDiagram YARA->>FV: POST .../expertise (GEN.08) FV-->>YARA: ExpertiseId YARA->>DB: expertiseId, history SUCCESS + YARA->>YARA: SMS owner (deduped) ``` ## Flow diagram (stages + soft-ensure) diff --git a/docs/fanavaran/06-yara-integration.md b/docs/fanavaran/06-yara-integration.md index dc97f6f..560d8f0 100644 --- a/docs/fanavaran/06-yara-integration.md +++ b/docs/fanavaran/06-yara-integration.md @@ -17,7 +17,7 @@ source: fanavaran-module-docs | Tenant config | boot + System Settings | `fanavaran-client-config.service.ts`, `system-settings.*` | | Orchestration | `ClaimRequestManagementModule` | `claim-request-management.service.ts` | | Policy select | same | `fanavaran-policy-selection.ts` | -| SMS after base | `SmsOrchestrationModule` | `sms-orchestration.service.ts` | +| SMS after expertise | `SmsOrchestrationModule` | `sms-orchestration.service.ts` | --- diff --git a/docs/fanavaran/08-dependencies.md b/docs/fanavaran/08-dependencies.md index c820f68..4a07811 100644 --- a/docs/fanavaran/08-dependencies.md +++ b/docs/fanavaran/08-dependencies.md @@ -21,7 +21,7 @@ source: fanavaran-module-docs | Dependency | Role | |------------|------| -| **SMS provider** | Notify owner after successful GEN.03 (`SmsOrchestrationService`; same as login SMS stack) | +| **SMS provider** | Notify owner after successful GEN.08 expertise (`SmsOrchestrationService`; same as login SMS stack) | | **Offline inquiry seeds** | Can supply driver/policy test data without live inquiry | | **Redis / Queue** | **Not** used for Fanavaran stage orchestration today — retries are in-process `setTimeout` + Mongo `nextRetryAt` | diff --git a/docs/fanavaran/09-error-handling.md b/docs/fanavaran/09-error-handling.md index 584f479..f07ecd9 100644 --- a/docs/fanavaran/09-error-handling.md +++ b/docs/fanavaran/09-error-handling.md @@ -69,4 +69,4 @@ Per HTTP step: ## SMS -After successful base claim, owner SMS may be sent once (`smsNotifiedAt`). Failure to SMS should not roll back Fanavaran claim create; treat as separate notification concern. +After successful expertise (last Fanavaran stage), owner SMS may be sent once (`fanavaranSync.expertise.smsNotifiedAt`). Failure to SMS should not roll back Fanavaran expertise submit; treat as separate notification concern. Claims already notified at base claim (`fanavaranSync.baseClaim.smsNotifiedAt`) are not re-notified. diff --git a/src/claim-request-management/claim-request-management.service.ts b/src/claim-request-management/claim-request-management.service.ts index 5ebbe33..0e43bc9 100644 --- a/src/claim-request-management/claim-request-management.service.ts +++ b/src/claim-request-management/claim-request-management.service.ts @@ -5918,6 +5918,13 @@ export class ClaimRequestManagementService { this.logger.log( `[executeFanavaranExpertiseSubmit] Already have expertiseId=${claimCase.expertiseId}; skipping Fanavaran POST`, ); + // Catch-up / deduped: SMS may still be pending if expertise predated this notify. + await this.notifyClaimOwnerFanavaranClaimRegistered({ + claimCaseId, + claimId: claimCase.claimId, + claimNo: claimCase.claimNo, + logPrefix: `[Fanavaran ${clientKey} V2 Expertise]`, + }); return ( (claimCase as any)?.fanavaranSync?.expertise?.response ?? { Id: claimCase.expertiseId, @@ -5982,6 +5989,14 @@ export class ClaimRequestManagementService { }, }); + // Best-effort: SMS after last Fanavaran stage (expertise) succeeds + await this.notifyClaimOwnerFanavaranClaimRegistered({ + claimCaseId, + claimId: claimCase.claimId, + claimNo: claimCase.claimNo, + logPrefix: `[Fanavaran ${clientKey} V2 Expertise]`, + }); + return response.data; } catch (error) { const exchange = this.fanavaranAuditService.captureAxiosExchange(error); @@ -6018,6 +6033,12 @@ export class ClaimRequestManagementService { }; } if (claimCase.expertiseId != null) { + await this.notifyClaimOwnerFanavaranClaimRegistered({ + claimCaseId, + claimId: claimCase.claimId, + claimNo: claimCase.claimNo, + logPrefix, + }); return { attempted: false, submitted: false, @@ -7083,11 +7104,11 @@ export class ClaimRequestManagementService { } /** - * After Fanavaran base claim create succeeds, SMS the claim owner with - * ClaimNo + claimId. Uses SmsOrchestrationService → same provider as login - * for this deployment (`SMS` / `SMS_PROVIDER`). Never throws. + * After Fanavaran expertise (last stage) succeeds, SMS the claim owner with + * publicId + claimId + ClaimNo. Uses SmsOrchestrationService → same provider + * as login for this deployment (`SMS` / `SMS_PROVIDER`). Never throws. */ - private async notifyClaimOwnerFanavaranBaseClaimRegistered(input: { + private async notifyClaimOwnerFanavaranClaimRegistered(input: { claimCaseId: string; claimId?: number | string | null; claimNo?: number | string | null; @@ -7106,7 +7127,9 @@ export class ClaimRequestManagementService { ); if (!claimCase) return; - if ((claimCase as any)?.fanavaranSync?.baseClaim?.smsNotifiedAt) { + const sync = (claimCase as any)?.fanavaranSync; + // Dedup: expertise stage, or older base-claim notify from before the move. + if (sync?.expertise?.smsNotifiedAt || sync?.baseClaim?.smsNotifiedAt) { this.logger.log( `${input.logPrefix} Fanavaran SMS already sent; skipping duplicate`, ); @@ -7127,23 +7150,21 @@ export class ClaimRequestManagementService { : String(input.claimCaseId); const sent = - await this.smsOrchestrationService.sendFanavaranBaseClaimRegisteredNotice( - { - receptor: phone, - publicId, - claimNo: input.claimNo, - claimId: input.claimId, - }, - ); + await this.smsOrchestrationService.sendFanavaranClaimRegisteredNotice({ + receptor: phone, + publicId, + claimNo: input.claimNo ?? claimCase.claimNo, + claimId: input.claimId ?? claimCase.claimId, + }); if (sent) { await this.claimCaseDbService.findByIdAndUpdate(input.claimCaseId, { $set: { - "fanavaranSync.baseClaim.smsNotifiedAt": new Date(), + "fanavaranSync.expertise.smsNotifiedAt": new Date(), }, }); this.logger.log( - `${input.logPrefix} Fanavaran claim SMS sent to claim owner phone=${phone} claimNo=${input.claimNo ?? "-"} claimId=${input.claimId ?? "-"}`, + `${input.logPrefix} Fanavaran claim SMS sent to claim owner phone=${phone} publicId=${publicId} claimNo=${input.claimNo ?? claimCase.claimNo ?? "-"} claimId=${input.claimId ?? claimCase.claimId ?? "-"}`, ); } } catch (error) { @@ -7301,14 +7322,6 @@ export class ClaimRequestManagementService { claimCaseId, updateData, ); - - // Best-effort: same SMS provider as login for this deployment - await this.notifyClaimOwnerFanavaranBaseClaimRegistered({ - claimCaseId, - claimId, - claimNo, - logPrefix, - }); } return response.data; diff --git a/src/claim-request-management/entites/schema/claim-cases.schema.ts b/src/claim-request-management/entites/schema/claim-cases.schema.ts index b34eaae..c5c341e 100644 --- a/src/claim-request-management/entites/schema/claim-cases.schema.ts +++ b/src/claim-request-management/entites/schema/claim-cases.schema.ts @@ -107,7 +107,7 @@ export class FanavaranSyncStage { @Prop({ type: Date }) lastPayloadBuiltAt?: Date; - /** When we SMS'd the claim owner about Fanavaran claimId/ClaimNo (base claim). */ + /** When we SMS'd the claim owner about Fanavaran claimId/ClaimNo (after expertise). */ @Prop({ type: Date }) smsNotifiedAt?: Date; diff --git a/src/core/config/fanavaran-client.config.ts b/src/core/config/fanavaran-client.config.ts index 2120427..9a0aa09 100644 --- a/src/core/config/fanavaran-client.config.ts +++ b/src/core/config/fanavaran-client.config.ts @@ -115,7 +115,7 @@ export const SEED_FANAVARAN_CLIENT_PROFILES: Record< defaults: { ...SHARED_FANAVARAN_DEFAULTS, // GEN.03 — کارشناس مسئول پرونده مالی - ClaimExpertId: 4543092, + ClaimExpertId: 2721, // GEN.08 — ارزیاب (proven successful submit 2026-07-18 ClaimExpertId: 2709) ExpertiseClaimExpertId: 2709, ClaimFileTypeId: 23, @@ -152,7 +152,7 @@ export const SEED_FANAVARAN_CLIENT_PROFILES: Record< password: "itT@l!3@user", corpId: "5650", contractId: "304", - location: "30900", + location: "1", }, // Expert role ids not confirmed for Moallem yet — start from shared shape. defaults: { diff --git a/src/sms-orchestration/provider/parsian-template-messages.ts b/src/sms-orchestration/provider/parsian-template-messages.ts index bb36cbf..7b2a990 100644 --- a/src/sms-orchestration/provider/parsian-template-messages.ts +++ b/src/sms-orchestration/provider/parsian-template-messages.ts @@ -19,7 +19,7 @@ const PARSIAN_TEMPLATE_BODIES: Record = { "yara-signature": "امضای پرونده {token} ({token2}) توسط کارشناس {token3} بررسی شد.\nلینک: {token10}", "yara-fanavaran-claim": - "کاربر گرامی پرونده شما به شماره {token3} در فناوران با شناسه {token2} و شماره {token} ثبت شده است. جهت پیگیری های آتی پرونده خود باید از این اطلاعات استفاده کنید.", + "کاربرگرامی پرونده شما به شماره {token} در سامانه فناوران با شناسه {token2} و شماره پرونده {token3} ثبت شده است. جهت پیگیری های آتی از این اطلاعات استفاده کنید.", }; function applyTokens( diff --git a/src/sms-orchestration/sms-orchestration.service.ts b/src/sms-orchestration/sms-orchestration.service.ts index 459817a..6138675 100644 --- a/src/sms-orchestration/sms-orchestration.service.ts +++ b/src/sms-orchestration/sms-orchestration.service.ts @@ -194,17 +194,18 @@ export class SmsOrchestrationService implements OnModuleInit { } /** - * Notify the claim owner (damaged party) that the Fanavaran base claim was - * created. Uses the same SMS gateway/provider as login for this deployment. + * Notify the claim owner (damaged party) after Fanavaran expertise (last + * stage) succeeds. Uses the same SMS gateway/provider as login. * - * token = ClaimNo, token2 = claimId (Fanavaran Id), token3 = Yara publicId + * token = Yara publicId (claim case number), token2 = Fanavaran claimId, + * token3 = Fanavaran claimNo * * Parsian body: - * کاربر گرامی پرونده شما به شماره {publicId} در فناوران با شناسه {claimId} - * و شماره {claimNo} ثبت شده است. جهت پیگیری های آتی پرونده خود باید از این - * اطلاعات استفاده کنید. + * کاربرگرامی پرونده شما به شماره {publicId} در سامانه فناوران با شناسه + * {claimId} و شماره پرونده {claimNo} ثبت شده است. جهت پیگیری های آتی از + * این اطلاعات استفاده کنید. */ - async sendFanavaranBaseClaimRegisteredNotice(params: { + async sendFanavaranClaimRegisteredNotice(params: { receptor: string; publicId: string; claimNo?: string | number | null; @@ -221,12 +222,22 @@ export class SmsOrchestrationService implements OnModuleInit { return this.sendTemplate({ template: "yara-fanavaran-claim", receptor: params.receptor, - token: params.publicId || "-", + token: params.publicId || "-", token2: claimId, token3: claimNo, }); } + /** @deprecated Use sendFanavaranClaimRegisteredNotice */ + async sendFanavaranBaseClaimRegisteredNotice(params: { + receptor: string; + publicId: string; + claimNo?: string | number | null; + claimId?: string | number | null; + }): Promise { + return this.sendFanavaranClaimRegisteredNotice(params); + } + private async sendTemplate(args: TemplateArgs): Promise { try { await this.smsGatewayService.verifyLookUp(args);