1use rust_decimal::prelude::ToPrimitive;
2
3use cala_types::balance::{BalanceAmount, BalanceSnapshot};
4
5use crate::primitives::*;
6
7use crate::{
8 account::*,
9 account_set::*,
10 entry::*,
11 journal::*,
12 outbox::event::{OutboxEvent, OutboxEventPayload},
13 transaction::TransactionValues,
14 tx_template::*,
15};
16
17use super::proto;
18
19impl From<OutboxEvent> for proto::CalaLedgerEvent {
20 fn from(
21 OutboxEvent {
22 id,
23 sequence,
24 payload,
25 recorded_at,
26 }: OutboxEvent,
27 ) -> Self {
28 let payload = match payload {
29 OutboxEventPayload::AccountCreated { source, account } => {
30 proto::cala_ledger_event::Payload::AccountCreated(proto::AccountCreated {
31 data_source_id: source.to_string(),
32 account: Some(proto::Account::from(account)),
33 })
34 }
35 OutboxEventPayload::AccountUpdated {
36 source,
37 account,
38 fields,
39 } => proto::cala_ledger_event::Payload::AccountUpdated(proto::AccountUpdated {
40 data_source_id: source.to_string(),
41 account: Some(proto::Account::from(account)),
42 fields,
43 }),
44 OutboxEventPayload::AccountSetCreated {
45 source,
46 account_set,
47 } => proto::cala_ledger_event::Payload::AccountSetCreated(proto::AccountSetCreated {
48 data_source_id: source.to_string(),
49 account_set: Some(proto::AccountSet::from(account_set)),
50 }),
51 OutboxEventPayload::AccountSetUpdated {
52 source,
53 account_set,
54 fields,
55 } => proto::cala_ledger_event::Payload::AccountSetUpdated(proto::AccountSetUpdated {
56 data_source_id: source.to_string(),
57 account_set: Some(proto::AccountSet::from(account_set)),
58 fields,
59 }),
60 OutboxEventPayload::AccountSetMemberCreated {
61 source,
62 account_set_id,
63 member_id,
64 } => proto::cala_ledger_event::Payload::AccountSetMemberCreated(
65 proto::AccountSetMemberCreated {
66 data_source_id: source.to_string(),
67 member: Some(proto::AccountSetMember {
68 account_set_id: account_set_id.to_string(),
69 member: Some(match member_id {
70 AccountSetMemberId::Account(account_id) => {
71 proto::account_set_member::Member::MemberAccountId(
72 account_id.to_string(),
73 )
74 }
75 AccountSetMemberId::AccountSet(account_set_id) => {
76 proto::account_set_member::Member::MemberAccountSetId(
77 account_set_id.to_string(),
78 )
79 }
80 }),
81 }),
82 },
83 ),
84 OutboxEventPayload::AccountSetMemberRemoved {
85 source,
86 account_set_id,
87 member_id,
88 } => proto::cala_ledger_event::Payload::AccountSetMemberRemoved(
89 proto::AccountSetMemberRemoved {
90 data_source_id: source.to_string(),
91 member: Some(proto::AccountSetMember {
92 account_set_id: account_set_id.to_string(),
93 member: Some(match member_id {
94 AccountSetMemberId::Account(account_id) => {
95 proto::account_set_member::Member::MemberAccountId(
96 account_id.to_string(),
97 )
98 }
99 AccountSetMemberId::AccountSet(account_set_id) => {
100 proto::account_set_member::Member::MemberAccountSetId(
101 account_set_id.to_string(),
102 )
103 }
104 }),
105 }),
106 },
107 ),
108 OutboxEventPayload::JournalCreated { source, journal } => {
109 proto::cala_ledger_event::Payload::JournalCreated(proto::JournalCreated {
110 data_source_id: source.to_string(),
111 journal: Some(proto::Journal::from(journal)),
112 })
113 }
114 OutboxEventPayload::JournalUpdated {
115 source,
116 journal,
117 fields,
118 } => proto::cala_ledger_event::Payload::JournalUpdated(proto::JournalUpdated {
119 data_source_id: source.to_string(),
120 journal: Some(proto::Journal::from(journal)),
121 fields,
122 }),
123 OutboxEventPayload::TxTemplateCreated {
124 source,
125 tx_template,
126 } => proto::cala_ledger_event::Payload::TxTemplateCreated(proto::TxTemplateCreated {
127 data_source_id: source.to_string(),
128 tx_template: Some(proto::TxTemplate::from(tx_template)),
129 }),
130 OutboxEventPayload::TransactionCreated {
131 source,
132 transaction,
133 } => proto::cala_ledger_event::Payload::TransactionCreated(proto::TransactionCreated {
134 data_source_id: source.to_string(),
135 transaction: Some(proto::Transaction::from(transaction)),
136 }),
137 OutboxEventPayload::TransactionUpdated {
138 source,
139 transaction,
140 fields,
141 } => proto::cala_ledger_event::Payload::TransactionUpdated(proto::TransactionUpdated {
142 data_source_id: source.to_string(),
143 transaction: Some(proto::Transaction::from(transaction)),
144 fields,
145 }),
146 OutboxEventPayload::EntryCreated { source, entry } => {
147 proto::cala_ledger_event::Payload::EntryCreated(proto::EntryCreated {
148 data_source_id: source.to_string(),
149 entry: Some(proto::Entry::from(entry)),
150 })
151 }
152 OutboxEventPayload::BalanceCreated { source, balance } => {
153 proto::cala_ledger_event::Payload::BalanceCreated(proto::BalanceCreated {
154 data_source_id: source.to_string(),
155 balance: Some(proto::Balance::from(balance)),
156 })
157 }
158 OutboxEventPayload::BalanceUpdated { source, balance } => {
159 proto::cala_ledger_event::Payload::BalanceUpdated(proto::BalanceUpdated {
160 data_source_id: source.to_string(),
161 balance: Some(proto::Balance::from(balance)),
162 })
163 }
164 OutboxEventPayload::Empty => proto::cala_ledger_event::Payload::Empty(true),
165 };
166 proto::CalaLedgerEvent {
167 id: id.to_string(),
168 sequence: u64::from(sequence),
169 recorded_at: Some(recorded_at.into()),
170 payload: Some(payload),
171 }
172 }
173}
174
175impl From<AccountValues> for proto::Account {
176 fn from(
177 AccountValues {
178 id,
179 version,
180 code,
181 name,
182 external_id,
183 normal_balance_type,
184 status,
185 description,
186 metadata,
187 config,
188 }: AccountValues,
189 ) -> Self {
190 let normal_balance_type: proto::DebitOrCredit = normal_balance_type.into();
191 let status: proto::Status = status.into();
192 proto::Account {
193 id: id.to_string(),
194 version,
195 code,
196 name,
197 external_id,
198 normal_balance_type: normal_balance_type as i32,
199 status: status as i32,
200 description,
201 metadata: metadata.map(|json| {
202 serde_json::from_value(json).expect("Could not transfer json -> struct")
203 }),
204 config: Some(proto::AccountConfig::from(config)),
205 }
206 }
207}
208
209impl From<AccountConfig> for proto::AccountConfig {
210 fn from(config: AccountConfig) -> Self {
211 proto::AccountConfig {
212 is_account_set: config.is_account_set,
213 eventually_consistent: config.eventually_consistent,
214 }
215 }
216}
217
218impl From<AccountSetValues> for proto::AccountSet {
219 fn from(
220 AccountSetValues {
221 id,
222 version,
223 journal_id,
224 name,
225 external_id,
226 normal_balance_type,
227 description,
228 metadata,
229 }: AccountSetValues,
230 ) -> Self {
231 let normal_balance_type: proto::DebitOrCredit = normal_balance_type.into();
232 proto::AccountSet {
233 id: id.to_string(),
234 version,
235 journal_id: journal_id.to_string(),
236 name,
237 external_id,
238 normal_balance_type: normal_balance_type as i32,
239 description,
240 metadata: metadata.map(|json| {
241 serde_json::from_value(json).expect("Could not transfer json -> struct")
242 }),
243 }
244 }
245}
246
247impl From<JournalValues> for proto::Journal {
248 fn from(
249 JournalValues {
250 id,
251 version,
252 name,
253 code,
254 status,
255 description,
256 config,
257 }: JournalValues,
258 ) -> Self {
259 let status: proto::Status = status.into();
260 proto::Journal {
261 id: id.to_string(),
262 version,
263 name,
264 code,
265 status: status as i32,
266 description,
267 config: Some(proto::JournalConfig::from(config)),
268 }
269 }
270}
271
272impl From<JournalConfig> for proto::JournalConfig {
273 fn from(config: JournalConfig) -> Self {
274 proto::JournalConfig {
275 enable_effective_balances: config.enable_effective_balances,
276 }
277 }
278}
279
280impl From<DebitOrCredit> for proto::DebitOrCredit {
281 fn from(priority: DebitOrCredit) -> Self {
282 match priority {
283 DebitOrCredit::Credit => proto::DebitOrCredit::Credit,
284 DebitOrCredit::Debit => proto::DebitOrCredit::Debit,
285 }
286 }
287}
288
289impl From<Status> for proto::Status {
290 fn from(priority: Status) -> Self {
291 match priority {
292 Status::Active => proto::Status::Active,
293 Status::Locked => proto::Status::Locked,
294 }
295 }
296}
297
298impl From<TxTemplateValues> for proto::TxTemplate {
299 fn from(
300 TxTemplateValues {
301 id,
302 version,
303 code,
304 params,
305 transaction,
306 entries,
307 description,
308 metadata,
309 }: TxTemplateValues,
310 ) -> Self {
311 let params = params
312 .unwrap_or_default()
313 .into_iter()
314 .map(|param| param.into())
315 .collect();
316 proto::TxTemplate {
317 id: id.to_string(),
318 version,
319 code,
320 params,
321 transaction: Some(transaction.into()),
322 entries: entries.into_iter().map(|entry| entry.into()).collect(),
323 description,
324 metadata: metadata.map(|json| {
325 serde_json::from_value(json).expect("Could not transfer json -> struct")
326 }),
327 }
328 }
329}
330
331impl From<TxTemplateEntry> for proto::TxTemplateEntry {
332 fn from(
333 TxTemplateEntry {
334 entry_type,
335 account_id,
336 layer,
337 direction,
338 currency,
339 units,
340 description,
341 metadata,
342 }: TxTemplateEntry,
343 ) -> Self {
344 proto::TxTemplateEntry {
345 entry_type: String::from(entry_type),
346 account_id: String::from(account_id),
347 layer: String::from(layer),
348 direction: String::from(direction),
349 currency: String::from(currency),
350 units: String::from(units),
351 description: description.map(String::from),
352 metadata: metadata.map(String::from),
353 }
354 }
355}
356
357impl From<ParamDefinition> for proto::ParamDefinition {
358 fn from(
359 ParamDefinition {
360 name,
361 r#type,
362 default,
363 description,
364 }: ParamDefinition,
365 ) -> Self {
366 let data_type: proto::ParamDataType = r#type.into();
367 proto::ParamDefinition {
368 name,
369 data_type: data_type as i32,
370 default: default.map(String::from),
371 description,
372 }
373 }
374}
375
376impl From<ParamDataType> for proto::ParamDataType {
377 fn from(param_data_type: ParamDataType) -> Self {
378 match param_data_type {
379 ParamDataType::String => proto::ParamDataType::String,
380 ParamDataType::Integer => proto::ParamDataType::Integer,
381 ParamDataType::Decimal => proto::ParamDataType::Decimal,
382 ParamDataType::Boolean => proto::ParamDataType::Boolean,
383 ParamDataType::Uuid => proto::ParamDataType::Uuid,
384 ParamDataType::Date => proto::ParamDataType::Date,
385 ParamDataType::Timestamp => proto::ParamDataType::Timestamp,
386 ParamDataType::Json => proto::ParamDataType::Json,
387 }
388 }
389}
390
391impl From<TxTemplateTransaction> for proto::TxTemplateTransaction {
392 fn from(
393 TxTemplateTransaction {
394 effective,
395 journal_id,
396 correlation_id,
397 external_id,
398 description,
399 metadata,
400 }: TxTemplateTransaction,
401 ) -> Self {
402 proto::TxTemplateTransaction {
403 effective: String::from(effective),
404 journal_id: String::from(journal_id),
405 correlation_id: correlation_id.map(String::from),
406 external_id: external_id.map(String::from),
407 description: description.map(String::from),
408 metadata: metadata.map(String::from),
409 }
410 }
411}
412
413impl From<TransactionValues> for proto::Transaction {
414 fn from(
415 TransactionValues {
416 id,
417 version,
418 created_at,
419 modified_at,
420 journal_id,
421 tx_template_id,
422 correlation_id,
423 external_id,
424 effective,
425 description,
426 metadata,
427 entry_ids,
428 voided_by,
429 void_of,
430 }: TransactionValues,
431 ) -> Self {
432 proto::Transaction {
433 id: id.to_string(),
434 version,
435 created_at: Some(created_at.into()),
436 modified_at: Some(modified_at.into()),
437 journal_id: journal_id.to_string(),
438 tx_template_id: tx_template_id.to_string(),
439 entry_ids: entry_ids.into_iter().map(|id| id.to_string()).collect(),
440 correlation_id,
441 external_id,
442 void_of: void_of.map(|id| id.to_string()),
443 voided_by: voided_by.map(|id| id.to_string()),
444 effective: effective.to_string(),
445 description,
446 metadata: metadata.map(|json| {
447 serde_json::from_value(json).expect("Could not transfer json -> struct")
448 }),
449 }
450 }
451}
452
453impl From<EntryValues> for proto::Entry {
454 fn from(
455 EntryValues {
456 id,
457 version,
458 journal_id,
459 transaction_id,
460 account_id,
461 entry_type,
462 sequence,
463 layer,
464 direction,
465 currency,
466 units,
467 description,
468 metadata,
469 }: EntryValues,
470 ) -> Self {
471 let layer: proto::Layer = layer.into();
472 let direction: proto::DebitOrCredit = direction.into();
473 let units = units.to_f64().expect("could not convert units to f64");
474 proto::Entry {
475 id: id.to_string(),
476 version,
477 journal_id: journal_id.to_string(),
478 transaction_id: transaction_id.to_string(),
479 account_id: account_id.to_string(),
480 entry_type: entry_type.to_string(),
481 sequence,
482 layer: layer.into(),
483 direction: direction.into(),
484 currency: currency.to_string(),
485 units: units.to_string(),
486 description,
487 metadata: metadata.map(|json| {
488 serde_json::from_value(json).expect("Could not transfer json -> struct")
489 }),
490 }
491 }
492}
493
494impl From<BalanceSnapshot> for proto::Balance {
495 fn from(
496 BalanceSnapshot {
497 journal_id,
498 account_id,
499 currency,
500 version,
501 created_at,
502 modified_at,
503 entry_id,
504 settled,
505 pending,
506 encumbrance,
507 }: BalanceSnapshot,
508 ) -> Self {
509 proto::Balance {
510 journal_id: journal_id.to_string(),
511 account_id: account_id.to_string(),
512 currency: currency.to_string(),
513 version,
514 created_at: Some(created_at.into()),
515 modified_at: Some(modified_at.into()),
516 entry_id: entry_id.to_string(),
517 settled: Some(proto::BalanceAmount::from(settled)),
518 pending: Some(proto::BalanceAmount::from(pending)),
519 encumbrance: Some(proto::BalanceAmount::from(encumbrance)),
520 }
521 }
522}
523
524impl From<BalanceAmount> for proto::BalanceAmount {
525 fn from(
526 BalanceAmount {
527 dr_balance,
528 cr_balance,
529 entry_id,
530 modified_at,
531 }: BalanceAmount,
532 ) -> Self {
533 proto::BalanceAmount {
534 dr_balance: dr_balance.to_string(),
535 cr_balance: cr_balance.to_string(),
536 entry_id: entry_id.to_string(),
537 modified_at: Some(modified_at.into()),
538 }
539 }
540}
541
542impl From<Layer> for proto::Layer {
543 fn from(layer: Layer) -> Self {
544 match layer {
545 Layer::Settled => proto::Layer::Settled,
546 Layer::Pending => proto::Layer::Pending,
547 Layer::Encumbrance => proto::Layer::Encumbrance,
548 }
549 }
550}