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