From cad8fbca4fb46894754886fbf83288c35b4f2542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Ben=C3=ADtez?= Date: Tue, 7 Jul 2026 13:25:43 -0300 Subject: [PATCH] =?UTF-8?q?Causa=20del=20403:=20Supabase=20eval=C3=BAa=20s?= =?UTF-8?q?iempre=20la=20pol=C3=ADtica=20INSERT=20cuando=20se=20usa=20.ups?= =?UTF-8?q?ert(),=20incluso=20si=20la=20fila=20ya=20existe.=20client=5Fedi?= =?UTF-8?q?tor=20no=20tiene=20INSERT=20en=20processes,=20entonces=20cualqu?= =?UTF-8?q?ier=20.upsert()=20sobre=20procesos=20existentes=20fallaba=20con?= =?UTF-8?q?=20403.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: nuevo método updateEditable() en process-repo.ts que usa .update().eq('id', process.id) con solo los campos editables (sin bpmn_xml, owner_id, created_by, id). Todos los paths de edición en process-store.ts y library-store.ts ahora usan updateEditable(). El .upsert() original queda únicamente para la creación inicial desde ImportPage y setCurrentProcess — rutas que client_editor nunca puede alcanzar (el import está bloqueado por el guard de rol). --- src/persistence/supabase/process-repo.ts | 22 ++++++++++++++++++++++ src/store/library-store.ts | 2 +- src/store/process-store.ts | 12 ++++++------ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/persistence/supabase/process-repo.ts b/src/persistence/supabase/process-repo.ts index a81b91b..9f5b887 100644 --- a/src/persistence/supabase/process-repo.ts +++ b/src/persistence/supabase/process-repo.ts @@ -72,6 +72,28 @@ export const supabaseProcessRepo = { if (error) throw error }, + // Actualiza solo campos editables por el usuario (sin bpmn_xml, owner_id, created_by). + // Usa UPDATE en lugar de upsert para evitar el chequeo de INSERT policy (que client_editor no tiene). + async updateEditable(process: Process, userId: string): Promise { + const { error } = await supabase + .from('processes') + .update({ + name: process.name, + client: process.clientName, + currency: process.currency, + overhead_percentage: process.overheadPercentage, + annual_frequency: process.annualFrequency, + analysis_horizon_years: process.analysisHorizonYears, + automation_investment: process.automationInvestment, + tags: process.tags, + group_id: process.groupId, + updated_by: userId, + updated_at: new Date().toISOString(), + }) + .eq('id', process.id) + if (error) throw error + }, + async getById(id: string): Promise { const { data, error } = await supabase .from('processes') diff --git a/src/store/library-store.ts b/src/store/library-store.ts index 44a3fc9..ee4ea5e 100644 --- a/src/store/library-store.ts +++ b/src/store/library-store.ts @@ -85,7 +85,7 @@ export const useLibraryStore = create((set, get) => ({ const process = get().processes.find((p) => p.id === processId) if (!process) return const updated = { ...process, groupId, updatedAt: Date.now() } - await supabaseProcessRepo.save(updated, userId) + await supabaseProcessRepo.updateEditable(updated, userId) set((state) => ({ processes: state.processes.map((p) => p.id === processId ? updated : p), })) diff --git a/src/store/process-store.ts b/src/store/process-store.ts index 3b6562e..166c297 100644 --- a/src/store/process-store.ts +++ b/src/store/process-store.ts @@ -62,7 +62,7 @@ export const useProcessStore = create((set, get) => ({ const current = get().currentProcess if (!current) return const updated: Process = { ...current, ...updates, updatedAt: Date.now() } - await supabaseProcessRepo.save(updated, userId) + await supabaseProcessRepo.updateEditable(updated, userId) set({ currentProcess: updated }) }, @@ -71,7 +71,7 @@ export const useProcessStore = create((set, get) => ({ const current = get().currentProcess if (current) { const updatedProcess = { ...current, updatedAt: Date.now() } - await supabaseProcessRepo.save(updatedProcess, userId) + await supabaseProcessRepo.updateEditable(updatedProcess, userId) set((state) => ({ activities: state.activities.map((a) => (a.id === activity.id ? activity : a)), currentProcess: updatedProcess, @@ -88,7 +88,7 @@ export const useProcessStore = create((set, get) => ({ const current = get().currentProcess if (current) { const updatedProcess = { ...current, updatedAt: Date.now() } - await supabaseProcessRepo.save(updatedProcess, userId) + await supabaseProcessRepo.updateEditable(updatedProcess, userId) set((state) => ({ gateways: state.gateways.map((g) => (g.id === gateway.id ? gateway : g)), currentProcess: updatedProcess, @@ -105,7 +105,7 @@ export const useProcessStore = create((set, get) => ({ const current = get().currentProcess if (current) { const updatedProcess = { ...current, updatedAt: Date.now() } - await supabaseProcessRepo.save(updatedProcess, userId) + await supabaseProcessRepo.updateEditable(updatedProcess, userId) set((state) => ({ resources: [...state.resources, resource], currentProcess: updatedProcess })) } else { set((state) => ({ resources: [...state.resources, resource] })) @@ -117,7 +117,7 @@ export const useProcessStore = create((set, get) => ({ const current = get().currentProcess if (current) { const updatedProcess = { ...current, updatedAt: Date.now() } - await supabaseProcessRepo.save(updatedProcess, userId) + await supabaseProcessRepo.updateEditable(updatedProcess, userId) set((state) => ({ resources: state.resources.map((r) => (r.id === resource.id ? resource : r)), currentProcess: updatedProcess, @@ -134,7 +134,7 @@ export const useProcessStore = create((set, get) => ({ const current = get().currentProcess if (current) { const updatedProcess = { ...current, updatedAt: Date.now() } - await supabaseProcessRepo.save(updatedProcess, userId) + await supabaseProcessRepo.updateEditable(updatedProcess, userId) set((state) => ({ resources: state.resources.filter((r) => r.id !== resourceId), currentProcess: updatedProcess,