use askama::Template; use askama_axum::IntoResponse; use axum::extract::{Path, State}; use sqlx::SqlitePool; use axum::response::Response; use crate::app::adjustment::AdjustmentDisplayItem; use crate::db::adjustment::{get_item_adjustment_valuation_weighted_mean, sum_all_adjustments_for_item, DbAdjustmentWithValuation}; use crate::db::inventory_item::{inventory_item_get_by_id_with_unit, DbInventoryItemWithCount}; use crate::error::AppError; use crate::session::SessionUser; use crate::util::currency::int_cents_to_dollars_string; use crate::util::formatting::format_either; #[derive(Template)] #[template(path = "item.html")] struct ItemTemplate { pub item_id: i64, pub item: ItemDisplayItem, } #[derive(Clone, Debug)] struct ItemDisplayItem { pub name: String, pub reorder_point: f64, pub allow_fractional_units: bool, pub display_unit: String, pub display_unit_short: String, pub amount: String, } impl From for ItemDisplayItem { fn from(item: DbInventoryItemWithCount) -> Self { let precision = if item.allow_fractional_units { 2 } else { 0 }; let amount = format!("{:.*}", precision, item.amount.unwrap_or_default()); Self { name: item.name, reorder_point: item.reorder_point, allow_fractional_units: item.allow_fractional_units, display_unit: item.display_unit_str, display_unit_short: item.display_unit_abbreviation, amount, } } } pub async fn item(State(db): State, Path(id): Path, user: SessionUser ) -> Result { let mut item: ItemDisplayItem = inventory_item_get_by_id_with_unit(&db, id).await?.into(); Ok(ItemTemplate { item_id: id, item }.into_response()) } pub async fn item_count(State(db): State, Path(id): Path) -> Result { let count = sum_all_adjustments_for_item(&db, id).await?; Ok(count.to_string().into_response()) }