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