# Implementation Testing Checklist — All Changes This Session

**Date:** 2026-03-20 / 2026-03-21
**Test Locally:** http://localhost:8095/login.php?method=password
**Login:** `Kamlesh.l@kaam.com` / `test123`

---

## Database Changes Made

### UAT (`mission_even_uat`)

| # | Change | Table | Action | Status |
|---|--------|-------|--------|--------|
| DB-1 | Created `audit_log` table | `audit_log` | CREATE TABLE (15 columns, 3 indexes) | Done |
| DB-2 | Created `notifications` table | `notifications` | CREATE TABLE (13 columns, 4 indexes) | Done |
| DB-3 | `ats_settings` already existed | `ats_settings` | No change — `enable_new_recruiter_redirect = 1` | Verified |
| DB-4 | `ats_login_tokens` already existed | `ats_login_tokens` | No change — SSO tokens table | Verified |

### PROD (`me_prod`)

| # | Change | Table | Action | Status |
|---|--------|-------|--------|--------|
| DB-5 | `audit_log` already existed | `audit_log` | No change (74 rows, created in prior session) | Verified |
| DB-6 | `notifications` already existed | `notifications` | No change (0 rows, created in prior session) | Verified |
| DB-7 | `ats_settings` already existed | `ats_settings` | `enable_new_recruiter_redirect = 0` (SSO off on PROD) | Verified |
| DB-8 | `ats_login_tokens` does NOT exist | — | Expected — SSO is UAT-only | No action needed |

### LOCAL (`recruiter_prod_local`)

| # | Change | Status |
|---|--------|--------|
| DB-9 | Test user password set for `Kamlesh.l@kaam.com` (user_id=4) | `test123` via ats_password |

**No structural DB changes needed on PROD. All tables already exist.**

---

## Feature 1: Job Repost / Activate / Inactive

### New Files Created

| File | Purpose |
|------|---------|
| `app/Services/JobActionService.php` | Modular service: `activateJob()`, `repostJob()`, `deactivateJob()`, `verifyJobAccess()` |
| `public/activate_job.php` | Endpoint: inactive/expired → active (30-day expiry) |
| `public/repost_job.php` | Endpoint: expired → NEW job (duplicates all data, 8 child tables) |

### Test Cases

| # | Test | Steps | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F1.1 | **Activate closed job** | Jobs → Closed tab → click green "Activate" → confirm | Job moves to Open tab, 30-day expiry, success toast | | |
| F1.2 | **Activate expired job** | Jobs → Expired tab → find a job → manually call `activate_job.php?id=X` | Job moves to Open tab | | |
| F1.3 | **Repost expired job** | Jobs → Expired tab → click red "Repost" → confirm | Redirected to NEW job detail page | | |
| F1.4 | Repost: verify new job data | Check the new job after repost | Status=Open, 29-day expiry, same title, skills, location, education, questions | | |
| F1.5 | Repost: original preserved | Go back to Expired tab, find original job | Still Expired, all candidates/pipeline intact | | |
| F1.6 | Repost: child tables copied | Check new job's skills, locations, education, benefits | All duplicated from source job | | |
| F1.7 | **Inactive active job** | Jobs → Open tab → click "Inactive" → confirm | Job moves to Closed tab | | |
| F1.8 | Inactive expired job | Jobs → Expired tab → click "Inactive" | Job moves to Closed tab | | |
| F1.9 | **Edit button on open jobs** | Jobs → Open tab → click "Edit" | Opens edit form with data pre-filled | | |
| F1.10 | Delete closed job | Jobs → Closed tab → click "Delete" → confirm | Job removed from list | | |
| F1.11 | Permission: wrong company | Try to activate a job from a company you don't have access to | "You do not have permission" error | | |
| F1.12 | Permission: sub_admin | Login as sub_admin, try to repost another admin's job | "You do not have permission" error | | |
| F1.13 | Permission: sub_admin own job | Login as sub_admin, repost/activate own job | Should succeed | | |
| F1.14 | Activate already active job | Call `activate_job.php?id=X` for an active job | "Only inactive or expired jobs can be activated" | | |
| F1.15 | Repost non-expired job | Call `repost_job.php?id=X` for an active job | "Only expired jobs can be reposted" | | |
| F1.16 | Invalid job ID | Call `activate_job.php?id=abc` | "Invalid job ID" error | | |
| F1.17 | **Job detail: action buttons** | Open detail page for expired/closed/open job | Shows Repost (expired), Activate (closed), Inactive (open) next to Edit/Share | | |
| F1.18 | ES sync after repost | Repost a job, check if new job appears in ES | RabbitMQ message pushed (check logs) | | |
| F1.19 | ES sync after activate | Activate a job, check if status updates in ES | RabbitMQ message pushed | | |

