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}