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/history.rs

163 lines
4.9 KiB

use crate::app::common::query_args::datetime_range::DatetimeRangeQueryArgs;
use crate::db::adjustment::{get_adjustments_target_date_range, DbAdjustment, DbAdjustmentWithUserAndItem};
use crate::error::{AppError, QueryExtractor};
use crate::session::SessionUser;
use crate::util::time::{tz_offset_to_string, LocalTimestampRange, UtcTimestampRange};
use anyhow::Result;
use askama::Template;
use askama_axum::{IntoResponse, Response};
use axum::extract::State;
use axum_htmx::HxRequest;
use chrono::prelude::*;
use serde::Deserialize;
use sqlx::SqlitePool;
use tracing::info;
use crate::util::currency;
#[derive(Template)]
#[template(path = "history.html")]
struct HistoryLogTemplate {
items: Vec<HistoryDisplayItem>,
start_date: String,
start_time: String,
end_date: String,
end_time: String,
time_zone: String,
}
#[derive(Template)]
#[template(path = "history_item_fragment.html")]
struct HistoryLogItemFragmentTemplate {
items: Vec<HistoryDisplayItem>
}
#[derive(Clone, Debug)]
struct HistoryDisplayItem {
pub create_date: String,
pub target_date: String,
pub user_name: String,
pub item_name: String,
pub item_unit: String,
pub item_unit_abbreviation: String,
pub item_type: HistoryItemEntry,
}
#[derive(Clone, Debug)]
struct PositiveAdjustmentDisplayItem {
pub amount: String,
pub unit_value: String,
}
impl From<DbAdjustment> for PositiveAdjustmentDisplayItem {
fn from(adjustment: DbAdjustment) -> Self {
Self {
amount: format!("{}", adjustment.amount),
unit_value: currency::int_cents_to_dollars_string(adjustment.unit_price.unwrap_or_default()),
}
}
}
#[derive(Clone, Debug)]
struct NegativeAdjustmentDisplayItem {
pub amount: String,
pub reason: String,
}
impl From<DbAdjustment> for NegativeAdjustmentDisplayItem {
fn from(adjustment: DbAdjustment) -> Self {
Self {
amount: format!("{}", adjustment.amount),
reason: adjustment.reason.into(),
}
}
}
#[derive(Clone, Debug)]
enum HistoryItemEntry {
PositiveAdjustment(PositiveAdjustmentDisplayItem),
NegativeAdjustment(NegativeAdjustmentDisplayItem),
}
impl HistoryDisplayItem {
pub fn from_adjustment(db_entry: DbAdjustmentWithUserAndItem, tz_offset: i32)
-> Result<Self> {
let simple_entry: DbAdjustment = db_entry.clone().into();
let timezone = FixedOffset::east_opt(tz_offset)
.ok_or(anyhow::anyhow!("Invalid timezone"))?;
let create_date = db_entry.create_date.with_timezone(&timezone)
.format("%Y-%m-%d %l:%M:%S %p").to_string();
let target_date = db_entry.target_date.with_timezone(&timezone)
.format("%Y-%m-%d %l:%M:%S %p").to_string();
let item_type = if simple_entry.amount > 0.0 {
HistoryItemEntry::PositiveAdjustment(simple_entry.into())
} else {
HistoryItemEntry::NegativeAdjustment(simple_entry.into())
};
Ok(Self {
create_date,
target_date,
user_name: db_entry.user_name,
item_name: db_entry.item_name,
item_unit: db_entry.item_unit,
item_unit_abbreviation: db_entry.item_unit_abbreviation,
item_type
})
}
}
pub async fn history_log_handler(
QueryExtractor(mut query): QueryExtractor<DatetimeRangeQueryArgs>,
HxRequest(hx_request): HxRequest,
State(db): State<SqlitePool>,
user: SessionUser
) -> Result<Response, AppError> {
info!("Query: {:?}", query);
let today = Local::now().naive_local().date();
let _ = query.time_zone_offset.get_or_insert(user.tz_offset);
let _ = query.end_date.get_or_insert(today.to_string());
let local_range: LocalTimestampRange = query.try_into()?;
let utc_range: UtcTimestampRange = local_range.into();
let tz_offset = local_range.start.timezone().local_minus_utc();
info!("Get items from: {} to {}", utc_range.start, utc_range.end);
let items = DbAdjustmentWithUserAndItem::query_by_date_range(
&db, utc_range.start, utc_range.end, 1000, 0)
.await?
.into_iter()
.map(|x| {
HistoryDisplayItem::from_adjustment(x, tz_offset)
})
.collect::<Result<Vec<HistoryDisplayItem>>>()?;
info!("Item count: {}", items.len());
if hx_request {
Ok(HistoryLogItemFragmentTemplate {items}.into_response())
}
else {
let time_zone = tz_offset_to_string(tz_offset);
let start_date = local_range.start.naive_local().date().to_string();
let start_time = local_range.start.naive_local().time().to_string();
let end_date = local_range.end.naive_local().date().to_string();
let end_time = local_range.end.naive_local().time().to_string();
Ok(HistoryLogTemplate {
items,
start_date,
start_time,
end_date,
end_time,
time_zone,
}.into_response())
}
}

Powered by TurnKey Linux.