---

## Feature 2: Smart Login/Logout Redirect (SSO vs Password)

> **Note:** SSO files (`login.php`, `sso-login.php`, `logout.php`) deployed to UAT only. NOT on PROD.

### Test Cases

| # | Test | Steps | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F2.1 | **Direct login URL** | Go to `/login.php?method=password` | Shows email/password form | | |
| F2.2 | **Login without params** | Go to `/login.php` (no cookie, no params) | Redirects to org-recruiter (`SSO_LOGOUT_REDIRECT_URL`) | | |
| F2.3 | **Password cookie** | Login with password → check cookies | `login_method=password` cookie set (30-day) | | |
| F2.4 | **SSO cookie** | Login via SSO → check cookies | `login_method=sso` cookie set (30-day) | | |
| F2.5 | **Logout: password user** | Login via password → click Logout | Redirected to `/login.php?method=password` (shows form) | | |
| F2.6 | **Logout: SSO user** | Login via SSO → click Logout | Redirected to org-recruiter login | | |
| F2.7 | **Cookie cleared on logout** | After logout → check cookies | `login_method` cookie deleted | | |
| F2.8 | **Session expiry: password** | Delete PHPSESSID cookie manually → visit any page | Redirected to login → cookie=password → shows form | | |
| F2.9 | **Session expiry: SSO** | Delete PHPSESSID → visit any page (cookie=sso) | Redirected to org-recruiter | | |
| F2.10 | **SSO error fallback** | Visit `/login.php?error=token_expired` | Shows login form (not redirect) | | |
| F2.11 | **Back button after logout** | Logout → press Back | Should NOT show cached dashboard | | |

---

## Feature 3: Bug Fixes (GROUP BY, Weight, Job Title/Location)

### Test Cases

| # | Test | Steps | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F3.1 | **Dashboard loads** | Login → dashboard | No SQL error, stats cards show | | |
| F3.2 | **Jobs page loads** | Click Jobs | No SQL error, table renders | | |
| F3.3 | **Job detail loads** | Click any job | No SQL error, full detail renders | | |
| F3.4 | **Candidates page loads** | Click Candidates | No SQL error, table renders (was GROUP BY error with ngo_pm) | | |
| F3.5 | **Edit job: title fallback** | Edit a job with empty `job_title` | Title field shows profession name instead of blank | | |
| F3.6 | **Edit job: location fallback** | Edit a job with empty `company_jobs.job_location` | Location field populated from `company_jobs_location` table | | |
| F3.7 | **Edit job: save with education** | Edit job, change education, click Update | Saves without "Field 'weight' doesn't have a default value" error | | |
| F3.8 | **Add job: save with education** | Post new job with education requirement | Saves without weight error | | |
| F3.9 | **Edit job: soft skills cloud** | Open edit form → scroll to soft skills section | Shows styled pill badges (not plain text) | | |
| F3.10 | **Update job: success toast** | Edit a job → click Update | Green success toast appears top-right, auto-dismisses | | |
| F3.11 | **Shortlist candidate** | Change candidate status to Shortlisted | No `audit_log` table error (table exists now) | | |
| F3.12 | **Default job expiry** | Post new job without setting expiry | Defaults to +29 days (date-only format YYYY-MM-DD) | | |

---

## Feature 4: Global Flash Toast Notifications

### Test Cases

| # | Test | Steps | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F4.1 | **Success toast** | Update a job / activate / repost | Green toast top-right with check icon, auto-dismiss 4s | | |
| F4.2 | **Error toast** | Trigger an error (e.g., invalid job) | Red toast top-right with exclamation icon | | |
| F4.3 | **Toast dismiss** | Click X on toast | Toast closes immediately | | |
| F4.4 | **Toast on redirect** | Activate job → redirected to jobs.php | Toast shows on the destination page | | |
| F4.5 | **Multiple actions** | Do action 1, then action 2 quickly | New toast replaces old toast (no stacking) | | |

