# Questionnaire and Inventory Leads Module - Deep Analysis

## Overview
This module is a sophisticated lead management system integrated with dynamic questionnaires and inventory selection capabilities. It enables sales teams to create leads, collect detailed requirement information through questionnaires, and automatically suggest/select inventory items based on questionnaire responses.

---

## 1. Core Architecture

### 1.1 Module Components

```
Questionnaire & Inventory Leads Module
├── Lead Management
│   ├── Lead Creation & Management
│   ├── Lead Status Pipeline
│   └── Lead Conversion
├── Questionnaire System
│   ├── Template Management
│   ├── Question Management
│   └── Conditional Logic & Response Handling
├── Inventory Integration
│   ├── Category Management
│   ├── Item Management
│   ├── Questionnaire-Inventory Mapping
│   └── Lead Inventory Selections
└── Allocation & Tracking
    ├── Inventory Allocations
    └── Lead Inventory Summaries
```

---

## 2. Data Models & Relationships

### 2.1 Lead Model (`Lead.php`)

**Purpose**: Central entity representing a prospective client/customer

**Key Attributes**:
```
Basic Information:
- company_name (string)
- contact_person_name (string)
- mobile_number (string)
- email (string)
- address, city, state, country, postal_code

Service Requirements:
- service_type_id (FK → ServiceType)
- guard_type (armed/unarmed/both)
- tentative_guards_count (integer)
- working_hours_type (8/12/24/custom hours)
- custom_working_hours (text)
- site_type (office/factory/residential/event/retail/hospital/educational/other)
- service_location (string)

Lead Tracking:
- lead_source (walk_in/reference/website/call/marketing/other)
- assigned_sales_exec_id (FK → User)
- lead_status (new/contacted/qualified/proposal_sent/negotiation/closed_won/closed_lost)

Compliance & Budget:
- compliance_required (yes/no)
- rba_applicable (boolean)
- budget_range_min (integer)
- budget_range_max (integer)

Follow-up & Conversion:
- sales_notes (text)
- client_expectations (text)
- follow_up_date (date)
- next_action (text)
- converted_to_client_id (FK → Client)
- converted_at (datetime)

System:
- tenant_id (UUID) - Multi-tenancy support
- timestamps & soft deletes
```

**Relationships**:
- `HasMany` → LeadQuestionnaireResponse
- `HasMany` → LeadInventorySelection
- `BelongsTo` → ServiceType
- `BelongsTo` → User (assigned_sales_exec_id)
- `BelongsTo` → Client (converted_to_client_id)

---

### 2.2 Questionnaire System Models

#### 2.2.1 QuestionnaireTemplate
**Purpose**: Template for collecting standardized requirements from leads per service type

**Key Attributes**:
```
- name (string) - Template name
- description (text) - Template description
- service_type_id (FK → ServiceType)
- is_active (boolean) - Control template availability
- tenant_id (UUID)
```

**Relationships**:
- `HasMany` → QuestionnaireQuestion (ordered by display_order)
- `HasMany` → activeQuestions (scope for non-deleted questions)
- `BelongsTo` → ServiceType

**Scopes**:
- `active()` - Only active templates
- `byServiceType($id)` - Filter by service type
- `forTenant($id)` - Multi-tenant filtering

---

#### 2.2.2 QuestionnaireQuestion
**Purpose**: Individual questions within a questionnaire template

**Key Attributes**:
```
- questionnaire_template_id (FK)
- question_text (string) - The actual question
- question_type (enum):
  * text, textarea, email, number (text inputs)
  * mcq (multiple choice)
  * checkbox (multi-select)
  * dropdown (select)
  * file (file upload)
  * date (date picker)
- is_mandatory (boolean) - Validation control
- options (JSON) - Question options for MCQ/checkbox/dropdown
  Example: ["Option 1", "Option 2", "Option 3"]
- conditional_logic (JSON) - Show/hide based on other answers
  Example: {"question_id": "xyz", "expected_answer": "yes"}
- display_order (integer) - Ordering in template
- help_text (text) - Help text for respondent
- tenant_id (UUID)
```

**Relationships**:
- `BelongsTo` → QuestionnaireTemplate

**Methods**:
- `getValidationRules()` - Generates Laravel validation rules based on question type and mandatory status

