gigafibre-fsm/apps/ops/src/components/shared/TicketStatusMenu.vue
louispaulb e1d3212bf7 feat(ops): ticket Statut control (Complété/Annulé) + sale activation → draft invoice
Add a "Statut" button on the ticket (distinct from the snooze "Reporter"):
Ouvert / En attente / Complété (Resolved) / Annulé (Closed). Additive — does not
touch the shared TicketStatusControl.

For a ticket with a linked open install job, an explicit "Activer + facture
brouillon" button (also offered when set to Complété) reuses the EXISTING hub
flow: POST /dispatch/job-status Completed → chain unblock → activateSubscription
ForJob → one consolidated prorated DRAFT invoice, gated by PRORATION_WRITE /
BILLING_APPROVAL_GATE (never auto-charges; billing manager edits/approves). No
new billing logic, no hub change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 15:04:08 -04:00

40 lines
2.6 KiB
Vue

<script setup>
/**
* TicketStatusMenu — bouton « Statut » du ticket (distinct du bouton « Reporter » = snooze).
*
* Change le STATUT du billet Issue, avec la distinction demandée : fermer en **Complété**
* (résolu avec succès → déclenche la fulfillment de vente : activation + facture) VS **Annulé**
* (fermé sans suite). Émet 'set-status' ; le parent écrit et gère la suite (activation vente).
* Purement additif — ne touche PAS TicketStatusControl (partagé, = report/snooze).
*/
import { computed } from 'vue'
const props = defineProps({
status: { type: String, default: '' },
})
const emit = defineEmits(['set-status'])
// Complété = Resolved (résolu) · Annulé = Closed (fermé sans suite). Les autres = états de travail.
const META = {
Open: { label: 'Ouvert', color: 'blue-6', icon: 'radio_button_unchecked' },
Replied: { label: 'Répondu', color: 'teal-6', icon: 'reply' },
'On Hold': { label: 'En attente', color: 'orange-7', icon: 'pause_circle' },
Resolved: { label: 'Complété', color: 'green-7', icon: 'check_circle' },
Closed: { label: 'Annulé', color: 'grey-6', icon: 'cancel' },
}
const cur = computed(() => META[props.status] || { label: props.status || 'Statut', color: 'grey-7', icon: 'flag' })
</script>
<template>
<q-btn-dropdown unelevated no-caps :color="cur.color" :icon="cur.icon" :label="'Statut : ' + cur.label" dense>
<q-list dense style="min-width:210px">
<q-item-label header class="q-py-xs">Changer le statut</q-item-label>
<q-item clickable v-close-popup @click="emit('set-status', 'Open')"><q-item-section avatar><q-icon name="radio_button_unchecked" color="blue-6" /></q-item-section><q-item-section>Ouvert</q-item-section></q-item>
<q-item clickable v-close-popup @click="emit('set-status', 'On Hold')"><q-item-section avatar><q-icon name="pause_circle" color="orange-7" /></q-item-section><q-item-section>En attente</q-item-section></q-item>
<q-separator />
<q-item clickable v-close-popup @click="emit('set-status', 'Resolved')"><q-item-section avatar><q-icon name="check_circle" color="green-7" /></q-item-section><q-item-section><q-item-label>Complété</q-item-label><q-item-label caption>Résolu pour une vente : active + facture</q-item-label></q-item-section></q-item>
<q-item clickable v-close-popup @click="emit('set-status', 'Closed')"><q-item-section avatar><q-icon name="cancel" color="grey-6" /></q-item-section><q-item-section><q-item-label>Annulé</q-item-label><q-item-label caption>Fermé sans suite (pas de facturation)</q-item-label></q-item-section></q-item>
</q-list>
</q-btn-dropdown>
</template>