use crate::FiscalError;
use crate::newtypes::{Cents, Rate};
use crate::tax_element::{TaxField, filter_fields, optional_field};
use super::totals::IcmsTotals;
use super::{accum, fc2, fc4};
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum IcmsCsosn {
Csosn101 {
orig: String,
csosn: String,
p_cred_sn: Rate,
v_cred_icms_sn: Cents,
},
Csosn102 {
orig: String,
csosn: String,
},
Csosn103 {
orig: String,
csosn: String,
},
Csosn300 {
orig: String,
csosn: String,
},
Csosn400 {
orig: String,
csosn: String,
},
Csosn201 {
orig: String,
csosn: String,
mod_bc_st: String,
p_mva_st: Option<Rate>,
p_red_bc_st: Option<Rate>,
v_bc_st: Cents,
p_icms_st: Rate,
v_icms_st: Cents,
v_bc_fcp_st: Option<Cents>,
p_fcp_st: Option<Rate>,
v_fcp_st: Option<Cents>,
p_cred_sn: Option<Rate>,
v_cred_icms_sn: Option<Cents>,
},
Csosn202 {
orig: String,
csosn: String,
mod_bc_st: String,
p_mva_st: Option<Rate>,
p_red_bc_st: Option<Rate>,
v_bc_st: Cents,
p_icms_st: Rate,
v_icms_st: Cents,
v_bc_fcp_st: Option<Cents>,
p_fcp_st: Option<Rate>,
v_fcp_st: Option<Cents>,
},
Csosn203 {
orig: String,
csosn: String,
mod_bc_st: String,
p_mva_st: Option<Rate>,
p_red_bc_st: Option<Rate>,
v_bc_st: Cents,
p_icms_st: Rate,
v_icms_st: Cents,
v_bc_fcp_st: Option<Cents>,
p_fcp_st: Option<Rate>,
v_fcp_st: Option<Cents>,
},
Csosn500 {
orig: String,
csosn: String,
v_bc_st_ret: Option<Cents>,
p_st: Option<Rate>,
v_icms_substituto: Option<Cents>,
v_icms_st_ret: Option<Cents>,
v_bc_fcp_st_ret: Option<Cents>,
p_fcp_st_ret: Option<Rate>,
v_fcp_st_ret: Option<Cents>,
p_red_bc_efet: Option<Rate>,
v_bc_efet: Option<Cents>,
p_icms_efet: Option<Rate>,
v_icms_efet: Option<Cents>,
},
Csosn900 {
orig: String,
csosn: String,
mod_bc: Option<String>,
v_bc: Option<Cents>,
p_red_bc: Option<Rate>,
p_icms: Option<Rate>,
v_icms: Option<Cents>,
mod_bc_st: Option<String>,
p_mva_st: Option<Rate>,
p_red_bc_st: Option<Rate>,
v_bc_st: Option<Cents>,
p_icms_st: Option<Rate>,
v_icms_st: Option<Cents>,
v_bc_fcp_st: Option<Cents>,
p_fcp_st: Option<Rate>,
v_fcp_st: Option<Cents>,
p_cred_sn: Option<Rate>,
v_cred_icms_sn: Option<Cents>,
},
}
impl IcmsCsosn {
pub fn csosn_code(&self) -> &str {
match self {
Self::Csosn101 { csosn, .. } => csosn.as_str(),
Self::Csosn102 { csosn, .. } => csosn.as_str(),
Self::Csosn103 { csosn, .. } => csosn.as_str(),
Self::Csosn201 { csosn, .. } => csosn.as_str(),
Self::Csosn202 { csosn, .. } => csosn.as_str(),
Self::Csosn203 { csosn, .. } => csosn.as_str(),
Self::Csosn300 { csosn, .. } => csosn.as_str(),
Self::Csosn400 { csosn, .. } => csosn.as_str(),
Self::Csosn500 { csosn, .. } => csosn.as_str(),
Self::Csosn900 { csosn, .. } => csosn.as_str(),
}
}
}
pub fn build_icms_csosn_xml(
csosn: &IcmsCsosn,
totals: &mut IcmsTotals,
) -> Result<(String, Vec<TaxField>), FiscalError> {
match csosn {
IcmsCsosn::Csosn101 {
orig,
csosn,
p_cred_sn,
v_cred_icms_sn,
} => {
let fields = filter_fields(vec![
Some(TaxField::new("orig", orig.as_str())),
Some(TaxField::new("CSOSN", csosn.as_str())),
Some(TaxField::new("pCredSN", fc4(Some(*p_cred_sn)).unwrap())),
Some(TaxField::new(
"vCredICMSSN",
fc2(Some(*v_cred_icms_sn)).unwrap(),
)),
]);
Ok(("ICMSSN101".to_string(), fields))
}
IcmsCsosn::Csosn102 { orig, csosn }
| IcmsCsosn::Csosn103 { orig, csosn }
| IcmsCsosn::Csosn300 { orig, csosn }
| IcmsCsosn::Csosn400 { orig, csosn } => {
let orig_val = if orig.is_empty() {
None
} else {
Some(orig.as_str())
};
let fields = filter_fields(vec![
optional_field("orig", orig_val),
Some(TaxField::new("CSOSN", csosn.as_str())),
]);
Ok(("ICMSSN102".to_string(), fields))
}
IcmsCsosn::Csosn201 {
orig,
csosn,
mod_bc_st,
p_mva_st,
p_red_bc_st,
v_bc_st,
p_icms_st,
v_icms_st,
v_bc_fcp_st,
p_fcp_st,
v_fcp_st,
p_cred_sn,
v_cred_icms_sn,
} => {
totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
totals.v_st = accum(totals.v_st, Some(*v_icms_st));
let mut fields_opt: Vec<Option<TaxField>> = vec![
Some(TaxField::new("orig", orig.as_str())),
Some(TaxField::new("CSOSN", csosn.as_str())),
];
fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
if let Some(v) = p_mva_st {
fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
}
if let Some(v) = p_red_bc_st {
fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
}
fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
fields_opt.push(Some(TaxField::new(
"pICMSST",
fc4(Some(*p_icms_st)).unwrap(),
)));
fields_opt.push(Some(TaxField::new(
"vICMSST",
fc2(Some(*v_icms_st)).unwrap(),
)));
fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
fields_opt.push(optional_field("pCredSN", fc4(*p_cred_sn).as_deref()));
fields_opt.push(optional_field(
"vCredICMSSN",
fc2(*v_cred_icms_sn).as_deref(),
));
Ok(("ICMSSN201".to_string(), filter_fields(fields_opt)))
}
IcmsCsosn::Csosn202 {
orig,
csosn,
mod_bc_st,
p_mva_st,
p_red_bc_st,
v_bc_st,
p_icms_st,
v_icms_st,
v_bc_fcp_st,
p_fcp_st,
v_fcp_st,
}
| IcmsCsosn::Csosn203 {
orig,
csosn,
mod_bc_st,
p_mva_st,
p_red_bc_st,
v_bc_st,
p_icms_st,
v_icms_st,
v_bc_fcp_st,
p_fcp_st,
v_fcp_st,
} => {
totals.v_bc_st = accum(totals.v_bc_st, Some(*v_bc_st));
totals.v_st = accum(totals.v_st, Some(*v_icms_st));
let mut fields_opt: Vec<Option<TaxField>> = vec![
Some(TaxField::new("orig", orig.as_str())),
Some(TaxField::new("CSOSN", csosn.as_str())),
];
fields_opt.push(Some(TaxField::new("modBCST", mod_bc_st.as_str())));
if let Some(v) = p_mva_st {
fields_opt.push(Some(TaxField::new("pMVAST", fc4(Some(*v)).unwrap())));
}
if let Some(v) = p_red_bc_st {
fields_opt.push(Some(TaxField::new("pRedBCST", fc4(Some(*v)).unwrap())));
}
fields_opt.push(Some(TaxField::new("vBCST", fc2(Some(*v_bc_st)).unwrap())));
fields_opt.push(Some(TaxField::new(
"pICMSST",
fc4(Some(*p_icms_st)).unwrap(),
)));
fields_opt.push(Some(TaxField::new(
"vICMSST",
fc2(Some(*v_icms_st)).unwrap(),
)));
fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
Ok(("ICMSSN202".to_string(), filter_fields(fields_opt)))
}
IcmsCsosn::Csosn500 {
orig,
csosn,
v_bc_st_ret,
p_st,
v_icms_substituto,
v_icms_st_ret,
v_bc_fcp_st_ret,
p_fcp_st_ret,
v_fcp_st_ret,
p_red_bc_efet,
v_bc_efet,
p_icms_efet,
v_icms_efet,
} => {
let fields = filter_fields(vec![
Some(TaxField::new("orig", orig.as_str())),
Some(TaxField::new("CSOSN", csosn.as_str())),
optional_field("vBCSTRet", fc2(*v_bc_st_ret).as_deref()),
optional_field("pST", fc4(*p_st).as_deref()),
optional_field("vICMSSubstituto", fc2(*v_icms_substituto).as_deref()),
optional_field("vICMSSTRet", fc2(*v_icms_st_ret).as_deref()),
optional_field("vBCFCPSTRet", fc2(*v_bc_fcp_st_ret).as_deref()),
optional_field("pFCPSTRet", fc4(*p_fcp_st_ret).as_deref()),
optional_field("vFCPSTRet", fc2(*v_fcp_st_ret).as_deref()),
optional_field("pRedBCEfet", fc4(*p_red_bc_efet).as_deref()),
optional_field("vBCEfet", fc2(*v_bc_efet).as_deref()),
optional_field("pICMSEfet", fc4(*p_icms_efet).as_deref()),
optional_field("vICMSEfet", fc2(*v_icms_efet).as_deref()),
]);
Ok(("ICMSSN500".to_string(), fields))
}
IcmsCsosn::Csosn900 {
orig,
csosn,
mod_bc,
v_bc,
p_red_bc,
p_icms,
v_icms,
mod_bc_st,
p_mva_st,
p_red_bc_st,
v_bc_st,
p_icms_st,
v_icms_st,
v_bc_fcp_st,
p_fcp_st,
v_fcp_st,
p_cred_sn,
v_cred_icms_sn,
} => {
totals.v_bc = accum(totals.v_bc, *v_bc);
totals.v_icms = accum(totals.v_icms, *v_icms);
totals.v_bc_st = accum(totals.v_bc_st, *v_bc_st);
totals.v_st = accum(totals.v_st, *v_icms_st);
let orig_val = if orig.is_empty() {
None
} else {
Some(orig.as_str())
};
let mut fields_opt: Vec<Option<TaxField>> = vec![
optional_field("orig", orig_val),
Some(TaxField::new("CSOSN", csosn.as_str())),
optional_field("modBC", mod_bc.as_deref()),
optional_field("vBC", fc2(*v_bc).as_deref()),
optional_field("pRedBC", fc4(*p_red_bc).as_deref()),
optional_field("pICMS", fc4(*p_icms).as_deref()),
optional_field("vICMS", fc2(*v_icms).as_deref()),
optional_field("modBCST", mod_bc_st.as_deref()),
optional_field("pMVAST", fc4(*p_mva_st).as_deref()),
optional_field("pRedBCST", fc4(*p_red_bc_st).as_deref()),
optional_field("vBCST", fc2(*v_bc_st).as_deref()),
optional_field("pICMSST", fc4(*p_icms_st).as_deref()),
optional_field("vICMSST", fc2(*v_icms_st).as_deref()),
];
fields_opt.push(optional_field("vBCFCPST", fc2(*v_bc_fcp_st).as_deref()));
fields_opt.push(optional_field("pFCPST", fc4(*p_fcp_st).as_deref()));
fields_opt.push(optional_field("vFCPST", fc2(*v_fcp_st).as_deref()));
fields_opt.push(optional_field("pCredSN", fc4(*p_cred_sn).as_deref()));
fields_opt.push(optional_field(
"vCredICMSSN",
fc2(*v_cred_icms_sn).as_deref(),
));
Ok(("ICMSSN900".to_string(), filter_fields(fields_opt)))
}
}
}