backbone_accounting/domain/entity/
printed_check.rs1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use sqlx::FromRow;
4use uuid::Uuid;
5use rust_decimal::Decimal;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9#[serde(transparent)]
10pub struct PrintedCheckId(pub Uuid);
11
12impl PrintedCheckId {
13 pub fn new(id: Uuid) -> Self { Self(id) }
14 pub fn generate() -> Self { Self(Uuid::new_v4()) }
15 pub fn into_inner(self) -> Uuid { self.0 }
16}
17
18impl std::fmt::Display for PrintedCheckId {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 write!(f, "{}", self.0)
21 }
22}
23
24impl std::str::FromStr for PrintedCheckId {
25 type Err = uuid::Error;
26 fn from_str(s: &str) -> Result<Self, Self::Err> {
27 Ok(Self(Uuid::parse_str(s)?))
28 }
29}
30
31impl From<Uuid> for PrintedCheckId {
32 fn from(id: Uuid) -> Self { Self(id) }
33}
34
35impl From<PrintedCheckId> for Uuid {
36 fn from(id: PrintedCheckId) -> Self { id.0 }
37}
38
39impl AsRef<Uuid> for PrintedCheckId {
40 fn as_ref(&self) -> &Uuid { &self.0 }
41}
42
43impl std::ops::Deref for PrintedCheckId {
44 type Target = Uuid;
45 fn deref(&self) -> &Self::Target { &self.0 }
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
49pub struct PrintedCheck {
50 pub id: Uuid,
51 pub bank_account_id: Uuid,
52 pub payment_id: Uuid,
53 pub payment_number: Option<String>,
54 pub check_number: String,
55 pub amount: Decimal,
56 pub payee_name: Option<String>,
57 pub status: String,
58 pub printed_at: DateTime<Utc>,
59 pub printed_by: Option<Uuid>,
60 pub created_at: DateTime<Utc>,
61 pub updated_at: DateTime<Utc>,
62 pub metadata: serde_json::Value,
63}
64
65impl PrintedCheck {
66 pub fn builder() -> PrintedCheckBuilder {
68 <PrintedCheckBuilder as Default>::default()
69 }
70
71 pub fn new(bank_account_id: Uuid, payment_id: Uuid, check_number: String, amount: Decimal, status: String, printed_at: DateTime<Utc>, metadata: serde_json::Value) -> Self {
73 Self {
74 id: Uuid::new_v4(),
75 bank_account_id,
76 payment_id,
77 payment_number: None,
78 check_number,
79 amount,
80 payee_name: None,
81 status,
82 printed_at,
83 printed_by: None,
84 created_at: Utc::now(),
85 updated_at: Utc::now(),
86 metadata,
87 }
88 }
89
90 pub fn id(&self) -> &Uuid {
92 &self.id
93 }
94
95 pub fn typed_id(&self) -> PrintedCheckId {
97 PrintedCheckId(self.id)
98 }
99
100 pub fn created_at(&self) -> &DateTime<Utc> {
102 &self.created_at
103 }
104
105 pub fn updated_at(&self) -> &DateTime<Utc> {
107 &self.updated_at
108 }
109
110 pub fn status(&self) -> &String {
112 &self.status
113 }
114
115
116 pub fn with_payment_number(mut self, value: String) -> Self {
122 self.payment_number = Some(value);
123 self
124 }
125
126 pub fn with_payee_name(mut self, value: String) -> Self {
128 self.payee_name = Some(value);
129 self
130 }
131
132 pub fn with_printed_by(mut self, value: Uuid) -> Self {
134 self.printed_by = Some(value);
135 self
136 }
137
138 pub fn apply_patch(&mut self, fields: std::collections::HashMap<String, serde_json::Value>) {
144 for (key, value) in fields {
145 match key.as_str() {
146 "bank_account_id" => {
147 if let Ok(v) = serde_json::from_value(value) { self.bank_account_id = v; }
148 }
149 "payment_id" => {
150 if let Ok(v) = serde_json::from_value(value) { self.payment_id = v; }
151 }
152 "payment_number" => {
153 if let Ok(v) = serde_json::from_value(value) { self.payment_number = v; }
154 }
155 "check_number" => {
156 if let Ok(v) = serde_json::from_value(value) { self.check_number = v; }
157 }
158 "amount" => {
159 if let Ok(v) = serde_json::from_value(value) { self.amount = v; }
160 }
161 "payee_name" => {
162 if let Ok(v) = serde_json::from_value(value) { self.payee_name = v; }
163 }
164 "status" => {
165 if let Ok(v) = serde_json::from_value(value) { self.status = v; }
166 }
167 "printed_at" => {
168 if let Ok(v) = serde_json::from_value(value) { self.printed_at = v; }
169 }
170 "printed_by" => {
171 if let Ok(v) = serde_json::from_value(value) { self.printed_by = v; }
172 }
173 "metadata" => {
174 if let Ok(v) = serde_json::from_value(value) { self.metadata = v; }
175 }
176 _ => {} }
178 }
179 }
180
181}
182
183impl super::Entity for PrintedCheck {
184 type Id = Uuid;
185
186 fn entity_id(&self) -> &Self::Id {
187 &self.id
188 }
189
190 fn entity_type() -> &'static str {
191 "PrintedCheck"
192 }
193}
194
195impl backbone_core::PersistentEntity for PrintedCheck {
196 fn write_protected_fields() -> &'static [&'static str] {
197 &["created_at"]
198 }
199 fn entity_id(&self) -> String {
200 self.id.to_string()
201 }
202 fn set_entity_id(&mut self, id: String) {
203 if let Ok(uuid) = uuid::Uuid::parse_str(&id) {
204 self.id = uuid;
205 }
206 }
207 fn created_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
208 Some(self.created_at)
209 }
210 fn set_created_at(&mut self, ts: chrono::DateTime<chrono::Utc>) {
211 self.created_at = ts;
212 }
213 fn updated_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
214 Some(self.updated_at)
215 }
216 fn set_updated_at(&mut self, ts: chrono::DateTime<chrono::Utc>) {
217 self.updated_at = ts;
218 }
219 fn deleted_at(&self) -> Option<chrono::DateTime<chrono::Utc>> {
220 None
221 }
222 fn set_deleted_at(&mut self, ts: Option<chrono::DateTime<chrono::Utc>>) {
223 let _ = ts;
224 }
225}
226
227impl backbone_orm::EntityRepoMeta for PrintedCheck {
228 fn column_types() -> std::collections::HashMap<String, String> {
229 let mut m = std::collections::HashMap::new();
230 m.insert("id".to_string(), "uuid".to_string());
231 m.insert("bank_account_id".to_string(), "uuid".to_string());
232 m.insert("payment_id".to_string(), "uuid".to_string());
233 m.insert("printed_at".to_string(), "timestamptz".to_string());
234 m.insert("created_at".to_string(), "timestamptz".to_string());
235 m.insert("updated_at".to_string(), "timestamptz".to_string());
236 m
237 }
238 fn search_fields() -> &'static [&'static str] {
239 &["check_number", "status"]
240 }
241}
242
243#[derive(Debug, Clone, Default)]
248pub struct PrintedCheckBuilder {
249 bank_account_id: Option<Uuid>,
250 payment_id: Option<Uuid>,
251 payment_number: Option<String>,
252 check_number: Option<String>,
253 amount: Option<Decimal>,
254 payee_name: Option<String>,
255 status: Option<String>,
256 printed_at: Option<DateTime<Utc>>,
257 printed_by: Option<Uuid>,
258 metadata: Option<serde_json::Value>,
259}
260
261impl PrintedCheckBuilder {
262 pub fn bank_account_id(mut self, value: Uuid) -> Self {
264 self.bank_account_id = Some(value);
265 self
266 }
267
268 pub fn payment_id(mut self, value: Uuid) -> Self {
270 self.payment_id = Some(value);
271 self
272 }
273
274 pub fn payment_number(mut self, value: String) -> Self {
276 self.payment_number = Some(value);
277 self
278 }
279
280 pub fn check_number(mut self, value: String) -> Self {
282 self.check_number = Some(value);
283 self
284 }
285
286 pub fn amount(mut self, value: Decimal) -> Self {
288 self.amount = Some(value);
289 self
290 }
291
292 pub fn payee_name(mut self, value: String) -> Self {
294 self.payee_name = Some(value);
295 self
296 }
297
298 pub fn status(mut self, value: String) -> Self {
300 self.status = Some(value);
301 self
302 }
303
304 pub fn printed_at(mut self, value: DateTime<Utc>) -> Self {
306 self.printed_at = Some(value);
307 self
308 }
309
310 pub fn printed_by(mut self, value: Uuid) -> Self {
312 self.printed_by = Some(value);
313 self
314 }
315
316 pub fn metadata(mut self, value: serde_json::Value) -> Self {
318 self.metadata = Some(value);
319 self
320 }
321
322 pub fn build(self) -> Result<PrintedCheck, String> {
326 let bank_account_id = self.bank_account_id.ok_or_else(|| "bank_account_id is required".to_string())?;
327 let payment_id = self.payment_id.ok_or_else(|| "payment_id is required".to_string())?;
328 let check_number = self.check_number.ok_or_else(|| "check_number is required".to_string())?;
329 let amount = self.amount.ok_or_else(|| "amount is required".to_string())?;
330
331 Ok(PrintedCheck {
332 id: Uuid::new_v4(),
333 bank_account_id,
334 payment_id,
335 payment_number: self.payment_number,
336 check_number,
337 amount,
338 payee_name: self.payee_name,
339 status: self.status.unwrap_or_default(),
340 printed_at: self.printed_at.unwrap_or(Utc::now()),
341 printed_by: self.printed_by,
342 created_at: Utc::now(),
343 updated_at: Utc::now(),
344 metadata: self.metadata.unwrap_or(serde_json::json!({})),
345 })
346 }
347}