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}