**Scopes**:
- `byTemplate($id)` - Questions for specific template
- `forTenant($id)` - Multi-tenant filtering

---

#### 2.2.3 LeadQuestionnaireResponse
**Purpose**: Stores answers provided by leads to questionnaire questions

**Key Attributes**:
```
- lead_id (FK → Lead)
- questionnaire_question_id (FK → QuestionnaireQuestion)
- answer (longText) - The answer provided
- answer_metadata (JSON) - Additional data, e.g., for file uploads
  Example: {"file_path": "...", "file_size": "...", "mime_type": "..."}
- tenant_id (UUID)
```

**Unique Constraint**: `(lead_id, questionnaire_question_id)` - One answer per lead-question pair

**Relationships**:
- `BelongsTo` → Lead
- `BelongsTo` → QuestionnaireQuestion

**Methods**:
- `getAnswerDisplay()` - Formats answer for display (handles arrays)
- `toArray()` - Custom array representation with question text

**Scopes**:
- `byLead($id)` - All responses for a lead with questions loaded
- `forTenant($id)` - Multi-tenant filtering

---

### 2.3 Inventory System Models

#### 2.3.1 InventoryCategory
**Purpose**: Organize inventory items into logical groups

**Key Attributes**:
```
- name (string) - Category name
- description (text) - Optional description
- slug (string) - URL-friendly identifier (unique)
- is_active (boolean) - Control visibility
- display_order (integer) - Ordering in UI
- tenant_id (UUID)
```

**Relationships**:
- `HasMany` → InventoryItem
- `HasMany` → activeItems (where is_active = true)

**Scopes**:
- `active()` - Only active categories
- `forTenant($id)` - Multi-tenant filtering

---

#### 2.3.2 InventoryItem
**Purpose**: Individual inventory items available for allocation

**Key Attributes**:
```
- category_id (FK → InventoryCategory)
- name (string) - Item name
- description (text) - Item description
- sku (string) - Stock Keeping Unit (unique)
- unit (string) - Unit of measurement (e.g., "piece", "box", "set")
- stock_quantity (integer) - Current stock available
- reorder_level (integer) - Threshold for restocking alert
- cost_price (decimal:2) - Cost to organization
- selling_price (decimal:2) - Price for clients
- is_active (boolean) - Item availability
- tenant_id (UUID)
```

**Relationships**:
- `BelongsTo` → InventoryCategory
- `HasMany` → QuestionnaireInventoryOption
- `HasMany` → LeadInventorySelection
- `HasMany` → InventoryAllocation

**Scopes**:
- `active()` - Only active items
- `inStock()` - Items with quantity > 0
- `lowStock()` - Items at or below reorder level
- `byCategory($id)` - Filter by category

---

#### 2.3.3 QuestionnaireInventoryOption
**Purpose**: Link questionnaire questions to inventory items for auto-selection

**Purpose Details**:
When a lead answers certain questionnaire questions, specific inventory items can be automatically suggested or pre-selected based on the answer.

**Key Attributes**:
```
- questionnaire_question_id (FK → QuestionnaireQuestion)
- inventory_item_id (FK → InventoryItem)
- default_quantity (integer) - Qty to suggest when this option selected
- is_optional (boolean) - Whether lead can skip this item
- option_label (string) - Display label for this combination
- display_order (integer) - Order in UI
- tenant_id (UUID)
```

**Unique Constraint**: `(questionnaire_question_id, inventory_item_id)` - One mapping per combination

**Relationships**:
- `BelongsTo` → QuestionnaireQuestion
- `BelongsTo` → InventoryItem

**Scopes**:
- `forTenant($id)` - Multi-tenant filtering

---

#### 2.3.4 LeadInventorySelection
**Purpose**: Track inventory items selected/requested by a lead during sales process

**Key Attributes**:
```
- lead_id (FK → Lead)
- inventory_item_id (FK → InventoryItem)
- quantity_requested (integer) - Qty requested by lead/sales exec
- unit_price_at_selection (decimal:2) - Price at time of selection
- total_price (decimal:2) - unit_price × quantity_requested
- notes (text) - Special notes for this selection
- status (enum):
  * requested - Initial selection
  * approved - Approved by management
  * rejected - Rejected during review
  * modified - Changed from original
- tenant_id (UUID)
```

