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::JournalValues,
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        }: JournalValues,
248    ) -> Self {
249        let status: proto::Status = status.into();
250        proto::Journal {
251            id: id.to_string(),
252            version,
253            name,
254            code,
255            status: status as i32,
256            description,
257        }
258    }
259}
260
261impl From<DebitOrCredit> for proto::DebitOrCredit {
262    fn from(priority: DebitOrCredit) -> Self {
263        match priority {
264            DebitOrCredit::Credit => proto::DebitOrCredit::Credit,
265            DebitOrCredit::Debit => proto::DebitOrCredit::Debit,
266        }
267    }
268}
269
270impl From<Status> for proto::Status {
271    fn from(priority: Status) -> Self {
272        match priority {
273            Status::Active => proto::Status::Active,
274            Status::Locked => proto::Status::Locked,
275        }
276    }
277}
278
279impl From<TxTemplateValues> for proto::TxTemplate {
280    fn from(
281        TxTemplateValues {
282            id,
283            version,
284            code,
285            params,
286            transaction,
287            entries,
288            description,
289            metadata,
290        }: TxTemplateValues,
291    ) -> Self {
292        let params = params
293            .unwrap_or_default()
294            .into_iter()
295            .map(|param| param.into())
296            .collect();
297        proto::TxTemplate {
298            id: id.to_string(),
299            version,
300            code,
301            params,
302            transaction: Some(transaction.into()),
303            entries: entries.into_iter().map(|entry| entry.into()).collect(),
304            description,
305            metadata: metadata.map(|json| {
306                serde_json::from_value(json).expect("Could not transfer json -> struct")
307            }),
308        }
309    }
310}
311
312impl From<TxTemplateEntry> for proto::TxTemplateEntry {
313    fn from(
314        TxTemplateEntry {
315            entry_type,
316            account_id,
317            layer,
318            direction,
319            currency,
320            units,
321            description,
322        }: TxTemplateEntry,
323    ) -> Self {
324        proto::TxTemplateEntry {
325            entry_type: String::from(entry_type),
326            account_id: String::from(account_id),
327            layer: String::from(layer),
328            direction: String::from(direction),
329            currency: String::from(currency),
330            units: String::from(units),
331            description: description.map(String::from),
332        }
333    }
334}
335
336impl From<ParamDefinition> for proto::ParamDefinition {
337    fn from(
338        ParamDefinition {
339            name,
340            r#type,
341            default,
342            description,
343        }: ParamDefinition,
344    ) -> Self {
345        let data_type: proto::ParamDataType = r#type.into();
346        proto::ParamDefinition {
347            name,
348            data_type: data_type as i32,
349            default: default.map(String::from),
350            description,
351        }
352    }
353}
354
355impl From<ParamDataType> for proto::ParamDataType {
356    fn from(param_data_type: ParamDataType) -> Self {
357        match param_data_type {
358            ParamDataType::String => proto::ParamDataType::String,
359            ParamDataType::Integer => proto::ParamDataType::Integer,
360            ParamDataType::Decimal => proto::ParamDataType::Decimal,
361            ParamDataType::Boolean => proto::ParamDataType::Boolean,
362            ParamDataType::Uuid => proto::ParamDataType::Uuid,
363            ParamDataType::Date => proto::ParamDataType::Date,
364            ParamDataType::Timestamp => proto::ParamDataType::Timestamp,
365            ParamDataType::Json => proto::ParamDataType::Json,
366        }
367    }
368}
369
370impl From<TxTemplateTransaction> for proto::TxTemplateTransaction {
371    fn from(
372        TxTemplateTransaction {
373            effective,
374            journal_id,
375            correlation_id,
376            external_id,
377            description,
378            metadata,
379        }: TxTemplateTransaction,
380    ) -> Self {
381        proto::TxTemplateTransaction {
382            effective: String::from(effective),
383            journal_id: String::from(journal_id),
384            correlation_id: correlation_id.map(String::from),
385            external_id: external_id.map(String::from),
386            description: description.map(String::from),
387            metadata: metadata.map(String::from),
388        }
389    }
390}
391
392impl From<TransactionValues> for proto::Transaction {
393    fn from(
394        TransactionValues {
395            id,
396            version,
397            created_at,
398            modified_at,
399            journal_id,
400            tx_template_id,
401            correlation_id,
402            external_id,
403            effective,
404            description,
405            metadata,
406            entry_ids,
407        }: TransactionValues,
408    ) -> Self {
409        proto::Transaction {
410            id: id.to_string(),
411            version,
412            created_at: Some(created_at.into()),
413            modified_at: Some(modified_at.into()),
414            journal_id: journal_id.to_string(),
415            tx_template_id: tx_template_id.to_string(),
416            entry_ids: entry_ids.into_iter().map(|id| id.to_string()).collect(),
417            correlation_id,
418            external_id,
419            effective: effective.to_string(),
420            description: description.map(String::from),
421            metadata: metadata.map(|json| {
422                serde_json::from_value(json).expect("Could not transfer json -> struct")
423            }),
424        }
425    }
426}
427
428impl From<EntryValues> for proto::Entry {
429    fn from(
430        EntryValues {
431            id,
432            version,
433            journal_id,
434            transaction_id,
435            account_id,
436            entry_type,
437            sequence,
438            layer,
439            direction,
440            currency,
441            units,
442            description,
443        }: EntryValues,
444    ) -> Self {
445        let layer: proto::Layer = layer.into();
446        let direction: proto::DebitOrCredit = direction.into();
447        let units = units.to_f64().expect("could not convert units to f64");
448        proto::Entry {
449            id: id.to_string(),
450            version,
451            journal_id: journal_id.to_string(),
452            transaction_id: transaction_id.to_string(),
453            account_id: account_id.to_string(),
454            entry_type: entry_type.to_string(),
455            sequence,
456            layer: layer.into(),
457            direction: direction.into(),
458            currency: currency.to_string(),
459            units: units.to_string(),
460            description: description.map(String::from),
461        }
462    }
463}
464
465impl From<BalanceSnapshot> for proto::Balance {
466    fn from(
467        BalanceSnapshot {
468            journal_id,
469            account_id,
470            currency,
471            version,
472            created_at,
473            modified_at,
474            entry_id,
475            settled,
476            pending,
477            encumbrance,
478        }: BalanceSnapshot,
479    ) -> Self {
480        proto::Balance {
481            journal_id: journal_id.to_string(),
482            account_id: account_id.to_string(),
483            currency: currency.to_string(),
484            version,
485            created_at: Some(created_at.into()),
486            modified_at: Some(modified_at.into()),
487            entry_id: entry_id.to_string(),
488            settled: Some(proto::BalanceAmount::from(settled)),
489            pending: Some(proto::BalanceAmount::from(pending)),
490            encumbrance: Some(proto::BalanceAmount::from(encumbrance)),
491        }
492    }
493}
494
495impl From<BalanceAmount> for proto::BalanceAmount {
496    fn from(
497        BalanceAmount {
498            dr_balance,
499            cr_balance,
500            entry_id,
501            modified_at,
502        }: BalanceAmount,
503    ) -> Self {
504        proto::BalanceAmount {
505            dr_balance: dr_balance.to_string(),
506            cr_balance: cr_balance.to_string(),
507            entry_id: entry_id.to_string(),
508            modified_at: Some(modified_at.into()),
509        }
510    }
511}
512
513impl From<Layer> for proto::Layer {
514    fn from(layer: Layer) -> Self {
515        match layer {
516            Layer::Settled => proto::Layer::Settled,
517            Layer::Pending => proto::Layer::Pending,
518            Layer::Encumbrance => proto::Layer::Encumbrance,
519        }
520    }
521}