# Page Review — Agents (Team)

- **Route(s):** `/agents/index` (+ view, create, update, structure-*, toggle-*, calendar, check-mobile)
- **Views:** `frontend/views/agents/{index,_form,create,update,_structure,view}.php`
- **Controller:** `frontend/controllers/AgentsController.php` (+ `common/models/User.php`, `UserProfile.php`, `UserShift`)
- **Demo reference:** `../Navagoo_MI` Team / org-chart · parity `ai_specs/07_DEMO_PARITY/admin-people/`
- **Reviewed:** 2026-07-01 · **Status:** 🔍

## 1. Element inventory
| Element | Type | Action | Target |
|---|---|---|---|
| Tabs المختصين / الرواتب / الهيكل التنظيمي | tabs | specialists cards / payroll table / org-chart | client |
| إنشاء موظف | button | create form | `/agents/create` |
| card: toggle | switch 🟡 | activate/deactivate | `toggle-status` |
| card: عرض التفاصيل / eye | link 🟢 | view | `/agents/view?id=` |
| card: pencil | link 🟢 | edit form | `/agents/update?id=` |
| org-chart node: + / rename / drag | 🟡 | add child / rename / reparent | `structure-*` |
| org-chart node: delete | 🔴 | delete/deactivate | `structure-delete` |
| edit form | form 🟡 | personal + wage/commission + shifts + time-off | `update` |

## 2. Design findings
| # | What | Expected | Actual | Severity | Evidence |
|---|------|----------|--------|----------|----------|
| D1 | Specialists cards tab | match demo | ✅ RTL cards (toggle, avatar, wage badge, email, phone, hours, view/edit) | — | ss_4071p89yb |
| D2 | Org-structure tab | org chart w/ controls | ✅ shop root → Rawan/Rola/(stub); zoom/layout/theme/help present | — | ss_3165fnyij |
| D3 | Payroll tab | monthly payroll table | ✅ RTL table; **month localized "يوليو 2026"** (contrast w/ calendar's English "July") | — | ss_4959sgzr8 |
| D4 | Update-Agent page title | Arabic | was English "Update Agent" → missing `ar` translation | MEDIUM | ✅ FIXED (R-003) |
| D5 | Password strength meter | localized | "0% Too Short" English (3rd-party pwstrength plugin) | LOW | ss_4483msm9v |

## 3. Logic findings
| # | Action | Result | Sev |
|---|--------|--------|-----|
| L1 | Specialists/Payroll/Org tabs load | ✅ all render (RTL) | — |
| L2 | Update form load (id=38 Rola) | ✅ renders populated (avatar, fields, RTL) | — |
| L3 | toggle / create / org-chart add-reparent-delete / time-off | not live-triggered (🟡/🔴 — would create/mutate real specialists); covered by code-review + R-002 already fixed & confirmed | note |

## 4. Code trace
**Code-review agent (AgentsController + User/UserProfile) — 0 CRIT, 2 HIGH, 2 MED, 2 LOW:**
| Sev | File:line | Issue | Status |
|---|---|---|---|
| HIGH | AgentsController.php:415 actionUpdate | `status` not re-asserted after `load()` → POST `status=3` soft-deletes agent, bypasses live-booking guard | ✅ FIXED (R-H003) |
| HIGH | AgentsController.php:1071 actionCalendar | null agent skips `checkOwnership` but still queries bookings by raw id → cross-shop customer/time leak | ✅ FIXED (R-H004) |
| MED | AgentsController.php:1076 actionCalendar | ignores `$start/$end` → loads ALL bookings for agent | ⚠️ LOGGED |
| MED | AgentsController.php:1193 checkMobile | `user_id` exclusion not shop-validated (low impact — base query already scoped) | ⚠️ LOGGED |
| LOW | AgentsController.php:417 actionUpdate | no transaction around User+profile+shifts save (create path has one) | ⚠️ LOGGED |
| LOW | AgentsController.php:622 UpdateUserRelatedTbls | `$prof->save(false)` return value unchecked (silent profile-save failure) | ⚠️ LOGGED |

**Confirmed clean by agent:** create-path mass-assignment (re-asserts type/status/shop), org-chart cycle guard (`_sanitizeManagerId`+`_descendantIds`), **R-002 locale fix present & correct in both add-child + reparent**, IDOR guards on structure-rename/reparent/delete, filter-events shop scope, wage/commission validation.

## 5. Fixes applied
| Issue | File:line | Change | Re-verified |
|-------|-----------|--------|-------------|
| R-002 locale NOT NULL on org-chart create/reparent | AgentsController.php:727,802 | set `$prof->locale = Yii::$app->language` before `save(false)` | ✅ confirmed by code-review agent |
| R-003 "Update Agent" untranslated | `common/messages/{ar,en}/backend.php` | add `'Update Agent' => 'تعديل موظف' / 'Update Agent'` | ✅ live: title now "تعديل موظف" |
| R-H003 actionUpdate status mass-assignment | AgentsController.php:~415 | re-assert `$model->status = $userModel->status` | ✅ php -l clean |
| R-H004 actionCalendar null-agent IDOR | AgentsController.php:~1071 | throw NotFoundHttpException when agent null | ✅ php -l clean |

## 6. Sign-off
- [x] All 3 tabs render (RTL)
- [x] Update form renders
- [x] 2 HIGH security fixes applied + lint clean
- [x] R-002 confirmed by independent code review
- [ ] live happy-path create/edit/toggle (deferred — no real specialist mutation while user away)
- [ ] MED/LOW logged for triage
