207 lines
7.7 KiB
Rust
207 lines
7.7 KiB
Rust
use crate::domain::entities::layout::{Layout, LayoutCsv, LayoutXlsx};
|
|
use rusqlite::{params, Connection, Result};
|
|
|
|
/// Converte o char delimitador para string legível no banco.
|
|
fn delim_para_str(c: char) -> String {
|
|
match c {
|
|
'\t' => "tab".to_string(),
|
|
c => c.to_string(),
|
|
}
|
|
}
|
|
|
|
/// Converte a string armazenada no banco de volta para char delimitador.
|
|
fn str_para_delim(s: &str) -> char {
|
|
match s {
|
|
"tab" => '\t',
|
|
s => s.chars().next().unwrap_or(';'),
|
|
}
|
|
}
|
|
|
|
/// Salva um layout no banco. Retorna o id gerado.
|
|
pub fn salvar(conn: &Connection, layout: &Layout) -> Result<i64> {
|
|
match layout {
|
|
Layout::Csv { nome, config, .. } => {
|
|
conn.execute(
|
|
"INSERT INTO layouts
|
|
(nome, tipo, delimitador, encoding, linha_cabecalho,
|
|
indice_numero, indice_serie, indice_valor, indice_data,
|
|
indice_documento_tipo)
|
|
VALUES (?1, 'csv', ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)",
|
|
params![
|
|
nome,
|
|
delim_para_str(config.delimitador),
|
|
config.encoding,
|
|
config.linha_cabecalho as i64,
|
|
config.indice_numero as i64,
|
|
config.indice_serie as i64,
|
|
config.indice_valor.map(|v| v as i64),
|
|
config.indice_data.map(|v| v as i64),
|
|
config.indice_documento_tipo.map(|v| v as i64),
|
|
],
|
|
)?;
|
|
Ok(conn.last_insert_rowid())
|
|
}
|
|
Layout::Xlsx { nome, config, .. } => {
|
|
conn.execute(
|
|
"INSERT INTO layouts
|
|
(nome, tipo, aba, pos_numero, pos_serie, pos_valor, pos_data,
|
|
pos_documento_tipo)
|
|
VALUES (?1, 'xlsx', ?2, ?3, ?4, ?5, ?6, ?7)",
|
|
params![
|
|
nome,
|
|
config.aba,
|
|
config.pos_numero,
|
|
config.pos_serie,
|
|
config.pos_valor,
|
|
config.pos_data,
|
|
config.pos_documento_tipo,
|
|
],
|
|
)?;
|
|
Ok(conn.last_insert_rowid())
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Atualiza um layout existente no banco.
|
|
/// Zera explicitamente os campos do tipo oposto para evitar dados órfãos.
|
|
pub fn atualizar(conn: &Connection, layout: &Layout) -> Result<()> {
|
|
let id = layout
|
|
.id()
|
|
.ok_or_else(|| rusqlite::Error::InvalidParameterName("id ausente".to_string()))?;
|
|
|
|
match layout {
|
|
Layout::Csv { nome, config, .. } => {
|
|
conn.execute(
|
|
"UPDATE layouts SET
|
|
nome = ?1, delimitador = ?2, encoding = ?3,
|
|
linha_cabecalho = ?4, indice_numero = ?5, indice_serie = ?6,
|
|
indice_valor = ?7, indice_data = ?8, indice_documento_tipo = ?9,
|
|
aba = NULL, pos_numero = NULL, pos_serie = NULL,
|
|
pos_valor = NULL, pos_data = NULL, pos_documento_tipo = NULL
|
|
WHERE id = ?10",
|
|
params![
|
|
nome,
|
|
delim_para_str(config.delimitador),
|
|
config.encoding,
|
|
config.linha_cabecalho as i64,
|
|
config.indice_numero as i64,
|
|
config.indice_serie as i64,
|
|
config.indice_valor.map(|v| v as i64),
|
|
config.indice_data.map(|v| v as i64),
|
|
config.indice_documento_tipo.map(|v| v as i64),
|
|
id,
|
|
],
|
|
)?;
|
|
}
|
|
Layout::Xlsx { nome, config, .. } => {
|
|
conn.execute(
|
|
"UPDATE layouts SET
|
|
nome = ?1, aba = ?2, pos_numero = ?3, pos_serie = ?4,
|
|
pos_valor = ?5, pos_data = ?6, pos_documento_tipo = ?7,
|
|
delimitador = NULL, encoding = NULL, linha_cabecalho = NULL,
|
|
indice_numero = NULL, indice_serie = NULL, indice_valor = NULL,
|
|
indice_data = NULL, indice_documento_tipo = NULL
|
|
WHERE id = ?8",
|
|
params![
|
|
nome,
|
|
config.aba,
|
|
config.pos_numero,
|
|
config.pos_serie,
|
|
config.pos_valor,
|
|
config.pos_data,
|
|
config.pos_documento_tipo,
|
|
id,
|
|
],
|
|
)?;
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// Lista todos os layouts salvos.
|
|
pub fn listar(conn: &Connection) -> Result<Vec<Layout>> {
|
|
let mut stmt = conn.prepare(
|
|
"SELECT id, nome, tipo,
|
|
delimitador, encoding, linha_cabecalho,
|
|
indice_numero, indice_serie, indice_valor, indice_data,
|
|
aba, pos_numero, pos_serie, pos_valor, pos_data,
|
|
indice_documento_tipo, pos_documento_tipo
|
|
FROM layouts ORDER BY nome ASC",
|
|
)?;
|
|
|
|
let layouts: Result<Vec<Layout>> = stmt
|
|
.query_map([], |row| {
|
|
let id: i64 = row.get("id")?;
|
|
let nome: String = row.get("nome")?;
|
|
let tipo: String = row.get("tipo")?;
|
|
|
|
if tipo == "csv" {
|
|
let delim_str: String = row.get("delimitador")?;
|
|
let delimitador = str_para_delim(&delim_str);
|
|
Ok(Layout::Csv {
|
|
id: Some(id),
|
|
nome,
|
|
config: LayoutCsv {
|
|
delimitador,
|
|
encoding: row.get("encoding")?,
|
|
linha_cabecalho: row.get::<_, i64>("linha_cabecalho")? as usize,
|
|
indice_numero: row.get::<_, i64>("indice_numero")? as usize,
|
|
indice_serie: row.get::<_, i64>("indice_serie")? as usize,
|
|
indice_valor: row
|
|
.get::<_, Option<i64>>("indice_valor")?
|
|
.map(|v| v as usize),
|
|
indice_data: row
|
|
.get::<_, Option<i64>>("indice_data")?
|
|
.map(|v| v as usize),
|
|
indice_documento_tipo: row
|
|
.get::<_, Option<i64>>("indice_documento_tipo")?
|
|
.map(|v| v as usize),
|
|
},
|
|
})
|
|
} else {
|
|
Ok(Layout::Xlsx {
|
|
id: Some(id),
|
|
nome,
|
|
config: LayoutXlsx {
|
|
aba: row.get("aba")?,
|
|
pos_numero: row.get("pos_numero")?,
|
|
pos_serie: row.get("pos_serie")?,
|
|
pos_valor: row.get("pos_valor")?,
|
|
pos_data: row.get("pos_data")?,
|
|
pos_documento_tipo: row.get("pos_documento_tipo")?,
|
|
},
|
|
})
|
|
}
|
|
})?
|
|
.collect();
|
|
|
|
layouts
|
|
}
|
|
|
|
/// Remove um layout pelo id.
|
|
pub fn excluir(conn: &Connection, id: i64) -> Result<()> {
|
|
conn.execute("DELETE FROM layouts WHERE id = ?1", [id])?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Verifica se já existe um layout com o nome fornecido.
|
|
pub fn existe_nome(conn: &Connection, nome: &str) -> Result<bool> {
|
|
let count: i64 = conn.query_row(
|
|
"SELECT COUNT(*) FROM layouts WHERE nome = ?1",
|
|
[nome],
|
|
|row| row.get(0),
|
|
)?;
|
|
Ok(count > 0)
|
|
}
|
|
|
|
/// Verifica se existe um layout com o nome fornecido, excluindo o registro com o id dado.
|
|
/// Usado para validar conflito de nome ao renomear um layout existente.
|
|
pub fn existe_nome_excluindo_id(conn: &Connection, nome: &str, id: i64) -> Result<bool> {
|
|
let count: i64 = conn.query_row(
|
|
"SELECT COUNT(*) FROM layouts WHERE nome = ?1 AND id != ?2",
|
|
params![nome, id],
|
|
|row| row.get(0),
|
|
)?;
|
|
Ok(count > 0)
|
|
}
|