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            metadata,
323        }: TxTemplateEntry,
324    ) -> Self {
325        proto::TxTemplateEntry {
326            entry_type: String::from(entry_type),
327            account_id: String::from(account_id),
328            layer: String::from(layer),
329            direction: String::from(direction),
330            currency: String::from(currency),
331            units: String::from(units),
332            description: description.map(String::from),
333            metadata: metadata.map(String::from),
334        }
335    }
336}
337
338impl From<ParamDefinition> for proto::ParamDefinition {
339    fn from(
340        ParamDefinition {
341            name,
342            r#type,
343            default,
344            description,
345        }: ParamDefinition,
346    ) -> Self {
347        let data_type: proto::ParamDataType = r#type.into();
348        proto::ParamDefinition {
349            name,
350            data_type: data_type as i32,
351            default: default.map(String::from),
352            description,
353        }
354    }
355}
356
357impl From<ParamDataType> for proto::ParamDataType {
358    fn from(param_data_type: ParamDataType) -> Self {
359        match param_data_type {
360            ParamDataType::String => proto::ParamDataType::String,
361            ParamDataType::Integer => proto::ParamDataType::Integer,
362            ParamDataType::Decimal => proto::ParamDataType::Decimal,
363            ParamDataType::Boolean => proto::ParamDataType::Boolean,
364            ParamDataType::Uuid => proto::ParamDataType::Uuid,
365            ParamDataType::Date => proto::ParamDataType::Date,
366            ParamDataType::Timestamp => proto::ParamDataType::Timestamp,
367            ParamDataType::Json => proto::ParamDataType::Json,
368        }
369    }
370}
371
372impl From<TxTemplateTransaction> for proto::TxTemplateTransaction {
373    fn from(
374        TxTemplateTransaction {
375            effective,
376            journal_id,
377            correlation_id,
378            external_id,
379            description,
380            metadata,
381        }: TxTemplateTransaction,
382    ) -> Self {
383        proto::TxTemplateTransaction {
384            effective: String::from(effective),
385            journal_id: String::from(journal_id),
386            correlation_id: correlation_id.map(String::from),
387            external_id: external_id.map(String::from),
388            description: description.map(String::from),
389            metadata: metadata.map(String::from),
390        }
391    }
392}
393
394impl From<TransactionValues> for proto::Transaction {
395    fn from(
396        TransactionValues {
397            id,
398            version,
399            created_at,
400            modified_at,
401            journal_id,
402            tx_template_id,
403            correlation_id,
404            external_id,
405            effective,
406            description,
407            metadata,
408            entry_ids,
409        }: TransactionValues,
410    ) -> Self {
411        proto::Transaction {
412            id: id.to_string(),
413            version,
414            created_at: Some(created_at.into()),
415            modified_at: Some(modified_at.into()),
416            journal_id: journal_id.to_string(),
417            tx_template_id: tx_template_id.to_string(),
418            entry_ids: entry_ids.into_iter().map(|id| id.to_string()).collect(),
419            correlation_id,
420            external_id,
421            effective: effective.to_string(),
422            description: description.map(String::from),
423            metadata: metadata.map(|json| {
424                serde_json::from_value(json).expect("Could not transfer json -> struct")
425            }),
426        }
427    }
428}
429
430impl From<EntryValues> for proto::Entry {
431    fn from(
432        EntryValues {
433            id,
434            version,
435            journal_id,
436            transaction_id,
437            account_id,
438            entry_type,
439            sequence,
440            layer,
441            direction,
442            currency,
443            units,
444            description,
445            metadata,
446        }: EntryValues,
447    ) -> Self {
448        let layer: proto::Layer = layer.into();
449        let direction: proto::DebitOrCredit = direction.into();
450        let units = units.to_f64().expect("could not convert units to f64");
451        proto::Entry {
452            id: id.to_string(),
453            version,
454            journal_id: journal_id.to_string(),
455            transaction_id: transaction_id.to_string(),
456            account_id: account_id.to_string(),
457            entry_type: entry_type.to_string(),
458            sequence,
459            layer: layer.into(),
460            direction: direction.into(),
461            currency: currency.to_string(),
462            units: units.to_string(),
463            description: description.map(String::from),
464            metadata: metadata.map(|json| {
465                serde_json::from_value(json).expect("Could not transfer json -> struct")
466            }),
467        }
468    }
469}
470
471impl From<BalanceSnapshot> for proto::Balance {
472    fn from(
473        BalanceSnapshot {
474            journal_id,
475            account_id,
476            currency,
477            version,
478            created_at,
479            modified_at,
480            entry_id,
481            settled,
482            pending,
483            encumbrance,
484        }: BalanceSnapshot,
485    ) -> Self {
486        proto::Balance {
487            journal_id: journal_id.to_string(),
488            account_id: account_id.to_string(),
489            currency: currency.to_string(),
490            version,
491            created_at: Some(created_at.into()),
492            modified_at: Some(modified_at.into()),
493            entry_id: entry_id.to_string(),
494            settled: Some(proto::BalanceAmount::from(settled)),
495            pending: Some(proto::BalanceAmount::from(pending)),
496            encumbrance: Some(proto::BalanceAmount::from(encumbrance)),
497        }
498    }
499}
500
501impl From<BalanceAmount> for proto::BalanceAmount {
502    fn from(
503        BalanceAmount {
504            dr_balance,
505            cr_balance,
506            entry_id,
507            modified_at,
508        }: BalanceAmount,
509    ) -> Self {
510        proto::BalanceAmount {
511            dr_balance: dr_balance.to_string(),
512            cr_balance: cr_balance.to_string(),
513            entry_id: entry_id.to_string(),
514            modified_at: Some(modified_at.into()),
515        }
516    }
517}
518
519impl From<Layer> for proto::Layer {
520    fn from(layer: Layer) -> Self {
521        match layer {
522            Layer::Settled => proto::Layer::Settled,
523            Layer::Pending => proto::Layer::Pending,
524            Layer::Encumbrance => proto::Layer::Encumbrance,
525        }
526    }
527}