Skip to main content

paycheck_utils/
deductions.rs

1//! Module for handling paycheck deductions.
2//! Defines structures and functions for managing pre-tax and post-tax deductions.
3
4/// Pre-tax deductions are applied before federal tax calculations.
5pub enum PreTaxDeduction {
6    Medical(Option<f32>),
7    Dental(Option<f32>),
8    Vision(Option<f32>),
9    Traditional401K(Option<f32>),
10    Roth401K(Option<f32>),
11    HSA(Option<f32>),
12    FSA(Option<f32>),
13}
14
15/// Post-tax deductions are applied after federal tax calculations
16pub enum PostTaxDeduction {
17    Roth401K(Option<f32>),
18    VoluntaryLife(Option<f32>),
19    VoluntaryADD(Option<f32>),
20    VoluntarySTD(Option<f32>),
21    VoluntaryLTD(Option<f32>),
22    WageGarnishment(Option<f32>), // e.g., child support, alimony
23}
24
25/// Struct to manage a collection of pre-tax deductions
26pub struct PreTaxDeductions {
27    pretax_deductions: Vec<PreTaxDeduction>,
28}
29
30/// Struct to manage a collection of post-tax deductions
31pub struct PostTaxDeductions {
32    posttax_deductions: Vec<PostTaxDeduction>,
33}
34
35impl PreTaxDeductions {
36    /// Create a new collection of pre-tax deductions
37    pub fn new(deductions: Vec<PreTaxDeduction>) -> Self {
38        PreTaxDeductions {
39            pretax_deductions: deductions,
40        }
41    }
42
43    /// Add multiple pre-tax deductions to the collection
44    pub fn add_pretax_deductions(&mut self, deductions: Vec<PreTaxDeduction>) {
45        self.pretax_deductions.extend(deductions);
46    }
47
48    /// Get a reference to the list of pre-tax deductions
49    pub fn get_pretax_deductions(&self) -> &Vec<PreTaxDeduction> {
50        &self.pretax_deductions
51    }
52
53    /// Calculate the total amount of pre-tax deductions
54    pub fn total_pretax_deductions(&self) -> f32 {
55        self.pretax_deductions
56            .iter()
57            .fold(0.0, |acc, deduction| match deduction {
58                PreTaxDeduction::Medical(amount)
59                | PreTaxDeduction::Dental(amount)
60                | PreTaxDeduction::Vision(amount)
61                | PreTaxDeduction::Traditional401K(amount)
62                | PreTaxDeduction::Roth401K(amount)
63                | PreTaxDeduction::HSA(amount)
64                | PreTaxDeduction::FSA(amount) => acc + amount.unwrap_or(0.0),
65            })
66    }
67}
68
69impl PostTaxDeductions {
70    /// Create a new collection of post-tax deductions
71    pub fn new(deductions: Vec<PostTaxDeduction>) -> Self {
72        PostTaxDeductions {
73            posttax_deductions: deductions,
74        }
75    }
76
77    /// Add multiple post-tax deductions to the collection
78    pub fn add_posttax_deductions(&mut self, deductions: Vec<PostTaxDeduction>) {
79        self.posttax_deductions.extend(deductions);
80    }
81
82    /// Get a reference to the list of post-tax deductions
83    pub fn get_posttax_deductions(&self) -> &Vec<PostTaxDeduction> {
84        &self.posttax_deductions
85    }
86
87    /// Calculate the total amount of post-tax deductions
88    pub fn total_posttax_deductions(&self) -> f32 {
89        self.posttax_deductions
90            .iter()
91            .fold(0.0, |acc, deduction| match deduction {
92                PostTaxDeduction::Roth401K(amount)
93                | PostTaxDeduction::VoluntaryLife(amount)
94                | PostTaxDeduction::VoluntaryADD(amount)
95                | PostTaxDeduction::VoluntarySTD(amount)
96                | PostTaxDeduction::VoluntaryLTD(amount)
97                | PostTaxDeduction::WageGarnishment(amount) => acc + amount.unwrap_or(0.0),
98            })
99    }
100}
101
102// UNIT TESTS FOR DEDUCTIONS MODULE
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107    use PostTaxDeduction::*;
108    use PreTaxDeduction::*;
109    #[test]
110    fn test_total_pretax_deductions() {
111        let deductions = PreTaxDeductions::new(vec![
112            Medical(Some(150.0)),
113            Dental(Some(50.0)),
114            Traditional401K(Some(200.0)),
115        ]);
116        let total = deductions.total_pretax_deductions();
117        assert_eq!(total, 400.0);
118    }
119    #[test]
120    fn test_get_pretax_deductions() {
121        let deductions = PreTaxDeductions::new(vec![
122            Medical(Some(150.0)),
123            Dental(Some(50.0)),
124            Traditional401K(Some(200.0)),
125        ]);
126        let pretax_list = deductions.get_pretax_deductions();
127        assert_eq!(pretax_list.len(), 3);
128    }
129    #[test]
130    fn test_add_pretax_deductions() {
131        let mut deductions = PreTaxDeductions::new(vec![Medical(Some(150.0))]);
132        deductions.add_pretax_deductions(vec![Dental(Some(50.0)), Traditional401K(Some(200.0))]);
133        let total = deductions.total_pretax_deductions();
134        assert_eq!(total, 400.0);
135    }
136    #[test]
137    fn test_total_posttax_deductions() {
138        let deductions = PostTaxDeductions::new(vec![
139            VoluntaryLife(Some(30.0)),
140            VoluntarySTD(Some(22.0)),
141            VoluntaryLTD(Some(34.0)),
142            WageGarnishment(Some(600.0)),
143        ]);
144        let total = deductions.total_posttax_deductions();
145        assert_eq!(total, 686.0);
146    }
147    #[test]
148    fn test_get_posttax_deductions() {
149        let deductions = PostTaxDeductions::new(vec![
150            VoluntaryLife(Some(30.0)),
151            VoluntarySTD(Some(22.0)),
152            VoluntaryLTD(Some(34.0)),
153            WageGarnishment(Some(600.0)),
154        ]);
155        let posttax_list = deductions.get_posttax_deductions();
156        assert_eq!(posttax_list.len(), 4);
157    }
158    #[test]
159    fn test_add_posttax_deductions() {
160        let mut deductions = PostTaxDeductions::new(vec![VoluntaryLife(Some(30.0))]);
161        deductions.add_posttax_deductions(vec![
162            VoluntarySTD(Some(22.0)),
163            VoluntaryLTD(Some(34.0)),
164            WageGarnishment(Some(600.0)),
165        ]);
166        let total = deductions.total_posttax_deductions();
167        assert_eq!(total, 686.0);
168    }
169}