1use serde::{Deserialize, Serialize};
9use uuid::Uuid;
10use chrono::{DateTime, Utc};
11use rust_decimal::Decimal;
12
13#[cfg(feature = "openapi")]
14#[cfg(feature = "openapi")]
15use utoipa::ToSchema;
16
17use crate::domain::entity::PrintedCheck;
18
19#[derive(Debug, Clone, Deserialize)]
28#[cfg_attr(feature = "openapi", derive(ToSchema))]
29#[serde(rename_all = "camelCase")]
30pub struct CreatePrintedCheckDto {
31 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
32 #[serde(alias = "bank_account_id")]
33 pub bank_account_id: Uuid,
34 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
35 #[serde(alias = "payment_id")]
36 pub payment_id: Uuid,
37 #[serde(default, skip_serializing_if = "Option::is_none", alias = "payment_number")]
38 pub payment_number: Option<String>,
39 #[cfg_attr(feature = "openapi", schema(example = "example"))]
40 #[serde(alias = "check_number")]
41 pub check_number: String,
42 pub amount: Decimal,
43 #[serde(default, skip_serializing_if = "Option::is_none", alias = "payee_name")]
44 pub payee_name: Option<String>,
45 #[cfg_attr(feature = "openapi", schema(example = "example"))]
46 pub status: String,
47 #[cfg_attr(feature = "openapi", schema(example = "2024-01-01T00:00:00Z"))]
48 #[serde(alias = "printed_at")]
49 pub printed_at: DateTime<Utc>,
50 #[serde(default, skip_serializing_if = "Option::is_none", alias = "printed_by")]
51 pub printed_by: Option<Uuid>,
52}
53
54#[derive(Debug, Clone, Deserialize)]
63#[cfg_attr(feature = "openapi", derive(ToSchema))]
64#[serde(rename_all = "camelCase")]
65pub struct UpdatePrintedCheckDto {
66 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
67 #[serde(alias = "bank_account_id")]
68 pub bank_account_id: Uuid,
69 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
70 #[serde(alias = "payment_id")]
71 pub payment_id: Uuid,
72 #[serde(default, skip_serializing_if = "Option::is_none", alias = "payment_number")]
73 pub payment_number: Option<String>,
74 #[cfg_attr(feature = "openapi", schema(example = "example"))]
75 #[serde(alias = "check_number")]
76 pub check_number: String,
77 pub amount: Decimal,
78 #[serde(default, skip_serializing_if = "Option::is_none", alias = "payee_name")]
79 pub payee_name: Option<String>,
80 #[cfg_attr(feature = "openapi", schema(example = "example"))]
81 pub status: String,
82 #[cfg_attr(feature = "openapi", schema(example = "2024-01-01T00:00:00Z"))]
83 #[serde(alias = "printed_at")]
84 pub printed_at: DateTime<Utc>,
85 #[serde(default, skip_serializing_if = "Option::is_none", alias = "printed_by")]
86 pub printed_by: Option<Uuid>,
87}
88
89#[derive(Debug, Clone, Default, Deserialize)]
98#[cfg_attr(feature = "openapi", derive(ToSchema))]
99#[serde(rename_all = "camelCase")]
100pub struct PatchPrintedCheckDto {
101 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
102 #[serde(skip_serializing_if = "Option::is_none", alias = "bank_account_id")]
103 pub bank_account_id: Option<Uuid>,
104 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
105 #[serde(skip_serializing_if = "Option::is_none", alias = "payment_id")]
106 pub payment_id: Option<Uuid>,
107 #[serde(skip_serializing_if = "Option::is_none", alias = "payment_number")]
108 pub payment_number: Option<String>,
109 #[cfg_attr(feature = "openapi", schema(example = "example"))]
110 #[serde(skip_serializing_if = "Option::is_none", alias = "check_number")]
111 pub check_number: Option<String>,
112 #[serde(skip_serializing_if = "Option::is_none")]
113 pub amount: Option<Decimal>,
114 #[serde(skip_serializing_if = "Option::is_none", alias = "payee_name")]
115 pub payee_name: Option<String>,
116 #[cfg_attr(feature = "openapi", schema(example = "example"))]
117 #[serde(skip_serializing_if = "Option::is_none")]
118 pub status: Option<String>,
119 #[cfg_attr(feature = "openapi", schema(example = "2024-01-01T00:00:00Z"))]
120 #[serde(skip_serializing_if = "Option::is_none", alias = "printed_at")]
121 pub printed_at: Option<DateTime<Utc>>,
122 #[serde(skip_serializing_if = "Option::is_none", alias = "printed_by")]
123 pub printed_by: Option<Uuid>,
124}
125
126impl PatchPrintedCheckDto {
127 pub fn has_changes(&self) -> bool {
129 self.bank_account_id.is_some() || self.payment_id.is_some() || self.payment_number.is_some() || self.check_number.is_some() || self.amount.is_some() || self.payee_name.is_some() || self.status.is_some() || self.printed_at.is_some() || self.printed_by.is_some()
130 }
131}
132
133#[derive(Debug, Clone, Serialize)]
142#[cfg_attr(feature = "openapi", derive(ToSchema))]
143#[serde(rename_all = "camelCase")]
144pub struct PrintedCheckResponseDto {
145 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
146 pub id: Uuid,
147 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
148 pub bank_account_id: Uuid,
149 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
150 pub payment_id: Uuid,
151 pub payment_number: Option<String>,
152 #[cfg_attr(feature = "openapi", schema(example = "example"))]
153 pub check_number: String,
154 pub amount: Decimal,
155 pub payee_name: Option<String>,
156 #[cfg_attr(feature = "openapi", schema(example = "example"))]
157 pub status: String,
158 #[cfg_attr(feature = "openapi", schema(example = "2024-01-01T00:00:00Z"))]
159 pub printed_at: DateTime<Utc>,
160 pub printed_by: Option<Uuid>,
161 #[cfg_attr(feature = "openapi", schema(example = "2024-01-01T00:00:00Z"))]
162 pub created_at: DateTime<Utc>,
163 #[cfg_attr(feature = "openapi", schema(example = "2024-01-01T00:00:00Z"))]
164 pub updated_at: DateTime<Utc>,
165 pub metadata: serde_json::Value,
166}
167
168#[derive(Debug, Clone, Serialize)]
177#[cfg_attr(feature = "openapi", derive(ToSchema))]
178#[serde(rename_all = "camelCase")]
179pub struct PrintedCheckListResponseDto {
180 pub items: Vec<PrintedCheckResponseDto>,
182 pub total: u64,
184 pub page: u32,
186 pub per_page: u32,
188 pub total_pages: u32,
190 pub has_next: bool,
192 pub has_prev: bool,
194}
195
196impl PrintedCheckListResponseDto {
197 pub fn new(items: Vec<PrintedCheckResponseDto>, total: u64, page: u32, per_page: u32) -> Self {
199 let total_pages = if per_page > 0 {
200 ((total as f64) / (per_page as f64)).ceil() as u32
201 } else {
202 0
203 };
204 Self {
205 items,
206 total,
207 page,
208 per_page,
209 total_pages,
210 has_next: page < total_pages,
211 has_prev: page > 1,
212 }
213 }
214}
215
216#[derive(Debug, Clone, Serialize)]
218#[cfg_attr(feature = "openapi", derive(ToSchema))]
219#[serde(rename_all = "camelCase")]
220pub struct PrintedCheckSummaryDto {
221 pub id: Uuid,
222 pub bank_account_id: Uuid,
223 pub payment_id: Uuid,
224 pub payment_number: Option<String>,
225 pub created_at: Option<DateTime<Utc>>,
226}
227
228impl From<PrintedCheck> for PrintedCheckResponseDto {
233 fn from(entity: PrintedCheck) -> Self {
234 Self {
235 id: entity.id,
236 bank_account_id: entity.bank_account_id,
237 payment_id: entity.payment_id,
238 payment_number: entity.payment_number,
239 check_number: entity.check_number,
240 amount: entity.amount,
241 payee_name: entity.payee_name,
242 status: entity.status,
243 printed_at: entity.printed_at,
244 printed_by: entity.printed_by,
245 created_at: entity.created_at,
246 updated_at: entity.updated_at,
247 metadata: entity.metadata,
248 }
249 }
250}
251
252impl From<PrintedCheck> for PrintedCheckSummaryDto {
253 fn from(entity: PrintedCheck) -> Self {
254 Self {
255 id: entity.id,
256 bank_account_id: entity.bank_account_id,
257 payment_id: entity.payment_id,
258 payment_number: entity.payment_number,
259 created_at: Some(entity.created_at),
260 }
261 }
262}
263
264impl From<CreatePrintedCheckDto> for PrintedCheck {
265 fn from(dto: CreatePrintedCheckDto) -> Self {
266 Self {
267 id: Uuid::new_v4(),
268 bank_account_id: dto.bank_account_id,
269 payment_id: dto.payment_id,
270 payment_number: dto.payment_number,
271 check_number: dto.check_number,
272 amount: dto.amount,
273 payee_name: dto.payee_name,
274 status: dto.status,
275 printed_at: dto.printed_at,
276 printed_by: dto.printed_by,
277 created_at: Utc::now(),
278 updated_at: Utc::now(),
279 metadata: serde_json::json!({}),
280 }
281 }
282}
283
284impl From<&PrintedCheck> for PrintedCheckResponseDto {
285 fn from(entity: &PrintedCheck) -> Self {
286 Self {
287 id: entity.id.clone(),
288 bank_account_id: entity.bank_account_id.clone(),
289 payment_id: entity.payment_id.clone(),
290 payment_number: entity.payment_number.clone(),
291 check_number: entity.check_number.clone(),
292 amount: entity.amount.clone(),
293 payee_name: entity.payee_name.clone(),
294 status: entity.status.clone(),
295 printed_at: entity.printed_at.clone(),
296 printed_by: entity.printed_by.clone(),
297 created_at: entity.created_at.clone(),
298 updated_at: entity.updated_at.clone(),
299 metadata: entity.metadata.clone(),
300 }
301 }
302}
303
304impl backbone_core::FromCreateDto<CreatePrintedCheckDto> for PrintedCheck {
305 fn from_create_dto(dto: CreatePrintedCheckDto) -> backbone_core::ServiceResult<Self> {
306 Ok(PrintedCheck::from(dto))
307 }
308}
309
310impl backbone_core::ApplyUpdateDto<UpdatePrintedCheckDto> for PrintedCheck {
311 fn apply_update(mut self, dto: UpdatePrintedCheckDto) -> backbone_core::ServiceResult<Self> {
312 self.updated_at = Utc::now();
313 self.bank_account_id = dto.bank_account_id;
314 self.payment_id = dto.payment_id;
315 self.payment_number = dto.payment_number;
316 self.check_number = dto.check_number;
317 self.amount = dto.amount;
318 self.payee_name = dto.payee_name;
319 self.status = dto.status;
320 self.printed_at = dto.printed_at;
321 self.printed_by = dto.printed_by;
322 Ok(self)
323 }
324}
325
326