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    // <<< CUSTOM METHODS START >>>
232    // <<< CUSTOM METHODS END >>>
233}
234
235impl super::Entity for WarrantyClaim {
236    type Id = Uuid;
237
238    fn entity_id(&self) -> &Self::Id {
239        &self.id
240    }
241
242    fn entity_type() -> &'static str {
243        "WarrantyClaim"
244    }
245}
246
247impl backbone_core::PersistentEntity for WarrantyClaim {
248    fn entity_id(&self) -> String {
249        self.id.to_string()
250    }
251    fn set_entity_id(&mut self, id: String) {
252        if let Ok(uuid) = uuid::Uuid::parse_str(&id) {
253            self.id = uuid;
254        }
255    }
256    fn created_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
257        self.metadata.created_at
258    }
259    fn set_created_at(&mut self, ts: chrono::DateTime<chrono::Utc>) {
260        self.metadata.created_at = Some(ts);
261    }
262    fn updated_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
263        self.metadata.updated_at
264    }
265    fn set_updated_at(&mut self, ts: chrono::DateTime<chrono::Utc>) {
266        self.metadata.updated_at = Some(ts);
267    }
268    fn deleted_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
269        self.metadata.deleted_at
270    }
271    fn set_deleted_at(&mut self, ts: Option<chrono::DateTime<chrono::Utc>>) {
272        self.metadata.deleted_at = ts;
273    }
274}
275
276impl backbone_orm::EntityRepoMeta for WarrantyClaim {
277    fn column_types() -> std::collections::HashMap<String, String> {
278        let mut m = std::collections::HashMap::new();
279        m.insert("id".to_string(), "uuid".to_string());
280        m.insert("customer_id".to_string(), "uuid".to_string());
281        m.insert("item_id".to_string(), "uuid".to_string());
282        m.insert("issue_id".to_string(), "uuid".to_string());
283        m.insert("status".to_string(), "warranty_status".to_string());
284        m.insert("claim_date".to_string(), "timestamptz".to_string());
285        m.insert("warranty_expiry".to_string(), "timestamptz".to_string());
286        m
287    }
288    fn search_fields() -> &'static [&'static str] {
289        &[]
290    }
291}
292
293/// Builder for WarrantyClaim entity
294///
295/// Provides a fluent API for constructing WarrantyClaim instances.
296/// System fields (id, metadata, timestamps) are auto-initialized.
297#[derive(Debug, Clone, Default)]
298pub struct WarrantyClaimBuilder {
299    customer_id: Option<Uuid>,
300    item_id: Option<Uuid>,
301    serial_no: Option<String>,
302    claim_date: Option<DateTime<Utc>>,
303    warranty_expiry: Option<DateTime<Utc>>,
304    is_under_warranty: Option<bool>,
305    status: Option<WarrantyStatus>,
306    issue_id: Option<Uuid>,
307    description: Option<String>,
308    resolution: Option<String>,
309}
310
311impl WarrantyClaimBuilder {
312    /// Set the customer_id field (optional)
313    pub fn customer_id(mut self, value: Uuid) -> Self {
314        self.customer_id = Some(value);
315        self
316    }
317
318    /// Set the item_id field (required)
319    pub fn item_id(mut self, value: Uuid) -> Self {
320        self.item_id = Some(value);
321        self
322    }
323
324    /// Set the serial_no field (optional)
325    pub fn serial_no(mut self, value: String) -> Self {
326        self.serial_no = Some(value);
327        self
328    }
329
330    /// Set the claim_date field (required)
331    pub fn claim_date(mut self, value: DateTime<Utc>) -> Self {
332        self.claim_date = Some(value);
333        self
334    }
335
336    /// Set the warranty_expiry field (optional)
337    pub fn warranty_expiry(mut self, value: DateTime<Utc>) -> Self {
338        self.warranty_expiry = Some(value);
339        self
340    }
341
342    /// Set the is_under_warranty field (default: `false`)
343    pub fn is_under_warranty(mut self, value: bool) -> Self {
344        self.is_under_warranty = Some(value);
345        self
346    }
347
348    /// Set the status field (default: `WarrantyStatus::default()`)
349    pub fn status(mut self, value: WarrantyStatus) -> Self {
350        self.status = Some(value);
351        self
352    }
353
354    /// Set the issue_id field (optional)
355    pub fn issue_id(mut self, value: Uuid) -> Self {
356        self.issue_id = Some(value);
357        self
358    }
359
360    /// Set the description field (optional)
361    pub fn description(mut self, value: String) -> Self {
362        self.description = Some(value);
363        self
364    }
365
366    /// Set the resolution field (optional)
367    pub fn resolution(mut self, value: String) -> Self {
368        self.resolution = Some(value);
369        self
370    }
371
372    /// Build the WarrantyClaim entity
373    ///
374    /// Returns Err if any required field without a default is missing.
375    pub fn build(self) -> Result<WarrantyClaim, String> {
376        let item_id = self.item_id.ok_or_else(|| "item_id is required".to_string())?;
377        let claim_date = self.claim_date.ok_or_else(|| "claim_date is required".to_string())?;
378
379        Ok(WarrantyClaim {
380            id: Uuid::new_v4(),
381            customer_id: self.customer_id,
382            item_id,
383            serial_no: self.serial_no,
384            claim_date,
385            warranty_expiry: self.warranty_expiry,
386            is_under_warranty: self.is_under_warranty.unwrap_or(false),
387            status: self.status.unwrap_or_default(),
388            issue_id: self.issue_id,
389            description: self.description,
390            resolution: self.resolution,
391            metadata: AuditMetadata::default(),
392        })
393    }
394}