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::JournalLine;
18use crate::domain::entity::PartyType;
19
20#[derive(Debug, Clone, Deserialize)]
29#[cfg_attr(feature = "openapi", derive(ToSchema))]
30#[serde(rename_all = "camelCase")]
31pub struct CreateJournalLineDto {
32 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
33 #[serde(alias = "journal_id")]
34 pub journal_id: Uuid,
35 #[serde(default, skip_serializing_if = "Option::is_none", alias = "branch_id")]
36 pub branch_id: Option<Uuid>,
37 #[serde(default, skip_serializing_if = "Option::is_none", alias = "party_type")]
38 pub party_type: Option<PartyType>,
39 #[serde(default, skip_serializing_if = "Option::is_none", alias = "party_id")]
40 pub party_id: Option<Uuid>,
41 #[cfg_attr(feature = "openapi", schema(example = 42))]
42 #[serde(alias = "line_number")]
43 pub line_number: i32,
44 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
45 #[serde(alias = "account_id")]
46 pub account_id: Uuid,
47 #[cfg_attr(feature = "openapi", schema(example = "example"))]
48 #[serde(alias = "account_number")]
49 pub account_number: String,
50 #[cfg_attr(feature = "openapi", schema(example = "example"))]
51 #[serde(alias = "account_name")]
52 pub account_name: String,
53 #[serde(alias = "debit_amount")]
54 pub debit_amount: Decimal,
55 #[serde(alias = "credit_amount")]
56 pub credit_amount: Decimal,
57 #[cfg_attr(feature = "openapi", schema(example = "example"))]
58 pub currency: String,
59 #[serde(alias = "exchange_rate")]
60 pub exchange_rate: Decimal,
61 #[serde(alias = "base_debit_amount")]
62 pub base_debit_amount: Decimal,
63 #[serde(alias = "base_credit_amount")]
64 pub base_credit_amount: Decimal,
65 #[serde(default, skip_serializing_if = "Option::is_none")]
66 pub description: Option<String>,
67 #[serde(default, skip_serializing_if = "Option::is_none", alias = "cost_center_id")]
68 pub cost_center_id: Option<Uuid>,
69 #[serde(default, skip_serializing_if = "Option::is_none", alias = "project_id")]
70 pub project_id: Option<Uuid>,
71 #[serde(default, skip_serializing_if = "Option::is_none", alias = "department_id")]
72 pub department_id: Option<Uuid>,
73 #[serde(default, skip_serializing_if = "Option::is_none")]
74 pub dimensions: Option<serde_json::Value>,
75 #[serde(default, skip_serializing_if = "Option::is_none", alias = "source_type")]
76 pub source_type: Option<String>,
77 #[serde(default, skip_serializing_if = "Option::is_none", alias = "source_id")]
78 pub source_id: Option<Uuid>,
79 #[serde(default, skip_serializing_if = "Option::is_none", alias = "source_reference")]
80 pub source_reference: Option<String>,
81 #[cfg_attr(feature = "openapi", schema(example = true))]
82 #[serde(alias = "is_tax_line")]
83 pub is_tax_line: bool,
84 #[serde(default, skip_serializing_if = "Option::is_none", alias = "tax_rate")]
85 pub tax_rate: Option<Decimal>,
86 #[serde(default, skip_serializing_if = "Option::is_none", alias = "tax_base_amount")]
87 pub tax_base_amount: Option<Decimal>,
88 #[serde(default, skip_serializing_if = "Option::is_none", alias = "related_line_id")]
89 pub related_line_id: Option<Uuid>,
90 #[cfg_attr(feature = "openapi", schema(example = true))]
91 #[serde(alias = "has_quantity")]
92 pub has_quantity: bool,
93 #[serde(default, skip_serializing_if = "Option::is_none")]
94 pub quantity: Option<Decimal>,
95 #[serde(default, skip_serializing_if = "Option::is_none")]
96 pub unit: Option<String>,
97 #[serde(default, skip_serializing_if = "Option::is_none", alias = "unit_price")]
98 pub unit_price: Option<Decimal>,
99 #[cfg_attr(feature = "openapi", schema(example = true))]
100 #[serde(alias = "is_reconciled")]
101 pub is_reconciled: bool,
102 #[serde(default, skip_serializing_if = "Option::is_none", alias = "reconciliation_id")]
103 pub reconciliation_id: Option<Uuid>,
104 #[serde(default, skip_serializing_if = "Option::is_none", alias = "reconciled_at")]
105 pub reconciled_at: Option<DateTime<Utc>>,
106 #[serde(default, skip_serializing_if = "Option::is_none", alias = "full_reconcile_id")]
107 pub full_reconcile_id: Option<Uuid>,
108 #[cfg_attr(feature = "openapi", schema(example = true))]
109 #[serde(alias = "is_posted")]
110 pub is_posted: bool,
111 #[serde(default, skip_serializing_if = "Option::is_none", alias = "ledger_id")]
112 pub ledger_id: Option<Uuid>,
113 #[serde(default, skip_serializing_if = "Option::is_none", alias = "posted_at")]
114 pub posted_at: Option<DateTime<Utc>>,
115 pub tags: serde_json::Value,
116 pub data: serde_json::Value,
117}
118
119#[derive(Debug, Clone, Deserialize)]
128#[cfg_attr(feature = "openapi", derive(ToSchema))]
129#[serde(rename_all = "camelCase")]
130pub struct UpdateJournalLineDto {
131 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
132 #[serde(alias = "journal_id")]
133 pub journal_id: Uuid,
134 #[serde(default, skip_serializing_if = "Option::is_none", alias = "branch_id")]
135 pub branch_id: Option<Uuid>,
136 #[serde(default, skip_serializing_if = "Option::is_none", alias = "party_type")]
137 pub party_type: Option<PartyType>,
138 #[serde(default, skip_serializing_if = "Option::is_none", alias = "party_id")]
139 pub party_id: Option<Uuid>,
140 #[cfg_attr(feature = "openapi", schema(example = 42))]
141 #[serde(alias = "line_number")]
142 pub line_number: i32,
143 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
144 #[serde(alias = "account_id")]
145 pub account_id: Uuid,
146 #[cfg_attr(feature = "openapi", schema(example = "example"))]
147 #[serde(alias = "account_number")]
148 pub account_number: String,
149 #[cfg_attr(feature = "openapi", schema(example = "example"))]
150 #[serde(alias = "account_name")]
151 pub account_name: String,
152 #[serde(alias = "debit_amount")]
153 pub debit_amount: Decimal,
154 #[serde(alias = "credit_amount")]
155 pub credit_amount: Decimal,
156 #[cfg_attr(feature = "openapi", schema(example = "example"))]
157 pub currency: String,
158 #[serde(alias = "exchange_rate")]
159 pub exchange_rate: Decimal,
160 #[serde(alias = "base_debit_amount")]
161 pub base_debit_amount: Decimal,
162 #[serde(alias = "base_credit_amount")]
163 pub base_credit_amount: Decimal,
164 #[serde(default, skip_serializing_if = "Option::is_none")]
165 pub description: Option<String>,
166 #[serde(default, skip_serializing_if = "Option::is_none", alias = "cost_center_id")]
167 pub cost_center_id: Option<Uuid>,
168 #[serde(default, skip_serializing_if = "Option::is_none", alias = "project_id")]
169 pub project_id: Option<Uuid>,
170 #[serde(default, skip_serializing_if = "Option::is_none", alias = "department_id")]
171 pub department_id: Option<Uuid>,
172 #[serde(default, skip_serializing_if = "Option::is_none")]
173 pub dimensions: Option<serde_json::Value>,
174 #[serde(default, skip_serializing_if = "Option::is_none", alias = "source_type")]
175 pub source_type: Option<String>,
176 #[serde(default, skip_serializing_if = "Option::is_none", alias = "source_id")]
177 pub source_id: Option<Uuid>,
178 #[serde(default, skip_serializing_if = "Option::is_none", alias = "source_reference")]
179 pub source_reference: Option<String>,
180 #[cfg_attr(feature = "openapi", schema(example = true))]
181 #[serde(alias = "is_tax_line")]
182 pub is_tax_line: bool,
183 #[serde(default, skip_serializing_if = "Option::is_none", alias = "tax_rate")]
184 pub tax_rate: Option<Decimal>,
185 #[serde(default, skip_serializing_if = "Option::is_none", alias = "tax_base_amount")]
186 pub tax_base_amount: Option<Decimal>,
187 #[serde(default, skip_serializing_if = "Option::is_none", alias = "related_line_id")]
188 pub related_line_id: Option<Uuid>,
189 #[cfg_attr(feature = "openapi", schema(example = true))]
190 #[serde(alias = "has_quantity")]
191 pub has_quantity: bool,
192 #[serde(default, skip_serializing_if = "Option::is_none")]
193 pub quantity: Option<Decimal>,
194 #[serde(default, skip_serializing_if = "Option::is_none")]
195 pub unit: Option<String>,
196 #[serde(default, skip_serializing_if = "Option::is_none", alias = "unit_price")]
197 pub unit_price: Option<Decimal>,
198 #[cfg_attr(feature = "openapi", schema(example = true))]
199 #[serde(alias = "is_reconciled")]
200 pub is_reconciled: bool,
201 #[serde(default, skip_serializing_if = "Option::is_none", alias = "reconciliation_id")]
202 pub reconciliation_id: Option<Uuid>,
203 #[serde(default, skip_serializing_if = "Option::is_none", alias = "reconciled_at")]
204 pub reconciled_at: Option<DateTime<Utc>>,
205 #[serde(default, skip_serializing_if = "Option::is_none", alias = "full_reconcile_id")]
206 pub full_reconcile_id: Option<Uuid>,
207 #[cfg_attr(feature = "openapi", schema(example = true))]
208 #[serde(alias = "is_posted")]
209 pub is_posted: bool,
210 #[serde(default, skip_serializing_if = "Option::is_none", alias = "ledger_id")]
211 pub ledger_id: Option<Uuid>,
212 #[serde(default, skip_serializing_if = "Option::is_none", alias = "posted_at")]
213 pub posted_at: Option<DateTime<Utc>>,
214 pub tags: serde_json::Value,
215 pub data: serde_json::Value,
216}
217
218#[derive(Debug, Clone, Default, Deserialize)]
227#[cfg_attr(feature = "openapi", derive(ToSchema))]
228#[serde(rename_all = "camelCase")]
229pub struct PatchJournalLineDto {
230 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
231 #[serde(skip_serializing_if = "Option::is_none", alias = "journal_id")]
232 pub journal_id: Option<Uuid>,
233 #[serde(skip_serializing_if = "Option::is_none", alias = "branch_id")]
234 pub branch_id: Option<Uuid>,
235 #[serde(skip_serializing_if = "Option::is_none", alias = "party_type")]
236 pub party_type: Option<PartyType>,
237 #[serde(skip_serializing_if = "Option::is_none", alias = "party_id")]
238 pub party_id: Option<Uuid>,
239 #[cfg_attr(feature = "openapi", schema(example = 42))]
240 #[serde(skip_serializing_if = "Option::is_none", alias = "line_number")]
241 pub line_number: Option<i32>,
242 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
243 #[serde(skip_serializing_if = "Option::is_none", alias = "account_id")]
244 pub account_id: Option<Uuid>,
245 #[cfg_attr(feature = "openapi", schema(example = "example"))]
246 #[serde(skip_serializing_if = "Option::is_none", alias = "account_number")]
247 pub account_number: Option<String>,
248 #[cfg_attr(feature = "openapi", schema(example = "example"))]
249 #[serde(skip_serializing_if = "Option::is_none", alias = "account_name")]
250 pub account_name: Option<String>,
251 #[serde(skip_serializing_if = "Option::is_none", alias = "debit_amount")]
252 pub debit_amount: Option<Decimal>,
253 #[serde(skip_serializing_if = "Option::is_none", alias = "credit_amount")]
254 pub credit_amount: Option<Decimal>,
255 #[cfg_attr(feature = "openapi", schema(example = "example"))]
256 #[serde(skip_serializing_if = "Option::is_none")]
257 pub currency: Option<String>,
258 #[serde(skip_serializing_if = "Option::is_none", alias = "exchange_rate")]
259 pub exchange_rate: Option<Decimal>,
260 #[serde(skip_serializing_if = "Option::is_none", alias = "base_debit_amount")]
261 pub base_debit_amount: Option<Decimal>,
262 #[serde(skip_serializing_if = "Option::is_none", alias = "base_credit_amount")]
263 pub base_credit_amount: Option<Decimal>,
264 #[serde(skip_serializing_if = "Option::is_none")]
265 pub description: Option<String>,
266 #[serde(skip_serializing_if = "Option::is_none", alias = "cost_center_id")]
267 pub cost_center_id: Option<Uuid>,
268 #[serde(skip_serializing_if = "Option::is_none", alias = "project_id")]
269 pub project_id: Option<Uuid>,
270 #[serde(skip_serializing_if = "Option::is_none", alias = "department_id")]
271 pub department_id: Option<Uuid>,
272 #[serde(skip_serializing_if = "Option::is_none")]
273 pub dimensions: Option<serde_json::Value>,
274 #[serde(skip_serializing_if = "Option::is_none", alias = "source_type")]
275 pub source_type: Option<String>,
276 #[serde(skip_serializing_if = "Option::is_none", alias = "source_id")]
277 pub source_id: Option<Uuid>,
278 #[serde(skip_serializing_if = "Option::is_none", alias = "source_reference")]
279 pub source_reference: Option<String>,
280 #[cfg_attr(feature = "openapi", schema(example = true))]
281 #[serde(skip_serializing_if = "Option::is_none", alias = "is_tax_line")]
282 pub is_tax_line: Option<bool>,
283 #[serde(skip_serializing_if = "Option::is_none", alias = "tax_rate")]
284 pub tax_rate: Option<Decimal>,
285 #[serde(skip_serializing_if = "Option::is_none", alias = "tax_base_amount")]
286 pub tax_base_amount: Option<Decimal>,
287 #[serde(skip_serializing_if = "Option::is_none", alias = "related_line_id")]
288 pub related_line_id: Option<Uuid>,
289 #[cfg_attr(feature = "openapi", schema(example = true))]
290 #[serde(skip_serializing_if = "Option::is_none", alias = "has_quantity")]
291 pub has_quantity: Option<bool>,
292 #[serde(skip_serializing_if = "Option::is_none")]
293 pub quantity: Option<Decimal>,
294 #[serde(skip_serializing_if = "Option::is_none")]
295 pub unit: Option<String>,
296 #[serde(skip_serializing_if = "Option::is_none", alias = "unit_price")]
297 pub unit_price: Option<Decimal>,
298 #[cfg_attr(feature = "openapi", schema(example = true))]
299 #[serde(skip_serializing_if = "Option::is_none", alias = "is_reconciled")]
300 pub is_reconciled: Option<bool>,
301 #[serde(skip_serializing_if = "Option::is_none", alias = "reconciliation_id")]
302 pub reconciliation_id: Option<Uuid>,
303 #[serde(skip_serializing_if = "Option::is_none", alias = "reconciled_at")]
304 pub reconciled_at: Option<DateTime<Utc>>,
305 #[serde(skip_serializing_if = "Option::is_none", alias = "full_reconcile_id")]
306 pub full_reconcile_id: Option<Uuid>,
307 #[cfg_attr(feature = "openapi", schema(example = true))]
308 #[serde(skip_serializing_if = "Option::is_none", alias = "is_posted")]
309 pub is_posted: Option<bool>,
310 #[serde(skip_serializing_if = "Option::is_none", alias = "ledger_id")]
311 pub ledger_id: Option<Uuid>,
312 #[serde(skip_serializing_if = "Option::is_none", alias = "posted_at")]
313 pub posted_at: Option<DateTime<Utc>>,
314 #[serde(skip_serializing_if = "Option::is_none")]
315 pub tags: Option<serde_json::Value>,
316 #[serde(skip_serializing_if = "Option::is_none")]
317 pub data: Option<serde_json::Value>,
318}
319
320impl PatchJournalLineDto {
321 pub fn has_changes(&self) -> bool {
323 self.journal_id.is_some() || self.branch_id.is_some() || self.party_type.is_some() || self.party_id.is_some() || self.line_number.is_some() || self.account_id.is_some() || self.account_number.is_some() || self.account_name.is_some() || self.debit_amount.is_some() || self.credit_amount.is_some() || self.currency.is_some() || self.exchange_rate.is_some() || self.base_debit_amount.is_some() || self.base_credit_amount.is_some() || self.description.is_some() || self.cost_center_id.is_some() || self.project_id.is_some() || self.department_id.is_some() || self.dimensions.is_some() || self.source_type.is_some() || self.source_id.is_some() || self.source_reference.is_some() || self.is_tax_line.is_some() || self.tax_rate.is_some() || self.tax_base_amount.is_some() || self.related_line_id.is_some() || self.has_quantity.is_some() || self.quantity.is_some() || self.unit.is_some() || self.unit_price.is_some() || self.is_reconciled.is_some() || self.reconciliation_id.is_some() || self.reconciled_at.is_some() || self.full_reconcile_id.is_some() || self.is_posted.is_some() || self.ledger_id.is_some() || self.posted_at.is_some() || self.tags.is_some() || self.data.is_some()
324 }
325}
326
327#[derive(Debug, Clone, Serialize)]
336#[cfg_attr(feature = "openapi", derive(ToSchema))]
337#[serde(rename_all = "camelCase")]
338pub struct JournalLineResponseDto {
339 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
340 pub id: Uuid,
341 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
342 pub journal_id: Uuid,
343 pub branch_id: Option<Uuid>,
344 pub party_type: Option<PartyType>,
345 pub party_id: Option<Uuid>,
346 #[cfg_attr(feature = "openapi", schema(example = 42))]
347 pub line_number: i32,
348 #[cfg_attr(feature = "openapi", schema(example = "550e8400-e29b-41d4-a716-446655440000"))]
349 pub account_id: Uuid,
350 #[cfg_attr(feature = "openapi", schema(example = "example"))]
351 pub account_number: String,
352 #[cfg_attr(feature = "openapi", schema(example = "example"))]
353 pub account_name: String,
354 pub debit_amount: Decimal,
355 pub credit_amount: Decimal,
356 #[cfg_attr(feature = "openapi", schema(example = "example"))]
357 pub currency: String,
358 pub exchange_rate: Decimal,
359 pub base_debit_amount: Decimal,
360 pub base_credit_amount: Decimal,
361 pub description: Option<String>,
362 pub cost_center_id: Option<Uuid>,
363 pub project_id: Option<Uuid>,
364 pub department_id: Option<Uuid>,
365 pub dimensions: Option<serde_json::Value>,
366 pub source_type: Option<String>,
367 pub source_id: Option<Uuid>,
368 pub source_reference: Option<String>,
369 #[cfg_attr(feature = "openapi", schema(example = true))]
370 pub is_tax_line: bool,
371 pub tax_rate: Option<Decimal>,
372 pub tax_base_amount: Option<Decimal>,
373 pub related_line_id: Option<Uuid>,
374 #[cfg_attr(feature = "openapi", schema(example = true))]
375 pub has_quantity: bool,
376 pub quantity: Option<Decimal>,
377 pub unit: Option<String>,
378 pub unit_price: Option<Decimal>,
379 #[cfg_attr(feature = "openapi", schema(example = true))]
380 pub is_reconciled: bool,
381 pub reconciliation_id: Option<Uuid>,
382 pub reconciled_at: Option<DateTime<Utc>>,
383 pub full_reconcile_id: Option<Uuid>,
384 #[cfg_attr(feature = "openapi", schema(example = true))]
385 pub is_posted: bool,
386 pub ledger_id: Option<Uuid>,
387 pub posted_at: Option<DateTime<Utc>>,
388 pub tags: serde_json::Value,
389 pub data: serde_json::Value,
390}
391
392#[derive(Debug, Clone, Serialize)]
401#[cfg_attr(feature = "openapi", derive(ToSchema))]
402#[serde(rename_all = "camelCase")]
403pub struct JournalLineListResponseDto {
404 pub items: Vec<JournalLineResponseDto>,
406 pub total: u64,
408 pub page: u32,
410 pub per_page: u32,
412 pub total_pages: u32,
414 pub has_next: bool,
416 pub has_prev: bool,
418}
419
420impl JournalLineListResponseDto {
421 pub fn new(items: Vec<JournalLineResponseDto>, total: u64, page: u32, per_page: u32) -> Self {
423 let total_pages = if per_page > 0 {
424 ((total as f64) / (per_page as f64)).ceil() as u32
425 } else {
426 0
427 };
428 Self {
429 items,
430 total,
431 page,
432 per_page,
433 total_pages,
434 has_next: page < total_pages,
435 has_prev: page > 1,
436 }
437 }
438}
439
440#[derive(Debug, Clone, Serialize)]
442#[cfg_attr(feature = "openapi", derive(ToSchema))]
443#[serde(rename_all = "camelCase")]
444pub struct JournalLineSummaryDto {
445 pub id: Uuid,
446 pub journal_id: Uuid,
447 pub branch_id: Option<Uuid>,
448 pub party_type: Option<PartyType>,
449 pub created_at: Option<DateTime<Utc>>,
450}
451
452impl From<JournalLine> for JournalLineResponseDto {
457 fn from(entity: JournalLine) -> Self {
458 Self {
459 id: entity.id,
460 journal_id: entity.journal_id,
461 branch_id: entity.branch_id,
462 party_type: entity.party_type,
463 party_id: entity.party_id,
464 line_number: entity.line_number,
465 account_id: entity.account_id,
466 account_number: entity.account_number,
467 account_name: entity.account_name,
468 debit_amount: entity.debit_amount,
469 credit_amount: entity.credit_amount,
470 currency: entity.currency,
471 exchange_rate: entity.exchange_rate,
472 base_debit_amount: entity.base_debit_amount,
473 base_credit_amount: entity.base_credit_amount,
474 description: entity.description,
475 cost_center_id: entity.cost_center_id,
476 project_id: entity.project_id,
477 department_id: entity.department_id,
478 dimensions: entity.dimensions,
479 source_type: entity.source_type,
480 source_id: entity.source_id,
481 source_reference: entity.source_reference,
482 is_tax_line: entity.is_tax_line,
483 tax_rate: entity.tax_rate,
484 tax_base_amount: entity.tax_base_amount,
485 related_line_id: entity.related_line_id,
486 has_quantity: entity.has_quantity,
487 quantity: entity.quantity,
488 unit: entity.unit,
489 unit_price: entity.unit_price,
490 is_reconciled: entity.is_reconciled,
491 reconciliation_id: entity.reconciliation_id,
492 reconciled_at: entity.reconciled_at,
493 full_reconcile_id: entity.full_reconcile_id,
494 is_posted: entity.is_posted,
495 ledger_id: entity.ledger_id,
496 posted_at: entity.posted_at,
497 tags: entity.tags,
498 data: entity.data,
499 }
500 }
501}
502
503impl From<JournalLine> for JournalLineSummaryDto {
504 fn from(entity: JournalLine) -> Self {
505 let created_at = backbone_core::PersistentEntity::created_at(&entity);
506 Self {
507 id: entity.id,
508 journal_id: entity.journal_id,
509 branch_id: entity.branch_id,
510 party_type: entity.party_type,
511 created_at,
512 }
513 }
514}
515
516impl From<CreateJournalLineDto> for JournalLine {
517 fn from(dto: CreateJournalLineDto) -> Self {
518 Self {
519 id: Uuid::new_v4(),
520 journal_id: dto.journal_id,
521 branch_id: dto.branch_id,
522 party_type: dto.party_type,
523 party_id: dto.party_id,
524 line_number: dto.line_number,
525 account_id: dto.account_id,
526 account_number: dto.account_number,
527 account_name: dto.account_name,
528 debit_amount: dto.debit_amount,
529 credit_amount: dto.credit_amount,
530 currency: dto.currency,
531 exchange_rate: dto.exchange_rate,
532 base_debit_amount: dto.base_debit_amount,
533 base_credit_amount: dto.base_credit_amount,
534 description: dto.description,
535 cost_center_id: dto.cost_center_id,
536 project_id: dto.project_id,
537 department_id: dto.department_id,
538 dimensions: dto.dimensions,
539 source_type: dto.source_type,
540 source_id: dto.source_id,
541 source_reference: dto.source_reference,
542 is_tax_line: dto.is_tax_line,
543 tax_rate: dto.tax_rate,
544 tax_base_amount: dto.tax_base_amount,
545 related_line_id: dto.related_line_id,
546 has_quantity: dto.has_quantity,
547 quantity: dto.quantity,
548 unit: dto.unit,
549 unit_price: dto.unit_price,
550 is_reconciled: dto.is_reconciled,
551 reconciliation_id: dto.reconciliation_id,
552 reconciled_at: dto.reconciled_at,
553 full_reconcile_id: dto.full_reconcile_id,
554 is_posted: dto.is_posted,
555 ledger_id: dto.ledger_id,
556 posted_at: dto.posted_at,
557 tags: dto.tags,
558 data: dto.data,
559 }
560 }
561}
562
563impl From<&JournalLine> for JournalLineResponseDto {
564 fn from(entity: &JournalLine) -> Self {
565 Self {
566 id: entity.id.clone(),
567 journal_id: entity.journal_id.clone(),
568 branch_id: entity.branch_id.clone(),
569 party_type: entity.party_type.clone(),
570 party_id: entity.party_id.clone(),
571 line_number: entity.line_number.clone(),
572 account_id: entity.account_id.clone(),
573 account_number: entity.account_number.clone(),
574 account_name: entity.account_name.clone(),
575 debit_amount: entity.debit_amount.clone(),
576 credit_amount: entity.credit_amount.clone(),
577 currency: entity.currency.clone(),
578 exchange_rate: entity.exchange_rate.clone(),
579 base_debit_amount: entity.base_debit_amount.clone(),
580 base_credit_amount: entity.base_credit_amount.clone(),
581 description: entity.description.clone(),
582 cost_center_id: entity.cost_center_id.clone(),
583 project_id: entity.project_id.clone(),
584 department_id: entity.department_id.clone(),
585 dimensions: entity.dimensions.clone(),
586 source_type: entity.source_type.clone(),
587 source_id: entity.source_id.clone(),
588 source_reference: entity.source_reference.clone(),
589 is_tax_line: entity.is_tax_line.clone(),
590 tax_rate: entity.tax_rate.clone(),
591 tax_base_amount: entity.tax_base_amount.clone(),
592 related_line_id: entity.related_line_id.clone(),
593 has_quantity: entity.has_quantity.clone(),
594 quantity: entity.quantity.clone(),
595 unit: entity.unit.clone(),
596 unit_price: entity.unit_price.clone(),
597 is_reconciled: entity.is_reconciled.clone(),
598 reconciliation_id: entity.reconciliation_id.clone(),
599 reconciled_at: entity.reconciled_at.clone(),
600 full_reconcile_id: entity.full_reconcile_id.clone(),
601 is_posted: entity.is_posted.clone(),
602 ledger_id: entity.ledger_id.clone(),
603 posted_at: entity.posted_at.clone(),
604 tags: entity.tags.clone(),
605 data: entity.data.clone(),
606 }
607 }
608}
609
610impl backbone_core::FromCreateDto<CreateJournalLineDto> for JournalLine {
611 fn from_create_dto(dto: CreateJournalLineDto) -> backbone_core::ServiceResult<Self> {
612 Ok(JournalLine::from(dto))
613 }
614}
615
616impl backbone_core::ApplyUpdateDto<UpdateJournalLineDto> for JournalLine {
617 fn apply_update(mut self, dto: UpdateJournalLineDto) -> backbone_core::ServiceResult<Self> {
618 self.journal_id = dto.journal_id;
619 self.branch_id = dto.branch_id;
620 self.party_type = dto.party_type;
621 self.party_id = dto.party_id;
622 self.line_number = dto.line_number;
623 self.account_id = dto.account_id;
624 self.account_number = dto.account_number;
625 self.account_name = dto.account_name;
626 self.debit_amount = dto.debit_amount;
627 self.credit_amount = dto.credit_amount;
628 self.currency = dto.currency;
629 self.exchange_rate = dto.exchange_rate;
630 self.base_debit_amount = dto.base_debit_amount;
631 self.base_credit_amount = dto.base_credit_amount;
632 self.description = dto.description;
633 self.cost_center_id = dto.cost_center_id;
634 self.project_id = dto.project_id;
635 self.department_id = dto.department_id;
636 self.dimensions = dto.dimensions;
637 self.source_type = dto.source_type;
638 self.source_id = dto.source_id;
639 self.source_reference = dto.source_reference;
640 self.is_tax_line = dto.is_tax_line;
641 self.tax_rate = dto.tax_rate;
642 self.tax_base_amount = dto.tax_base_amount;
643 self.related_line_id = dto.related_line_id;
644 self.has_quantity = dto.has_quantity;
645 self.quantity = dto.quantity;
646 self.unit = dto.unit;
647 self.unit_price = dto.unit_price;
648 self.is_reconciled = dto.is_reconciled;
649 self.reconciliation_id = dto.reconciliation_id;
650 self.reconciled_at = dto.reconciled_at;
651 self.full_reconcile_id = dto.full_reconcile_id;
652 self.is_posted = dto.is_posted;
653 self.ledger_id = dto.ledger_id;
654 self.posted_at = dto.posted_at;
655 self.tags = dto.tags;
656 self.data = dto.data;
657 Ok(self)
658 }
659}
660
661