1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Default, Serialize)]
5pub struct UpdateTimeEntry {
6 #[serde(skip_serializing_if = "Option::is_none")]
7 pub project_id: Option<Option<i64>>,
8 #[serde(skip_serializing_if = "Option::is_none")]
9 pub description: Option<String>,
10 #[serde(skip_serializing_if = "Option::is_none")]
11 pub billable: Option<bool>,
12 #[serde(skip_serializing_if = "Option::is_none")]
13 pub tags: Option<Vec<String>>,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub tag_ids: Option<Vec<i64>>,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 pub start: Option<DateTime<Utc>>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub stop: Option<Option<DateTime<Utc>>>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub duration: Option<i64>,
22}
23
24impl UpdateTimeEntry {
25 pub fn project_id(project_id: Option<i64>) -> Self {
26 Self {
27 project_id: Some(project_id),
28 ..Self::default()
29 }
30 }
31
32 pub fn description(description: impl Into<String>) -> Self {
33 Self {
34 description: Some(description.into()),
35 ..Self::default()
36 }
37 }
38}
39
40#[derive(Debug, Clone, Serialize)]
41pub struct StartTimeEntry {
42 pub workspace_id: i64,
43 pub start: DateTime<Utc>,
44 pub duration: i64,
45 pub created_with: String,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub description: Option<String>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 pub project_id: Option<i64>,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub task_id: Option<i64>,
52 #[serde(skip_serializing_if = "Option::is_none")]
53 pub billable: Option<bool>,
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub tags: Option<Vec<String>>,
56 #[serde(skip_serializing_if = "Option::is_none")]
57 pub tag_ids: Option<Vec<i64>>,
58}
59
60impl StartTimeEntry {
61 pub fn new(workspace_id: i64, created_with: impl Into<String>) -> Self {
62 Self {
63 workspace_id,
64 start: Utc::now(),
65 duration: -1,
66 created_with: created_with.into(),
67 description: None,
68 project_id: None,
69 task_id: None,
70 billable: None,
71 tags: None,
72 tag_ids: None,
73 }
74 }
75
76 pub fn description(mut self, description: impl Into<String>) -> Self {
77 self.description = Some(description.into());
78 self
79 }
80
81 pub fn project_id(mut self, project_id: i64) -> Self {
82 self.project_id = Some(project_id);
83 self
84 }
85}
86
87#[derive(Debug, Clone, Serialize)]
88pub struct BulkUpdateOperation {
89 pub op: String,
90 pub path: String,
91 pub value: serde_json::Value,
92}
93
94impl BulkUpdateOperation {
95 pub fn replace(path: impl Into<String>, value: serde_json::Value) -> Self {
96 Self {
97 op: "replace".to_string(),
98 path: path.into(),
99 value,
100 }
101 }
102}
103
104#[derive(Debug, Clone, Deserialize)]
105pub struct BulkUpdateResponse {
106 #[serde(default)]
107 pub success: Vec<i64>,
108 #[serde(default)]
109 pub failure: Vec<BulkUpdateFailure>,
110}
111
112#[derive(Debug, Clone, Deserialize)]
113pub struct BulkUpdateFailure {
114 pub id: i64,
115 pub message: String,
116}