Skip to main content

backbone_pos/presentation/dto/
pos_opening_entry_dto.rs

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