summaryrefslogtreecommitdiff
path: root/schist_core/schist_models/src/budget_period_unit.rs
blob: 77d86417bf25e92d3f2aad813bd343639235be97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use core::fmt;
use std::str::FromStr;

use anyhow::{Result, bail};
use diesel::{backend::Backend, deserialize::{self, FromSql, FromSqlRow}, expression::AsExpression, serialize::{self, ToSql}, sql_types::Text, sqlite::Sqlite};
use serde::{Deserialize, Serialize};

#[derive(
    Eq,
    PartialEq,
    Serialize,
    Deserialize,
    Clone,
    Debug,
    AsExpression,
    FromSqlRow,
)]
#[diesel(sql_type=Text)]
pub enum BudgetPeriodUnit {
    Day,
    Month,
    Year,
}

impl fmt::Display for BudgetPeriodUnit {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            BudgetPeriodUnit::Day => "DAY".fmt(f),
            BudgetPeriodUnit::Month => "MONTH".fmt(f),
            BudgetPeriodUnit::Year => "YEAR".fmt(f),
        }
    }
}

impl FromStr for BudgetPeriodUnit {
    type Err = anyhow::Error;

    fn from_str(s: &str) -> Result<Self> {
        match s {
            "DAY" => Ok(BudgetPeriodUnit::Day),
            "MONTH" => Ok(BudgetPeriodUnit::Month),
            "YEAR" => Ok(BudgetPeriodUnit::Year),
            _ => bail!("\"{}\" is not a valid budget period unit. Valid values are: DAY, MONTH, YEAR", s),
        }
    }
}

impl ToSql<Text, Sqlite> for BudgetPeriodUnit {
    fn to_sql<'b>(
        &'b self,
        out: &mut diesel::serialize::Output<'b, '_, Sqlite>,
    ) -> serialize::Result {
        out.set_value(self.to_string());
        Ok(serialize::IsNull::No)
    }
}

impl FromSql<Text, Sqlite> for BudgetPeriodUnit {
    fn from_sql(bytes: <Sqlite as Backend>::RawValue<'_>) -> deserialize::Result<BudgetPeriodUnit> {
        let str = <String as FromSql<Text, Sqlite>>::from_sql(bytes)?;
        Ok(str.parse()?)
    }
}

#[cfg(test)]
mod test {
    use anyhow::Result;

    use super::BudgetPeriodUnit;

    #[test]
    fn display_when_day_then_day() {
        assert_eq!("DAY", format!("{}", BudgetPeriodUnit::Day));
    }

    #[test]
    fn display_when_month_then_month() {
        assert_eq!("MONTH", format!("{}", BudgetPeriodUnit::Month));
    }

    #[test]
    fn display_when_year_then_year() {
        assert_eq!("YEAR", format!("{}", BudgetPeriodUnit::Year));
    }

    #[test]
    fn from_str_when_day_then_day() {
        let result: Result<BudgetPeriodUnit> = "DAY".parse();
        assert!(result.is_ok());
        assert_eq!(BudgetPeriodUnit::Day, result.unwrap());
    }

    #[test]
    fn from_str_when_month_then_month() {
        let result: Result<BudgetPeriodUnit> = "MONTH".parse();
        assert!(result.is_ok());
        assert_eq!(BudgetPeriodUnit::Month, result.unwrap());
    }

    #[test]
    fn from_str_when_year_then_year() {
        let result: Result<BudgetPeriodUnit> = "YEAR".parse();
        assert!(result.is_ok());
        assert_eq!(BudgetPeriodUnit::Year, result.unwrap());
    }

    #[test]
    fn from_str_when_sentence_case_day_then_err() {
        let result: Result<BudgetPeriodUnit> = "Day".parse();
        assert!(result.is_err());
    }
}