From 92169b0fba2603d974233a2fb806dc10b48a67c8 Mon Sep 17 00:00:00 2001 From: laxmanhalaki Date: Fri, 6 Mar 2026 19:40:02 +0530 Subject: [PATCH] schema enhanced and made nececaasry model changes --- docs/dealer_onboard_backend_schema.mermaid | 253 +++++++++++------- src/common/config/constants.ts | 22 ++ src/database/models/Application.ts | 16 ++ src/database/models/Resignation.ts | 15 ++ src/database/models/TerminationRequest.ts | 17 +- src/emailtemplates/non_opportunity.html | 17 +- .../onboarding/onboarding.controller.ts | 68 +++++ src/modules/onboarding/onboarding.routes.ts | 26 +- .../self-service/constitutional.controller.ts | 34 ++- .../self-service/relocation.controller.ts | 23 +- .../self-service/resignation.controller.ts | 54 +++- .../self-service/resignation.routes.ts | 1 + .../termination/termination.controller.ts | 178 ++++++++++++ src/modules/termination/termination.routes.ts | 15 ++ src/server.ts | 2 + 15 files changed, 608 insertions(+), 133 deletions(-) create mode 100644 src/modules/termination/termination.controller.ts create mode 100644 src/modules/termination/termination.routes.ts diff --git a/docs/dealer_onboard_backend_schema.mermaid b/docs/dealer_onboard_backend_schema.mermaid index 2eb9ef4..b28b986 100644 --- a/docs/dealer_onboard_backend_schema.mermaid +++ b/docs/dealer_onboard_backend_schema.mermaid @@ -241,58 +241,63 @@ erDiagram %% DEALER ENTITY (POST-ONBOARDING) %% ============================================ DEALERS { - uuid dealer_id PK - uuid application_id FK - string dealer_code UK - string dealer_name - string constitution_type - text registered_address - string gst_number - string pan_number + uuid id PK + uuid applicationId FK + uuid dealerCodeId FK + string legalName + string businessName + string constitutionType + text registeredAddress + string gstNumber + string panNumber string status - date activation_date - date last_working_day - boolean portal_access_active + timestamp onboardedAt timestamp created_at timestamp updated_at } %% ============================================ - %% DEALER APPLICATION + %% ONBOARDING APPLICATION (ONBOARDING PHASE) %% ============================================ APPLICATIONS { - uuid application_id PK - string registration_number UK - string applicant_name + uuid id PK + string applicationId UK + uuid opportunityId FK + string applicantName string email UK - string mobile_number - integer age - string country + string phone + string businessType + string preferredLocation + string city string state - string district - string pincode - string interested_city - string company_name - string education_qualification - boolean owns_re_bike - boolean is_existing_dealer - text address + integer experienceYears + string investmentCapacity + integer age + string education + string companyName + string source + string existingDealer + string ownRoyalEnfield + string royalEnfieldModel text description - string preferred_location - string application_status - string opportunity_status - boolean is_shortlisted - boolean dd_lead_shortlisted - uuid assigned_to FK - uuid zone_id FK - uuid region_id FK - uuid area_id FK - uuid assigned_dd_zm FK - uuid assigned_rbm FK + text address + string pincode + string locationType + string currentStage + string overallStatus + integer progressPercentage + boolean isShortlisted + boolean ddLeadShortlisted + decimal score + uuid assignedTo FK + uuid architectureAssignedTo FK + string architectureStatus + uuid submittedBy FK + uuid zoneId FK + uuid regionId FK + uuid areaId FK json documents json timeline - integer progress_percentage - timestamp submitted_at timestamp created_at timestamp updated_at } @@ -660,7 +665,7 @@ erDiagram %% OUTLET MANAGEMENT %% ============================================ OUTLETS { - uuid outlet_id PK + uuid id PK string code UK string name string type @@ -671,8 +676,8 @@ erDiagram decimal latitude decimal longitude string status - date established_date - uuid dealer_id FK + date establishedDate + uuid dealerId FK string region string zone timestamp created_at @@ -699,49 +704,62 @@ erDiagram } %% ============================================ - %% DEALER SELF-SERVICE (SECTION 12) + %% DEALER SERVICE APPLICATIONS (POST-ONBOARDING) + %% Also known as Self-Service or Lifecycle Requests %% ============================================ - DEALER_RESIGNATIONS { - uuid resignation_id PK - uuid dealer_id FK - string outlet_code - date last_operational_date_sales - date last_operational_date_service - date proposed_lwd - string reason_type - text reason_description + RESIGNATIONS { + uuid id PK + string resignationId UK + uuid outletId FK + uuid dealerId FK + string resignationType + date lastOperationalDateSales + date lastOperationalDateServices + text reason + text additionalInfo + string currentStage string status - boolean is_withdrawn - timestamp submitted_at + integer progressPercentage + timestamp submittedOn + json documents + json timeline + text rejectionReason + json departmentalClearances + timestamp created_at timestamp updated_at } - DEALER_RELOCATIONS { - uuid relocation_id PK - uuid dealer_id FK - string current_location_json - string proposed_location_json - decimal distance_km - string property_type - date expected_relocation_date + RELOCATION_REQUESTS { + uuid id PK + string requestId UK + uuid outletId FK + uuid dealerId FK + string relocationType + text newAddress + string newCity + string newState text reason + string currentStage string status - timestamp submitted_at - } - - DEALER_CONSTITUTION_CHANGES { - uuid constitution_change_id PK - string request_id UK - uuid outlet_id FK - uuid dealer_id FK - string change_type - text description - string current_stage - string status - integer progress_percentage + integer progressPercentage + json documents + json timeline + timestamp created_at + timestamp updated_at + } + + CONSTITUTIONAL_CHANGES { + uuid id PK + string requestId UK + uuid outletId FK + uuid dealerId FK + string changeType + text description + string currentStage + string status + integer progressPercentage json documents json timeline - timestamp submitted_at timestamp created_at timestamp updated_at } @@ -883,17 +901,22 @@ erDiagram } %% ============================================ - %% TERMINATION & F&F SETTLEMENT (SECTION 4.3 & 10) + %% TERMINATION (A TYPE OF SERVICE APPLICATION) %% ============================================ TERMINATION_REQUESTS { - uuid termination_id PK - uuid dealer_id FK + uuid id PK + uuid dealerId FK string category text reason - date proposed_lwd + date proposedLwd string status - uuid initiated_by FK + string currentStage + uuid initiatedBy FK + text comments + json timeline + json documents timestamp created_at + timestamp updated_at } TERMINATION_APPROVALS { @@ -907,14 +930,20 @@ erDiagram timestamp created_at } - FNF_CASES { - uuid fnf_id PK - uuid dealer_id FK - uuid source_id FK - string source_type - date last_working_day + FNF_SETTLEMENTS { + uuid id PK + uuid resignationId FK + uuid terminationRequestId FK + uuid outletId FK + uuid dealerId FK string status - timestamp initiated_at + decimal totalReceivables + decimal totalPayables + decimal netAmount + date settlementDate + json clearanceDocuments + timestamp created_at + timestamp updated_at } FNF_DEPARTMENT_CLEARANCES { @@ -1149,6 +1178,26 @@ erDiagram timestamp access_revoked_at } + REQUEST_PARTICIPANTS { + uuid id PK + uuid requestId FK + string requestType + uuid userId FK + string role + boolean isActive + timestamp created_at + timestamp updated_at + } + + %% NOTE: Polymorphic Relationships + %% DOCUMENTS, WORK_NOTES, and REQUEST_PARTICIPANTS + %% use 'requestType' and 'requestId' to link with: + %% - APPLICATIONS (Onboarding) + %% - RESIGNATIONS + %% - RELOCATION_REQUESTS + %% - CONSTITUTIONAL_CHANGES + %% - TERMINATION_REQUESTS + %% ============================================ %% RELATIONSHIPS %% ============================================ @@ -1226,16 +1275,18 @@ erDiagram APPLICATIONS ||--o{ DEALERS : "onboarded_as" DEALERS ||--o{ USERS : "has_portal_users" - DEALERS ||--o{ DEALER_RESIGNATIONS : "initiates" - DEALERS ||--o{ DEALER_RELOCATIONS : "requests" - DEALERS ||--o{ DEALER_CONSTITUTION_CHANGES : "proposes" + DEALERS ||--o{ RESIGNATIONS : "initiates" + DEALERS ||--o{ RELOCATION_REQUESTS : "requests" + DEALERS ||--o{ CONSTITUTIONAL_CHANGES : "proposes" DEALERS ||--o{ TERMINATION_REQUESTS : "terminated_by" TERMINATION_REQUESTS ||--o{ TERMINATION_APPROVALS : "requires" - DEALERS ||--o{ FNF_CASES : "settled_in" - FNF_CASES ||--o{ FNF_DEPARTMENT_CLEARANCES : "requires_NOC_from" - FNF_CASES ||--o{ FNF_SETTLEMENT_SUMMARIES : "consolidated_in" + DEALERS ||--o{ FNF_SETTLEMENTS : "settled_in" + RESIGNATIONS ||--o{ FNF_SETTLEMENTS : "triggers" + TERMINATION_REQUESTS ||--o{ FNF_SETTLEMENTS : "triggers" + FNF_SETTLEMENTS ||--o{ FNF_DEPARTMENT_CLEARANCES : "requires_NOC_from" + FNF_SETTLEMENTS ||--o{ FNF_SETTLEMENT_SUMMARIES : "consolidated_in" DEALERS ||--o{ DEALER_PORTAL_CONFIG : "governed_by" @@ -1271,21 +1322,29 @@ erDiagram SLA_CONFIGURATIONS ||--o{ SLA_CONFIG_REMINDERS : "defines" SLA_CONFIGURATIONS ||--o{ SLA_CONFIG_ESCALATIONS : "defines" - FNF_CASES ||--o{ FNF_LINE_ITEMS : "has" + FNF_SETTLEMENTS ||--o{ FNF_LINE_ITEMS : "has" FNF_DEPARTMENT_CLEARANCES ||--o{ FNF_LINE_ITEMS : "details" USERS ||--o{ FNF_LINE_ITEMS : "added" USERS ||--o{ APPLICATIONS : "currently_assigned" USERS ||--o{ OUTLETS : "has_outlets" - OUTLETS ||--o{ DEALER_CONSTITUTION_CHANGES : "requests_change" + OUTLETS ||--o{ CONSTITUTIONAL_CHANGES : "requests_change" + OUTLETS ||--o{ RELOCATION_REQUESTS : "requests_relocation" + OUTLETS ||--o{ RESIGNATIONS : "initiates_resignation" APPLICATIONS ||--o{ FINANCE_PAYMENTS : "has_payments" USERS ||--o{ FINANCE_PAYMENTS : "verifies_payments" - DEALER_RESIGNATIONS ||--o{ EXIT_FEEDBACK : "has_feedback" + RESIGNATIONS ||--o{ EXIT_FEEDBACK : "has_feedback" TERMINATION_REQUESTS ||--o{ EXIT_FEEDBACK : "has_feedback" USERS ||--o{ EXIT_FEEDBACK : "submitted_by" SLA_TRACKING ||--o{ SLA_BREACHES : "has_breaches" + + APPLICATIONS ||--o{ REQUEST_PARTICIPANTS : "has_participants" + RESIGNATIONS ||--o{ REQUEST_PARTICIPANTS : "has_participants" + TERMINATION_REQUESTS ||--o{ REQUEST_PARTICIPANTS : "has_participants" + RELOCATION_REQUESTS ||--o{ REQUEST_PARTICIPANTS : "has_participants" + CONSTITUTIONAL_CHANGES ||--o{ REQUEST_PARTICIPANTS : "has_participants" diff --git a/src/common/config/constants.ts b/src/common/config/constants.ts index 702d05a..858de56 100644 --- a/src/common/config/constants.ts +++ b/src/common/config/constants.ts @@ -34,6 +34,7 @@ export const APPLICATION_STAGES = { DD_HEAD: 'DD Head', NBH: 'NBH', LEGAL: 'Legal', + ARCHITECTURE: 'Architecture', FINANCE: 'Finance', LEVEL_1_APPROVED: 'Level 1 Approved', LEVEL_2_APPROVED: 'Level 2 Approved', @@ -84,6 +85,24 @@ export const APPLICATION_STATUS = { DISQUALIFIED: 'Disqualified' } as const; +// Termination Stages +export const TERMINATION_STAGES = { + SUBMITTED: 'Submitted', + RBM_REVIEW: 'RBM Review', + ZBH_REVIEW: 'ZBH Review', + DD_LEAD_REVIEW: 'DD Lead Review', + LEGAL_VERIFICATION: 'Legal Verification', + NBH_EVALUATION: 'NBH Evaluation', + SCN_ISSUED: 'Show Cause Notice', + PERSONAL_HEARING: 'Personal Hearing', + NBH_FINAL_APPROVAL: 'NBH Final Approval', + CCO_APPROVAL: 'CCO Approval', + CEO_APPROVAL: 'CEO Final Approval', + LEGAL_LETTER: 'Legal - Termination Letter', + TERMINATED: 'Terminated', + REJECTED: 'Rejected' +} as const; + // Resignation Stages export const RESIGNATION_STAGES = { ASM: 'ASM', @@ -92,6 +111,9 @@ export const RESIGNATION_STAGES = { NBH: 'NBH', DD_ADMIN: 'DD Admin', LEGAL: 'Legal', + SPARES_CLEARANCE: 'Spares Clearance', + SERVICE_CLEARANCE: 'Service Clearance', + ACCOUNTS_CLEARANCE: 'Accounts Clearance', FINANCE: 'Finance', FNF_INITIATED: 'F&F Initiated', COMPLETED: 'Completed', diff --git a/src/database/models/Application.ts b/src/database/models/Application.ts index 91455e1..35966e4 100644 --- a/src/database/models/Application.ts +++ b/src/database/models/Application.ts @@ -31,6 +31,8 @@ export interface ApplicationAttributes { isShortlisted: boolean; ddLeadShortlisted: boolean; assignedTo: string | null; + architectureAssignedTo: string | null; + architectureStatus: string | null; submittedBy: string | null; zoneId: string | null; regionId: string | null; @@ -176,6 +178,19 @@ export default (sequelize: Sequelize) => { key: 'id' } }, + architectureAssignedTo: { + type: DataTypes.UUID, + allowNull: true, + references: { + model: 'users', + key: 'id' + } + }, + architectureStatus: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: 'Pending' + }, submittedBy: { type: DataTypes.UUID, allowNull: true, @@ -231,6 +246,7 @@ export default (sequelize: Sequelize) => { (Application as any).associate = (models: any) => { Application.belongsTo(models.User, { foreignKey: 'submittedBy', as: 'submitter' }); Application.belongsTo(models.User, { foreignKey: 'assignedTo', as: 'assignee' }); + Application.belongsTo(models.User, { foreignKey: 'architectureAssignedTo', as: 'architectureAssignee' }); Application.belongsTo(models.Opportunity, { foreignKey: 'opportunityId', as: 'opportunity' }); Application.belongsTo(models.Zone, { foreignKey: 'zoneId', as: 'zone' }); Application.belongsTo(models.Region, { foreignKey: 'regionId', as: 'region' }); diff --git a/src/database/models/Resignation.ts b/src/database/models/Resignation.ts index 6ea0aa7..da2037c 100644 --- a/src/database/models/Resignation.ts +++ b/src/database/models/Resignation.ts @@ -18,6 +18,12 @@ export interface ResignationAttributes { documents: any[]; timeline: any[]; rejectionReason: string | null; + departmentalClearances: { + spares: boolean; + service: boolean; + accounts: boolean; + logistics: boolean; + } | null; } export interface ResignationInstance extends Model, ResignationAttributes { } @@ -97,6 +103,15 @@ export default (sequelize: Sequelize) => { rejectionReason: { type: DataTypes.TEXT, allowNull: true + }, + departmentalClearances: { + type: DataTypes.JSON, + defaultValue: { + spares: false, + service: false, + accounts: false, + logistics: false + } } }, { tableName: 'resignations', diff --git a/src/database/models/TerminationRequest.ts b/src/database/models/TerminationRequest.ts index e68c74c..4c33f15 100644 --- a/src/database/models/TerminationRequest.ts +++ b/src/database/models/TerminationRequest.ts @@ -7,8 +7,11 @@ export interface TerminationRequestAttributes { reason: string; proposedLwd: Date; status: string; + currentStage: string; initiatedBy: string; comments: string | null; + timeline: any[]; + documents: any[]; } export interface TerminationRequestInstance extends Model, TerminationRequestAttributes { } @@ -42,7 +45,11 @@ export default (sequelize: Sequelize) => { }, status: { type: DataTypes.STRING, - defaultValue: 'pending' + defaultValue: 'Initiated' + }, + currentStage: { + type: DataTypes.STRING, + defaultValue: 'INITIATED' }, initiatedBy: { type: DataTypes.UUID, @@ -55,6 +62,14 @@ export default (sequelize: Sequelize) => { comments: { type: DataTypes.TEXT, allowNull: true + }, + timeline: { + type: DataTypes.JSON, + defaultValue: [] + }, + documents: { + type: DataTypes.JSON, + defaultValue: [] } }, { tableName: 'termination_requests', diff --git a/src/emailtemplates/non_opportunity.html b/src/emailtemplates/non_opportunity.html index 5420a15..fe4c771 100644 --- a/src/emailtemplates/non_opportunity.html +++ b/src/emailtemplates/non_opportunity.html @@ -43,12 +43,17 @@

Dear {{applicantName}},

-

Thank you for showing interest in becoming a Royal Enfield dealer.

-

We have reviewed our current network plan for {{location}}, and currently, there are no - open opportunities available in this area.

-

We have saved your details in our database and will contact you should an opportunity arise in the - future.

-

We appreciate your enthusiasm for the brand.

+

Thank you for your interest in Royal Enfield and for your application to represent our brand as an + authorized dealer.

+

We have carefully reviewed your expression of interest in relation to our current network expansion + strategy for {{location}}. At this juncture, we do not have any immediate vacancies or + planned dealership opportunities available in this specific territory.

+

However, we have successfully retained your profile in our prospective partners database. Rest assured, + our team will proactively reach out to you should a suitable opportunity materialize in this region or + if our strategic requirements in your preferred location evolve further.

+

We appreciate the time you took to share your details and your continued enthusiasm for Royal Enfield. +

+

Best regards,
Dealer Development Team
Royal Enfield