Skip to main content

boleto_utils/
builder.rs

1use crate::{cobranca::{Cobranca, CodBarras, CodigoMoeda, CodBanco}, utils::date_to_fator_vencimento};
2use chrono::NaiveDate;
3
4impl Cobranca {
5    pub fn builder() -> CobrancaBuilder<NoCodBanco, NoCodMoeda> {
6        CobrancaBuilder::new()
7    }
8}
9
10pub struct NoCodMoeda;
11pub struct NoCodBanco;
12
13
14pub struct CobrancaBuilder<CB, CM> {
15    pub cod_banco: CB,
16    pub cod_moeda: CM,
17    pub data_vencimento: Option<NaiveDate>,
18    pub valor: Option<f64>,
19}
20
21impl CobrancaBuilder<NoCodBanco, NoCodMoeda> {
22    pub fn new() -> CobrancaBuilder<NoCodBanco, NoCodMoeda> {
23        Self {
24            cod_banco: NoCodBanco,
25            cod_moeda: NoCodMoeda,
26            data_vencimento: None,
27            valor: None,
28        }
29    }
30}
31
32impl<CM> CobrancaBuilder<NoCodBanco, CM> {
33    pub fn cod_banco(self, cod_banco: CodBanco) -> CobrancaBuilder<CodBanco, CM> {
34        CobrancaBuilder {
35            cod_banco: cod_banco,
36            cod_moeda: self.cod_moeda,
37            data_vencimento: self.data_vencimento,
38            valor: self.valor,
39        }
40    }
41}
42
43impl<CB> CobrancaBuilder<CB, NoCodMoeda> {
44    pub fn cod_moeda(self, cod_moeda: CodigoMoeda) -> CobrancaBuilder<CB, CodigoMoeda> {
45        CobrancaBuilder {
46            cod_banco: self.cod_banco,
47            cod_moeda: cod_moeda,
48            data_vencimento: self.data_vencimento,
49            valor: self.valor,
50        }
51    }
52}
53
54impl<CB, CM> CobrancaBuilder<CB, CM> {
55    pub fn data_vencimento(self, data_vencimento: NaiveDate) -> CobrancaBuilder<CB, CM> {
56        CobrancaBuilder {
57            cod_banco: self.cod_banco,
58            cod_moeda: self.cod_moeda,
59            data_vencimento: Some(data_vencimento),
60            valor: self.valor,
61        }
62    }
63}
64
65impl<CB, CM> CobrancaBuilder<CB, CM> {
66    pub fn valor(self, valor: f64) -> CobrancaBuilder<CB, CM> {
67        CobrancaBuilder {
68            cod_banco: self.cod_banco,
69            cod_moeda: self.cod_moeda,
70            data_vencimento: self.data_vencimento,
71            valor: Some(valor),
72        }
73    }
74}
75
76impl CobrancaBuilder<CodBanco, CodigoMoeda> {
77    pub fn build(self) -> Cobranca {
78        let cobranca = {
79            let mut result = [b'0'; 44];
80
81            let fator_vencimento = if let Some(data_vencimento) = self.data_vencimento {
82                date_to_fator_vencimento(data_vencimento).unwrap_or(0u16)
83            } else {
84                0u16
85            };
86
87            let valor = if let Some(valor) = self.valor {
88                (valor * 100.0).trunc() as u64
89            } else {
90                0u64
91            };
92
93            result[0..3].copy_from_slice(format!("{:03}", self.cod_banco.0).as_ref());
94            result[3] = self.cod_moeda.into();
95            result[5..9].copy_from_slice(format!("{:04}", fator_vencimento).as_ref());
96            result[9..19].copy_from_slice(format!("{:010}", valor).as_ref());
97
98            let mut cobranca = CodBarras::new(&result).unwrap();
99            cobranca.update_dv();
100
101            cobranca
102        };
103
104        Cobranca::new(cobranca.as_bytes()).unwrap()
105    }
106}