brokerage-db 0.2.0

Database management for trader brokerage data with a MongoDB backend.
Documentation
use crate::{account::BrokerageAccount, security::Security};
use anyhow::Result;
use bson::oid::ObjectId;
use mongodb::Database;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
pub enum TradeSide {
    Buy,
    Sell,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct TradeExecution {
    pub _id: bson::oid::ObjectId,
    pub brokerage_account_id: bson::oid::ObjectId,
    pub brokerage_execution_id: String,
    pub execution_timestamp_ms: i64,
    pub commission: f64,
    pub quantity: u64,
    pub price: f64,
    pub security_id: bson::oid::ObjectId,
    pub side: TradeSide,
}

impl TradeExecution {
    pub const COLLECTION_NAME: &'static str = "trade_executions";

    pub async fn insert(&self, db: &Database) -> Result<()> {
        let result = db
            .collection::<Self>(Self::COLLECTION_NAME)
            .insert_one(self)
            .await?;
        tracing::info!(
            "inserted trade execution {:?}: (reported insert id: {:?})",
            self,
            result.inserted_id
        );
        Ok(())
    }

    pub async fn find_by_id(db: &Database, id: ObjectId) -> Result<Option<Self>> {
        let result = db
            .collection::<Self>(Self::COLLECTION_NAME)
            .find_one(bson::doc! {"_id": id})
            .await?;

        Ok(result)
    }

    pub async fn brokerage_account(&self, db: &Database) -> Result<BrokerageAccount> {
        Ok(BrokerageAccount::find_by_id(db, self.brokerage_account_id)
            .await?
            .unwrap())
    }

    pub async fn security(&self, db: &Database) -> Result<Security> {
        Ok(Security::find_by_id(db, self.security_id).await?.unwrap())
    }
}