1use serde::{Deserialize, Serialize};
8
9use crate::tax_element::{
10 TaxElement, TaxField, filter_fields, optional_field, serialize_tax_element,
11};
12
13#[derive(Debug, Clone, Default, Serialize, Deserialize)]
20#[serde(rename_all = "camelCase")]
21#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
22#[cfg_attr(feature = "ts", ts(export))]
23#[non_exhaustive]
24pub struct IsData {
25 pub cst_is: String,
27 pub c_class_trib_is: String,
29 pub v_bc_is: Option<String>,
31 pub p_is: Option<String>,
33 pub p_is_espec: Option<String>,
35 pub u_trib: Option<String>,
37 pub q_trib: Option<String>,
39 pub v_is: String,
41}
42
43impl IsData {
44 pub fn new(
50 cst_is: impl Into<String>,
51 c_class_trib_is: impl Into<String>,
52 v_is: impl Into<String>,
53 ) -> Self {
54 Self {
55 cst_is: cst_is.into(),
56 c_class_trib_is: c_class_trib_is.into(),
57 v_is: v_is.into(),
58 ..Default::default()
59 }
60 }
61 pub fn v_bc_is(mut self, v: impl Into<String>) -> Self {
63 self.v_bc_is = Some(v.into());
64 self
65 }
66 pub fn p_is(mut self, v: impl Into<String>) -> Self {
68 self.p_is = Some(v.into());
69 self
70 }
71 pub fn p_is_espec(mut self, v: impl Into<String>) -> Self {
73 self.p_is_espec = Some(v.into());
74 self
75 }
76 pub fn u_trib(mut self, v: impl Into<String>) -> Self {
78 self.u_trib = Some(v.into());
79 self
80 }
81 pub fn q_trib(mut self, v: impl Into<String>) -> Self {
83 self.q_trib = Some(v.into());
84 self
85 }
86}
87
88fn calculate_is(data: &IsData) -> TaxElement {
95 let mut fields: Vec<Option<TaxField>> = vec![
96 Some(TaxField::new("CSTIS", &data.cst_is)),
97 Some(TaxField::new("cClassTribIS", &data.c_class_trib_is)),
98 ];
99
100 if let Some(ref v_bc_is) = data.v_bc_is {
101 fields.push(Some(TaxField::new("vBCIS", v_bc_is)));
102 fields.push(optional_field("pIS", data.p_is.as_deref()));
103 fields.push(optional_field("pISEspec", data.p_is_espec.as_deref()));
104 }
105
106 if let (Some(u_trib), Some(q_trib)) = (&data.u_trib, &data.q_trib) {
107 fields.push(Some(TaxField::new("uTrib", u_trib)));
108 fields.push(Some(TaxField::new("qTrib", q_trib)));
109 }
110
111 fields.push(Some(TaxField::new("vIS", &data.v_is)));
112
113 TaxElement {
114 outer_tag: None,
115 outer_fields: vec![],
116 variant_tag: "IS".into(),
117 fields: filter_fields(fields),
118 }
119}
120
121pub fn build_is_xml(data: &IsData) -> String {
123 serialize_tax_element(&calculate_is(data))
124}