use crate::commands::{Command, RequestType}; use crate::context::Context; use crate::Result; use geoffrey_db::helper::load_location; use geoffrey_models::models::item::ItemListing; use geoffrey_models::models::locations::{Location, LocationDataDb, LocationDb, LocationType}; use geoffrey_models::models::parameters::add_item_params::AddItemParams; use geoffrey_models::models::player::Player; use geoffrey_models::models::response::api_error::GeoffreyAPIError; use geoffrey_models::models::CommandLevel; use std::sync::Arc; pub struct AddItem {} impl Command for AddItem { type Req = AddItemParams; type Resp = Location; fn command_name() -> String { "add_item".to_string() } fn request_type() -> RequestType { RequestType::POST } fn command_level() -> CommandLevel { CommandLevel::REGISTERED } fn validate_parameters(req: &Self::Req) -> Result<()> { if req.quantity == 0 { Err(GeoffreyAPIError::ParameterInvalid("quantity".to_string())) } else { Ok(()) } } fn run_command(ctx: Arc, req: &Self::Req, user: Option) -> Result { let user = user.unwrap(); let shops: Vec = ctx .db .filter(|_, loc: &LocationDb| { let loc_type: LocationType = loc.loc_data.clone().into(); loc_type == LocationType::Shop && loc.owners().contains(&user.id.unwrap()) && loc.name.to_lowercase().contains(&req.shop.to_lowercase()) })? .collect(); if shops.is_empty() { Err(GeoffreyAPIError::EntryNotFound) } else if shops.len() > 1 { Err(GeoffreyAPIError::MultipleLocationsMatch) } else { let mut shop = shops[0].clone(); if let LocationDataDb::Shop(shop_data) = &mut shop.loc_data { shop_data.item_listings.insert(ItemListing::new( &req.item_name, req.price, req.quantity, )); let shop = ctx.db.insert(shop)?; load_location(&ctx.db, &shop).map_err(|err| err.into()) } else { Err(GeoffreyAPIError::EntryNotFound) } } } }