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 %}
|
{% for item in items %}
|
||||||
<article id="item-{{item.id}}-card">
|
<article>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<p>{{ item.item }}</p>
|
<p>{{ item.create_date }}</p>
|
||||||
<p>{{ item.amount }}</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>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
Loading…
Reference in new issue