gigafibre-fsm/apps/ops/src/components/shared
louispaulb 218f6fc7b1 feat(ops): Service Contract detail view + sub-delete redirects there
Contract termination is a fee-bearing, auditable workflow — it belongs
on the contract, not buried in a sub's delete dialog. Standard SaaS /
telecom practice: subs are an immutable event stream, contracts
orchestrate their lifecycle.

ServiceContractDetail.vue (new)
  • Status banner: contract type, dates, status — "Résilier" button
    when actionable, termination invoice link when already résilié.
  • Term progress bar: months_elapsed / duration_months with color
    ramp (primary → amber near end → positive when done).
  • Financial summary grid: mensualité, abonnement (clickable), devis,
    lieu, total avantages, résiduel, signature method & date.
  • Benefits detail table: per-row description, regular_price vs
    granted_price, économie, reconnu à date, et "À rembourser"
    (valeur résiduelle) — this is what the rep needs to see before
    deciding to break a contract.
  • Termination recap (only when status=Résilié): date, raison,
    penalty breakdown, link to the termination invoice.
  • "Résilier" action runs a 2-step dialog: first calls
    /contract/calculate-termination for the preview, then prompts for
    a reason (textarea, min 3 chars) before firing /contract/terminate.
    On success: cascade-cancels the linked sub (status=Annulé +
    end_date + cancellation_date — no hard delete), mutates the
    local doc so the modal refreshes in place, and emits
    contract-terminated so the parent page updates its sub + contract
    rows + drops an audit comment on the customer.

DetailModal
  • SECTION_MAP now routes Service Contract → ServiceContractDetail.
    Also added 'Service Subscription' → SubscriptionDetail (same
    template fits; was falling through to the generic grid).
  • Re-emits contract-terminated so the parent can listen.

ClientDetailPage
  • confirmDeleteSub: when a live contract references the sub, the
    dialog now simply redirects the rep to the contract modal
    ("Voir le contrat") instead of trying to do termination from
    the sub row. Terminal-state contracts (Résilié/Complété/Expiré)
    still get the inline link-scrub path so stale refs don't block
    a legit delete.
  • onContractTerminated: reflects the cascade locally — contract
    row → Résilié, sub row → Cancelled + end_date, audit Comment
    posted to the customer's notes feed.
2026-04-23 14:46:34 -04:00
..
detail-sections feat(ops): Service Contract detail view + sub-delete redirects there 2026-04-23 14:46:34 -04:00
ConversationPanel.vue refactor: major cleanup — remove dead dispatch app, commit all backend code, extract client composables 2026-04-08 17:38:38 -04:00
CreateInvoiceModal.vue refactor: reduce token count, DRY code, consolidate docs 2026-04-13 08:39:58 -04:00
DetailModal.vue feat(ops): Service Contract detail view + sub-delete redirects there 2026-04-23 14:46:34 -04:00
InlineField.vue feat: inline editing, search, notifications + full repo cleanup 2026-03-31 07:34:41 -04:00
OutageAlertsPanel.vue refactor: reduce token count, DRY code, consolidate docs 2026-04-13 08:39:58 -04:00
ProjectWizard.vue feat: flow editor, Gemini QR scanner with offline queue, dispatch planning v2 2026-04-22 10:44:17 -04:00
RecurrenceSelector.vue feat: dispatch planning mode, offer pool, shared presets, recurrence selector 2026-04-08 22:44:18 -04:00
TagEditor.vue refactor: major cleanup — remove dead dispatch app, commit all backend code, extract client composables 2026-04-08 17:38:38 -04:00
TaskNode.vue fix(ops/TaskNode): drop credentials:'include' on job-delete fetch 2026-04-23 10:57:57 -04:00
UnifiedCreateModal.vue refactor: major cleanup — remove dead dispatch app, commit all backend code, extract client composables 2026-04-08 17:38:38 -04:00