Add buy_merchandise endpoint
Temporary for now, eventually this should actually create a transaction record. All it does now is update the merchandise quantity.
This commit is contained in:
parent
58583a553a
commit
e0bba0254c
@ -9,7 +9,8 @@ use warp::reply::{json, with_header, with_status};
|
||||
use warp::{Rejection, Reply};
|
||||
|
||||
use super::models::{
|
||||
InteriorRefList, ListParams, MerchandiseList, Model, Owner, Shop, UpdateableModel,
|
||||
InteriorRefList, ListParams, MerchandiseList, MerchandiseParams, Model, Owner, Shop,
|
||||
UpdateableModel,
|
||||
};
|
||||
use super::problem::{reject_anyhow, unauthorized_no_api_key, unauthorized_no_owner};
|
||||
use super::Environment;
|
||||
@ -608,3 +609,42 @@ pub async fn get_merchandise_list_by_shop_id(
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn buy_merchandise(
|
||||
shop_id: i32,
|
||||
merchandise_params: MerchandiseParams,
|
||||
api_key: Option<Uuid>,
|
||||
env: Environment,
|
||||
) -> Result<impl Reply, Rejection> {
|
||||
let owner_id = authenticate(&env, api_key).await.map_err(reject_anyhow)?;
|
||||
// TODO: create transaction
|
||||
let updated_merchandise_list = MerchandiseList::update_merchandise_quantity(
|
||||
&env.db,
|
||||
shop_id,
|
||||
&(merchandise_params.mod_name),
|
||||
merchandise_params.local_form_id,
|
||||
merchandise_params.quantity_delta,
|
||||
)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
let url = updated_merchandise_list
|
||||
.url(&env.api_url)
|
||||
.map_err(reject_anyhow)?;
|
||||
let reply = json(&updated_merchandise_list);
|
||||
let reply = with_header(reply, "Location", url.as_str());
|
||||
let reply = with_status(reply, StatusCode::CREATED);
|
||||
env.caches
|
||||
.merchandise_list
|
||||
.delete_response(
|
||||
updated_merchandise_list
|
||||
.id
|
||||
.expect("saved merchandise_list has no id"),
|
||||
)
|
||||
.await;
|
||||
env.caches
|
||||
.merchandise_list_by_shop_id
|
||||
.delete_response(updated_merchandise_list.shop_id)
|
||||
.await;
|
||||
env.caches.list_merchandise_lists.clear().await;
|
||||
Ok(reply)
|
||||
}
|
||||
|
13
src/main.rs
13
src/main.rs
@ -23,7 +23,7 @@ mod problem;
|
||||
|
||||
use caches::Caches;
|
||||
use models::interior_ref_list::InteriorRefList;
|
||||
use models::merchandise_list::MerchandiseList;
|
||||
use models::merchandise_list::{MerchandiseList, MerchandiseParams};
|
||||
use models::owner::Owner;
|
||||
use models::shop::Shop;
|
||||
use models::ListParams;
|
||||
@ -292,6 +292,16 @@ async fn main() -> Result<()> {
|
||||
.and(with_env(env.clone()))
|
||||
.and_then(handlers::get_merchandise_list_by_shop_id),
|
||||
);
|
||||
let buy_merchandise_handler = warp::path("shops").and(
|
||||
warp::path::param()
|
||||
.and(warp::path("merchandise_list"))
|
||||
.and(warp::path::end())
|
||||
.and(warp::post())
|
||||
.and(warp::query::<MerchandiseParams>())
|
||||
.and(warp::header::optional("api-key"))
|
||||
.and(with_env(env.clone()))
|
||||
.and_then(handlers::buy_merchandise),
|
||||
);
|
||||
|
||||
let routes = warp::path("v1")
|
||||
.and(balanced_or_tree!(
|
||||
@ -310,6 +320,7 @@ async fn main() -> Result<()> {
|
||||
get_merchandise_list_by_shop_id_handler,
|
||||
update_interior_ref_list_by_shop_id_handler,
|
||||
update_merchandise_list_by_shop_id_handler,
|
||||
buy_merchandise_handler,
|
||||
get_interior_ref_list_handler,
|
||||
delete_interior_ref_list_handler,
|
||||
update_interior_ref_list_handler,
|
||||
|
@ -2,6 +2,7 @@ use anyhow::{Error, Result};
|
||||
use async_trait::async_trait;
|
||||
use chrono::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use sqlx::postgres::PgPool;
|
||||
use sqlx::types::Json;
|
||||
use tracing::instrument;
|
||||
@ -36,6 +37,13 @@ pub struct MerchandiseList {
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Deserialize)]
|
||||
pub struct MerchandiseParams {
|
||||
pub mod_name: String,
|
||||
pub local_form_id: i32,
|
||||
pub quantity_delta: i32,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Model for MerchandiseList {
|
||||
fn resource_name() -> &'static str {
|
||||
@ -185,4 +193,48 @@ impl MerchandiseList {
|
||||
return Err(forbidden_permission());
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
pub async fn update_merchandise_quantity(
|
||||
db: &PgPool,
|
||||
shop_id: i32,
|
||||
mod_name: &str,
|
||||
local_form_id: i32,
|
||||
quantity_delta: i32,
|
||||
) -> Result<Self> {
|
||||
Ok(sqlx::query_as_unchecked!(
|
||||
Self,
|
||||
"UPDATE
|
||||
merchandise_lists
|
||||
SET
|
||||
form_list =
|
||||
jsonb_set(
|
||||
form_list,
|
||||
array[elem_index::text, 'quantity'],
|
||||
to_jsonb(quantity::int + $4),
|
||||
true
|
||||
)
|
||||
FROM (
|
||||
SELECT
|
||||
pos - 1 as elem_index,
|
||||
elem->>'quantity' as quantity
|
||||
FROM
|
||||
merchandise_lists,
|
||||
jsonb_array_elements(form_list) with ordinality arr(elem, pos)
|
||||
WHERE
|
||||
shop_id = $1 AND
|
||||
elem->>'mod_name' = $2::text AND
|
||||
elem->>'local_form_id' = $3::text
|
||||
) sub
|
||||
WHERE
|
||||
shop_id = $1
|
||||
RETURNING merchandise_lists.*",
|
||||
shop_id,
|
||||
mod_name,
|
||||
local_form_id,
|
||||
quantity_delta,
|
||||
)
|
||||
.fetch_one(db)
|
||||
.await?)
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ pub mod owner;
|
||||
pub mod shop;
|
||||
|
||||
pub use interior_ref_list::InteriorRefList;
|
||||
pub use merchandise_list::{MerchandiseList, MerchandiseParams};
|
||||
pub use model::{Model, UpdateableModel};
|
||||
pub use owner::Owner;
|
||||
pub use shop::Shop;
|
||||
pub use merchandise_list::MerchandiseList;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Deserialize)]
|
||||
pub enum Order {
|
||||
|
Loading…
Reference in New Issue
Block a user