---

## Feature 5: UI Layout Fixes

### Test Cases

| # | Test | Steps | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F5.1 | **Jobs table: horizontal scroll** | Narrow browser to 768px | Table scrolls horizontally, filters/header stay above (not clipped) | | |
| F5.2 | **Jobs table: header fixed** | Scroll table horizontally on tablet | "49 total" header and filter pills do NOT scroll with table | | |
| F5.3 | **Job detail: skills layout** | Open any job with skills + soft skills | Skills Required and Soft Skills side by side (2 columns) | | |
| F5.4 | **Job detail: benefits layout** | Open any job with benefits + supplement pay | Benefits and Supplement Pay side by side below skills | | |
| F5.5 | **Job detail: questions** | Open any job with screening questions | Questions full-width below benefits row | | |

---

## Feature 6: Responsive / Mobile UI (Global)

> **Test these at 3 widths:** Desktop (1440px), Tablet (768px), Phone (375px)
> Use browser DevTools → Responsive Mode to simulate.

### Dashboard

| # | Test | Width | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F6.1 | Stat cards | 768px | 2 columns | | |
| F6.2 | Stat cards | 480px | 1 column | | |
| F6.3 | Charts | 768px | Single column (stacked) | | |
| F6.4 | Page header | 768px | Title and buttons stack vertically | | |

### Jobs Page

| # | Test | Width | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F6.5 | Filter pills | 768px | Horizontally scrollable if needed | | |
| F6.6 | Table | 768px | Horizontal scroll, min-width 900px | | |
| F6.7 | Action buttons | 768px | Wrap or fit, no overflow | | |
| F6.8 | "Post New Job" button | 480px | Full width | | |

### Job Detail

| # | Test | Width | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F6.9 | Skills/Benefits grid | 768px | Stacks to 1 column (`.two-col-grid`) | | |
| F6.10 | Details grid | 968px | Stacks to 1 column | | |
| F6.11 | Header action buttons | 768px | Wrap to fit | | |
| F6.12 | Quick stats | 480px | Stack vertically | | |
| F6.13 | Modals | 375px | Fit viewport (no overflow) | | |

### Kanban Board

| # | Test | Width | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F6.14 | Kanban columns | 1024px | 260px wide, horizontal scroll | | |
| F6.15 | Kanban columns | 768px | 240px wide | | |
| F6.16 | Kanban columns | 480px | 220px wide | | |
| F6.17 | Candidate cards | 768px | Compact: smaller avatar, 13px name, truncated info | | |
| F6.18 | Card action buttons | 768px | Wrap to fit (not overflow card) | | |
| F6.19 | Card action buttons | 480px | Stack vertically, full width | | |
| F6.20 | Card info (email/phone) | 768px | Truncated with ellipsis, not clipped | | |
| F6.21 | Card drag on mobile | 768px | Can still drag cards between columns | | |

### Kanban Interview Trigger

| # | Test | Steps | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F6.22 | **Drag to Interview** | Drag card from Shortlisted to Interview column | Toast: "Candidate moved to Interview" + schedule modal auto-opens | | |
| F6.23 | Drag to Shortlisted | Drag card from Applied to Shortlisted | Toast: "Candidate moved to Shortlisted" (no modal) | | |
| F6.24 | Drag to Selected | Drag card to Selected | Toast: "Candidate moved to Selected" | | |
| F6.25 | Drag to Rejected | Drag card to Rejected | Toast: "Candidate moved to Rejected" | | |

### Candidates Page

| # | Test | Width | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F6.26 | Table | 768px | Horizontal scroll wrapper (min-width 800px) | | |
| F6.27 | Page loads | Any | No GROUP BY SQL error | | |

### Interviews Page

| # | Test | Width | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F6.28 | Interview cards | 768px | Stack vertically (not side by side) | | |
| F6.29 | Stat grids | 768px | 2 columns | | |
| F6.30 | Stat grids | 480px | 1 column | | |
| F6.31 | Modals | 375px | Fit viewport | | |

