cala_ledger/outbox/server/
convert.rs

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}