Skip to main content

backbone_support/domain/entity/
warranty_claim.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use sqlx::FromRow;
4use uuid::Uuid;
5
6use super::WarrantyStatus;
7use super::AuditMetadata;
8
9/// Strongly-typed ID for WarrantyClaim
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11#[serde(transparent)]
12pub struct WarrantyClaimId(pub Uuid);
13
14impl WarrantyClaimId {
15    pub fn new(id: Uuid) -> Self { Self(id) }
16    pub fn generate() -> Self { Self(Uuid::new_v4()) }
17    pub fn into_inner(self) -> Uuid { self.0 }
18}
19
20impl std::fmt::Display for WarrantyClaimId {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        write!(f, "{}", self.0)
23    }
24}
25
26impl std::str::FromStr for WarrantyClaimId {
27    type Err = uuid::Error;
28    fn from_str(s: &str) -> Result<Self, Self::Err> {
29        Ok(Self(Uuid::parse_str(s)?))
30    }
31}
32
33impl From<Uuid> for WarrantyClaimId {
34    fn from(id: Uuid) -> Self { Self(id) }
35}
36
37impl From<WarrantyClaimId> for Uuid {
38    fn from(id: WarrantyClaimId) -> Self { id.0 }
39}
40
41impl AsRef<Uuid> for WarrantyClaimId {
42    fn as_ref(&self) -> &Uuid { &self.0 }
43}
44
45impl std::ops::Deref for WarrantyClaimId {
46    type Target = Uuid;
47    fn deref(&self) -> &Self::Target { &self.0 }
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
51pub struct WarrantyClaim {
52    pub id: Uuid,
53    pub customer_id: Option<Uuid>,
54    pub item_id: Uuid,
55    pub serial_no: Option<String>,
56    pub claim_date: DateTime<Utc>,
57    pub warranty_expiry: Option<DateTime<Utc>>,
58    pub is_under_warranty: bool,
59    pub status: WarrantyStatus,
60    pub issue_id: Option<Uuid>,
61    pub description: Option<String>,
62    pub resolution: Option<String>,
63    #[serde(default)]
64    #[sqlx(json)]
65    pub metadata: AuditMetadata,
66}
67
68impl WarrantyClaim {
69    /// Create a builder for WarrantyClaim
70    pub fn builder() -> WarrantyClaimBuilder {
71        <WarrantyClaimBuilder as Default>::default()
72    }
73
74    /// Create a new WarrantyClaim with required fields
75    pub fn new(item_id: Uuid, claim_date: DateTime<Utc>, is_under_warranty: bool, status: WarrantyStatus) -> Self {
76        Self {
77            id: Uuid::new_v4(),
78            customer_id: None,
79            item_id,
80            serial_no: None,
81            claim_date,
82            warranty_expiry: None,
83            is_under_warranty,
84            status,
85            issue_id: None,
86            description: None,
87            resolution: None,
88            metadata: AuditMetadata::default(),
89        }
90    }
91
92    /// Get the entity's unique identifier
93    pub fn id(&self) -> &Uuid {
94        &self.id
95    }
96
97    /// Get a strongly-typed ID for this entity
98    pub fn typed_id(&self) -> WarrantyClaimId {
99        WarrantyClaimId(self.id)
100    }
101
102    /// Get when this entity was created
103    pub fn created_at(&self) -> Option<&DateTime<Utc>> {
104        self.metadata.created_at.as_ref()
105    }
106
107    /// Get when this entity was last updated
108    pub fn updated_at(&self) -> Option<&DateTime<Utc>> {
109        self.metadata.updated_at.as_ref()
110    }
111
112    /// Check if this entity is soft deleted
113    pub fn is_deleted(&self) -> bool {
114        self.metadata.deleted_at.is_some()
115    }
116
117    /// Check if this entity is active (not deleted)
118    pub fn is_active(&self) -> bool {
119        self.metadata.deleted_at.is_none()
120    }
121
122    /// Get when this entity was deleted
123    pub fn deleted_at(&self) -> Option<&DateTime<Utc>> {
124        self.metadata.deleted_at.as_ref()
125    }
126
127    /// Get who created this entity
128    pub fn created_by(&self) -> Option<&Uuid> {
129        self.metadata.created_by.as_ref()
130    }
131
132    /// Get who last updated this entity
133    pub fn updated_by(&self) -> Option<&Uuid> {
134        self.metadata.updated_by.as_ref()
135    }
136
137    /// Get who deleted this entity
138    pub fn deleted_by(&self) -> Option<&Uuid> {
139        self.metadata.deleted_by.as_ref()
140    }
141
142    /// Get the current status
143    pub fn status(&self) -> &WarrantyStatus {
144        &self.status
145    }
146
147
148    // ==========================================================
149    // Fluent Setters (with_* for optional fields)
150    // ==========================================================
151
152    /// Set the customer_id field (chainable)
153    pub fn with_customer_id(mut self, value: Uuid) -> Self {
154        self.customer_id = Some(value);
155        self
156    }
157
158    /// Set the serial_no field (chainable)
159    pub fn with_serial_no(mut self, value: String) -> Self {
160        self.serial_no = Some(value);
161        self
162    }
163
164    /// Set the warranty_expiry field (chainable)
165    pub fn with_warranty_expiry(mut self, value: DateTime<Utc>) -> Self {
166        self.warranty_expiry = Some(value);
167        self
168    }
169
170    /// Set the issue_id field (chainable)
171    pub fn with_issue_id(mut self, value: Uuid) -> Self {
172        self.issue_id = Some(value);
173        self
174    }
175
176    /// Set the description field (chainable)
177    pub fn with_description(mut self, value: String) -> Self {
178        self.description = Some(value);
179        self
180    }
181
182    /// Set the resolution field (chainable)
183    pub fn with_resolution(mut self, value: String) -> Self {
184        self.resolution = Some(value);
185        self
186    }
187
188    // ==========================================================
189    // Partial Update
190    // ==========================================================
191
192    /// Apply partial updates from a map of field name to JSON value
193    pub fn apply_patch(&mut self, fields: std::collections::HashMap<String, serde_json::Value>) {
194        for (key, value) in fields {
195            match key.as_str() {
196                "customer_id" => {
197                    if let Ok(v) = serde_json::from_value(value) { self.customer_id = v; }
198                }
199                "item_id" => {
200                    if let Ok(v) = serde_json::from_value(value) { self.item_id = v; }
201                }
202                "serial_no" => {
203                    if let Ok(v) = serde_json::from_value(value) { self.serial_no = v; }
204                }
205                "claim_date" => {
206                    if let Ok(v) = serde_json::from_value(value) { self.claim_date = v; }
207                }
208                "warranty_expiry" => {
209                    if let Ok(v) = serde_json::from_value(value) { self.warranty_expiry = v; }
210                }
211                "is_under_warranty" => {
212                    if let Ok(v) = serde_json::from_value(value) { self.is_under_warranty = v; }
213                }
214                "status" => {
215                    if let Ok(v) = serde_json::from_value(value) { self.status = v; }
216                }
217                "issue_id" => {
218                    if let Ok(v) = serde_json::from_value(value) { self.issue_id = v; }
219                }
220                "description" => {
221                    if let Ok(v) = serde_json::from_value(value) { self.description = v; }
222                }
223                "resolution" => {
224                    if let Ok(v) = serde_json::from_value(value) { self.resolution = v; }
225                }
226                _ => {} // ignore unknown fields
227            }
228        }
229    }
230
231}
232
233impl super::Entity for WarrantyClaim {
234    type Id = Uuid;
235
236    fn entity_id(&self) -> &Self::Id {
237        &self.id
238    }
239
240    fn entity_type() -> &'static str {
241        "WarrantyClaim"
242    }
243}
244
245impl backbone_core::PersistentEntity for WarrantyClaim {
246    fn entity_id(&self) -> String {
247        self.id.to_string()
248    }
249    fn set_entity_id(&mut self, id: String) {
250        if let Ok(uuid) = uuid::Uuid::parse_str(&id) {
251            self.id = uuid;
252        }
253    }
254    fn created_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
255        self.metadata.created_at
256    }
257    fn set_created_at(&mut self, ts: chrono::DateTime<chrono::Utc>) {
258        self.metadata.created_at = Some(ts);
259    }
260    fn updated_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
261        self.metadata.updated_at
262    }
263    fn set_updated_at(&mut self, ts: chrono::DateTime<chrono::Utc>) {
264        self.metadata.updated_at = Some(ts);
265    }
266    fn deleted_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
267        self.metadata.deleted_at
268    }
269    fn set_deleted_at(&mut self, ts: Option<chrono::DateTime<chrono::Utc>>) {
270        self.metadata.deleted_at = ts;
271    }
272}
273
274impl backbone_orm::EntityRepoMeta for WarrantyClaim {
275    fn column_types() -> std::collections::HashMap<String, String> {
276        let mut m = std::collections::HashMap::new();
277        m.insert("id".to_string(), "uuid".to_string());
278        m.insert("customer_id".to_string(), "uuid".to_string());
279        m.insert("item_id".to_string(), "uuid".to_string());
280        m.insert("issue_id".to_string(), "uuid".to_string());
281        m.insert("status".to_string(), "warranty_status".to_string());
282        m.insert("claim_date".to_string(), "timestamptz".to_string());
283        m.insert("warranty_expiry".to_string(), "timestamptz".to_string());
284        m
285    }
286    fn search_fields() -> &'static [&'static str] {
287        &[]
288    }
289}
290
291/// Builder for WarrantyClaim entity
292///
293/// Provides a fluent API for constructing WarrantyClaim instances.
294/// System fields (id, metadata, timestamps) are auto-initialized.
295#[derive(Debug, Clone, Default)]
296pub struct WarrantyClaimBuilder {
297    customer_id: Option<Uuid>,
298    item_id: Option<Uuid>,
299    serial_no: Option<String>,
300    claim_date: Option<DateTime<Utc>>,
301    warranty_expiry: Option<DateTime<Utc>>,
302    is_under_warranty: Option<bool>,
303    status: Option<WarrantyStatus>,
304    issue_id: Option<Uuid>,
305    description: Option<String>,
306    resolution: Option<String>,
307}
308
309impl WarrantyClaimBuilder {
310    /// Set the customer_id field (optional)
311    pub fn customer_id(mut self, value: Uuid) -> Self {
312        self.customer_id = Some(value);
313        self
314    }
315
316    /// Set the item_id field (required)
317    pub fn item_id(mut self, value: Uuid) -> Self {
318        self.item_id = Some(value);
319        self
320    }
321
322    /// Set the serial_no field (optional)
323    pub fn serial_no(mut self, value: String) -> Self {
324        self.serial_no = Some(value);
325        self
326    }
327
328    /// Set the claim_date field (required)
329    pub fn claim_date(mut self, value: DateTime<Utc>) -> Self {
330        self.claim_date = Some(value);
331        self
332    }
333
334    /// Set the warranty_expiry field (optional)
335    pub fn warranty_expiry(mut self, value: DateTime<Utc>) -> Self {
336        self.warranty_expiry = Some(value);
337        self
338    }
339
340    /// Set the is_under_warranty field (default: `false`)
341    pub fn is_under_warranty(mut self, value: bool) -> Self {
342        self.is_under_warranty = Some(value);
343        self
344    }
345
346    /// Set the status field (default: `WarrantyStatus::default()`)
347    pub fn status(mut self, value: WarrantyStatus) -> Self {
348        self.status = Some(value);
349        self
350    }
351
352    /// Set the issue_id field (optional)
353    pub fn issue_id(mut self, value: Uuid) -> Self {
354        self.issue_id = Some(value);
355        self
356    }
357
358    /// Set the description field (optional)
359    pub fn description(mut self, value: String) -> Self {
360        self.description = Some(value);
361        self
362    }
363
364    /// Set the resolution field (optional)
365    pub fn resolution(mut self, value: String) -> Self {
366        self.resolution = Some(value);
367        self
368    }
369
370    /// Build the WarrantyClaim entity
371    ///
372    /// Returns Err if any required field without a default is missing.
373    pub fn build(self) -> Result<WarrantyClaim, String> {
374        let item_id = self.item_id.ok_or_else(|| "item_id is required".to_string())?;
375        let claim_date = self.claim_date.ok_or_else(|| "claim_date is required".to_string())?;
376
377        Ok(WarrantyClaim {
378            id: Uuid::new_v4(),
379            customer_id: self.customer_id,
380            item_id,
381            serial_no: self.serial_no,
382            claim_date,
383            warranty_expiry: self.warranty_expiry,
384            is_under_warranty: self.is_under_warranty.unwrap_or(false),
385            status: self.status.unwrap_or_default(),
386            issue_id: self.issue_id,
387            description: self.description,
388            resolution: self.resolution,
389            metadata: AuditMetadata::default(),
390        })
391    }
392}