use crate::internal::domain::{AccountId, BrokerOrderId, Money, ReadOnlyOrderStatus};
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PaperOrderLifecycleStatus {
Submitted,
Open,
Filled,
Cancelled,
Refused,
}
impl PaperOrderLifecycleStatus {
#[must_use]
pub const fn is_terminal(self) -> bool {
matches!(self, Self::Filled | Self::Cancelled | Self::Refused)
}
#[must_use]
pub fn from_submit_receipt_status(broker_status: Option<&str>) -> Self {
match broker_status.map(normalize_broker_status).as_deref() {
Some("filled") => Self::Filled,
Some("cancelled" | "canceled") => Self::Cancelled,
Some("rejected" | "refused" | "inactive") => Self::Refused,
Some("submitted" | "presubmitted" | "open" | "localcandidate") | None => {
Self::Submitted
}
Some(_) => Self::Submitted,
}
}
#[must_use]
pub fn from_cancel_receipt_status(broker_status: Option<&str>, accepted: bool) -> Self {
match broker_status.map(normalize_broker_status).as_deref() {
Some("cancelled" | "canceled") => Self::Cancelled,
Some("filled") => Self::Filled,
Some("rejected" | "refused" | "inactive") => Self::Refused,
Some("submitted" | "presubmitted" | "open") => Self::Open,
Some(_) | None if accepted => Self::Cancelled,
Some(_) | None => Self::Refused,
}
}
#[must_use]
pub fn from_modify_receipt_status(broker_status: Option<&str>, accepted: bool) -> Self {
match broker_status.map(normalize_broker_status).as_deref() {
Some("filled") => Self::Filled,
Some("cancelled" | "canceled") => Self::Cancelled,
Some("rejected" | "refused" | "inactive") => Self::Refused,
Some("submitted" | "presubmitted" | "open" | "modified" | "pendingmodify") => {
Self::Open
}
Some(_) | None if accepted => Self::Open,
Some(_) | None => Self::Refused,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct PaperOrderLifecycleRecord {
pub account_id: AccountId,
pub broker_order_id: BrokerOrderId,
pub status: PaperOrderLifecycleStatus,
#[serde(with = "time::serde::rfc3339")]
pub updated_at: OffsetDateTime,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum LiveOrderLifecycleStatus {
Submitted,
Open,
PendingCancel,
Filled,
Cancelled,
Refused,
}
impl LiveOrderLifecycleStatus {
#[must_use]
pub const fn is_terminal(self) -> bool {
matches!(self, Self::Filled | Self::Cancelled | Self::Refused)
}
#[must_use]
pub const fn from_read_only_order_status(status: ReadOnlyOrderStatus) -> Self {
match status {
ReadOnlyOrderStatus::Open => Self::Open,
ReadOnlyOrderStatus::Filled => Self::Filled,
ReadOnlyOrderStatus::Cancelled => Self::Cancelled,
ReadOnlyOrderStatus::Unknown => Self::Submitted,
}
}
#[must_use]
pub fn from_cancel_receipt_status(broker_status: Option<&str>, accepted: bool) -> Self {
match broker_status.map(normalize_broker_status).as_deref() {
Some("cancelled" | "canceled") => Self::Cancelled,
Some("pendingcancel") => Self::PendingCancel,
Some("filled") => Self::Filled,
Some("rejected" | "refused" | "inactive") => Self::Refused,
Some("submitted" | "presubmitted" | "open") => Self::Open,
Some(_) | None if accepted => Self::PendingCancel,
Some(_) | None => Self::Refused,
}
}
#[must_use]
pub fn from_modify_receipt_status(broker_status: Option<&str>, accepted: bool) -> Self {
match broker_status.map(normalize_broker_status).as_deref() {
Some("filled") => Self::Filled,
Some("cancelled" | "canceled") => Self::Cancelled,
Some("rejected" | "refused" | "inactive") => Self::Refused,
Some("submitted" | "presubmitted" | "open" | "modified" | "pendingmodify") => {
Self::Open
}
Some(_) | None if accepted => Self::Open,
Some(_) | None => Self::Refused,
}
}
}
fn normalize_broker_status(status: &str) -> String {
status
.chars()
.filter(|character| !matches!(character, '_' | '-' | ' '))
.flat_map(char::to_lowercase)
.collect()
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct LiveExecutionCorrelation {
pub correlation_id: String,
pub broker_order_id: BrokerOrderId,
#[serde(with = "time::serde::rfc3339")]
pub updated_at: OffsetDateTime,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct LiveOrderLifecycleRecord {
pub account_id: AccountId,
pub broker_order_id: BrokerOrderId,
pub status: LiveOrderLifecycleStatus,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub notional: Option<Money>,
pub execution_correlation: Option<LiveExecutionCorrelation>,
#[serde(with = "time::serde::rfc3339")]
pub updated_at: OffsetDateTime,
}