135 lines
4.1 KiB
Markdown
135 lines
4.1 KiB
Markdown
# 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.).
|
|
|