1use std::str::FromStr;
17
18use indexmap::IndexMap;
19use nautilus_core::{UUID4, UnixNanos};
20use nautilus_model::{
21 enums::{
22 ContingencyType, LiquiditySide, OrderSide, OrderStatus, OrderType, TimeInForce, TriggerType,
23 },
24 events::{
25 OrderAccepted, OrderCancelRejected, OrderCanceled, OrderDenied, OrderEmulated,
26 OrderEventAny, OrderExpired, OrderFilled, OrderInitialized, OrderModifyRejected,
27 OrderPendingCancel, OrderPendingUpdate, OrderRejected, OrderReleased, OrderSnapshot,
28 OrderSubmitted, OrderTriggered, OrderUpdated,
29 },
30 identifiers::{
31 AccountId, ClientOrderId, ExecAlgorithmId, InstrumentId, OrderListId, PositionId,
32 StrategyId, TradeId, TraderId, VenueOrderId,
33 },
34 types::{Currency, Money, Price, Quantity},
35};
36use rust_decimal::Decimal;
37use sqlx::{FromRow, Row, postgres::PgRow};
38use ustr::Ustr;
39
40use crate::sql::models::enums::TrailingOffsetTypeModel;
41
42pub struct OrderEventAnyModel(pub OrderEventAny);
43pub struct OrderAcceptedModel(pub OrderAccepted);
44pub struct OrderCancelRejectedModel(pub OrderCancelRejected);
45pub struct OrderCanceledModel(pub OrderCanceled);
46pub struct OrderDeniedModel(pub OrderDenied);
47pub struct OrderEmulatedModel(pub OrderEmulated);
48pub struct OrderExpiredModel(pub OrderExpired);
49pub struct OrderFilledModel(pub OrderFilled);
50pub struct OrderInitializedModel(pub OrderInitialized);
51pub struct OrderModifyRejectedModel(pub OrderModifyRejected);
52pub struct OrderPendingCancelModel(pub OrderPendingCancel);
53pub struct OrderPendingUpdateModel(pub OrderPendingUpdate);
54pub struct OrderRejectedModel(pub OrderRejected);
55pub struct OrderReleasedModel(pub OrderReleased);
56pub struct OrderSubmittedModel(pub OrderSubmitted);
57pub struct OrderTriggeredModel(pub OrderTriggered);
58pub struct OrderUpdatedModel(pub OrderUpdated);
59pub struct OrderSnapshotModel(pub OrderSnapshot);
60
61impl<'r> FromRow<'r, PgRow> for OrderEventAnyModel {
62 fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
63 let kind = row.get::<String, _>("kind");
64 if kind == "OrderAccepted" {
65 let model = OrderAcceptedModel::from_row(row)?;
66 Ok(OrderEventAnyModel(OrderEventAny::Accepted(model.0)))
67 } else if kind == "OrderCancelRejected" {
68 let model = OrderCancelRejectedModel::from_row(row)?;
69 Ok(OrderEventAnyModel(OrderEventAny::CancelRejected(model.0)))
70 } else if kind == "OrderCanceled" {
71 let model = OrderCanceledModel::from_row(row)?;
72 Ok(OrderEventAnyModel(OrderEventAny::Canceled(model.0)))
73 } else if kind == "OrderDenied" {
74 let model = OrderDeniedModel::from_row(row)?;
75 Ok(OrderEventAnyModel(OrderEventAny::Denied(model.0)))
76 } else if kind == "OrderEmulated" {
77 let model = OrderEmulatedModel::from_row(row)?;
78 Ok(OrderEventAnyModel(OrderEventAny::Emulated(model.0)))
79 } else if kind == "OrderExpired" {
80 let model = OrderExpiredModel::from_row(row)?;
81 Ok(OrderEventAnyModel(OrderEventAny::Expired(model.0)))
82 } else if kind == "OrderFilled" {
83 let model = OrderFilledModel::from_row(row)?;
84 Ok(OrderEventAnyModel(OrderEventAny::Filled(model.0)))
85 } else if kind == "OrderInitialized" {
86 let model = OrderInitializedModel::from_row(row)?;
87 Ok(OrderEventAnyModel(OrderEventAny::Initialized(model.0)))
88 } else if kind == "OrderModifyRejected" {
89 let model = OrderModifyRejectedModel::from_row(row)?;
90 Ok(OrderEventAnyModel(OrderEventAny::ModifyRejected(model.0)))
91 } else if kind == "OrderPendingCancel" {
92 let model = OrderPendingCancelModel::from_row(row)?;
93 Ok(OrderEventAnyModel(OrderEventAny::PendingCancel(model.0)))
94 } else if kind == "OrderPendingUpdate" {
95 let model = OrderPendingUpdateModel::from_row(row)?;
96 Ok(OrderEventAnyModel(OrderEventAny::PendingUpdate(model.0)))
97 } else if kind == "OrderRejected" {
98 let model = OrderRejectedModel::from_row(row)?;
99 Ok(OrderEventAnyModel(OrderEventAny::Rejected(model.0)))
100 } else if kind == "OrderReleased" {
101 let model = OrderReleasedModel::from_row(row)?;
102 Ok(OrderEventAnyModel(OrderEventAny::Released(model.0)))
103 } else if kind == "OrderSubmitted" {
104 let model = OrderSubmittedModel::from_row(row)?;
105 Ok(OrderEventAnyModel(OrderEventAny::Submitted(model.0)))
106 } else if kind == "OrderTriggered" {
107 let model = OrderTriggeredModel::from_row(row)?;
108 Ok(OrderEventAnyModel(OrderEventAny::Triggered(model.0)))
109 } else if kind == "OrderUpdated" {
110 let model = OrderUpdatedModel::from_row(row)?;
111 Ok(OrderEventAnyModel(OrderEventAny::Updated(model.0)))
112 } else {
113 panic!("Unknown order event kind: {kind} in Postgres transformation",)
114 }
115 }
116}
117
118impl<'r> FromRow<'r, PgRow> for OrderInitializedModel {
119 fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
120 let event_id = row.try_get::<&str, _>("id").map(UUID4::from)?;
121 let client_order_id = row
122 .try_get::<&str, _>("client_order_id")
123 .map(ClientOrderId::from)?;
124 let trader_id = row.try_get::<&str, _>("trader_id").map(TraderId::from)?;
125 let strategy_id = row
126 .try_get::<&str, _>("strategy_id")
127 .map(StrategyId::from)?;
128 let instrument_id = row
129 .try_get::<&str, _>("instrument_id")
130 .map(InstrumentId::from)?;
131 let order_type = row
132 .try_get::<&str, _>("order_type")
133 .map(|x| OrderType::from_str(x).unwrap())?;
134 let order_side = row
135 .try_get::<&str, _>("order_side")
136 .map(|x| OrderSide::from_str(x).unwrap())?;
137 let quantity = row.try_get::<&str, _>("quantity").map(Quantity::from)?;
138 let time_in_force = row
139 .try_get::<&str, _>("time_in_force")
140 .map(|x| TimeInForce::from_str(x).unwrap())?;
141 let post_only = row.try_get::<bool, _>("post_only")?;
142 let reduce_only = row.try_get::<bool, _>("reduce_only")?;
143 let quote_quantity = row.try_get::<bool, _>("quote_quantity")?;
144 let reconciliation = row.try_get::<bool, _>("reconciliation")?;
145 let ts_event = row.try_get::<String, _>("ts_event").map(UnixNanos::from)?;
146 let ts_init = row.try_get::<String, _>("ts_init").map(UnixNanos::from)?;
147 let price = row
148 .try_get::<Option<&str>, _>("price")
149 .ok()
150 .and_then(|x| x.map(Price::from));
151 let trigger_price = row
152 .try_get::<Option<&str>, _>("trigger_price")
153 .ok()
154 .and_then(|x| x.map(Price::from));
155 let trigger_type = row
156 .try_get::<Option<&str>, _>("trigger_type")
157 .ok()
158 .and_then(|x| x.map(|x| TriggerType::from_str(x).unwrap()));
159 let limit_offset = row
160 .try_get::<Option<&str>, _>("limit_offset")
161 .ok()
162 .and_then(|x| x.and_then(|s| Decimal::from_str(s).ok()));
163 let trailing_offset = row
164 .try_get::<Option<&str>, _>("trailing_offset")
165 .ok()
166 .and_then(|x| x.and_then(|s| Decimal::from_str(s).ok()));
167 let trailing_offset_type = row
168 .try_get::<Option<TrailingOffsetTypeModel>, _>("trailing_offset_type")
169 .ok()
170 .and_then(|x| x.map(|x| x.0));
171 let expire_time = row
172 .try_get::<Option<&str>, _>("expire_time")
173 .ok()
174 .and_then(|x| x.map(UnixNanos::from));
175 let display_qty = row
176 .try_get::<Option<&str>, _>("display_qty")
177 .ok()
178 .and_then(|x| x.map(Quantity::from));
179 let emulation_trigger = row
180 .try_get::<Option<&str>, _>("emulation_trigger")
181 .ok()
182 .and_then(|x| x.map(|x| TriggerType::from_str(x).unwrap()));
183 let trigger_instrument_id = row
184 .try_get::<Option<&str>, _>("trigger_instrument_id")
185 .ok()
186 .and_then(|x| x.map(InstrumentId::from));
187 let contingency_type = row
188 .try_get::<Option<&str>, _>("contingency_type")
189 .ok()
190 .and_then(|x| x.map(|x| ContingencyType::from_str(x).unwrap()));
191 let order_list_id = row
192 .try_get::<Option<&str>, _>("order_list_id")
193 .ok()
194 .and_then(|x| x.map(OrderListId::from));
195 let linked_order_ids = row
196 .try_get::<Vec<String>, _>("linked_order_ids")
197 .ok()
198 .map(|x| x.iter().map(|x| ClientOrderId::from(x.as_str())).collect());
199 let parent_order_id = row
200 .try_get::<Option<&str>, _>("parent_order_id")
201 .ok()
202 .and_then(|x| x.map(ClientOrderId::from));
203 let exec_algorithm_id = row
204 .try_get::<Option<&str>, _>("exec_algorithm_id")
205 .ok()
206 .and_then(|x| x.map(ExecAlgorithmId::from));
207 let exec_algorithm_params: Option<IndexMap<Ustr, Ustr>> = row
208 .try_get::<Option<serde_json::Value>, _>("exec_algorithm_params")
209 .ok()
210 .and_then(|x| x.map(|x| serde_json::from_value::<IndexMap<String, String>>(x).unwrap()))
211 .map(|x| {
212 x.into_iter()
213 .map(|(k, v)| (Ustr::from(k.as_str()), Ustr::from(v.as_str())))
214 .collect()
215 });
216 let exec_spawn_id = row
217 .try_get::<Option<&str>, _>("exec_spawn_id")
218 .ok()
219 .and_then(|x| x.map(ClientOrderId::from));
220 let tags: Option<Vec<Ustr>> = row
221 .try_get::<Option<serde_json::Value>, _>("tags")
222 .ok()
223 .and_then(|x| x.map(|x| serde_json::from_value::<Vec<String>>(x).unwrap()))
224 .map(|x| x.into_iter().map(|x| Ustr::from(x.as_str())).collect());
225 let order_event = OrderInitialized::new(
226 trader_id,
227 strategy_id,
228 instrument_id,
229 client_order_id,
230 order_side,
231 order_type,
232 quantity,
233 time_in_force,
234 post_only,
235 reduce_only,
236 quote_quantity,
237 reconciliation,
238 event_id,
239 ts_event,
240 ts_init,
241 price,
242 trigger_price,
243 trigger_type,
244 limit_offset,
245 trailing_offset,
246 trailing_offset_type,
247 expire_time,
248 display_qty,
249 emulation_trigger,
250 trigger_instrument_id,
251 contingency_type,
252 order_list_id,
253 linked_order_ids,
254 parent_order_id,
255 exec_algorithm_id,
256 exec_algorithm_params,
257 exec_spawn_id,
258 tags,
259 );
260 Ok(OrderInitializedModel(order_event))
261 }
262}
263
264impl<'r> FromRow<'r, PgRow> for OrderAcceptedModel {
265 fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
266 let event_id = row.try_get::<&str, _>("id").map(UUID4::from)?;
267 let trader_id = row.try_get::<&str, _>("trader_id").map(TraderId::from)?;
268 let strategy_id = row
269 .try_get::<&str, _>("strategy_id")
270 .map(StrategyId::from)?;
271 let instrument_id = row
272 .try_get::<&str, _>("instrument_id")
273 .map(InstrumentId::from)?;
274 let client_order_id = row
275 .try_get::<&str, _>("client_order_id")
276 .map(ClientOrderId::from)?;
277 let venue_order_id = row
278 .try_get::<&str, _>("venue_order_id")
279 .map(VenueOrderId::from)?;
280 let account_id = row.try_get::<&str, _>("account_id").map(AccountId::from)?;
281 let ts_event = row.try_get::<&str, _>("ts_event").map(UnixNanos::from)?;
282 let ts_init = row.try_get::<&str, _>("ts_init").map(UnixNanos::from)?;
283 let order_event = OrderAccepted::new(
284 trader_id,
285 strategy_id,
286 instrument_id,
287 client_order_id,
288 venue_order_id,
289 account_id,
290 event_id,
291 ts_event,
292 ts_init,
293 false,
294 );
295 Ok(OrderAcceptedModel(order_event))
296 }
297}
298
299impl<'r> FromRow<'r, PgRow> for OrderCancelRejectedModel {
300 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
301 todo!()
302 }
303}
304
305impl<'r> FromRow<'r, PgRow> for OrderCanceledModel {
306 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
307 todo!()
308 }
309}
310
311impl<'r> FromRow<'r, PgRow> for OrderDeniedModel {
312 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
313 todo!()
314 }
315}
316
317impl<'r> FromRow<'r, PgRow> for OrderEmulatedModel {
318 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
319 todo!()
320 }
321}
322
323impl<'r> FromRow<'r, PgRow> for OrderExpiredModel {
324 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
325 todo!()
326 }
327}
328
329impl<'r> FromRow<'r, PgRow> for OrderFilledModel {
330 fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
331 let event_id = row.try_get::<&str, _>("id").map(UUID4::from)?;
332 let trader_id = row.try_get::<&str, _>("trader_id").map(TraderId::from)?;
333 let strategy_id = row
334 .try_get::<&str, _>("strategy_id")
335 .map(StrategyId::from)?;
336 let instrument_id = row
337 .try_get::<&str, _>("instrument_id")
338 .map(InstrumentId::from)?;
339 let client_order_id = row
340 .try_get::<&str, _>("client_order_id")
341 .map(ClientOrderId::from)?;
342 let venue_order_id = row
343 .try_get::<&str, _>("venue_order_id")
344 .map(VenueOrderId::from)?;
345 let account_id = row.try_get::<&str, _>("account_id").map(AccountId::from)?;
346 let trade_id = row.try_get::<&str, _>("trade_id").map(TradeId::from)?;
347 let order_side = row
348 .try_get::<&str, _>("order_side")
349 .map(|x| OrderSide::from_str(x).unwrap())?;
350 let order_type = row
351 .try_get::<&str, _>("order_type")
352 .map(|x| OrderType::from_str(x).unwrap())?;
353 let last_px = row.try_get::<&str, _>("last_px").map(Price::from)?;
354 let last_qty = row.try_get::<&str, _>("last_qty").map(Quantity::from)?;
355 let currency = row.try_get::<&str, _>("currency").map(Currency::from)?;
356 let liquidity_side = row
357 .try_get::<&str, _>("liquidity_side")
358 .map(|x| LiquiditySide::from_str(x).unwrap())?;
359 let ts_event = row.try_get::<&str, _>("ts_event").map(UnixNanos::from)?;
360 let ts_init = row.try_get::<&str, _>("ts_init").map(UnixNanos::from)?;
361 let position_id = row
362 .try_get::<Option<&str>, _>("position_id")
363 .map(|x| x.map(PositionId::from))?;
364 let commission = row
365 .try_get::<Option<&str>, _>("commission")
366 .map(|x| x.map(|x| Money::from_str(x).unwrap()))?;
367 let order_event = OrderFilled::new(
368 trader_id,
369 strategy_id,
370 instrument_id,
371 client_order_id,
372 venue_order_id,
373 account_id,
374 trade_id,
375 order_side,
376 order_type,
377 last_qty,
378 last_px,
379 currency,
380 liquidity_side,
381 event_id,
382 ts_event,
383 ts_init,
384 false,
385 position_id,
386 commission,
387 );
388 Ok(OrderFilledModel(order_event))
389 }
390}
391
392impl<'r> FromRow<'r, PgRow> for OrderModifyRejectedModel {
393 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
394 todo!()
395 }
396}
397
398impl<'r> FromRow<'r, PgRow> for OrderPendingCancelModel {
399 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
400 todo!()
401 }
402}
403
404impl<'r> FromRow<'r, PgRow> for OrderPendingUpdateModel {
405 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
406 todo!()
407 }
408}
409
410impl<'r> FromRow<'r, PgRow> for OrderRejectedModel {
411 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
412 todo!()
413 }
414}
415
416impl<'r> FromRow<'r, PgRow> for OrderReleasedModel {
417 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
418 todo!()
419 }
420}
421
422impl<'r> FromRow<'r, PgRow> for OrderSubmittedModel {
423 fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
424 let trader_id = row.try_get::<&str, _>("trader_id").map(TraderId::from)?;
425 let strategy_id = row
426 .try_get::<&str, _>("strategy_id")
427 .map(StrategyId::from)?;
428 let instrument_id = row
429 .try_get::<&str, _>("instrument_id")
430 .map(InstrumentId::from)?;
431 let client_order_id = row
432 .try_get::<&str, _>("client_order_id")
433 .map(ClientOrderId::from)?;
434 let account_id = row.try_get::<&str, _>("account_id").map(AccountId::from)?;
435 let event_id = row.try_get::<&str, _>("id").map(UUID4::from)?;
436 let ts_event = row
437 .try_get::<String, _>("ts_event")
438 .map(|res| UnixNanos::from(res.as_str()))?;
439 let ts_init = row
440 .try_get::<String, _>("ts_init")
441 .map(|res| UnixNanos::from(res.as_str()))?;
442 let order_event = OrderSubmitted::new(
443 trader_id,
444 strategy_id,
445 instrument_id,
446 client_order_id,
447 account_id,
448 event_id,
449 ts_event,
450 ts_init,
451 );
452 Ok(OrderSubmittedModel(order_event))
453 }
454}
455
456impl<'r> FromRow<'r, PgRow> for OrderTriggeredModel {
457 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
458 todo!()
459 }
460}
461
462impl<'r> FromRow<'r, PgRow> for OrderUpdatedModel {
463 fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
464 todo!()
465 }
466}
467
468impl<'r> FromRow<'r, PgRow> for OrderSnapshotModel {
469 fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
470 let trader_id = row.try_get::<&str, _>("trader_id").map(TraderId::from)?;
471 let strategy_id = row
472 .try_get::<&str, _>("strategy_id")
473 .map(StrategyId::from)?;
474 let instrument_id = row
475 .try_get::<&str, _>("instrument_id")
476 .map(InstrumentId::from)?;
477 let client_order_id = row
478 .try_get::<&str, _>("client_order_id")
479 .map(ClientOrderId::from)?;
480 let venue_order_id = row
481 .try_get::<Option<&str>, _>("venue_order_id")
482 .ok()
483 .and_then(|x| x.map(VenueOrderId::from));
484 let position_id = row
485 .try_get::<Option<&str>, _>("position_id")
486 .ok()
487 .and_then(|x| x.map(PositionId::from));
488 let account_id = row
489 .try_get::<Option<&str>, _>("account_id")
490 .ok()
491 .and_then(|x| x.map(AccountId::from));
492 let last_trade_id = row
493 .try_get::<Option<&str>, _>("last_trade_id")
494 .ok()
495 .and_then(|x| x.map(TradeId::from));
496 let order_type = row
497 .try_get::<&str, _>("order_type")
498 .map(|x| OrderType::from_str(x).expect("Invalid `OrderType`"))?;
499 let order_side = row
500 .try_get::<&str, _>("order_side")
501 .map(|x| OrderSide::from_str(x).expect("Invalid `OrderSide`"))?;
502 let quantity = row.try_get::<&str, _>("quantity").map(Quantity::from)?;
503 let price = row
504 .try_get::<Option<&str>, _>("price")
505 .ok()
506 .and_then(|x| x.map(Price::from));
507 let trigger_price = row
508 .try_get::<Option<&str>, _>("trigger_price")
509 .ok()
510 .and_then(|x| x.map(Price::from));
511 let trigger_type = row
512 .try_get::<Option<&str>, _>("trigger_type")
513 .ok()
514 .and_then(|x| x.map(|x| TriggerType::from_str(x).expect("Invalid `TriggerType`")));
515 let limit_offset = row
516 .try_get::<Option<&str>, _>("limit_offset")
517 .ok()
518 .and_then(|x| x.and_then(|s| Decimal::from_str(s).ok()));
519 let trailing_offset = row
520 .try_get::<Option<&str>, _>("trailing_offset")
521 .ok()
522 .and_then(|x| x.and_then(|s| Decimal::from_str(s).ok()));
523 let trailing_offset_type = row
524 .try_get::<Option<TrailingOffsetTypeModel>, _>("trailing_offset_type")
525 .ok()
526 .and_then(|x| x.map(|x| x.0));
527 let time_in_force = row
528 .try_get::<&str, _>("time_in_force")
529 .map(|x| TimeInForce::from_str(x).expect("Invalid `TimeInForce`"))?;
530 let expire_time = row
531 .try_get::<Option<&str>, _>("expire_time")
532 .ok()
533 .and_then(|x| x.map(UnixNanos::from));
534 let filled_qty = row.try_get::<&str, _>("filled_qty").map(Quantity::from)?;
535 let liquidity_side = row
536 .try_get::<Option<&str>, _>("liquidity_side")
537 .ok()
538 .and_then(|x| x.map(|x| LiquiditySide::from_str(x).expect("Invalid `LiquiditySide`")));
539 let avg_px = row.try_get::<Option<f64>, _>("avg_px").ok().flatten();
540 let slippage = row.try_get::<Option<f64>, _>("slippage").ok().flatten();
541 let commissions = row
542 .try_get::<Option<Vec<String>>, _>("commissions")?
543 .map_or_else(Vec::new, |c| {
544 c.into_iter().map(|s| Money::from(&s)).collect()
545 });
546 let status = row
547 .try_get::<&str, _>("status")
548 .map(|x| OrderStatus::from_str(x).expect("Invalid `OrderStatus`"))?;
549 let is_post_only = row.try_get::<bool, _>("is_post_only")?;
550 let is_reduce_only = row.try_get::<bool, _>("is_reduce_only")?;
551 let is_quote_quantity = row.try_get::<bool, _>("is_quote_quantity")?;
552 let display_qty = row
553 .try_get::<Option<&str>, _>("display_qty")
554 .ok()
555 .and_then(|x| x.map(Quantity::from));
556 let emulation_trigger = row
557 .try_get::<Option<&str>, _>("emulation_trigger")
558 .ok()
559 .and_then(|x| x.map(|x| TriggerType::from_str(x).expect("Invalid `TriggerType`")));
560 let trigger_instrument_id = row
561 .try_get::<Option<&str>, _>("trigger_instrument_id")
562 .ok()
563 .and_then(|x| x.map(InstrumentId::from));
564 let contingency_type = row
565 .try_get::<Option<&str>, _>("contingency_type")
566 .ok()
567 .and_then(|x| {
568 x.map(|x| ContingencyType::from_str(x).expect("Invalid `ContingencyType`"))
569 });
570 let order_list_id = row
571 .try_get::<Option<&str>, _>("order_list_id")
572 .ok()
573 .and_then(|x| x.map(OrderListId::from));
574 let linked_order_ids = row
575 .try_get::<Option<Vec<String>>, _>("linked_order_ids")
576 .ok()
577 .and_then(|ids| ids.map(|ids| ids.into_iter().map(ClientOrderId::from).collect()));
578 let parent_order_id = row
579 .try_get::<Option<&str>, _>("parent_order_id")
580 .ok()
581 .and_then(|x| x.map(ClientOrderId::from));
582 let exec_algorithm_id = row
583 .try_get::<Option<&str>, _>("exec_algorithm_id")
584 .ok()
585 .and_then(|x| x.map(ExecAlgorithmId::from));
586 let exec_algorithm_params: Option<IndexMap<Ustr, Ustr>> = row
587 .try_get::<Option<serde_json::Value>, _>("exec_algorithm_params")
588 .ok()
589 .and_then(|x| {
590 x.map(|x| {
591 serde_json::from_value::<IndexMap<String, String>>(x)
592 .expect("Invalid exec algorithm params")
593 })
594 })
595 .map(|x| {
596 x.into_iter()
597 .map(|(k, v)| (Ustr::from(k.as_str()), Ustr::from(v.as_str())))
598 .collect()
599 });
600 let exec_spawn_id = row
601 .try_get::<Option<&str>, _>("exec_spawn_id")
602 .ok()
603 .and_then(|x| x.map(ClientOrderId::from));
604 let tags = row
605 .try_get::<Option<serde_json::Value>, _>("tags")
606 .ok()
607 .flatten()
608 .and_then(|tags_value| {
609 serde_json::from_value::<Vec<String>>(tags_value)
610 .ok()
611 .map(|vec| {
612 vec.into_iter()
613 .map(|tag| Ustr::from(tag.as_str()))
614 .collect::<Vec<Ustr>>()
615 })
616 });
617 let init_id = row.try_get::<&str, _>("init_id").map(UUID4::from)?;
618 let ts_init = row.try_get::<String, _>("ts_init").map(UnixNanos::from)?;
619 let ts_last = row.try_get::<String, _>("ts_last").map(UnixNanos::from)?;
620
621 let snapshot = OrderSnapshot {
622 trader_id,
623 strategy_id,
624 instrument_id,
625 client_order_id,
626 venue_order_id,
627 position_id,
628 account_id,
629 last_trade_id,
630 order_type,
631 order_side,
632 quantity,
633 price,
634 trigger_price,
635 trigger_type,
636 limit_offset,
637 trailing_offset,
638 trailing_offset_type,
639 time_in_force,
640 expire_time,
641 filled_qty,
642 liquidity_side,
643 avg_px,
644 slippage,
645 commissions,
646 status,
647 is_post_only,
648 is_reduce_only,
649 is_quote_quantity,
650 display_qty,
651 emulation_trigger,
652 trigger_instrument_id,
653 contingency_type,
654 order_list_id,
655 linked_order_ids,
656 parent_order_id,
657 exec_algorithm_id,
658 exec_algorithm_params,
659 exec_spawn_id,
660 tags,
661 init_id,
662 ts_init,
663 ts_last,
664 };
665
666 Ok(OrderSnapshotModel(snapshot))
667 }
668}