1use chrono::{DateTime, Utc, NaiveDate};
2use serde::{Deserialize, Serialize};
3use sqlx::FromRow;
4use uuid::Uuid;
5use rust_decimal::Decimal;
6
7use super::RequestKanbanState;
8use super::RequestPriority;
9use super::MaintenanceType;
10use super::RepeatUnit;
11use super::RepeatType;
12use super::AuditMetadata;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
16#[serde(transparent)]
17pub struct MaintenanceRequestId(pub Uuid);
18
19impl MaintenanceRequestId {
20 pub fn new(id: Uuid) -> Self { Self(id) }
21 pub fn generate() -> Self { Self(Uuid::new_v4()) }
22 pub fn into_inner(self) -> Uuid { self.0 }
23}
24
25impl std::fmt::Display for MaintenanceRequestId {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 write!(f, "{}", self.0)
28 }
29}
30
31impl std::str::FromStr for MaintenanceRequestId {
32 type Err = uuid::Error;
33 fn from_str(s: &str) -> Result<Self, Self::Err> {
34 Ok(Self(Uuid::parse_str(s)?))
35 }
36}
37
38impl From<Uuid> for MaintenanceRequestId {
39 fn from(id: Uuid) -> Self { Self(id) }
40}
41
42impl From<MaintenanceRequestId> for Uuid {
43 fn from(id: MaintenanceRequestId) -> Self { id.0 }
44}
45
46impl AsRef<Uuid> for MaintenanceRequestId {
47 fn as_ref(&self) -> &Uuid { &self.0 }
48}
49
50impl std::ops::Deref for MaintenanceRequestId {
51 type Target = Uuid;
52 fn deref(&self) -> &Self::Target { &self.0 }
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
56pub struct MaintenanceRequest {
57 pub id: Uuid,
58 pub name: String,
59 pub description: Option<String>,
60 pub request_date: NaiveDate,
61 pub schedule_date: Option<DateTime<Utc>>,
62 pub schedule_end: Option<DateTime<Utc>>,
63 pub close_date: Option<NaiveDate>,
64 pub duration: Decimal,
65 pub owner_user_id: Option<Uuid>,
66 pub user_id: Option<Uuid>,
67 pub asset_id: Option<Uuid>,
68 pub stage_id: Uuid,
69 pub kanban_state: RequestKanbanState,
70 pub priority: RequestPriority,
71 pub maintenance_type: MaintenanceType,
72 pub recurring: bool,
73 pub repeat_interval: i32,
74 pub repeat_unit: RepeatUnit,
75 pub repeat_type: RepeatType,
76 pub repeat_until: Option<NaiveDate>,
77 pub successor_request_id: Option<Uuid>,
78 pub successor_of_request_id: Option<Uuid>,
79 #[serde(default)]
80 #[sqlx(json)]
81 pub metadata: AuditMetadata,
82}
83
84impl MaintenanceRequest {
85 pub fn builder() -> MaintenanceRequestBuilder {
87 <MaintenanceRequestBuilder as Default>::default()
88 }
89
90 pub fn new(name: String, request_date: NaiveDate, duration: Decimal, stage_id: Uuid, kanban_state: RequestKanbanState, priority: RequestPriority, maintenance_type: MaintenanceType, recurring: bool, repeat_interval: i32, repeat_unit: RepeatUnit, repeat_type: RepeatType) -> Self {
92 Self {
93 id: Uuid::new_v4(),
94 name,
95 description: None,
96 request_date,
97 schedule_date: None,
98 schedule_end: None,
99 close_date: None,
100 duration,
101 owner_user_id: None,
102 user_id: None,
103 asset_id: None,
104 stage_id,
105 kanban_state,
106 priority,
107 maintenance_type,
108 recurring,
109 repeat_interval,
110 repeat_unit,
111 repeat_type,
112 repeat_until: None,
113 successor_request_id: None,
114 successor_of_request_id: None,
115 metadata: AuditMetadata::default(),
116 }
117 }
118
119 pub fn id(&self) -> &Uuid {
121 &self.id
122 }
123
124 pub fn typed_id(&self) -> MaintenanceRequestId {
126 MaintenanceRequestId(self.id)
127 }
128
129 pub fn created_at(&self) -> Option<&DateTime<Utc>> {
131 self.metadata.created_at.as_ref()
132 }
133
134 pub fn updated_at(&self) -> Option<&DateTime<Utc>> {
136 self.metadata.updated_at.as_ref()
137 }
138
139 pub fn is_deleted(&self) -> bool {
141 self.metadata.deleted_at.is_some()
142 }
143
144 pub fn is_active(&self) -> bool {
146 self.metadata.deleted_at.is_none()
147 }
148
149 pub fn deleted_at(&self) -> Option<&DateTime<Utc>> {
151 self.metadata.deleted_at.as_ref()
152 }
153
154 pub fn created_by(&self) -> Option<&Uuid> {
156 self.metadata.created_by.as_ref()
157 }
158
159 pub fn updated_by(&self) -> Option<&Uuid> {
161 self.metadata.updated_by.as_ref()
162 }
163
164 pub fn deleted_by(&self) -> Option<&Uuid> {
166 self.metadata.deleted_by.as_ref()
167 }
168
169
170 pub fn with_description(mut self, value: String) -> Self {
176 self.description = Some(value);
177 self
178 }
179
180 pub fn with_schedule_date(mut self, value: DateTime<Utc>) -> Self {
182 self.schedule_date = Some(value);
183 self
184 }
185
186 pub fn with_schedule_end(mut self, value: DateTime<Utc>) -> Self {
188 self.schedule_end = Some(value);
189 self
190 }
191
192 pub fn with_close_date(mut self, value: NaiveDate) -> Self {
194 self.close_date = Some(value);
195 self
196 }
197
198 pub fn with_owner_user_id(mut self, value: Uuid) -> Self {
200 self.owner_user_id = Some(value);
201 self
202 }
203
204 pub fn with_user_id(mut self, value: Uuid) -> Self {
206 self.user_id = Some(value);
207 self
208 }
209
210 pub fn with_asset_id(mut self, value: Uuid) -> Self {
212 self.asset_id = Some(value);
213 self
214 }
215
216 pub fn with_repeat_until(mut self, value: NaiveDate) -> Self {
218 self.repeat_until = Some(value);
219 self
220 }
221
222 pub fn with_successor_request_id(mut self, value: Uuid) -> Self {
224 self.successor_request_id = Some(value);
225 self
226 }
227
228 pub fn with_successor_of_request_id(mut self, value: Uuid) -> Self {
230 self.successor_of_request_id = Some(value);
231 self
232 }
233
234 pub fn apply_patch(&mut self, fields: std::collections::HashMap<String, serde_json::Value>) {
240 for (key, value) in fields {
241 match key.as_str() {
242 "name" => {
243 if let Ok(v) = serde_json::from_value(value) { self.name = v; }
244 }
245 "description" => {
246 if let Ok(v) = serde_json::from_value(value) { self.description = v; }
247 }
248 "request_date" => {
249 if let Ok(v) = serde_json::from_value(value) { self.request_date = v; }
250 }
251 "schedule_date" => {
252 if let Ok(v) = serde_json::from_value(value) { self.schedule_date = v; }
253 }
254 "schedule_end" => {
255 if let Ok(v) = serde_json::from_value(value) { self.schedule_end = v; }
256 }
257 "close_date" => {
258 if let Ok(v) = serde_json::from_value(value) { self.close_date = v; }
259 }
260 "duration" => {
261 if let Ok(v) = serde_json::from_value(value) { self.duration = v; }
262 }
263 "owner_user_id" => {
264 if let Ok(v) = serde_json::from_value(value) { self.owner_user_id = v; }
265 }
266 "user_id" => {
267 if let Ok(v) = serde_json::from_value(value) { self.user_id = v; }
268 }
269 "asset_id" => {
270 if let Ok(v) = serde_json::from_value(value) { self.asset_id = v; }
271 }
272 "stage_id" => {
273 if let Ok(v) = serde_json::from_value(value) { self.stage_id = v; }
274 }
275 "kanban_state" => {
276 if let Ok(v) = serde_json::from_value(value) { self.kanban_state = v; }
277 }
278 "priority" => {
279 if let Ok(v) = serde_json::from_value(value) { self.priority = v; }
280 }
281 "maintenance_type" => {
282 if let Ok(v) = serde_json::from_value(value) { self.maintenance_type = v; }
283 }
284 "recurring" => {
285 if let Ok(v) = serde_json::from_value(value) { self.recurring = v; }
286 }
287 "repeat_interval" => {
288 if let Ok(v) = serde_json::from_value(value) { self.repeat_interval = v; }
289 }
290 "repeat_unit" => {
291 if let Ok(v) = serde_json::from_value(value) { self.repeat_unit = v; }
292 }
293 "repeat_type" => {
294 if let Ok(v) = serde_json::from_value(value) { self.repeat_type = v; }
295 }
296 "repeat_until" => {
297 if let Ok(v) = serde_json::from_value(value) { self.repeat_until = v; }
298 }
299 "successor_request_id" => {
300 if let Ok(v) = serde_json::from_value(value) { self.successor_request_id = v; }
301 }
302 "successor_of_request_id" => {
303 if let Ok(v) = serde_json::from_value(value) { self.successor_of_request_id = v; }
304 }
305 _ => {} }
307 }
308 }
309
310 }
313
314impl super::Entity for MaintenanceRequest {
315 type Id = Uuid;
316
317 fn entity_id(&self) -> &Self::Id {
318 &self.id
319 }
320
321 fn entity_type() -> &'static str {
322 "MaintenanceRequest"
323 }
324}
325
326impl backbone_core::PersistentEntity for MaintenanceRequest {
327 fn entity_id(&self) -> String {
328 self.id.to_string()
329 }
330 fn set_entity_id(&mut self, id: String) {
331 if let Ok(uuid) = uuid::Uuid::parse_str(&id) {
332 self.id = uuid;
333 }
334 }
335 fn created_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
336 self.metadata.created_at
337 }
338 fn set_created_at(&mut self, ts: chrono::DateTime<chrono::Utc>) {
339 self.metadata.created_at = Some(ts);
340 }
341 fn updated_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
342 self.metadata.updated_at
343 }
344 fn set_updated_at(&mut self, ts: chrono::DateTime<chrono::Utc>) {
345 self.metadata.updated_at = Some(ts);
346 }
347 fn deleted_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
348 self.metadata.deleted_at
349 }
350 fn set_deleted_at(&mut self, ts: Option<chrono::DateTime<chrono::Utc>>) {
351 self.metadata.deleted_at = ts;
352 }
353}
354
355impl backbone_orm::EntityRepoMeta for MaintenanceRequest {
356 fn column_types() -> std::collections::HashMap<String, String> {
357 let mut m = std::collections::HashMap::new();
358 m.insert("id".to_string(), "uuid".to_string());
359 m.insert("owner_user_id".to_string(), "uuid".to_string());
360 m.insert("user_id".to_string(), "uuid".to_string());
361 m.insert("asset_id".to_string(), "uuid".to_string());
362 m.insert("stage_id".to_string(), "uuid".to_string());
363 m.insert("successor_request_id".to_string(), "uuid".to_string());
364 m.insert("successor_of_request_id".to_string(), "uuid".to_string());
365 m.insert("kanban_state".to_string(), "request_kanban_state".to_string());
366 m.insert("priority".to_string(), "request_priority".to_string());
367 m.insert("maintenance_type".to_string(), "maintenance_type".to_string());
368 m.insert("repeat_unit".to_string(), "repeat_unit".to_string());
369 m.insert("repeat_type".to_string(), "repeat_type".to_string());
370 m.insert("request_date".to_string(), "date".to_string());
371 m.insert("schedule_date".to_string(), "timestamptz".to_string());
372 m.insert("schedule_end".to_string(), "timestamptz".to_string());
373 m.insert("close_date".to_string(), "date".to_string());
374 m.insert("repeat_until".to_string(), "date".to_string());
375 m
376 }
377 fn search_fields() -> &'static [&'static str] {
378 &["name"]
379 }
380}
381
382#[derive(Debug, Clone, Default)]
387pub struct MaintenanceRequestBuilder {
388 name: Option<String>,
389 description: Option<String>,
390 request_date: Option<NaiveDate>,
391 schedule_date: Option<DateTime<Utc>>,
392 schedule_end: Option<DateTime<Utc>>,
393 close_date: Option<NaiveDate>,
394 duration: Option<Decimal>,
395 owner_user_id: Option<Uuid>,
396 user_id: Option<Uuid>,
397 asset_id: Option<Uuid>,
398 stage_id: Option<Uuid>,
399 kanban_state: Option<RequestKanbanState>,
400 priority: Option<RequestPriority>,
401 maintenance_type: Option<MaintenanceType>,
402 recurring: Option<bool>,
403 repeat_interval: Option<i32>,
404 repeat_unit: Option<RepeatUnit>,
405 repeat_type: Option<RepeatType>,
406 repeat_until: Option<NaiveDate>,
407 successor_request_id: Option<Uuid>,
408 successor_of_request_id: Option<Uuid>,
409}
410
411impl MaintenanceRequestBuilder {
412 pub fn name(mut self, value: String) -> Self {
414 self.name = Some(value);
415 self
416 }
417
418 pub fn description(mut self, value: String) -> Self {
420 self.description = Some(value);
421 self
422 }
423
424 pub fn request_date(mut self, value: NaiveDate) -> Self {
426 self.request_date = Some(value);
427 self
428 }
429
430 pub fn schedule_date(mut self, value: DateTime<Utc>) -> Self {
432 self.schedule_date = Some(value);
433 self
434 }
435
436 pub fn schedule_end(mut self, value: DateTime<Utc>) -> Self {
438 self.schedule_end = Some(value);
439 self
440 }
441
442 pub fn close_date(mut self, value: NaiveDate) -> Self {
444 self.close_date = Some(value);
445 self
446 }
447
448 pub fn duration(mut self, value: Decimal) -> Self {
450 self.duration = Some(value);
451 self
452 }
453
454 pub fn owner_user_id(mut self, value: Uuid) -> Self {
456 self.owner_user_id = Some(value);
457 self
458 }
459
460 pub fn user_id(mut self, value: Uuid) -> Self {
462 self.user_id = Some(value);
463 self
464 }
465
466 pub fn asset_id(mut self, value: Uuid) -> Self {
468 self.asset_id = Some(value);
469 self
470 }
471
472 pub fn stage_id(mut self, value: Uuid) -> Self {
474 self.stage_id = Some(value);
475 self
476 }
477
478 pub fn kanban_state(mut self, value: RequestKanbanState) -> Self {
480 self.kanban_state = Some(value);
481 self
482 }
483
484 pub fn priority(mut self, value: RequestPriority) -> Self {
486 self.priority = Some(value);
487 self
488 }
489
490 pub fn maintenance_type(mut self, value: MaintenanceType) -> Self {
492 self.maintenance_type = Some(value);
493 self
494 }
495
496 pub fn recurring(mut self, value: bool) -> Self {
498 self.recurring = Some(value);
499 self
500 }
501
502 pub fn repeat_interval(mut self, value: i32) -> Self {
504 self.repeat_interval = Some(value);
505 self
506 }
507
508 pub fn repeat_unit(mut self, value: RepeatUnit) -> Self {
510 self.repeat_unit = Some(value);
511 self
512 }
513
514 pub fn repeat_type(mut self, value: RepeatType) -> Self {
516 self.repeat_type = Some(value);
517 self
518 }
519
520 pub fn repeat_until(mut self, value: NaiveDate) -> Self {
522 self.repeat_until = Some(value);
523 self
524 }
525
526 pub fn successor_request_id(mut self, value: Uuid) -> Self {
528 self.successor_request_id = Some(value);
529 self
530 }
531
532 pub fn successor_of_request_id(mut self, value: Uuid) -> Self {
534 self.successor_of_request_id = Some(value);
535 self
536 }
537
538 pub fn build(self) -> Result<MaintenanceRequest, String> {
542 let name = self.name.ok_or_else(|| "name is required".to_string())?;
543 let stage_id = self.stage_id.ok_or_else(|| "stage_id is required".to_string())?;
544 let priority = self.priority.ok_or_else(|| "priority is required".to_string())?;
545
546 Ok(MaintenanceRequest {
547 id: Uuid::new_v4(),
548 name,
549 description: self.description,
550 request_date: self.request_date.unwrap_or_default(),
551 schedule_date: self.schedule_date,
552 schedule_end: self.schedule_end,
553 close_date: self.close_date,
554 duration: self.duration.unwrap_or(Decimal::from(0)),
555 owner_user_id: self.owner_user_id,
556 user_id: self.user_id,
557 asset_id: self.asset_id,
558 stage_id,
559 kanban_state: self.kanban_state.unwrap_or_default(),
560 priority,
561 maintenance_type: self.maintenance_type.unwrap_or_default(),
562 recurring: self.recurring.unwrap_or(false),
563 repeat_interval: self.repeat_interval.unwrap_or(1),
564 repeat_unit: self.repeat_unit.unwrap_or_default(),
565 repeat_type: self.repeat_type.unwrap_or_default(),
566 repeat_until: self.repeat_until,
567 successor_request_id: self.successor_request_id,
568 successor_of_request_id: self.successor_of_request_id,
569 metadata: AuditMetadata::default(),
570 })
571 }
572}