use serde::Serialize; use sqlx::SqlitePool; use anyhow::Result; use chrono::{DateTime, Utc}; use tracing::error; #[derive(Debug, Serialize)] #[derive(sqlx::FromRow)] pub struct DbNegativeAdjustment { pub id: i64, pub item: i64, pub user: i64, pub create_date: i64, pub target_date: i64, pub amount: f64, pub reason: DbNegativeAdjustmentReason, } pub async fn add_negative_adjustment(db: &SqlitePool, item: i64, user: i64, create_date: DateTime, target_date: DateTime, amount: f64, reason: DbNegativeAdjustmentReason) -> Result { let reason: i64 = reason.into(); let res = sqlx::query!( r#" INSERT INTO NegativeAdjustment (item, user, create_date, target_date, amount, reason) VALUES (?, ?, ?, ?, ?, ?) "#, item, user, create_date, target_date, amount, reason ).execute(db).await?; let new_id = res.last_insert_rowid(); Ok(new_id) } pub async fn get_negative_adjustments_target_date_range( db: &SqlitePool, start_date: DateTime, end_date: DateTime ) -> Result> { sqlx::query_as!( DbNegativeAdjustment, r#" SELECT id, item, user, create_date, target_date, amount, reason FROM NegativeAdjustment WHERE target_date >= ? AND target_date <= ? "#, start_date, end_date ) .fetch_all(db) .await.map_err(Into::into) } #[derive(Debug, Clone, Copy, Serialize)] pub enum DbNegativeAdjustmentReason { Unknown, Sale, Destruction, Expiration, Theft, } impl Into for DbNegativeAdjustmentReason { fn into(self) -> i64 { match self { Self::Unknown => 0, Self::Sale => 10, Self::Destruction => 20, Self::Expiration => 25, Self::Theft => 30, } } } impl From for DbNegativeAdjustmentReason { fn from(item: i64) -> Self { match item { 0 => Self::Unknown, 10 => Self::Sale, 20 => Self::Destruction, 25 => Self::Expiration, 30 => Self::Theft, _ => { error!("unknown negative adjustment reason value: {}", item); Self::Unknown } } } } impl TryFrom<&str> for DbNegativeAdjustmentReason { type Error = anyhow::Error; fn try_from(value: &str) -> std::result::Result { match value { "unknown" => Ok(Self::Unknown), "sale" => Ok(Self::Sale), "destruction" => Ok(Self::Destruction), "expiration" => Ok(Self::Expiration), "theft" => Ok(Self::Theft), _ => Err(anyhow::anyhow!("unknown negative adjustment reason")) } } } impl Into for DbNegativeAdjustmentReason { fn into(self) -> String { match self { Self::Unknown => { String::from("unknown") } Self::Sale => { String::from("sale") } Self::Destruction => { String::from("destruction") } Self::Expiration => { String::from("expiration") } Self::Theft => { String::from("theft") } } } }