Compare commits
39 Commits
v1.3.30
...
v1.4.4-fix
| Author | SHA1 | Date | |
|---|---|---|---|
| 22cda312cf | |||
| d112ad061e | |||
| be917f8fb7 | |||
| cb48afeb9c | |||
| 2b8ff711ed | |||
| 9a4ccabd1b | |||
| 32728eec37 | |||
| 905ca253d7 | |||
| d89b79a3f8 | |||
| c4dda7e2e5 | |||
| 662f3681a5 | |||
| a56d7188f2 | |||
| 7e1ee6bc04 | |||
| 6a8881d41d | |||
| 3b3eb1a4cc | |||
| c7109b1017 | |||
| f45d1e8170 | |||
| 8ea5ba771a | |||
| 84578fe43d | |||
| 3e94789cb0 | |||
| 292d0b85d9 | |||
| a8edab029d | |||
| cbaef8772d | |||
| 80740afbf0 | |||
| 7134c85bb7 | |||
| 4a157d27cb | |||
| a0f2f91131 | |||
| 15f141c191 | |||
| 96a84ec194 | |||
| 7d0c416248 | |||
| 60ec60bf29 | |||
| 6d9e28a6f2 | |||
| ecb9ce3926 | |||
| de5d5aaafb | |||
| a11db54ffc | |||
| 674caf2b7a | |||
| bdfd54e0cf | |||
| 9c64c06ed9 | |||
| 3cf1864af9 |
@@ -97,6 +97,7 @@ fn main() {
|
||||
plugins::supabase::sb_listar_recentes,
|
||||
plugins::supabase::sb_buscar_por_id,
|
||||
plugins::supabase::sb_buscar_por_uuid,
|
||||
plugins::supabase::sb_buscar_por_id_fechamento,
|
||||
plugins::supabase::sb_atualizar_fechamento,
|
||||
plugins::supabase::sb_salvar_listas,
|
||||
plugins::supabase::sb_carregar_listas,
|
||||
|
||||
@@ -140,6 +140,7 @@ impl SupabaseClient {
|
||||
"observacoes": estado.get("observacoes").and_then(|v| v.as_str()).unwrap_or(""),
|
||||
"clientes": estado.get("clientes").and_then(|v| v.as_i64()).unwrap_or(0),
|
||||
"frango": estado.get("frango").and_then(|v| v.as_i64()).unwrap_or(0),
|
||||
"vendas": estado.get("vendas").and_then(|v| v.as_f64()).unwrap_or(0.0),
|
||||
});
|
||||
|
||||
// Primeiro tenta INSERT (upsert via Prefer)
|
||||
@@ -193,10 +194,10 @@ impl SupabaseClient {
|
||||
}
|
||||
}
|
||||
|
||||
/// Busca um fechamento pelo UUID.
|
||||
/// Busca um fechamento pelo campo "id" (UUID externo).
|
||||
pub fn buscar_por_uuid(&self, uuid: &str) -> Result<Option<Value>, SupabaseError> {
|
||||
let url = format!(
|
||||
"{}/rest/v1/fechamentos_web?uuid=eq.{}&select=*",
|
||||
"{}/rest/v1/fechamentos_web?id=eq.{}&select=*",
|
||||
self.base_url, uuid
|
||||
);
|
||||
|
||||
@@ -220,22 +221,22 @@ impl SupabaseClient {
|
||||
}
|
||||
}
|
||||
|
||||
/// Atualiza campos específicos de um fechamento pelo UUID (PATCH).
|
||||
pub fn atualizar_fechamento(&self, uuid: &str, updates: &serde_json::Value) -> Result<Value, SupabaseError> {
|
||||
/// Busca um fechamento pelo id_fechamento (ex: uniao_2026-06-24_silanea).
|
||||
pub fn buscar_por_id_fechamento(&self, id_fechamento: &str) -> Result<Option<Value>, SupabaseError> {
|
||||
let url = format!(
|
||||
"{}/rest/v1/fechamentos_web?uuid=eq.{}",
|
||||
self.base_url, uuid
|
||||
"{}/rest/v1/fechamentos_web?id_fechamento=eq.{}&select=*",
|
||||
self.base_url, urlencoding::encode(id_fechamento)
|
||||
);
|
||||
|
||||
let resp = self
|
||||
.http
|
||||
.patch(&url)
|
||||
.headers(self.headers(true))
|
||||
.json(updates)
|
||||
.get(&url)
|
||||
.headers(self.headers(false))
|
||||
.send()?;
|
||||
|
||||
if resp.status().is_success() {
|
||||
Ok(serde_json::json!({ "ok": true, "uuid": uuid }))
|
||||
let arr: Vec<Value> = resp.json()?;
|
||||
Ok(arr.into_iter().next())
|
||||
} else {
|
||||
let status = resp.status();
|
||||
let body = resp.text().unwrap_or_default();
|
||||
@@ -246,11 +247,59 @@ impl SupabaseClient {
|
||||
)))
|
||||
}
|
||||
}
|
||||
pub fn listar_recentes(&self, loja: &str, limite: i64) -> Result<Vec<Value>, SupabaseError> {
|
||||
|
||||
/// 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> {
|
||||
// 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.
|
||||
let map = updates.as_object().cloned().unwrap_or_default();
|
||||
|
||||
if map.is_empty() {
|
||||
return Err(SupabaseError::Api("Nenhum campo para atualizar".into()));
|
||||
}
|
||||
|
||||
let url = format!(
|
||||
"{}/rest/v1/fechamentos_web?loja=eq.{}&order=data.desc,atualizado_em.desc&limit={}&select=id,uuid,data,operador,turno,saldo_troco,saldo_esperado,fechamento,sync_status,observacoes,atualizado_em",
|
||||
"{}/rest/v1/fechamentos_web?id_fechamento=eq.{}",
|
||||
self.base_url,
|
||||
urlencoding::encode(loja),
|
||||
urlencoding::encode(id_fechamento)
|
||||
);
|
||||
|
||||
log::info!("[PATCH] url={} body={:#?}", url, map);
|
||||
|
||||
let resp = self
|
||||
.http
|
||||
.patch(&url)
|
||||
.headers(self.headers(true))
|
||||
.header("Prefer", "return=representation")
|
||||
.json(&map)
|
||||
.send()?;
|
||||
|
||||
let status = resp.status();
|
||||
if status.is_success() {
|
||||
// Ler a resposta real do Supabase (retorna o registro atualizado)
|
||||
if let Ok(ret) = resp.json::<serde_json::Value>() {
|
||||
log::info!("[PATCH] sucesso — resposta: {}", ret);
|
||||
} else {
|
||||
log::warn!("[PATCH] sucesso mas não conseguiu ler resposta");
|
||||
}
|
||||
Ok(serde_json::json!({ "ok": true, "id_fechamento": id_fechamento }))
|
||||
} else {
|
||||
let body = resp.text().unwrap_or_default();
|
||||
log::error!("[PATCH] HTTP {} body: {}", status.as_u16(), body);
|
||||
Err(SupabaseError::Api(format!(
|
||||
"HTTP {}: {}",
|
||||
status.as_u16(),
|
||||
body
|
||||
)))
|
||||
}
|
||||
}
|
||||
pub fn listar_recentes(&self, loja: &str, limite: i64) -> Result<Vec<Value>, SupabaseError> {
|
||||
let loja_normalized = sem_acento(&loja.to_lowercase());
|
||||
let url = format!(
|
||||
"{}/rest/v1/fechamentos_web?loja=eq.{}&order=data.desc,atualizado_em.desc&limit={}&select=id,id_fechamento,data,operador,turno,saldo_troco,saldo_esperado,fechamento_dinheiro,fechamento_cartoes,fechamento_areceber,diferenca,status_diferenca,observacoes,atualizado_em,dados",
|
||||
self.base_url,
|
||||
urlencoding::encode(&loja_normalized),
|
||||
limite,
|
||||
);
|
||||
|
||||
@@ -366,6 +415,48 @@ impl SupabaseClient {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tenta forçar PostgREST a recarregar schema com novas colunas (vendas, edited_at, edited_by).
|
||||
/// Estratégia: INSERT com novas colunas → se PGRST204, espera 1.5s → retry.
|
||||
/// Fire-and-forget — falha não bloqueia.
|
||||
pub fn run_migration(&self) {
|
||||
let payload = serde_json::json!({
|
||||
"id_fechamento": "_mig_probe_1900",
|
||||
"loja": "_probe_",
|
||||
"data": "1900-01-01",
|
||||
"operador": "_probe_",
|
||||
"vendas": 0,
|
||||
"edited_at": null,
|
||||
"edited_by": null
|
||||
});
|
||||
let r1 = self.http
|
||||
.post(&format!("{}/rest/v1/fechamentos_web", self.base_url))
|
||||
.headers(self.headers(true))
|
||||
.header("Prefer", "resolution=merge-duplicates")
|
||||
.json(&payload)
|
||||
.send();
|
||||
if let Ok(resp) = r1 {
|
||||
if resp.status().as_u16() == 400 {
|
||||
std::thread::sleep(std::time::Duration::from_millis(1500));
|
||||
let _ = self.http
|
||||
.post(&format!("{}/rest/v1/fechamentos_web", self.base_url))
|
||||
.headers(self.headers(true))
|
||||
.header("Prefer", "resolution=merge-duplicates")
|
||||
.json(&serde_json::json!({
|
||||
"id_fechamento": "_mig_probe_1900",
|
||||
"vendas": 0,
|
||||
"edited_at": null,
|
||||
"edited_by": null
|
||||
}))
|
||||
.send();
|
||||
}
|
||||
}
|
||||
// Limpa probe
|
||||
let _ = self.http
|
||||
.delete(&format!("{}/rest/v1/fechamentos_web?id_fechamento=eq._mig_probe_1900", self.base_url))
|
||||
.headers(self.headers(true))
|
||||
.send();
|
||||
}
|
||||
|
||||
/// Verifica se está online.
|
||||
pub fn health_check(&self) -> bool {
|
||||
let url = format!("{}/rest/v1/?limit=0", self.base_url);
|
||||
@@ -422,13 +513,22 @@ pub fn sb_buscar_por_uuid(
|
||||
sb.buscar_por_uuid(&uuid)
|
||||
}
|
||||
|
||||
/// Busca um fechamento pelo id_fechamento (ex: uniao_2026-06-24_silanea).
|
||||
#[tauri::command]
|
||||
pub fn sb_buscar_por_id_fechamento(
|
||||
sb: State<'_, SupabaseClient>,
|
||||
id_fechamento: String,
|
||||
) -> Result<Option<serde_json::Value>, SupabaseError> {
|
||||
sb.buscar_por_id_fechamento(&id_fechamento)
|
||||
}
|
||||
|
||||
#[tauri::command(rename_all = "snake_case")]
|
||||
pub fn sb_atualizar_fechamento(
|
||||
sb: State<'_, SupabaseClient>,
|
||||
uuid: String,
|
||||
id_fechamento: String,
|
||||
updates: serde_json::Value,
|
||||
) -> Result<serde_json::Value, SupabaseError> {
|
||||
sb.atualizar_fechamento(&uuid, &updates)
|
||||
sb.atualizar_fechamento(&id_fechamento, &updates)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
|
||||
+1193
-148
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user