Compare commits

...

2 Commits

Author SHA1 Message Date
root bf878545b3 fix: denylist移除arrays/objetos — 解决PATCH成功但字段不保存
Build Fechamento de Caixa / build (macos-14, app) (push) Has been cancelled
Build Fechamento de Caixa / build (ubuntu-22.04, deb) (push) Has been cancelled
Build Fechamento de Caixa / build (windows-2022, msi) (push) Has been cancelled
2026-07-01 14:17:38 +00:00
root 22cda312cf fix: remove whitelist do PATCH — Supabase valida colunas; adiciona edited_at/edited_by no payload
Build Fechamento de Caixa / build (macos-14, app) (push) Has been cancelled
Build Fechamento de Caixa / build (ubuntu-22.04, deb) (push) Has been cancelled
Build Fechamento de Caixa / build (windows-2022, msi) (push) Has been cancelled
2026-07-01 13:40:37 +00:00
2 changed files with 19 additions and 21 deletions
+16 -20
View File
@@ -250,32 +250,28 @@ impl SupabaseClient {
/// Atualiza campos específicos de um fechamento pelo id_fechamento. /// Atualiza campos específicos de um fechamento pelo id_fechamento.
pub fn atualizar_fechamento(&self, id_fechamento: &str, updates: &serde_json::Value) -> Result<Value, SupabaseError> { pub fn atualizar_fechamento(&self, id_fechamento: &str, updates: &serde_json::Value) -> Result<Value, SupabaseError> {
// Whitelist: só colunas que existem na tabela fechamentos_web. // Campos que o frontend envia mas NÃO existem como colunas na tabela.
// Campos de lista (vales, despesas, sangrias, etc.) vivem no JSONB `dados` // Arrays e objetos são guardados no JSONB `dados` — não em colunas escalar.
// e são tratados separadamente via salvar_listas / carregar_listas. static BLOCKED: &[&str] = &[
static ALLOWED: &[&str] = &[ "id", "uuid", "criado_em", "atualizado_em", "enviado_por",
"data", "loja", "turno", "operador", "ip_origem", "user_agent", "id_fechamento",
"saldo_troco", "saldo_credito", "saldo_debito", "saldo_alimentacao", // arrays e objetos que existem dentro do JSONB `dados`
"saldo_vales", "saldo_areceber", "vales", "despesas", "sangrias", "cancelamentos",
"total_cartao_credito", "total_cartao_debito", "total_cartao_alimentacao", "pixcnpj", "receber",
"total_cartao_pix", "total_pixcnpj", "cartoes_credito", "cartoes_debito",
"total_sangrias", "total_despesas", "total_vales", "cartoes_alimentacao", "cartoes_pix",
"total_areceber", "total_cancelamentos",
"fechamento_dinheiro", "fechamento_cartoes", "fechamento_areceber",
"clientes", "frango", "vendas", "saldo_esperado",
"observacoes", "edited_at", "edited_by",
]; ];
let filtered: serde_json::Map<String, serde_json::Value> = updates let map = updates.as_object().cloned().unwrap_or_default();
.as_object()
.cloned() // Remove campos bloqueados
.unwrap_or_default() let filtered: serde_json::Map<String, serde_json::Value> = map
.into_iter() .into_iter()
.filter(|(k, _)| ALLOWED.contains(&k.as_str())) .filter(|(k, _)| !BLOCKED.contains(&k.as_str()))
.collect(); .collect();
if filtered.is_empty() { if filtered.is_empty() {
return Err(SupabaseError::Api("Nenhum campo válido para atualizar".into())); return Err(SupabaseError::Api("Nenhum campo para atualizar".into()));
} }
let url = format!( let url = format!(
+3 -1
View File
@@ -3113,7 +3113,9 @@ window.salvarEdicaoConsulta = async function() {
frango: parseInt(inp('edit-frango') || '0'), frango: parseInt(inp('edit-frango') || '0'),
vendas: p(inp('edit-vendas')), vendas: p(inp('edit-vendas')),
saldo_esperado: p(inp('edit-esperado')), saldo_esperado: p(inp('edit-esperado')),
observacoes: inp('edit-obs') observacoes: inp('edit-obs'),
edited_at: new Date().toISOString(),
edited_by: full.operador || '',
}; };
const hasTauri = !!(window.__TAURI__ && window.__TAURI__.core); const hasTauri = !!(window.__TAURI__ && window.__TAURI__.core);