use chrono::NaiveDate; use chrono::NaiveTime; use serde::{Deserialize, Serialize}; /// Type of special day that affects timesheet calculations. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum SpecialDayType { #[serde(rename = "VACATION")] Vacation, #[serde(rename = "UNDERTIME")] Undertime, #[serde(rename = "HOLIDAY")] Holiday, #[serde(rename = "WEEKEND")] Weekend, } impl std::fmt::Display for SpecialDayType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { SpecialDayType::Vacation => write!(f, "VACATION"), SpecialDayType::Undertime => write!(f, "UNDERTIME"), SpecialDayType::Holiday => write!(f, "HOLIDAY"), SpecialDayType::Weekend => write!(f, "WEEKEND"), } } } /// A Timecard represents a single work period with start and end times. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Timecard { pub from_time: NaiveTime, pub to_time: NaiveTime, } impl Timecard { pub fn new(from_time: NaiveTime, to_time: NaiveTime) -> Self { Self { from_time, to_time } } } /// A Timesheet aggregates all time tracking information for a single day. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Timesheet { pub date: NaiveDate, #[serde(default)] pub is_sick_leave: bool, #[serde(default)] pub special_day_type: Option, pub timecards: Vec, } impl Timesheet { pub fn new(date: NaiveDate) -> Self { Self { date, is_sick_leave: false, special_day_type: None, timecards: Vec::new(), } } pub fn with_sick_leave(mut self, is_sick_leave: bool) -> Self { self.is_sick_leave = is_sick_leave; self } pub fn with_special_day_type(mut self, special_day_type: SpecialDayType) -> Self { self.special_day_type = Some(special_day_type); self } pub fn with_timecards(mut self, timecards: Vec) -> Self { self.timecards = timecards; self } }