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 pub ind_deduz_deson: bool,
429}
430
431impl IcmsTotals {
432 pub fn new() -> Self {
434 Self::default()
435 }
436 pub fn v_bc(mut self, v: Cents) -> Self {
438 self.v_bc = v;
439 self
440 }
441 pub fn v_icms(mut self, v: Cents) -> Self {
443 self.v_icms = v;
444 self
445 }
446 pub fn v_icms_deson(mut self, v: Cents) -> Self {
448 self.v_icms_deson = v;
449 self
450 }
451 pub fn v_bc_st(mut self, v: Cents) -> Self {
453 self.v_bc_st = v;
454 self
455 }
456 pub fn v_st(mut self, v: Cents) -> Self {
458 self.v_st = v;
459 self
460 }
461 pub fn v_fcp(mut self, v: Cents) -> Self {
463 self.v_fcp = v;
464 self
465 }
466 pub fn v_fcp_st(mut self, v: Cents) -> Self {
468 self.v_fcp_st = v;
469 self
470 }
471 pub fn v_fcp_st_ret(mut self, v: Cents) -> Self {
473 self.v_fcp_st_ret = v;
474 self
475 }
476 pub fn v_fcp_uf_dest(mut self, v: Cents) -> Self {
478 self.v_fcp_uf_dest = v;
479 self
480 }
481 pub fn v_icms_uf_dest(mut self, v: Cents) -> Self {
483 self.v_icms_uf_dest = v;
484 self
485 }
486 pub fn v_icms_uf_remet(mut self, v: Cents) -> Self {
488 self.v_icms_uf_remet = v;
489 self
490 }
491 pub fn v_icms_mono(mut self, v: Cents) -> Self {
493 self.v_icms_mono = v;
494 self
495 }
496 pub fn v_icms_mono_reten(mut self, v: Cents) -> Self {
498 self.v_icms_mono_reten = v;
499 self
500 }
501 pub fn v_icms_mono_ret(mut self, v: Cents) -> Self {
503 self.v_icms_mono_ret = v;
504 self
505 }
506 pub fn ind_deduz_deson(mut self, v: bool) -> Self {
510 self.ind_deduz_deson = v;
511 self
512 }
513}
514
515pub fn create_icms_totals() -> IcmsTotals {
529 IcmsTotals::default()
530}
531
532#[derive(Debug, Clone)]
542#[non_exhaustive]
543pub enum IcmsCst {
544 Cst00 {
546 orig: String,
548 mod_bc: String,
550 v_bc: Cents,
552 p_icms: Rate,
554 v_icms: Cents,
556 p_fcp: Option<Rate>,
558 v_fcp: Option<Cents>,
560 },
561 Cst02 {
563 orig: String,
565 q_bc_mono: Option<i64>,
567 ad_rem_icms: Rate,
569 v_icms_mono: Cents,
571 },
572 Cst10 {
574 orig: String,
576 mod_bc: String,
578 v_bc: Cents,
580 p_icms: Rate,
582 v_icms: Cents,
584 v_bc_fcp: Option<Cents>,
586 p_fcp: Option<Rate>,
588 v_fcp: Option<Cents>,
590 mod_bc_st: String,
592 p_mva_st: Option<Rate>,
594 p_red_bc_st: Option<Rate>,
596 v_bc_st: Cents,
598 p_icms_st: Rate,
600 v_icms_st: Cents,
602 v_bc_fcp_st: Option<Cents>,
604 p_fcp_st: Option<Rate>,
606 v_fcp_st: Option<Cents>,
608 v_icms_st_deson: Option<Cents>,
610 mot_des_icms_st: Option<String>,
612 },
613 Cst15 {
616 orig: String,
618 q_bc_mono: Option<i64>,
620 ad_rem_icms: Rate,
622 v_icms_mono: Cents,
624 q_bc_mono_reten: Option<i64>,
626 ad_rem_icms_reten: Rate,
628 v_icms_mono_reten: Cents,
630 p_red_ad_rem: Option<Rate>,
632 mot_red_ad_rem: Option<String>,
634 },
635 Cst20 {
637 orig: String,
639 mod_bc: String,
641 p_red_bc: Rate,
643 v_bc: Cents,
645 p_icms: Rate,
647 v_icms: Cents,
649 v_bc_fcp: Option<Cents>,
651 p_fcp: Option<Rate>,
653 v_fcp: Option<Cents>,
655 v_icms_deson: Option<Cents>,
657 mot_des_icms: Option<String>,
659 ind_deduz_deson: Option<String>,
661 },
662 Cst30 {
664 orig: String,
666 mod_bc_st: String,
668 p_mva_st: Option<Rate>,
670 p_red_bc_st: Option<Rate>,
672 v_bc_st: Cents,
674 p_icms_st: Rate,
676 v_icms_st: Cents,
678 v_bc_fcp_st: Option<Cents>,
680 p_fcp_st: Option<Rate>,
682 v_fcp_st: Option<Cents>,
684 v_icms_deson: Option<Cents>,
686 mot_des_icms: Option<String>,
688 ind_deduz_deson: Option<String>,
690 },
691 Cst40 {
693 orig: String,
695 v_icms_deson: Option<Cents>,
697 mot_des_icms: Option<String>,
699 ind_deduz_deson: Option<String>,
701 },
702 Cst41 {
704 orig: String,
706 v_icms_deson: Option<Cents>,
708 mot_des_icms: Option<String>,
710 ind_deduz_deson: Option<String>,
712 },
713 Cst50 {
715 orig: String,
717 v_icms_deson: Option<Cents>,
719 mot_des_icms: Option<String>,
721 ind_deduz_deson: Option<String>,
723 },
724 Cst51 {
726 orig: String,
728 mod_bc: Option<String>,
730 p_red_bc: Option<Rate>,
732 c_benef_rbc: Option<String>,
734 v_bc: Option<Cents>,
736 p_icms: Option<Rate>,
738 v_icms_op: Option<Cents>,
740 p_dif: Option<Rate>,
742 v_icms_dif: Option<Cents>,
744 v_icms: Option<Cents>,
746 v_bc_fcp: Option<Cents>,
748 p_fcp: Option<Rate>,
750 v_fcp: Option<Cents>,
752 p_fcp_dif: Option<Rate>,
754 v_fcp_dif: Option<Cents>,
756 v_fcp_efet: Option<Cents>,
758 },
759 Cst53 {
762 orig: String,
764 q_bc_mono: Option<i64>,
766 ad_rem_icms: Option<Rate>,
768 v_icms_mono_op: Option<Cents>,
770 p_dif: Option<Rate>,
772 v_icms_mono_dif: Option<Cents>,
774 v_icms_mono: Option<Cents>,
776 },
777 Cst60 {
779 orig: String,
781 v_bc_st_ret: Option<Cents>,
783 p_st: Option<Rate>,
785 v_icms_substituto: Option<Cents>,
787 v_icms_st_ret: Option<Cents>,
789 v_bc_fcp_st_ret: Option<Cents>,
791 p_fcp_st_ret: Option<Rate>,
793 v_fcp_st_ret: Option<Cents>,
795 p_red_bc_efet: Option<Rate>,
797 v_bc_efet: Option<Cents>,
799 p_icms_efet: Option<Rate>,
801 v_icms_efet: Option<Cents>,
803 },
804 Cst61 {
806 orig: String,
808 q_bc_mono_ret: Option<i64>,
810 ad_rem_icms_ret: Rate,
812 v_icms_mono_ret: Cents,
814 },
815 Cst70 {
817 orig: String,
819 mod_bc: String,
821 p_red_bc: Rate,
823 v_bc: Cents,
825 p_icms: Rate,
827 v_icms: Cents,
829 v_bc_fcp: Option<Cents>,
831 p_fcp: Option<Rate>,
833 v_fcp: Option<Cents>,
835 mod_bc_st: String,
837 p_mva_st: Option<Rate>,
839 p_red_bc_st: Option<Rate>,
841 v_bc_st: Cents,
843 p_icms_st: Rate,
845 v_icms_st: Cents,
847 v_bc_fcp_st: Option<Cents>,
849 p_fcp_st: Option<Rate>,
851 v_fcp_st: Option<Cents>,
853 v_icms_deson: Option<Cents>,
855 mot_des_icms: Option<String>,
857 ind_deduz_deson: Option<String>,
859 v_icms_st_deson: Option<Cents>,
861 mot_des_icms_st: Option<String>,
863 },
864 Cst90 {
866 orig: String,
868 mod_bc: Option<String>,
870 v_bc: Option<Cents>,
872 p_red_bc: Option<Rate>,
874 c_benef_rbc: Option<String>,
876 p_icms: Option<Rate>,
878 v_icms_op: Option<Cents>,
880 p_dif: Option<Rate>,
882 v_icms_dif: Option<Cents>,
884 v_icms: Option<Cents>,
886 v_bc_fcp: Option<Cents>,
888 p_fcp: Option<Rate>,
890 v_fcp: Option<Cents>,
892 p_fcp_dif: Option<Rate>,
894 v_fcp_dif: Option<Cents>,
896 v_fcp_efet: Option<Cents>,
898 mod_bc_st: Option<String>,
900 p_mva_st: Option<Rate>,
902 p_red_bc_st: Option<Rate>,
904 v_bc_st: Option<Cents>,
906 p_icms_st: Option<Rate>,
908 v_icms_st: Option<Cents>,
910 v_bc_fcp_st: Option<Cents>,
912 p_fcp_st: Option<Rate>,
914 v_fcp_st: Option<Cents>,
916 v_icms_deson: Option<Cents>,
918 mot_des_icms: Option<String>,
920 ind_deduz_deson: Option<String>,
922 v_icms_st_deson: Option<Cents>,
924 mot_des_icms_st: Option<String>,
926 },
927}
928
929impl IcmsCst {
930 pub fn cst_code(&self) -> &str {
932 match self {
933 Self::Cst00 { .. } => "00",
934 Self::Cst02 { .. } => "02",
935 Self::Cst10 { .. } => "10",
936 Self::Cst15 { .. } => "15",
937 Self::Cst20 { .. } => "20",
938 Self::Cst30 { .. } => "30",
939 Self::Cst40 { .. } => "40",
940 Self::Cst41 { .. } => "41",
941 Self::Cst50 { .. } => "50",
942 Self::Cst51 { .. } => "51",
943 Self::Cst53 { .. } => "53",
944 Self::Cst60 { .. } => "60",
945 Self::Cst61 { .. } => "61",
946 Self::Cst70 { .. } => "70",
947 Self::Cst90 { .. } => "90",
948 }
949 }
950}
951
952pub fn build_icms_cst_xml(
965 cst: &IcmsCst,
966 totals: &mut IcmsTotals,
967) -> Result<(String, Vec<TaxField>), FiscalError> {
968 match cst {
969 IcmsCst::Cst00 {
970 orig,
971 mod_bc,
972 v_bc,
973 p_icms,
974 v_icms,
975 p_fcp,
976 v_fcp,
977 } => {
978 totals.v_bc = accum(totals.v_bc, Some(*v_bc));
979 totals.v_icms = accum(totals.v_icms, Some(*v_icms));
980 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
981 let fields = filter_fields(vec![
982 Some(TaxField::new("orig", orig.as_str())),
983 Some(TaxField::new("CST", "00")),
984 Some(TaxField::new("modBC", mod_bc.as_str())),
985 Some(TaxField::new("vBC", fc2(Some(*v_bc)).unwrap())),
986 Some(TaxField::new("pICMS", fc4(Some(*p_icms)).unwrap())),
987 Some(TaxField::new("vICMS", fc2(Some(*v_icms)).unwrap())),
988 optional_field("pFCP", fc4(*p_fcp).as_deref()),
989 optional_field("vFCP", fc2(*v_fcp).as_deref()),
990 ]);
991 Ok(("ICMS00".to_string(), fields))
992 }
993
994 IcmsCst::Cst02 {
995 orig,
996 q_bc_mono,
997 ad_rem_icms,
998 v_icms_mono,
999 } => {
1000 totals.q_bc_mono = accum_raw(totals.q_bc_mono, *q_bc_mono);
1001 totals.v_icms_mono = accum(totals.v_icms_mono, Some(*v_icms_mono));
1002 let fields = filter_fields(vec![
1003 Some(TaxField::new("orig", orig.as_str())),
1004 Some(TaxField::new("CST", "02")),
1005 optional_field("qBCMono", fc4_raw(*q_bc_mono).as_deref()),
1006 Some(TaxField::new("adRemICMS", fc4(Some(*ad_rem_icms)).unwrap())),
1007 Some(TaxField::new("vICMSMono", fc2(Some(*v_icms_mono)).unwrap())),
1008 ]);
1009 Ok(("ICMS02".to_string(), fields))
1010 }
1011
1012 IcmsCst::Cst10 {
1013 orig,
1014 mod_bc,
1015 v_bc,
1016 p_icms,
1017 v_icms,
1018 v_bc_fcp,
1019 p_fcp,
1020 v_fcp,
1021 mod_bc_st,
1022 p_mva_st,
1023 p_red_bc_st,
1024 v_bc_st,
1025 p_icms_st,
1026 v_icms_st,
1027 v_bc_fcp_st,
1028 p_fcp_st,
1029 v_fcp_st,
1030 v_icms_st_deson,
1031 mot_des_icms_st,
1032 } => {
1033 totals.v_bc = accum(totals.v_bc, Some(*v_bc));
1034 totals.v_icms = accum(totals.v_icms, Some(*v_icms));
1035 totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
1036 totals.v_st = accum(totals.v_st, Some(*v_icms_st));
1037 totals.v_fcp_st = accum(totals.v_fcp_st, *v_fcp_st);
1038 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
1039 let mut fields_opt: Vec<Option<TaxField>> = vec![
1040 Some(TaxField::new("orig", orig.as_str())),
1041 Some(TaxField::new("CST", "10")),
1042 Some(TaxField::new("modBC", mod_bc.as_str())),
1043 Some(TaxField::new("vBC", fc2(Some(*v_bc)).unwrap())),
1044 Some(TaxField::new("pICMS", fc4(Some(*p_icms)).unwrap())),
1045 Some(TaxField::new("vICMS", fc2(Some(*v_icms)).unwrap())),
1046 ];
1047 fields_opt.push(optional_field("vBCFCP", fc2(*v_bc_fcp).as_deref()));
1049 fields_opt.push(optional_field("pFCP", fc4(*p_fcp).as_deref()));
1050 fields_opt.push(optional_field("vFCP", fc2(*v_fcp).as_deref()));
1051 fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
1053 if let Some(v) = p_mva_st {
1054 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
1055 }
1056 if let Some(v) = p_red_bc_st {
1057 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
1058 }
1059 fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
1060 fields_opt.push(Some(TaxField::new(
1061 "pICMSST",
1062 fc4(Some(*p_icms_st)).unwrap(),
1063 )));
1064 fields_opt.push(Some(TaxField::new(
1065 "vICMSST",
1066 fc2(Some(*v_icms_st)).unwrap(),
1067 )));
1068 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1070 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1071 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1072 fields_opt.push(optional_field(
1074 "vICMSSTDeson",
1075 fc2(*v_icms_st_deson).as_deref(),
1076 ));
1077 fields_opt.push(optional_field("motDesICMSST", mot_des_icms_st.as_deref()));
1078 Ok(("ICMS10".to_string(), filter_fields(fields_opt)))
1079 }
1080
1081 IcmsCst::Cst15 {
1082 orig,
1083 q_bc_mono,
1084 ad_rem_icms,
1085 v_icms_mono,
1086 q_bc_mono_reten,
1087 ad_rem_icms_reten,
1088 v_icms_mono_reten,
1089 p_red_ad_rem,
1090 mot_red_ad_rem,
1091 } => {
1092 totals.q_bc_mono = accum_raw(totals.q_bc_mono, *q_bc_mono);
1093 totals.v_icms_mono = accum(totals.v_icms_mono, Some(*v_icms_mono));
1094 totals.q_bc_mono_reten = accum_raw(totals.q_bc_mono_reten, *q_bc_mono_reten);
1095 totals.v_icms_mono_reten = accum(totals.v_icms_mono_reten, Some(*v_icms_mono_reten));
1096 let mut fields = filter_fields(vec![
1097 Some(TaxField::new("orig", orig.as_str())),
1098 Some(TaxField::new("CST", "15")),
1099 optional_field("qBCMono", fc4_raw(*q_bc_mono).as_deref()),
1100 Some(TaxField::new("adRemICMS", fc4(Some(*ad_rem_icms)).unwrap())),
1101 Some(TaxField::new("vICMSMono", fc2(Some(*v_icms_mono)).unwrap())),
1102 optional_field("qBCMonoReten", fc4_raw(*q_bc_mono_reten).as_deref()),
1103 Some(TaxField::new(
1104 "adRemICMSReten",
1105 fc4(Some(*ad_rem_icms_reten)).unwrap(),
1106 )),
1107 Some(TaxField::new(
1108 "vICMSMonoReten",
1109 fc2(Some(*v_icms_mono_reten)).unwrap(),
1110 )),
1111 ]);
1112 if p_red_ad_rem.is_some() {
1113 fields.push(TaxField::new("pRedAdRem", fc4(*p_red_ad_rem).unwrap()));
1114 fields.push(required_field("motRedAdRem", mot_red_ad_rem.as_deref())?);
1115 }
1116 Ok(("ICMS15".to_string(), fields))
1117 }
1118
1119 IcmsCst::Cst20 {
1120 orig,
1121 mod_bc,
1122 p_red_bc,
1123 v_bc,
1124 p_icms,
1125 v_icms,
1126 v_bc_fcp,
1127 p_fcp,
1128 v_fcp,
1129 v_icms_deson,
1130 mot_des_icms,
1131 ind_deduz_deson,
1132 } => {
1133 totals.v_icms_deson = accum(totals.v_icms_deson, *v_icms_deson);
1134 if ind_deduz_deson.as_deref() == Some("1") {
1135 totals.ind_deduz_deson = true;
1136 }
1137 totals.v_bc = accum(totals.v_bc, Some(*v_bc));
1138 totals.v_icms = accum(totals.v_icms, Some(*v_icms));
1139 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
1140 let mut fields_opt: Vec<Option<TaxField>> = vec![
1141 Some(TaxField::new("orig", orig.as_str())),
1142 Some(TaxField::new("CST", "20")),
1143 Some(TaxField::new("modBC", mod_bc.as_str())),
1144 Some(TaxField::new("pRedBC", fc4(Some(*p_red_bc)).unwrap())),
1145 Some(TaxField::new("vBC", fc2(Some(*v_bc)).unwrap())),
1146 Some(TaxField::new("pICMS", fc4(Some(*p_icms)).unwrap())),
1147 Some(TaxField::new("vICMS", fc2(Some(*v_icms)).unwrap())),
1148 ];
1149 fields_opt.push(optional_field("vBCFCP", fc2(*v_bc_fcp).as_deref()));
1151 fields_opt.push(optional_field("pFCP", fc4(*p_fcp).as_deref()));
1152 fields_opt.push(optional_field("vFCP", fc2(*v_fcp).as_deref()));
1153 fields_opt.push(optional_field("vICMSDeson", fc2(*v_icms_deson).as_deref()));
1155 fields_opt.push(optional_field("motDesICMS", mot_des_icms.as_deref()));
1156 fields_opt.push(optional_field("indDeduzDeson", ind_deduz_deson.as_deref()));
1157 Ok(("ICMS20".to_string(), filter_fields(fields_opt)))
1158 }
1159
1160 IcmsCst::Cst30 {
1161 orig,
1162 mod_bc_st,
1163 p_mva_st,
1164 p_red_bc_st,
1165 v_bc_st,
1166 p_icms_st,
1167 v_icms_st,
1168 v_bc_fcp_st,
1169 p_fcp_st,
1170 v_fcp_st,
1171 v_icms_deson,
1172 mot_des_icms,
1173 ind_deduz_deson,
1174 } => {
1175 totals.v_icms_deson = accum(totals.v_icms_deson, *v_icms_deson);
1176 if ind_deduz_deson.as_deref() == Some("1") {
1177 totals.ind_deduz_deson = true;
1178 }
1179 totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
1180 totals.v_st = accum(totals.v_st, Some(*v_icms_st));
1181 totals.v_fcp_st = accum(totals.v_fcp_st, *v_fcp_st);
1182 let mut fields_opt: Vec<Option<TaxField>> = vec![
1183 Some(TaxField::new("orig", orig.as_str())),
1184 Some(TaxField::new("CST", "30")),
1185 ];
1186 fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
1188 if let Some(v) = p_mva_st {
1189 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
1190 }
1191 if let Some(v) = p_red_bc_st {
1192 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
1193 }
1194 fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
1195 fields_opt.push(Some(TaxField::new(
1196 "pICMSST",
1197 fc4(Some(*p_icms_st)).unwrap(),
1198 )));
1199 fields_opt.push(Some(TaxField::new(
1200 "vICMSST",
1201 fc2(Some(*v_icms_st)).unwrap(),
1202 )));
1203 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1205 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1206 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1207 fields_opt.push(optional_field("vICMSDeson", fc2(*v_icms_deson).as_deref()));
1209 fields_opt.push(optional_field("motDesICMS", mot_des_icms.as_deref()));
1210 fields_opt.push(optional_field("indDeduzDeson", ind_deduz_deson.as_deref()));
1211 Ok(("ICMS30".to_string(), filter_fields(fields_opt)))
1212 }
1213
1214 IcmsCst::Cst40 {
1215 orig,
1216 v_icms_deson,
1217 mot_des_icms,
1218 ind_deduz_deson,
1219 }
1220 | IcmsCst::Cst41 {
1221 orig,
1222 v_icms_deson,
1223 mot_des_icms,
1224 ind_deduz_deson,
1225 }
1226 | IcmsCst::Cst50 {
1227 orig,
1228 v_icms_deson,
1229 mot_des_icms,
1230 ind_deduz_deson,
1231 } => {
1232 totals.v_icms_deson = accum(totals.v_icms_deson, *v_icms_deson);
1233 if ind_deduz_deson.as_deref() == Some("1") {
1234 totals.ind_deduz_deson = true;
1235 }
1236 let mut fields_opt: Vec<Option<TaxField>> = vec![
1237 Some(TaxField::new("orig", orig.as_str())),
1238 Some(TaxField::new("CST", cst.cst_code())),
1239 ];
1240 fields_opt.push(optional_field("vICMSDeson", fc2(*v_icms_deson).as_deref()));
1242 fields_opt.push(optional_field("motDesICMS", mot_des_icms.as_deref()));
1243 fields_opt.push(optional_field("indDeduzDeson", ind_deduz_deson.as_deref()));
1244 Ok(("ICMS40".to_string(), filter_fields(fields_opt)))
1245 }
1246
1247 IcmsCst::Cst51 {
1248 orig,
1249 mod_bc,
1250 p_red_bc,
1251 c_benef_rbc,
1252 v_bc,
1253 p_icms,
1254 v_icms_op,
1255 p_dif,
1256 v_icms_dif,
1257 v_icms,
1258 v_bc_fcp,
1259 p_fcp,
1260 v_fcp,
1261 p_fcp_dif,
1262 v_fcp_dif,
1263 v_fcp_efet,
1264 } => {
1265 totals.v_bc = accum(totals.v_bc, *v_bc);
1266 totals.v_icms = accum(totals.v_icms, *v_icms);
1267 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
1268 let fields_opt: Vec<Option<TaxField>> = vec![
1269 Some(TaxField::new("orig", orig.as_str())),
1270 Some(TaxField::new("CST", "51")),
1271 optional_field("modBC", mod_bc.as_deref()),
1272 optional_field("pRedBC", fc4(*p_red_bc).as_deref()),
1273 optional_field("cBenefRBC", c_benef_rbc.as_deref()),
1274 optional_field("vBC", fc2(*v_bc).as_deref()),
1275 optional_field("pICMS", fc4(*p_icms).as_deref()),
1276 optional_field("vICMSOp", fc2(*v_icms_op).as_deref()),
1277 optional_field("pDif", fc4(*p_dif).as_deref()),
1278 optional_field("vICMSDif", fc2(*v_icms_dif).as_deref()),
1279 optional_field("vICMS", fc2(*v_icms).as_deref()),
1280 optional_field("vBCFCP", fc2(*v_bc_fcp).as_deref()),
1281 optional_field("pFCP", fc4(*p_fcp).as_deref()),
1282 optional_field("vFCP", fc2(*v_fcp).as_deref()),
1283 optional_field("pFCPDif", fc4(*p_fcp_dif).as_deref()),
1284 optional_field("vFCPDif", fc2(*v_fcp_dif).as_deref()),
1285 optional_field("vFCPEfet", fc2(*v_fcp_efet).as_deref()),
1286 ];
1287 Ok(("ICMS51".to_string(), filter_fields(fields_opt)))
1288 }
1289
1290 IcmsCst::Cst53 {
1291 orig,
1292 q_bc_mono,
1293 ad_rem_icms,
1294 v_icms_mono_op,
1295 p_dif,
1296 v_icms_mono_dif,
1297 v_icms_mono,
1298 } => {
1299 totals.q_bc_mono = accum_raw(totals.q_bc_mono, *q_bc_mono);
1300 totals.v_icms_mono = accum(totals.v_icms_mono, *v_icms_mono);
1301 totals.q_bc_mono_reten = accum_raw(totals.q_bc_mono_reten, None);
1302 totals.v_icms_mono_reten = accum(totals.v_icms_mono_reten, None);
1303 let fields_opt: Vec<Option<TaxField>> = vec![
1304 Some(TaxField::new("orig", orig.as_str())),
1305 Some(TaxField::new("CST", "53")),
1306 optional_field("qBCMono", fc4_raw(*q_bc_mono).as_deref()),
1307 optional_field("adRemICMS", fc4(*ad_rem_icms).as_deref()),
1308 optional_field("vICMSMonoOp", fc2(*v_icms_mono_op).as_deref()),
1309 optional_field("pDif", fc4(*p_dif).as_deref()),
1310 optional_field("vICMSMonoDif", fc2(*v_icms_mono_dif).as_deref()),
1311 optional_field("vICMSMono", fc2(*v_icms_mono).as_deref()),
1312 ];
1313 Ok(("ICMS53".to_string(), filter_fields(fields_opt)))
1314 }
1315
1316 IcmsCst::Cst60 {
1317 orig,
1318 v_bc_st_ret,
1319 p_st,
1320 v_icms_substituto,
1321 v_icms_st_ret,
1322 v_bc_fcp_st_ret,
1323 p_fcp_st_ret,
1324 v_fcp_st_ret,
1325 p_red_bc_efet,
1326 v_bc_efet,
1327 p_icms_efet,
1328 v_icms_efet,
1329 } => {
1330 totals.v_fcp_st_ret = accum(totals.v_fcp_st_ret, *v_fcp_st_ret);
1331 let fields_opt: Vec<Option<TaxField>> = vec![
1332 Some(TaxField::new("orig", orig.as_str())),
1333 Some(TaxField::new("CST", "60")),
1334 optional_field("vBCSTRet", fc2(*v_bc_st_ret).as_deref()),
1335 optional_field("pST", fc4(*p_st).as_deref()),
1336 optional_field("vICMSSubstituto", fc2(*v_icms_substituto).as_deref()),
1337 optional_field("vICMSSTRet", fc2(*v_icms_st_ret).as_deref()),
1338 optional_field("vBCFCPSTRet", fc2(*v_bc_fcp_st_ret).as_deref()),
1339 optional_field("pFCPSTRet", fc4(*p_fcp_st_ret).as_deref()),
1340 optional_field("vFCPSTRet", fc2(*v_fcp_st_ret).as_deref()),
1341 optional_field("pRedBCEfet", fc4(*p_red_bc_efet).as_deref()),
1342 optional_field("vBCEfet", fc2(*v_bc_efet).as_deref()),
1343 optional_field("pICMSEfet", fc4(*p_icms_efet).as_deref()),
1344 optional_field("vICMSEfet", fc2(*v_icms_efet).as_deref()),
1345 ];
1346 Ok(("ICMS60".to_string(), filter_fields(fields_opt)))
1347 }
1348
1349 IcmsCst::Cst61 {
1350 orig,
1351 q_bc_mono_ret,
1352 ad_rem_icms_ret,
1353 v_icms_mono_ret,
1354 } => {
1355 totals.q_bc_mono_ret = accum_raw(totals.q_bc_mono_ret, *q_bc_mono_ret);
1356 totals.v_icms_mono_ret = accum(totals.v_icms_mono_ret, Some(*v_icms_mono_ret));
1357 let fields = filter_fields(vec![
1358 Some(TaxField::new("orig", orig.as_str())),
1359 Some(TaxField::new("CST", "61")),
1360 optional_field("qBCMonoRet", fc4_raw(*q_bc_mono_ret).as_deref()),
1361 Some(TaxField::new(
1362 "adRemICMSRet",
1363 fc4(Some(*ad_rem_icms_ret)).unwrap(),
1364 )),
1365 Some(TaxField::new(
1366 "vICMSMonoRet",
1367 fc2(Some(*v_icms_mono_ret)).unwrap(),
1368 )),
1369 ]);
1370 Ok(("ICMS61".to_string(), fields))
1371 }
1372
1373 IcmsCst::Cst70 {
1374 orig,
1375 mod_bc,
1376 p_red_bc,
1377 v_bc,
1378 p_icms,
1379 v_icms,
1380 v_bc_fcp,
1381 p_fcp,
1382 v_fcp,
1383 mod_bc_st,
1384 p_mva_st,
1385 p_red_bc_st,
1386 v_bc_st,
1387 p_icms_st,
1388 v_icms_st,
1389 v_bc_fcp_st,
1390 p_fcp_st,
1391 v_fcp_st,
1392 v_icms_deson,
1393 mot_des_icms,
1394 ind_deduz_deson,
1395 v_icms_st_deson,
1396 mot_des_icms_st,
1397 } => {
1398 totals.v_icms_deson = accum(totals.v_icms_deson, *v_icms_deson);
1399 if ind_deduz_deson.as_deref() == Some("1") {
1400 totals.ind_deduz_deson = true;
1401 }
1402 totals.v_bc = accum(totals.v_bc, Some(*v_bc));
1403 totals.v_icms = accum(totals.v_icms, Some(*v_icms));
1404 totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
1405 totals.v_st = accum(totals.v_st, Some(*v_icms_st));
1406 totals.v_fcp_st = accum(totals.v_fcp_st, *v_fcp_st);
1407 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
1408 let mut fields_opt: Vec<Option<TaxField>> = vec![
1409 Some(TaxField::new("orig", orig.as_str())),
1410 Some(TaxField::new("CST", "70")),
1411 Some(TaxField::new("modBC", mod_bc.as_str())),
1412 Some(TaxField::new("pRedBC", fc4(Some(*p_red_bc)).unwrap())),
1413 Some(TaxField::new("vBC", fc2(Some(*v_bc)).unwrap())),
1414 Some(TaxField::new("pICMS", fc4(Some(*p_icms)).unwrap())),
1415 Some(TaxField::new("vICMS", fc2(Some(*v_icms)).unwrap())),
1416 ];
1417 fields_opt.push(optional_field("vBCFCP", fc2(*v_bc_fcp).as_deref()));
1419 fields_opt.push(optional_field("pFCP", fc4(*p_fcp).as_deref()));
1420 fields_opt.push(optional_field("vFCP", fc2(*v_fcp).as_deref()));
1421 fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
1423 if let Some(v) = p_mva_st {
1424 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
1425 }
1426 if let Some(v) = p_red_bc_st {
1427 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
1428 }
1429 fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
1430 fields_opt.push(Some(TaxField::new(
1431 "pICMSST",
1432 fc4(Some(*p_icms_st)).unwrap(),
1433 )));
1434 fields_opt.push(Some(TaxField::new(
1435 "vICMSST",
1436 fc2(Some(*v_icms_st)).unwrap(),
1437 )));
1438 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1440 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1441 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1442 fields_opt.push(optional_field("vICMSDeson", fc2(*v_icms_deson).as_deref()));
1444 fields_opt.push(optional_field("motDesICMS", mot_des_icms.as_deref()));
1445 fields_opt.push(optional_field("indDeduzDeson", ind_deduz_deson.as_deref()));
1446 fields_opt.push(optional_field(
1448 "vICMSSTDeson",
1449 fc2(*v_icms_st_deson).as_deref(),
1450 ));
1451 fields_opt.push(optional_field("motDesICMSST", mot_des_icms_st.as_deref()));
1452 Ok(("ICMS70".to_string(), filter_fields(fields_opt)))
1453 }
1454
1455 IcmsCst::Cst90 {
1456 orig,
1457 mod_bc,
1458 v_bc,
1459 p_red_bc,
1460 c_benef_rbc,
1461 p_icms,
1462 v_icms_op,
1463 p_dif,
1464 v_icms_dif,
1465 v_icms,
1466 v_bc_fcp,
1467 p_fcp,
1468 v_fcp,
1469 p_fcp_dif,
1470 v_fcp_dif,
1471 v_fcp_efet,
1472 mod_bc_st,
1473 p_mva_st,
1474 p_red_bc_st,
1475 v_bc_st,
1476 p_icms_st,
1477 v_icms_st,
1478 v_bc_fcp_st,
1479 p_fcp_st,
1480 v_fcp_st,
1481 v_icms_deson,
1482 mot_des_icms,
1483 ind_deduz_deson,
1484 v_icms_st_deson,
1485 mot_des_icms_st,
1486 } => {
1487 totals.v_icms_deson = accum(totals.v_icms_deson, *v_icms_deson);
1488 if ind_deduz_deson.as_deref() == Some("1") {
1489 totals.ind_deduz_deson = true;
1490 }
1491 totals.v_bc = accum(totals.v_bc, *v_bc);
1492 totals.v_icms = accum(totals.v_icms, *v_icms);
1493 totals.v_bc_st = accum(totals.v_bc_st, *v_bc_st);
1494 totals.v_st = accum(totals.v_st, *v_icms_st);
1495 totals.v_fcp_st = accum(totals.v_fcp_st, *v_fcp_st);
1496 totals.v_fcp = accum(totals.v_fcp, *v_fcp);
1497 let mut fields_opt: Vec<Option<TaxField>> = vec![
1498 Some(TaxField::new("orig", orig.as_str())),
1499 Some(TaxField::new("CST", "90")),
1500 optional_field("modBC", mod_bc.as_deref()),
1501 optional_field("vBC", fc2(*v_bc).as_deref()),
1502 optional_field("pRedBC", fc4(*p_red_bc).as_deref()),
1503 optional_field("cBenefRBC", c_benef_rbc.as_deref()),
1504 optional_field("pICMS", fc4(*p_icms).as_deref()),
1505 optional_field("vICMSOp", fc2(*v_icms_op).as_deref()),
1506 optional_field("pDif", fc4(*p_dif).as_deref()),
1507 optional_field("vICMSDif", fc2(*v_icms_dif).as_deref()),
1508 optional_field("vICMS", fc2(*v_icms).as_deref()),
1509 ];
1510 fields_opt.push(optional_field("vBCFCP", fc2(*v_bc_fcp).as_deref()));
1512 fields_opt.push(optional_field("pFCP", fc4(*p_fcp).as_deref()));
1513 fields_opt.push(optional_field("vFCP", fc2(*v_fcp).as_deref()));
1514 fields_opt.push(optional_field("pFCPDif", fc4(*p_fcp_dif).as_deref()));
1516 fields_opt.push(optional_field("vFCPDif", fc2(*v_fcp_dif).as_deref()));
1517 fields_opt.push(optional_field("vFCPEfet", fc2(*v_fcp_efet).as_deref()));
1518 fields_opt.push(optional_field("modBCST", mod_bc_st.as_deref()));
1520 fields_opt.push(optional_field("pMVAST", fc4(*p_mva_st).as_deref()));
1521 fields_opt.push(optional_field("pRedBCST", fc4(*p_red_bc_st).as_deref()));
1522 fields_opt.push(optional_field("vBCST", fc2(*v_bc_st).as_deref()));
1523 fields_opt.push(optional_field("pICMSST", fc4(*p_icms_st).as_deref()));
1524 fields_opt.push(optional_field("vICMSST", fc2(*v_icms_st).as_deref()));
1525 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1527 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1528 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1529 fields_opt.push(optional_field("vICMSDeson", fc2(*v_icms_deson).as_deref()));
1531 fields_opt.push(optional_field("motDesICMS", mot_des_icms.as_deref()));
1532 fields_opt.push(optional_field("indDeduzDeson", ind_deduz_deson.as_deref()));
1533 fields_opt.push(optional_field(
1535 "vICMSSTDeson",
1536 fc2(*v_icms_st_deson).as_deref(),
1537 ));
1538 fields_opt.push(optional_field("motDesICMSST", mot_des_icms_st.as_deref()));
1539 Ok(("ICMS90".to_string(), filter_fields(fields_opt)))
1540 }
1541 }
1542}
1543
1544#[derive(Debug, Clone)]
1554#[non_exhaustive]
1555pub enum IcmsCsosn {
1556 Csosn101 {
1558 orig: String,
1560 csosn: String,
1562 p_cred_sn: Rate,
1564 v_cred_icms_sn: Cents,
1566 },
1567 Csosn102 {
1569 orig: String,
1571 csosn: String,
1573 },
1574 Csosn103 {
1577 orig: String,
1579 csosn: String,
1581 },
1582 Csosn300 {
1584 orig: String,
1586 csosn: String,
1588 },
1589 Csosn400 {
1591 orig: String,
1593 csosn: String,
1595 },
1596 Csosn201 {
1599 orig: String,
1601 csosn: String,
1603 mod_bc_st: String,
1605 p_mva_st: Option<Rate>,
1607 p_red_bc_st: Option<Rate>,
1609 v_bc_st: Cents,
1611 p_icms_st: Rate,
1613 v_icms_st: Cents,
1615 v_bc_fcp_st: Option<Cents>,
1617 p_fcp_st: Option<Rate>,
1619 v_fcp_st: Option<Cents>,
1621 p_cred_sn: Option<Rate>,
1623 v_cred_icms_sn: Option<Cents>,
1625 },
1626 Csosn202 {
1629 orig: String,
1631 csosn: String,
1633 mod_bc_st: String,
1635 p_mva_st: Option<Rate>,
1637 p_red_bc_st: Option<Rate>,
1639 v_bc_st: Cents,
1641 p_icms_st: Rate,
1643 v_icms_st: Cents,
1645 v_bc_fcp_st: Option<Cents>,
1647 p_fcp_st: Option<Rate>,
1649 v_fcp_st: Option<Cents>,
1651 },
1652 Csosn203 {
1655 orig: String,
1657 csosn: String,
1659 mod_bc_st: String,
1661 p_mva_st: Option<Rate>,
1663 p_red_bc_st: Option<Rate>,
1665 v_bc_st: Cents,
1667 p_icms_st: Rate,
1669 v_icms_st: Cents,
1671 v_bc_fcp_st: Option<Cents>,
1673 p_fcp_st: Option<Rate>,
1675 v_fcp_st: Option<Cents>,
1677 },
1678 Csosn500 {
1680 orig: String,
1682 csosn: String,
1684 v_bc_st_ret: Option<Cents>,
1686 p_st: Option<Rate>,
1688 v_icms_substituto: Option<Cents>,
1690 v_icms_st_ret: Option<Cents>,
1692 v_bc_fcp_st_ret: Option<Cents>,
1694 p_fcp_st_ret: Option<Rate>,
1696 v_fcp_st_ret: Option<Cents>,
1698 p_red_bc_efet: Option<Rate>,
1700 v_bc_efet: Option<Cents>,
1702 p_icms_efet: Option<Rate>,
1704 v_icms_efet: Option<Cents>,
1706 },
1707 Csosn900 {
1709 orig: String,
1711 csosn: String,
1713 mod_bc: Option<String>,
1715 v_bc: Option<Cents>,
1717 p_red_bc: Option<Rate>,
1719 p_icms: Option<Rate>,
1721 v_icms: Option<Cents>,
1723 mod_bc_st: Option<String>,
1725 p_mva_st: Option<Rate>,
1727 p_red_bc_st: Option<Rate>,
1729 v_bc_st: Option<Cents>,
1731 p_icms_st: Option<Rate>,
1733 v_icms_st: Option<Cents>,
1735 v_bc_fcp_st: Option<Cents>,
1737 p_fcp_st: Option<Rate>,
1739 v_fcp_st: Option<Cents>,
1741 p_cred_sn: Option<Rate>,
1743 v_cred_icms_sn: Option<Cents>,
1745 },
1746}
1747
1748impl IcmsCsosn {
1749 pub fn csosn_code(&self) -> &str {
1751 match self {
1752 Self::Csosn101 { csosn, .. } => csosn.as_str(),
1753 Self::Csosn102 { csosn, .. } => csosn.as_str(),
1754 Self::Csosn103 { csosn, .. } => csosn.as_str(),
1755 Self::Csosn201 { csosn, .. } => csosn.as_str(),
1756 Self::Csosn202 { csosn, .. } => csosn.as_str(),
1757 Self::Csosn203 { csosn, .. } => csosn.as_str(),
1758 Self::Csosn300 { csosn, .. } => csosn.as_str(),
1759 Self::Csosn400 { csosn, .. } => csosn.as_str(),
1760 Self::Csosn500 { csosn, .. } => csosn.as_str(),
1761 Self::Csosn900 { csosn, .. } => csosn.as_str(),
1762 }
1763 }
1764}
1765
1766pub fn build_icms_csosn_xml(
1779 csosn: &IcmsCsosn,
1780 totals: &mut IcmsTotals,
1781) -> Result<(String, Vec<TaxField>), FiscalError> {
1782 match csosn {
1783 IcmsCsosn::Csosn101 {
1784 orig,
1785 csosn,
1786 p_cred_sn,
1787 v_cred_icms_sn,
1788 } => {
1789 let fields = filter_fields(vec![
1790 Some(TaxField::new("orig", orig.as_str())),
1791 Some(TaxField::new("CSOSN", csosn.as_str())),
1792 Some(TaxField::new("pCredSN", fc4(Some(*p_cred_sn)).unwrap())),
1793 Some(TaxField::new(
1794 "vCredICMSSN",
1795 fc2(Some(*v_cred_icms_sn)).unwrap(),
1796 )),
1797 ]);
1798 Ok(("ICMSSN101".to_string(), fields))
1799 }
1800
1801 IcmsCsosn::Csosn102 { orig, csosn }
1802 | IcmsCsosn::Csosn103 { orig, csosn }
1803 | IcmsCsosn::Csosn300 { orig, csosn }
1804 | IcmsCsosn::Csosn400 { orig, csosn } => {
1805 let orig_val = if orig.is_empty() {
1806 None
1807 } else {
1808 Some(orig.as_str())
1809 };
1810 let fields = filter_fields(vec![
1811 optional_field("orig", orig_val),
1812 Some(TaxField::new("CSOSN", csosn.as_str())),
1813 ]);
1814 Ok(("ICMSSN102".to_string(), fields))
1815 }
1816
1817 IcmsCsosn::Csosn201 {
1818 orig,
1819 csosn,
1820 mod_bc_st,
1821 p_mva_st,
1822 p_red_bc_st,
1823 v_bc_st,
1824 p_icms_st,
1825 v_icms_st,
1826 v_bc_fcp_st,
1827 p_fcp_st,
1828 v_fcp_st,
1829 p_cred_sn,
1830 v_cred_icms_sn,
1831 } => {
1832 totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
1833 totals.v_st = accum(totals.v_st, Some(*v_icms_st));
1834
1835 let mut fields_opt: Vec<Option<TaxField>> = vec![
1836 Some(TaxField::new("orig", orig.as_str())),
1837 Some(TaxField::new("CSOSN", csosn.as_str())),
1838 ];
1839 fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
1841 if let Some(v) = p_mva_st {
1842 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
1843 }
1844 if let Some(v) = p_red_bc_st {
1845 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
1846 }
1847 fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
1848 fields_opt.push(Some(TaxField::new(
1849 "pICMSST",
1850 fc4(Some(*p_icms_st)).unwrap(),
1851 )));
1852 fields_opt.push(Some(TaxField::new(
1853 "vICMSST",
1854 fc2(Some(*v_icms_st)).unwrap(),
1855 )));
1856 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1858 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1859 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1860 fields_opt.push(optional_field("pCredSN", fc4(*p_cred_sn).as_deref()));
1862 fields_opt.push(optional_field(
1863 "vCredICMSSN",
1864 fc2(*v_cred_icms_sn).as_deref(),
1865 ));
1866 Ok(("ICMSSN201".to_string(), filter_fields(fields_opt)))
1867 }
1868
1869 IcmsCsosn::Csosn202 {
1870 orig,
1871 csosn,
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 }
1882 | IcmsCsosn::Csosn203 {
1883 orig,
1884 csosn,
1885 mod_bc_st,
1886 p_mva_st,
1887 p_red_bc_st,
1888 v_bc_st,
1889 p_icms_st,
1890 v_icms_st,
1891 v_bc_fcp_st,
1892 p_fcp_st,
1893 v_fcp_st,
1894 } => {
1895 totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
1896 totals.v_st = accum(totals.v_st, Some(*v_icms_st));
1897
1898 let mut fields_opt: Vec<Option<TaxField>> = vec![
1899 Some(TaxField::new("orig", orig.as_str())),
1900 Some(TaxField::new("CSOSN", csosn.as_str())),
1901 ];
1902 fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
1904 if let Some(v) = p_mva_st {
1905 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
1906 }
1907 if let Some(v) = p_red_bc_st {
1908 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
1909 }
1910 fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
1911 fields_opt.push(Some(TaxField::new(
1912 "pICMSST",
1913 fc4(Some(*p_icms_st)).unwrap(),
1914 )));
1915 fields_opt.push(Some(TaxField::new(
1916 "vICMSST",
1917 fc2(Some(*v_icms_st)).unwrap(),
1918 )));
1919 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
1921 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
1922 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
1923 Ok(("ICMSSN202".to_string(), filter_fields(fields_opt)))
1924 }
1925
1926 IcmsCsosn::Csosn500 {
1927 orig,
1928 csosn,
1929 v_bc_st_ret,
1930 p_st,
1931 v_icms_substituto,
1932 v_icms_st_ret,
1933 v_bc_fcp_st_ret,
1934 p_fcp_st_ret,
1935 v_fcp_st_ret,
1936 p_red_bc_efet,
1937 v_bc_efet,
1938 p_icms_efet,
1939 v_icms_efet,
1940 } => {
1941 let fields = filter_fields(vec![
1942 Some(TaxField::new("orig", orig.as_str())),
1943 Some(TaxField::new("CSOSN", csosn.as_str())),
1944 optional_field("vBCSTRet", fc2(*v_bc_st_ret).as_deref()),
1945 optional_field("pST", fc4(*p_st).as_deref()),
1946 optional_field("vICMSSubstituto", fc2(*v_icms_substituto).as_deref()),
1947 optional_field("vICMSSTRet", fc2(*v_icms_st_ret).as_deref()),
1948 optional_field("vBCFCPSTRet", fc2(*v_bc_fcp_st_ret).as_deref()),
1949 optional_field("pFCPSTRet", fc4(*p_fcp_st_ret).as_deref()),
1950 optional_field("vFCPSTRet", fc2(*v_fcp_st_ret).as_deref()),
1951 optional_field("pRedBCEfet", fc4(*p_red_bc_efet).as_deref()),
1952 optional_field("vBCEfet", fc2(*v_bc_efet).as_deref()),
1953 optional_field("pICMSEfet", fc4(*p_icms_efet).as_deref()),
1954 optional_field("vICMSEfet", fc2(*v_icms_efet).as_deref()),
1955 ]);
1956 Ok(("ICMSSN500".to_string(), fields))
1957 }
1958
1959 IcmsCsosn::Csosn900 {
1960 orig,
1961 csosn,
1962 mod_bc,
1963 v_bc,
1964 p_red_bc,
1965 p_icms,
1966 v_icms,
1967 mod_bc_st,
1968 p_mva_st,
1969 p_red_bc_st,
1970 v_bc_st,
1971 p_icms_st,
1972 v_icms_st,
1973 v_bc_fcp_st,
1974 p_fcp_st,
1975 v_fcp_st,
1976 p_cred_sn,
1977 v_cred_icms_sn,
1978 } => {
1979 totals.v_bc = accum(totals.v_bc, *v_bc);
1980 totals.v_icms = accum(totals.v_icms, *v_icms);
1981 totals.v_bc_st = accum(totals.v_bc_st, *v_bc_st);
1982 totals.v_st = accum(totals.v_st, *v_icms_st);
1983
1984 let orig_val = if orig.is_empty() {
1985 None
1986 } else {
1987 Some(orig.as_str())
1988 };
1989 let mut fields_opt: Vec<Option<TaxField>> = vec![
1990 optional_field("orig", orig_val),
1991 Some(TaxField::new("CSOSN", csosn.as_str())),
1992 optional_field("modBC", mod_bc.as_deref()),
1993 optional_field("vBC", fc2(*v_bc).as_deref()),
1994 optional_field("pRedBC", fc4(*p_red_bc).as_deref()),
1995 optional_field("pICMS", fc4(*p_icms).as_deref()),
1996 optional_field("vICMS", fc2(*v_icms).as_deref()),
1997 optional_field("modBCST", mod_bc_st.as_deref()),
1999 optional_field("pMVAST", fc4(*p_mva_st).as_deref()),
2000 optional_field("pRedBCST", fc4(*p_red_bc_st).as_deref()),
2001 optional_field("vBCST", fc2(*v_bc_st).as_deref()),
2002 optional_field("pICMSST", fc4(*p_icms_st).as_deref()),
2003 optional_field("vICMSST", fc2(*v_icms_st).as_deref()),
2004 ];
2005 fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
2007 fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
2008 fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
2009 fields_opt.push(optional_field("pCredSN", fc4(*p_cred_sn).as_deref()));
2011 fields_opt.push(optional_field(
2012 "vCredICMSSN",
2013 fc2(*v_cred_icms_sn).as_deref(),
2014 ));
2015 Ok(("ICMSSN900".to_string(), filter_fields(fields_opt)))
2016 }
2017 }
2018}
2019
2020fn fc2(v: Option<Cents>) -> Option<String> {
2024 format_cents_or_none(v.map(|c| c.0), 2)
2025}
2026
2027fn fc4(v: Option<Rate>) -> Option<String> {
2029 format_cents_or_none(v.map(|r| r.0), 4)
2030}
2031
2032fn fc4_raw(v: Option<i64>) -> Option<String> {
2034 format_cents_or_none(v, 4)
2035}
2036
2037pub fn build_icms_xml(
2050 variant: &IcmsVariant,
2051 totals: &mut IcmsTotals,
2052) -> Result<String, FiscalError> {
2053 let (variant_tag, fields) = match variant {
2054 IcmsVariant::Cst(cst) => build_icms_cst_xml(cst, totals)?,
2055 IcmsVariant::Csosn(csosn) => build_icms_csosn_xml(csosn, totals)?,
2056 };
2057
2058 let element = TaxElement {
2059 outer_tag: Some("ICMS".to_string()),
2060 outer_fields: vec![],
2061 variant_tag,
2062 fields,
2063 };
2064
2065 Ok(serialize_tax_element(&element))
2066}
2067
2068pub fn build_icms_part_xml(data: &IcmsPartData) -> Result<(String, IcmsTotals), FiscalError> {
2077 let mut totals = create_icms_totals();
2078 totals.v_bc = accum(totals.v_bc, Some(data.v_bc));
2079 totals.v_icms = accum(totals.v_icms, Some(data.v_icms));
2080 totals.v_bc_st = accum(totals.v_bc_st, Some(data.v_bc_st));
2081 totals.v_st = accum(totals.v_st, Some(data.v_icms_st));
2082 if data.ind_deduz_deson.as_deref() == Some("1") {
2083 totals.ind_deduz_deson = true;
2084 }
2085
2086 let mut fields_opt: Vec<Option<TaxField>> = vec![
2087 Some(TaxField::new("orig", data.orig.as_str())),
2088 Some(TaxField::new("CST", data.cst.as_str())),
2089 Some(TaxField::new("modBC", data.mod_bc.as_str())),
2090 Some(TaxField::new("vBC", fc2(Some(data.v_bc)).unwrap())),
2091 optional_field("pRedBC", fc4(data.p_red_bc).as_deref()),
2092 Some(TaxField::new("pICMS", fc4(Some(data.p_icms)).unwrap())),
2093 Some(TaxField::new("vICMS", fc2(Some(data.v_icms)).unwrap())),
2094 ];
2095
2096 fields_opt.push(Some(TaxField::new("modBCST", data.mod_bc_st.as_str())));
2098 if let Some(v) = data.p_mva_st {
2099 fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(v)).unwrap())));
2100 }
2101 if let Some(v) = data.p_red_bc_st {
2102 fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(v)).unwrap())));
2103 }
2104 fields_opt.push(Some(TaxField::new(
2105 "vBCST",
2106 fc2(Some(data.v_bc_st)).unwrap(),
2107 )));
2108 fields_opt.push(Some(TaxField::new(
2109 "pICMSST",
2110 fc4(Some(data.p_icms_st)).unwrap(),
2111 )));
2112 fields_opt.push(Some(TaxField::new(
2113 "vICMSST",
2114 fc2(Some(data.v_icms_st)).unwrap(),
2115 )));
2116
2117 fields_opt.push(optional_field("vBCFCPST", fc2(data.v_bc_fcp_st).as_deref()));
2119 fields_opt.push(optional_field("pFCPST", fc4(data.p_fcp_st).as_deref()));
2120 fields_opt.push(optional_field("vFCPST", fc2(data.v_fcp_st).as_deref()));
2121
2122 fields_opt.push(Some(TaxField::new(
2124 "pBCOp",
2125 fc4(Some(data.p_bc_op)).unwrap(),
2126 )));
2127 fields_opt.push(Some(TaxField::new("UFST", data.uf_st.as_str())));
2128
2129 fields_opt.push(optional_field(
2131 "vICMSDeson",
2132 fc2(data.v_icms_deson).as_deref(),
2133 ));
2134 fields_opt.push(optional_field("motDesICMS", data.mot_des_icms.as_deref()));
2135 fields_opt.push(optional_field(
2136 "indDeduzDeson",
2137 data.ind_deduz_deson.as_deref(),
2138 ));
2139
2140 let fields = filter_fields(fields_opt);
2141
2142 let element = TaxElement {
2143 outer_tag: Some("ICMS".to_string()),
2144 outer_fields: vec![],
2145 variant_tag: "ICMSPart".to_string(),
2146 fields,
2147 };
2148
2149 Ok((serialize_tax_element(&element), totals))
2150}
2151
2152pub fn build_icms_st_xml(data: &IcmsStData) -> Result<(String, IcmsTotals), FiscalError> {
2160 let mut totals = create_icms_totals();
2161 totals.v_fcp_st_ret = accum(totals.v_fcp_st_ret, data.v_fcp_st_ret);
2162
2163 let fields_opt: Vec<Option<TaxField>> = vec![
2164 Some(TaxField::new("orig", data.orig.as_str())),
2165 Some(TaxField::new("CST", data.cst.as_str())),
2166 Some(TaxField::new(
2167 "vBCSTRet",
2168 fc2(Some(data.v_bc_st_ret)).unwrap(),
2169 )),
2170 optional_field("pST", fc4(data.p_st).as_deref()),
2171 optional_field("vICMSSubstituto", fc2(data.v_icms_substituto).as_deref()),
2172 Some(TaxField::new(
2173 "vICMSSTRet",
2174 fc2(Some(data.v_icms_st_ret)).unwrap(),
2175 )),
2176 optional_field("vBCFCPSTRet", fc2(data.v_bc_fcp_st_ret).as_deref()),
2177 optional_field("pFCPSTRet", fc4(data.p_fcp_st_ret).as_deref()),
2178 optional_field("vFCPSTRet", fc2(data.v_fcp_st_ret).as_deref()),
2179 Some(TaxField::new(
2180 "vBCSTDest",
2181 fc2(Some(data.v_bc_st_dest)).unwrap(),
2182 )),
2183 Some(TaxField::new(
2184 "vICMSSTDest",
2185 fc2(Some(data.v_icms_st_dest)).unwrap(),
2186 )),
2187 optional_field("pRedBCEfet", fc4(data.p_red_bc_efet).as_deref()),
2188 optional_field("vBCEfet", fc2(data.v_bc_efet).as_deref()),
2189 optional_field("pICMSEfet", fc4(data.p_icms_efet).as_deref()),
2190 optional_field("vICMSEfet", fc2(data.v_icms_efet).as_deref()),
2191 ];
2192
2193 let fields = filter_fields(fields_opt);
2194
2195 let element = TaxElement {
2196 outer_tag: Some("ICMS".to_string()),
2197 outer_fields: vec![],
2198 variant_tag: "ICMSST".to_string(),
2199 fields,
2200 };
2201
2202 Ok((serialize_tax_element(&element), totals))
2203}
2204
2205pub fn build_icms_uf_dest_xml(data: &IcmsUfDestData) -> Result<(String, IcmsTotals), FiscalError> {
2213 let mut totals = create_icms_totals();
2214 totals.v_icms_uf_dest = accum(totals.v_icms_uf_dest, Some(data.v_icms_uf_dest));
2215 totals.v_fcp_uf_dest = accum(totals.v_fcp_uf_dest, data.v_fcp_uf_dest);
2216 totals.v_icms_uf_remet = accum(totals.v_icms_uf_remet, data.v_icms_uf_remet);
2217
2218 let fields_opt: Vec<Option<TaxField>> = vec![
2219 Some(TaxField::new(
2220 "vBCUFDest",
2221 fc2(Some(data.v_bc_uf_dest)).unwrap(),
2222 )),
2223 optional_field("vBCFCPUFDest", fc2(data.v_bc_fcp_uf_dest).as_deref()),
2224 optional_field("pFCPUFDest", fc4(data.p_fcp_uf_dest).as_deref()),
2225 Some(TaxField::new(
2226 "pICMSUFDest",
2227 fc4(Some(data.p_icms_uf_dest)).unwrap(),
2228 )),
2229 Some(TaxField::new(
2230 "pICMSInter",
2231 fc4(Some(data.p_icms_inter)).unwrap(),
2232 )),
2233 Some(TaxField::new("pICMSInterPart", "100.0000")),
2234 optional_field("vFCPUFDest", fc2(data.v_fcp_uf_dest).as_deref()),
2235 Some(TaxField::new(
2236 "vICMSUFDest",
2237 fc2(Some(data.v_icms_uf_dest)).unwrap(),
2238 )),
2239 Some(TaxField::new(
2240 "vICMSUFRemet",
2241 fc2(Some(data.v_icms_uf_remet.unwrap_or(Cents(0)))).unwrap(),
2242 )),
2243 ];
2244
2245 let fields = filter_fields(fields_opt);
2246
2247 let element = TaxElement {
2248 outer_tag: None,
2249 outer_fields: vec![],
2250 variant_tag: "ICMSUFDest".to_string(),
2251 fields,
2252 };
2253
2254 Ok((serialize_tax_element(&element), totals))
2255}
2256
2257pub fn merge_icms_totals(target: &mut IcmsTotals, source: &IcmsTotals) {
2264 target.v_bc += source.v_bc;
2265 target.v_icms += source.v_icms;
2266 target.v_icms_deson += source.v_icms_deson;
2267 target.v_bc_st += source.v_bc_st;
2268 target.v_st += source.v_st;
2269 target.v_fcp += source.v_fcp;
2270 target.v_fcp_st += source.v_fcp_st;
2271 target.v_fcp_st_ret += source.v_fcp_st_ret;
2272 target.v_fcp_uf_dest += source.v_fcp_uf_dest;
2273 target.v_icms_uf_dest += source.v_icms_uf_dest;
2274 target.v_icms_uf_remet += source.v_icms_uf_remet;
2275 target.q_bc_mono += source.q_bc_mono;
2276 target.v_icms_mono += source.v_icms_mono;
2277 target.q_bc_mono_reten += source.q_bc_mono_reten;
2278 target.v_icms_mono_reten += source.v_icms_mono_reten;
2279 target.q_bc_mono_ret += source.q_bc_mono_ret;
2280 target.v_icms_mono_ret += source.v_icms_mono_ret;
2281 if source.ind_deduz_deson {
2283 target.ind_deduz_deson = true;
2284 }
2285}
2286
2287#[cfg(test)]
2288mod tests {
2289 use super::*;
2290 use crate::newtypes::{Cents, Rate};
2291
2292 #[test]
2295 fn icms_totals_builder_v_icms_uf_remet() {
2296 let t = IcmsTotals::new().v_icms_uf_remet(Cents(500));
2297 assert_eq!(t.v_icms_uf_remet, Cents(500));
2298 }
2299
2300 #[test]
2301 fn icms_totals_builder_v_icms_mono() {
2302 let t = IcmsTotals::new().v_icms_mono(Cents(300));
2303 assert_eq!(t.v_icms_mono, Cents(300));
2304 }
2305
2306 #[test]
2307 fn icms_totals_builder_v_icms_mono_reten() {
2308 let t = IcmsTotals::new().v_icms_mono_reten(Cents(200));
2309 assert_eq!(t.v_icms_mono_reten, Cents(200));
2310 }
2311
2312 #[test]
2313 fn icms_totals_builder_v_icms_mono_ret() {
2314 let t = IcmsTotals::new().v_icms_mono_ret(Cents(100));
2315 assert_eq!(t.v_icms_mono_ret, Cents(100));
2316 }
2317
2318 #[test]
2319 fn icms_totals_builder_ind_deduz_deson() {
2320 let t = IcmsTotals::new().ind_deduz_deson(true);
2321 assert!(t.ind_deduz_deson);
2322 let t2 = IcmsTotals::new().ind_deduz_deson(false);
2323 assert!(!t2.ind_deduz_deson);
2324 }
2325
2326 #[test]
2329 fn cst_code_cst30() {
2330 let cst = IcmsCst::Cst30 {
2331 orig: "0".into(),
2332 mod_bc_st: "4".into(),
2333 p_mva_st: None,
2334 p_red_bc_st: None,
2335 v_bc_st: Cents(1000),
2336 p_icms_st: Rate(1800),
2337 v_icms_st: Cents(180),
2338 v_bc_fcp_st: None,
2339 p_fcp_st: None,
2340 v_fcp_st: None,
2341 v_icms_deson: None,
2342 mot_des_icms: None,
2343 ind_deduz_deson: None,
2344 };
2345 assert_eq!(cst.cst_code(), "30");
2346 }
2347
2348 #[test]
2349 fn cst_code_cst51() {
2350 let cst = IcmsCst::Cst51 {
2351 orig: "0".into(),
2352 mod_bc: None,
2353 p_red_bc: None,
2354 c_benef_rbc: None,
2355 v_bc: None,
2356 p_icms: None,
2357 v_icms_op: None,
2358 p_dif: None,
2359 v_icms_dif: None,
2360 v_icms: None,
2361 v_bc_fcp: None,
2362 p_fcp: None,
2363 v_fcp: None,
2364 p_fcp_dif: None,
2365 v_fcp_dif: None,
2366 v_fcp_efet: None,
2367 };
2368 assert_eq!(cst.cst_code(), "51");
2369 }
2370
2371 #[test]
2372 fn cst_code_cst53() {
2373 let cst = IcmsCst::Cst53 {
2374 orig: "0".into(),
2375 q_bc_mono: None,
2376 ad_rem_icms: None,
2377 v_icms_mono_op: None,
2378 p_dif: None,
2379 v_icms_mono_dif: None,
2380 v_icms_mono: None,
2381 };
2382 assert_eq!(cst.cst_code(), "53");
2383 }
2384
2385 #[test]
2386 fn cst_code_cst61() {
2387 let cst = IcmsCst::Cst61 {
2388 orig: "0".into(),
2389 q_bc_mono_ret: None,
2390 ad_rem_icms_ret: Rate(100),
2391 v_icms_mono_ret: Cents(50),
2392 };
2393 assert_eq!(cst.cst_code(), "61");
2394 }
2395
2396 #[test]
2399 fn csosn_code_102() {
2400 let c = IcmsCsosn::Csosn102 {
2401 orig: "0".into(),
2402 csosn: "102".into(),
2403 };
2404 assert_eq!(c.csosn_code(), "102");
2405 }
2406
2407 #[test]
2408 fn csosn_code_103() {
2409 let c = IcmsCsosn::Csosn103 {
2410 orig: "0".into(),
2411 csosn: "103".into(),
2412 };
2413 assert_eq!(c.csosn_code(), "103");
2414 }
2415
2416 #[test]
2417 fn csosn_code_201() {
2418 let c = IcmsCsosn::Csosn201 {
2419 orig: "0".into(),
2420 csosn: "201".into(),
2421 mod_bc_st: "4".into(),
2422 p_mva_st: None,
2423 p_red_bc_st: None,
2424 v_bc_st: Cents(0),
2425 p_icms_st: Rate(0),
2426 v_icms_st: Cents(0),
2427 v_bc_fcp_st: None,
2428 p_fcp_st: None,
2429 v_fcp_st: None,
2430 p_cred_sn: None,
2431 v_cred_icms_sn: None,
2432 };
2433 assert_eq!(c.csosn_code(), "201");
2434 }
2435
2436 #[test]
2437 fn csosn_code_202() {
2438 let c = IcmsCsosn::Csosn202 {
2439 orig: "0".into(),
2440 csosn: "202".into(),
2441 mod_bc_st: "4".into(),
2442 p_mva_st: None,
2443 p_red_bc_st: None,
2444 v_bc_st: Cents(0),
2445 p_icms_st: Rate(0),
2446 v_icms_st: Cents(0),
2447 v_bc_fcp_st: None,
2448 p_fcp_st: None,
2449 v_fcp_st: None,
2450 };
2451 assert_eq!(c.csosn_code(), "202");
2452 }
2453
2454 #[test]
2455 fn csosn_code_203() {
2456 let c = IcmsCsosn::Csosn203 {
2457 orig: "0".into(),
2458 csosn: "203".into(),
2459 mod_bc_st: "4".into(),
2460 p_mva_st: None,
2461 p_red_bc_st: None,
2462 v_bc_st: Cents(0),
2463 p_icms_st: Rate(0),
2464 v_icms_st: Cents(0),
2465 v_bc_fcp_st: None,
2466 p_fcp_st: None,
2467 v_fcp_st: None,
2468 };
2469 assert_eq!(c.csosn_code(), "203");
2470 }
2471
2472 #[test]
2473 fn csosn_code_300() {
2474 let c = IcmsCsosn::Csosn300 {
2475 orig: "0".into(),
2476 csosn: "300".into(),
2477 };
2478 assert_eq!(c.csosn_code(), "300");
2479 }
2480
2481 #[test]
2482 fn csosn_code_400() {
2483 let c = IcmsCsosn::Csosn400 {
2484 orig: "0".into(),
2485 csosn: "400".into(),
2486 };
2487 assert_eq!(c.csosn_code(), "400");
2488 }
2489
2490 #[test]
2491 fn csosn_code_500() {
2492 let c = IcmsCsosn::Csosn500 {
2493 orig: "0".into(),
2494 csosn: "500".into(),
2495 v_bc_st_ret: None,
2496 p_st: None,
2497 v_icms_substituto: None,
2498 v_icms_st_ret: None,
2499 v_bc_fcp_st_ret: None,
2500 p_fcp_st_ret: None,
2501 v_fcp_st_ret: None,
2502 p_red_bc_efet: None,
2503 v_bc_efet: None,
2504 p_icms_efet: None,
2505 v_icms_efet: None,
2506 };
2507 assert_eq!(c.csosn_code(), "500");
2508 }
2509
2510 #[test]
2511 fn csosn_code_900() {
2512 let c = IcmsCsosn::Csosn900 {
2513 orig: "0".into(),
2514 csosn: "900".into(),
2515 mod_bc: None,
2516 v_bc: None,
2517 p_red_bc: None,
2518 p_icms: None,
2519 v_icms: None,
2520 mod_bc_st: None,
2521 p_mva_st: None,
2522 p_red_bc_st: None,
2523 v_bc_st: None,
2524 p_icms_st: None,
2525 v_icms_st: None,
2526 v_bc_fcp_st: None,
2527 p_fcp_st: None,
2528 v_fcp_st: None,
2529 p_cred_sn: None,
2530 v_cred_icms_sn: None,
2531 };
2532 assert_eq!(c.csosn_code(), "900");
2533 }
2534
2535 #[test]
2538 fn csosn102_empty_orig_omits_orig_field() {
2539 let c = IcmsCsosn::Csosn102 {
2540 orig: String::new(),
2541 csosn: "102".into(),
2542 };
2543 let mut totals = IcmsTotals::new();
2544 let (tag, fields) = build_icms_csosn_xml(&c, &mut totals).unwrap();
2545 assert_eq!(tag, "ICMSSN102");
2546 assert!(fields.iter().all(|f| f.name != "orig"));
2548 }
2549
2550 #[test]
2553 fn merge_icms_totals_propagates_ind_deduz_deson() {
2554 let mut target = IcmsTotals::new();
2555 assert!(!target.ind_deduz_deson);
2556
2557 let source = IcmsTotals::new()
2558 .v_bc(Cents(1000))
2559 .v_icms(Cents(180))
2560 .v_icms_mono(Cents(50))
2561 .v_icms_mono_reten(Cents(25))
2562 .v_icms_mono_ret(Cents(10))
2563 .v_icms_uf_remet(Cents(30))
2564 .ind_deduz_deson(true);
2565
2566 merge_icms_totals(&mut target, &source);
2567 assert!(target.ind_deduz_deson);
2568 assert_eq!(target.v_bc, Cents(1000));
2569 assert_eq!(target.v_icms, Cents(180));
2570 assert_eq!(target.v_icms_mono, Cents(50));
2571 assert_eq!(target.v_icms_mono_reten, Cents(25));
2572 assert_eq!(target.v_icms_mono_ret, Cents(10));
2573 assert_eq!(target.v_icms_uf_remet, Cents(30));
2574 }
2575
2576 #[test]
2577 fn merge_icms_totals_does_not_set_false_on_target() {
2578 let mut target = IcmsTotals::new().ind_deduz_deson(true);
2579 let source = IcmsTotals::new(); merge_icms_totals(&mut target, &source);
2581 assert!(target.ind_deduz_deson);
2583 }
2584
2585 #[test]
2588 fn cst_code_cst00() {
2589 let cst = IcmsCst::Cst00 {
2590 orig: "0".into(),
2591 mod_bc: "3".into(),
2592 v_bc: Cents(10000),
2593 p_icms: Rate(1800),
2594 v_icms: Cents(1800),
2595 p_fcp: None,
2596 v_fcp: None,
2597 };
2598 assert_eq!(cst.cst_code(), "00");
2599 }
2600
2601 #[test]
2602 fn cst_code_cst02() {
2603 let cst = IcmsCst::Cst02 {
2604 orig: "0".into(),
2605 q_bc_mono: None,
2606 ad_rem_icms: Rate(100),
2607 v_icms_mono: Cents(50),
2608 };
2609 assert_eq!(cst.cst_code(), "02");
2610 }
2611
2612 #[test]
2613 fn cst_code_cst10() {
2614 let cst = IcmsCst::Cst10 {
2615 orig: "0".into(),
2616 mod_bc: "3".into(),
2617 v_bc: Cents(10000),
2618 p_icms: Rate(1800),
2619 v_icms: Cents(1800),
2620 v_bc_fcp: None,
2621 p_fcp: None,
2622 v_fcp: None,
2623 mod_bc_st: "4".into(),
2624 p_mva_st: None,
2625 p_red_bc_st: None,
2626 v_bc_st: Cents(10000),
2627 p_icms_st: Rate(1800),
2628 v_icms_st: Cents(1800),
2629 v_bc_fcp_st: None,
2630 p_fcp_st: None,
2631 v_fcp_st: None,
2632 v_icms_st_deson: None,
2633 mot_des_icms_st: None,
2634 };
2635 assert_eq!(cst.cst_code(), "10");
2636 }
2637
2638 #[test]
2639 fn cst_code_cst15() {
2640 let cst = IcmsCst::Cst15 {
2641 orig: "0".into(),
2642 q_bc_mono: None,
2643 ad_rem_icms: Rate(100),
2644 v_icms_mono: Cents(50),
2645 q_bc_mono_reten: None,
2646 ad_rem_icms_reten: Rate(80),
2647 v_icms_mono_reten: Cents(40),
2648 p_red_ad_rem: None,
2649 mot_red_ad_rem: None,
2650 };
2651 assert_eq!(cst.cst_code(), "15");
2652 }
2653
2654 #[test]
2655 fn cst_code_cst20() {
2656 let cst = IcmsCst::Cst20 {
2657 orig: "0".into(),
2658 mod_bc: "3".into(),
2659 p_red_bc: Rate(5000),
2660 v_bc: Cents(5000),
2661 p_icms: Rate(1800),
2662 v_icms: Cents(900),
2663 v_bc_fcp: None,
2664 p_fcp: None,
2665 v_fcp: None,
2666 v_icms_deson: None,
2667 mot_des_icms: None,
2668 ind_deduz_deson: None,
2669 };
2670 assert_eq!(cst.cst_code(), "20");
2671 }
2672
2673 #[test]
2674 fn cst_code_cst60() {
2675 let cst = IcmsCst::Cst60 {
2676 orig: "0".into(),
2677 v_bc_st_ret: None,
2678 p_st: None,
2679 v_icms_substituto: None,
2680 v_icms_st_ret: None,
2681 v_bc_fcp_st_ret: None,
2682 p_fcp_st_ret: None,
2683 v_fcp_st_ret: None,
2684 p_red_bc_efet: None,
2685 v_bc_efet: None,
2686 p_icms_efet: None,
2687 v_icms_efet: None,
2688 };
2689 assert_eq!(cst.cst_code(), "60");
2690 }
2691
2692 #[test]
2693 fn cst_code_cst70() {
2694 let cst = IcmsCst::Cst70 {
2695 orig: "0".into(),
2696 mod_bc: "3".into(),
2697 p_red_bc: Rate(5000),
2698 v_bc: Cents(5000),
2699 p_icms: Rate(1800),
2700 v_icms: Cents(900),
2701 v_bc_fcp: None,
2702 p_fcp: None,
2703 v_fcp: None,
2704 mod_bc_st: "4".into(),
2705 p_mva_st: None,
2706 p_red_bc_st: None,
2707 v_bc_st: Cents(5000),
2708 p_icms_st: Rate(1800),
2709 v_icms_st: Cents(900),
2710 v_bc_fcp_st: None,
2711 p_fcp_st: None,
2712 v_fcp_st: None,
2713 v_icms_deson: None,
2714 mot_des_icms: None,
2715 ind_deduz_deson: None,
2716 v_icms_st_deson: None,
2717 mot_des_icms_st: None,
2718 };
2719 assert_eq!(cst.cst_code(), "70");
2720 }
2721
2722 #[test]
2723 fn cst_code_cst90() {
2724 let cst = IcmsCst::Cst90 {
2725 orig: "0".into(),
2726 mod_bc: None,
2727 v_bc: None,
2728 p_red_bc: None,
2729 c_benef_rbc: None,
2730 p_icms: None,
2731 v_icms_op: None,
2732 p_dif: None,
2733 v_icms_dif: None,
2734 v_icms: None,
2735 v_bc_fcp: None,
2736 p_fcp: None,
2737 v_fcp: None,
2738 p_fcp_dif: None,
2739 v_fcp_dif: None,
2740 v_fcp_efet: None,
2741 mod_bc_st: None,
2742 p_mva_st: None,
2743 p_red_bc_st: None,
2744 v_bc_st: None,
2745 p_icms_st: None,
2746 v_icms_st: None,
2747 v_bc_fcp_st: None,
2748 p_fcp_st: None,
2749 v_fcp_st: None,
2750 v_icms_deson: None,
2751 mot_des_icms: None,
2752 ind_deduz_deson: None,
2753 v_icms_st_deson: None,
2754 mot_des_icms_st: None,
2755 };
2756 assert_eq!(cst.cst_code(), "90");
2757 }
2758
2759 #[test]
2762 fn csosn_code_101() {
2763 let c = IcmsCsosn::Csosn101 {
2764 orig: "0".into(),
2765 csosn: "101".into(),
2766 p_cred_sn: Rate(150),
2767 v_cred_icms_sn: Cents(30),
2768 };
2769 assert_eq!(c.csosn_code(), "101");
2770 }
2771}