Skip to content

Commit

Permalink
Major refactor.
Browse files Browse the repository at this point in the history
Detect file instead forcing user to go to the alternatives.
Initial table that in the future could be editable.
  • Loading branch information
vaijira committed Sep 1, 2024
1 parent 6d69dde commit dbf39f5
Show file tree
Hide file tree
Showing 13 changed files with 538 additions and 1,418 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ futures = "0.3"
futures-signals = "0.3"
gloo-file = { version = "0.2", features = [ "futures" ] }
html5ever = "0.25"
infer = "0.16.0"
instant = { version = "0.1", features = [ "wasm-bindgen", "inaccurate" ] }
js-sys = "0.3"
log = "0.4"
Expand Down
2 changes: 1 addition & 1 deletion dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ <h2>Instrucciones para la generación del modelo 720.</h2>
<p>Tiene más información de cómo descargar los informes si desliza el puntero por el signo de interrogación adjunto a cada opción de subida de fichero.</p>
<p>Introduzca los datos personales para la generación del fichero del modelo 720, de otra forma al importarlo dará error.</p>
<p>Pulse "Descargar informe AEAT 720" y guarde el fichero en el disco duro.</p>
<p>Finalmente suba el fichero descargado con el modelo 720 a <a alt="enlace modelo 720 AEAT" target="_blank" rel="noopener external " href="https://sede.agenciatributaria.gob.es/Sede/procedimientoini/GI34.shtml">página corespondiente de la AEAT</a> y comparta en redes sociales si le ha resultado de utilidad.</p>
<p>Finalmente suba el fichero descargado con el modelo 720 a <a alt="enlace modelo 720 AEAT" target="_blank" rel="noopener external " href="https://sede.agenciatributaria.gob.es/Sede/procedimientoini/GI34.shtml">página correspondiente de la AEAT</a> y comparta en redes sociales si le ha resultado de utilidad.</p>
<div id="burocratinApp" ><script src="js/index.js"></script></div>
</body>
</html>
835 changes: 127 additions & 708 deletions src/app.rs

Large diffs are not rendered by default.

44 changes: 31 additions & 13 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{convert::From, sync::Arc};

pub type AccountNotes = Vec<AccountNote>;
pub type BalanceNotes = Vec<BalanceNote>;
pub type Aeat720Records = Vec<Aeat720Record>;

pub const SPAIN_COUNTRY_CODE: &str = "ES";

