Skip to main content

backbone_inventory/domain/entity/
inventory_company_setting.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use sqlx::FromRow;
4use uuid::Uuid;
5
6use super::InventoryCostMethod;
7use super::ValuationPolicy;
8use super::AuditMetadata;
9
10/// Strongly-typed ID for InventoryCompanySetting
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12#[serde(transparent)]
13pub struct InventoryCompanySettingId(pub Uuid);
14
15impl InventoryCompanySettingId {
16    pub fn new(id: Uuid) -> Self { Self(id) }
17    pub fn generate() -> Self { Self(Uuid::new_v4()) }
18    pub fn into_inner(self) -> Uuid { self.0 }
19}
20
21impl std::fmt::Display for InventoryCompanySettingId {
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        write!(f, "{}", self.0)
24    }
25}
26
27impl std::str::FromStr for InventoryCompanySettingId {
28    type Err = uuid::Error;
29    fn from_str(s: &str) -> Result<Self, Self::Err> {
30        Ok(Self(Uuid::parse_str(s)?))
31    }
32}
33
34impl From<Uuid> for InventoryCompanySettingId {
35    fn from(id: Uuid) -> Self { Self(id) }
36}
37
38impl From<InventoryCompanySettingId> for Uuid {
39    fn from(id: InventoryCompanySettingId) -> Self { id.0 }
40}
41
42impl AsRef<Uuid> for InventoryCompanySettingId {
43    fn as_ref(&self) -> &Uuid { &self.0 }
44}
45
46impl std::ops::Deref for InventoryCompanySettingId {
47    type Target = Uuid;
48    fn deref(&self) -> &Self::Target { &self.0 }
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
52pub struct InventoryCompanySetting {
53    pub id: Uuid,
54    pub cost_method: InventoryCostMethod,
55    pub valuation_policy: ValuationPolicy,
56    pub anglo_saxon_accounting: bool,
57    pub stock_interim_delivered_account_id: Option<Uuid>,
58    #[serde(default)]
59    #[sqlx(json)]
60    pub metadata: AuditMetadata,
61}
62
63impl InventoryCompanySetting {
64    /// Create a builder for InventoryCompanySetting
65    pub fn builder() -> InventoryCompanySettingBuilder {
66        <InventoryCompanySettingBuilder as Default>::default()
67    }
68
69    /// Create a new InventoryCompanySetting with required fields
70    pub fn new(cost_method: InventoryCostMethod, valuation_policy: ValuationPolicy, anglo_saxon_accounting: bool) -> Self {
71        Self {
72            id: Uuid::new_v4(),
73            cost_method,
74            valuation_policy,
75            anglo_saxon_accounting,
76            stock_interim_delivered_account_id: None,
77            metadata: AuditMetadata::default(),
78        }
79    }
80
81    /// Get the entity's unique identifier
82    pub fn id(&self) -> &Uuid {
83        &self.id
84    }
85
86    /// Get a strongly-typed ID for this entity
87    pub fn typed_id(&self) -> InventoryCompanySettingId {
88        InventoryCompanySettingId(self.id)
89    }
90
91    /// Get when this entity was created
92    pub fn created_at(&self) -> Option<&DateTime<Utc>> {
93        self.metadata.created_at.as_ref()
94    }
95
96    /// Get when this entity was last updated
97    pub fn updated_at(&self) -> Option<&DateTime<Utc>> {
98        self.metadata.updated_at.as_ref()
99    }
100
101    /// Check if this entity is soft deleted
102    pub fn is_deleted(&self) -> bool {
103        self.metadata.deleted_at.is_some()
104    }
105
106    /// Check if this entity is active (not deleted)
107    pub fn is_active(&self) -> bool {
108        self.metadata.deleted_at.is_none()
109    }
110
111    /// Get when this entity was deleted
112    pub fn deleted_at(&self) -> Option<&DateTime<Utc>> {
113        self.metadata.deleted_at.as_ref()
114    }
115
116    /// Get who created this entity
117    pub fn created_by(&self) -> Option<&Uuid> {
118        self.metadata.created_by.as_ref()
119    }
120
121    /// Get who last updated this entity
122    pub fn updated_by(&self) -> Option<&Uuid> {
123        self.metadata.updated_by.as_ref()
124    }
125
126    /// Get who deleted this entity
127    pub fn deleted_by(&self) -> Option<&Uuid> {
128        self.metadata.deleted_by.as_ref()
129    }
130
131
132    // ==========================================================
133    // Fluent Setters (with_* for optional fields)
134    // ==========================================================
135
136    /// Set the stock_interim_delivered_account_id field (chainable)
137    pub fn with_stock_interim_delivered_account_id(mut self, value: Uuid) -> Self {
138        self.stock_interim_delivered_account_id = Some(value);
139        self
140    }
141
142    // ==========================================================
143    // Partial Update
144    // ==========================================================
145
146    /// Apply partial updates from a map of field name to JSON value
147    pub fn apply_patch(&mut self, fields: std::collections::HashMap<String, serde_json::Value>) {
148        for (key, value) in fields {
149            match key.as_str() {
150                "cost_method" => {
151                    if let Ok(v) = serde_json::from_value(value) { self.cost_method = v; }
152                }
153                "valuation_policy" => {
154                    if let Ok(v) = serde_json::from_value(value) { self.valuation_policy = v; }
155                }
156                "anglo_saxon_accounting" => {
157                    if let Ok(v) = serde_json::from_value(value) { self.anglo_saxon_accounting = v; }
158                }
159                "stock_interim_delivered_account_id" => {
160                    if let Ok(v) = serde_json::from_value(value) { self.stock_interim_delivered_account_id = v; }
161                }
162                _ => {} // ignore unknown fields
163            }
164        }
165    }
166
167}
168
169impl super::Entity for InventoryCompanySetting {
170    type Id = Uuid;
171
172    fn entity_id(&self) -> &Self::Id {
173        &self.id
174    }
175
176    fn entity_type() -> &'static str {
177        "InventoryCompanySetting"
178    }
179}
180
181impl backbone_core::PersistentEntity for InventoryCompanySetting {
182    fn entity_id(&self) -> String {
183        self.id.to_string()
184    }
185    fn set_entity_id(&mut self, id: String) {
186        if let Ok(uuid) = uuid::Uuid::parse_str(&id) {
187            self.id = uuid;
188        }
189    }
190    fn created_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
191        self.metadata.created_at
192    }
193    fn set_created_at(&mut self, ts: chrono::DateTime<chrono::Utc>) {
194        self.metadata.created_at = Some(ts);
195    }
196    fn updated_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
197        self.metadata.updated_at
198    }
199    fn set_updated_at(&mut self, ts: chrono::DateTime<chrono::Utc>) {
200        self.metadata.updated_at = Some(ts);
201    }
202    fn deleted_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
203        self.metadata.deleted_at
204    }
205    fn set_deleted_at(&mut self, ts: Option<chrono::DateTime<chrono::Utc>>) {
206        self.metadata.deleted_at = ts;
207    }
208}
209
210impl backbone_orm::EntityRepoMeta for InventoryCompanySetting {
211    fn column_types() -> std::collections::HashMap<String, String> {
212        let mut m = std::collections::HashMap::new();
213        m.insert("id".to_string(), "uuid".to_string());
214        m.insert("stock_interim_delivered_account_id".to_string(), "uuid".to_string());
215        m.insert("cost_method".to_string(), "inventory_cost_method".to_string());
216        m.insert("valuation_policy".to_string(), "valuation_policy".to_string());
217        m
218    }
219    fn search_fields() -> &'static [&'static str] {
220        &[]
221    }
222}
223
224/// Builder for InventoryCompanySetting entity
225///
226/// Provides a fluent API for constructing InventoryCompanySetting instances.
227/// System fields (id, metadata, timestamps) are auto-initialized.
228#[derive(Debug, Clone, Default)]
229pub struct InventoryCompanySettingBuilder {
230    cost_method: Option<InventoryCostMethod>,
231    valuation_policy: Option<ValuationPolicy>,
232    anglo_saxon_accounting: Option<bool>,
233    stock_interim_delivered_account_id: Option<Uuid>,
234}
235
236impl InventoryCompanySettingBuilder {
237    /// Set the cost_method field (default: `InventoryCostMethod::default()`)
238    pub fn cost_method(mut self, value: InventoryCostMethod) -> Self {
239        self.cost_method = Some(value);
240        self
241    }
242
243    /// Set the valuation_policy field (default: `ValuationPolicy::default()`)
244    pub fn valuation_policy(mut self, value: ValuationPolicy) -> Self {
245        self.valuation_policy = Some(value);
246        self
247    }
248
249    /// Set the anglo_saxon_accounting field (default: `false`)
250    pub fn anglo_saxon_accounting(mut self, value: bool) -> Self {
251        self.anglo_saxon_accounting = Some(value);
252        self
253    }
254
255    /// Set the stock_interim_delivered_account_id field (optional)
256    pub fn stock_interim_delivered_account_id(mut self, value: Uuid) -> Self {
257        self.stock_interim_delivered_account_id = Some(value);
258        self
259    }
260
261    /// Build the InventoryCompanySetting entity
262    ///
263    /// Returns Err if any required field without a default is missing.
264    pub fn build(self) -> Result<InventoryCompanySetting, String> {
265
266        Ok(InventoryCompanySetting {
267            id: Uuid::new_v4(),
268            cost_method: self.cost_method.unwrap_or_default(),
269            valuation_policy: self.valuation_policy.unwrap_or_default(),
270            anglo_saxon_accounting: self.anglo_saxon_accounting.unwrap_or(false),
271            stock_interim_delivered_account_id: self.stock_interim_delivered_account_id,
272            metadata: AuditMetadata::default(),
273        })
274    }
275}