# Business Rules

## Application Workflows

### Lead Lifecycle

```
[Raw Lead] -> [Verified Lead] -> [Client]
                |
                v
         [Not Interested]
                |
                v
          [Call Back]
```

- Leads are created as "raw" (default status)
- `POST /lead/verified/convert` - Converts raw to verified (sets `cnvt_to_verified_at`)
- `POST /lead/client/all/fetch` - Clients (further conversion; `cnvt_to_client_at` tracked)
- `POST /lead/not_interest/convert` - Marks as not interested
- `POST /lead/call_back/convert` - Creates callback entry
- Leads can be claimed, transferred (single/bulk), shared, and prioritized
- Lead phone numbers are normalized in `lead_phones` table (supports multiple phones per lead)
- Lead emails are normalized in `lead_emails` table (supports multiple emails per lead)

### Meeting Lifecycle

```
[Created] -> [Arrived] -> [Started] -> [OTP Sent] -> [OTP Verified] -> [Completed]
                                                                             |
                                                                        [Interested/Not Interested]
                              [Cancelled] (any stage)
```

**Status flow rules:**
1. `meeting_arrived`: Lead arrives within 30-minute window of scheduled time
2. `meeting_started`: Meeting started with GPS coordinates (`start_lat`, `start_long`)
3. `meeting_otp_send`: Sends 4-digit OTP to lead's phone number (country_code + phone)
4. `meeting_otp_verify`: Verifies OTP; clears OTP fields after success
5. `meeting_completed`: Marks completion with interest status, reason, end GPS
6. `meeting_cancel`: Can be cancelled at any stage with reason
7. Active user tracked via `meeting_users.is_active`
8. Rescheduling creates new `meeting_schedule` record (history preserved)

**OTP rules:**
- 4-digit random (1000-9999)
- Expires in 5 minutes
- Sent via SMS API to lead's phone number
- Cleared after successful verification (one-time use)

### Demo Lifecycle

```
[Created] -> [Scheduled] -> [Started] -> [Completed]
                                       -> [Cancelled]
```

- Demos integrate with Google Calendar (optional)
- Google Meet link generated for online demos
- Attendee responses synced via Google Calendar API (`syncAttendeeResponses`)
- Multiple assignees, products, and schedules supported

### Sales & Finance Flow

1. Sale created on a lead (`/lead/sale/create`)
2. Sale has approval status: pending -> approved/rejected
3. Finance team approves via `/finance/sale/approve`
4. Bill raised via `/finance/sale/bill/mark`
5. Payments recorded via `/lead/sale/payment/create`
6. Payment status auto-synced: `unpaid` -> `partial` -> `paid` (via `syncPaymentStatus()`)
7. Incentives can be updated on sales (`/lead/sale/incentive/update`)

### Leave Management

1. Leave types defined (Sick, Casual, Annual, etc.)
2. Leave entitlements assigned to users per period
3. User applies for leave (`/leave/application/create`)
4. Manager approves/rejects (`/leave/application/approve` or `/leave/application/reject`)
5. Approval recorded in `leave_approvals` table
6. Attendance system respects approved leaves

### Attendance Rules

- Check-in and check-out with GPS coordinates and photo
- Boolean status flags (mutually exclusive):
  - `is_present`, `is_absent`, `is_holiday`, `is_weekoff`, `is_halfday`, `is_late`
- Backfill service auto-marks attendance based on:
  - Holidays (from holidays table)
  - Week-offs (from user_working_days)
  - Approved leave applications
  - Remaining: marked absent
- Location tracking during check-in/out period
- Late/halfday determined by shift settings

### Task Management

- Tasks can be assigned to users (via `assigned_to` field)
- Support recurring tasks: daily, weekly, fortnightly, monthly, quarterly, half-yearly, yearly
- Tasks have queries (Q&A thread between assignee and creator)
- Task stages trackable
- Products can be linked to tasks

## User Roles & Permissions

