diff --git a/src-tauri/src/plugins/supabase.rs b/src-tauri/src/plugins/supabase.rs index 4441fdc..e08679a 100644 --- a/src-tauri/src/plugins/supabase.rs +++ b/src-tauri/src/plugins/supabase.rs @@ -250,12 +250,27 @@ impl SupabaseClient { /// Atualiza campos específicos de um fechamento pelo id_fechamento. pub fn atualizar_fechamento(&self, id_fechamento: &str, updates: &serde_json::Value) -> Result { - // Sem whitelist — o frontend envia só o que o usuário editou. - // O Supabase/Postgres valida as colunas existentes. - // edited_at é atualizado pelo frontend no objeto updates. + // Campos que o frontend envia mas NÃO existem como colunas na tabela. + // Arrays e objetos são guardados no JSONB `dados` — não em colunas escalar. + static BLOCKED: &[&str] = &[ + "id", "uuid", "criado_em", "atualizado_em", "enviado_por", + "ip_origem", "user_agent", "id_fechamento", + // arrays e objetos que existem dentro do JSONB `dados` + "vales", "despesas", "sangrias", "cancelamentos", + "pixcnpj", "receber", + "cartoes_credito", "cartoes_debito", + "cartoes_alimentacao", "cartoes_pix", + ]; + let map = updates.as_object().cloned().unwrap_or_default(); - if map.is_empty() { + // Remove campos bloqueados + let filtered: serde_json::Map = map + .into_iter() + .filter(|(k, _)| !BLOCKED.contains(&k.as_str())) + .collect(); + + if filtered.is_empty() { return Err(SupabaseError::Api("Nenhum campo para atualizar".into())); } @@ -265,14 +280,14 @@ impl SupabaseClient { urlencoding::encode(id_fechamento) ); - log::info!("[PATCH] url={} body={:#?}", url, map); + log::info!("[PATCH] url={} body={:#?}", url, filtered); let resp = self .http .patch(&url) .headers(self.headers(true)) .header("Prefer", "return=representation") - .json(&map) + .json(&filtered) .send()?; let status = resp.status();