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 warp::{Rejection, Reply};
|
||||||
|
|
||||||
use super::models::{
|
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::problem::{reject_anyhow, unauthorized_no_api_key, unauthorized_no_owner};
|
||||||
use super::Environment;
|
use super::Environment;
|
||||||
@ -608,3 +609,42 @@ pub async fn get_merchandise_list_by_shop_id(
|
|||||||
})
|
})
|
||||||
.await
|
.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 caches::Caches;
|
||||||
use models::interior_ref_list::InteriorRefList;
|
use models::interior_ref_list::InteriorRefList;
|
||||||
use models::merchandise_list::MerchandiseList;
|
use models::merchandise_list::{MerchandiseList, MerchandiseParams};
|
||||||
use models::owner::Owner;
|
use models::owner::Owner;
|
||||||
use models::shop::Shop;
|
use models::shop::Shop;
|
||||||
use models::ListParams;
|
use models::ListParams;
|
||||||
@ -292,6 +292,16 @@ async fn main() -> Result<()> {
|
|||||||
.and(with_env(env.clone()))
|
.and(with_env(env.clone()))
|
||||||
.and_then(handlers::get_merchandise_list_by_shop_id),
|
.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")
|
let routes = warp::path("v1")
|
||||||
.and(balanced_or_tree!(
|
.and(balanced_or_tree!(
|
||||||
@ -310,6 +320,7 @@ async fn main() -> Result<()> {
|
|||||||
get_merchandise_list_by_shop_id_handler,
|
get_merchandise_list_by_shop_id_handler,
|
||||||
update_interior_ref_list_by_shop_id_handler,
|
update_interior_ref_list_by_shop_id_handler,
|
||||||
update_merchandise_list_by_shop_id_handler,
|
update_merchandise_list_by_shop_id_handler,
|
||||||
|
buy_merchandise_handler,
|
||||||
get_interior_ref_list_handler,
|
get_interior_ref_list_handler,
|
||||||
delete_interior_ref_list_handler,
|
delete_interior_ref_list_handler,
|
||||||
update_interior_ref_list_handler,
|
update_interior_ref_list_handler,
|
||||||
|
@ -2,6 +2,7 @@ use anyhow::{Error, Result};
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::json;
|
||||||
use sqlx::postgres::PgPool;
|
use sqlx::postgres::PgPool;
|
||||||
use sqlx::types::Json;
|
use sqlx::types::Json;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@ -36,6 +37,13 @@ pub struct MerchandiseList {
|
|||||||
pub updated_at: Option<NaiveDateTime>,
|
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]
|
#[async_trait]
|
||||||
impl Model for MerchandiseList {
|
impl Model for MerchandiseList {
|
||||||
fn resource_name() -> &'static str {
|
fn resource_name() -> &'static str {
|
||||||
@ -185,4 +193,48 @@ impl MerchandiseList {
|
|||||||
return Err(forbidden_permission());
|
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 mod shop;
|
||||||
|
|
||||||
pub use interior_ref_list::InteriorRefList;
|
pub use interior_ref_list::InteriorRefList;
|
||||||
|
pub use merchandise_list::{MerchandiseList, MerchandiseParams};
|
||||||
pub use model::{Model, UpdateableModel};
|
pub use model::{Model, UpdateableModel};
|
||||||
pub use owner::Owner;
|
pub use owner::Owner;
|
||||||
pub use shop::Shop;
|
pub use shop::Shop;
|
||||||
pub use merchandise_list::MerchandiseList;
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Deserialize)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone, Deserialize)]
|
||||||
pub enum Order {
|
pub enum Order {
|
||||||
|
Loading…
Reference in New Issue
Block a user