Skip to main content

klirr_core/models/
valid_input.rs

1use crate::prelude::*;
2
3/// Input which has been validated and is ready for processing.
4/// Controls which language to use, the month for which to generate the invoice,
5/// the items to be invoiced, the layout of the invoice, and an optional output path
6/// for the generated PDF file.
7#[derive(Debug, Clone, Display, Builder, Getters)]
8#[display("Layout: {}, Period: {}, out: {:?}, items: {}, language: {}", layout, period, maybe_output_path.as_ref().map(|d|d.display()), items, language)]
9pub struct ValidInput {
10    /// The language to use for the invoice, used on labels, headers etc.
11    /// Defaults to English (`Language::EN`).
12    #[builder(default)]
13    #[getset(get = "pub")]
14    language: Language,
15
16    /// The period for which to generate the invoice, this affects the invoice
17    /// number as well as the invoice date and due date.
18    ///
19    /// Note: We use the period type with the highest granularity, so that we
20    /// always can convert it to a kind of period of more coarse granularity.
21    /// For example, if the period is `YearMonthAndFortnight`, we can always
22    /// convert it to `YearAndMonth` later in the flow if that matches the invoice
23    /// cadence.
24    #[getset(get = "pub")]
25    period: YearMonthAndFortnight,
26
27    /// The items to be invoiced, either services or expenses.
28    #[builder(default)]
29    #[getset(get = "pub")]
30    items: InvoicedItems,
31
32    /// The layout of the invoice to use
33    #[builder(default)]
34    #[getset(get = "pub")]
35    layout: Layout,
36
37    /// An optional override of where to save the output PDF file.
38    #[getset(get = "pub")]
39    maybe_output_path: Option<PathBuf>,
40
41    /// If set, the invoice will be sent via email after generation.
42    ///
43    /// If set to true but email is not configured, an error will be thrown later.
44    #[getset(get = "pub")]
45    email: Option<DecryptedEmailSettings>,
46}
47
48impl HasSample for ValidInput {
49    fn sample() -> Self {
50        Self::builder()
51            .period(YearMonthAndFortnight::sample())
52            .items(InvoicedItems::sample())
53            .maybe_output_path(PathBuf::from("invoice.pdf"))
54            .build()
55    }
56
57    fn sample_other() -> Self {
58        Self::builder()
59            .period(YearMonthAndFortnight::sample_other())
60            .items(InvoicedItems::sample_other())
61            .build()
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68    use test_log::test;
69
70    type Sut = ValidInput;
71
72    #[test]
73    fn valid_input_sample() {
74        let sample = Sut::sample();
75        assert!(sample.maybe_output_path.is_some());
76    }
77
78    #[test]
79    fn valid_input_sample_other() {
80        let sample = Sut::sample_other();
81        assert!(sample.maybe_output_path.is_none());
82    }
83}