# Dealer User Architecture ## Overview **Dealers and regular users are stored in the SAME `users` table.** This is the correct approach because dealers ARE users in the system - they login via SSO, participate in workflows, receive notifications, etc. ## Why Single Table? ### ✅ Advantages: 1. **Unified Authentication**: Dealers login via the same Okta SSO as regular users 2. **Shared Functionality**: Dealers need all user features (notifications, workflow participation, etc.) 3. **Simpler Architecture**: No need for joins or complex queries 4. **Data Consistency**: Single source of truth for all users 5. **Workflow Integration**: Dealers can be approvers, participants, or action takers seamlessly ### ❌ Why NOT Separate Table: - Would require complex joins for every query - Data duplication (email, name, etc. in both tables) - Dealers still need user authentication and permissions - More complex to maintain ## How Dealers Are Identified Dealers are identified using **three criteria** (any one matches): 1. **`employeeId` field starts with `'RE-'`** (e.g., `RE-MH-001`, `RE-DL-002`) - This is the **primary identifier** for dealers - Dealer code is stored in `employeeId` field 2. **`designation` contains `'dealer'`** (case-insensitive) - Example: `"Dealer"`, `"Senior Dealer"`, etc. 3. **`department` contains `'dealer'`** (case-insensitive) - Example: `"Dealer Operations"`, `"Dealer Management"`, etc. ## Database Schema ```sql users { user_id UUID PK email VARCHAR(255) UNIQUE okta_sub VARCHAR(100) UNIQUE -- From Okta SSO employee_id VARCHAR(50) -- For dealers: stores dealer code (RE-MH-001) display_name VARCHAR(255) designation VARCHAR(255) -- For dealers: "Dealer" department VARCHAR(255) -- For dealers: "Dealer Operations" role ENUM('USER', 'MANAGEMENT', 'ADMIN') is_active BOOLEAN -- ... other user fields } ``` ## Example Data ### Regular User: ```json { "userId": "uuid-1", "email": "john.doe@royalenfield.com", "employeeId": "E12345", // Regular employee ID "designation": "Software Engineer", "department": "IT", "role": "USER" } ``` ### Dealer User: ```json { "userId": "uuid-2", "email": "test.2@royalenfield.com", "employeeId": "RE-MH-001", // Dealer code stored here "designation": "Dealer", "department": "Dealer Operations", "role": "USER" } ``` ## Querying Dealers The `dealer.service.ts` uses these filters to find dealers: ```typescript User.findAll({ where: { [Op.or]: [ { designation: { [Op.iLike]: '%dealer%' } }, { employeeId: { [Op.like]: 'RE-%' } }, { department: { [Op.iLike]: '%dealer%' } }, ], isActive: true, } }); ``` ## Seed Script Behavior When running `npm run seed:dealers`: 1. **If user exists (from Okta SSO)**: - ✅ Preserves `oktaSub` (real Okta subject ID) - ✅ Preserves `role` (from Okta) - ✅ Updates `employeeId` with dealer code - ✅ Updates `designation` to "Dealer" (if not already) - ✅ Updates `department` to "Dealer Operations" (if not already) 2. **If user doesn't exist**: - Creates placeholder user - Sets `oktaSub` to `dealer-{code}-pending-sso` - When dealer logs in via SSO, `oktaSub` gets updated automatically ## Workflow Integration Dealers participate in workflows just like regular users: - **As Approvers**: In Steps 1 & 5 of claim management workflow - **As Participants**: Can be added to any workflow - **As Action Takers**: Can submit proposals, completion documents, etc. The system identifies them as dealers by checking `employeeId` starting with `'RE-'` or `designation` containing `'dealer'`. ## API Endpoints - `GET /api/v1/dealers` - Get all dealers (filters users table) - `GET /api/v1/dealers/code/:dealerCode` - Get dealer by code - `GET /api/v1/dealers/email/:email` - Get dealer by email - `GET /api/v1/dealers/search?q=term` - Search dealers All endpoints query the same `users` table with dealer-specific filters. ## Conclusion **✅ Single `users` table is the correct approach.** No separate dealer table needed. Dealers are users with special identification markers (dealer code in `employeeId`, dealer designation, etc.).