tempo_cli/models/
client_report.rs

1use chrono::{DateTime, NaiveDate, Utc};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
5pub struct ClientReport {
6    pub id: Option<i64>,
7    pub client_name: String,
8    pub project_id: Option<i64>,
9    pub report_period_start: NaiveDate,
10    pub report_period_end: NaiveDate,
11    pub total_hours: f64,
12    pub hourly_rate: Option<f64>,
13    pub notes: Option<String>,
14    pub status: ReportStatus,
15    pub created_at: DateTime<Utc>,
16    pub sent_at: Option<DateTime<Utc>>,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
20pub enum ReportStatus {
21    Draft,
22    Sent,
23    Paid,
24}
25
26impl std::fmt::Display for ReportStatus {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        match self {
29            ReportStatus::Draft => write!(f, "draft"),
30            ReportStatus::Sent => write!(f, "sent"),
31            ReportStatus::Paid => write!(f, "paid"),
32        }
33    }
34}
35
36impl ClientReport {
37    pub fn new(
38        client_name: String,
39        report_period_start: NaiveDate,
40        report_period_end: NaiveDate,
41        total_hours: f64,
42    ) -> Self {
43        Self {
44            id: None,
45            client_name,
46            project_id: None,
47            report_period_start,
48            report_period_end,
49            total_hours,
50            hourly_rate: None,
51            notes: None,
52            status: ReportStatus::Draft,
53            created_at: Utc::now(),
54            sent_at: None,
55        }
56    }
57
58    pub fn total_amount(&self) -> Option<f64> {
59        self.hourly_rate.map(|rate| rate * self.total_hours)
60    }
61
62    pub fn mark_sent(&mut self) {
63        self.status = ReportStatus::Sent;
64        self.sent_at = Some(Utc::now());
65    }
66
67    pub fn mark_paid(&mut self) {
68        self.status = ReportStatus::Paid;
69    }
70}
71