parent
74342dcc82
commit
5fd8e249b1
@ -0,0 +1,206 @@
|
||||
use serde::Serialize;
|
||||
use anyhow::Result;
|
||||
use chrono::{DateTime, Utc};
|
||||
use sqlx::SqlitePool;
|
||||
use tracing::error;
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(sqlx::FromRow)]
|
||||
pub struct DbAdjustment {
|
||||
pub id: i64,
|
||||
pub item: i64,
|
||||
pub user: i64,
|
||||
pub create_date: DateTime<Utc>,
|
||||
pub target_date: DateTime<Utc>,
|
||||
pub amount: f64,
|
||||
pub unit_price: Option<i64>,
|
||||
#[sqlx(try_from = "i64")]
|
||||
pub reason: DbAdjustmentReason,
|
||||
}
|
||||
|
||||
|
||||
pub async fn add_new_stock_adjustment(db: &SqlitePool, item: i64, user: i64,
|
||||
create_date: DateTime<Utc>, target_date: DateTime<Utc>,
|
||||
amount: f64, unit_price: i64)
|
||||
-> Result<i64> {
|
||||
let reason: i64 = DbAdjustmentReason::NewStock.into();
|
||||
let res = sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO Adjustment (
|
||||
item,
|
||||
user,
|
||||
create_date,
|
||||
target_date,
|
||||
amount,
|
||||
reason,
|
||||
unit_price)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
"#,
|
||||
item, user, create_date, target_date, amount, reason, unit_price
|
||||
).execute(db).await?;
|
||||
|
||||
let new_id = res.last_insert_rowid();
|
||||
|
||||
Ok(new_id)
|
||||
}
|
||||
|
||||
pub async fn get_adjustments_target_date_range(
|
||||
db: &SqlitePool, start_date: DateTime<Utc>, end_date: DateTime<Utc>
|
||||
) -> Result<Vec<DbAdjustment>> {
|
||||
|
||||
sqlx::query_as::<_, DbAdjustment>(r#"
|
||||
SELECT id, item, user,
|
||||
create_date,
|
||||
target_date,
|
||||
amount,
|
||||
reason,
|
||||
unit_price
|
||||
FROM Adjustment
|
||||
WHERE target_date >= ? AND target_date <= ?
|
||||
"#,)
|
||||
.bind(start_date)
|
||||
.bind(end_date)
|
||||
.fetch_all(db)
|
||||
.await.map_err(Into::into)
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(sqlx::FromRow)]
|
||||
pub struct DbAdjustmentWithUserAndItem {
|
||||
pub id: i64,
|
||||
pub item: i64,
|
||||
pub item_name: String,
|
||||
pub item_unit: String,
|
||||
pub item_unit_abbreviation: String,
|
||||
pub user: i64,
|
||||
pub user_name: String,
|
||||
pub create_date: DateTime<Utc>,
|
||||
pub target_date: DateTime<Utc>,
|
||||
pub amount: f64,
|
||||
pub unit_price: Option<i64>,
|
||||
#[sqlx(try_from = "i64")]
|
||||
pub reason: DbAdjustmentReason,
|
||||
}
|
||||
|
||||
impl DbAdjustmentWithUserAndItem {
|
||||
pub async fn query_by_date_range(db: &SqlitePool,
|
||||
start_date: DateTime<Utc>,
|
||||
end_date: DateTime<Utc>,
|
||||
page_size: i64,
|
||||
page_num: i64) -> Result<Vec<Self>> {
|
||||
let offset = page_size * page_num;
|
||||
|
||||
sqlx::query_as::<_, DbAdjustmentWithUserAndItem>(r#"
|
||||
SELECT
|
||||
adj.id as id,
|
||||
adj.item as item,
|
||||
item.name as item_name,
|
||||
unit.unit as item_unit,
|
||||
unit.abbreviation as item_unit_abbreviation,
|
||||
adj.user as user,
|
||||
user.name as user_name,
|
||||
adj.create_date as create_date,
|
||||
adj.target_date as target_date,
|
||||
adj.amount as amount,
|
||||
adj.unit_price as unit_price,
|
||||
adj.reason as reason
|
||||
FROM Adjustment as adj
|
||||
JOIN User as user on adj.user = user.id
|
||||
JOIN InventoryItem as item on adj.item = item.id
|
||||
JOIN DisplayUnit as unit on item.display_unit = unit.id
|
||||
WHERE adj.target_date >= ? AND adj.target_date <= ?
|
||||
LIMIT ? OFFSET ?
|
||||
"#,)
|
||||
.bind(start_date)
|
||||
.bind(end_date)
|
||||
.bind(page_size)
|
||||
.bind(offset)
|
||||
.fetch_all(db)
|
||||
.await.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<DbAdjustment> for DbAdjustmentWithUserAndItem {
|
||||
fn into(self) -> DbAdjustment {
|
||||
DbAdjustment {
|
||||
id: self.id,
|
||||
item: self.item,
|
||||
user: self.user,
|
||||
create_date: self.create_date,
|
||||
target_date: self.target_date,
|
||||
amount: self.amount,
|
||||
unit_price: self.unit_price,
|
||||
reason: self.reason,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize)]
|
||||
pub enum DbAdjustmentReason {
|
||||
Unknown,
|
||||
Sale,
|
||||
Destruction,
|
||||
Expiration,
|
||||
Theft,
|
||||
NewStock,
|
||||
}
|
||||
|
||||
impl Into<i64> for DbAdjustmentReason {
|
||||
fn into(self) -> i64 {
|
||||
match self {
|
||||
Self::Unknown => 0,
|
||||
Self::Sale => 10,
|
||||
Self::Destruction => 20,
|
||||
Self::Expiration => 25,
|
||||
Self::Theft => 30,
|
||||
Self::NewStock => 50,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for DbAdjustmentReason {
|
||||
fn from(item: i64) -> Self {
|
||||
match item {
|
||||
0 => Self::Unknown,
|
||||
10 => Self::Sale,
|
||||
20 => Self::Destruction,
|
||||
25 => Self::Expiration,
|
||||
30 => Self::Theft,
|
||||
50 => Self::NewStock,
|
||||
_ => {
|
||||
error!("unknown negative adjustment reason value: {}", item);
|
||||
Self::Unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for DbAdjustmentReason {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
|
||||
match value {
|
||||
"unknown" => Ok(Self::Unknown),
|
||||
"sale" => Ok(Self::Sale),
|
||||
"destruction" => Ok(Self::Destruction),
|
||||
"expiration" => Ok(Self::Expiration),
|
||||
"theft" => Ok(Self::Theft),
|
||||
"new-stock" => Ok(Self::NewStock),
|
||||
_ => Err(anyhow::anyhow!("unknown negative adjustment reason"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for DbAdjustmentReason {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
Self::Unknown => { String::from("unknown") }
|
||||
Self::Sale => { String::from("sale") }
|
||||
Self::Destruction => { String::from("destruction") }
|
||||
Self::Expiration => { String::from("expiration") }
|
||||
Self::Theft => { String::from("theft") }
|
||||
Self::NewStock => { String::from("new-stock") }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
use serde::Serialize;
|
||||
use sqlx::SqlitePool;
|
||||
use anyhow::Result;
|
||||
use chrono::{DateTime, Utc};
|
||||
use tracing::error;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[derive(sqlx::FromRow)]
|
||||
pub struct DbNegativeAdjustment {
|
||||
pub id: i64,
|
||||
pub item: i64,
|
||||
pub user: i64,
|
||||
pub create_date: i64,
|
||||
pub target_date: i64,
|
||||
pub amount: f64,
|
||||
pub reason: DbNegativeAdjustmentReason,
|
||||
}
|
||||
|
||||
pub async fn add_negative_adjustment(db: &SqlitePool, item: i64, user: i64,
|
||||
create_date: DateTime<Utc>, target_date: DateTime<Utc>,
|
||||
amount: f64, reason: DbNegativeAdjustmentReason) -> Result<i64> {
|
||||
let reason: i64 = reason.into();
|
||||
let res = sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO NegativeAdjustment (item, user, create_date, target_date, amount, reason)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
"#,
|
||||
item, user, create_date, target_date, amount, reason
|
||||
).execute(db).await?;
|
||||
|
||||
let new_id = res.last_insert_rowid();
|
||||
|
||||
Ok(new_id)
|
||||
}
|
||||
|
||||
pub async fn get_negative_adjustments_target_date_range(
|
||||
db: &SqlitePool, start_date: DateTime<Utc>, end_date: DateTime<Utc>
|
||||
) -> Result<Vec<DbNegativeAdjustment>> {
|
||||
sqlx::query_as!(
|
||||
DbNegativeAdjustment,
|
||||
r#"
|
||||
SELECT id, item, user, create_date, target_date, amount, reason
|
||||
FROM NegativeAdjustment
|
||||
WHERE target_date >= ? AND target_date <= ?
|
||||
"#,
|
||||
start_date, end_date
|
||||
)
|
||||
.fetch_all(db)
|
||||
.await.map_err(Into::into)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize)]
|
||||
pub enum DbNegativeAdjustmentReason {
|
||||
Unknown,
|
||||
Sale,
|
||||
Destruction,
|
||||
Expiration,
|
||||
Theft,
|
||||
}
|
||||
|
||||
impl Into<i64> for DbNegativeAdjustmentReason {
|
||||
fn into(self) -> i64 {
|
||||
match self {
|
||||
Self::Unknown => 0,
|
||||
Self::Sale => 10,
|
||||
Self::Destruction => 20,
|
||||
Self::Expiration => 25,
|
||||
Self::Theft => 30,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for DbNegativeAdjustmentReason {
|
||||
fn from(item: i64) -> Self {
|
||||
match item {
|
||||
0 => Self::Unknown,
|
||||
10 => Self::Sale,
|
||||
20 => Self::Destruction,
|
||||
25 => Self::Expiration,
|
||||
30 => Self::Theft,
|
||||
_ => {
|
||||
error!("unknown negative adjustment reason value: {}", item);
|
||||
Self::Unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for DbNegativeAdjustmentReason {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
|
||||
match value {
|
||||
"unknown" => Ok(Self::Unknown),
|
||||
"sale" => Ok(Self::Sale),
|
||||
"destruction" => Ok(Self::Destruction),
|
||||
"expiration" => Ok(Self::Expiration),
|
||||
"theft" => Ok(Self::Theft),
|
||||
_ => Err(anyhow::anyhow!("unknown negative adjustment reason"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for DbNegativeAdjustmentReason {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
Self::Unknown => { String::from("unknown") }
|
||||
Self::Sale => { String::from("sale") }
|
||||
Self::Destruction => { String::from("destruction") }
|
||||
Self::Expiration => { String::from("expiration") }
|
||||
Self::Theft => { String::from("theft") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
use serde::Serialize;
|
||||
use anyhow::Result;
|
||||
use chrono::{DateTime, Utc};
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[derive(sqlx::FromRow)]
|
||||
pub struct DbPositiveAdjustment {
|
||||
pub id: i64,
|
||||
pub item: i64,
|
||||
pub user: i64,
|
||||
pub create_date: DateTime<Utc>,
|
||||
pub target_date: DateTime<Utc>,
|
||||
pub amount: f64,
|
||||
pub unit_price: i64,
|
||||
}
|
||||
|
||||
pub async fn add_positive_adjustment(db: &SqlitePool, item: i64, user: i64,
|
||||
create_date: DateTime<Utc>, target_date: DateTime<Utc>,
|
||||
amount: f64, unit_price: i64)
|
||||
-> Result<i64> {
|
||||
let res = sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO PositiveAdjustment (item, user, create_date, target_date, amount, unit_price)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
"#,
|
||||
item, user, create_date, target_date, amount, unit_price
|
||||
).execute(db).await?;
|
||||
|
||||
let new_id = res.last_insert_rowid();
|
||||
|
||||
Ok(new_id)
|
||||
}
|
||||
|
||||
pub async fn get_positive_adjustments_target_date_range(
|
||||
db: &SqlitePool, start_date: DateTime<Utc>, end_date: DateTime<Utc>
|
||||
) -> Result<Vec<DbPositiveAdjustment>> {
|
||||
|
||||
sqlx::query_as::<_, DbPositiveAdjustment>(r#"
|
||||
SELECT id, item, user,
|
||||
create_date,
|
||||
target_date,
|
||||
amount, unit_price
|
||||
FROM PositiveAdjustment
|
||||
WHERE target_date >= ? AND target_date <= ?
|
||||
"#,)
|
||||
.bind(start_date)
|
||||
.bind(end_date)
|
||||
.fetch_all(db)
|
||||
.await.map_err(Into::into)
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,18 @@
|
||||
|
||||
{% for item in items %}
|
||||
<article id="item-{{item.id}}-card">
|
||||
<article>
|
||||
<div class="grid">
|
||||
<p>{{ item.item }}</p>
|
||||
<p>{{ item.amount }}</p>
|
||||
<p>{{ item.create_date }}</p>
|
||||
<p>{{ item.item_name }}</p>
|
||||
<p>{{ item.user_name }}</p>
|
||||
<p>
|
||||
{% match item.item_type %}
|
||||
{% when HistoryItemEntry::PositiveAdjustment with (entry) %}
|
||||
{{ entry.amount }} @ {{ entry.unit_value }}
|
||||
{% when HistoryItemEntry::NegativeAdjustment with (entry) %}
|
||||
{{ entry.amount }} {{ entry.reason }}
|
||||
{% endmatch %}
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
Loading…
Reference in new issue