Skip to main content

backbone_bucket/presentation/dto/
processing_job_dto.rs

1//! ProcessingJob DTOs (Data Transfer Objects)
2//!
3//! Generated by metaphor-schema. Do not edit manually.
4//!
5//! DTOs provide a clean separation between domain entities and API
6//! representations, with validation and OpenAPI documentation support.
7
8use serde::{Deserialize, Serialize};
9use uuid::Uuid;
10use chrono::{DateTime, Utc};
11
12#[cfg(feature = "openapi")]
13#[cfg(feature = "openapi")]
14use utoipa::ToSchema;
15
16#[cfg(feature = "validation")]
17use validator::Validate;
18
19use crate::domain::entity::ProcessingJob;
20use crate::domain::entity::AuditMetadata;
21use crate::domain::entity::JobStatus;
22use crate::domain::entity::ProcessingJobType;
23
24// =============================================================================
25// Create DTO
26// =============================================================================
27
28/// Request DTO for creating a new ProcessingJob
29///
30/// Used in POST requests to create new entities.
31/// Excludes auto-generated fields (id, created_at, updated_at, deleted_at).
32#[derive(Debug, Clone, Deserialize)]
33#[cfg_attr(feature = "openapi", derive(ToSchema))]
34#[cfg_attr(feature = "validation", derive(Validate))]
35#[serde(rename_all = "camelCase")]
36pub struct CreateProcessingJobDto {
37    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
38    #[serde(alias = "file_id")]
39    pub file_id: Uuid,
40    #[serde(alias = "job_type")]
41    pub job_type: ProcessingJobType,
42    pub status: JobStatus,
43    #[cfg_attr(feature = "openapi", schema(example = 42))]
44    pub priority: i32,
45    #[serde(default, skip_serializing_if = "Option::is_none", alias = "input_data")]
46    pub input_data: Option<serde_json::Value>,
47    #[serde(default, skip_serializing_if = "Option::is_none", alias = "result_data")]
48    pub result_data: Option<serde_json::Value>,
49    #[serde(default, skip_serializing_if = "Option::is_none", alias = "error_message")]
50    pub error_message: Option<String>,
51    #[serde(default, skip_serializing_if = "Option::is_none", alias = "started_at")]
52    pub started_at: Option<DateTime<Utc>>,
53    #[serde(default, skip_serializing_if = "Option::is_none", alias = "completed_at")]
54    pub completed_at: Option<DateTime<Utc>>,
55    #[cfg_attr(feature = "openapi", schema(example = 42))]
56    #[serde(alias = "retry_count")]
57    pub retry_count: i32,
58    #[cfg_attr(feature = "openapi", schema(example = 42))]
59    #[serde(alias = "max_retries")]
60    pub max_retries: i32,
61}
62
63// =============================================================================
64// Update DTO
65// =============================================================================
66
67/// Request DTO for full update of a ProcessingJob
68///
69/// Used in PUT requests for full entity replacement.
70/// All fields are required (except auto-generated ones).
71#[derive(Debug, Clone, Deserialize)]
72#[cfg_attr(feature = "openapi", derive(ToSchema))]
73#[cfg_attr(feature = "validation", derive(Validate))]
74#[serde(rename_all = "camelCase")]
75pub struct UpdateProcessingJobDto {
76    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
77    #[serde(alias = "file_id")]
78    pub file_id: Uuid,
79    #[serde(alias = "job_type")]
80    pub job_type: ProcessingJobType,
81    pub status: JobStatus,
82    #[cfg_attr(feature = "openapi", schema(example = 42))]
83    pub priority: i32,
84    #[serde(default, skip_serializing_if = "Option::is_none", alias = "input_data")]
85    pub input_data: Option<serde_json::Value>,
86    #[serde(default, skip_serializing_if = "Option::is_none", alias = "result_data")]
87    pub result_data: Option<serde_json::Value>,
88    #[serde(default, skip_serializing_if = "Option::is_none", alias = "error_message")]
89    pub error_message: Option<String>,
90    #[serde(default, skip_serializing_if = "Option::is_none", alias = "started_at")]
91    pub started_at: Option<DateTime<Utc>>,
92    #[serde(default, skip_serializing_if = "Option::is_none", alias = "completed_at")]
93    pub completed_at: Option<DateTime<Utc>>,
94    #[cfg_attr(feature = "openapi", schema(example = 42))]
95    #[serde(alias = "retry_count")]
96    pub retry_count: i32,
97    #[cfg_attr(feature = "openapi", schema(example = 42))]
98    #[serde(alias = "max_retries")]
99    pub max_retries: i32,
100}
101
102// =============================================================================
103// Patch DTO
104// =============================================================================
105
106/// Request DTO for partial update of a ProcessingJob
107///
108/// Used in PATCH requests for partial updates.
109/// All fields are optional - only provided fields will be updated.
110#[derive(Debug, Clone, Default, Deserialize)]
111#[cfg_attr(feature = "openapi", derive(ToSchema))]
112#[cfg_attr(feature = "validation", derive(Validate))]
113#[serde(rename_all = "camelCase")]
114pub struct PatchProcessingJobDto {
115    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
116    #[serde(skip_serializing_if = "Option::is_none", alias = "file_id")]
117    pub file_id: Option<Uuid>,
118    #[serde(skip_serializing_if = "Option::is_none", alias = "job_type")]
119    pub job_type: Option<ProcessingJobType>,
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub status: Option<JobStatus>,
122    #[cfg_attr(feature = "openapi", schema(example = 42))]
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub priority: Option<i32>,
125    #[serde(skip_serializing_if = "Option::is_none", alias = "input_data")]
126    pub input_data: Option<serde_json::Value>,
127    #[serde(skip_serializing_if = "Option::is_none", alias = "result_data")]
128    pub result_data: Option<serde_json::Value>,
129    #[serde(skip_serializing_if = "Option::is_none", alias = "error_message")]
130    pub error_message: Option<String>,
131    #[serde(skip_serializing_if = "Option::is_none", alias = "started_at")]
132    pub started_at: Option<DateTime<Utc>>,
133    #[serde(skip_serializing_if = "Option::is_none", alias = "completed_at")]
134    pub completed_at: Option<DateTime<Utc>>,
135    #[cfg_attr(feature = "openapi", schema(example = 42))]
136    #[serde(skip_serializing_if = "Option::is_none", alias = "retry_count")]
137    pub retry_count: Option<i32>,
138    #[cfg_attr(feature = "openapi", schema(example = 42))]
139    #[serde(skip_serializing_if = "Option::is_none", alias = "max_retries")]
140    pub max_retries: Option<i32>,
141}
142
143impl PatchProcessingJobDto {
144    /// Check if any field is set
145    pub fn has_changes(&self) -> bool {
146        self.file_id.is_some() || self.job_type.is_some() || self.status.is_some() || self.priority.is_some() || self.input_data.is_some() || self.result_data.is_some() || self.error_message.is_some() || self.started_at.is_some() || self.completed_at.is_some() || self.retry_count.is_some() || self.max_retries.is_some()
147    }
148}
149
150// =============================================================================
151// Response DTO
152// =============================================================================
153
154/// Response DTO for ProcessingJob entity
155///
156/// Used in API responses for single entity.
157/// Includes all fields including metadata.
158#[derive(Debug, Clone, Serialize)]
159#[cfg_attr(feature = "openapi", derive(ToSchema))]
160#[serde(rename_all = "camelCase")]
161pub struct ProcessingJobResponseDto {
162    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
163    pub id: Uuid,
164    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
165    pub file_id: Uuid,
166    pub job_type: ProcessingJobType,
167    pub status: JobStatus,
168    #[cfg_attr(feature = "openapi", schema(example = 42))]
169    pub priority: i32,
170    pub input_data: Option<serde_json::Value>,
171    pub result_data: Option<serde_json::Value>,
172    pub error_message: Option<String>,
173    pub started_at: Option<DateTime<Utc>>,
174    pub completed_at: Option<DateTime<Utc>>,
175    #[cfg_attr(feature = "openapi", schema(example = 42))]
176    pub retry_count: i32,
177    #[cfg_attr(feature = "openapi", schema(example = 42))]
178    pub max_retries: i32,
179    pub metadata: AuditMetadata,
180}
181
182// =============================================================================
183// List Response DTO
184// =============================================================================
185
186/// Paginated list response for ProcessingJob entities
187///
188/// Used in API responses for list endpoints.
189/// Includes pagination metadata.
190#[derive(Debug, Clone, Serialize)]
191#[cfg_attr(feature = "openapi", derive(ToSchema))]
192#[serde(rename_all = "camelCase")]
193pub struct ProcessingJobListResponseDto {
194    /// List of items
195    pub items: Vec<ProcessingJobResponseDto>,
196    /// Total number of items (across all pages)
197    pub total: u64,
198    /// Current page number (1-indexed)
199    pub page: u32,
200    /// Number of items per page
201    pub per_page: u32,
202    /// Total number of pages
203    pub total_pages: u32,
204    /// Whether there is a next page
205    pub has_next: bool,
206    /// Whether there is a previous page
207    pub has_prev: bool,
208}
209
210impl ProcessingJobListResponseDto {
211    /// Create a new list response from items and pagination info
212    pub fn new(items: Vec<ProcessingJobResponseDto>, total: u64, page: u32, per_page: u32) -> Self {
213        let total_pages = if per_page > 0 {
214            ((total as f64) / (per_page as f64)).ceil() as u32
215        } else {
216            0
217        };
218        Self {
219            items,
220            total,
221            page,
222            per_page,
223            total_pages,
224            has_next: page < total_pages,
225            has_prev: page > 1,
226        }
227    }
228}
229
230/// Summary DTO for list views (compact version)
231#[derive(Debug, Clone, Serialize)]
232#[cfg_attr(feature = "openapi", derive(ToSchema))]
233#[serde(rename_all = "camelCase")]
234pub struct ProcessingJobSummaryDto {
235    pub id: Uuid,
236    pub file_id: Uuid,
237    pub job_type: ProcessingJobType,
238    pub status: JobStatus,
239    pub created_at: Option<DateTime<Utc>>,
240}
241
242// =============================================================================
243// Conversions
244// =============================================================================
245
246impl From<ProcessingJob> for ProcessingJobResponseDto {
247    fn from(entity: ProcessingJob) -> Self {
248        Self {
249            id: entity.id,
250            file_id: entity.file_id,
251            job_type: entity.job_type,
252            status: entity.status,
253            priority: entity.priority,
254            input_data: entity.input_data,
255            result_data: entity.result_data,
256            error_message: entity.error_message,
257            started_at: entity.started_at,
258            completed_at: entity.completed_at,
259            retry_count: entity.retry_count,
260            max_retries: entity.max_retries,
261            metadata: entity.metadata,
262        }
263    }
264}
265
266impl From<ProcessingJob> for ProcessingJobSummaryDto {
267    fn from(entity: ProcessingJob) -> Self {
268        let created_at = backbone_core::PersistentEntity::created_at(&entity);
269        Self {
270            id: entity.id,
271            file_id: entity.file_id,
272            job_type: entity.job_type,
273            status: entity.status,
274            created_at,
275        }
276    }
277}
278
279impl From<CreateProcessingJobDto> for ProcessingJob {
280    fn from(dto: CreateProcessingJobDto) -> Self {
281        Self {
282            id: Uuid::new_v4(),
283            file_id: dto.file_id,
284            job_type: dto.job_type,
285            status: dto.status,
286            priority: dto.priority,
287            input_data: dto.input_data,
288            result_data: dto.result_data,
289            error_message: dto.error_message,
290            started_at: dto.started_at,
291            completed_at: dto.completed_at,
292            retry_count: dto.retry_count,
293            max_retries: dto.max_retries,
294            metadata: AuditMetadata::default(),
295        }
296    }
297}
298
299impl From<&ProcessingJob> for ProcessingJobResponseDto {
300    fn from(entity: &ProcessingJob) -> Self {
301        Self {
302            id: entity.id.clone(),
303            file_id: entity.file_id.clone(),
304            job_type: entity.job_type.clone(),
305            status: entity.status.clone(),
306            priority: entity.priority.clone(),
307            input_data: entity.input_data.clone(),
308            result_data: entity.result_data.clone(),
309            error_message: entity.error_message.clone(),
310            started_at: entity.started_at.clone(),
311            completed_at: entity.completed_at.clone(),
312            retry_count: entity.retry_count.clone(),
313            max_retries: entity.max_retries.clone(),
314            metadata: entity.metadata.clone(),
315        }
316    }
317}
318
319impl backbone_core::FromCreateDto<CreateProcessingJobDto> for ProcessingJob {
320    fn from_create_dto(dto: CreateProcessingJobDto) -> backbone_core::ServiceResult<Self> {
321        Ok(ProcessingJob::from(dto))
322    }
323}
324
325impl backbone_core::ApplyUpdateDto<UpdateProcessingJobDto> for ProcessingJob {
326    fn apply_update(mut self, dto: UpdateProcessingJobDto) -> backbone_core::ServiceResult<Self> {
327        self.file_id = dto.file_id;
328        self.job_type = dto.job_type;
329        self.status = dto.status;
330        self.priority = dto.priority;
331        self.input_data = dto.input_data;
332        self.result_data = dto.result_data;
333        self.error_message = dto.error_message;
334        self.started_at = dto.started_at;
335        self.completed_at = dto.completed_at;
336        self.retry_count = dto.retry_count;
337        self.max_retries = dto.max_retries;
338        Ok(self)
339    }
340}
341
342// =============================================================================
343// Custom DTOs
344// =============================================================================
345
346// Add custom DTOs specific to ProcessingJob here.
347// This section will be preserved during regeneration.
348// >>> END CUSTOM DTOs
349