Fix: align frontend commands with backend, fix data model mismatch
- Rename commands: salvar_local→salvar_fechamento, enviar_fechamento→sb_salvar_fechamento, etc. - Fix typo: cartoes.credo→cartoes.credito - storage: accept serde_json::Value instead of FechamentoEstado for flexibility - Add Default derive on FechamentoEstado and SyncStatus - Commands now return simplified JSON for frontend compatibility
This commit is contained in:
@@ -33,7 +33,7 @@ impl serde::Serialize for StorageError {
|
|||||||
|
|
||||||
// ── Tipos ──────────────────────────────────────────────────────────────────
|
// ── Tipos ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||||
pub struct FechamentoEstado {
|
pub struct FechamentoEstado {
|
||||||
pub id: Option<i64>,
|
pub id: Option<i64>,
|
||||||
pub uuid: String,
|
pub uuid: String,
|
||||||
@@ -80,9 +80,10 @@ pub struct CartaoData {
|
|||||||
pub voucher: Vec<TableRow>,
|
pub voucher: Vec<TableRow>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Default)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum SyncStatus {
|
pub enum SyncStatus {
|
||||||
|
#[default]
|
||||||
Local, // só local, não sincronizado
|
Local, // só local, não sincronizado
|
||||||
Syncing, // sync em progresso
|
Syncing, // sync em progresso
|
||||||
Synced, // sincronizado com servidor
|
Synced, // sincronizado com servidor
|
||||||
@@ -365,21 +366,126 @@ impl DbManager {
|
|||||||
|
|
||||||
// ── Tauri Commands ─────────────────────────────────────────────────────────
|
// ── Tauri Commands ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
// ── Tauri Commands ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Salva fechamento com estrutura flexível ( campos simples do frontend JS )
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn salvar_fechamento(
|
pub fn salvar_fechamento(
|
||||||
db: State<'_, DbManager>,
|
db: State<'_, DbManager>,
|
||||||
estado: FechamentoEstado,
|
estado: serde_json::Value,
|
||||||
) -> Result<SalvarResult, StorageError> {
|
) -> Result<SalvarResult, StorageError> {
|
||||||
db.salvar(&estado)
|
// Extrai campos simples do JSON flexível
|
||||||
|
let uuid = estado.get("uuid").and_then(|v| v.as_str()).unwrap_or("").to_string();
|
||||||
|
let loja = estado.get("loja").and_then(|v| v.as_str()).unwrap_or("").to_string();
|
||||||
|
let data = estado.get("data").and_then(|v| v.as_str()).unwrap_or("").to_string();
|
||||||
|
let operador = estado.get("operador").and_then(|v| v.as_str()).unwrap_or("").to_string();
|
||||||
|
let turno = estado.get("turno").and_then(|v| v.as_str()).unwrap_or("").to_string();
|
||||||
|
let saldo_troco = estado.get("saldo_troco").and_then(|v| v.as_f64()).unwrap_or(0.0);
|
||||||
|
let fechamento = estado.get("fechamento").and_then(|v| v.as_f64()).unwrap_or(0.0);
|
||||||
|
let saldo_esperado = saldo_troco + fechamento;
|
||||||
|
let diferenca = estado.get("diferenca").and_then(|v| v.as_f64()).unwrap_or(0.0);
|
||||||
|
|
||||||
|
// Constrói TableData a partir de despesas/receber arrays
|
||||||
|
let despesas: Vec<serde_json::Value> = estado.get("despesas")
|
||||||
|
.and_then(|v| v.as_array())
|
||||||
|
.map(|arr| arr.to_vec())
|
||||||
|
.unwrap_or_default();
|
||||||
|
let receber: Vec<serde_json::Value> = estado.get("receber")
|
||||||
|
.and_then(|v| v.as_array())
|
||||||
|
.map(|arr| arr.to_vec())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let to_table_row = |v: &serde_json::Value| -> TableRow {
|
||||||
|
TableRow {
|
||||||
|
descricao: v.get("desc").and_then(|s| s.as_str()).map(String::from),
|
||||||
|
valor: v.get("valor").and_then(|n| n.as_f64()),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let tabelas = TableData {
|
||||||
|
despesas: despesas.iter().map(to_table_row).collect(),
|
||||||
|
areceber: receber.iter().map(to_table_row).collect(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cartoes como scalars
|
||||||
|
let cartoes_json = estado.get("cartoes");
|
||||||
|
let cartoes = CartaoData {
|
||||||
|
credito: vec![TableRow { valor: cartoes_json.and_then(|c| c.get("credito")).and_then(|v| v.as_f64()), ..Default::default() }],
|
||||||
|
debito: vec![TableRow { valor: cartoes_json.and_then(|c| c.get("debito")).and_then(|v| v.as_f64()), ..Default::default() }],
|
||||||
|
alimentacao: vec![TableRow { valor: cartoes_json.and_then(|c| c.get("alimentacao")).and_then(|v| v.as_f64()), ..Default::default() }],
|
||||||
|
voucher: vec![TableRow { valor: cartoes_json.and_then(|c| c.get("voucher")).and_then(|v| v.as_f64()), ..Default::default() }],
|
||||||
|
};
|
||||||
|
|
||||||
|
let estado_rust = FechamentoEstado {
|
||||||
|
id: estado.get("id_local").and_then(|v| v.as_i64()),
|
||||||
|
uuid,
|
||||||
|
loja,
|
||||||
|
data,
|
||||||
|
operador,
|
||||||
|
turno,
|
||||||
|
saldo_troco,
|
||||||
|
fechamento,
|
||||||
|
saldo_esperado,
|
||||||
|
tabelas,
|
||||||
|
cartoes,
|
||||||
|
sync_status: SyncStatus::Local,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
db.salvar(&estado_rust)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Carrega rascunho e devolve estrutura simples para o frontend
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn carregar_rascunho(
|
pub fn carregar_rascunho(
|
||||||
db: State<'_, DbManager>,
|
db: State<'_, DbManager>,
|
||||||
loja: String,
|
loja: String,
|
||||||
data: String,
|
data: String,
|
||||||
) -> Result<Option<FechamentoEstado>, StorageError> {
|
) -> Result<Option<serde_json::Value>, StorageError> {
|
||||||
db.carregar_rascunho(&loja, &data)
|
match db.carregar_rascunho(&loja, &data)? {
|
||||||
|
Some(e) => {
|
||||||
|
// Simplifica para formato que o frontend espera
|
||||||
|
let total_sangrias: f64 = e.tabelas.sangrias.iter().filter_map(|r| r.valor).sum();
|
||||||
|
let total_despesas: f64 = e.tabelas.despesas.iter().filter_map(|r| r.valor).sum();
|
||||||
|
let total_receber: f64 = e.tabelas.areceber.iter().filter_map(|r| r.valor).sum();
|
||||||
|
let despesa_rows: Vec<_> = e.tabelas.despesas.iter().filter_map(|r| {
|
||||||
|
r.descricao.as_ref().map(|d| serde_json::json!({"desc": d, "valor": r.valor}))
|
||||||
|
}).collect();
|
||||||
|
let receber_rows: Vec<_> = e.tabelas.areceber.iter().filter_map(|r| {
|
||||||
|
r.descricao.as_ref().map(|d| serde_json::json!({"desc": d, "valor": r.valor}))
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
Ok(Some(serde_json::json!({
|
||||||
|
"id_local": e.id,
|
||||||
|
"uuid": e.uuid,
|
||||||
|
"loja": e.loja,
|
||||||
|
"data": e.data,
|
||||||
|
"operador": e.operador,
|
||||||
|
"turno": e.turno,
|
||||||
|
"saldo_troco": e.saldo_troco,
|
||||||
|
"fechamento": e.fechamento,
|
||||||
|
"saldo_esperado": e.saldo_esperado,
|
||||||
|
"diferenca": e.fechamento - e.saldo_esperado,
|
||||||
|
"despesas": despesa_rows,
|
||||||
|
"total_sangrias": total_sangrias,
|
||||||
|
"total_despesas": total_despesas,
|
||||||
|
"vales": 0.0,
|
||||||
|
"cartoes": {
|
||||||
|
"credito": e.cartoes.credito.iter().find_map(|r| r.valor).unwrap_or(0.0),
|
||||||
|
"debito": e.cartoes.debito.iter().find_map(|r| r.valor).unwrap_or(0.0),
|
||||||
|
"alimentacao": e.cartoes.alimentacao.iter().find_map(|r| r.valor).unwrap_or(0.0),
|
||||||
|
"voucher": e.cartoes.voucher.iter().find_map(|r| r.valor).unwrap_or(0.0),
|
||||||
|
"cancelamentos": 0.0,
|
||||||
|
},
|
||||||
|
"receber": receber_rows,
|
||||||
|
"observacoes": "",
|
||||||
|
"sync_status": "local",
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -387,16 +493,53 @@ pub fn listar_fechamentos(
|
|||||||
db: State<'_, DbManager>,
|
db: State<'_, DbManager>,
|
||||||
loja: String,
|
loja: String,
|
||||||
limite: Option<i64>,
|
limite: Option<i64>,
|
||||||
) -> Result<Vec<FechamentoEstado>, StorageError> {
|
) -> Result<Vec<serde_json::Value>, StorageError> {
|
||||||
db.listar(&loja, limite.unwrap_or(50))
|
let rows = db.listar(&loja, limite.unwrap_or(50))?;
|
||||||
|
Ok(rows.into_iter().map(|e| serde_json::json!({
|
||||||
|
"id": e.id,
|
||||||
|
"uuid": e.uuid,
|
||||||
|
"data": e.data,
|
||||||
|
"operador": e.operador,
|
||||||
|
"turno": e.turno,
|
||||||
|
"saldo_esperado": e.saldo_esperado,
|
||||||
|
"sync_status": format!("{:?}", e.sync_status).to_lowercase(),
|
||||||
|
})).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn buscar_fechamento_por_id(
|
pub fn buscar_fechamento_por_id(
|
||||||
db: State<'_, DbManager>,
|
db: State<'_, DbManager>,
|
||||||
id: i64,
|
id: i64,
|
||||||
) -> Result<Option<FechamentoEstado>, StorageError> {
|
) -> Result<Option<serde_json::Value>, StorageError> {
|
||||||
db.buscar_por_id(id)
|
match db.buscar_por_id(id)? {
|
||||||
|
Some(e) => Ok(Some(serde_json::json!({
|
||||||
|
"id_local": e.id,
|
||||||
|
"uuid": e.uuid,
|
||||||
|
"loja": e.loja,
|
||||||
|
"data": e.data,
|
||||||
|
"operador": e.operador,
|
||||||
|
"turno": e.turno,
|
||||||
|
"saldo_troco": e.saldo_troco,
|
||||||
|
"fechamento": e.fechamento,
|
||||||
|
"saldo_esperado": e.saldo_esperado,
|
||||||
|
"diferenca": e.fechamento - e.saldo_esperado,
|
||||||
|
"despesas": e.tabelas.despesas.iter().filter_map(|r| r.descricao.as_ref().map(|d| serde_json::json!({"desc": d, "valor": r.valor}))).collect::<Vec<_>>(),
|
||||||
|
"total_sangrias": e.tabelas.sangrias.iter().filter_map(|r| r.valor).sum::<f64>(),
|
||||||
|
"total_despesas": e.tabelas.despesas.iter().filter_map(|r| r.valor).sum::<f64>(),
|
||||||
|
"vales": 0.0,
|
||||||
|
"cartoes": {
|
||||||
|
"credito": e.cartoes.credito.iter().find_map(|r| r.valor).unwrap_or(0.0),
|
||||||
|
"debito": e.cartoes.debito.iter().find_map(|r| r.valor).unwrap_or(0.0),
|
||||||
|
"alimentacao": e.cartoes.alimentacao.iter().find_map(|r| r.valor).unwrap_or(0.0),
|
||||||
|
"voucher": e.cartoes.voucher.iter().find_map(|r| r.valor).unwrap_or(0.0),
|
||||||
|
"cancelamentos": 0.0,
|
||||||
|
},
|
||||||
|
"receber": e.tabelas.areceber.iter().filter_map(|r| r.descricao.as_ref().map(|d| serde_json::json!({"desc": d, "valor": r.valor}))).collect::<Vec<_>>(),
|
||||||
|
"observacoes": "",
|
||||||
|
"sync_status": format!("{:?}", e.sync_status).to_lowercase(),
|
||||||
|
}))),
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
|||||||
+6
-6
@@ -613,7 +613,7 @@ function calcular() {
|
|||||||
estado.total_despesas = estado.despesas.filter(d => !d.desc.includes('Sangria')).reduce((s,d) => s+d.valor, 0);
|
estado.total_despesas = estado.despesas.filter(d => !d.desc.includes('Sangria')).reduce((s,d) => s+d.valor, 0);
|
||||||
estado.vales = parseFloat(val('f-vales')) || 0;
|
estado.vales = parseFloat(val('f-vales')) || 0;
|
||||||
estado.cartoes = {
|
estado.cartoes = {
|
||||||
credo: parseFloat(val('f-credito')) || 0,
|
credito: parseFloat(val('f-credito')) || 0,
|
||||||
debito: parseFloat(val('f-debito')) || 0,
|
debito: parseFloat(val('f-debito')) || 0,
|
||||||
alimentacao: parseFloat(val('f-alimentacao')) || 0,
|
alimentacao: parseFloat(val('f-alimentacao')) || 0,
|
||||||
voucher: parseFloat(val('f-voucher')) || 0,
|
voucher: parseFloat(val('f-voucher')) || 0,
|
||||||
@@ -642,7 +642,7 @@ function updateBadges() {
|
|||||||
async function salvarRascunho(silent = false) {
|
async function salvarRascunho(silent = false) {
|
||||||
calcular();
|
calcular();
|
||||||
try {
|
try {
|
||||||
const result = await invokeSafe('salvar_local', { estado: JSON.stringify(estado) });
|
const result = await invokeSafe('salvar_fechamento', { estado });
|
||||||
estado.id_local = result.id;
|
estado.id_local = result.id;
|
||||||
estado.uuid = result.uuid;
|
estado.uuid = result.uuid;
|
||||||
if (!silent) toast('Rascunho salvo (local)', 'success');
|
if (!silent) toast('Rascunho salvo (local)', 'success');
|
||||||
@@ -689,7 +689,7 @@ async function enviarFechamento() {
|
|||||||
if (!estado.loja || !estado.data) { toast('Loja e data so obrigatorios', 'error'); return; }
|
if (!estado.loja || !estado.data) { toast('Loja e data so obrigatorios', 'error'); return; }
|
||||||
showLoad('Enviando ao servidor…');
|
showLoad('Enviando ao servidor…');
|
||||||
try {
|
try {
|
||||||
await invokeSafe('enviar_fechamento', { estado: JSON.stringify(estado) });
|
await invokeSafe('sb_salvar_fechamento', { estado });
|
||||||
toast('Enviado com sucesso!', 'success');
|
toast('Enviado com sucesso!', 'success');
|
||||||
atualizarSyncBadge('synced');
|
atualizarSyncBadge('synced');
|
||||||
} catch(e) { toast(`Erro ao enviar: ${e}`, 'error'); }
|
} catch(e) { toast(`Erro ao enviar: ${e}`, 'error'); }
|
||||||
@@ -739,7 +739,7 @@ async function imprimirAgora() {
|
|||||||
document.getElementById('modal-print').classList.remove('show');
|
document.getElementById('modal-print').classList.remove('show');
|
||||||
showLoad('Imprimindo…');
|
showLoad('Imprimindo…');
|
||||||
try {
|
try {
|
||||||
await invokeSafe('imprimir_fechamento', { estado: JSON.stringify(estado) });
|
await invokeSafe('imprimir_recibo', { estado });
|
||||||
toast('Impresso com sucesso!', 'success');
|
toast('Impresso com sucesso!', 'success');
|
||||||
} catch(e) { toast(`Erro na impressao: ${e}`, 'error'); }
|
} catch(e) { toast(`Erro na impressao: ${e}`, 'error'); }
|
||||||
hideLoad();
|
hideLoad();
|
||||||
@@ -755,7 +755,7 @@ async function listarRecentes() {
|
|||||||
if (!loja) { toast('Selecione a loja primeiro', 'error'); return; }
|
if (!loja) { toast('Selecione a loja primeiro', 'error'); return; }
|
||||||
showLoad('Carregando recentes…');
|
showLoad('Carregando recentes…');
|
||||||
try {
|
try {
|
||||||
const lista = await invokeSafe('listar_recentes', { loja, limite: 20 });
|
const lista = await invokeSafe('sb_listar_recentes', { loja, limite: 20 });
|
||||||
const html = lista.map(r => `
|
const html = lista.map(r => `
|
||||||
<tr onclick="selecionarRecente(${r.id})" style="cursor:pointer">
|
<tr onclick="selecionarRecente(${r.id})" style="cursor:pointer">
|
||||||
<td>${r.data}</td><td>${r.operador||'—'}</td><td>${r.turno}º</td>
|
<td>${r.data}</td><td>${r.operador||'—'}</td><td>${r.turno}º</td>
|
||||||
@@ -785,7 +785,7 @@ async function selecionarRecente(id) {
|
|||||||
document.getElementById('modal-recentes')?.classList.remove('show');
|
document.getElementById('modal-recentes')?.classList.remove('show');
|
||||||
showLoad('Carregando…');
|
showLoad('Carregando…');
|
||||||
try {
|
try {
|
||||||
const r = await invokeSafe('buscar_fechamento', { id });
|
const r = await invokeSafe('buscar_fechamento_por_id', { id });
|
||||||
Object.assign(estado, r);
|
Object.assign(estado, r);
|
||||||
document.getElementById('f-saldo-troco').value = r.saldo_troco || '';
|
document.getElementById('f-saldo-troco').value = r.saldo_troco || '';
|
||||||
document.getElementById('f-fechamento').value = r.fechamento || '';
|
document.getElementById('f-fechamento').value = r.fechamento || '';
|
||||||
|
|||||||
Reference in New Issue
Block a user