# Phase 3D — Multi-Employee Batch Schedule Assignment ## 1. Architecture Batch Assignment upgrades the Advance Assignment Wizard to allow multiple employee selections for users with direct scheduling privileges. The core design relies on a two-stage workflow enforced by the new \atch-assign.php\ endpoint: 1. **Validate**: A read-only preflight check. Returns normalized conflict, invalid state, and leave warnings for every selected employee. 2. **Apply**: Using the Phase 3C.3 atomic per-employee lock (\SELECT employee_id FOR UPDATE\), the backend safely revalidates conflicts and creates schedules in isolated transactions. ## 2. API Contract \POST /api/schedule-manager/batch-assign.php\ **Request payload:** \\\json { \ employee_ids\: [\EMP1\, \EMP2\], \schedule\: { \work_time_id\: 2, \effective_date\: \2026-08-10\, \recurrence_type\: \none\ }, \mode\: \validate\ // or \apply\ } \\\ ## 3. Validation Results - **Ready**: Employee is valid and has no schedule conflicts. - **Conflict**: A scheduling overlap exists. Will be skipped during Apply. - **Warning**: Employee is technically 'Ready' but has overlapping approved leave. Handled via the \leave_requests\ table. - **Invalid**: Not found, inactive, or outside tenant permissions. ## 4. Per-Employee Transaction Model To ensure partial-success, \atch-assign.php\ runs the \Apply\ step using an atomic loop: \\\ ext FOREACH employee: BEGIN TRANSACTION Lock employee row FOR UPDATE Revalidate detectScheduleConflicts() Insert if valid COMMIT (or ROLLBACK on conflict) \\\ This ensures one conflicting employee does not crash or roll back the other 49 successfully assigned employees. ## 5. Security & Idempotency - **Idempotency**: Because Apply always revalidates under lock, rapid repeated requests will detect the previously inserted schedule as a conflict and safely skip it. - **Tenant Isolation**: \dmin_request_require_employee_scope()\ restricts schedule edits to employees within the authenticated user's branch/company. ## 6. Files Modified - \ rontend/src/components/schedule-manager/schedule-manager-components/AssignScheduleWizard.jsx\ - \ackend/schedule-manager/batch-assign.php\ (NEW) ## 7. QA Results - **2 employees**: PASS - **50 employees**: PASS - **Duplicate IDs normalized**: PASS - **Leave Warnings shown**: PASS - **Conflicts skipped safely without breaking batch**: PASS ## 8. Known Limitations - The Review Summary does not provide deep diffs of conflicts. Conflicting employees are simply flagged and skipped. ## 9. Next Phase Recommendation Phase 3E: Bulk Schedule Exceptions & Adjustments. Now that mass-creation works, users will need a safe UX to modify or clear specific dates from recurring schedules without affecting the rest of the pattern. ## Phase 3D.1 — Leave Warning Precision & Timezone Verification **Status: PASS** ### 1. Root Cause of False-Positive Leave Warnings In Phase 3D, leave warnings were generated by querying any approved \leave_requests\ that broadly intersected the entire \effective_date\ and \end_date\ range of the schedule pattern. This caused false-positives for recurring schedules (e.g. a weekly Monday/Wednesday shift would generate a warning for an approved Tuesday leave, even though Tuesday had no scheduled occurrences). ### 2. Leave Occurrence Logic The backend \getLeaveWarnings()\ function was upgraded to dynamically generate actual scheduled date occurrences in PHP (mirroring the frontend preview generator logic). It respects: - One Day - Daily Range - Weekly Pattern (matching specific days of the week) - Recurrence Interval Once the array of actual occurrence dates is generated, it is checked against the employee's approved leave blocks. If a generated date lands within \date_from\ and \date_until\ of an approved leave, an explicit warning object is returned containing the exact \date\ and \leave_type\. ### 3. Timezone Verification Verified that PHP's timezone for historical date checking was vulnerable to system defaults. Added \date_default_timezone_set('Asia/Manila');\ immediately before checking the \effective_date < \\ logic to guarantee deterministic server-side bounds matching the frontend UX timezone context. ### 4. API Changes The warning structure was updated to match conventions: \\\json \ warnings\: [ { \type\: \approved_leave\, \date\: \2026-08-12\, \leave_type\: \Vacation Leave\ } ] \\\ ### 5. UI Updates Updated \AssignScheduleWizard.jsx\ to parse the new object format and render explicit warning strings like: _\Approved Vacation Leave on 2026-08-12\_ ### 6. Database Changes NONE. ## Phase 3D.1 — Leave Warning Precision **Status: PASS** ### 1. Root Cause of False-Positive Leave Warnings In Phase 3D, leave warnings were generated by querying any approved \leave_requests\ that broadly intersected the entire \effective_date\ and \end_date\ range of the schedule pattern. This caused false-positives for recurring schedules (e.g. a weekly Monday/Wednesday shift would generate a warning for an approved Tuesday leave, even though Tuesday had no scheduled occurrences). ### 2. Occurrence-Based Leave Detection The backend \getLeaveWarnings()\ function was rewritten to precisely generate actual scheduled dates before checking leaves. It mirrors the frontend preview logic by respecting: - One Day - Daily Range - Weekly Pattern (matching specific days of the week) - Recurrence Interval Once the array of proposed working dates is populated (capped at 365 iterations for safety), the script iterates through approved leave blocks. If a generated schedule date intersects a leave block, the date is pushed into a grouped array specific to that \leave_type\. ### 3. Timezone Verification Verified that PHP's timezone for historical date checking was vulnerable to system defaults. Added \date_default_timezone_set('Asia/Manila');\ immediately before checking the \effective_date < \\ logic to guarantee deterministic server-side boundaries that match the frontend UX context. ### 4. API Changes The warning structure was updated to match project JSON conventions and avoid duplicate warning rows for multi-day leaves: \\\json \ warnings\: [ { \type\: \approved_leave\, \affected_dates\: [ \2026-08-12\, \2026-08-13\ ], \leave_type\: \Vacation Leave\ } ] \\\ ### 5. UI Updates Updated \AssignScheduleWizard.jsx\ to parse the grouped \ffected_dates\ format and elegantly render it in the Validation Review UI. ### 6. QA Results - **Weekly Pattern Test**: A Mon/Wed/Fri schedule spanning the entire month correctly ignores a Thursday leave date. A Friday leave accurately produces a warning localized to Friday's date. - **Daily / One-Day Tests**: One-Day triggers only if the specific day is on leave. Daily Range correctly detects any intersecting days. - **Concurrency Regression**: Validated that \mode='apply'\ strictly maintains the \FOR UPDATE\ employee row lock and \detectScheduleConflicts()\ revalidation before any insert. - **Advisory Behavior**: Validated that warnings do not block the atomic \INSERT\, leaving final discretion to HR. ### 7. Database Changes NONE. ### 8. Remaining Limitations None identified for this specific Phase 3D scope.