/* |-------------------------------------------------------------------------- | Agência PSI |-------------------------------------------------------------------------- | Criado e desenvolvido por Leonardo Nohama | | Tecnologia aplicada à escuta. | Estrutura para o cuidado. | | Arquivo: src/features/agenda/composables/useFinancialExceptions.js | Data: 2026 | Local: São Carlos/SP — Brasil |-------------------------------------------------------------------------- | © 2026 — Todos os direitos reservados |-------------------------------------------------------------------------- */ // CRUD sobre a tabela public.financial_exceptions. // // Interface pública: // exceptions – ref([]) lista de regras do owner (próprias + da clínica) // loading – ref(false) // error – ref('') // // load(ownerId) – carrega registros do owner + regras globais (owner_id IS NULL) // save(payload) – cria ou atualiza (id presente = update dos campos editáveis) // remove(id) – hard delete (apenas registros do próprio owner) import { ref } from 'vue'; import { supabase } from '@/lib/supabase/client'; import { tenantDb } from '@/lib/supabase/tenantClient'; export function useFinancialExceptions() { const exceptions = ref([]); const loading = ref(false); const error = ref(''); // ── Carregar exceções do owner + regras globais da clínica ─────────── async function load(ownerId) { if (!ownerId) return; loading.value = true; error.value = ''; try { const { data, error: err } = await tenantDb().from('financial_exceptions').select('*').or(`owner_id.eq.${ownerId},owner_id.is.null`).order('exception_type', { ascending: true }).order('created_at', { ascending: true }); if (err) throw err; exceptions.value = data || []; } catch (e) { error.value = e?.message || 'Falha ao carregar exceções financeiras.'; exceptions.value = []; } finally { loading.value = false; } } // ── Criar ou atualizar uma exceção ─────────────────────────────────── // Para UPDATE, apenas os campos editáveis são enviados: // charge_mode, charge_value, charge_pct, min_hours_notice // Regras globais (owner_id IS NULL) não devem ser editadas — o chamador // é responsável por não chamar save() nesses registros. async function save(payload) { error.value = ''; try { if (payload.id) { const { error: err } = await tenantDb().from('financial_exceptions') .update({ charge_mode: payload.charge_mode, charge_value: payload.charge_value ?? null, charge_pct: payload.charge_pct ?? null, min_hours_notice: payload.min_hours_notice ?? null, default_consume_on_miss: !!payload.default_consume_on_miss }) .eq('id', payload.id); if (err) throw err; } else { const { error: err } = await tenantDb().from('financial_exceptions').insert({ owner_id: payload.owner_id, exception_type: payload.exception_type, charge_mode: payload.charge_mode, charge_value: payload.charge_value ?? null, charge_pct: payload.charge_pct ?? null, min_hours_notice: payload.min_hours_notice ?? null, default_consume_on_miss: !!payload.default_consume_on_miss }); if (err) throw err; } } catch (e) { error.value = e?.message || 'Falha ao salvar exceção financeira.'; throw e; } } // ── Hard delete — apenas registros do próprio owner ────────────────── // Regras globais (owner_id IS NULL) são protegidas pelo RLS do banco; // a UI também deve esconder o botão de remover nesses casos. async function remove(id) { error.value = ''; try { const { error: err } = await tenantDb().from('financial_exceptions').delete().eq('id', id); if (err) throw err; exceptions.value = exceptions.value.filter((e) => e.id !== id); } catch (e) { error.value = e?.message || 'Falha ao remover exceção financeira.'; throw e; } } return { exceptions, loading, error, load, save, remove }; }