use std::ops::Add;
use chrono::{DateTime, Utc};
use rust_decimal::prelude::Zero;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::db::Collectable;
use crate::payment::{self, Payment};
use crate::product::Product;
use crate::Database;
use crate::Result;
use crate::{db::Identifiable, user, user::UserId};
pub type OrderCost = Decimal;
pub type OrderId = Uuid;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Order {
pub id: OrderId,
pub user: UserId,
pub time: DateTime<Utc>,
pub status: OrderStatus,
pub mode: OrderMode,
pub items: Vec<Product>,
}
impl Collectable for Order {
fn get_collection_name() -> &'static str {
"orders"
}
}
impl Identifiable for Order {
fn get_id(&self) -> uuid::Uuid {
self.id
}
}
impl Order {
pub fn total_cost(&self) -> Decimal {
let mut delta = Decimal::zero();
for item in &self.items {
delta += item.cost();
}
delta
}
pub async fn fulfill(mut self, db: &Database) -> Result<()> {
self.status = OrderStatus::Processing;
db.set(&self)?;
for item in &self.items {
item.realize_for(self.user, db).await?;
}
self.status = OrderStatus::Completed { time: Utc::now() };
db.set(&self)?;
Ok(())
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum OrderStatus {
Initiated,
Processing,
Failed,
Completed { time: DateTime<Utc> },
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum OrderMode {
Manual,
Api,
Auto,
}