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}