1use serde::{Deserialize, Deserializer, Serialize, Serializer};
7use std::convert::TryFrom;
8use std::fs::File;
9use std::io::Read;
10use std::str::FromStr;
11pub mod dest;
12pub mod emit;
13pub mod endereco;
14mod error;
15pub mod ide;
16pub mod item;
17pub mod totais;
18pub mod transporte;
19use dest::Destinatario;
20use emit::Emitente;
21pub use error::Error;
22use ide::Identificacao;
23use item::Item;
24use totais::Totalizacao;
25use transporte::Transporte;
26
27#[derive(Debug, PartialEq)]
32pub struct Nfe {
33 pub versao: VersaoLayout,
34 pub chave_acesso: String,
35 pub ide: Identificacao,
36 pub emit: Emitente,
37 pub dest: Option<Destinatario>,
38 pub itens: Vec<Item>,
39 pub totais: Totalizacao,
40 pub transporte: Transporte,
41 pub informacao_complementar: Option<String>,
43}
44
45#[derive(Debug, Eq, PartialEq, Copy, Clone, Deserialize)]
47pub enum VersaoLayout {
48 #[serde(rename = "4.00")]
49 V4_00 = 4,
50}
51
52impl FromStr for Nfe {
53 type Err = Error;
54
55 fn from_str(s: &str) -> Result<Self, Self::Err> {
56 quick_xml::de::from_str(s).map_err(|e| e.into())
57 }
58}
59
60impl TryFrom<File> for Nfe {
61 type Error = Error;
62
63 fn try_from(mut f: File) -> Result<Self, Self::Error> {
64 let mut xml = String::new();
65 f.read_to_string(&mut xml).map_err(|e| Error::Io(e))?;
66
67 xml.parse::<Nfe>()
68 }
69}
70
71impl ToString for Nfe {
72 fn to_string(&self) -> String {
73 quick_xml::se::to_string(self).expect("Falha ao serializar a nota")
74 }
75}
76
77impl<'de> Deserialize<'de> for Nfe {
78 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
79 where
80 D: Deserializer<'de>,
81 {
82 let nfe = NfeRootContainer::deserialize(deserializer)?;
83
84 Ok(Self {
85 versao: nfe.inf.versao,
86 chave_acesso: nfe.inf.chave_acesso.replace("NFe", ""),
87 ide: nfe.inf.ide,
88 emit: nfe.inf.emit,
89 dest: nfe.inf.dest,
90 itens: nfe.inf.itens,
91 totais: nfe.inf.totais,
92 transporte: nfe.inf.transporte,
93 informacao_complementar: match nfe.inf.add {
94 Some(add) => add.informacao_complementar,
95 None => None,
96 },
97 })
98 }
99}
100
101impl Serialize for Nfe {
102 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
103 where
104 S: Serializer,
105 {
106 let inf = NfeInfContainer {
107 versao: self.versao,
108 chave_acesso: format!("NFe{}", self.chave_acesso),
109 ide: self.ide.clone(),
110 emit: self.emit.clone(),
111 dest: self.dest.clone(),
112 itens: self.itens.clone(),
113 totais: self.totais.clone(),
114 transporte: self.transporte.clone(),
115 add: match self.informacao_complementar.clone() {
116 Some(ic) => Some(InfAddContainer {
117 informacao_complementar: Some(ic),
118 }),
119 None => None,
120 },
121 };
122
123 let root = NfeRootContainer { inf };
124
125 root.serialize(serializer)
126 }
127}
128
129impl Serialize for VersaoLayout {
130 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
131 where
132 S: Serializer,
133 {
134 serializer.serialize_str(match self {
135 VersaoLayout::V4_00 => "4.00",
136 })
137 }
138}
139
140#[derive(Deserialize, Serialize)]
141#[serde(rename = "NFe")]
142struct NfeRootContainer {
143 #[serde(rename = "infNFe")]
144 pub inf: NfeInfContainer,
145}
146
147#[derive(Deserialize, Serialize)]
148struct InfAddContainer {
149 #[serde(rename = "$unflatten=infCpl")]
150 pub informacao_complementar: Option<String>,
151}
152
153#[derive(Deserialize, Serialize)]
154struct NfeInfContainer {
155 #[serde(rename = "versao")]
156 pub versao: VersaoLayout,
157 #[serde(rename = "Id")]
158 pub chave_acesso: String,
159 #[serde(rename = "ide")]
160 pub ide: Identificacao,
161 #[serde(rename = "emit")]
162 pub emit: Emitente,
163 #[serde(rename = "dest")]
164 pub dest: Option<Destinatario>,
165 #[serde(rename = "det")]
166 pub itens: Vec<Item>,
167 #[serde(rename = "total")]
168 pub totais: Totalizacao,
169 #[serde(rename = "transp")]
170 pub transporte: Transporte,
171 #[serde(rename = "infAdic")]
172 pub add: Option<InfAddContainer>,
173}