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::EntryCreated { source, entry } => {
138                proto::cala_ledger_event::Payload::EntryCreated(proto::EntryCreated {
139                    data_source_id: source.to_string(),
140                    entry: Some(proto::Entry::from(entry)),
141                })
142            }
143            OutboxEventPayload::BalanceCreated { source, balance } => {
144                proto::cala_ledger_event::Payload::BalanceCreated(proto::BalanceCreated {
145                    data_source_id: source.to_string(),
146                    balance: Some(proto::Balance::from(balance)),
147                })
148            }
149            OutboxEventPayload::BalanceUpdated { source, balance } => {
150                proto::cala_ledger_event::Payload::BalanceUpdated(proto::BalanceUpdated {
151                    data_source_id: source.to_string(),
152                    balance: Some(proto::Balance::from(balance)),
153                })
154            }
155            OutboxEventPayload::Empty => proto::cala_ledger_event::Payload::Empty(true),
156        };
157        proto::CalaLedgerEvent {
158            id: id.to_string(),
159            sequence: u64::from(sequence),
160            recorded_at: Some(recorded_at.into()),
161            payload: Some(payload),
162        }
163    }
164}
165
166impl From<AccountValues> for proto::Account {
167    fn from(
168        AccountValues {
169            id,
170            version,
171            code,
172            name,
173            external_id,
174            normal_balance_type,
175            status,
176            description,
177            metadata,
178            config,
179        }: AccountValues,
180    ) -> Self {
181        let normal_balance_type: proto::DebitOrCredit = normal_balance_type.into();
182        let status: proto::Status = status.into();
183        proto::Account {
184            id: id.to_string(),
185            version,
186            code,
187            name,
188            external_id,
189            normal_balance_type: normal_balance_type as i32,
190            status: status as i32,
191            description,
192            metadata: metadata.map(|json| {
193                serde_json::from_value(json).expect("Could not transfer json -> struct")
194            }),
195            config: Some(proto::AccountConfig::from(config)),
196        }
197    }
198}
199
200impl From<AccountConfig> for proto::AccountConfig {
201    fn from(config: AccountConfig) -> Self {
202        proto::AccountConfig {
203            is_account_set: config.is_account_set,
204            eventually_consistent: config.eventually_consistent,
205        }
206    }
207}
208
209impl From<AccountSetValues> for proto::AccountSet {
210    fn from(
211        AccountSetValues {
212            id,
213            version,
214            journal_id,
215            name,
216            external_id,
217            normal_balance_type,
218            description,
219            metadata,
220        }: AccountSetValues,
221    ) -> Self {
222        let normal_balance_type: proto::DebitOrCredit = normal_balance_type.into();
223        proto::AccountSet {
224            id: id.to_string(),
225            version,
226            journal_id: journal_id.to_string(),
227            name,
228            external_id,
229            normal_balance_type: normal_balance_type as i32,
230            description,
231            metadata: metadata.map(|json| {
232                serde_json::from_value(json).expect("Could not transfer json -> struct")
233            }),
234        }
235    }
236}
237
238impl From<JournalValues> for proto::Journal {
239    fn from(
240        JournalValues {
241            id,
242            version,
243            name,
244            code,
245            status,
246            description,
247            config,
248        }: JournalValues,
249    ) -> Self {
250        let status: proto::Status = status.into();
251        proto::Journal {
252            id: id.to_string(),
253            version,
254            name,
255            code,
256            status: status as i32,
257            description,
258            config: Some(proto::JournalConfig::from(config)),
259        }
260    }
261}
262
263impl From<JournalConfig> for proto::JournalConfig {
264    fn from(config: JournalConfig) -> Self {
265        proto::JournalConfig {
266            enable_effective_balances: config.enable_effective_balances,
267        }
268    }
269}
270
271impl From<DebitOrCredit> for proto::DebitOrCredit {
272    fn from(priority: DebitOrCredit) -> Self {
273        match priority {
274            DebitOrCredit::Credit => proto::DebitOrCredit::Credit,
275            DebitOrCredit::Debit => proto::DebitOrCredit::Debit,
276        }
277    }
278}
279
280impl From<Status> for proto::Status {
281    fn from(priority: Status) -> Self {
282        match priority {
283            Status::Active => proto::Status::Active,
284            Status::Locked => proto::Status::Locked,
285        }
286    }
287}
288
289impl From<TxTemplateValues> for proto::TxTemplate {
290    fn from(
291        TxTemplateValues {
292            id,
293            version,
294            code,
295            params,
296            transaction,
297            entries,
298            description,
299            metadata,
300        }: TxTemplateValues,
301    ) -> Self {
302        let params = params
303            .unwrap_or_default()
304            .into_iter()
305            .map(|param| param.into())
306            .collect();
307        proto::TxTemplate {
308            id: id.to_string(),
309            version,
310            code,
311            params,
312            transaction: Some(transaction.into()),
313            entries: entries.into_iter().map(|entry| entry.into()).collect(),
314            description,
315            metadata: metadata.map(|json| {
316                serde_json::from_value(json).expect("Could not transfer json -> struct")
317            }),
318        }
319    }
320}
321
322impl From<TxTemplateEntry> for proto::TxTemplateEntry {
323    fn from(
324        TxTemplateEntry {
325            entry_type,
326            account_id,
327            layer,
328            direction,
329            currency,
330            units,
331            description,
332            metadata,
333        }: TxTemplateEntry,
334    ) -> Self {
335        proto::TxTemplateEntry {
336            entry_type: String::from(entry_type),
337            account_id: String::from(account_id),
338            layer: String::from(layer),
339            direction: String::from(direction),
340            currency: String::from(currency),
341            units: String::from(units),
342            description: description.map(String::from),
343            metadata: metadata.map(String::from),
344        }
345    }
346}
347
348impl From<ParamDefinition> for proto::ParamDefinition {
349    fn from(
350        ParamDefinition {
351            name,
352            r#type,
353            default,
354            description,
355        }: ParamDefinition,
356    ) -> Self {
357        let data_type: proto::ParamDataType = r#type.into();
358        proto::ParamDefinition {
359            name,
360            data_type: data_type as i32,
361            default: default.map(String::from),
362            description,
363        }
364    }
365}
366
367impl From<ParamDataType> for proto::ParamDataType {
368    fn from(param_data_type: ParamDataType) -> Self {
369        match param_data_type {
370            ParamDataType::String => proto::ParamDataType::String,
371            ParamDataType::Integer => proto::ParamDataType::Integer,
372            ParamDataType::Decimal => proto::ParamDataType::Decimal,
373            ParamDataType::Boolean => proto::ParamDataType::Boolean,
374            ParamDataType::Uuid => proto::ParamDataType::Uuid,
375            ParamDataType::Date => proto::ParamDataType::Date,
376            ParamDataType::Timestamp => proto::ParamDataType::Timestamp,
377            ParamDataType::Json => proto::ParamDataType::Json,
378        }
379    }
380}
381
382impl From<TxTemplateTransaction> for proto::TxTemplateTransaction {
383    fn from(
384        TxTemplateTransaction {
385            effective,
386            journal_id,
387            correlation_id,
388            external_id,
389            description,
390            metadata,
391        }: TxTemplateTransaction,
392    ) -> Self {
393        proto::TxTemplateTransaction {
394            effective: String::from(effective),
395            journal_id: String::from(journal_id),
396            correlation_id: correlation_id.map(String::from),
397            external_id: external_id.map(String::from),
398            description: description.map(String::from),
399            metadata: metadata.map(String::from),
400        }
401    }
402}
403
404impl From<TransactionValues> for proto::Transaction {
405    fn from(
406        TransactionValues {
407            id,
408            version,
409            created_at,
410            modified_at,
411            journal_id,
412            tx_template_id,
413            correlation_id,
414            external_id,
415            effective,
416            description,
417            metadata,
418            entry_ids,
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            effective: effective.to_string(),
432            description,
433            metadata: metadata.map(|json| {
434                serde_json::from_value(json).expect("Could not transfer json -> struct")
435            }),
436        }
437    }
438}
439
440impl From<EntryValues> for proto::Entry {
441    fn from(
442        EntryValues {
443            id,
444            version,
445            journal_id,
446            transaction_id,
447            account_id,
448            entry_type,
449            sequence,
450            layer,
451            direction,
452            currency,
453            units,
454            description,
455            metadata,
456        }: EntryValues,
457    ) -> Self {
458        let layer: proto::Layer = layer.into();
459        let direction: proto::DebitOrCredit = direction.into();
460        let units = units.to_f64().expect("could not convert units to f64");
461        proto::Entry {
462            id: id.to_string(),
463            version,
464            journal_id: journal_id.to_string(),
465            transaction_id: transaction_id.to_string(),
466            account_id: account_id.to_string(),
467            entry_type: entry_type.to_string(),
468            sequence,
469            layer: layer.into(),
470            direction: direction.into(),
471            currency: currency.to_string(),
472            units: units.to_string(),
473            description,
474            metadata: metadata.map(|json| {
475                serde_json::from_value(json).expect("Could not transfer json -> struct")
476            }),
477        }
478    }
479}
480
481impl From<BalanceSnapshot> for proto::Balance {
482    fn from(
483        BalanceSnapshot {
484            journal_id,
485            account_id,
486            currency,
487            version,
488            created_at,
489            modified_at,
490            entry_id,
491            settled,
492            pending,
493            encumbrance,
494        }: BalanceSnapshot,
495    ) -> Self {
496        proto::Balance {
497            journal_id: journal_id.to_string(),
498            account_id: account_id.to_string(),
499            currency: currency.to_string(),
500            version,
501            created_at: Some(created_at.into()),
502            modified_at: Some(modified_at.into()),
503            entry_id: entry_id.to_string(),
504            settled: Some(proto::BalanceAmount::from(settled)),
505            pending: Some(proto::BalanceAmount::from(pending)),
506            encumbrance: Some(proto::BalanceAmount::from(encumbrance)),
507        }
508    }
509}
510
511impl From<BalanceAmount> for proto::BalanceAmount {
512    fn from(
513        BalanceAmount {
514            dr_balance,
515            cr_balance,
516            entry_id,
517            modified_at,
518        }: BalanceAmount,
519    ) -> Self {
520        proto::BalanceAmount {
521            dr_balance: dr_balance.to_string(),
522            cr_balance: cr_balance.to_string(),
523            entry_id: entry_id.to_string(),
524            modified_at: Some(modified_at.into()),
525        }
526    }
527}
528
529impl From<Layer> for proto::Layer {
530    fn from(layer: Layer) -> Self {
531        match layer {
532            Layer::Settled => proto::Layer::Settled,
533            Layer::Pending => proto::Layer::Pending,
534            Layer::Encumbrance => proto::Layer::Encumbrance,
535        }
536    }
537}