MelissaPaciente: fix openWhatsapp + dialog inline novo lancamento financeiro
DOIS BUGS DE COMPORTAMENTO:
1. openWhatsapp nao abria o drawer
conversationDrawerStore.openForPatient(patientId) espera STRING id,
nao objeto. Eu passava { id, name, phone, avatar_url } — store
ignorava e drawer nunca abria.
FIX: passar String(props.patientId) (mesmo pattern que MelissaPacientes).
BONUS: a store seta this.error sem dar throw quando paciente nao tem
telefone cadastrado. Detectamos com `if (err && !isOpen)` e mostramos
toast warn com a mensagem da store ("Paciente sem telefone cadastrado").
Funcao virou async pra aguardar o openForPatient.
2. addFinancial era placeholder "Em breve"
User correto: o sistema ja tem suporte (composables/useFinancialRecords
tem createManualRecord). Implementado dialog inline simples no
prontuario.
NOVO em src/features/patients/composables/usePatientFinancial.js
- createRecord(patientId, payload) — INSERT financial_records com
type='receita', resolve owner_id (auth.getUser) e tenant_id (lazy
import tenantStore pra evitar circular). Auto-reload via _lastPatientId.
Retorna {ok, data?, error?}.
NOVO em MelissaPaciente.vue
- Refs novoLancOpen + novoLancForm (description/amount/due_date/payment_method)
- PAYMENT_METHODS array (Pix/Cartao/Dinheiro/Transferencia/Boleto/Convenio)
- addFinancial() agora abre o dialog (era toast "em breve")
- salvarLancamento() handler com validacao (valor > 0, due_date obrigatorio)
- <Dialog> v-model:visible 420px com form: descricao + grid 2-col
(valor InputNumber BRL + vencimento date input) + select forma
- CSS .mpa-novo-lanc + responsive (1-col em <540px)
ESLint: 0 errors.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -138,6 +138,58 @@ export function usePatientFinancial() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cria um novo lancamento manual (type=receita) pro paciente.
|
||||
* Insere com tenant_id + owner_id resolvidos via auth/tenant store.
|
||||
* Auto-reload ao final pra refletir nos KPIs e tabela.
|
||||
*
|
||||
* payload: { description, amount, due_date, payment_method? }
|
||||
* Retorna {ok, data?, error?}.
|
||||
*/
|
||||
async function createRecord(patientId, payload = {}) {
|
||||
if (!patientId || busy.value) return { ok: false, error: 'busy' };
|
||||
if (!payload?.amount || Number.isNaN(Number(payload.amount))) {
|
||||
return { ok: false, error: 'Valor invalido' };
|
||||
}
|
||||
busy.value = true;
|
||||
try {
|
||||
const { data: userData } = await supabase.auth.getUser();
|
||||
const ownerId = userData?.user?.id;
|
||||
// tenant_id: tenta tenantStore lazy import, fallback null (RLS
|
||||
// via owner_id ainda permite insert).
|
||||
let tenantId = null;
|
||||
try {
|
||||
const { useTenantStore } = await import('@/stores/tenantStore');
|
||||
tenantId = useTenantStore().activeTenantId || null;
|
||||
} catch { /* sem tenant store — segue */ }
|
||||
|
||||
const row = {
|
||||
patient_id: patientId,
|
||||
owner_id: ownerId,
|
||||
tenant_id: tenantId,
|
||||
type: 'receita',
|
||||
amount: Number(payload.amount),
|
||||
due_date: payload.due_date || null,
|
||||
description: String(payload.description || '').trim() || null,
|
||||
payment_method: payload.payment_method || null,
|
||||
paid_at: null
|
||||
};
|
||||
|
||||
const { data, error: err } = await supabase
|
||||
.from('financial_records')
|
||||
.insert([row])
|
||||
.select()
|
||||
.single();
|
||||
if (err) throw err;
|
||||
if (_lastPatientId) await load(_lastPatientId);
|
||||
return { ok: true, data };
|
||||
} catch (e) {
|
||||
return { ok: false, error: e?.message || 'Erro ao criar lançamento' };
|
||||
} finally {
|
||||
busy.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverte: remove paid_at (volta pra pendente). Auto-reload.
|
||||
*/
|
||||
@@ -172,6 +224,7 @@ export function usePatientFinancial() {
|
||||
statusFinanceiro,
|
||||
recordsOrdenados,
|
||||
markPaid,
|
||||
markUnpaid
|
||||
markUnpaid,
|
||||
createRecord
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user