fbfb95648e
Modulo 4 da Fase 1. 9 arquivos novos em features/financeiro/: 4 services (_tenantGuards, financialSelects, financialRecords Repository, financialExceptionsRepository, billingContractsRepository) + 4 composables (useFinancialRecords, useFinancialExceptions, useBillingContracts, useBillingOrchestrator). Old composables ainda em paralelo — Fase C (cutover) bloqueada pelas decisoes #2/#3/#6 de billing (memoria agenda_billing_decisoes). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
91 lines
2.6 KiB
JavaScript
91 lines
2.6 KiB
JavaScript
/*
|
|
|--------------------------------------------------------------------------
|
|
| Agência PSI
|
|
|--------------------------------------------------------------------------
|
|
| Arquivo: src/features/financeiro/composables/useFinancialExceptions.js
|
|
|
|
|
| Cache de regras de exceção financeira POR INSTÂNCIA do composable.
|
|
| Substitui o _exceptionsCache módulo-level do useAgendaFinanceiro.js
|
|
| (que vazava entre instâncias — audit baseline alta).
|
|
|
|
|
| Cache TTL: vive enquanto o composable existir. Chamar invalidate()
|
|
| ao trocar tenant.
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
import { ref } from 'vue';
|
|
import {
|
|
getRule,
|
|
listAll,
|
|
upsertRule,
|
|
calcChargeAmount
|
|
} from '@/features/financeiro/services/financialExceptionsRepository';
|
|
|
|
export function useFinancialExceptions() {
|
|
const rules = ref([]);
|
|
const loading = ref(false);
|
|
const error = ref('');
|
|
|
|
// Cache local — chave: `${tenantId}:${exceptionType}`
|
|
const _cache = new Map();
|
|
|
|
async function getRuleCached(exceptionType, { tenantId } = {}) {
|
|
const key = `${tenantId || 'active'}:${exceptionType}`;
|
|
if (_cache.has(key)) return _cache.get(key);
|
|
try {
|
|
const rule = await getRule(exceptionType, { tenantId });
|
|
_cache.set(key, rule);
|
|
return rule;
|
|
} catch (e) {
|
|
error.value = e?.message || 'Falha ao carregar regra de exceção.';
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function loadAll(opts = {}) {
|
|
loading.value = true;
|
|
error.value = '';
|
|
try {
|
|
rules.value = await listAll(opts);
|
|
} catch (e) {
|
|
error.value = e?.message || 'Falha ao carregar regras.';
|
|
rules.value = [];
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
async function upsert(payload) {
|
|
loading.value = true;
|
|
error.value = '';
|
|
try {
|
|
const updated = await upsertRule(payload);
|
|
const idx = rules.value.findIndex((r) => r.id === updated.id);
|
|
if (idx >= 0) rules.value[idx] = updated;
|
|
else rules.value = [...rules.value, updated];
|
|
invalidate();
|
|
return updated;
|
|
} catch (e) {
|
|
error.value = e?.message || 'Falha ao salvar regra.';
|
|
throw e;
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
function invalidate() {
|
|
_cache.clear();
|
|
}
|
|
|
|
return {
|
|
rules,
|
|
loading,
|
|
error,
|
|
getRuleCached,
|
|
loadAll,
|
|
upsert,
|
|
invalidate,
|
|
// re-export utilitário (puro, não state)
|
|
calcChargeAmount
|
|
};
|
|
}
|