Commit Graph
18 Commits
Author SHA1 Message Date
root 43800345c1 feat(dashboard): technician performance report + real technician names
Wahab customer request (relay #748 v3 next-wave).

3a. Fix 'Tech #N' display:
- FM dashboard's "Technician Workload" card was built from
  `Tech #${t.assigned_to}`; it now reads Ticket.assigned_technician_name
  (falling back to 'Unassigned', matching /tickets).
- Template sweep confirms no other `Tech #` placeholder exists.

3b. Technician performance dashboard:
- New bearer-gated GET /api/tickets/tech-performance aggregating existing
  ticket columns only (no schema change): per-technician total assigned,
  completed, in progress, escalated, cancelled, pending, open tasks,
  completion rate, and created_at -> closed_at resolution time with explicit
  counts for finished tasks lacking a timestamp. Rows key on user id so
  same-name technicians stay separate; labels are real names. Fleet totals
  and an unassigned-ticket count are included.
- New /dashboard/tech-performance page (FM + CEO nav and links) with sortable
  table, completion bars and empty states; same-origin vendored assets only.
- Bucket map, service, schemas and tests in app/services/ticket.py,
  app/schemas/ticket.py, tests/test_tech_performance.py.

Tests: 111 passed (101 existing + 10 new).
2026-09-10 04:00:19 +00:00
root a6eb799efa feat(whatsapp,branding): WhatsApp demo-number wiring + Denya logo assets
WhatsApp demo path (relay #748):
- WHATSAPP_DEMO_TO config under the WhatsApp section (env-based, .env-only;
  .env.example keeps an empty placeholder; real numbers never enter source).
- build_demo_webhook_payload() in app/routers/whatsapp.py builds the Meta
  demo payload from it (fails closed when unset), so the webhook round trip
  logs from_number = demo number (surfaces in GET /api/whatsapp/mock-log) and
  the auto-reply targets the same number.
- tests/test_whatsapp_demo_number.py: default empty + never committed in
  tracked files, payload builder from/to, 200/403/401 gates unchanged.

Branding (logo-assets-v1, sha256-verified, same-origin app/static/branding):
- Login header uses h96 full lockup; logged-in topbar (base.html) uses h48 on
  a light chip (logo ink is ~2:1 vs the dark nav); favicons 32x32 + 16x16 in
  <head>. img-src 'self' data: blob: already allows /static/branding/*.
- tests/test_branding_assets.py: page placement + same-origin serving + CSP.
- AGENTS.md synced.
2026-09-09 19:32:21 +00:00
fm crewmate 05d768343c fix(frontend): vendor Alpine.js + Tailwind same-origin (LAN-safe demo)
The P0 templates loaded Alpine.js from cdn.jsdelivr.net and Tailwind from
cdn.tailwindcss.com, so LAN-only demo clients got a login page whose JS never
engaged (stuck form). Vendor both libraries under app/static/vendor/
(alpine-3.17.2.min.js, tailwind-3.4.17.js) served same-origin at /static,
point base.html at local paths, and drop both CDN hosts from the CSP
(script-src/style-src stay 'self' 'unsafe-inline'; connect-src 'self').

HTML pages now ship Cache-Control: no-cache; vendored assets are cached
public, max-age=31536000, immutable (versioned filenames). HSTS stays
TLS-gated. Adds tests/test_frontend_vendoring.py (no external script src on
/login, both vendor paths 200, no-cache + immutable header checks, CSP
without CDN hosts).
2026-09-09 01:01:47 +00:00
root e0a7479c3e feat: backdated reported date for old active tickets
Wahab can now enter historical tickets that keep their true reported date:

- Add nullable tickets.reported_at (DateTime) via alembic d5e0f2a1c3b4;
  backfill existing rows from created_at so nothing shows empty.
- TicketCreate.reported_at (optional) is persisted by create_ticket and
  defaults to now when omitted, so existing create behavior is unchanged.
- New-issue form gains a 'Reported Date' date picker (defaults to today,
  past dates allowed, future blocked) and sends reported_at in the payload.
- List and detail pages show 'Reported' next to 'Created' (date-only,
  labeled) so backdated tickets are obvious; SLA deadline is unchanged and
  still runs from creation time so backfilling never instantly breaches.
- Tests: backdated create persists + is exposed on list/detail; omitted
  reported_at defaults to now; SLA window unchanged; full datetime round trip.
2026-08-03 09:40:23 +00:00
root 6b92c9098c no-mistakes(review): Guard photo cleanup; add transitions helper and assign auto-advance 2026-08-02 14:26:48 +00:00
root 237284b012 no-mistakes(review): Make Cancelled reachable from all active states; wire phone PATCH; exclude cancelled from CEO resolution avg 2026-08-02 14:12:46 +00:00
root 1dd88a141e feat: Wahab demo prep — Cancelled status, phone persistence, admin delete, users picker, detail-page fixes
- Add Cancelled as terminal status reachable from all active states; exclude
  from SLA breach reporting and dashboard active counts; add to status pickers
- Persist customer phone on ticket create/update (was silently dropped);
  add tickets.phone migration + legacy self-heal guard
- Add admin-only DELETE /api/tickets/{id} (removes timeline/photos/escalations)
- Add GET /api/auth/users for the assign-technician dropdown (was hardcoded)
- TicketOut now returns nested unit/category so the detail page stops showing
  '—' for Unit/Property/Category
- Ticket numbering uses max+1 so deletions never re-issue a number
- New-issue form: require Category and (standard mode) Priority client-side
- Tests: 11 new cases covering cancellation, SLA exemption, phone, delete,
  users endpoint, numbering
2026-08-02 14:06:30 +00:00
root 663354eeaf no-mistakes(review): Extend legacy self-heal rename; clear stale Mould & Damp priority default 2026-08-02 13:22:32 +00:00
root ae17005932 no-mistakes(review): Fix stale urgent priority when leaving emergency mode 2026-08-02 12:26:19 +00:00
root 2407f294f4 feat: Sprint A Wahab review batch — categories, property hierarchy, priority grouping
Items 1-5, 9, 11 from denya-wahab-feedback-s2:
- Category.show_in_form (alert-only flag): Gas Leak hidden from issue picker
  but kept urgent for SLA/alert and reporting; emergency quick path on the
  new-issue form creates urgent tickets via include_hidden categories.
- Seed: Aluminum/Glass, Carpentry, Mould & Damp (Medium default) maintenance
  categories; Lost Property renamed Missing Item (+ sub).
- One alembic migration: add show_in_form (backfill True, Gas Leak False) +
  data rename Lost Property -> Missing Item.
- Property -> Building -> Apartment cascade with searchable apartment combobox
  on the new-issue form and ticket list filters; /api/tickets/units gains
  building filter + /units/grouped variant; /api/tickets gains additive
  building/unit_id filters. apartment_mapping.json committed (deterministic).
- Group-by-priority toggle on /tickets (four sections + unknown bucket,
  age-sortable, composes with filters, URL deep links), FM dashboard active
  tickets, and CS dashboard priority card click-through.
- Tests: 13 new (category visibility, seed idempotency/sync, unit grouping,
  ticket building/unit filters).
2026-08-02 09:30:29 +00:00
root 47be148240 fix(dashboard): paginate CEO dashboard ticket fetch to respect API cap
The CEO dashboard requested /api/tickets?page_size=500, but the API caps
page_size at 200 (le=200 in app/routers/tickets.py), so the request
returned 422 and every KPI/chart rendered zeros.

- ceo.html: fetch all tickets by looping pages of page_size=200 until
  total items are collected (with a safety bound), keeping KPIs accurate
  as volume grows past 200.
- tests: add test suite anchoring the pagination contract — page_size=500
  returns 422, page_size=200 returns items/total/page/page_size, and a
  page loop collects every ticket without duplicates.
- pyproject: enable pytest-asyncio auto mode and tests/ discovery.
- .gitignore: un-ignore committed tests/test_*.py.
2026-07-31 09:53:35 +00:00
root cf55576d10 feat: Denya Developers brand theming
- Brand colors: primary #0d2b18 (deep forest green), accent #c8a96e (gold), bg #faf8f5 (cream), text #1a1a1a
- Nav bg #0d2b18 with gold logo mark and white text
- Denya Developers + OneCare branding in nav header
- Gold accent borders, hover states, and active tab highlights
- Toast/success use brand green shades
- Body background cream (#faf8f5)
2026-07-25 00:19:59 +00:00
root ef2297ea87 no-mistakes(review): Fixed aging bucket boundaries and removed wasteful API call 2026-07-23 19:21:31 +00:00
root a9c17d0703 fix: address remaining review findings
- Fix detail.html to use assigned_technician_name (not .assigned_technician?.full_name)
- Remove double error toast in submitNote() catch block
- Replace wasteful API calls in CEO dashboard with units+data approach
- Remove QR Code option from reported_via dropdown (excluded per scope)
2026-07-23 19:18:17 +00:00
root 5560496653 no-mistakes(review): Fix F01/F02/F05: technician name, duplicate timeline, FM dashboard property counts 2026-07-23 19:13:10 +00:00
root 7fab1ede51 fix: address ask-user findings from review
- Move unit loading to use real /api/tickets/units endpoint
- Match unit code format to backend seed (0101E style)
- Send unit_id in create ticket payload
- Fix tech IDs to match seed order (9-15 for Prosper-Afful)
- Add customer_name and phone fields to TicketCreate schema
- Map form customer_name/phone into API payload
2026-07-23 19:08:49 +00:00
root 3dc383e62d fix: auto-fix findings from no-mistakes review
- Remove duplicate  import
- Fix  →  in create ticket
- Fix  →  in ticket detail
- Add note field to TicketUpdate schema and handle note-only updates in backend
- Update frontend submitNote() to use PATCH endpoint
2026-07-23 19:06:33 +00:00
root 9aa7971a28 feat: Sprint 3 frontend dashboards with Alpine.js + Jinja2
- Login page with JWT auth and role-based redirect
- CS Dashboard: KPI cards, priority breakdown, recent tickets
- FM Dashboard: tech workload, aging analysis, emergency alerts
- CEO Dashboard: executive KPIs, charts, risk indicators
- All Issues: filterable/sortable ticket table with pagination
- Create Issue: form with category tree, property/unit selector, photo uploads
- Issue Detail: full timeline, photo gallery, SLA status, action modals
- Role-based nav bar: CS/FM/Executive links adapt to user role
- Base template: shared Alpine.js app state, toast notifications, loading overlay
2026-07-23 19:01:26 +00:00