You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
inventory-app/src/app/item/create.rs

182 lines
5.9 KiB

use crate::error::AppError;
use crate::session::SessionUser;
use askama::Template;
use askama_axum::{IntoResponse, Response};
use axum::extract::State;
use axum::{async_trait, debug_handler, Form};
use serde::Deserialize;
use crate::app::routes::AppState;
use crate::db::display_unit::DbDisplayUnit;
use crate::db;
use crate::util::extract::form_helpers::form_checkbox_is_checked;
use crate::util::extract::htmx_form_data::{HtmxFormData, HtmxFormDataError};
use crate::util::extract::validated_form::ValidatedForm;
#[derive(Template, Debug)]
#[template(path = "item/item-create-form.html")]
pub struct CreateItemFormTemplate {
pub display_units: Vec<DbDisplayUnit>,
pub name_value: String,
pub name_error: &'static str,
pub display_unit_value: String,
pub display_unit_error: &'static str,
pub reorder_point_value: String,
pub reorder_point_error: &'static str,
pub pims_id_value: String,
pub pims_id_error: &'static str,
pub vetcove_id_value: String,
pub vetcove_id_error: &'static str,
pub allow_fractional_units_value: bool,
}
impl CreateItemFormTemplate {
pub fn clear_inputs(&mut self) {
self.name_value.clear();
self.display_unit_value.clear();
self.reorder_point_value.clear();
self.pims_id_value.clear();
self.vetcove_id_value.clear();
self.allow_fractional_units_value = false;
}
}
#[derive(Deserialize, Debug)]
pub struct CreateItemFormData {
name: String,
display_unit: String,
reorder_point: f64,
allow_fractional_units: Option<String>,
pims_id: Option<String>,
vetcove_id: Option<String>,
}
#[async_trait]
impl HtmxFormData for CreateItemFormData {
type FormTemplate = CreateItemFormTemplate;
async fn validate(self, state: &AppState) -> Result<Self, HtmxFormDataError<Self::FormTemplate>> {
let mut base = Self::base_template(&state).await?;
let display_units = &base.display_units;
let allow_fractional_units = form_checkbox_is_checked(&self.allow_fractional_units);
let name_error = if self.name.is_empty() {
"Please provide a name"
} else {
""
};
let display_unit_error = if self.display_unit.is_empty() {
"Please provide a display unit"
} else if !display_units.iter().any(|x| x.abbreviation.eq(&self.display_unit)){
"Invalid display unit"
} else {
""
};
let reorder_point_error = if self.reorder_point.is_nan()
|| self.reorder_point.is_infinite()
|| self.reorder_point.is_sign_negative()
{
"Provide a positive number"
} else if !(allow_fractional_units || self.reorder_point.fract() == 0.0) {
"Fractional units not allowed"
} else {
""
};
let pims_id_error = if let Some(pims_id) = &self.pims_id {
if pims_id.chars().any(char::is_whitespace) {
"Invalid PIMS id"
}
else {
""
}
}
else {
""
};
let vetcove_id_error = if let Some(vetcove_id) = &self.vetcove_id {
if !vetcove_id.chars().all(|c| c.is_ascii_digit()) {
"Invalid Vectcove id"
}
else {
""
}
}
else {
""
};
if !(name_error.is_empty()
&& display_unit_error.is_empty()
&& reorder_point_error.is_empty()
&& pims_id_error.is_empty()
&& vetcove_id_error.is_empty()) {
base.name_value = self.name;
base.name_error = name_error;
base.display_unit_value = self.display_unit;
base.display_unit_error = display_unit_error;
base.reorder_point_value = format!("{:.2}", self.reorder_point);
base.reorder_point_error = reorder_point_error;
base.pims_id_value = self.pims_id.as_deref().unwrap_or_default().to_string();
base.pims_id_error = pims_id_error;
base.vetcove_id_value = self.vetcove_id.as_deref().unwrap_or_default().to_string();
base.vetcove_id_error = vetcove_id_error;
base.allow_fractional_units_value = allow_fractional_units;
return Err(HtmxFormDataError::ValidationError(base));
}
Ok(self)
}
async fn base_template(state: &AppState) -> anyhow::Result<Self::FormTemplate> {
let db = &state.db;
let display_units = db::display_unit::get_display_units(&db).await?;
Ok(Self::FormTemplate {
display_units,
name_value: "".to_owned(),
name_error: "",
display_unit_value: "".to_owned(),
display_unit_error: "",
reorder_point_value: "".to_owned(),
reorder_point_error: "",
pims_id_value: "".to_owned(),
pims_id_error: "",
vetcove_id_value: "".to_owned(),
vetcove_id_error: "",
allow_fractional_units_value: false,
})
}
}
#[debug_handler]
pub async fn create_item_form_post(
State(state): State<AppState>,
user: SessionUser,
form_data: ValidatedForm<CreateItemFormData>,
) -> Result<Response, AppError> {
let allow_fractional_units = form_checkbox_is_checked(&form_data.allow_fractional_units);
let _new_id = db::inventory_item::add_inventory_item(&state.db, &form_data.name, form_data.reorder_point,
allow_fractional_units, &form_data.display_unit,
&form_data.pims_id, &form_data.vetcove_id,
).await?;
Ok(CreateItemFormData::base_template(&state).await?.into_response())
}
#[debug_handler]
pub async fn create_item_form_get(
State(state): State<AppState>,
) -> Result<Response, AppError> {
Ok(CreateItemFormData::base_template(&state).await?.into_response())
}

Powered by TurnKey Linux.