### Notifications Page

| # | Test | Width | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F6.32 | Notification items | 768px | Stack vertically (icon, text, actions) | | |
| F6.33 | Filter tabs | 768px | Horizontally scrollable | | |
| F6.34 | Actions buttons | 480px | Stack vertically | | |

### Global (All Pages)

| # | Test | Width | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F6.35 | Container padding | 768px | 12px padding (compact) | | |
| F6.36 | Page title | 480px | 18px font size | | |
| F6.37 | Navbar | 1024px | Collapses to mobile menu | | |
| F6.38 | Toast notification | 480px | Full width (edge to edge) | | |
| F6.39 | Search bars | 768px | Full width | | |
| F6.40 | No horizontal overflow | 375px | No page-level horizontal scrollbar on any page | | |

---

## Feature 7: Brevo API Key Update

| # | Test | Steps | Expected | Status | Notes |
|---|------|-------|----------|--------|-------|
| F7.1 | Brevo key on PROD | Check `app/config/config.php` on EC2 | Key: `xkeysib-6ec10b45...yb9QUE5eothXf9k8` | | |
| F7.2 | Brevo key on LOCAL | Check local `app/config/config.php` | Same key | | |
| F7.3 | WhatsApp send works | Send WhatsApp message to candidate | Delivered via Brevo | | |

---

## Files Changed — Full List

### New Files (4):

| File | Deployed To |
|------|-------------|
| `app/Services/JobActionService.php` | PROD + UAT |
| `public/activate_job.php` | PROD + UAT |
| `public/repost_job.php` | PROD + UAT |
| `public/assets/css/responsive.css` | LOCAL only (not yet deployed) |

### Modified Files (15):

| File | Change | PROD | UAT |
|------|--------|------|-----|
| `app/Services/ProductionDBAdapter.php` | GROUP BY fixes (3x MIN(), dedup subquery) | Yes | Yes |
| `app/views/jobs.php` | Repost/Activate/Edit buttons + table scroll | Yes | Yes |
| `app/views/job_detail.php` | Action buttons + `.two-col-grid` + details-grid responsive | Yes | Yes |
| `app/views/edit_job.php` | Soft skills cloud CSS | Yes | Yes |
| `app/views/layout/header.php` | Flash toast + responsive.css link | Yes | Yes |
| `app/views/kanban_production.php` | Mobile CSS + interview trigger + toasts | LOCAL only | |
| `app/views/interviews.php` | Responsive CSS added | LOCAL only | |
| `app/views/candidates.php` | Table scroll wrapper | LOCAL only | |
| `app/views/dashboard.php` | Stat card responsive CSS | LOCAL only | |
| `public/edit_job.php` | Job title/location fallback + weight fix | Yes | Yes |
| `public/add_job.php` | Weight column fix in education insert | Yes | Yes |
| `public/candidates.php` | GROUP BY fix (ngo_pm.image, pm.name) | LOCAL only | |
| `public/notifications.php` | Responsive CSS expanded | LOCAL only | |
| `public/login.php` | Smart redirect (SSO) | UAT only | |
| `public/sso-login.php` | SSO cookie | UAT only | |
| `public/logout.php` | Cookie clear + redirect | UAT only | |

### Deployment Status:

| Environment | What's deployed | What's pending |
|-------------|----------------|----------------|
| **PROD** | Repost/Activate, GROUP BY fixes, edit_job fixes, toast, Brevo key | Responsive CSS, kanban trigger, candidates GROUP BY fix |
| **UAT** | Everything via GitLab CI (pending pipeline run) | Latest responsive CSS changes (this session) |
| **LOCAL** | Everything | — |

---

## Quick Smoke Test (5 minutes)

Run through these 10 tests to verify core functionality:

1. Login at `/login.php?method=password`
2. Dashboard loads without errors
3. Jobs → Open tab shows jobs
4. Jobs → Expired tab → click Repost → new job created
5. Jobs → Closed tab → click Activate → job goes to Open
6. Edit a job → click Update → success toast shown
7. Candidates page loads (no GROUP BY error)
8. Kanban → drag card to Interview → schedule modal auto-opens
9. Resize browser to 375px → no horizontal overflow on any page
10. Logout → redirected to login form