**Unique Constraint**: `(lead_id, inventory_item_id)` - One selection per lead-item pair

**Relationships**:
- `BelongsTo` → Lead
- `BelongsTo` → InventoryItem
- `HasMany` → InventoryAllocation

**Methods**:
- `calculateTotalPrice()` - Returns unit_price × quantity_requested

**Scopes**:
- `byLead($id)` - Selections for a lead
- `byStatus($status)` - Filter by status
- `approved()` - Only approved selections
- `forTenant($id)` - Multi-tenant filtering

---

#### 2.3.5 InventoryAllocation
**Purpose**: Allocate/reserve inventory from inventory pool to fulfilled lead selections

**Key Attributes**:
```
- lead_inventory_selection_id (FK → LeadInventorySelection)
- inventory_item_id (FK → InventoryItem)
- quantity_allocated (integer) - Qty actually allocated
- allocation_status (enum):
  * reserved - Item reserved, not yet committed
  * committed - Confirmed allocation
  * released - Item returned to stock
- allocation_date (date) - When allocation made
- expected_delivery (date) - Expected delivery date
- notes (text) - Allocation notes
- tenant_id (UUID)
```

**Relationships**:
- `BelongsTo` → LeadInventorySelection
- `BelongsTo` → InventoryItem

**Methods**:
- `commit()` - Change status from reserved to committed
- `release()` - Release allocated quantity back to inventory

**Scopes**:
- `byStatus($status)` - Filter by allocation status
- `reserved()` - Only reserved allocations
- `committed()` - Only committed allocations
- `forTenant($id)` - Multi-tenant filtering

---

#### 2.3.6 LeadInventorySummary
**Purpose**: Aggregated summary of all inventory items for a lead

**Key Attributes**:
```
- lead_id (FK → Lead)
- total_items_count (integer) - Total unique items selected
- total_inventory_cost (decimal:2) - Sum of cost_price × quantities
- total_inventory_price (decimal:2) - Sum of selling_price × quantities
- category_breakdown (JSON) - By-category cost breakdown
  Example: {
    "Security Equipment": 5000.00,
    "Uniforms": 2000.00,
    "Technology": 8000.00
  }
- last_updated (datetime) - When summary last recalculated
- tenant_id (UUID)
```

**Relationships**:
- `BelongsTo` → Lead

**Methods**:
- `recalculate()` - Recalculates all totals from approved lead_inventory_selections
  - Only counts `approved` status selections
  - Rebuilds category breakdown
  - Updates all totals
  - Saves record

**Scopes**:
- `forTenant($id)` - Multi-tenant filtering

---

## 3. Workflow & Data Flow

### 3.1 Lead Creation Workflow

```
1. Sales exec creates new Lead
   ↓
2. Lead assigned ServiceType
   ↓
3. Capture basic info: company, contact, location, budget
   ↓
4. Specify requirements: guard type, hours, site type
   ↓
5. Lead saved with status = "new"
```

**LeadController Methods**:
- `create()` - Show lead creation form
- `store()` - Validate & save lead
- `edit()` - Show edit form
- `update()` - Update lead details

---

### 3.2 Questionnaire Collection Workflow

```
1. Sales exec selects Lead
   ↓
2. System loads QuestionnaireTemplate based on Lead's ServiceType
   ↓
3. Lead answers questions (ordered by display_order)
   ↓
4. Conditional logic evaluated:
   - Show/hide questions based on previous answers
   - Validate against question rules
   ↓
5. Answers saved to LeadQuestionnaireResponse
   ↓
6. Based on answers → QuestionnaireInventoryOption lookup
   ↓
7. Inventory items suggested automatically
```

**Process Details**:
- Questions ordered by `display_order` for logical flow
- `is_mandatory` enforces required fields
- `question_type` determines UI control and validation
- `conditional_logic` (JSON) controls field visibility
- Responses include `answer_metadata` for complex data

---

### 3.3 Inventory Selection Workflow

