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.
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 de lista (vales, despesas, sangrias, etc.) vivem no JSONB `dados`
// e são tratados separadamente via salvar_listas / carregar_listas.
static ALLOWED: &[&str] = &[
"data", "loja", "turno", "operador",
"saldo_troco", "saldo_credito", "saldo_debito", "saldo_alimentacao",
"saldo_vales", "saldo_areceber",
"total_cartao_credito", "total_cartao_debito", "total_cartao_alimentacao",
"total_cartao_pix", "total_pixcnpj",
"total_sangrias", "total_despesas", "total_vales",
"total_areceber", "total_cancelamentos",
"fechamento_dinheiro", "fechamento_cartoes", "fechamento_areceber",
"clientes", "frango", "vendas", "saldo_esperado",
"observacoes", "edited_at", "edited_by",
// 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 filtered: serde_json::Map<String, serde_json::Value> = updates
.as_object()
.cloned()
.unwrap_or_default()
let map = updates.as_object().cloned().unwrap_or_default();
// Remove campos bloqueados
let filtered: serde_json::Map<String, serde_json::Value> = map
.into_iter()
.filter(|(k, _)| ALLOWED.contains(&k.as_str()))
.filter(|(k, _)| !BLOCKED.contains(&k.as_str()))
.collect();
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!(
+3 -1
View File
@@ -3113,7 +3113,9 @@ window.salvarEdicaoConsulta = async function() {
frango: parseInt(inp('edit-frango') || '0'),
vendas: p(inp('edit-vendas')),
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);