#![allow(missing_docs)]
use serde::Deserialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
pub enum PostbackValidationError {
#[error("postback dhan_client_id is required")]
MissingClientId,
#[error("postback order_id is required")]
MissingOrderId,
#[error("postback order_status is required")]
MissingOrderStatus,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PostbackPayload {
pub dhan_client_id: Option<String>,
pub order_id: Option<String>,
pub correlation_id: Option<String>,
pub order_status: Option<String>,
pub transaction_type: Option<String>,
pub exchange_segment: Option<String>,
pub product_type: Option<String>,
pub order_type: Option<String>,
pub validity: Option<String>,
pub trading_symbol: Option<String>,
pub security_id: Option<String>,
#[serde(default)]
pub quantity: Option<u64>,
#[serde(default)]
pub disclosed_quantity: Option<u64>,
#[serde(default)]
pub price: Option<f64>,
#[serde(default)]
pub trigger_price: Option<f64>,
#[serde(default)]
pub after_market_order: Option<bool>,
#[serde(default)]
pub bo_profit_value: Option<f64>,
#[serde(default)]
pub bo_stop_loss_value: Option<f64>,
pub leg_name: Option<String>,
pub create_time: Option<String>,
pub update_time: Option<String>,
pub exchange_time: Option<String>,
pub drv_expiry_date: Option<String>,
pub drv_option_type: Option<String>,
#[serde(default)]
pub drv_strike_price: Option<f64>,
pub oms_error_code: Option<String>,
pub oms_error_description: Option<String>,
#[serde(default, alias = "filled_qty")]
pub filled_qty: Option<u64>,
pub algo_id: Option<String>,
}
impl PostbackPayload {
pub fn validate(&self) -> Result<(), PostbackValidationError> {
if self
.dhan_client_id
.as_deref()
.is_none_or(|value| value.trim().is_empty())
{
return Err(PostbackValidationError::MissingClientId);
}
if self
.order_id
.as_deref()
.is_none_or(|value| value.trim().is_empty())
{
return Err(PostbackValidationError::MissingOrderId);
}
if self
.order_status
.as_deref()
.is_none_or(|value| value.trim().is_empty())
{
return Err(PostbackValidationError::MissingOrderStatus);
}
Ok(())
}
pub fn is_traded(&self) -> bool {
self.order_status.as_deref() == Some("TRADED")
}
pub fn is_rejected(&self) -> bool {
self.order_status.as_deref() == Some("REJECTED")
}
pub fn is_cancelled(&self) -> bool {
self.order_status.as_deref() == Some("CANCELLED")
}
pub fn is_pending(&self) -> bool {
self.order_status.as_deref() == Some("PENDING")
}
pub fn is_buy(&self) -> bool {
self.transaction_type.as_deref() == Some("BUY")
}
pub fn is_sell(&self) -> bool {
self.transaction_type.as_deref() == Some("SELL")
}
}