agenda: C10 pos-test fixes + lock sessao encerrada + addendum doc
Bugs descobertos durante testes C10/A2/B/C com user:
1) _reloadRange not defined: _buildHandlers nao destruturava
_reloadRange do deps (passava mas nao desempacotava). Toast
ReferenceError ao tentar reload pos-status change. Fix em
useMelissaAgenda.js:_buildHandlers.
2) Badge $ amber em sessao cancelada: MelissaAgenda.vue badge gate
ignorava status. Cancelado+state=none (records cancelled
filtrados) ainda recebia badge "cobranca pendente". Fix: gate
sessaoEncerrada (cancelado/faltou) -> sem badge nunca.
3) Botao "Gerar cobranca" em sessao encerrada: AgendaEventoFinanceiro
Panel mostrava botao mesmo em cancelado/faltou -> user podia
emitir fatura nova em sessao que nao aconteceu. Fix: v-if
!isSessaoEncerrada + label muda pra "Sessao cancelada · sem
cobranca ativa".
4) paymentLabel usava ev.price em vez de paymentAmount pra state
'pending': caso multa R$ 30 mostrava R$ 150 (ev.price original).
Fix: usar paymentAmount tambem em pending.
5) Lock total em sessao encerrada (cancelado/faltou):
- "Editar sessao" SOME do popover
- Realizada/Falta/Reagendar/Cancelar disabled com tooltip
- Apenas "Agendada" continua funcional (caminho explicito de
recuperacao). Single path de saida do estado encerrado.
Adicoes UX em AgendaStatusChangeConfirmDialog:
- Hint contextual sobre min_hours_notice explicando POR QUE multa
veio (des)marcada por padrao: "Cancelou 18.5h antes da sessao.
Regra: multa apenas quando cancelamento <2h -> sem multa por
padrao." Terapeuta ve a razao e pode inverter conscientemente.
Adicoes UX em MelissaEventoPanel:
- Botao "Agendada" (variante --info azul cyan) no grupo status
pra reset/recuperacao. CSS .evento-act--info hover + is-current.
Doc:
- Addendum C10 no topo de src/docs/agenda-compromisso-financeiro
-cenarios.html capturando todas as divergencias/melhorias vs
mockup original + 3 pendencias pos-C13 (reverse transitions,
popover snapshot, A2 markPaid stale).
Pendencias salvas em memoria pra puxar pos-C13.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -100,6 +100,20 @@ const scenario = computed(() => {
|
||||
|
||||
const canAct = computed(() => record.value && (record.value.status === 'pending' || record.value.status === 'overdue'));
|
||||
|
||||
// Sessão encerrada (não rolou) — bloqueia geração de cobrança nova.
|
||||
// Multa em cancelado/faltou deve passar pelo AgendaStatusChangeConfirmDialog,
|
||||
// não por "Gerar cobrança" solto que ignora o motivo.
|
||||
const isSessaoEncerrada = computed(() => {
|
||||
const s = String(props.evento?.status || '').toLowerCase();
|
||||
return s === 'cancelado' || s === 'cancelada' || s === 'faltou';
|
||||
});
|
||||
const semCobrancaLabel = computed(() => {
|
||||
const s = String(props.evento?.status || '').toLowerCase();
|
||||
if (s === 'cancelado' || s === 'cancelada') return 'Sessão cancelada · sem cobrança ativa';
|
||||
if (s === 'faltou') return 'Sessão não realizada · sem cobrança ativa';
|
||||
return 'Sem cobrança gerada';
|
||||
});
|
||||
|
||||
// ── buscar financial_record pelo evento ───────────────────────────────────────
|
||||
async function fetchRecord() {
|
||||
if (!props.evento.id) return;
|
||||
@@ -235,10 +249,13 @@ function requestCancel() {
|
||||
<div v-else-if="scenario === 'sem-cobranca'" class="fin-panel__body fin-panel__body--empty">
|
||||
<div class="flex items-center gap-2 text-[var(--text-color-secondary)]">
|
||||
<i class="pi pi-minus-circle text-sm opacity-50" />
|
||||
<span class="text-sm">Sem cobrança gerada</span>
|
||||
<span class="text-sm">{{ semCobrancaLabel }}</span>
|
||||
</div>
|
||||
<Button label="Gerar cobrança" icon="pi pi-plus" size="small" class="rounded-full mt-2" :loading="generating || finLoading" @click="onGerarCobranca" />
|
||||
<div v-if="props.evento.price" class="text-xs text-[var(--text-color-secondary)] mt-1">Valor da sessão: {{ fmtBRL(props.evento.price) }}</div>
|
||||
<!-- Botão "Gerar cobrança" só aparece em status ativo (agendado/realizado).
|
||||
Pra cancelado/faltou: sessão não aconteceu → cobrança nova não cabe
|
||||
aqui. Pra registrar multa, usar o dialog de status change. -->
|
||||
<Button v-if="!isSessaoEncerrada" label="Gerar cobrança" icon="pi pi-plus" size="small" class="rounded-full mt-2" :loading="generating || finLoading" @click="onGerarCobranca" />
|
||||
<div v-if="props.evento.price && !isSessaoEncerrada" class="text-xs text-[var(--text-color-secondary)] mt-1">Valor da sessão: {{ fmtBRL(props.evento.price) }}</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Carregando o financial_record ────────────────────────────────── -->
|
||||
|
||||
Reference in New Issue
Block a user