### Permission Structure

Format: `{module}.{sub_module}.{action}`

| Module | Sub-modules | Actions |
|--------|-------------|---------|
| `account_management` | account, document | create, read, update, delete, override |
| `task_management` | task | create, read, update, delete, override |
| `project_management` | project | create, read, update, delete, override |
| `user_management` | user, live_location | create, read, update, delete, override, export, contact |
| `lead_management` | company, raw_lead, verified_lead, client | create, read, update, delete, override, export, contact |
| `quotation_management` | quotation, terms, email_body | create, read, update, delete, override, export |
| `meeting_management` | meeting | create, read, update, delete, override, export |
| `demo_management` | demo | create, read, update, delete, override, export |
| `visit_management` | visit | create, read, delete, export, override |
| `payroll_management` | payroll | create, read, update, delete, override, export |
| `product_management` | product | create, read, update, delete, override, export |
| `leave_management` | leave_type, leave_entitlement, leave_application | create, read, update, delete, override |
| `holiday_management` | holiday | create, read, update, delete, override |
| `finance_management` | finance | read, update, delete, override, export |
| `marketing_management` | templates, campaign | create, read, update, delete, override |
| `report_management` | sales, attendances, calls, activity_log, client_analytics, user_analytics, campaign | read, update, delete, override, export, create |
| `setting` | role, smtp_credential, sms_credential, waba_credential, rcs_credential, payment_type, api_credentials, payslip_signature | create, read, update, delete, override |

### "override" Permission
Acts as a super-admin permission for the given sub-module, bypassing ownership/data-scoping checks (e.g., viewing all leads vs. only assigned leads).

### "contact" Permission (Lead Management)
Allows viewing contact details (phone numbers, emails) of leads. Users without this see masked phone numbers.

## Notifications

- **Push notifications** via Firebase Cloud Messaging (FCM HTTP v1)
- Token stored in `users.fcm_token`
- Notifications triggered for upcoming activities (meetings, demos, follow-ups, callbacks)
- `DispatchUpcomingActivityNotifications` job runs every minute, checks activities within next 15 minutes
- `ScheduledNotificationLog` tracks delivery status
- Activity logging via Spatie Activitylog for audit trail

## Google Calendar Integration

- Two service implementations: `GoogleCalendarService` and `OptimizedGoogleCalendarService`
- Optimized version features: circuit breaker (5 failures = 5min cooldown), token caching (1h TTL), exponential backoff (3 retries)
- Used for demo creation/update/delete/sync
- Credentials via `credentials.json` + stored tokens in `google_tokens`/`google_access_tokens` tables
- Default timezone: `Asia/Kolkata`

## Quick Actions

These are dashboard/shortcut operations:
- Lead claiming: First user to claim gets ownership
- Lead sharing: Share lead with another user
- Impersonation: Admin can impersonate another user (for troubleshooting)
- Bulk operations: Transfer, delete leads in bulk

## Analytics Reports Available

- Dashboard counts (leads, meetings, tasks, projects, demos, visits, sales)
- Call logs chart data
- Sales chart data
- Aggregated lead sales
- Attendance reports (aggregated + detailed)
- User activity logs
- User KPI tracking (calls, meetings, visits, demos, sales, notes, callbacks, follow-ups, quotations, lead conversions)
- Timesheet data per user
- Lead analytics
- User analytics

## Assumptions & Constraints

- **Single timezone**: Asia/Kolkata (Indian market CRM)
- **Indian mobile numbers**: Country code + phone, SMS via Indian provider (Bluewaves Media)
- **Fiscal year**: Supports both calendar (Jan-Dec) and fiscal year (custom start month)
- **No multi-language support**: English only
- **No soft deletes on all tables**: Some tables hard-delete, others soft-delete
- **Phone uniqueness**: `lead_phones.phone` has unique constraint
- **Phone masking**: For users without `contact` permission, phone numbers show `******`