```
Method 1: Auto-Selection (Answer-Based)
├─ Question answered by lead
├─ Lookup QuestionnaireInventoryOption
├─ Identify mapped InventoryItem(s)
├─ Auto-create LeadInventorySelection
│  └─ quantity = default_quantity from option
└─ Generate LeadInventorySummary

Method 2: Manual Selection (Sales Exec)
├─ Sales exec manually selects items
├─ Specify quantity_requested
├─ System calculates total_price
├─ LeadInventorySelection created
└─ Summary updated

Selection Status Flow:
requested → approved → (allocations created)
         ↘ rejected ↗
         ↘ modified ↗
```

---

### 3.4 Inventory Allocation Workflow

```
1. LeadInventorySelection approved
   ↓
2. System reserves inventory quantity
   ↓
3. InventoryAllocation created:
   allocation_status = "reserved"
   ↓
4. Management reviews allocation
   ↓
5. Either:
   a) commit() → status = "committed"
      └─ Confirmed for fulfillment
   b) release() → status = "released"
      └─ Return to inventory pool

Inventory Impact:
- Allocation only affects tracking, not stock_quantity
- stock_quantity updated when actual delivery occurs
```

---

### 3.5 Lead Conversion Workflow

```
1. Lead qualified & approved
   ↓
2. Update lead_status → "closed_won"
   ↓
3. Set converted_to_client_id = new Client ID
   ↓
4. Set converted_at = current datetime
   ↓
5. Create Client from Lead data
   ↓
6. Transfer all selections/allocations to client service
```

---

## 4. Key Features

### 4.1 Questionnaire Features

**Dynamic Questions**:
- 9 question types: text, textarea, email, number, mcq, checkbox, dropdown, file, date
- Conditional logic for show/hide rules
- Mandatory field validation
- Custom help text per question

**Template Management**:
- Service-type specific templates
- Reusable across leads
- Versioning via soft deletes
- Active/inactive toggle

**Response Handling**:
- JSON metadata storage (file paths, additional data)
- Display formatting with `getAnswerDisplay()`
- Custom array export with question context

---

### 4.2 Inventory Features

**Inventory Management**:
- Hierarchical organization (Category → Items)
- SKU tracking for unique identification
- Cost vs. selling price differentiation
- Stock level monitoring with reorder alerts

**Questionnaire-Inventory Linking**:
- Dynamic item suggestion based on answers
- Default quantities per suggestion
- Optional items (lead can skip)
- Display ordering control

**Selection & Allocation**:
- Multiple items per lead
- Quantity flexibility
- Status workflow (requested → approved → allocated)
- Point-in-time pricing capture

---

### 4.3 Summary & Reporting

**LeadInventorySummary**:
- Aggregated view of selections
- Total cost & revenue calculation
- Category-wise breakdown
- Automatic recalculation on selection approval
- Last-updated tracking

**Export Capabilities**:
- CSV export of questionnaire responses
- Lead-wise summary reports
- Filter by template, date range, status

---

## 5. Controllers & Endpoints

### 5.1 LeadController

| Method | Route | Purpose |
|--------|-------|---------|
| `index()` | GET /leads | List leads with search/filter |
| `create()` | GET /leads/create | Show lead creation form |
| `store()` | POST /leads | Create new lead |
| `show()` | GET /leads/{lead} | Display lead details |
| `edit()` | GET /leads/{lead}/edit | Show edit form |
| `update()` | PUT /leads/{lead} | Update lead |
| `destroy()` | DELETE /leads/{lead} | Soft delete lead |
| `statusPipeline()` | GET /leads/status/pipeline | View leads by status |

**Filters in index()**:
- Search: company_name, contact_person_name, email
- Status: lead_status filter
- City: service location filter
- Guard Type: armed/unarmed/both filter

---

### 5.2 QuestionnaireController

| Method | Route | Purpose |
|--------|-------|---------|
| `index()` | GET /questionnaires | List templates |
| `create()` | GET /questionnaires/create | Show creation form |
| `store()` | POST /questionnaires | Create template with questions |
| `show()` | GET /questionnaires/{template} | Display template |
| `edit()` | GET /questionnaires/{template}/edit | Edit template |
| `update()` | PUT /questionnaires/{template} | Update template & questions |
| `destroy()` | DELETE /questionnaires/{template} | Soft delete template |

