agenda: label + badge cientes de pacote em sessoes state=none

Bug descoberto durante teste C11: sessao 27/05 do Andre Green
(materializada via Falta+reverse, pertence ao pacote saldo)
mostrava "A cobrar R$ 40,00" no popover mesmo sem fatura ativa.
Implicava que dava pra gerar cobranca avulsa solta — conflito
com o flow do pacote (Usar consume saldo).

Fix em paymentLabel: quando state='none' e ev.contract existe,
label muda conforme estilo:
- saldo: "Aguardando uso do pacote"
- upfront: "Coberta pelo pacote (upfront)"
Avulsa sem pacote continua mostrando "A cobrar R$ X".

Simetria em MelissaAgenda.vue badge gate: nao mostra badge $ amber
em sessao state=none com pacote amarrado (hasPacoteTied). Sem
isso, sessao agendada de pacote saldo no calendar ficava com
badge "cobranca pendente" enganoso.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Leonardo
2026-05-20 12:09:45 -03:00
parent 3f3f2acc70
commit 45984e885b
2 changed files with 11 additions and 1 deletions
+5 -1
View File
@@ -659,11 +659,15 @@ const fcOptions = computed(() => ({
// state='none' (records cancelled filtrados) — sessão não rolou,
// cobrança nova não cabe. Multa pendente vem com state='pending'
// e aí entra pelo ramo anterior, ok.
// Sessão com pacote ativo (saldo OU upfront) com state='none' também
// NÃO ganha badge — billing é via pacote, não cobrança avulsa solta.
// Pra saldo: aguarda "Usar"; pra upfront: já coberta pelo contrato.
const statusLower = String(ext.status || '').toLowerCase();
const sessaoEncerrada = statusLower === 'cancelado' || statusLower === 'cancelada' || statusLower === 'faltou';
const hasPacoteTied = !!ext.contract;
const wantBadge = isSessao && ext.patient_id && ext.paymentState !== 'paid' && !sessaoEncerrada && (
ext.paymentState === 'pending' || ext.paymentState === 'overdue' ||
(!ext.is_occurrence && (ext.paymentState === 'none' || !ext.paymentState))
(!ext.is_occurrence && (ext.paymentState === 'none' || !ext.paymentState) && !hasPacoteTied)
);
if (wantBadge) {
payBadgeHtml = `<span class="mc-fc-event__paybadge" title="Cobrança pendente"><i class="pi pi-dollar"></i></span>`;
@@ -190,6 +190,12 @@ const paymentLabel = computed(() => {
const slug = String(ev.value.status || '').toLowerCase();
if (slug === 'cancelado' || slug === 'cancelada') return 'Sessão cancelada · sem cobrança ativa';
if (slug === 'faltou') return 'Sessão não realizada · sem cobrança ativa';
// Pacote tied → não cabe "A cobrar R$ X" solto porque o billing é via
// pacote (saldo: aguarda Usar; upfront: já está coberto pelo contrato).
// Contract row já mostra o status do pacote.
const cInfo = ev.value.contract;
if (cInfo?.style === 'saldo') return 'Aguardando uso do pacote';
if (cInfo?.style === 'upfront') return 'Coberta pelo pacote (upfront)';
return valorFmt ? `A cobrar ${valorFmt}` : 'Cobrança ainda não gerada';
});