Leads
Lead CRUD Operations
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| LEAD-001 | Create a new lead from existing contact | Logged in as user with `leads:manage` permission, at least one contact exists, one WhatsApp account connected | 1. Navigate to Leads view 2. Click "New Lead" button 3. Select a contact from dropdown 4. Select WhatsApp account 5. Set stage to "new" 6. Enter source (e.g., "manual") 7. Click "Save" | Lead appears in Leads list with selected contact, stage, and source. Success toast shows "Lead created". Lead ID is assigned. Lead's assigned_user_id and assigned_team_id are sourced from the linked contact's assignee fields. | High |
| LEAD-002 | [REMOVED] Create lead with assignment to user | Logged in as user with `leads:manage` permission, at least one contact and one team member exists | 1. Navigate to create lead form 2. Select contact 3. Assign to user via "Assigned User" dropdown 4. Submit form | Lead is created with `assigned_user_id` populated. Lead appears in assigned user's view/list (subject to visibility rules). | High |
| LEAD-003 | [REMOVED] Create lead with assignment to team | Logged in as user with `leads:manage` permission, at least one contact and one team exists | 1. Navigate to create lead form 2. Select contact 3. Assign to team via "Assigned Team" dropdown 4. Submit form | Lead is created with `assigned_team_id` populated. Lead appears in team's view (subject to visibility rules). | High |
| LEAD-004 | Create lead with initial score | Logged in as user with `leads:manage` permission, at least one contact exists | 1. Navigate to create lead form 2. Select contact 3. Set score field to numeric value (e.g., 75) 4. Submit form | Lead is created with score saved and visible in lead details. | Medium |
| LEAD-005 | List all leads with pagination | Logged in as user with `leads:view` permission, at least 30 leads exist in org | 1. Navigate to Leads view 2. Observe leads list showing first 25 items 3. Click "Next" or scroll to load more | First page shows 25 leads with pagination controls. Second page shows next 25 leads. Total count displays at bottom (e.g., "Showing 1-25 of 150"). Only leads visible to user (based on contact assignment and role) are shown. | High |
| LEAD-006 | List leads filtered by stage | Logged in as user with `leads:view` permission, leads in multiple stages exist | 1. Navigate to Leads view 2. Click stage filter dropdown 3. Select "Qualified" stage 4. View results | List shows only leads with stage = "qualified" that user has permission to view. Other stages are hidden. Filter badge shows "Qualified" is active. | High |
| LEAD-007 | List leads filtered by assigned user | Logged in as user with `leads:view` permission, leads with contacts assigned to different users exist | 1. Navigate to Leads view 2. Open "Assigned User" filter 3. Select a specific user 4. View results | List shows only leads whose contact is assigned to selected user that current user can view. Filter shows selected user name. Assignee sourced from contact's assigned_user_id. | High |
| LEAD-008 | List leads filtered by contact | Logged in as user with `leads:view` permission, multiple leads for same contact exist | 1. Navigate to Leads view 2. Open "Contact" filter 3. Select contact 4. View results | List shows only leads linked to selected contact that user can access. | Medium |
| LEAD-009 | Search leads by contact name | Logged in as user with `leads:view` permission, leads with known contact names exist | 1. Navigate to Leads view 2. Enter contact name in search box (e.g., "John") 3. Press Enter or wait for auto-search | List filters to show only leads where contact_name contains "John" and user has visibility. Results update in real-time (no page reload). | High |
| LEAD-010 | Search leads by contact phone | Logged in as user with `leads:view` permission, leads with known contact phones exist | 1. Navigate to Leads view 2. Enter phone number in search box (e.g., "+1234567890") 3. Press Enter or wait for auto-search | List filters to show only leads where contact_phone contains phone number and user can view. Results update in real-time. | High |
| LEAD-011 | Get lead details | Logged in as user with `leads:view` permission, at least one lead exists that user can view | 1. Navigate to Leads view 2. Click on a lead row to open detail panel 3. Observe detail panel | Detail panel opens showing: lead ID, contact name, contact phone, current stage, assigned user (sourced from contact), assigned team (sourced from contact), score, source, created date, lost_reason (if applicable). Contact audit log visible. User must have visibility permission for lead. | High |
| LEAD-012 | Update lead stage to next stage | Logged in as user with `leads:manage` permission, lead in "new" stage exists that user can view | 1. Open lead detail panel 2. Click stage badge 3. Select "Contacted" from stage menu 4. Confirm | Lead stage updates to "Contacted". Stage badge color changes. Detail panel reflects new stage immediately. Audit log entry created. | High |
| LEAD-013 | Update lead stage via Kanban drag-and-drop | Logged in as user with `leads:manage` permission, Kanban view active, lead in "new" column exists that user can view | 1. Navigate to Leads view in Kanban mode 2. Drag lead card from "New" column 3. Drop on "Contacted" column 4. Release | Lead card moves to "Contacted" column. Lead status updates in backend. No page refresh needed. | High |
| LEAD-014 | Update lead stage to "lost" with reason | Logged in as user with `leads:manage` permission, lead in "qualified" stage exists that user can view | 1. Open lead detail panel 2. Click stage badge 3. Select "Lost" 4. Modal opens asking for lost_reason 5. Enter reason (e.g., "Budget constraints") 6. Click "Confirm Lost" | Lead stage updates to "Lost". lost_reason field is saved with entered text. Stage badge turns red. Audit log shows lost reason. | High |
| LEAD-015 | Update lead stage — no lost reason required if not selecting lost | Logged in as user with `leads:manage` permission, lead in "contacted" stage exists that user can view | 1. Open lead detail panel 2. Click stage badge 3. Select "Qualified" 4. Confirm without entering reason | Lead updates to "Qualified" stage. No modal appears. No lost_reason field shown. | High |
| LEAD-016 | [REMOVED] Update lead assignment to different user | Logged in as user with `leads:manage` permission, lead exists that user can view, multiple team members exist | 1. Open lead detail panel 2. Click "Assigned User" field 3. Select different user from dropdown 4. Confirm | assigned_user_id updates. Detail panel refreshes showing new assignee. Audit log entry created. Lead visibility may change for other users based on new assignment. | High |
| LEAD-017 | [REMOVED] Update lead assignment to team | Logged in as user with `leads:manage` permission, lead exists that user can view, multiple teams exist | 1. Open lead detail panel 2. Click "Assigned Team" field 3. Select different team 4. Confirm | assigned_team_id updates. Detail panel shows new team. Audit log entry created. Lead visibility updated for team members. | High |
| LEAD-018 | Delete a lead | Logged in as user with `leads:manage` permission, lead exists with no active enrollments that user can view | 1. Open lead detail panel 2. Click "Delete" button 3. Confirm deletion in modal | Lead removed from list. Detail panel closes. Success toast shows "Lead deleted". Lead no longer appears in any filter/search. User must have visibility permission to delete. | High |
| LEAD-019 | Cannot delete lead with active nurture enrollment | Logged in as user with `leads:manage` permission, lead exists with active nurture enrollment that user can view | 1. Open lead detail panel with active enrollment 2. Click "Delete" button | Delete button is disabled or error toast shows "Cannot delete: active enrollments exist". Lead remains in list. | Medium |
| LEAD-020 | View lead — contact name and phone pre-filled from contact | Logged in as user with `leads:view` permission, lead linked to contact "John +1234567890" exists that user can view | 1. Navigate to Leads view 2. Click lead row 3. Open detail panel | Lead detail panel shows contact_name = "John" and contact_phone = "+1234567890" (fetched from contact record, not stored on lead). | High |
| LEAD-086 | Assign lead by updating contact assignment | Logged in as user with `leads:manage` permission, lead exists that user can view, contact linked to that lead exists that user can manage | 1. Navigate to Contacts view 2. Open the contact linked to the lead 3. Update contact's "Assigned User" field to a different user 4. Save | Contact assignment updates. Lead's assigned_user_id field is automatically refreshed to match the contact's assignment. Lead detail panel reflects updated assignee on next view/refresh. Lead visibility may change for other users. | High |
| LEAD-087 | Lead assignee reflects contact's team assignment | Logged in as user with `leads:view` permission, lead exists with contact assigned to a team that user can view | 1. Navigate to Leads view 2. Click lead row to open detail panel | Lead's assigned_team_id field displays the team currently assigned to the linked contact. Changing contact's team assignment cascades to lead's assigned_team_id. | High |
Lead Temperature Marking
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| LEAD-088 | Create lead with hot temperature | Logged in as user with `leads:manage` permission, at least one contact exists | 1. Navigate to create lead form 2. Select contact 3. Select temperature as "hot" 4. Click "Save" | Lead is created with temperature = "hot" and appears in lead list with hot indicator/badge. Detail panel shows temperature field. | High |
| LEAD-089 | Create lead with cold temperature | Logged in as user with `leads:manage` permission, at least one contact exists | 1. Navigate to create lead form 2. Select contact 3. Select temperature as "cold" 4. Click "Save" | Lead is created with temperature = "cold" and appears in lead list with cold indicator/badge. Detail panel shows temperature field. | High |
| LEAD-090 | Create lead without temperature (neutral default) | Logged in as user with `leads:manage` permission, at least one contact exists | 1. Navigate to create lead form 2. Select contact 3. Leave temperature unselected 4. Click "Save" | Lead is created with no explicit temperature or temperature = null. Detail panel shows temperature as unset or neutral. | Medium |
| LEAD-091 | Update lead temperature from hot to cold | Logged in as user with `leads:manage` permission, lead with temperature = "hot" exists that user can view | 1. Open lead detail panel 2. Click temperature indicator/dropdown 3. Select "cold" 4. Confirm | Lead temperature updates from "hot" to "cold". Badge/indicator color changes. Audit log shows temperature change. Detail panel refreshes immediately. | High |
| LEAD-092 | Update lead temperature from cold to hot | Logged in as user with `leads:manage` permission, lead with temperature = "cold" exists that user can view | 1. Open lead detail panel 2. Click temperature indicator/dropdown 3. Select "hot" 4. Confirm | Lead temperature updates from "cold" to "hot". Badge color changes. Audit log entry created. | High |
| LEAD-093 | List leads filtered by temperature: hot | Logged in as user with `leads:view` permission, leads with mixed temperatures exist | 1. Navigate to Leads view 2. Open temperature filter dropdown 3. Select "hot" 4. View results | List shows only leads with temperature = "hot" that user has permission to view. Filter badge shows "Hot" is active. Count updates to reflect filtered results. | High |
| LEAD-094 | List leads filtered by temperature: cold | Logged in as user with `leads:view` permission, leads with mixed temperatures exist | 1. Navigate to Leads view 2. Open temperature filter dropdown 3. Select "cold" 4. View results | List shows only leads with temperature = "cold" that user has permission to view. Filter badge shows "Cold" is active. | High |
| LEAD-095 | List leads filtered by temperature: all | Logged in as user with `leads:view` permission, temperature filter previously active | 1. Navigate to Leads view 2. Open temperature filter dropdown 3. Select "All" or clear filter 4. View results | List shows leads with all temperature values. Filter is cleared or shows "All temperatures". List count reflects unfiltered results. | Medium |
| LEAD-096 | Temperature filter combined with stage filter | Logged in as user with `leads:view` permission, leads with various stages and temperatures exist | 1. Navigate to Leads view 2. Select temperature = "hot" 3. Select stage = "qualified" 4. View results | List shows only leads matching both temperature = "hot" AND stage = "qualified". Both filter badges visible. Results respect visibility rules. | High |
| LEAD-097 | Kanban view displays lead temperature | Logged in as user with `leads:view` permission, Kanban view active, leads with different temperatures exist | 1. Navigate to Leads view in Kanban mode 2. Observe lead cards in columns | Each lead card shows temperature indicator/badge (hot red, cold blue, or neutral gray). Temperature visible without opening detail panel. | High |
| LEAD-098 | List view shows temperature as sortable column | Logged in as user with `leads:view` permission, leads with mixed temperatures exist | 1. Navigate to Leads list view 2. Observe table columns 3. Click temperature column header to sort | Temperature column visible in table. Clicking header sorts leads by temperature (hot first, then neutral, then cold, or reverse). | Medium |
| LEAD-099 | Temperature change recorded in audit log | Logged in as user with `leads:manage` permission, lead with temperature exists that user can view | 1. Open lead detail 2. Change temperature from "hot" to "cold" 3. View activity/audit log | Audit log entry shows: "Temperature changed from 'hot' to 'cold'", timestamp, actor_id. | High |
| LEAD-100 | Bulk update lead temperatures | Logged in as user with `leads:manage` permission, multiple leads in list view selected | 1. Select 3+ leads via checkboxes 2. Open bulk actions menu 3. Select "Change Temperature" 4. Choose "hot" 5. Confirm | All selected leads' temperatures update to "hot". Success toast shows "Updated X leads". Audit log shows one entry per lead with bulk action indicator. | Medium |
Lead Permissions & Role Boundaries
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| LEAD-021 | Agent cannot create lead — no `leads:manage` permission | Logged in as Agent role (has `leads:view` but not `leads:manage`) | 1. Navigate to Leads view 2. Attempt to click "New Lead" button | Button is disabled or hidden. If clicked via dev tools, API returns 403 Forbidden. Toast shows "Permission denied: leads:manage required". | High |
| LEAD-022 | Agent cannot update lead stage | Logged in as Agent role, lead exists | 1. Navigate to Leads view 2. Open lead detail panel 3. Attempt to click stage badge and change stage | Stage badge is disabled/read-only. If attempted via API, returns 403 Forbidden. No update occurs. | High |
| LEAD-023 | Agent cannot delete lead | Logged in as Agent role, lead exists | 1. Navigate to Leads view 2. Open lead detail panel 3. Attempt to click "Delete" button | Delete button is disabled or hidden. If attempted via API, returns 403 Forbidden. | High |
| LEAD-024 | Agent can view leads | Logged in as Agent role with `leads:view` permission | 1. Navigate to Leads view 2. List loads | Leads list displays only leads visible to Agent (contact assignments, or per org visibility rules). Agent can read all fields. | High |
| LEAD-025 | Admin can create, update, delete leads | Logged in as Admin role | 1. Create lead 2. Update stage 3. Delete lead | All operations succeed. Admin sees all leads regardless of contact assignment. | High |
| LEAD-026 | User cannot view leads from different organization | Logged in to Org A, lead exists in Org B | 1. Attempt to navigate to /leads or call GET /leads with org_id filter for Org B | List returns empty or 403 Forbidden. Lead from Org B not visible. Results scoped to current org_id only. | High |
| LEAD-027 | User can only view leads linked to contacts assigned to them or their team | Logged in as user with `leads:view`, leads linked to contacts with different assignments exist | 1. Navigate to Leads view 2. Observe list of visible leads | List shows only leads where contact's assigned_user_id = current user OR contact's assigned_team_id in current user's teams OR user is admin. Leads linked to contacts assigned to other users/teams are hidden. | High |
| LEAD-028 | User cannot view lead detail if contact not assigned to them | Logged in as user with `leads:view`, lead linked to contact assigned to different user | 1. Navigate to GET /leads/{lead_id} 2. Attempt to open lead detail panel | API returns 403 Forbidden or detail panel does not open. Toast shows "You do not have permission to view this lead". | High |
| LEAD-029 | User cannot update lead if contact not assigned to them | Logged in as user with `leads:manage`, lead linked to contact assigned to different user | 1. Navigate to lead detail 2. Attempt to update stage or other fields | Update button disabled or API returns 403 Forbidden. Toast shows "You do not have permission to modify this lead". | High |
| LEAD-030 | User cannot delete lead if contact not assigned to them | Logged in as user with `leads:manage`, lead linked to contact assigned to different user | 1. Navigate to lead detail 2. Attempt to click Delete button | Delete button disabled or API returns 403 Forbidden. | High |
Lead Visibility Query Clause
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| LEAD-031 | Lead list respects visibility clause filtering | Logged in as non-admin user with `leads:view`, multiple leads linked to contacts with different assignments exist | 1. Call GET /leads with page_size=100 2. Observe returned lead list | Lead service applies visibility_clause to query based on contact's assignment. Only leads linked to contacts assigned to user or user's teams are returned. Cursor/offset pagination works correctly with filtered results. | High |
| LEAD-032 | Admin user sees all leads without visibility filtering | Logged in as Admin role with `leads:view` | 1. Call GET /leads 2. Observe returned lead list | All leads in org are returned regardless of contact assignment. No visibility_clause restrictions applied. | High |
Lead Validation & Error Handling
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| LEAD-033 | Create lead — contact_id required | Logged in as user with `leads:manage`, no contact selected | 1. Navigate to create lead form 2. Leave contact field empty 3. Click "Save" | Form validation error appears under contact field: "Contact is required". Save button disabled. No API call made. | High |
| LEAD-034 | Create lead — whatsapp_account_id required | Logged in as user with `leads:manage`, contact selected but no WhatsApp account | 1. Navigate to create lead form 2. Select contact 3. Leave WhatsApp account empty 4. Click "Save" | Form validation error: "WhatsApp account is required". No API call made. | High |
| LEAD-035 | Create lead — invalid contact_id | Logged in as user with `leads:manage` | 1. Submit POST /leads with contact_id = "invalid-uuid" | API returns 422 Unprocessable Entity with validation error. Toast shows "Invalid contact ID format". | Medium |
| LEAD-036 | Create lead — contact does not exist | Logged in as user with `leads:manage` | 1. Submit POST /leads with valid UUID format but non-existent contact_id | API returns 404 Not Found. Toast shows "Contact not found". | Medium |
| LEAD-037 | Create lead — duplicate lead for same contact | Logged in as user with `leads:manage`, lead already exists for contact "John" | 1. Attempt to create another lead for same contact "John" | Depending on business rule: either allows multiple leads per contact (if permitted) or returns 409 Conflict with message "Lead already exists for this contact". | Low |
| LEAD-038 | Update lead — invalid stage value | Logged in as user with `leads:manage`, lead exists that user can view | 1. Open lead detail panel 2. Submit PATCH /leads/{id} with stage = "invalid_stage" | API returns 400 Bad Request with detail "Invalid stage value". Must be one of: new, contacted, qualified, converted, lost. | Medium |
| LEAD-039 | Update lead — lost_reason only valid when stage = "lost" | Logged in as user with `leads:manage`, lead in "contacted" stage that user can view | 1. Submit PATCH with stage = "contacted" and lost_reason = "Budget" | API accepts or ignores lost_reason when stage != "lost". No error if lost_reason ignored, or field rejected. | Low |
| LEAD-040 | [REMOVED] Update lead — assigned_user_id must exist | Logged in as user with `leads:manage` | 1. Submit PATCH /leads/{id} with assigned_user_id = invalid-uuid | API returns 404 Not Found or 400 Bad Request. Toast shows "User not found". | Medium |
| LEAD-041 | [REMOVED] Update lead — assigned_team_id must exist | Logged in as user with `leads:manage` | 1. Submit PATCH /leads/{id} with assigned_team_id = invalid-uuid | API returns 404 Not Found. Toast shows "Team not found". | Medium |
| LEAD-042 | Get lead — 404 if lead does not exist | Logged in as user with `leads:view` | 1. Navigate to /leads/{non-existent-id} or click lead that was deleted | API returns 404 Not Found. Toast shows "Lead not found". Detail panel closes or blank state shown. | Medium |
| LEAD-043 | Get lead — 403 if user lacks visibility permission | Logged in as user with `leads:view`, lead linked to contact assigned to different user | 1. Navigate to /leads/{lead_id} | API returns 403 Forbidden. Toast shows "You do not have permission to view this lead". Detail panel does not open. | High |
| LEAD-044 | Pagination — page_size minimum 1 | Logged in as user with `leads:view` | 1. Submit GET /leads?page_size=0 | API returns 422 Unprocessable Entity with validation error "page_size must be >= 1". | Low |
| LEAD-045 | Pagination — page_size maximum 500 | Logged in as user with `leads:view` | 1. Submit GET /leads?page_size=501 | API returns 422 Unprocessable Entity with validation error "page_size must be <= 500". | Low |
| LEAD-046 | Pagination — page minimum 1 | Logged in as user with `leads:view` | 1. Submit GET /leads?page=0 | API returns 422 Unprocessable Entity with validation error "page must be >= 1". | Low |
| LEAD-101 | Update lead — invalid temperature value | Logged in as user with `leads:manage`, lead exists that user can view | 1. Submit PATCH /leads/{id} with temperature = "warm" (invalid value) | API returns 400 Bad Request with detail "Invalid temperature value". Must be one of: hot, cold, or null. | Medium |
Lead Stage Transitions & Workflow
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| LEAD-047 | Lead created in "new" stage by default | Logged in as user with `leads:manage`, create lead without explicit stage | 1. Create lead omitting stage field 2. Open detail panel | Lead defaults to stage = "new". | High |
| LEAD-048 | Lead can transition new → contacted → qualified → converted → lost | Logged in as user with `leads:manage` | 1. Create lead (stage = "new") 2. Update to "contacted" 3. Update to "qualified" 4. Update to "converted" | Each transition succeeds. Stage badge updates color. Audit log shows each change with timestamp. | High |
| LEAD-049 | Lead can transition backwards (e.g., qualified → contacted) | Logged in as user with `leads:manage`, lead in "qualified" stage that user can view | 1. Open lead detail panel 2. Change stage to "contacted" | Backwards transition allowed. Stage updates successfully. No error. | Medium |
| LEAD-050 | Lead can jump stages (e.g., new → qualified) | Logged in as user with `leads:manage`, lead in "new" stage that user can view | 1. Change stage directly to "qualified" without "contacted" | Jump transition allowed. No intermediate stage required. | Medium |
| LEAD-051 | Lead stage can transition to "lost" from any stage | Logged in as user with `leads:manage`, leads in various stages that user can view | 1. For each stage (new, contacted, qualified, converted): change to "lost" with reason | All transitions to "lost" succeed. Modal appears for lost_reason. | High |
| LEAD-052 | Lead already "lost" cannot transition to other stages except back to "new" | Logged in as user with `leads:manage`, lead in "lost" stage that user can view | 1. Attempt to change stage from "lost" to "contacted" | Transition allowed or blocked depending on business rule. If blocked, error message shows "Cannot transition from lost stage". | Low |
Lead List & Kanban Views
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| LEAD-053 | Leads displayed in Kanban columns by stage | Logged in as user with `leads:view`, leads in all 5 stages exist that user can view | 1. Navigate to Leads view 2. Select "Kanban" view mode | Five columns displayed: "New", "Contacted", "Qualified", "Converted", "Lost". Each lead card shows in correct column by stage. Only leads visible to user (based on contact assignment) are displayed. | High |
| LEAD-054 | Kanban column headers show lead count per stage | Logged in as user with `leads:view`, Kanban view active | 1. Observe Kanban columns | Each column header shows count (e.g., "New (12)" for 12 leads in new stage visible to user). Count reflects visibility filtering. | Medium |
| LEAD-055 | Lead card displays contact name and stage badge in Kanban | Logged in as user with `leads:view`, Kanban view active | 1. Observe a lead card in Kanban column | Card shows: contact name, status badge with appropriate color, assigned user from contact (if any). | High |
| LEAD-056 | Quick action buttons in Kanban: advance stage | Logged in as user with `leads:manage`, Kanban view active, lead in "new" stage that user can view | 1. Hover over lead card 2. Click "→" (advance) button | Lead moves to "Contacted" column. No modal. Immediate update. | High |
| LEAD-057 | Quick action buttons in Kanban: mark lost | Logged in as user with `leads:manage`, Kanban view active, lead in "qualified" stage that user can view | 1. Hover over lead card 2. Click "✕" (lost) button | Modal opens asking for lost_reason. After confirming, lead moves to "Lost" column. | High |
| LEAD-058 | Leads switched to List view show all columns | Logged in as user with `leads:view`, leads in various stages that user can view | 1. Navigate to Leads view 2. Toggle to "List" view | Leads shown in table with columns: Contact Name, Phone, Stage, Assigned User (from contact), Stage Badge, Score, Source, Temperature. Sortable/filterable. Only leads visible to user (based on contact assignment) displayed. | High |
| LEAD-059 | Empty leads state | Logged in as user with `leads:view`, no leads exist in org or no leads visible to user | 1. Navigate to Leads view | Empty state message shown: "No leads yet. Create your first lead to get started." Create button visible. | Medium |
| LEAD-060 | Leads search/filter returns no results | Logged in as user with `leads:view`, search term matches no leads visible to user | 1. Enter search "nonexistent_name" 2. View results | Empty results message: "No leads match your search." Filters still visible for reset. | Medium |
Lead Source & WhatsApp Account
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| LEAD-061 | Create lead with source field populated | Logged in as user with `leads:manage` | 1. Create lead with source = "manual" (or "imported", "api", etc.) 2. View detail | source field saved and visible in detail panel. Audit log shows source. | Medium |
| LEAD-062 | Lead WhatsApp account link validation | Logged in as user with `leads:manage`, at least 2 WhatsApp accounts connected | 1. Create lead with WhatsApp account A 2. View lead details 3. Verify account link | whatsapp_account_id saved. In detail panel, if nurture sequences or messages sent, they use this account. | Medium |
| LEAD-063 | Update lead WhatsApp account assignment | Logged in as user with `leads:manage`, lead exists that user can view, 2+ WhatsApp accounts | 1. Open lead detail 2. Change whatsapp_account_id to different account 3. Confirm | Lead whatsapp_account_id updates. Future nurture messages use new account. | Low |
Lead Audit & Activity Tracking
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| LEAD-064 | Lead creation recorded in audit log | Logged in as user with `leads:manage`, create lead | 1. Create lead 2. Open detail panel 3. Scroll to "Activity" tab | Audit log entry shows: "Lead created by [user name]", timestamp, action = "create", actor_id = current user. | High |
| LEAD-065 | Lead stage change recorded in audit log | Logged in as user with `leads:manage`, lead exists that user can view | 1. Change lead stage from "new" to "contacted" 2. View activity log | Audit log entry shows: "Stage changed from 'new' to 'contacted'", timestamp, actor_id. | High |
| LEAD-066 | Lead assignment change recorded in audit log — via contact assignment | Logged in as user with `leads:manage`, lead exists linked to contact that user can manage | 1. Navigate to contact linked to lead 2. Change contact's "Assigned User" field 3. Save 4. View lead activity log | Audit log entry shows: "Assigned to [new user name]", timestamp. Lead's assigned_user_id automatically reflects contact's new assignment. | High |
| LEAD-067 | Lost reason change recorded in audit log | Logged in as user with `leads:manage`, mark lead as lost with reason | 1. Transition to "lost" stage with reason "Budget" 2. View activity log | Audit log entry shows: "Marked as lost - reason: Budget", timestamp. | Medium |
Lead Reminders
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| LEAD-068 | Add reminder to lead | Logged in as user with permission, lead open in detail panel that user can view | 1. Click "Add Reminder" button 2. Enter due date/time and note (e.g., "Follow up call") 3. Click "Save" | Reminder created and appears in "Reminders" section of detail panel. Due date and note visible. Toast shows "Reminder added". | High |