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