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:
Leonardo
2026-05-20 09:59:05 -03:00
parent 3caf5792f8
commit 753182cfad
6 changed files with 207 additions and 10 deletions
@@ -182,6 +182,26 @@ function _calcInitialFineApply() {
return true;
}
// Texto explicativo de porquê a multa veio (des)marcada por padrão.
// Aparece abaixo do checkbox no bloco multa pra deixar a regra visível
// ao terapeuta no momento da decisão.
const fineDefaultReason = computed(() => {
const r = props.regraExcecao;
if (!r || r.charge_mode === 'none') return '';
if (props.novoStatus !== 'cancelado' || r.min_hours_notice == null || !props.evento?.inicio_em) return '';
const horasAteSessao = (new Date(props.evento.inicio_em).getTime() - Date.now()) / (1000 * 60 * 60);
const min = Number(r.min_hours_notice);
const horasFmt = horasAteSessao < 0
? `${Math.abs(horasAteSessao).toFixed(1)}h após o início`
: horasAteSessao < 1
? `${Math.round(horasAteSessao * 60)}min antes`
: `${horasAteSessao.toFixed(1)}h antes`;
if (horasAteSessao >= min) {
return `Cancelou ${horasFmt} da sessão. Regra: multa apenas quando cancelamento ocorre com menos de ${min}h de antecedência → sem multa por padrão.`;
}
return `Cancelou ${horasFmt} da sessão (menos que os ${min}h da regra) → multa aplicada por padrão.`;
});
// ─── Actions ───────────────────────────────────────────────────────────
function onConfirm() {
emit('confirm', {
@@ -264,6 +284,9 @@ function onCancel() {
class="asccd-fine-input"
/>
</div>
<small v-if="fineDefaultReason" class="asccd-hint">
<i class="pi pi-info-circle" /> {{ fineDefaultReason }}
</small>
<small v-if="isPacoteUpfront" class="asccd-hint">
Pacote pago; multa entra como cobrança adicional avulsa.
</small>