**Features**:
- Bulk question creation/update
- Service type association
- Exception handling with detailed error messages
- ModelNotFoundException handling

---

### 5.3 ResponseController

| Method | Route | Purpose |
|--------|-------|---------|
| `index()` | GET /responses | List questionnaire responses |
| `show()` | GET /responses/{response} | Display single response |
| `export()` | POST /responses/export | CSV export responses |

**Features**:
- Search by lead company name
- Filter by template
- CSV streaming download
- Error handling

---

### 5.4 InventoryController

**Inventory Categories**:
- `indexCategories()` - List categories
- `createCategory()` - Create form
- `storeCategory()` - Save category
- `showCategory()` - View category & items
- `editCategory()` - Edit form
- `updateCategory()` - Update category
- `destroyCategory()` - Delete category

**Inventory Items**:
- `indexItems()` - List items
- `createItem()` - Create form
- `storeItem()` - Save item
- `showItem()` - View item
- `editItem()` - Edit form
- `updateItem()` - Update item
- `destroyItem()` - Delete item

**Inventory Allocations**:
- `allocations()` - List allocations
- `createAllocation()` - Create form
- `storeAllocation()` - Save allocation
- `showAllocation()` - View allocation
- `updateAllocationStatus()` - Change status
- `destroyAllocation()` - Delete allocation

---

## 6. Database Schema

### 6.1 Questionnaire Tables

```sql
questionnaire_templates
├── id (UUID, PK)
├── name
├── description
├── service_type_id (FK)
├── is_active
├── tenant_id
└── timestamps, softDeletes

questionnaire_questions
├── id (UUID, PK)
├── questionnaire_template_id (UUID, FK)
├── question_text
├── question_type (text|textarea|email|number|mcq|checkbox|dropdown|file|date)
├── is_mandatory
├── options (JSON)
├── conditional_logic (JSON)
├── display_order
├── help_text
├── tenant_id
└── timestamps, softDeletes
```

---

### 6.2 Lead Tables

```sql
leads
├── id (UUID, PK)
├── company_name
├── contact_person_name
├── email
├── mobile_number
├── address, city, state, country, postal_code
├── lead_source
├── assigned_sales_exec_id (FK → users)
├── lead_status
├── service_type_id (FK)
├── guard_type
├── tentative_guards_count
├── working_hours_type
├── custom_working_hours
├── site_type
├── service_location
├── compliance_required
├── rba_applicable
├── sales_notes
├── client_expectations
├── budget_range_min, budget_range_max
├── follow_up_date
├── next_action
├── converted_to_client_id
├── converted_at
├── tenant_id
└── timestamps, softDeletes

lead_questionnaire_responses
├── id (UUID, PK)
├── lead_id (UUID, FK)
├── questionnaire_question_id (UUID, FK)
├── answer (longText)
├── answer_metadata (JSON)
├── tenant_id
├── timestamps, softDeletes
└── UNIQUE(lead_id, questionnaire_question_id)
```

---

### 6.3 Inventory Tables

```sql
inventory_categories
├── id (UUID, PK)
├── name
├── description
├── slug (UNIQUE)
├── display_order
├── tenant_id
└── timestamps, softDeletes

inventory_items
├── id (UUID, PK)
├── category_id (UUID, FK)
├── name
├── description
├── sku (UNIQUE)
├── unit
├── cost_price
├── selling_price
├── stock_quantity
├── reorder_level
├── is_active
├── tenant_id
└── timestamps, softDeletes

questionnaire_inventory_options
├── id (UUID, PK)
├── questionnaire_question_id (UUID, FK)
├── inventory_item_id (UUID, FK)
├── option_label
├── default_quantity
├── is_optional
├── display_order
├── tenant_id
├── timestamps, softDeletes
└── UNIQUE(questionnaire_question_id, inventory_item_id)

lead_inventory_selections
├── id (UUID, PK)
├── lead_id (UUID, FK)
├── inventory_item_id (UUID, FK)
├── quantity_requested
├── unit_price_at_selection
├── total_price
├── notes
├── status (requested|approved|rejected|modified)
├── tenant_id
├── timestamps, softDeletes
└── UNIQUE(lead_id, inventory_item_id)

inventory_allocations
├── id (UUID, PK)
├── lead_inventory_selection_id (UUID, FK)
├── inventory_item_id (UUID, FK)
├── quantity_allocated
├── allocation_status (reserved|committed|released)
├── allocation_date
├── expected_delivery
├── notes
├── tenant_id
├── timestamps, softDeletes

lead_inventory_summaries
├── id (UUID, PK)
├── lead_id (UUID, FK)
├── total_items_count
├── total_inventory_cost
├── total_inventory_price
├── category_breakdown (JSON)
├── last_updated
├── tenant_id
├── timestamps, softDeletes
└── UNIQUE(lead_id)
```

