1use crate::{project::Project, source::Source};
4use serde::{Deserialize, Serialize};
5use zino_core::{
6 Map, Uuid,
7 datetime::DateTime,
8 error::Error,
9 extension::JsonObjectExt,
10 model::{Model, ModelHooks},
11 validation::Validation,
12};
13use zino_derive::{DecodeRow, Entity, ModelAccessor, Schema};
14
15#[cfg(feature = "tags")]
16use crate::tag::Tag;
17
18#[cfg(any(feature = "owner-id", feature = "maintainer-id"))]
19use crate::user::User;
20
21#[cfg(feature = "maintainer-id")]
22use zino_auth::UserSession;
23
24#[derive(
26 Debug, Clone, Default, Serialize, Deserialize, DecodeRow, Entity, Schema, ModelAccessor,
27)]
28#[serde(default)]
29#[schema(auto_rename)]
30pub struct Task {
31 #[schema(read_only)]
33 id: Uuid,
34 #[schema(not_null)]
35 name: String,
36 #[cfg(feature = "namespace")]
37 #[schema(default_value = "Task::model_namespace", index_type = "hash")]
38 namespace: String,
39 #[cfg(feature = "visibility")]
40 #[schema(default_value = "Internal")]
41 visibility: String,
42 #[schema(default_value = "Active", index_type = "hash")]
43 status: String,
44 description: String,
45
46 #[schema(reference = "Project")]
48 project_id: Uuid, #[schema(reference = "Source")]
50 input_id: Uuid, #[schema(reference = "Source")]
52 output_id: Option<Uuid>, #[schema(reference = "Task", index_type = "gin")]
54 dependencies: Vec<Uuid>, valid_from: DateTime,
56 expires_at: DateTime,
57 schedule: String,
58 last_time: DateTime,
59 next_time: DateTime,
60 priority: u16,
61 #[cfg(feature = "tags")]
62 #[schema(reference = "Tag", index_type = "gin")]
63 tags: Vec<Uuid>, extra: Map,
67
68 #[cfg(feature = "owner-id")]
70 #[schema(reference = "User")]
71 owner_id: Option<Uuid>, #[cfg(feature = "maintainer-id")]
73 #[schema(reference = "User")]
74 maintainer_id: Option<Uuid>, #[schema(read_only, default_value = "now", index_type = "btree")]
76 created_at: DateTime,
77 #[schema(default_value = "now", index_type = "btree")]
78 updated_at: DateTime,
79 version: u64,
80 #[cfg(feature = "edition")]
81 edition: u32,
82}
83
84impl Model for Task {
85 const MODEL_NAME: &'static str = "task";
86
87 #[inline]
88 fn new() -> Self {
89 Self {
90 id: Uuid::now_v7(),
91 ..Self::default()
92 }
93 }
94
95 fn read_map(&mut self, data: &Map) -> Validation {
96 let mut validation = Validation::new();
97 if let Some(result) = data.parse_uuid("id") {
98 match result {
99 Ok(id) => self.id = id,
100 Err(err) => validation.record_fail("id", err),
101 }
102 }
103 if let Some(name) = data.parse_string("name") {
104 self.name = name.into_owned();
105 }
106 if let Some(description) = data.parse_string("description") {
107 self.description = description.into_owned();
108 }
109 #[cfg(feature = "tags")]
110 if let Some(result) = data.parse_array("tags") {
111 match result {
112 Ok(tags) => self.tags = tags,
113 Err(err) => validation.record_fail("tags", err),
114 }
115 }
116 #[cfg(feature = "owner-id")]
117 if let Some(result) = data.parse_uuid("owner_id") {
118 match result {
119 Ok(owner_id) => self.owner_id = Some(owner_id),
120 Err(err) => validation.record_fail("owner_id", err),
121 }
122 }
123 #[cfg(feature = "maintainer-id")]
124 if let Some(result) = data.parse_uuid("maintainer_id") {
125 match result {
126 Ok(maintainer_id) => self.maintainer_id = Some(maintainer_id),
127 Err(err) => validation.record_fail("maintainer_id", err),
128 }
129 }
130 validation
131 }
132}
133
134impl ModelHooks for Task {
135 type Data = ();
136 #[cfg(feature = "maintainer-id")]
137 type Extension = UserSession<Uuid, String>;
138 #[cfg(not(feature = "maintainer-id"))]
139 type Extension = ();
140
141 #[cfg(feature = "maintainer-id")]
142 #[inline]
143 async fn after_extract(&mut self, session: Self::Extension) -> Result<(), Error> {
144 self.maintainer_id = Some(*session.user_id());
145 Ok(())
146 }
147
148 #[cfg(feature = "maintainer-id")]
149 #[inline]
150 async fn before_validation(
151 data: &mut Map,
152 extension: Option<&Self::Extension>,
153 ) -> Result<(), Error> {
154 if let Some(session) = extension {
155 data.upsert("maintainer_id", session.user_id().to_string());
156 }
157 Ok(())
158 }
159}