1use crate::FiscalError;
18use crate::format_utils::format_cents_or_none;
19use crate::newtypes::{Cents, Rate};
20use crate::tax_element::{
21 TaxElement, TaxField, filter_fields, optional_field, required_field, serialize_tax_element,
22};
23
24fn accum(current: Cents, value: Option<Cents>) -> Cents {
26 current + value.unwrap_or(Cents(0))
27}
28
29fn accum_raw(current: i64, value: Option<i64>) -> i64 {
31 current + value.unwrap_or(0)
32}
33
34#[derive(Debug, Clone)]
40#[non_exhaustive]
41pub enum IcmsVariant {
42 Cst(Box<IcmsCst>),
44 Csosn(Box<IcmsCsosn>),
46}
47
48impl From<IcmsCst> for IcmsVariant {
49 fn from(cst: IcmsCst) -> Self {
50 Self::Cst(Box::new(cst))
51 }
52}
53
54impl From<IcmsCsosn> for IcmsVariant {
55 fn from(csosn: IcmsCsosn) -> Self {
56 Self::Csosn(Box::new(csosn))
57 }
58}
59
60#[derive(Debug, Clone)]
65#[non_exhaustive]
66pub struct IcmsPartData {
67 pub orig: String,
69 pub cst: String,
71 pub mod_bc: String,
73 pub v_bc: Cents,
75 pub p_red_bc: Option<Rate>,
77 pub p_icms: Rate,
79 pub v_icms: Cents,
81 pub mod_bc_st: String,
83 pub p_mva_st: Option<Rate>,
85 pub p_red_bc_st: Option<Rate>,
87 pub v_bc_st: Cents,
89 pub p_icms_st: Rate,
91 pub v_icms_st: Cents,
93 pub v_bc_fcp_st: Option<Cents>,
95 pub p_fcp_st: Option<Rate>,
97 pub v_fcp_st: Option<Cents>,
99 pub p_bc_op: Rate,
101 pub uf_st: String,
103 pub v_icms_deson: Option<Cents>,
105 pub mot_des_icms: Option<String>,
107 pub ind_deduz_deson: Option<String>,
109}
110
111impl IcmsPartData {
112 #[allow(clippy::too_many_arguments)]
114 pub fn new(
115 orig: impl Into<String>,
116 cst: impl Into<String>,
117 mod_bc: impl Into<String>,
118 v_bc: Cents,
119 p_icms: Rate,
120 v_icms: Cents,
121 mod_bc_st: impl Into<String>,
122 v_bc_st: Cents,
123 p_icms_st: Rate,
124 v_icms_st: Cents,
125 p_bc_op: Rate,
126 uf_st: impl Into<String>,
127 ) -> Self {
128 Self {
129 orig: orig.into(),
130 cst: cst.into(),
131 mod_bc: mod_bc.into(),
132 v_bc,
133 p_red_bc: None,
134 p_icms,
135 v_icms,
136 mod_bc_st: mod_bc_st.into(),
137 p_mva_st: None,
138 p_red_bc_st: None,
139 v_bc_st,
140 p_icms_st,
141 v_icms_st,
142 v_bc_fcp_st: None,
143 p_fcp_st: None,
144 v_fcp_st: None,
145 p_bc_op,
146 uf_st: uf_st.into(),
147 v_icms_deson: None,
148 mot_des_icms: None,
149 ind_deduz_deson: None,
150 }
151 }
152 pub fn p_red_bc(mut self, v: Rate) -> Self {
154 self.p_red_bc = Some(v);
155 self
156 }
157 pub fn p_mva_st(mut self, v: Rate) -> Self {
159 self.p_mva_st = Some(v);
160 self
161 }
162 pub fn p_red_bc_st(mut self, v: Rate) -> Self {
164 self.p_red_bc_st = Some(v);
165 self
166 }
167 pub fn v_bc_fcp_st(mut self, v: Cents) -> Self {
169 self.v_bc_fcp_st = Some(v);
170 self
171 }
172 pub fn p_fcp_st(mut self, v: Rate) -> Self {
174 self.p_fcp_st = Some(v);
175 self
176 }
177 pub fn v_fcp_st(mut self, v: Cents) -> Self {
179 self.v_fcp_st = Some(v);
180 self
181 }
182 pub fn v_icms_deson(mut self, v: Cents) -> Self {
184 self.v_icms_deson = Some(v);
185 self
186 }
187 pub fn mot_des_icms(mut self, v: impl Into<String>) -> Self {
189 self.mot_des_icms = Some(v.into());
190 self
191 }
192 pub fn ind_deduz_deson(mut self, v: impl Into<String>) -> Self {
194 self.ind_deduz_deson = Some(v.into());
195 self
196 }
197}
198
199#[derive(Debug, Clone)]
203#[non_exhaustive]
204pub struct IcmsStData {
205 pub orig: String,
207 pub cst: String,
209 pub v_bc_st_ret: Cents,
211 pub p_st: Option<Rate>,
213 pub v_icms_substituto: Option<Cents>,
215 pub v_icms_st_ret: Cents,
217 pub v_bc_fcp_st_ret: Option<Cents>,
219 pub p_fcp_st_ret: Option<Rate>,
221 pub v_fcp_st_ret: Option<Cents>,
223 pub v_bc_st_dest: Cents,
225 pub v_icms_st_dest: Cents,
227 pub p_red_bc_efet: Option<Rate>,
229 pub v_bc_efet: Option<Cents>,
231 pub p_icms_efet: Option<Rate>,
233 pub v_icms_efet: Option<Cents>,
235}
236
237impl IcmsStData {
238 #[allow(clippy::too_many_arguments)]
240 pub fn new(
241 orig: impl Into<String>,
242 cst: impl Into<String>,
243 v_bc_st_ret: Cents,
244 v_icms_st_ret: Cents,
245 v_bc_st_dest: Cents,
246 v_icms_st_dest: Cents,
247 ) -> Self {
248 Self {
249 orig: orig.into(),
250 cst: cst.into(),
251 v_bc_st_ret,
252 p_st: None,
253 v_icms_substituto: None,
254 v_icms_st_ret,
255 v_bc_fcp_st_ret: None,
256 p_fcp_st_ret: None,
257 v_fcp_st_ret: None,
258 v_bc_st_dest,
259 v_icms_st_dest,
260 p_red_bc_efet: None,
261 v_bc_efet: None,
262 p_icms_efet: None,
263 v_icms_efet: None,
264 }
265 }
266 pub fn p_st(mut self, v: Rate) -> Self {
268 self.p_st = Some(v);
269 self
270 }
271 pub fn v_icms_substituto(mut self, v: Cents) -> Self {
273 self.v_icms_substituto = Some(v);
274 self
275 }
276 pub fn v_bc_fcp_st_ret(mut self, v: Cents) -> Self {
278 self.v_bc_fcp_st_ret = Some(v);
279 self
280 }
281 pub fn p_fcp_st_ret(mut self, v: Rate) -> Self {
283 self.p_fcp_st_ret = Some(v);
284 self
285 }
286 pub fn v_fcp_st_ret(mut self, v: Cents) -> Self {
288 self.v_fcp_st_ret = Some(v);
289 self
290 }
291 pub fn p_red_bc_efet(mut self, v: Rate) -> Self {
293 self.p_red_bc_efet = Some(v);
294 self
295 }
296 pub fn v_bc_efet(mut self, v: Cents) -> Self {
298 self.v_bc_efet = Some(v);
299 self
300 }
301 pub fn p_icms_efet(mut self, v: Rate) -> Self {
303 self.p_icms_efet = Some(v);
304 self
305 }
306 pub fn v_icms_efet(mut self, v: Cents) -> Self {
308 self.v_icms_efet = Some(v);
309 self
310 }
311}
312
313#[derive(Debug, Clone)]
318#[non_exhaustive]
319pub struct IcmsUfDestData {
320 pub v_bc_uf_dest: Cents,
322 pub v_bc_fcp_uf_dest: Option<Cents>,
324 pub p_fcp_uf_dest: Option<Rate>,
326 pub p_icms_uf_dest: Rate,
328 pub p_icms_inter: Rate,
330 pub v_fcp_uf_dest: Option<Cents>,
332 pub v_icms_uf_dest: Cents,
334 pub v_icms_uf_remet: Option<Cents>,
336}
337
338impl IcmsUfDestData {
339 pub fn new(
341 v_bc_uf_dest: Cents,
342 p_icms_uf_dest: Rate,
343 p_icms_inter: Rate,
344 v_icms_uf_dest: Cents,
345 ) -> Self {
346 Self {
347 v_bc_uf_dest,
348 v_bc_fcp_uf_dest: None,
349 p_fcp_uf_dest: None,
350 p_icms_uf_dest,
351 p_icms_inter,
352 v_fcp_uf_dest: None,
353 v_icms_uf_dest,
354 v_icms_uf_remet: None,
355 }
356 }
357 pub fn v_bc_fcp_uf_dest(mut self, v: Cents) -> Self {
359 self.v_bc_fcp_uf_dest = Some(v);
360 self
361 }
362 pub fn p_fcp_uf_dest(mut self, v: Rate) -> Self {
364 self.p_fcp_uf_dest = Some(v);
365 self
366 }
367 pub fn v_fcp_uf_dest(mut self, v: Cents) -> Self {
369 self.v_fcp_uf_dest = Some(v);
370 self
371 }
372 pub fn v_icms_uf_remet(mut self, v: Cents) -> Self {
374 self.v_icms_uf_remet = Some(v);
375 self
376 }
377}
378
379#[derive(Debug, Clone, Default, PartialEq, Eq)]
387#[non_exhaustive]
388pub struct IcmsTotals {
389 pub v_bc: Cents,
391 pub v_icms: Cents,
393 pub v_icms_deson: Cents,
395 pub v_bc_st: Cents,
397 pub v_st: Cents,
399 pub v_fcp: Cents,
401 pub v_fcp_st: Cents,
403 pub v_fcp_st_ret: Cents,
405 pub v_fcp_uf_dest: Cents,
407 pub v_icms_uf_dest: Cents,
409 pub v_icms_uf_remet: Cents,
411 pub q_bc_mono: i64,
413 pub v_icms_mono: Cents,
415 pub q_bc_mono_reten: i64,
417 pub v_icms_mono_reten: Cents,
419 pub q_bc_mono_ret: i64,
421 pub v_icms_mono_ret: Cents,
423}
424
425impl IcmsTotals {
426 pub fn new() -> Self {
428 Self::default()
429 }
430 pub fn v_bc(mut self, v: Cents) -> Self {
432 self.v_bc = v;
433 self
434 }
435 pub fn v_icms(mut self, v: Cents) -> Self {
437 self.v_icms = v;
438 self
439 }
440 pub fn v_icms_deson(mut self, v: Cents) -> Self {
442 self.v_icms_deson = v;
443 self
444 }
445 pub fn v_bc_st(mut self, v: Cents) -> Self {
447 self.v_bc_st = v;
448 self
449 }
450 pub fn v_st(mut self, v: Cents) -> Self {
452 self.v_st = v;
453 self
454 }
455 pub fn v_fcp(mut self, v: Cents) -> Self {
457 self.v_fcp = v;
458 self
459 }
460 pub fn v_fcp_st(mut self, v: Cents) -> Self {
462 self.v_fcp_st = v;
463 self
464 }
465 pub fn v_fcp_st_ret(mut self, v: Cents) -> Self {
467 self.v_fcp_st_ret = v;
468 self
469 }
470 pub fn v_fcp_uf_dest(mut self, v: Cents) -> Self {
472 self.v_fcp_uf_dest = v;
473 self
474 }
475 pub fn v_icms_uf_dest(mut self, v: Cents) -> Self {
477 self.v_icms_uf_dest = v;
478 self
479 }
480 pub fn v_icms_uf_remet(mut self, v: Cents) -> Self {
482 self.v_icms_uf_remet = v;
483 self
484 }
485 pub fn v_icms_mono(mut self, v: Cents) -> Self {
487 self.v_icms_mono = v;
488 self
489 }
490 pub fn v_icms_mono_reten(mut self, v: Cents) -> Self {
492 self.v_icms_mono_reten = v;
493 self
494 }
495 pub fn v_icms_mono_ret(mut self, v: Cents) -> Self {
497 self.v_icms_mono_ret = v;
498 self
499 }
500}
501
502pub fn create_icms_totals() -> IcmsTotals {
516 IcmsTotals::default()
517}
518
519#[derive(Debug, Clone)]
529#[non_exhaustive]
530pub enum IcmsCst {
531 Cst00 {
533 orig: String,
535 mod_bc: String,
537 v_bc: Cents,
539 p_icms: Rate,
541 v_icms: Cents,
543 p_fcp: Option<Rate>,
545 v_fcp: Option<Cents>,
547 },
548 Cst02 {
550 orig: String,
552 q_bc_mono: Option<i64>,
554 ad_rem_icms: Rate,
556 v_icms_mono: Cents,
558 },
559 Cst10 {
561 orig: String,
563 mod_bc: String,
565 v_bc: Cents,
567 p_icms: Rate,
569 v_icms: Cents,
571 v_bc_fcp: Option<Cents>,
573 p_fcp: Option<Rate>,
575 v_fcp: Option<Cents>,
577 mod_bc_st: String,
579 p_mva_st: Option<Rate>,
581 p_red_bc_st: Option<Rate>,
583 v_bc_st: Cents,
585 p_icms_st: Rate,
587 v_icms_st: Cents,
589 v_bc_fcp_st: Option<Cents>,
591 p_fcp_st: Option<Rate>,
593 v_fcp_st: Option<Cents>,
595 v_icms_st_deson: Option<Cents>,
597 mot_des_icms_st: Option<String>,
599 },
600 Cst15 {
603 orig: String,
605 q_bc_mono: Option<i64>,
607 ad_rem_icms: Rate,
609 v_icms_mono: Cents,
611 q_bc_mono_reten: Option<i64>,
613 ad_rem_icms_reten: Rate,
615 v_icms_mono_reten: Cents,
617 p_red_ad_rem: Option<Rate>,
619 mot_red_ad_rem: Option<String>,
621 },
622 Cst20 {
624 orig: String,
626 mod_bc: String,
628 p_red_bc: Rate,
630 v_bc: Cents,
632 p_icms: Rate,
634 v_icms: Cents,
636 v_bc_fcp: Option<Cents>,
638 p_fcp: Option<Rate>,
640 v_fcp: Option<Cents>,
642 v_icms_deson: Option<Cents>,
644 mot_des_icms: Option<String>,
646 ind_deduz_deson: Option<String>,
648 },
649 Cst30 {
651 orig: String,
653 mod_bc_st: String,
655 p_mva_st: Option<Rate>,
657 p_red_bc_st: Option<Rate>,
659 v_bc_st: Cents,
661 p_icms_st: Rate,
663 v_icms_st: Cents,
665 v_bc_fcp_st: Option<Cents>,
667 p_fcp_st: Option<Rate>,
669 v_fcp_st: Option<Cents>,
671 v_icms_deson: Option<Cents>,
673 mot_des_icms: Option<String>,
675 ind_deduz_deson: Option<String>,
677 },
678 Cst40 {
680 orig: String,
682 v_icms_deson: Option<Cents>,
684 mot_des_icms: Option<String>,
686 ind_deduz_deson: Option<String>,
688 },
689 Cst41 {
691 orig: String,
693 v_icms_deson: Option<Cents>,
695 mot_des_icms: Option<String>,
697 ind_deduz_deson: Option<String>,
699 },
700 Cst50 {
702 orig: String,
704 v_icms_deson: Option<Cents>,
706 mot_des_icms: Option<String>,
708 ind_deduz_deson: Option<String>,
710 },
711 Cst51 {
713 orig: String,
715 mod_bc: Option<String>,
717 p_red_bc: Option<Rate>,
719 c_benef_rbc: Option<String>,
721 v_bc: Option<Cents>,
723 p_icms: Option<Rate>,
725 v_icms_op: Option<Cents>,
727 p_dif: Option<Rate>,
729 v_icms_dif: Option<Cents>,
731 v_icms: Option<Cents>,
733 v_bc_fcp: Option<Cents>,
735 p_fcp: Option<Rate>,
737 v_fcp: Option<Cents>,
739 p_fcp_dif: Option<Rate>,
741 v_fcp_dif: Option<Cents>,
743 v_fcp_efet: Option<Cents>,
745 },
746 Cst53 {
749 orig: String,
751 q_bc_mono: Option<i64>,
753 ad_rem_icms: Option<Rate>,
755 v_icms_mono_op: Option<Cents>,
757 p_dif: Option<Rate>,
759 v_icms_mono_dif: Option<Cents>,
761 v_icms_mono: Option<Cents>,
763 },
764 Cst60 {
766 orig: String,
768 v_bc_st_ret: Option<Cents>,
770 p_st: Option<Rate>,
772 v_icms_substituto: Option<Cents>,
774 v_icms_st_ret: Option<Cents>,
776 v_bc_fcp_st_ret: Option<Cents>,
778 p_fcp_st_ret: Option<Rate>,
780 v_fcp_st_ret: Option<Cents>,
782 p_red_bc_efet: Option<Rate>,
784 v_bc_efet: Option<Cents>,
786 p_icms_efet: Option<Rate>,
788 v_icms_efet: Option<Cents>,
790 },
791 Cst61 {
793 orig: String,
795 q_bc_mono_ret: Option<i64>,
797 ad_rem_icms_ret: Rate,
799 v_icms_mono_ret: Cents,
801 },
802 Cst70 {
804 orig: String,
806 mod_bc: String,
808 p_red_bc: Rate,
810 v_bc: Cents,
812 p_icms: Rate,
814 v_icms: Cents,
816 v_bc_fcp: Option<Cents>,
818 p_fcp: Option<Rate>,
820 v_fcp: Option<Cents>,
822 mod_bc_st: String,
824 p_mva_st: Option<Rate>,
826 p_red_bc_st: Option<Rate>,
828 v_bc_st: Cents,
830 p_icms_st: Rate,
832 v_icms_st: Cents,
834 v_bc_fcp_st: Option<Cents>,
836 p_fcp_st: Option<Rate>,
838 v_fcp_st: Option<Cents>,
840 v_icms_deson: Option<Cents>,
842 mot_des_icms: Option<String>,
844 ind_deduz_deson: Option<String>,
846 v_icms_st_deson: Option<Cents>,
848 mot_des_icms_st: Option<String>,
850 },
851 Cst90 {
853 orig: String,
855 mod_bc: Option<String>,
857 v_bc: Option<Cents>,
859 p_red_bc: Option<Rate>,
861 c_benef_rbc: Option<String>,
863 p_icms: Option<Rate>,
865 v_icms_op: Option<Cents>,
867 p_dif: Option<Rate>,
869 v_icms_dif: Option<Cents>,
871 v_icms: Option<Cents>,
873 v_bc_fcp: Option<Cents>,
875 p_fcp: Option<Rate>,
877 v_fcp: Option<Cents>,
879 p_fcp_dif: Option<Rate>,
881 v_fcp_dif: Option<Cents>,
883 v_fcp_efet: Option<Cents>,
885 mod_bc_st: Option<String>,
887 p_mva_st: Option<Rate>,
889 p_red_bc_st: Option<Rate>,
891 v_bc_st: Option<Cents>,
893 p_icms_st: Option<Rate>,
895 v_icms_st: Option<Cents>,
897 v_bc_fcp_st: Option<Cents>,
899 p_fcp_st: Option<Rate>,
901 v_fcp_st: Option<Cents>,
903 v_icms_deson: Option<Cents>,
905 mot_des_icms: Option<String>,
907 ind_deduz_deson: Option<String>,
909 v_icms_st_deson: Option<Cents>,
911 mot_des_icms_st: Option<String>,
913 },
914}
915
916impl IcmsCst {
917 pub fn cst_code(&self) -> &str {
919 match self {
920 Self::Cst00 { .. } => "00",
921 Self::Cst02 { .. } => "02",
922 Self::Cst10 { .. } => "10",
923 Self::Cst15 { .. } => "15",
924 Self::Cst20 { .. } => "20",
925 Self::Cst30 { .. } => "30",
926 Self::Cst40 { .. } => "40",
927 Self::Cst41 { .. } => "41",
928 Self::Cst50 { .. } => "50",
929 Self::Cst51 { .. } => "51",
930 Self::Cst53 { .. } => "53",
931 Self::Cst60 { .. } => "60",
932 Self::Cst61 { .. } => "61",
933 Self::Cst70 { .. } => "70",
934 Self::Cst90 { .. } => "90",
935 }
936 }
937}
938
939pub fn build_icms_cst_xml(
952 cst: &IcmsCst,
953 totals: &mut IcmsTotals,
954) -> Result<(String, Vec<TaxField>), FiscalError> {
955 match cst {
956 IcmsCst::Cst00 {
957 orig,
958 mod_bc,
959 v_bc,
960 p_icms,
961 v_icms,
962 p_fcp,
963 v_fcp,
964 } => {
965 totals.v_bc = accum(totals.v_bc, Some(*v_bc));
966 totals.v_icms = accum(totals.v_icms, Some(*v_icms));
967 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
968 let fields = filter_fields(vec![
969 Some(TaxField::new("orig", orig.as_str())),
970 Some(TaxField::new("CST", "00")),
971 Some(TaxField::new("modBC", mod_bc.as_str())),
972 Some(TaxField::new("vBC", fc2(Some(*v_bc)).unwrap())),
973 Some(TaxField::new("pICMS", fc4(Some(*p_icms)).unwrap())),
974 Some(TaxField::new("vICMS", fc2(Some(*v_icms)).unwrap())),
975 optional_field("pFCP", fc4(*p_fcp).as_deref()),
976 optional_field("vFCP", fc2(*v_fcp).as_deref()),
977 ]);
978 Ok(("ICMS00".to_string(), fields))
979 }
980
981 IcmsCst::Cst02 {
982 orig,
983 q_bc_mono,
984 ad_rem_icms,
985 v_icms_mono,
986 } => {
987 totals.q_bc_mono = accum_raw(totals.q_bc_mono, *q_bc_mono);
988 totals.v_icms_mono = accum(totals.v_icms_mono, Some(*v_icms_mono));
989 let fields = filter_fields(vec![
990 Some(TaxField::new("orig", orig.as_str())),
991 Some(TaxField::new("CST", "02")),
992 optional_field("qBCMono", fc4_raw(*q_bc_mono).as_deref()),
993 Some(TaxField::new("adRemICMS", fc4(Some(*ad_rem_icms)).unwrap())),
994 Some(TaxField::new("vICMSMono", fc2(Some(*v_icms_mono)).unwrap())),
995 ]);
996 Ok(("ICMS02".to_string(), fields))
997 }
998
999 IcmsCst::Cst10 {
1000 orig,
1001 mod_bc,
1002 v_bc,
1003 p_icms,
1004 v_icms,
1005 v_bc_fcp,
1006 p_fcp,
1007 v_fcp,
1008 mod_bc_st,
1009 p_mva_st,
1010 p_red_bc_st,
1011 v_bc_st,
1012 p_icms_st,
1013 v_icms_st,
1014 v_bc_fcp_st,
1015 p_fcp_st,
1016 v_fcp_st,
1017 v_icms_st_deson,
1018 mot_des_icms_st,
1019 } => {
1020 totals.v_bc = accum(totals.v_bc, Some(*v_bc));
1021 totals.v_icms = accum(totals.v_icms, Some(*v_icms));
1022 totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
1023 totals.v_st = accum(totals.v_st, Some(*v_icms_st));
1024 totals.v_fcp_st = accum(totals.v_fcp_st, *v_fcp_st);
1025 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
1026 let mut fields_opt: Vec<Option<TaxField>> = vec![
1027 Some(TaxField::new("orig", orig.as_str())),
1028 Some(TaxField::new("CST", "10")),
1029 Some(TaxField::new("modBC", mod_bc.as_str())),
1030 Some(TaxField::new("vBC", fc2(Some(*v_bc)).unwrap())),
1031 Some(TaxField::new("pICMS", fc4(Some(*p_icms)).unwrap())),
1032 Some(TaxField::new("vICMS", fc2(Some(*v_icms)).unwrap())),
1033 ];
1034 fields_opt.push(optional_field("vBCFCP", fc2(*v_bc_fcp).as_deref()));
1036 fields_opt.push(optional_field("pFCP", fc4(*p_fcp).as_deref()));
1037 fields_opt.push(optional_field("vFCP", fc2(*v_fcp).as_deref()));
1038 fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
1040 if let Some(v) = p_mva_st {
1041 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
1042 }
1043 if let Some(v) = p_red_bc_st {
1044 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
1045 }
1046 fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
1047 fields_opt.push(Some(TaxField::new(
1048 "pICMSST",
1049 fc4(Some(*p_icms_st)).unwrap(),
1050 )));
1051 fields_opt.push(Some(TaxField::new(
1052 "vICMSST",
1053 fc2(Some(*v_icms_st)).unwrap(),
1054 )));
1055 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1057 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1058 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1059 fields_opt.push(optional_field(
1061 "vICMSSTDeson",
1062 fc2(*v_icms_st_deson).as_deref(),
1063 ));
1064 fields_opt.push(optional_field("motDesICMSST", mot_des_icms_st.as_deref()));
1065 Ok(("ICMS10".to_string(), filter_fields(fields_opt)))
1066 }
1067
1068 IcmsCst::Cst15 {
1069 orig,
1070 q_bc_mono,
1071 ad_rem_icms,
1072 v_icms_mono,
1073 q_bc_mono_reten,
1074 ad_rem_icms_reten,
1075 v_icms_mono_reten,
1076 p_red_ad_rem,
1077 mot_red_ad_rem,
1078 } => {
1079 totals.q_bc_mono = accum_raw(totals.q_bc_mono, *q_bc_mono);
1080 totals.v_icms_mono = accum(totals.v_icms_mono, Some(*v_icms_mono));
1081 totals.q_bc_mono_reten = accum_raw(totals.q_bc_mono_reten, *q_bc_mono_reten);
1082 totals.v_icms_mono_reten = accum(totals.v_icms_mono_reten, Some(*v_icms_mono_reten));
1083 let mut fields = filter_fields(vec![
1084 Some(TaxField::new("orig", orig.as_str())),
1085 Some(TaxField::new("CST", "15")),
1086 optional_field("qBCMono", fc4_raw(*q_bc_mono).as_deref()),
1087 Some(TaxField::new("adRemICMS", fc4(Some(*ad_rem_icms)).unwrap())),
1088 Some(TaxField::new("vICMSMono", fc2(Some(*v_icms_mono)).unwrap())),
1089 optional_field("qBCMonoReten", fc4_raw(*q_bc_mono_reten).as_deref()),
1090 Some(TaxField::new(
1091 "adRemICMSReten",
1092 fc4(Some(*ad_rem_icms_reten)).unwrap(),
1093 )),
1094 Some(TaxField::new(
1095 "vICMSMonoReten",
1096 fc2(Some(*v_icms_mono_reten)).unwrap(),
1097 )),
1098 ]);
1099 if p_red_ad_rem.is_some() {
1100 fields.push(TaxField::new("pRedAdRem", fc4(*p_red_ad_rem).unwrap()));
1101 fields.push(required_field("motRedAdRem", mot_red_ad_rem.as_deref())?);
1102 }
1103 Ok(("ICMS15".to_string(), fields))
1104 }
1105
1106 IcmsCst::Cst20 {
1107 orig,
1108 mod_bc,
1109 p_red_bc,
1110 v_bc,
1111 p_icms,
1112 v_icms,
1113 v_bc_fcp,
1114 p_fcp,
1115 v_fcp,
1116 v_icms_deson,
1117 mot_des_icms,
1118 ind_deduz_deson,
1119 } => {
1120 totals.v_icms_deson = accum(totals.v_icms_deson, *v_icms_deson);
1121 totals.v_bc = accum(totals.v_bc, Some(*v_bc));
1122 totals.v_icms = accum(totals.v_icms, Some(*v_icms));
1123 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
1124 let mut fields_opt: Vec<Option<TaxField>> = vec![
1125 Some(TaxField::new("orig", orig.as_str())),
1126 Some(TaxField::new("CST", "20")),
1127 Some(TaxField::new("modBC", mod_bc.as_str())),
1128 Some(TaxField::new("pRedBC", fc4(Some(*p_red_bc)).unwrap())),
1129 Some(TaxField::new("vBC", fc2(Some(*v_bc)).unwrap())),
1130 Some(TaxField::new("pICMS", fc4(Some(*p_icms)).unwrap())),
1131 Some(TaxField::new("vICMS", fc2(Some(*v_icms)).unwrap())),
1132 ];
1133 fields_opt.push(optional_field("vBCFCP", fc2(*v_bc_fcp).as_deref()));
1135 fields_opt.push(optional_field("pFCP", fc4(*p_fcp).as_deref()));
1136 fields_opt.push(optional_field("vFCP", fc2(*v_fcp).as_deref()));
1137 fields_opt.push(optional_field("vICMSDeson", fc2(*v_icms_deson).as_deref()));
1139 fields_opt.push(optional_field("motDesICMS", mot_des_icms.as_deref()));
1140 fields_opt.push(optional_field("indDeduzDeson", ind_deduz_deson.as_deref()));
1141 Ok(("ICMS20".to_string(), filter_fields(fields_opt)))
1142 }
1143
1144 IcmsCst::Cst30 {
1145 orig,
1146 mod_bc_st,
1147 p_mva_st,
1148 p_red_bc_st,
1149 v_bc_st,
1150 p_icms_st,
1151 v_icms_st,
1152 v_bc_fcp_st,
1153 p_fcp_st,
1154 v_fcp_st,
1155 v_icms_deson,
1156 mot_des_icms,
1157 ind_deduz_deson,
1158 } => {
1159 totals.v_icms_deson = accum(totals.v_icms_deson, *v_icms_deson);
1160 totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
1161 totals.v_st = accum(totals.v_st, Some(*v_icms_st));
1162 totals.v_fcp_st = accum(totals.v_fcp_st, *v_fcp_st);
1163 let mut fields_opt: Vec<Option<TaxField>> = vec![
1164 Some(TaxField::new("orig", orig.as_str())),
1165 Some(TaxField::new("CST", "30")),
1166 ];
1167 fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
1169 if let Some(v) = p_mva_st {
1170 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
1171 }
1172 if let Some(v) = p_red_bc_st {
1173 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
1174 }
1175 fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
1176 fields_opt.push(Some(TaxField::new(
1177 "pICMSST",
1178 fc4(Some(*p_icms_st)).unwrap(),
1179 )));
1180 fields_opt.push(Some(TaxField::new(
1181 "vICMSST",
1182 fc2(Some(*v_icms_st)).unwrap(),
1183 )));
1184 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1186 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1187 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1188 fields_opt.push(optional_field("vICMSDeson", fc2(*v_icms_deson).as_deref()));
1190 fields_opt.push(optional_field("motDesICMS", mot_des_icms.as_deref()));
1191 fields_opt.push(optional_field("indDeduzDeson", ind_deduz_deson.as_deref()));
1192 Ok(("ICMS30".to_string(), filter_fields(fields_opt)))
1193 }
1194
1195 IcmsCst::Cst40 {
1196 orig,
1197 v_icms_deson,
1198 mot_des_icms,
1199 ind_deduz_deson,
1200 }
1201 | IcmsCst::Cst41 {
1202 orig,
1203 v_icms_deson,
1204 mot_des_icms,
1205 ind_deduz_deson,
1206 }
1207 | IcmsCst::Cst50 {
1208 orig,
1209 v_icms_deson,
1210 mot_des_icms,
1211 ind_deduz_deson,
1212 } => {
1213 totals.v_icms_deson = accum(totals.v_icms_deson, *v_icms_deson);
1214 let mut fields_opt: Vec<Option<TaxField>> = vec![
1215 Some(TaxField::new("orig", orig.as_str())),
1216 Some(TaxField::new("CST", cst.cst_code())),
1217 ];
1218 fields_opt.push(optional_field("vICMSDeson", fc2(*v_icms_deson).as_deref()));
1220 fields_opt.push(optional_field("motDesICMS", mot_des_icms.as_deref()));
1221 fields_opt.push(optional_field("indDeduzDeson", ind_deduz_deson.as_deref()));
1222 Ok(("ICMS40".to_string(), filter_fields(fields_opt)))
1223 }
1224
1225 IcmsCst::Cst51 {
1226 orig,
1227 mod_bc,
1228 p_red_bc,
1229 c_benef_rbc,
1230 v_bc,
1231 p_icms,
1232 v_icms_op,
1233 p_dif,
1234 v_icms_dif,
1235 v_icms,
1236 v_bc_fcp,
1237 p_fcp,
1238 v_fcp,
1239 p_fcp_dif,
1240 v_fcp_dif,
1241 v_fcp_efet,
1242 } => {
1243 totals.v_bc = accum(totals.v_bc, *v_bc);
1244 totals.v_icms = accum(totals.v_icms, *v_icms);
1245 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
1246 let fields_opt: Vec<Option<TaxField>> = vec![
1247 Some(TaxField::new("orig", orig.as_str())),
1248 Some(TaxField::new("CST", "51")),
1249 optional_field("modBC", mod_bc.as_deref()),
1250 optional_field("pRedBC", fc4(*p_red_bc).as_deref()),
1251 optional_field("cBenefRBC", c_benef_rbc.as_deref()),
1252 optional_field("vBC", fc2(*v_bc).as_deref()),
1253 optional_field("pICMS", fc4(*p_icms).as_deref()),
1254 optional_field("vICMSOp", fc2(*v_icms_op).as_deref()),
1255 optional_field("pDif", fc4(*p_dif).as_deref()),
1256 optional_field("vICMSDif", fc2(*v_icms_dif).as_deref()),
1257 optional_field("vICMS", fc2(*v_icms).as_deref()),
1258 optional_field("vBCFCP", fc2(*v_bc_fcp).as_deref()),
1259 optional_field("pFCP", fc4(*p_fcp).as_deref()),
1260 optional_field("vFCP", fc2(*v_fcp).as_deref()),
1261 optional_field("pFCPDif", fc4(*p_fcp_dif).as_deref()),
1262 optional_field("vFCPDif", fc2(*v_fcp_dif).as_deref()),
1263 optional_field("vFCPEfet", fc2(*v_fcp_efet).as_deref()),
1264 ];
1265 Ok(("ICMS51".to_string(), filter_fields(fields_opt)))
1266 }
1267
1268 IcmsCst::Cst53 {
1269 orig,
1270 q_bc_mono,
1271 ad_rem_icms,
1272 v_icms_mono_op,
1273 p_dif,
1274 v_icms_mono_dif,
1275 v_icms_mono,
1276 } => {
1277 totals.q_bc_mono = accum_raw(totals.q_bc_mono, *q_bc_mono);
1278 totals.v_icms_mono = accum(totals.v_icms_mono, *v_icms_mono);
1279 totals.q_bc_mono_reten = accum_raw(totals.q_bc_mono_reten, None);
1280 totals.v_icms_mono_reten = accum(totals.v_icms_mono_reten, None);
1281 let fields_opt: Vec<Option<TaxField>> = vec![
1282 Some(TaxField::new("orig", orig.as_str())),
1283 Some(TaxField::new("CST", "53")),
1284 optional_field("qBCMono", fc4_raw(*q_bc_mono).as_deref()),
1285 optional_field("adRemICMS", fc4(*ad_rem_icms).as_deref()),
1286 optional_field("vICMSMonoOp", fc2(*v_icms_mono_op).as_deref()),
1287 optional_field("pDif", fc4(*p_dif).as_deref()),
1288 optional_field("vICMSMonoDif", fc2(*v_icms_mono_dif).as_deref()),
1289 optional_field("vICMSMono", fc2(*v_icms_mono).as_deref()),
1290 ];
1291 Ok(("ICMS53".to_string(), filter_fields(fields_opt)))
1292 }
1293
1294 IcmsCst::Cst60 {
1295 orig,
1296 v_bc_st_ret,
1297 p_st,
1298 v_icms_substituto,
1299 v_icms_st_ret,
1300 v_bc_fcp_st_ret,
1301 p_fcp_st_ret,
1302 v_fcp_st_ret,
1303 p_red_bc_efet,
1304 v_bc_efet,
1305 p_icms_efet,
1306 v_icms_efet,
1307 } => {
1308 totals.v_fcp_st_ret = accum(totals.v_fcp_st_ret, *v_fcp_st_ret);
1309 let fields_opt: Vec<Option<TaxField>> = vec![
1310 Some(TaxField::new("orig", orig.as_str())),
1311 Some(TaxField::new("CST", "60")),
1312 optional_field("vBCSTRet", fc2(*v_bc_st_ret).as_deref()),
1313 optional_field("pST", fc4(*p_st).as_deref()),
1314 optional_field("vICMSSubstituto", fc2(*v_icms_substituto).as_deref()),
1315 optional_field("vICMSSTRet", fc2(*v_icms_st_ret).as_deref()),
1316 optional_field("vBCFCPSTRet", fc2(*v_bc_fcp_st_ret).as_deref()),
1317 optional_field("pFCPSTRet", fc4(*p_fcp_st_ret).as_deref()),
1318 optional_field("vFCPSTRet", fc2(*v_fcp_st_ret).as_deref()),
1319 optional_field("pRedBCEfet", fc4(*p_red_bc_efet).as_deref()),
1320 optional_field("vBCEfet", fc2(*v_bc_efet).as_deref()),
1321 optional_field("pICMSEfet", fc4(*p_icms_efet).as_deref()),
1322 optional_field("vICMSEfet", fc2(*v_icms_efet).as_deref()),
1323 ];
1324 Ok(("ICMS60".to_string(), filter_fields(fields_opt)))
1325 }
1326
1327 IcmsCst::Cst61 {
1328 orig,
1329 q_bc_mono_ret,
1330 ad_rem_icms_ret,
1331 v_icms_mono_ret,
1332 } => {
1333 totals.q_bc_mono_ret = accum_raw(totals.q_bc_mono_ret, *q_bc_mono_ret);
1334 totals.v_icms_mono_ret = accum(totals.v_icms_mono_ret, Some(*v_icms_mono_ret));
1335 let fields = filter_fields(vec![
1336 Some(TaxField::new("orig", orig.as_str())),
1337 Some(TaxField::new("CST", "61")),
1338 optional_field("qBCMonoRet", fc4_raw(*q_bc_mono_ret).as_deref()),
1339 Some(TaxField::new(
1340 "adRemICMSRet",
1341 fc4(Some(*ad_rem_icms_ret)).unwrap(),
1342 )),
1343 Some(TaxField::new(
1344 "vICMSMonoRet",
1345 fc2(Some(*v_icms_mono_ret)).unwrap(),
1346 )),
1347 ]);
1348 Ok(("ICMS61".to_string(), fields))
1349 }
1350
1351 IcmsCst::Cst70 {
1352 orig,
1353 mod_bc,
1354 p_red_bc,
1355 v_bc,
1356 p_icms,
1357 v_icms,
1358 v_bc_fcp,
1359 p_fcp,
1360 v_fcp,
1361 mod_bc_st,
1362 p_mva_st,
1363 p_red_bc_st,
1364 v_bc_st,
1365 p_icms_st,
1366 v_icms_st,
1367 v_bc_fcp_st,
1368 p_fcp_st,
1369 v_fcp_st,
1370 v_icms_deson,
1371 mot_des_icms,
1372 ind_deduz_deson,
1373 v_icms_st_deson,
1374 mot_des_icms_st,
1375 } => {
1376 totals.v_icms_deson = accum(totals.v_icms_deson, *v_icms_deson);
1377 totals.v_bc = accum(totals.v_bc, Some(*v_bc));
1378 totals.v_icms = accum(totals.v_icms, Some(*v_icms));
1379 totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
1380 totals.v_st = accum(totals.v_st, Some(*v_icms_st));
1381 totals.v_fcp_st = accum(totals.v_fcp_st, *v_fcp_st);
1382 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
1383 let mut fields_opt: Vec<Option<TaxField>> = vec![
1384 Some(TaxField::new("orig", orig.as_str())),
1385 Some(TaxField::new("CST", "70")),
1386 Some(TaxField::new("modBC", mod_bc.as_str())),
1387 Some(TaxField::new("pRedBC", fc4(Some(*p_red_bc)).unwrap())),
1388 Some(TaxField::new("vBC", fc2(Some(*v_bc)).unwrap())),
1389 Some(TaxField::new("pICMS", fc4(Some(*p_icms)).unwrap())),
1390 Some(TaxField::new("vICMS", fc2(Some(*v_icms)).unwrap())),
1391 ];
1392 fields_opt.push(optional_field("vBCFCP", fc2(*v_bc_fcp).as_deref()));
1394 fields_opt.push(optional_field("pFCP", fc4(*p_fcp).as_deref()));
1395 fields_opt.push(optional_field("vFCP", fc2(*v_fcp).as_deref()));
1396 fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
1398 if let Some(v) = p_mva_st {
1399 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
1400 }
1401 if let Some(v) = p_red_bc_st {
1402 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
1403 }
1404 fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
1405 fields_opt.push(Some(TaxField::new(
1406 "pICMSST",
1407 fc4(Some(*p_icms_st)).unwrap(),
1408 )));
1409 fields_opt.push(Some(TaxField::new(
1410 "vICMSST",
1411 fc2(Some(*v_icms_st)).unwrap(),
1412 )));
1413 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1415 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1416 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1417 fields_opt.push(optional_field("vICMSDeson", fc2(*v_icms_deson).as_deref()));
1419 fields_opt.push(optional_field("motDesICMS", mot_des_icms.as_deref()));
1420 fields_opt.push(optional_field("indDeduzDeson", ind_deduz_deson.as_deref()));
1421 fields_opt.push(optional_field(
1423 "vICMSSTDeson",
1424 fc2(*v_icms_st_deson).as_deref(),
1425 ));
1426 fields_opt.push(optional_field("motDesICMSST", mot_des_icms_st.as_deref()));
1427 Ok(("ICMS70".to_string(), filter_fields(fields_opt)))
1428 }
1429
1430 IcmsCst::Cst90 {
1431 orig,
1432 mod_bc,
1433 v_bc,
1434 p_red_bc,
1435 c_benef_rbc,
1436 p_icms,
1437 v_icms_op,
1438 p_dif,
1439 v_icms_dif,
1440 v_icms,
1441 v_bc_fcp,
1442 p_fcp,
1443 v_fcp,
1444 p_fcp_dif,
1445 v_fcp_dif,
1446 v_fcp_efet,
1447 mod_bc_st,
1448 p_mva_st,
1449 p_red_bc_st,
1450 v_bc_st,
1451 p_icms_st,
1452 v_icms_st,
1453 v_bc_fcp_st,
1454 p_fcp_st,
1455 v_fcp_st,
1456 v_icms_deson,
1457 mot_des_icms,
1458 ind_deduz_deson,
1459 v_icms_st_deson,
1460 mot_des_icms_st,
1461 } => {
1462 totals.v_icms_deson = accum(totals.v_icms_deson, *v_icms_deson);
1463 totals.v_bc = accum(totals.v_bc, *v_bc);
1464 totals.v_icms = accum(totals.v_icms, *v_icms);
1465 totals.v_bc_st = accum(totals.v_bc_st, *v_bc_st);
1466 totals.v_st = accum(totals.v_st, *v_icms_st);
1467 totals.v_fcp_st = accum(totals.v_fcp_st, *v_fcp_st);
1468 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
1469 let mut fields_opt: Vec<Option<TaxField>> = vec![
1470 Some(TaxField::new("orig", orig.as_str())),
1471 Some(TaxField::new("CST", "90")),
1472 optional_field("modBC", mod_bc.as_deref()),
1473 optional_field("vBC", fc2(*v_bc).as_deref()),
1474 optional_field("pRedBC", fc4(*p_red_bc).as_deref()),
1475 optional_field("cBenefRBC", c_benef_rbc.as_deref()),
1476 optional_field("pICMS", fc4(*p_icms).as_deref()),
1477 optional_field("vICMSOp", fc2(*v_icms_op).as_deref()),
1478 optional_field("pDif", fc4(*p_dif).as_deref()),
1479 optional_field("vICMSDif", fc2(*v_icms_dif).as_deref()),
1480 optional_field("vICMS", fc2(*v_icms).as_deref()),
1481 ];
1482 fields_opt.push(optional_field("vBCFCP", fc2(*v_bc_fcp).as_deref()));
1484 fields_opt.push(optional_field("pFCP", fc4(*p_fcp).as_deref()));
1485 fields_opt.push(optional_field("vFCP", fc2(*v_fcp).as_deref()));
1486 fields_opt.push(optional_field("pFCPDif", fc4(*p_fcp_dif).as_deref()));
1488 fields_opt.push(optional_field("vFCPDif", fc2(*v_fcp_dif).as_deref()));
1489 fields_opt.push(optional_field("vFCPEfet", fc2(*v_fcp_efet).as_deref()));
1490 fields_opt.push(optional_field("modBCST", mod_bc_st.as_deref()));
1492 fields_opt.push(optional_field("pMVAST", fc4(*p_mva_st).as_deref()));
1493 fields_opt.push(optional_field("pRedBCST", fc4(*p_red_bc_st).as_deref()));
1494 fields_opt.push(optional_field("vBCST", fc2(*v_bc_st).as_deref()));
1495 fields_opt.push(optional_field("pICMSST", fc4(*p_icms_st).as_deref()));
1496 fields_opt.push(optional_field("vICMSST", fc2(*v_icms_st).as_deref()));
1497 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1499 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1500 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1501 fields_opt.push(optional_field("vICMSDeson", fc2(*v_icms_deson).as_deref()));
1503 fields_opt.push(optional_field("motDesICMS", mot_des_icms.as_deref()));
1504 fields_opt.push(optional_field("indDeduzDeson", ind_deduz_deson.as_deref()));
1505 fields_opt.push(optional_field(
1507 "vICMSSTDeson",
1508 fc2(*v_icms_st_deson).as_deref(),
1509 ));
1510 fields_opt.push(optional_field("motDesICMSST", mot_des_icms_st.as_deref()));
1511 Ok(("ICMS90".to_string(), filter_fields(fields_opt)))
1512 }
1513 }
1514}
1515
1516#[derive(Debug, Clone)]
1526#[non_exhaustive]
1527pub enum IcmsCsosn {
1528 Csosn101 {
1530 orig: String,
1532 csosn: String,
1534 p_cred_sn: Rate,
1536 v_cred_icms_sn: Cents,
1538 },
1539 Csosn102 {
1542 orig: String,
1544 csosn: String,
1546 },
1547 Csosn201 {
1550 orig: String,
1552 csosn: String,
1554 mod_bc_st: String,
1556 p_mva_st: Option<Rate>,
1558 p_red_bc_st: Option<Rate>,
1560 v_bc_st: Cents,
1562 p_icms_st: Rate,
1564 v_icms_st: Cents,
1566 v_bc_fcp_st: Option<Cents>,
1568 p_fcp_st: Option<Rate>,
1570 v_fcp_st: Option<Cents>,
1572 p_cred_sn: Option<Rate>,
1574 v_cred_icms_sn: Option<Cents>,
1576 },
1577 Csosn202 {
1580 orig: String,
1582 csosn: String,
1584 mod_bc_st: String,
1586 p_mva_st: Option<Rate>,
1588 p_red_bc_st: Option<Rate>,
1590 v_bc_st: Cents,
1592 p_icms_st: Rate,
1594 v_icms_st: Cents,
1596 v_bc_fcp_st: Option<Cents>,
1598 p_fcp_st: Option<Rate>,
1600 v_fcp_st: Option<Cents>,
1602 },
1603 Csosn500 {
1605 orig: String,
1607 csosn: String,
1609 v_bc_st_ret: Option<Cents>,
1611 p_st: Option<Rate>,
1613 v_icms_substituto: Option<Cents>,
1615 v_icms_st_ret: Option<Cents>,
1617 v_bc_fcp_st_ret: Option<Cents>,
1619 p_fcp_st_ret: Option<Rate>,
1621 v_fcp_st_ret: Option<Cents>,
1623 p_red_bc_efet: Option<Rate>,
1625 v_bc_efet: Option<Cents>,
1627 p_icms_efet: Option<Rate>,
1629 v_icms_efet: Option<Cents>,
1631 },
1632 Csosn900 {
1634 orig: String,
1636 csosn: String,
1638 mod_bc: Option<String>,
1640 v_bc: Option<Cents>,
1642 p_red_bc: Option<Rate>,
1644 p_icms: Option<Rate>,
1646 v_icms: Option<Cents>,
1648 mod_bc_st: Option<String>,
1650 p_mva_st: Option<Rate>,
1652 p_red_bc_st: Option<Rate>,
1654 v_bc_st: Option<Cents>,
1656 p_icms_st: Option<Rate>,
1658 v_icms_st: Option<Cents>,
1660 v_bc_fcp_st: Option<Cents>,
1662 p_fcp_st: Option<Rate>,
1664 v_fcp_st: Option<Cents>,
1666 p_cred_sn: Option<Rate>,
1668 v_cred_icms_sn: Option<Cents>,
1670 },
1671}
1672
1673impl IcmsCsosn {
1674 pub fn csosn_code(&self) -> &str {
1676 match self {
1677 Self::Csosn101 { csosn, .. } => csosn.as_str(),
1678 Self::Csosn102 { csosn, .. } => csosn.as_str(),
1679 Self::Csosn201 { csosn, .. } => csosn.as_str(),
1680 Self::Csosn202 { csosn, .. } => csosn.as_str(),
1681 Self::Csosn500 { csosn, .. } => csosn.as_str(),
1682 Self::Csosn900 { csosn, .. } => csosn.as_str(),
1683 }
1684 }
1685}
1686
1687pub fn build_icms_csosn_xml(
1700 csosn: &IcmsCsosn,
1701 totals: &mut IcmsTotals,
1702) -> Result<(String, Vec<TaxField>), FiscalError> {
1703 match csosn {
1704 IcmsCsosn::Csosn101 {
1705 orig,
1706 csosn,
1707 p_cred_sn,
1708 v_cred_icms_sn,
1709 } => {
1710 let fields = filter_fields(vec![
1711 Some(TaxField::new("orig", orig.as_str())),
1712 Some(TaxField::new("CSOSN", csosn.as_str())),
1713 Some(TaxField::new("pCredSN", fc4(Some(*p_cred_sn)).unwrap())),
1714 Some(TaxField::new(
1715 "vCredICMSSN",
1716 fc2(Some(*v_cred_icms_sn)).unwrap(),
1717 )),
1718 ]);
1719 Ok(("ICMSSN101".to_string(), fields))
1720 }
1721
1722 IcmsCsosn::Csosn102 { orig, csosn } => {
1723 let orig_val = if orig.is_empty() {
1724 None
1725 } else {
1726 Some(orig.as_str())
1727 };
1728 let fields = filter_fields(vec![
1729 optional_field("orig", orig_val),
1730 Some(TaxField::new("CSOSN", csosn.as_str())),
1731 ]);
1732 Ok(("ICMSSN102".to_string(), fields))
1733 }
1734
1735 IcmsCsosn::Csosn201 {
1736 orig,
1737 csosn,
1738 mod_bc_st,
1739 p_mva_st,
1740 p_red_bc_st,
1741 v_bc_st,
1742 p_icms_st,
1743 v_icms_st,
1744 v_bc_fcp_st,
1745 p_fcp_st,
1746 v_fcp_st,
1747 p_cred_sn,
1748 v_cred_icms_sn,
1749 } => {
1750 totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
1751 totals.v_st = accum(totals.v_st, Some(*v_icms_st));
1752
1753 let mut fields_opt: Vec<Option<TaxField>> = vec![
1754 Some(TaxField::new("orig", orig.as_str())),
1755 Some(TaxField::new("CSOSN", csosn.as_str())),
1756 ];
1757 fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
1759 if let Some(v) = p_mva_st {
1760 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
1761 }
1762 if let Some(v) = p_red_bc_st {
1763 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
1764 }
1765 fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
1766 fields_opt.push(Some(TaxField::new(
1767 "pICMSST",
1768 fc4(Some(*p_icms_st)).unwrap(),
1769 )));
1770 fields_opt.push(Some(TaxField::new(
1771 "vICMSST",
1772 fc2(Some(*v_icms_st)).unwrap(),
1773 )));
1774 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1776 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1777 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1778 fields_opt.push(optional_field("pCredSN", fc4(*p_cred_sn).as_deref()));
1780 fields_opt.push(optional_field(
1781 "vCredICMSSN",
1782 fc2(*v_cred_icms_sn).as_deref(),
1783 ));
1784 Ok(("ICMSSN201".to_string(), filter_fields(fields_opt)))
1785 }
1786
1787 IcmsCsosn::Csosn202 {
1788 orig,
1789 csosn,
1790 mod_bc_st,
1791 p_mva_st,
1792 p_red_bc_st,
1793 v_bc_st,
1794 p_icms_st,
1795 v_icms_st,
1796 v_bc_fcp_st,
1797 p_fcp_st,
1798 v_fcp_st,
1799 } => {
1800 totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
1801 totals.v_st = accum(totals.v_st, Some(*v_icms_st));
1802
1803 let mut fields_opt: Vec<Option<TaxField>> = vec![
1804 Some(TaxField::new("orig", orig.as_str())),
1805 Some(TaxField::new("CSOSN", csosn.as_str())),
1806 ];
1807 fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
1809 if let Some(v) = p_mva_st {
1810 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
1811 }
1812 if let Some(v) = p_red_bc_st {
1813 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
1814 }
1815 fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
1816 fields_opt.push(Some(TaxField::new(
1817 "pICMSST",
1818 fc4(Some(*p_icms_st)).unwrap(),
1819 )));
1820 fields_opt.push(Some(TaxField::new(
1821 "vICMSST",
1822 fc2(Some(*v_icms_st)).unwrap(),
1823 )));
1824 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1826 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1827 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1828 Ok(("ICMSSN202".to_string(), filter_fields(fields_opt)))
1829 }
1830
1831 IcmsCsosn::Csosn500 {
1832 orig,
1833 csosn,
1834 v_bc_st_ret,
1835 p_st,
1836 v_icms_substituto,
1837 v_icms_st_ret,
1838 v_bc_fcp_st_ret,
1839 p_fcp_st_ret,
1840 v_fcp_st_ret,
1841 p_red_bc_efet,
1842 v_bc_efet,
1843 p_icms_efet,
1844 v_icms_efet,
1845 } => {
1846 let fields = filter_fields(vec![
1847 Some(TaxField::new("orig", orig.as_str())),
1848 Some(TaxField::new("CSOSN", csosn.as_str())),
1849 optional_field("vBCSTRet", fc2(*v_bc_st_ret).as_deref()),
1850 optional_field("pST", fc4(*p_st).as_deref()),
1851 optional_field("vICMSSubstituto", fc2(*v_icms_substituto).as_deref()),
1852 optional_field("vICMSSTRet", fc2(*v_icms_st_ret).as_deref()),
1853 optional_field("vBCFCPSTRet", fc2(*v_bc_fcp_st_ret).as_deref()),
1854 optional_field("pFCPSTRet", fc4(*p_fcp_st_ret).as_deref()),
1855 optional_field("vFCPSTRet", fc2(*v_fcp_st_ret).as_deref()),
1856 optional_field("pRedBCEfet", fc4(*p_red_bc_efet).as_deref()),
1857 optional_field("vBCEfet", fc2(*v_bc_efet).as_deref()),
1858 optional_field("pICMSEfet", fc4(*p_icms_efet).as_deref()),
1859 optional_field("vICMSEfet", fc2(*v_icms_efet).as_deref()),
1860 ]);
1861 Ok(("ICMSSN500".to_string(), fields))
1862 }
1863
1864 IcmsCsosn::Csosn900 {
1865 orig,
1866 csosn,
1867 mod_bc,
1868 v_bc,
1869 p_red_bc,
1870 p_icms,
1871 v_icms,
1872 mod_bc_st,
1873 p_mva_st,
1874 p_red_bc_st,
1875 v_bc_st,
1876 p_icms_st,
1877 v_icms_st,
1878 v_bc_fcp_st,
1879 p_fcp_st,
1880 v_fcp_st,
1881 p_cred_sn,
1882 v_cred_icms_sn,
1883 } => {
1884 totals.v_bc = accum(totals.v_bc, *v_bc);
1885 totals.v_icms = accum(totals.v_icms, *v_icms);
1886 totals.v_bc_st = accum(totals.v_bc_st, *v_bc_st);
1887 totals.v_st = accum(totals.v_st, *v_icms_st);
1888
1889 let orig_val = if orig.is_empty() {
1890 None
1891 } else {
1892 Some(orig.as_str())
1893 };
1894 let mut fields_opt: Vec<Option<TaxField>> = vec![
1895 optional_field("orig", orig_val),
1896 Some(TaxField::new("CSOSN", csosn.as_str())),
1897 optional_field("modBC", mod_bc.as_deref()),
1898 optional_field("vBC", fc2(*v_bc).as_deref()),
1899 optional_field("pRedBC", fc4(*p_red_bc).as_deref()),
1900 optional_field("pICMS", fc4(*p_icms).as_deref()),
1901 optional_field("vICMS", fc2(*v_icms).as_deref()),
1902 optional_field("modBCST", mod_bc_st.as_deref()),
1904 optional_field("pMVAST", fc4(*p_mva_st).as_deref()),
1905 optional_field("pRedBCST", fc4(*p_red_bc_st).as_deref()),
1906 optional_field("vBCST", fc2(*v_bc_st).as_deref()),
1907 optional_field("pICMSST", fc4(*p_icms_st).as_deref()),
1908 optional_field("vICMSST", fc2(*v_icms_st).as_deref()),
1909 ];
1910 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1912 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1913 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1914 fields_opt.push(optional_field("pCredSN", fc4(*p_cred_sn).as_deref()));
1916 fields_opt.push(optional_field(
1917 "vCredICMSSN",
1918 fc2(*v_cred_icms_sn).as_deref(),
1919 ));
1920 Ok(("ICMSSN900".to_string(), filter_fields(fields_opt)))
1921 }
1922 }
1923}
1924
1925fn fc2(v: Option<Cents>) -> Option<String> {
1929 format_cents_or_none(v.map(|c| c.0), 2)
1930}
1931
1932fn fc4(v: Option<Rate>) -> Option<String> {
1934 format_cents_or_none(v.map(|r| r.0), 4)
1935}
1936
1937fn fc4_raw(v: Option<i64>) -> Option<String> {
1939 format_cents_or_none(v, 4)
1940}
1941
1942pub fn build_icms_xml(
1955 variant: &IcmsVariant,
1956 totals: &mut IcmsTotals,
1957) -> Result<String, FiscalError> {
1958 let (variant_tag, fields) = match variant {
1959 IcmsVariant::Cst(cst) => build_icms_cst_xml(cst, totals)?,
1960 IcmsVariant::Csosn(csosn) => build_icms_csosn_xml(csosn, totals)?,
1961 };
1962
1963 let element = TaxElement {
1964 outer_tag: Some("ICMS".to_string()),
1965 outer_fields: vec![],
1966 variant_tag,
1967 fields,
1968 };
1969
1970 Ok(serialize_tax_element(&element))
1971}
1972
1973pub fn build_icms_part_xml(data: &IcmsPartData) -> Result<(String, IcmsTotals), FiscalError> {
1982 let mut totals = create_icms_totals();
1983 totals.v_bc = accum(totals.v_bc, Some(data.v_bc));
1984 totals.v_icms = accum(totals.v_icms, Some(data.v_icms));
1985 totals.v_bc_st = accum(totals.v_bc_st, Some(data.v_bc_st));
1986 totals.v_st = accum(totals.v_st, Some(data.v_icms_st));
1987
1988 let mut fields_opt: Vec<Option<TaxField>> = vec![
1989 Some(TaxField::new("orig", data.orig.as_str())),
1990 Some(TaxField::new("CST", data.cst.as_str())),
1991 Some(TaxField::new("modBC", data.mod_bc.as_str())),
1992 Some(TaxField::new("vBC", fc2(Some(data.v_bc)).unwrap())),
1993 optional_field("pRedBC", fc4(data.p_red_bc).as_deref()),
1994 Some(TaxField::new("pICMS", fc4(Some(data.p_icms)).unwrap())),
1995 Some(TaxField::new("vICMS", fc2(Some(data.v_icms)).unwrap())),
1996 ];
1997
1998 fields_opt.push(Some(TaxField::new("modBCST", data.mod_bc_st.as_str())));
2000 if let Some(v) = data.p_mva_st {
2001 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(v)).unwrap())));
2002 }
2003 if let Some(v) = data.p_red_bc_st {
2004 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(v)).unwrap())));
2005 }
2006 fields_opt.push(Some(TaxField::new(
2007 "vBCST",
2008 fc2(Some(data.v_bc_st)).unwrap(),
2009 )));
2010 fields_opt.push(Some(TaxField::new(
2011 "pICMSST",
2012 fc4(Some(data.p_icms_st)).unwrap(),
2013 )));
2014 fields_opt.push(Some(TaxField::new(
2015 "vICMSST",
2016 fc2(Some(data.v_icms_st)).unwrap(),
2017 )));
2018
2019 fields_opt.push(optional_field("vBCFCPST", fc2(data.v_bc_fcp_st).as_deref()));
2021 fields_opt.push(optional_field("pFCPST", fc4(data.p_fcp_st).as_deref()));
2022 fields_opt.push(optional_field("vFCPST", fc2(data.v_fcp_st).as_deref()));
2023
2024 fields_opt.push(Some(TaxField::new(
2026 "pBCOp",
2027 fc4(Some(data.p_bc_op)).unwrap(),
2028 )));
2029 fields_opt.push(Some(TaxField::new("UFST", data.uf_st.as_str())));
2030
2031 fields_opt.push(optional_field(
2033 "vICMSDeson",
2034 fc2(data.v_icms_deson).as_deref(),
2035 ));
2036 fields_opt.push(optional_field("motDesICMS", data.mot_des_icms.as_deref()));
2037 fields_opt.push(optional_field(
2038 "indDeduzDeson",
2039 data.ind_deduz_deson.as_deref(),
2040 ));
2041
2042 let fields = filter_fields(fields_opt);
2043
2044 let element = TaxElement {
2045 outer_tag: Some("ICMS".to_string()),
2046 outer_fields: vec![],
2047 variant_tag: "ICMSPart".to_string(),
2048 fields,
2049 };
2050
2051 Ok((serialize_tax_element(&element), totals))
2052}
2053
2054pub fn build_icms_st_xml(data: &IcmsStData) -> Result<(String, IcmsTotals), FiscalError> {
2062 let mut totals = create_icms_totals();
2063 totals.v_fcp_st_ret = accum(totals.v_fcp_st_ret, data.v_fcp_st_ret);
2064
2065 let fields_opt: Vec<Option<TaxField>> = vec![
2066 Some(TaxField::new("orig", data.orig.as_str())),
2067 Some(TaxField::new("CST", data.cst.as_str())),
2068 Some(TaxField::new(
2069 "vBCSTRet",
2070 fc2(Some(data.v_bc_st_ret)).unwrap(),
2071 )),
2072 optional_field("pST", fc4(data.p_st).as_deref()),
2073 optional_field("vICMSSubstituto", fc2(data.v_icms_substituto).as_deref()),
2074 Some(TaxField::new(
2075 "vICMSSTRet",
2076 fc2(Some(data.v_icms_st_ret)).unwrap(),
2077 )),
2078 optional_field("vBCFCPSTRet", fc2(data.v_bc_fcp_st_ret).as_deref()),
2079 optional_field("pFCPSTRet", fc4(data.p_fcp_st_ret).as_deref()),
2080 optional_field("vFCPSTRet", fc2(data.v_fcp_st_ret).as_deref()),
2081 Some(TaxField::new(
2082 "vBCSTDest",
2083 fc2(Some(data.v_bc_st_dest)).unwrap(),
2084 )),
2085 Some(TaxField::new(
2086 "vICMSSTDest",
2087 fc2(Some(data.v_icms_st_dest)).unwrap(),
2088 )),
2089 optional_field("pRedBCEfet", fc4(data.p_red_bc_efet).as_deref()),
2090 optional_field("vBCEfet", fc2(data.v_bc_efet).as_deref()),
2091 optional_field("pICMSEfet", fc4(data.p_icms_efet).as_deref()),
2092 optional_field("vICMSEfet", fc2(data.v_icms_efet).as_deref()),
2093 ];
2094
2095 let fields = filter_fields(fields_opt);
2096
2097 let element = TaxElement {
2098 outer_tag: Some("ICMS".to_string()),
2099 outer_fields: vec![],
2100 variant_tag: "ICMSST".to_string(),
2101 fields,
2102 };
2103
2104 Ok((serialize_tax_element(&element), totals))
2105}
2106
2107pub fn build_icms_uf_dest_xml(data: &IcmsUfDestData) -> Result<(String, IcmsTotals), FiscalError> {
2115 let mut totals = create_icms_totals();
2116 totals.v_icms_uf_dest = accum(totals.v_icms_uf_dest, Some(data.v_icms_uf_dest));
2117 totals.v_fcp_uf_dest = accum(totals.v_fcp_uf_dest, data.v_fcp_uf_dest);
2118 totals.v_icms_uf_remet = accum(totals.v_icms_uf_remet, data.v_icms_uf_remet);
2119
2120 let fields_opt: Vec<Option<TaxField>> = vec![
2121 Some(TaxField::new(
2122 "vBCUFDest",
2123 fc2(Some(data.v_bc_uf_dest)).unwrap(),
2124 )),
2125 optional_field("vBCFCPUFDest", fc2(data.v_bc_fcp_uf_dest).as_deref()),
2126 optional_field("pFCPUFDest", fc4(data.p_fcp_uf_dest).as_deref()),
2127 Some(TaxField::new(
2128 "pICMSUFDest",
2129 fc4(Some(data.p_icms_uf_dest)).unwrap(),
2130 )),
2131 Some(TaxField::new(
2132 "pICMSInter",
2133 fc4(Some(data.p_icms_inter)).unwrap(),
2134 )),
2135 Some(TaxField::new("pICMSInterPart", "100.0000")),
2136 optional_field("vFCPUFDest", fc2(data.v_fcp_uf_dest).as_deref()),
2137 Some(TaxField::new(
2138 "vICMSUFDest",
2139 fc2(Some(data.v_icms_uf_dest)).unwrap(),
2140 )),
2141 Some(TaxField::new(
2142 "vICMSUFRemet",
2143 fc2(Some(data.v_icms_uf_remet.unwrap_or(Cents(0)))).unwrap(),
2144 )),
2145 ];
2146
2147 let fields = filter_fields(fields_opt);
2148
2149 let element = TaxElement {
2150 outer_tag: None,
2151 outer_fields: vec![],
2152 variant_tag: "ICMSUFDest".to_string(),
2153 fields,
2154 };
2155
2156 Ok((serialize_tax_element(&element), totals))
2157}
2158
2159pub fn merge_icms_totals(target: &mut IcmsTotals, source: &IcmsTotals) {
2166 target.v_bc += source.v_bc;
2167 target.v_icms += source.v_icms;
2168 target.v_icms_deson += source.v_icms_deson;
2169 target.v_bc_st += source.v_bc_st;
2170 target.v_st += source.v_st;
2171 target.v_fcp += source.v_fcp;
2172 target.v_fcp_st += source.v_fcp_st;
2173 target.v_fcp_st_ret += source.v_fcp_st_ret;
2174 target.v_fcp_uf_dest += source.v_fcp_uf_dest;
2175 target.v_icms_uf_dest += source.v_icms_uf_dest;
2176 target.v_icms_uf_remet += source.v_icms_uf_remet;
2177 target.q_bc_mono += source.q_bc_mono;
2178 target.v_icms_mono += source.v_icms_mono;
2179 target.q_bc_mono_reten += source.q_bc_mono_reten;
2180 target.v_icms_mono_reten += source.v_icms_mono_reten;
2181 target.q_bc_mono_ret += source.q_bc_mono_ret;
2182 target.v_icms_mono_ret += source.v_icms_mono_ret;
2183}