feat(export): add project lifecycle export
zhenyi committed
Added lib/export/project/lifecycle.rs lib/export/project/lifecycle.rs +127 −0 View lib/export/project/lifecycle.rs
@@ -0,0 +1,127 @@
1use db::project::project_state::ProjectState as DbState;
2use serde::{Deserialize, Serialize};
3use time::OffsetDateTime;
4use utoipa::ToSchema;
5use uuid::Uuid;
6use validator::Validate;
7
8#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, PartialEq)]
9#[serde(rename_all = "snake_case")]
10pub enum ProjectState {
11 Backlog,
12 Planned,
13 InProgress,
14 Paused,
15 Completed,
16 Cancelled,
17}
18
19impl From<DbState> for ProjectState {
20 fn from(s: DbState) -> Self {
21 match s {
22 DbState::Backlog => Self::Backlog,
23 DbState::Planned => Self::Planned,
24 DbState::InProgress => Self::InProgress,
25 DbState::Paused => Self::Paused,
26 DbState::Completed => Self::Completed,
27 DbState::Cancelled => Self::Cancelled,
28 }
29 }
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
33#[serde(rename_all = "snake_case")]
34pub enum ProjectHealth {
35 OnTrack,
36 AtRisk,
37 OffTrack,
38 None,
39}
40
41impl From<Option<db::project::project_health::ProjectHealth>> for ProjectHealth {
42 fn from(h: Option<db::project::project_health::ProjectHealth>) -> Self {
43 match h {
44 Some(db::project::project_health::ProjectHealth::OnTrack) => Self::OnTrack,
45 Some(db::project::project_health::ProjectHealth::AtRisk) => Self::AtRisk,
46 Some(db::project::project_health::ProjectHealth::OffTrack) => Self::OffTrack,
47 None => Self::None,
48 }
49 }
50}
51
52#[derive(Debug, Clone, Deserialize, Validate, ToSchema)]
53pub struct CreateProjectCmd {
54 pub space_id: Uuid,
55 #[validate(length(min = 1, max = 100))]
56 pub name: String,
57 #[validate(length(max = 2000))]
58 pub description: Option<String>,
59 pub lead_id: Option<Uuid>,
60 pub icon: Option<String>,
61 pub color: Option<String>,
62 pub target_date: Option<time::Date>,
63}
64
65#[derive(Debug, Clone, Deserialize, Validate, ToSchema)]
66pub struct UpdateProjectCmd {
67 #[validate(length(min = 1, max = 100))]
68 pub name: Option<String>,
69 #[validate(length(max = 2000))]
70 pub description: Option<String>,
71 pub lead_id: Option<Uuid>,
72 pub icon: Option<String>,
73 pub color: Option<String>,
74 pub state: Option<ProjectState>,
75 pub target_date: Option<time::Date>,
76 pub health: Option<ProjectHealth>,
77 pub sort_order: Option<i32>,
78}
79
80#[derive(Debug, Clone, Serialize, ToSchema)]
81pub struct ProjectView {
82 pub id: Uuid,
83 pub space_id: Uuid,
84 pub creator_id: Uuid,
85 pub lead_id: Option<Uuid>,
86 pub name: String,
87 pub description: Option<String>,
88 pub icon: Option<String>,
89 pub color: Option<String>,
90 pub state: ProjectState,
91 pub target_date: Option<time::Date>,
92 pub started_at: Option<OffsetDateTime>,
93 pub completed_at: Option<OffsetDateTime>,
94 pub cancelled_at: Option<OffsetDateTime>,
95 pub health: ProjectHealth,
96 pub sort_order: i32,
97 pub starred: i32,
98 pub created_at: OffsetDateTime,
99 pub updated_at: Option<OffsetDateTime>,
100}
101
102#[derive(Debug, Clone, Serialize, ToSchema)]
103pub struct ProjectPage {
104 pub total: u64,
105 pub items: Vec<ProjectView>,
106}
107
108#[derive(Debug, Clone, Deserialize, ToSchema)]
109pub struct ListProjectQuery {
110 pub space_id: Uuid,
111 pub state: Option<ProjectState>,
112 pub lead_id: Option<Uuid>,
113 pub starred_only: Option<bool>,
114 pub q: Option<String>,
115 #[serde(default = "default_page")]
116 pub page: u64,
117 #[serde(default = "default_per_page")]
118 pub per_page: u64,
119}
120
121fn default_page() -> u64 {
122 1
123}
124
125fn default_per_page() -> u64 {
126 20
127}