|
|
|
@ -2,14 +2,15 @@ use crate::error::AppError;
|
|
|
|
use crate::session::SessionUser;
|
|
|
|
use crate::session::SessionUser;
|
|
|
|
use askama::Template;
|
|
|
|
use askama::Template;
|
|
|
|
use askama_axum::{IntoResponse, Response};
|
|
|
|
use askama_axum::{IntoResponse, Response};
|
|
|
|
use axum::extract::{Path, State};
|
|
|
|
use axum::extract::State;
|
|
|
|
use axum::{debug_handler, Form};
|
|
|
|
use axum::{async_trait, debug_handler, Form};
|
|
|
|
use axum_htmx::{HxEvent, HxResponseTrigger};
|
|
|
|
|
|
|
|
use serde::Deserialize;
|
|
|
|
use serde::Deserialize;
|
|
|
|
use sqlx::SqlitePool;
|
|
|
|
use crate::app::routes::AppState;
|
|
|
|
use tracing::info;
|
|
|
|
|
|
|
|
use crate::db::display_unit::DbDisplayUnit;
|
|
|
|
use crate::db::display_unit::DbDisplayUnit;
|
|
|
|
use crate::db;
|
|
|
|
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)]
|
|
|
|
#[derive(Template, Debug)]
|
|
|
|
#[template(path = "item/item-create-form.html")]
|
|
|
|
#[template(path = "item/item-create-form.html")]
|
|
|
|
@ -49,29 +50,14 @@ pub struct CreateItemFormData {
|
|
|
|
vetcove_id: Option<String>,
|
|
|
|
vetcove_id: Option<String>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn form_checkbox_is_checked(val: &Option<String>) -> bool {
|
|
|
|
#[async_trait]
|
|
|
|
val.as_ref().map(|val| val == "on").unwrap_or(false)
|
|
|
|
impl HtmxFormData for CreateItemFormData {
|
|
|
|
}
|
|
|
|
type FormTemplate = CreateItemFormTemplate;
|
|
|
|
|
|
|
|
|
|
|
|
impl CreateItemFormData {
|
|
|
|
async fn validate(self, state: &AppState) -> Result<Self, HtmxFormDataError<Self::FormTemplate>> {
|
|
|
|
pub fn base_template() -> CreateItemFormTemplate {
|
|
|
|
let mut base = Self::base_template(&state).await?;
|
|
|
|
CreateItemFormTemplate {
|
|
|
|
let display_units = &base.display_units;
|
|
|
|
display_units: vec![],
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn validate(&self, display_units: Vec<DbDisplayUnit>) -> Result<CreateItemFormTemplate, CreateItemFormTemplate> {
|
|
|
|
|
|
|
|
let allow_fractional_units = form_checkbox_is_checked(&self.allow_fractional_units);
|
|
|
|
let allow_fractional_units = form_checkbox_is_checked(&self.allow_fractional_units);
|
|
|
|
|
|
|
|
|
|
|
|
let name_error = if self.name.is_empty() {
|
|
|
|
let name_error = if self.name.is_empty() {
|
|
|
|
@ -124,68 +110,72 @@ impl CreateItemFormData {
|
|
|
|
""
|
|
|
|
""
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let template = CreateItemFormTemplate {
|
|
|
|
|
|
|
|
display_units,
|
|
|
|
|
|
|
|
name_value: self.name.clone(),
|
|
|
|
|
|
|
|
name_error,
|
|
|
|
|
|
|
|
display_unit_value: self.display_unit.clone(),
|
|
|
|
|
|
|
|
display_unit_error,
|
|
|
|
|
|
|
|
reorder_point_value: format!("{:.2}", self.reorder_point),
|
|
|
|
|
|
|
|
reorder_point_error,
|
|
|
|
|
|
|
|
pims_id_value: self.pims_id.as_deref().unwrap_or_default().to_string(),
|
|
|
|
|
|
|
|
pims_id_error,
|
|
|
|
|
|
|
|
vetcove_id_value: self.vetcove_id.as_deref().unwrap_or_default().to_string(),
|
|
|
|
|
|
|
|
vetcove_id_error,
|
|
|
|
|
|
|
|
allow_fractional_units_value: allow_fractional_units,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !(name_error.is_empty()
|
|
|
|
if !(name_error.is_empty()
|
|
|
|
&& display_unit_error.is_empty()
|
|
|
|
&& display_unit_error.is_empty()
|
|
|
|
&& reorder_point_error.is_empty()
|
|
|
|
&& reorder_point_error.is_empty()
|
|
|
|
&& pims_id_error.is_empty()
|
|
|
|
&& pims_id_error.is_empty()
|
|
|
|
&& vetcove_id_error.is_empty()) {
|
|
|
|
&& vetcove_id_error.is_empty()) {
|
|
|
|
return Err(template);
|
|
|
|
|
|
|
|
|
|
|
|
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(template)
|
|
|
|
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]
|
|
|
|
#[debug_handler]
|
|
|
|
pub async fn create_item_form_post(
|
|
|
|
pub async fn create_item_form_post(
|
|
|
|
State(db): State<SqlitePool>,
|
|
|
|
State(state): State<AppState>,
|
|
|
|
user: SessionUser,
|
|
|
|
user: SessionUser,
|
|
|
|
mut form_data: Form<CreateItemFormData>,
|
|
|
|
form_data: ValidatedForm<CreateItemFormData>,
|
|
|
|
) -> Result<Response, AppError> {
|
|
|
|
) -> Result<Response, AppError> {
|
|
|
|
|
|
|
|
|
|
|
|
let display_units = db::display_unit::get_display_units(&db).await?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let validation = form_data.validate(display_units);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Err(resp) = validation {
|
|
|
|
|
|
|
|
return Ok(resp.into_response());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let allow_fractional_units = form_checkbox_is_checked(&form_data.allow_fractional_units);
|
|
|
|
let allow_fractional_units = form_checkbox_is_checked(&form_data.allow_fractional_units);
|
|
|
|
|
|
|
|
|
|
|
|
let _new_id = db::inventory_item::add_inventory_item(&db, &form_data.name, form_data.reorder_point,
|
|
|
|
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,
|
|
|
|
allow_fractional_units, &form_data.display_unit,
|
|
|
|
&form_data.pims_id, &form_data.vetcove_id,
|
|
|
|
&form_data.pims_id, &form_data.vetcove_id,
|
|
|
|
).await?;
|
|
|
|
).await?;
|
|
|
|
|
|
|
|
|
|
|
|
let mut template = validation.unwrap();
|
|
|
|
Ok(CreateItemFormData::base_template(&state).await?.into_response())
|
|
|
|
template.clear_inputs();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(template.into_response())
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[debug_handler]
|
|
|
|
#[debug_handler]
|
|
|
|
pub async fn create_item_form_get(
|
|
|
|
pub async fn create_item_form_get(
|
|
|
|
State(db): State<SqlitePool>,
|
|
|
|
State(state): State<AppState>,
|
|
|
|
) -> Result<Response, AppError> {
|
|
|
|
) -> Result<Response, AppError> {
|
|
|
|
|
|
|
|
Ok(CreateItemFormData::base_template(&state).await?.into_response())
|
|
|
|
let mut base = CreateItemFormData::base_template();
|
|
|
|
|
|
|
|
base.display_units = db::display_unit::get_display_units(&db).await?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(base.into_response())
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|