F1b: 6 tabelas anon-facing ficam em public (decisao roteamento anon)
Fluxos anon identificam tenant por token/slug e nao resolvem o schema fisico. Decisao (opcao C): manter em public com RLS por token. Volta a global: patient_intake_requests, patient_invites, patient_invite_attempts, document_share_links, agendador_configuracoes, agendador_solicitacoes. - migration 20260613000001_f1b: remove as 6 do _tenant_template (template v2, 78 tabelas). Smoke: clone gera 78, zero tabelas anon no schema, drop limpo - frontend: 38 cadeias em 14 arquivos revertidas tenantDb().from() -> supabase.from() com tenant_id/owner_id restaurado (via comparacao com main) - edge: convert-abandoned-intakes restaurada do main (SELECT global) - save-intake-progress: ja usava public, sem mudanca - doc F0 atualizado: 78 tenant + 59 global Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -79,7 +79,7 @@ async function onFileSelected(event, field) {
|
||||
// Persiste imediatamente no banco sem fechar o accordion
|
||||
const uid = ownerId.value;
|
||||
const tenantId = await getActiveTenantId(uid);
|
||||
await tenantDb().from('agendador_configuracoes').upsert({ owner_id: uid, ...buildPayload('identidade'), updated_at: new Date().toISOString() }, { onConflict: 'owner_id' });
|
||||
await supabase.from('agendador_configuracoes').upsert({ owner_id: uid, tenant_id: tenantId, ...buildPayload('identidade'), updated_at: new Date().toISOString() }, { onConflict: 'owner_id' });
|
||||
toast.add({ severity: 'success', summary: 'Imagem salva', life: 2000 });
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -361,7 +361,7 @@ async function load() {
|
||||
const uid = await getOwnerId();
|
||||
ownerId.value = uid;
|
||||
|
||||
const [{ data, error }] = await Promise.all([tenantDb().from('agendador_configuracoes').select('*').eq('owner_id', uid).maybeSingle(), loadPaymentSettings(uid)]);
|
||||
const [{ data, error }] = await Promise.all([supabase.from('agendador_configuracoes').select('*').eq('owner_id', uid).maybeSingle(), loadPaymentSettings(uid)]);
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
@@ -400,7 +400,7 @@ async function toggleAtivo() {
|
||||
try {
|
||||
const tenantId = await getActiveTenantId(uid);
|
||||
|
||||
await tenantDb().from('agendador_configuracoes').upsert({ owner_id: uid, ativo: novoAtivo, updated_at: new Date().toISOString() }, { onConflict: 'owner_id' });
|
||||
await supabase.from('agendador_configuracoes').upsert({ owner_id: uid, tenant_id: tenantId, ativo: novoAtivo, updated_at: new Date().toISOString() }, { onConflict: 'owner_id' });
|
||||
|
||||
toast.add({
|
||||
severity: novoAtivo ? 'success' : 'info',
|
||||
@@ -422,7 +422,7 @@ async function saveCard(cardKey) {
|
||||
const tenantId = await getActiveTenantId(uid);
|
||||
const payload = buildPayload(cardKey);
|
||||
|
||||
await tenantDb().from('agendador_configuracoes').upsert({ owner_id: uid, ...payload, updated_at: new Date().toISOString() }, { onConflict: 'owner_id' });
|
||||
await supabase.from('agendador_configuracoes').upsert({ owner_id: uid, tenant_id: tenantId, ...payload, updated_at: new Date().toISOString() }, { onConflict: 'owner_id' });
|
||||
|
||||
toast.add({ severity: 'success', summary: 'Salvo', life: 2500 });
|
||||
expandedCard.value = new Set();
|
||||
|
||||
@@ -343,7 +343,7 @@ async function load() {
|
||||
ownerId.value = uid;
|
||||
|
||||
const [{ data, error }] = await Promise.all([
|
||||
tenantDb().from('agendador_configuracoes').select('*').eq('owner_id', uid).maybeSingle(),
|
||||
supabase.from('agendador_configuracoes').select('*').eq('owner_id', uid).maybeSingle(),
|
||||
loadPaymentSettings(uid)
|
||||
]);
|
||||
if (error) throw error;
|
||||
@@ -382,9 +382,10 @@ async function toggleAtivo() {
|
||||
cfg.value.ativo = novoAtivo;
|
||||
try {
|
||||
const tenantId = await getActiveTenantId(uid);
|
||||
const { error } = await tenantDb().from('agendador_configuracoes')
|
||||
const { error } = await supabase
|
||||
.from('agendador_configuracoes')
|
||||
.upsert(
|
||||
{ owner_id: uid, ativo: novoAtivo, updated_at: new Date().toISOString() },
|
||||
{ owner_id: uid, tenant_id: tenantId, ativo: novoAtivo, updated_at: new Date().toISOString() },
|
||||
{ onConflict: 'owner_id' }
|
||||
);
|
||||
if (error) throw error;
|
||||
@@ -473,9 +474,10 @@ async function saveCard(cardKey) {
|
||||
const uid = ownerId.value;
|
||||
const tenantId = await getActiveTenantId(uid);
|
||||
const payload = buildPayload(cardKey);
|
||||
const { error } = await tenantDb().from('agendador_configuracoes')
|
||||
const { error } = await supabase
|
||||
.from('agendador_configuracoes')
|
||||
.upsert(
|
||||
{ owner_id: uid, ...payload, updated_at: new Date().toISOString() },
|
||||
{ owner_id: uid, tenant_id: tenantId, ...payload, updated_at: new Date().toISOString() },
|
||||
{ onConflict: 'owner_id' }
|
||||
);
|
||||
if (error) throw error;
|
||||
@@ -516,9 +518,10 @@ async function onFileSelected(event, field) {
|
||||
if (field === 'fundo') cfg.value.imagem_fundo_url = url;
|
||||
const uid = ownerId.value;
|
||||
const tenantId = await getActiveTenantId(uid);
|
||||
await tenantDb().from('agendador_configuracoes')
|
||||
await supabase
|
||||
.from('agendador_configuracoes')
|
||||
.upsert(
|
||||
{ owner_id: uid, ...buildPayload('identidade'), updated_at: new Date().toISOString() },
|
||||
{ owner_id: uid, tenant_id: tenantId, ...buildPayload('identidade'), updated_at: new Date().toISOString() },
|
||||
{ onConflict: 'owner_id' }
|
||||
);
|
||||
toast.add({ severity: 'success', summary: 'Imagem salva', life: 2000 });
|
||||
|
||||
@@ -222,12 +222,14 @@ async function fetchSolicitacoes() {
|
||||
if (!ownerId.value) return;
|
||||
loading.value = true;
|
||||
try {
|
||||
let q = tenantDb().from('agendador_solicitacoes')
|
||||
.select('id, owner_id, paciente_nome, paciente_sobrenome, paciente_email, paciente_celular, paciente_cpf, tipo, modalidade, data_solicitada, hora_solicitada, reservado_ate, motivo, como_conheceu, status, recusado_motivo, autorizado_em, created_at')
|
||||
let q = supabase
|
||||
.from('agendador_solicitacoes')
|
||||
.select('id, owner_id, tenant_id, paciente_nome, paciente_sobrenome, paciente_email, paciente_celular, paciente_cpf, tipo, modalidade, data_solicitada, hora_solicitada, reservado_ate, motivo, como_conheceu, status, recusado_motivo, autorizado_em, created_at')
|
||||
.order('data_solicitada', { ascending: false })
|
||||
.order('hora_solicitada', { ascending: true });
|
||||
|
||||
if (!isClinic.value) q = q.eq('owner_id', ownerId.value);
|
||||
if (isClinic.value) q = q.eq('tenant_id', tenantId.value);
|
||||
else q = q.eq('owner_id', ownerId.value);
|
||||
|
||||
const { data, error } = await q;
|
||||
if (error) throw error;
|
||||
@@ -293,7 +295,8 @@ async function autorizar() {
|
||||
if (!item) return;
|
||||
dlg.value.saving = true;
|
||||
try {
|
||||
const { error } = await tenantDb().from('agendador_solicitacoes')
|
||||
const { error } = await supabase
|
||||
.from('agendador_solicitacoes')
|
||||
.update({ status: 'autorizado', autorizado_em: new Date().toISOString() })
|
||||
.eq('id', item.id);
|
||||
if (error) throw error;
|
||||
@@ -323,7 +326,8 @@ async function recusar() {
|
||||
dlg.value.saving = true;
|
||||
try {
|
||||
const motivo = String(dlg.value.recusa_note || '').trim() || null;
|
||||
const { error } = await tenantDb().from('agendador_solicitacoes')
|
||||
const { error } = await supabase
|
||||
.from('agendador_solicitacoes')
|
||||
.update({ status: 'recusado', recusado_motivo: motivo })
|
||||
.eq('id', item.id);
|
||||
if (error) throw error;
|
||||
@@ -442,7 +446,8 @@ async function onEventSaved(arg) {
|
||||
const dbPayload = {};
|
||||
for (const k of dbFields) if (normalized[k] !== undefined) dbPayload[k] = normalized[k];
|
||||
await createEvento(dbPayload);
|
||||
const { error } = await tenantDb().from('agendador_solicitacoes')
|
||||
const { error } = await supabase
|
||||
.from('agendador_solicitacoes')
|
||||
.update({ status: 'convertido' })
|
||||
.eq('id', target.id);
|
||||
if (error) throw error;
|
||||
|
||||
@@ -16,7 +16,6 @@ import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
import { useConfirm } from 'primevue/useconfirm';
|
||||
import { supabase } from '@/lib/supabase/client';
|
||||
import { tenantDb } from '@/lib/supabase/tenantClient';
|
||||
import { useTenantStore } from '@/stores/tenantStore';
|
||||
// Fase 2 (Graphify hotspot): convertToPatient duplicado em 2 pages — extração pro repository.
|
||||
import { createPatient, markIntakeConverted } from '@/features/patients/services/patientsRepository';
|
||||
@@ -258,7 +257,8 @@ const pagedItems = computed(() => {
|
||||
async function fetchIntakes() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const { data, error } = await tenantDb().from('patient_intake_requests').select('*')
|
||||
const { data, error } = await supabase
|
||||
.from('patient_intake_requests').select('*')
|
||||
.order('created_at', { ascending: false });
|
||||
if (error) throw error;
|
||||
const weight = (s) => (s === 'new' ? 0 : s === 'converted' ? 1 : s === 'rejected' ? 2 : 9);
|
||||
@@ -346,7 +346,7 @@ async function markRejected() {
|
||||
dlg.value.saving = true;
|
||||
try {
|
||||
const reason = String(dlg.value.reject_note || '').trim() || null;
|
||||
const { error } = await tenantDb().from('patient_intake_requests')
|
||||
const { error } = await supabase.from('patient_intake_requests')
|
||||
.update({ status: 'rejected', rejected_reason: reason, updated_at: new Date().toISOString() })
|
||||
.eq('id', item.id);
|
||||
if (error) throw error;
|
||||
|
||||
Reference in New Issue
Block a user