---

## 7. Key Business Logic

### 7.1 Questionnaire Validation

```php
// From QuestionnaireQuestion
public function getValidationRules(): array
{
    $rule = $this->is_mandatory ? 'required|' : 'nullable|';
    
    // Append type-specific rules
    // MCQ: in:option1,option2,...
    // Email: email
    // Date: date
    // File: file|mimes:...
    // Numeric: numeric|min:...|max:...
    
    return $rule . (type-specific rules);
}
```

### 7.2 LeadInventorySummary Recalculation

```php
public function recalculate(): void
{
    // Get ONLY approved selections
    $selections = LeadInventorySelection::where('lead_id', $this->lead_id)
        ->where('status', 'approved')
        ->with('inventoryItem')
        ->get();

    // Calculate totals
    foreach ($selections as $selection) {
        $totalCount += $selection->quantity_requested;
        $totalPrice += $selection->total_price;
        $totalCost += (cost_price × qty);
        $categoryBreakdown[category] += selection_price;
    }
    
    // Save aggregated data
}
```

### 7.3 Conditional Logic Evaluation

```json
// Example conditional_logic for a question
{
  "question_id": "xyz-uuid",
  "expected_answer": "yes",
  "operator": "equals"
}
// Or complex logic:
{
  "operator": "AND",
  "conditions": [
    {"question_id": "...", "expected_answer": "..."},
    {"question_id": "...", "expected_answer": "..."}
  ]
}
```

---

## 8. Multi-Tenancy Implementation

All models use `tenant_id` (UUID) for data isolation:

```php
// All queries automatically filter by tenant
Model::where('tenant_id', auth()->user()->tenant_id)->get();

// Scopes enforce this
public function scopeForTenant($query, $tenantId)
{
    return $query->where('tenant_id', $tenantId);
}
```

---

## 9. Integration Points

### 9.1 With ServiceType
- Lead specifies required service type
- Questionnaire template selected based on service type
- Questions tailored to service requirements

### 9.2 With User (Sales Executive)
- Lead assigned to sales executive
- Sales exec collects questionnaire responses
- Sales exec makes inventory selections
- Lead updates tracked by responsible exec

### 9.3 With Client (Upon Conversion)
- Lead converted to Client record
- All inventory selections transferred
- Service contract created with allocations
- Lead soft-deleted (archived)

### 9.4 With InventoryItem
- Items used across multiple contexts:
  - Questionnaire suggestions
  - Lead manual selections
  - Allocations for fulfillment
  - Pricing captured at selection time

---

## 10. Common Use Cases

### 10.1 Add New Guard Service Lead
1. Create Lead with ServiceType = "Guard Service"
2. Load Guard Service Questionnaire Template
3. Lead answers: number of guards, duration, location, special requirements
4. System suggests: uniforms, equipment, technology (via QuestionnaireInventoryOption)
5. Sales exec adjusts quantities as needed
6. LeadInventorySummary shows total cost & revenue

### 10.2 Multi-Item Selection with Auto-Suggestions
```
Questionnaire:
- "How many security personnel?" → Answer: 5
- "Do you need special equipment?" → Answer: Yes
- "Site is outdoor?" → Answer: Yes

Auto-Selected Inventory:
- Uniforms (qty: 5 × default_quantity)
- Body Armor (qty: 5 × default_quantity)
- Outdoor Radios (qty: 5 × default_quantity)

Sales Exec Can:
- Approve selection
- Modify quantities
- Add/remove items
- Update notes
```

### 10.3 Lead Comparison & Pipeline
```
// Status Pipeline View
New (5)         → Contacted (8)      → Qualified (12)
                ↘ Not Interested (3) ↗
                
Proposal Sent (10)  → Negotiation (4)  → Closed Won (2)
                ↘ Closed Lost (2) ↗
```

