# Test Scenario Guide: Annual Visit Plan

### 1. Title
# Test Scenario Guide: Annual Visit Plan (Maintenance Scheduling)

### 2. Scenario Introduction 🏢
The **Annual Visit Plan** feature is designed to bridge the gap between high-level maintenance contracts and the execution of visits. It provides a **planning layer** where supervisors can distribute a contract's total required visits across the 12 months of the year. This allows for better resource allocation, client alignment (via schedule uploads), and proactive validation against contract constraints before any actual visit records are committed to the system.

### 3. Technical Schema Changes (Detailed) 🔍

*   **Endpoint:** `POST /api/maintenance/annual-visit-plans`
    *   **Validation Changes:**
        *   `contract_id`: **Required**, must exist in `mod_maintenance_contracts`.
        *   `items`: **Required array**, contains month-by-month distribution.
        *   `items.*.month`: **Required**, format `YYYY-MM`.
        *   `items.*.visit_count`: **Required integer**, minimum `0`.
*   **Endpoint:** `POST /api/maintenance/annual-visit-plans/upload`
    *   **Validation Changes:**
        *   `file`: **Required**, supports `xlsx`, `xls`, `csv`.
*   **Endpoint:** `GET /api/maintenance/annual-visit-plans/{id}/summary`
    *   **Response Changes:** Returns a breakdown of `planned_visits` vs. `backlog_visits` per month and a validation object containing **Rule A, B, and C** results.

### 4. Why the Update? (Change Log) 🔄
**Previous Behavior:**
*   Visits were either generated automatically by fixed rules or imported directly into the backlog without a prior review/planning stage.
*   No way to visualize the distribution of visits across months relative to existing backlog entries.
*   No proactive warning for months that might have been accidentally skipped (Zero-visit months).

**New Behavior:**
*   **Intermediate Planning**: Supervisors can save draft plans and iterate on them.
*   **Integrated Review**: Real-time comparison between the new plan and existing system backlog.
*   **Enhanced Integrity**: Mandatory **Handover Guard** prevents plan approval until the asset receipt process is finalized.
*   **Flexibility**: Support for both manual entry and bulk extraction from client-provided Excel schedules.

### 5. API Endpoints Table 📊

| Process | Endpoint | Method | Description |
| :--- | :--- | :--- | :--- |
| **Save Draft** | `/api/maintenance/annual-visit-plans` | `POST` | Create or update a yearly visit distribution draft. |
| **Extract Schedule** | `/api/maintenance/annual-visit-plans/upload` | `POST` | Parse an Excel file to extract months and visit counts. |
| **Review Summary** | `/api/maintenance/annual-visit-plans/{id}/summary` | `GET` | Compare draft vs. backlog and run validation rules. |
| **Approve Plan** | `/api/maintenance/annual-visit-plans/{id}/approve` | `POST` | Finalize plan and generate visits in the backlog. |

### 6. Test Cases 🧪

*   **[Case 1] The Happy Path (Excel to Approved):**
    1.  Upload a valid Excel schedule containing 12 months of visits.
    2.  Review the extracted counts and save as a **Draft**.
    3.  Verify the **Review Summary** shows the correct total matching the contract.
    4.  Trigger **Approve** and confirm that `mod_maintenance_visits` are created with `status = awaiting_scheduling` and correct `planned_date` placeholders.

*   **[Case 2] Handover Guard Enforcement:**
    1.  Attempt to **Approve** a plan for a project where the Handover Visit is either not completed or the report is not approved.
    2.  **Expected Result**: System returns a `500` error with a message indicating the Handover Guard restriction.

*   **[Case 3] Validation Constraints (Rules A, B, C):**
    *   **Rule A (Failure)**: Send a plan where the sum of `visit_count` is 10 but the contract requires 12. -> **Expected**: `is_valid: false` in summary.
    *   **Rule B (Failure)**: Include a month (e.g., `2027-01`) that is outside the contract's end date. -> **Expected**: Error message in validation results.
    *   **Rule C (Warning)**: Skip a month within the contract period. -> **Expected**: `is_valid: true` but `warnings` array contains the missing month notification.

*   **[Case 4] Unauthorized Access:**
    1.  Attempt to access summary or approve a plan without a valid `sanctum` token.
    2.  **Expected Result**: `401 Unauthorized`.
