no-mistakes(document): Docs synced for Cancelled status; lint cleaned

This commit is contained in:
root
2026-08-02 14:37:37 +00:00
parent 6b92c9098c
commit bf361d76bc
6 changed files with 12 additions and 9 deletions
+3 -2
View File
@@ -74,8 +74,9 @@ Frontend: Alpine.js (CDN) + Tailwind CSS (CDN). Auth state in localStorage. Role
|--------|------|------|-------------|
| POST | `/api/tickets` | Bearer | Create ticket (auto-number PAV-YYYY-NNNNN) |
| GET | `/api/tickets` | No | List tickets (filter: status, priority, property, building, unit_id, category_id, assigned_to, date_from, date_to) |
| GET | `/api/tickets/{id}` | No | Get ticket detail with timeline, photos, SLA status |
| PATCH | `/api/tickets/{id}` | Bearer | Update ticket (validates status transitions) |
| GET | `/api/tickets/{id}` | No | Get ticket detail with timeline, photos, SLA status, nested unit/category, phone |
| GET | `/api/tickets/{id}/transitions` | No | Valid next statuses for the ticket's current status (drives the detail-page status picker) |
| PATCH | `/api/tickets/{id}` | Bearer | Update ticket (validates status transitions; assigning a technician auto-advances New/Logged/Triage to Assigned) |
| DELETE | `/api/tickets/{id}` | Admin/Jerome, Admin/Wahab | Delete ticket + children (timeline/photos/escalations); test/scratch cleanup only |
| POST | `/api/tickets/{id}/status` | Bearer | Change status with note |
| GET | `/api/tickets/{id}/sla` | No | Check SLA breach status |
+4 -2
View File
@@ -120,7 +120,7 @@ Close Ticket
Archive → Executive Reporting
```
### Detailed Ticket Lifecycle (15 Statuses)
### Detailed Ticket Lifecycle (16 Statuses)
| # | Status | Description | Who Sets |
|---|--------|-------------|----------|
@@ -139,6 +139,7 @@ Archive → Executive Reporting
| 13 | **Wahab Review** | Final QA oversight and closure approval | Wahab |
| 14 | **Closed** | Ticket officially closed | Wahab / Nicholas |
| 15 | **Reopened** | Issue resurfaces within 7 days | Agent / System |
| 16 | **Cancelled** | Ticket withdrawn (test/scratch cleanup, guest no-show); terminal — reachable from any active state, excluded from SLA breach reporting and dashboard active counts | Any staff (via dashboard) |
### Step-by-Step Detail
@@ -154,9 +155,10 @@ Archive → Executive Reporting
9. **Wahab Review** — Wahab does final QA oversight in dashboard → status → Wahab Review → approves or sends back
10. **Auto Follow-up** (48 hours later — internal only) — System flags ticket for Wahab/Nicholas: `Issue PAV-001 (505E WC) — resolved 48h ago. Any follow-up needed?` → If issue resurfaces → auto-reopens, escalates to Ama
### Reopening & Reassignment
### Reopening, Reassignment & Cancellation
- **Reopening:** If a verified-closed issue resurfaces within 7 days, the gatekeeper can Reopen it. A reopened issue auto-escalates to Ama.
- **Cancellation:** Any ticket can be cancelled from an active state (terminal; cannot resume work). Cancelled tickets are excluded from SLA breach reporting and dashboard active counts.
- **Reassignment:** A technician who cannot complete a job can request: `#reassign PAV-001 [technician name]` → Nicholas receives notification and approves/reassigns in dashboard.
---
-1
View File
@@ -3,7 +3,6 @@
from __future__ import annotations
from datetime import datetime, timedelta, timezone
from functools import wraps
from typing import Annotated, Any, Callable
import bcrypt
+1 -1
View File
@@ -2,7 +2,7 @@
from __future__ import annotations
from pydantic import BaseModel, EmailStr
from pydantic import BaseModel
class RegisterRequest(BaseModel):
-2
View File
@@ -3,11 +3,9 @@
from __future__ import annotations
from fastapi import HTTPException, status
from jose import JWTError, jwt
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.config import settings
from app.core.security import (
create_access_token,
create_refresh_token,
+4 -1
View File
@@ -281,7 +281,10 @@ async def test_ticket_number_uses_max_plus_one(client, seed_tickets):
await session.commit()
fourth = await _create_ticket(client, token, description="numbering d")
suffix = lambda tn: int(tn.rsplit("-", 1)[1])
def suffix(tn: str) -> int:
return int(tn.rsplit("-", 1)[1])
survivors = {suffix(first["ticket_number"]), suffix(third["ticket_number"])}
assert suffix(fourth["ticket_number"]) not in survivors
assert suffix(fourth["ticket_number"]) > max(survivors)