Expand Down Expand Up @@ -115,31 +116,48 @@ impl BrokerInformation {
}
}
}
pub struct FinancialInformation {
pub account_notes: AccountNotes,
pub balance_notes: BalanceNotes,

#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
pub struct Aeat720Record {
pub company: CompanyInfo,
pub quantity: Decimal,
pub value_in_euro: Decimal,
pub first_tx_date: usize,
pub broker: Arc<BrokerInformation>,
}

#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)]
pub struct PersonalInformation {
pub name: String,
pub surname: String,
pub nif: String,
pub year: usize,
pub phone: String,
}

impl FinancialInformation {
#[allow(dead_code)]
#[derive(Debug, Eq, Clone, PartialEq, Deserialize, Serialize)]
pub struct Aeat720Information {
pub records: Vec<Aeat720Record>,
pub personal_info: PersonalInformation,
}

pub const DEFAULT_YEAR: usize = 2024;

impl Aeat720Information {
pub fn new() -> Self {
Self {
account_notes: vec![],
balance_notes: vec![],
name: String::from(""),
surname: String::from(""),
nif: String::from(""),
year: 0,
phone: String::from(""),
records: vec![],
personal_info: PersonalInformation {
name: String::from(""),
surname: String::from(""),
nif: String::from(""),
year: DEFAULT_YEAR,
phone: String::from(""),
},
}
}

pub fn full_name(&self) -> String {
self.surname.clone() + " " + &self.name
self.personal_info.surname.clone() + " " + &self.personal_info.name
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ mod data;
mod feathers;
mod footer;
mod parsers;
mod personal_info;
mod reports;
mod table;
mod tooltip;
mod utils;

Expand Down
122 changes: 122 additions & 0 deletions src/personal_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
use std::sync::Arc;

use dominator::{clone, events, html, with_node, Dom};
use futures_signals::signal::Mutable;
use web_sys::HtmlInputElement;

use crate::{
css::{FLEX_CONTAINER_CLASS, FLEX_CONTAINER_ITEM_20_CLASS},
data::{PersonalInformation, DEFAULT_YEAR},
};

pub struct PersonalInfoViewer {
personal_info: Mutable<PersonalInformation>,
}

impl PersonalInfoViewer {
pub fn new(personal_info: Mutable<PersonalInformation>) -> Arc<Self> {
Arc::new(PersonalInfoViewer { personal_info })
}

pub fn render(this: &Arc<Self>) -> Dom {
html!("section", {
.class(&*FLEX_CONTAINER_CLASS)
.child(html!("span", {
.class(&*FLEX_CONTAINER_ITEM_20_CLASS)
.children(&mut [
html!("label", {
.attr("for", "name")
.text("Nombre: ")
}),
html!("input" => HtmlInputElement, {
.attr("id", "name")
.attr("alt", "Nombre")
.attr("type", "text")
.with_node!(element => {
.event(clone!(this => move |_: events::Input| {
this.personal_info.lock_mut().name = element.value().to_uppercase();
}))
})
}),
])
}))
.child(html!("span", {
.class(&*FLEX_CONTAINER_ITEM_20_CLASS)
.children(&mut [
html!("label", {
.attr("for", "surname")
.text("Apellidos: ")
}),
html!("input" => HtmlInputElement, {
.attr("id", "surname")
.attr("alt", "Apellidos")
.attr("type", "text")
.with_node!(element => {
.event(clone!(this => move |_: events::Input| {
this.personal_info.lock_mut().surname = element.value().to_uppercase();
}))
})
}),
])
}))
.child(html!("span", {
.class(&*FLEX_CONTAINER_ITEM_20_CLASS)
.children(&mut [
html!("label", {
.attr("for", "nif")
.text("NIF: ")
}),
html!("input" => HtmlInputElement, {
.attr("id", "nif")
.attr("alt", "NIF")
.attr("type", "text")
.with_node!(element => {
.event(clone!(this => move |_: events::Input| {
this.personal_info.lock_mut().nif = element.value().to_uppercase();
}))
})
}),
])
}))
.child(html!("span", {
.class(&*FLEX_CONTAINER_ITEM_20_CLASS)
.children(&mut [
html!("label", {
.attr("for", "year")
.text("Año: ")
}),
html!("input" => HtmlInputElement, {
.attr("id", "year")
.attr("alt", "Año")
.attr("type", "text")
.attr("placeholder", &DEFAULT_YEAR.to_string())
.with_node!(element => {
.event(clone!(this => move |_: events::Input| {
this.personal_info.lock_mut().year = element.value().parse::<usize>().unwrap_or(DEFAULT_YEAR);
}))
})
}),
])
}))
.child(html!("span", {
.class(&*FLEX_CONTAINER_ITEM_20_CLASS)
.children(&mut [
html!("label", {
.attr("for", "phone")
.text("Teléfono: ")
}),
html!("input" => HtmlInputElement, {
.attr("id", "phone")
.attr("alt", "Teléfono")
.attr("type", "text")
.with_node!(element => {
.event(clone!(this => move |_: events::Input| {
this.personal_info.lock_mut().phone = element.value().to_uppercase();
}))
})
}),
])
}))
})
}
}
74 changes: 30 additions & 44 deletions src/reports/aeat_720.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::data::{AccountNote, BalanceNote, FinancialInformation};
use crate::data::{Aeat720Information, Aeat720Record};
use anyhow::{bail, Result};
use chrono::NaiveDate;
use encoding_rs::ISO_8859_15;
use rust_decimal::{prelude::ToPrimitive, Decimal};
use std::io::Write;
Expand Down Expand Up @@ -228,7 +227,13 @@ impl Default for SummaryRegister {
}

impl SummaryRegister {
fn new(notes: &[BalanceNote], year: usize, nif: &str, name: &str, phone: &str) -> Result<Self> {
fn new(
records: &[Aeat720Record],
year: usize,
nif: &str,
name: &str,
phone: &str,
) -> Result<Self> {
let mut fields = Self::default().fields;

Aeat720Field::write_field(&mut fields, Self::NIF_FIELD, nif)?;
Expand All @@ -246,12 +251,12 @@ impl SummaryRegister {
Aeat720Field::write_numeric_field(
&mut fields,
Self::TOTAL_DETAIL_REGISTERS_FIELD,
notes.len(),
records.len(),
)?;

let mut total_acquisition = Decimal::new(0, 2);

for note in notes {
for note in records {
total_acquisition += note.value_in_euro;
}

Expand Down Expand Up @@ -456,13 +461,7 @@ impl Default for DetailRegister {
}

impl DetailRegister {
fn new(
note: &BalanceNote,
transactions: &[AccountNote],
year: usize,
nif: &str,
name: &str,
) -> Result<Self> {
fn new(record: &Aeat720Record, year: usize, nif: &str, name: &str) -> Result<Self> {
let mut fields = Self::default().fields;

Aeat720Field::write_numeric_field(&mut fields, Self::YEAR_FIELD, year)?;
Expand All @@ -472,38 +471,26 @@ impl DetailRegister {
Aeat720Field::write_field(
&mut fields,
Self::COUNTRY_CODE_FIELD,
&note.broker.country_code,
&record.broker.country_code,
)?;
Aeat720Field::write_field(&mut fields, Self::STOCK_ID_FIELD, &note.company.isin)?;
Aeat720Field::write_field(&mut fields, Self::STOCK_ID_FIELD, &record.company.isin)?;
Aeat720Field::write_field(
&mut fields,
Self::ENTITY_NAME_FIELD,
&note.company.name.to_uppercase(),
&record.company.name.to_uppercase(),
)?;
Aeat720Field::write_field(
&mut fields,
Self::ENTITY_COUNTRY_CODE_FIELD,
&note.company.isin[0..2],
&record.company.isin[0..2],
)?;
let first_tx_date = {
let company = transactions.iter().find(|&x| x.company == note.company);
match company {
Some(c) => c.date.format("%Y%m%d").to_string(),
None => NaiveDate::from_ymd_opt(year as i32, 1, 1)
.unwrap()
.format("%Y%m%d")
.to_string(),
}
.parse::<usize>()
.unwrap_or(0)
};
Aeat720Field::write_numeric_field(
&mut fields,
Self::FIRST_ACQUISITION_DATE_FIELD,
first_tx_date,
record.first_tx_date,
)?;

if note.value_in_euro.is_sign_negative() {
if record.value_in_euro.is_sign_negative() {
Aeat720Field::write_field(
&mut fields,
Self::ACQUISITON_SIGN_FIELD,
Expand All @@ -513,9 +500,9 @@ impl DetailRegister {
Aeat720Field::write_numeric_field(
&mut fields,
Self::ACQUISITION_INT_FIELD,
note.value_in_euro.trunc().abs().to_usize().unwrap_or(0),
record.value_in_euro.trunc().abs().to_usize().unwrap_or(0),
)?;
let mut remainder = note.value_in_euro.fract();
let mut remainder = record.value_in_euro.fract();
remainder.set_scale(0)?;
Aeat720Field::write_numeric_field(
&mut fields,
Expand All @@ -526,10 +513,10 @@ impl DetailRegister {
Aeat720Field::write_numeric_field(
&mut fields,
Self::STOCK_QUANTITY_INT_FIELD,
note.quantity.trunc().abs().to_usize().unwrap_or(0),
record.quantity.trunc().abs().to_usize().unwrap_or(0),
)?;

let mut remainder = note.quantity.fract();
let mut remainder = record.quantity.fract();
remainder.set_scale(2)?;
Aeat720Field::write_numeric_field(
&mut fields,
Expand All @@ -549,28 +536,27 @@ pub struct Aeat720Report {
}

impl Aeat720Report {
pub fn new(info: &FinancialInformation) -> Result<Aeat720Report> {
pub fn new(info: &Aeat720Information) -> Result<Aeat720Report> {
let mut details = Vec::new();
let full_name = info.full_name();

for balance_note in &info.balance_notes {
for record in &info.records {
let detail = DetailRegister::new(
balance_note,
&info.account_notes,
info.year,
&info.nif,
record,
info.personal_info.year,
&info.personal_info.nif,
&full_name,
)?;
details.push(detail);
}

Ok(Aeat720Report {
summary: SummaryRegister::new(
&info.balance_notes,
info.year,
&info.nif,
&info.records,
info.personal_info.year,
&info.personal_info.nif,
&full_name,
&info.phone,
&info.personal_info.phone,
)?,
details,
})
Expand Down
Loading

0 comments on commit dbf39f5

Please sign in to comment.