/* |-------------------------------------------------------------------------- | Agência PSI |-------------------------------------------------------------------------- | Criado e desenvolvido por Leonardo Nohama | | Tecnologia aplicada à escuta. | Estrutura para o cuidado. | | Arquivo: src/features/agenda/composables/usePatientDiscounts.js | Data: 2026 | Local: São Carlos/SP — Brasil |-------------------------------------------------------------------------- | © 2026 — Todos os direitos reservados |-------------------------------------------------------------------------- */ // CRUD completo sobre a tabela public.patient_discounts. // // Interface pública: // discounts – ref([]) lista de descontos do owner // loading – ref(false) // error – ref('') // // load(ownerId) – carrega todos os registros do owner // save(payload) – cria ou atualiza (id presente = update) // remove(id) – soft-delete (active = false) // loadActive(ownerId, patientId) – desconto ativo vigente para um paciente import { ref } from 'vue'; import { supabase } from '@/lib/supabase/client'; import { tenantDb } from '@/lib/supabase/tenantClient'; export function usePatientDiscounts() { const discounts = ref([]); const loading = ref(false); const error = ref(''); // ── Carregar todos os descontos do owner ───────────────────────────── async function load(ownerId) { if (!ownerId) return; loading.value = true; error.value = ''; try { const { data, error: err } = await tenantDb().from('patient_discounts').select('*').eq('owner_id', ownerId).order('created_at', { ascending: false }); if (err) throw err; discounts.value = data || []; } catch (e) { error.value = e?.message || 'Falha ao carregar descontos.'; discounts.value = []; } finally { loading.value = false; } } // ── Criar ou atualizar um desconto ─────────────────────────────────── // payload deve conter: { owner_id, patient_id, discount_pct, discount_flat, ... } // Se payload.id estiver presente, faz UPDATE; caso contrário, INSERT. async function save(payload) { error.value = ''; try { if (payload.id) { const { id, owner_id, tenant_id, ...fields } = payload; const { error: err } = await tenantDb().from('patient_discounts').update(fields).eq('id', id).eq('owner_id', owner_id); if (err) throw err; } else { // eslint-disable-next-line no-unused-vars const { tenant_id: _dropTenantId, ...insertFields } = payload; const { error: err } = await tenantDb().from('patient_discounts').insert(insertFields); if (err) throw err; } } catch (e) { error.value = e?.message || 'Falha ao salvar desconto.'; throw e; } } // ── Soft-delete: marca active = false ─────────────────────────────── async function remove(id) { error.value = ''; try { const { error: err } = await tenantDb().from('patient_discounts').update({ active: false }).eq('id', id); if (err) throw err; discounts.value = discounts.value.filter((d) => d.id !== id); } catch (e) { error.value = e?.message || 'Falha ao desativar desconto.'; throw e; } } // ── Desconto ativo vigente para um paciente específico ─────────────── // Retorna o primeiro registro que satisfaz: // active = true // active_from IS NULL OR active_from <= now() // active_to IS NULL OR active_to >= now() // Ordenado por created_at DESC (mais recente tem precedência). async function loadActive(ownerId, patientId) { if (!ownerId || !patientId) return null; try { const now = new Date().toISOString(); const { data, error: err } = await tenantDb().from('patient_discounts') .select('*') .eq('owner_id', ownerId) .eq('patient_id', patientId) .eq('active', true) .or(`active_from.is.null,active_from.lte.${now}`) .or(`active_to.is.null,active_to.gte.${now}`) .order('created_at', { ascending: false }) .limit(1) .maybeSingle(); if (err) throw err; return data || null; } catch (e) { console.warn('[usePatientDiscounts] loadActive error:', e?.message); return null; } } return { discounts, loading, error, load, save, remove, loadActive }; }