### 10.4 Budget Analysis
```
For Each Lead:
- budget_range_min/max captured
- total_inventory_price calculated
- Variance analysis: selected_cost vs. budget range

LeadInventorySummary.category_breakdown shows:
- Security Equipment: $5,000
- Technology: $3,500
- Uniforms: $2,200
- Total: $10,700 (within budget?)
```

---

## 11. Performance Considerations

### 11.1 Indexes
```
questionnaire_questions: display_order, tenant_id
questionnaire_inventory_options: display_order, tenant_id
lead_inventory_selections: status, tenant_id
inventory_allocations: allocation_date, tenant_id
lead_questionnaire_responses: tenant_id
```

### 11.2 Eager Loading
```php
// Load relations efficiently
$lead->load(['questionnaireResponses.question', 'inventorySelections.item']);

// Count queries
$templates->withCount('questions')
          ->withCount('activeQuestions')
```

### 11.3 JSON Queries
```php
// Conditional logic stored as JSON for flexibility
$questions->where('conditional_logic->operator', 'AND')
          ->where('conditional_logic->conditions', 'like', '%...')
```

---

## 12. Error Handling & Edge Cases

### 12.1 Handled Scenarios
- **Duplicate email**: Validation prevents duplicate lead emails
- **Question without options**: MCQ questions must have options array
- **Circular conditional logic**: Should be validated on save
- **Deleted item in selection**: Foreign key cascadeOnDelete handles
- **Orphaned responses**: Cascade delete when question/template deleted
- **Missing template**: Service type without template handled gracefully

### 12.2 Potential Issues
- **Performance**: Large # of questions with conditional logic
  - Solution: Lazy load conditional logic evaluation
- **Inventory sync**: price_at_selection stored to prevent issues
  - But current_price can diverge from selling_price
  - Solution: Regular reconciliation job
- **Concurrent allocations**: Race condition on stock_quantity
  - Solution: Use DB transactions with locks

---

## 13. Security Considerations

### 13.1 Authorization
- Routes protected by `auth` middleware
- Multi-tenancy isolation via `tenant_id` filter
- Sales execs can only see their assigned leads

### 13.2 Validation
- All input validated with comprehensive rules
- File uploads limited to specific mimetypes
- Date/numeric fields validated

### 13.3 Data Protection
- Soft deletes preserve audit trail
- Question responses stored securely
- File uploads stored in secure paths
- No sensitive data in logs

---

## 14. Summary Table: Module Components

| Component | Purpose | Key Classes | Key Operations |
|-----------|---------|-----------|-----------------|
| **Lead Management** | Prospect tracking | Lead, LeadController | CRUD, status pipeline |
| **Questionnaires** | Requirement collection | QuestionnaireTemplate, QuestionnaireQuestion, QuestionnaireController | Template creation, question management, conditional logic |
| **Responses** | Stored answers | LeadQuestionnaireResponse, ResponseController | Response recording, export, filtering |
| **Inventory** | Item management | InventoryCategory, InventoryItem, InventoryController | Item catalog, category organization, pricing |
| **Linking** | Q→Item mapping | QuestionnaireInventoryOption | Auto-suggestions, defaults |
| **Selections** | Lead item choices | LeadInventorySelection | Selection tracking, status workflow |
| **Allocation** | Stock reservation | InventoryAllocation | Reservation, commitment, release |
| **Summarization** | Aggregated data | LeadInventorySummary | Total calculations, breakdowns, recalculation |

---

## 15. Conclusion

The Questionnaire and Inventory Leads module is a sophisticated, multi-layered system that:

✅ **Captures** lead information through structured templates
✅ **Collects** detailed requirements via dynamic questionnaires  
✅ **Suggests** inventory based on responses  
✅ **Tracks** item selections through approval workflow  
✅ **Allocates** inventory with status management  
✅ **Summarizes** costs and breakdowns for reporting  
✅ **Supports** multi-tenancy across all operations  
✅ **Handles** soft deletes for data integrity  

The architecture is extensible and supports complex business workflows with proper isolation, validation, and error handling.

