use crate::db::adjustment::add_adjustment; use crate::db::adjustment::adjustment_reason::DbAdjustmentReason; use crate::db::inventory_item::does_inventory_item_allow_fractional_units; use crate::error::AppError; use crate::session::SessionUser; use askama::Template; use askama_axum::{IntoResponse, Response}; use axum::extract::{Path, State}; use axum::{debug_handler, Form}; use axum_htmx::{HxEvent, HxResponseTrigger}; use serde::Deserialize; use sqlx::SqlitePool; use tracing::info; #[derive(Template)] #[template(path = "item/adjustment/negative-adjustment-form.html")] pub struct NegativeAdjustmentFormTemplate { pub item_id: i64, pub amount_error: &'static str, pub reason_error: &'static str, } #[derive(Deserialize, Debug)] pub struct NegativeAdjustmentFormData { pub amount: f64, pub reason: Option, } #[debug_handler] pub async fn negative_adjustment_form_post( State(db): State, Path(id): Path, user: SessionUser, mut form_data: Form, ) -> Result { let adjustment_amount = if form_data.amount > 0.0 { -1.0 * form_data.amount } else { form_data.amount }; let fractional_units_allowed = does_inventory_item_allow_fractional_units(&db, id).await?; let reason = form_data .reason .take() .and_then(|s| DbAdjustmentReason::try_from(s.as_str()).ok()) .unwrap_or_else(|| DbAdjustmentReason::Unknown); let amount_error = if adjustment_amount == 0.0 { "Please input a non-zero amount" } else if !(fractional_units_allowed || adjustment_amount.fract() == 0.0) { "Please input a whole number" } else { "" }; let reason_error = if reason == DbAdjustmentReason::Unknown { "Unknown adjustment reason" } else { "" }; if !(amount_error.is_empty() && reason_error.is_empty()) { return Ok(NegativeAdjustmentFormTemplate { item_id: id, amount_error, reason_error, } .into_response()); } let trigger_events = HxResponseTrigger::normal(std::iter::once(HxEvent::from("new-adjustment"))); let timestamp = chrono::Utc::now(); info!( "Add adjustment form: (Amount {}, Reason {:?}, for user {}", form_data.amount, reason, user.name ); let _new_id = add_adjustment( &db, id, user.id, timestamp, timestamp, adjustment_amount, None, reason, ) .await?; Ok(( trigger_events, NegativeAdjustmentFormTemplate { item_id: id, amount_error: "", reason_error: "", } .into_response(), ) .into_response()) } pub async fn negative_adjustment_form_get(Path(id): Path) -> Result { Ok(NegativeAdjustmentFormTemplate { item_id: id, amount_error: "", reason_error: "", } .into_response()) }