use chrono::NaiveDateTime; use derive_more::Deref; use serde::{Deserialize, Serialize}; use crate::v2::{CategoryId, CategoryKey, CategoryName, CategorySvg, DetailedProduct}; use crate::*; #[derive(Serialize, Deserialize, Debug)] pub struct Failure { pub errors: Vec, } #[derive(Serialize, Deserialize, Debug, Default)] pub struct Config { pub pay_methods: Vec, pub coupons: bool, pub currency: String, pub shipping: bool, pub shipping_methods: Vec, } #[derive(Serialize, Deserialize, Debug)] pub struct Account { pub id: AccountId, pub email: Email, pub login: Login, pub role: Role, pub customer_id: uuid::Uuid, pub state: AccountState, pub addresses: Vec, } impl From<(FullAccount, Vec)> for Account { fn from( ( FullAccount { id, email, login, pass_hash: _, role, customer_id, state, }, addresses, ): (FullAccount, Vec), ) -> Self { Self { id, email, login, role, customer_id, state, addresses: addresses.into_iter().map(From::from).collect(), } } } #[derive(Serialize, Deserialize, Debug)] pub struct AccountAddress { pub id: AddressId, pub name: Name, pub email: Email, pub phone: Phone, pub street: Street, pub city: City, pub country: Country, pub zip: Zip, pub account_id: AccountId, pub is_default: bool, } impl From for AccountAddress { fn from( crate::AccountAddress { id, name, email, phone, street, city, country, zip, account_id, is_default, }: crate::AccountAddress, ) -> Self { Self { id, name, email, phone, street, city, country, zip, account_id, is_default, } } } #[derive(Serialize, Deserialize, Debug)] #[serde(transparent)] pub struct Orders(pub Vec); impl From<(Vec, Vec)> for Orders { fn from((orders, mut items): (Vec, Vec)) -> Self { Self( orders .into_iter() .map( |crate::Order { id, buyer_id, status, order_ext_id: _, service_order_id: _, checkout_notes, address_id, }| { Order { id, buyer_id, status, items: items.drain_filter(|item| item.order_id == id).collect(), checkout_notes, address_id, } }, ) .collect(), ) } } impl From<(crate::Order, Vec)> for Order { fn from( ( crate::Order { id, buyer_id, status, order_ext_id: _, service_order_id: _, checkout_notes, address_id, }, mut items, ): (crate::Order, Vec), ) -> Self { Order { id, buyer_id, status, items: items.drain_filter(|item| item.order_id == id).collect(), checkout_notes, address_id, } } } #[derive(Serialize, Deserialize, Debug)] pub struct Order { pub id: crate::OrderId, pub buyer_id: Option, pub status: crate::OrderStatus, pub items: Vec, pub checkout_notes: Option, pub address_id: OrderAddressId, } #[derive(Serialize, Deserialize, Debug)] pub struct ShoppingCartItem { pub id: ShoppingCartItemId, pub product_variant_id: ProductVariantId, pub product_id: ProductId, pub shopping_cart_id: ShoppingCartId, pub quantity: Quantity, pub quantity_unit: QuantityUnit, } impl From for ShoppingCartItem { fn from( crate::ShoppingCartItem { id, product_variant_id, product_id, shopping_cart_id, quantity, quantity_unit, }: crate::ShoppingCartItem, ) -> Self { Self { id, product_variant_id, product_id, shopping_cart_id, quantity, quantity_unit, } } } #[derive(Serialize, Deserialize, Debug)] pub struct ShoppingCart { pub id: ShoppingCartId, pub buyer_id: AccountId, pub payment_method: PaymentMethod, pub state: ShoppingCartState, pub items: Vec, pub checkout_notes: String, } impl From<(crate::ShoppingCart, Vec)> for ShoppingCart { fn from( ( crate::ShoppingCart { id, buyer_id, payment_method, state, checkout_notes, }, items, ): (crate::ShoppingCart, Vec), ) -> Self { Self { id, buyer_id, payment_method, state, checkout_notes: checkout_notes.unwrap_or_default(), items: items .into_iter() .map( |crate::ShoppingCartItem { id, product_variant_id, product_id, shopping_cart_id, quantity, quantity_unit, }| ShoppingCartItem { id, product_id, product_variant_id, shopping_cart_id, quantity, quantity_unit, }, ) .collect(), } } } #[derive(Debug, Hash, PartialEq, Serialize, Deserialize)] pub struct Photo { pub id: PhotoId, pub file_name: FileName, pub url: String, pub unique_name: UniqueName, } #[derive(Clone, Debug, Hash, PartialOrd, PartialEq, Eq, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] pub struct Category { pub id: CategoryId, pub parent_id: Option, pub name: CategoryName, pub key: CategoryKey, pub svg: CategorySvg, } impl From<&crate::Category> for Category { fn from(&crate::Category { name, key, svg }: &crate::Category) -> Self { Self { id: Default::default(), parent_id: None, name: CategoryName::from(name), key: CategoryKey::from(key), svg: CategorySvg::from(svg), } } } #[derive(Serialize, Deserialize, Debug, Hash)] pub struct Product { pub id: ProductId, pub name: ProductName, pub short_description: ProductShortDesc, pub long_description: ProductLongDesc, pub category: Option, pub price: Price, pub available: bool, pub quantity_unit: QuantityUnit, pub deliver_days_flag: Days, pub photos: Vec, } impl<'path> From<( crate::Product, &mut Vec, &mut Vec, &'path str, )> for Product { fn from( ( crate::Product { id, name, short_description, long_description, category, price, deliver_days_flag, }, photos, product_stocks, public_path, ): ( crate::Product, &mut Vec, &mut Vec, &'path str, ), ) -> Self { let pos = product_stocks .iter() .position(|stock| stock.product_id == id); let (available, quantity_unit) = pos .map(|idx| product_stocks.remove(idx)) .map(|stock| (**stock.quantity > 0, stock.quantity_unit)) .unwrap_or_else(|| (false, QuantityUnit::Piece)); Self { id, name, short_description, long_description, category: category.and_then(CategoryMapper::api_from_product_category), price, available, quantity_unit, deliver_days_flag, photos: photos .drain_filter(|photo| photo.product_id == id) .map( |ProductLinkedPhoto { photo_id: id, local_path: _, file_name, product_id: _, unique_name, }| Photo { id, url: format!("{}/{}", public_path, unique_name.as_str()), unique_name, file_name, }, ) .collect(), } } } #[derive(Serialize, Deserialize, Debug, Deref)] #[serde(transparent)] pub struct Products(pub Vec); // impl // From<( // Vec, // Vec, // Vec, // String, // )> for Products // { // fn from( // (products, mut photos, mut products_stock, public_path): ( // Vec, // Vec, // Vec, // String, // ), // ) -> Self { // Self( // products // .into_iter() // .map(|p| (p, &mut photos, &mut products_stock, // public_path.as_str()).into()) .collect(), // ) // } // } #[derive(Serialize, Deserialize, Debug)] pub struct SignInInput { pub login: Login, pub password: Password, } #[derive(Serialize, Deserialize, Debug)] pub struct SessionOutput { pub access_token: AccessTokenString, pub refresh_token: RefreshTokenString, pub exp: NaiveDateTime, pub role: Role, } #[derive(Serialize, Deserialize, Debug)] pub struct CreateAccountInput { pub email: Email, pub login: Login, pub password: Password, } #[derive(Serialize, Deserialize, Debug)] pub enum OrderAddressInput { Address(CreateOrderAddress), AccountAddress(AddressId), DefaultAccountAddress, } #[derive(Serialize, Deserialize, Debug)] pub struct CreateOrderInput { /// Required customer e-mail pub email: String, /// Required customer phone number pub phone: String, /// Required customer first name pub first_name: String, /// Required customer last name pub last_name: String, /// Required customer language pub language: String, /// User currency pub currency: String, pub address: OrderAddressInput, pub payment_method: PaymentMethod, } #[derive(Serialize, Deserialize, Debug)] pub struct DeleteItemInput { pub shopping_cart_item_id: ShoppingCartItemId, } #[derive(Serialize, Deserialize, Debug)] pub struct DeleteItemOutput { pub success: bool, } #[derive(Serialize, Deserialize, Debug)] pub struct UpdateItemInput { pub product_variant_id: ProductVariantId, pub product_id: ProductId, pub quantity: Quantity, pub quantity_unit: QuantityUnit, } #[derive(Serialize, Deserialize, Debug)] pub struct UpdateItemOutput { pub shopping_cart_item: ShoppingCartItem, } #[derive(Serialize, Deserialize, Debug)] pub struct UpdateCartInput { pub items: Vec, pub notes: String, pub payment_method: Option, } #[derive(Serialize, Deserialize, Debug)] pub struct UpdateCartOutput { pub cart_id: ShoppingCartId, pub items: Vec, pub checkout_notes: String, pub payment_method: PaymentMethod, } #[derive(Serialize, Deserialize, Debug)] pub struct SearchRequest { /// Match string pub q: String, pub lang: String, } #[derive(Serialize, Deserialize, Debug)] pub struct CreateOrderAddress { pub name: Name, pub email: Email, pub phone: Phone, pub street: Street, pub city: City, pub country: Country, pub zip: Zip, } #[derive(Serialize, Deserialize, Debug)] pub struct UpdateOrderAddress { pub id: OrderAddressId, pub name: Name, pub email: Email, pub street: Street, pub city: City, pub country: Country, pub zip: Zip, } #[derive(Serialize, Deserialize, Debug)] pub struct PlaceOrderResult { pub redirect_uri: String, pub order_id: OrderId, } pub mod admin { use serde::{Deserialize, Serialize}; use crate::*; #[derive(Deserialize, Serialize, Debug)] pub struct RegisterInput { pub login: Login, pub email: Email, pub password: Password, pub password_confirmation: PasswordConfirmation, pub role: Role, } #[derive(Serialize, Deserialize, Debug, Default)] pub struct RegisterResponse { pub errors: Vec, pub account: Option, } #[derive(Serialize, Deserialize, Debug)] pub enum RegisterError { PasswordDiffer, } #[derive(Serialize, Deserialize, Debug)] pub struct SignInInput { pub login: Option, pub email: Option, pub password: Password, } #[derive(Serialize, Deserialize, Debug)] pub struct LogoutResponse {} } pub mod v2 { use crate::api::{Category, Photo}; #[derive(Debug, Hash, serde::Serialize, serde::Deserialize)] pub struct ProductVariant { pub id: crate::ProductVariantId, pub product_id: crate::ProductId, pub name: crate::ProductName, pub short_description: crate::ProductShortDesc, pub long_description: crate::ProductLongDesc, pub category: Option, pub price: crate::Price, pub available: bool, pub quantity_unit: crate::QuantityUnit, pub deliver_days_flag: crate::Days, pub photos: Vec, } }