Skip to main content

backbone_inventory/presentation/dto/
delivery_note_item_dto.rs

1//! DeliveryNoteItem 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 OpenAPI documentation support.
7
8use serde::{Deserialize, Serialize};
9use uuid::Uuid;
10use chrono::{DateTime, Utc};
11use rust_decimal::Decimal;
12
13#[cfg(feature = "openapi")]
14#[cfg(feature = "openapi")]
15use utoipa::ToSchema;
16
17use crate::domain::entity::DeliveryNoteItem;
18use crate::domain::entity::AuditMetadata;
19
20// =============================================================================
21// Create DTO
22// =============================================================================
23
24/// Request DTO for creating a new DeliveryNoteItem
25///
26/// Used in POST requests to create new entities.
27/// Excludes auto-generated fields (id, created_at, updated_at, deleted_at).
28#[derive(Debug, Clone, Deserialize)]
29#[cfg_attr(feature = "openapi", derive(ToSchema))]
30#[serde(rename_all = "camelCase")]
31pub struct CreateDeliveryNoteItemDto {
32    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
33    #[serde(alias = "delivery_id")]
34    pub delivery_id: Uuid,
35    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
36    #[serde(alias = "item_id")]
37    pub item_id: Uuid,
38    pub quantity: Decimal,
39    #[serde(alias = "valuation_rate")]
40    pub valuation_rate: Decimal,
41    #[serde(alias = "cogs_amount")]
42    pub cogs_amount: Decimal,
43}
44
45// =============================================================================
46// Update DTO
47// =============================================================================
48
49/// Request DTO for full update of a DeliveryNoteItem
50///
51/// Used in PUT requests for full entity replacement.
52/// All fields are required (except auto-generated ones).
53#[derive(Debug, Clone, Deserialize)]
54#[cfg_attr(feature = "openapi", derive(ToSchema))]
55#[serde(rename_all = "camelCase")]
56pub struct UpdateDeliveryNoteItemDto {
57    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
58    #[serde(alias = "delivery_id")]
59    pub delivery_id: Uuid,
60    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
61    #[serde(alias = "item_id")]
62    pub item_id: Uuid,
63    pub quantity: Decimal,
64    #[serde(alias = "valuation_rate")]
65    pub valuation_rate: Decimal,
66    #[serde(alias = "cogs_amount")]
67    pub cogs_amount: Decimal,
68}
69
70// =============================================================================
71// Patch DTO
72// =============================================================================
73
74/// Request DTO for partial update of a DeliveryNoteItem
75///
76/// Used in PATCH requests for partial updates.
77/// All fields are optional - only provided fields will be updated.
78#[derive(Debug, Clone, Default, Deserialize)]
79#[cfg_attr(feature = "openapi", derive(ToSchema))]
80#[serde(rename_all = "camelCase")]
81pub struct PatchDeliveryNoteItemDto {
82    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
83    #[serde(skip_serializing_if = "Option::is_none", alias = "delivery_id")]
84    pub delivery_id: Option<Uuid>,
85    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
86    #[serde(skip_serializing_if = "Option::is_none", alias = "item_id")]
87    pub item_id: Option<Uuid>,
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub quantity: Option<Decimal>,
90    #[serde(skip_serializing_if = "Option::is_none", alias = "valuation_rate")]
91    pub valuation_rate: Option<Decimal>,
92    #[serde(skip_serializing_if = "Option::is_none", alias = "cogs_amount")]
93    pub cogs_amount: Option<Decimal>,
94}
95
96impl PatchDeliveryNoteItemDto {
97    /// Check if any field is set
98    pub fn has_changes(&self) -> bool {
99        self.delivery_id.is_some() || self.item_id.is_some() || self.quantity.is_some() || self.valuation_rate.is_some() || self.cogs_amount.is_some()
100    }
101}
102
103// =============================================================================
104// Response DTO
105// =============================================================================
106
107/// Response DTO for DeliveryNoteItem entity
108///
109/// Used in API responses for single entity.
110/// Includes all fields including metadata.
111#[derive(Debug, Clone, Serialize)]
112#[cfg_attr(feature = "openapi", derive(ToSchema))]
113#[serde(rename_all = "camelCase")]
114pub struct DeliveryNoteItemResponseDto {
115    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
116    pub id: Uuid,
117    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
118    pub delivery_id: Uuid,
119    #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
120    pub item_id: Uuid,
121    pub quantity: Decimal,
122    pub valuation_rate: Decimal,
123    pub cogs_amount: Decimal,
124    pub metadata: AuditMetadata,
125}
126
127// =============================================================================
128// List Response DTO
129// =============================================================================
130
131/// Paginated list response for DeliveryNoteItem entities
132///
133/// Used in API responses for list endpoints.
134/// Includes pagination metadata.
135#[derive(Debug, Clone, Serialize)]
136#[cfg_attr(feature = "openapi", derive(ToSchema))]
137#[serde(rename_all = "camelCase")]
138pub struct DeliveryNoteItemListResponseDto {
139    /// List of items
140    pub items: Vec<DeliveryNoteItemResponseDto>,
141    /// Total number of items (across all pages)
142    pub total: u64,
143    /// Current page number (1-indexed)
144    pub page: u32,
145    /// Number of items per page
146    pub per_page: u32,
147    /// Total number of pages
148    pub total_pages: u32,
149    /// Whether there is a next page
150    pub has_next: bool,
151    /// Whether there is a previous page
152    pub has_prev: bool,
153}
154
155impl DeliveryNoteItemListResponseDto {
156    /// Create a new list response from items and pagination info
157    pub fn new(items: Vec<DeliveryNoteItemResponseDto>, total: u64, page: u32, per_page: u32) -> Self {
158        let total_pages = if per_page > 0 {
159            ((total as f64) / (per_page as f64)).ceil() as u32
160        } else {
161            0
162        };
163        Self {
164            items,
165            total,
166            page,
167            per_page,
168            total_pages,
169            has_next: page < total_pages,
170            has_prev: page > 1,
171        }
172    }
173}
174
175/// Summary DTO for list views (compact version)
176#[derive(Debug, Clone, Serialize)]
177#[cfg_attr(feature = "openapi", derive(ToSchema))]
178#[serde(rename_all = "camelCase")]
179pub struct DeliveryNoteItemSummaryDto {
180    pub id: Uuid,
181    pub delivery_id: Uuid,
182    pub item_id: Uuid,
183    pub quantity: Decimal,
184    pub created_at: Option<DateTime<Utc>>,
185}
186
187// =============================================================================
188// Conversions
189// =============================================================================
190
191impl From<DeliveryNoteItem> for DeliveryNoteItemResponseDto {
192    fn from(entity: DeliveryNoteItem) -> Self {
193        Self {
194            id: entity.id,
195            delivery_id: entity.delivery_id,
196            item_id: entity.item_id,
197            quantity: entity.quantity,
198            valuation_rate: entity.valuation_rate,
199            cogs_amount: entity.cogs_amount,
200            metadata: entity.metadata,
201        }
202    }
203}
204
205impl From<DeliveryNoteItem> for DeliveryNoteItemSummaryDto {
206    fn from(entity: DeliveryNoteItem) -> Self {
207        let created_at = backbone_core::PersistentEntity::created_at(&entity);
208        Self {
209            id: entity.id,
210            delivery_id: entity.delivery_id,
211            item_id: entity.item_id,
212            quantity: entity.quantity,
213            created_at,
214        }
215    }
216}
217
218impl From<CreateDeliveryNoteItemDto> for DeliveryNoteItem {
219    fn from(dto: CreateDeliveryNoteItemDto) -> Self {
220        Self {
221            id: Uuid::new_v4(),
222            delivery_id: dto.delivery_id,
223            item_id: dto.item_id,
224            quantity: dto.quantity,
225            valuation_rate: dto.valuation_rate,
226            cogs_amount: dto.cogs_amount,
227            metadata: AuditMetadata::default(),
228        }
229    }
230}
231
232impl From<&DeliveryNoteItem> for DeliveryNoteItemResponseDto {
233    fn from(entity: &DeliveryNoteItem) -> Self {
234        Self {
235            id: entity.id.clone(),
236            delivery_id: entity.delivery_id.clone(),
237            item_id: entity.item_id.clone(),
238            quantity: entity.quantity.clone(),
239            valuation_rate: entity.valuation_rate.clone(),
240            cogs_amount: entity.cogs_amount.clone(),
241            metadata: entity.metadata.clone(),
242        }
243    }
244}
245
246impl backbone_core::FromCreateDto<CreateDeliveryNoteItemDto> for DeliveryNoteItem {
247    fn from_create_dto(dto: CreateDeliveryNoteItemDto) -> backbone_core::ServiceResult<Self> {
248        Ok(DeliveryNoteItem::from(dto))
249    }
250}
251
252impl backbone_core::ApplyUpdateDto<UpdateDeliveryNoteItemDto> for DeliveryNoteItem {
253    fn apply_update(mut self, dto: UpdateDeliveryNoteItemDto) -> backbone_core::ServiceResult<Self> {
254        self.delivery_id = dto.delivery_id;
255        self.item_id = dto.item_id;
256        self.quantity = dto.quantity;
257        self.valuation_rate = dto.valuation_rate;
258        self.cogs_amount = dto.cogs_amount;
259        Ok(self)
260    }
261}
262
263// =============================================================================
264// Custom DTOs
265// =============================================================================
266
267// Add custom DTOs specific to DeliveryNoteItem here.
268// This section will be preserved during regeneration.
269// >>> END CUSTOM DTOs
270