Skip to main content

rust_viewflow/core/workflows/
leave_request.rs

1use async_trait::async_trait;
2use chrono;
3use serde_json;
4use std::sync::Arc;
5
6use crate::core::engine::generate_id;
7use crate::core::{
8    TaskState, TaskStatus, WorkflowDefinition, WorkflowResult, WorkflowState, WorkflowStatus,
9};
10use crate::db::WorkflowDatabase;
11
12/// Leave request workflow definition
13pub struct LeaveRequestWorkflow {
14    database: Arc<dyn WorkflowDatabase>,
15}
16
17impl LeaveRequestWorkflow {
18    pub fn new(database: Arc<dyn WorkflowDatabase>) -> Self {
19        Self { database }
20    }
21
22    fn task_name(locale: &str, stage: &str) -> &'static str {
23        match (locale, stage) {
24            ("zh-CN", "manager") => "直属经理审批",
25            ("zh-CN", "hr") => "HR 备案",
26            ("zh-TW", "manager") => "直屬主管審批",
27            ("zh-TW", "hr") => "HR 備案",
28            (_, "manager") => "Manager Approval",
29            (_, "hr") => "HR Approval",
30            _ => "Task",
31        }
32    }
33}
34
35#[async_trait]
36impl WorkflowDefinition for LeaveRequestWorkflow {
37    fn name(&self) -> &str {
38        "leave_request"
39    }
40
41    async fn start(&self, data: serde_json::Value) -> WorkflowResult<WorkflowState> {
42        let now = chrono::Utc::now();
43        let workflow_id = generate_id();
44        let locale = data.get("locale").and_then(|v| v.as_str()).unwrap_or("en");
45
46        let workflow = WorkflowState {
47            id: workflow_id.clone(),
48            name: self.name().to_string(),
49            status: WorkflowStatus::Running,
50            data: data.clone(),
51            created_at: now,
52            updated_at: now,
53        };
54
55        self.database.create_workflow(&workflow).await?;
56
57        let manager_task = TaskState {
58            id: generate_id(),
59            workflow_id: workflow_id.clone(),
60            name: Self::task_name(locale, "manager").to_string(),
61            status: TaskStatus::Pending,
62            assignee: data
63                .get("manager_id")
64                .and_then(|v| v.as_str())
65                .map(|s| s.to_string()),
66            data: data.clone(),
67            created_at: now,
68            updated_at: now,
69            completed_at: None,
70        };
71
72        self.database.create_task(&manager_task).await?;
73
74        Ok(workflow)
75    }
76
77    async fn execute_task(
78        &self,
79        task_id: &str,
80        data: serde_json::Value,
81    ) -> WorkflowResult<TaskState> {
82        let mut task = self.database.get_task(task_id).await?;
83        let locale = data
84            .get("locale")
85            .and_then(|v| v.as_str())
86            .or_else(|| task.data.get("locale").and_then(|v| v.as_str()))
87            .unwrap_or("en");
88
89        if data
90            .get("approved")
91            .and_then(|v| v.as_bool())
92            .unwrap_or(false)
93        {
94            task.status = TaskStatus::Completed;
95            task.completed_at = Some(chrono::Utc::now());
96
97            if task.name.contains("Manager")
98                || task.name.contains("经理")
99                || task.name.contains("主管")
100            {
101                let hr_task = TaskState {
102                    id: generate_id(),
103                    workflow_id: task.workflow_id.clone(),
104                    name: Self::task_name(locale, "hr").to_string(),
105                    status: TaskStatus::Pending,
106                    assignee: data
107                        .get("hr_id")
108                        .and_then(|v| v.as_str())
109                        .map(|s| s.to_string())
110                        .or_else(|| Some("hr@example.com".to_string())),
111                    data: data.clone(),
112                    created_at: chrono::Utc::now(),
113                    updated_at: chrono::Utc::now(),
114                    completed_at: None,
115                };
116                self.database.create_task(&hr_task).await?;
117            } else {
118                let mut workflow = self.database.get_workflow(&task.workflow_id).await?;
119                workflow.status = WorkflowStatus::Completed;
120                workflow.updated_at = chrono::Utc::now();
121                self.database.update_workflow(&workflow).await?;
122            }
123        } else {
124            task.status = TaskStatus::Cancelled;
125            task.completed_at = Some(chrono::Utc::now());
126
127            let mut workflow = self.database.get_workflow(&task.workflow_id).await?;
128            workflow.status = WorkflowStatus::Cancelled;
129            workflow.updated_at = chrono::Utc::now();
130            self.database.update_workflow(&workflow).await?;
131        }
132
133        task.data = data;
134        task.updated_at = chrono::Utc::now();
135
136        self.database.update_task(&task).await?;
137
138        Ok(task)
139    }
140
141    async fn get_tasks(&self, workflow_id: &str) -> WorkflowResult<Vec<TaskState>> {
142        self.database.get_tasks_by_workflow(workflow_id).await
143    }
144}