Allow batch adding items
This commit is contained in:
parent
693fe68797
commit
125627d7d2
|
@ -0,0 +1,68 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO items (name, parent, class, original_packaging, description)\n SELECT * FROM UNNEST($1::VARCHAR[], $2::UUID[], $3::UUID[], $4::UUID[], $5::VARCHAR[])\n RETURNING *",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "parent",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "class",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "short_id",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "original_packaging",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "description",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"VarcharArray",
|
||||
"UuidArray",
|
||||
"UuidArray",
|
||||
"UuidArray",
|
||||
"VarcharArray"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "b54d323092a1dc2e34d3882a06b3cd119362d0baf5effbbd09f969ee31f385ef"
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use actix_identity::Identity;
|
||||
use actix_web::{error, get, post, web, Responder};
|
||||
use actix_web::{error, get, post, web, HttpRequest, Responder};
|
||||
use maud::html;
|
||||
use serde::Deserialize;
|
||||
use sqlx::PgPool;
|
||||
|
@ -249,8 +249,14 @@ async fn list(pool: web::Data<PgPool>, user: Identity) -> actix_web::Result<impl
|
|||
))
|
||||
}
|
||||
|
||||
fn default_quantity() -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct NewItemForm {
|
||||
#[serde(default = "default_quantity")]
|
||||
pub quantity: usize,
|
||||
pub name: Option<String>,
|
||||
pub parent: Option<Uuid>,
|
||||
pub class: Uuid,
|
||||
|
@ -260,6 +266,7 @@ pub struct NewItemForm {
|
|||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct NewItemFormPrefilled {
|
||||
pub quantity: Option<usize>,
|
||||
pub name: Option<String>,
|
||||
pub parent: Option<Uuid>,
|
||||
pub class: Option<Uuid>,
|
||||
|
@ -336,7 +343,10 @@ async fn add_form(
|
|||
..Default::default()
|
||||
})
|
||||
|
||||
button .btn.btn-primary type="submit" { "Add" }
|
||||
div .input-group {
|
||||
button .btn.btn-primary type="submit" { "Add" }
|
||||
input .form-control.flex-grow-0.w-auto #quantity name="quantity" type="number" value=(form.quantity.unwrap_or(default_quantity())) min="1";
|
||||
}
|
||||
}
|
||||
},
|
||||
))
|
||||
|
@ -344,24 +354,59 @@ async fn add_form(
|
|||
|
||||
#[post("/items/add")]
|
||||
async fn add_post(
|
||||
req: HttpRequest,
|
||||
data: web::Form<NewItemForm>,
|
||||
pool: web::Data<PgPool>,
|
||||
_user: Identity,
|
||||
user: Identity,
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let data = data.into_inner();
|
||||
let item = manage::item::add(
|
||||
&pool,
|
||||
NewItem {
|
||||
name: data.name,
|
||||
class: data.class,
|
||||
parent: data.parent,
|
||||
original_packaging: data.original_packaging,
|
||||
description: data.description,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
Ok(web::Redirect::to("/item/".to_owned() + &item.id.to_string()).see_other())
|
||||
let new_item = NewItem {
|
||||
name: data.name,
|
||||
class: data.class,
|
||||
parent: data.parent,
|
||||
original_packaging: data.original_packaging,
|
||||
description: data.description,
|
||||
};
|
||||
if data.quantity == 1 {
|
||||
let item = manage::item::add(&pool, new_item)
|
||||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
Ok(
|
||||
web::Redirect::to("/item/".to_owned() + &item.id.to_string())
|
||||
.see_other()
|
||||
.respond_to(&req)
|
||||
.map_into_boxed_body(),
|
||||
)
|
||||
} else {
|
||||
let items = manage::item::add_multiple(&pool, new_item, data.quantity)
|
||||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
Ok(templates::base(
|
||||
TemplateConfig {
|
||||
path: "/items/add",
|
||||
title: Some("Added Items"),
|
||||
page_title: Some(Box::new("Added Items")),
|
||||
page_actions: vec![PageActionGroup::generate_labels(
|
||||
&items.iter().collect::<Vec<&Item>>(),
|
||||
)],
|
||||
user: Some(user),
|
||||
..Default::default()
|
||||
},
|
||||
html! {
|
||||
ul {
|
||||
@for item in items {
|
||||
li {
|
||||
a href={ "/item/" (item.id) } { (item.id) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a href="/items" { "Back to all items" }
|
||||
},
|
||||
)
|
||||
.respond_to(&req)
|
||||
.map_into_boxed_body())
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/item/{id}/edit")]
|
||||
|
|
|
@ -23,6 +23,26 @@ pub async fn add(pool: &PgPool, new_item: NewItem) -> Result<Item, sqlx::Error>
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn add_multiple(
|
||||
pool: &PgPool,
|
||||
new_item: NewItem,
|
||||
quantity: usize,
|
||||
) -> Result<Vec<Item>, sqlx::Error> {
|
||||
query_as!(
|
||||
Item,
|
||||
r#"INSERT INTO items (name, parent, class, original_packaging, description)
|
||||
SELECT * FROM UNNEST($1::VARCHAR[], $2::UUID[], $3::UUID[], $4::UUID[], $5::VARCHAR[])
|
||||
RETURNING *"#,
|
||||
&vec![new_item.name; quantity] as &[Option<String>],
|
||||
&vec![new_item.parent; quantity] as &[Option<Uuid>],
|
||||
&vec![new_item.class; quantity],
|
||||
&vec![new_item.original_packaging; quantity] as &[Option<Uuid>],
|
||||
&vec![new_item.description; quantity]
|
||||
)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get(pool: &PgPool, id: Uuid) -> Result<Item, sqlx::Error> {
|
||||
query_as!(Item, "SELECT * FROM items WHERE id = $1", id)
|
||||
.fetch_one(pool)
|
||||
|
|
Loading…
Reference in a new issue