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}