tempo_cli/models/
client_report.rs1use 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}