2022-05-06 11:47:18 +02:00
|
|
|
#![feature(drain_filter)]
|
|
|
|
|
|
|
|
pub mod api;
|
|
|
|
|
2022-05-08 09:47:05 +02:00
|
|
|
pub mod encrypt;
|
|
|
|
|
2022-05-13 15:24:11 +02:00
|
|
|
use std::fmt::{Display, Formatter};
|
2022-05-16 16:08:14 +02:00
|
|
|
use std::ops;
|
2022-11-11 16:32:07 +01:00
|
|
|
use std::ops::{BitOr, Range};
|
2022-05-06 11:47:18 +02:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
2022-05-15 10:30:15 +02:00
|
|
|
use derive_more::{Deref, DerefMut, Display, From};
|
2022-05-06 11:47:18 +02:00
|
|
|
use serde::de::{Error, Visitor};
|
|
|
|
use serde::{Deserialize, Deserializer, Serialize};
|
|
|
|
|
2022-05-08 09:47:05 +02:00
|
|
|
pub use crate::encrypt::*;
|
2022-11-29 11:21:31 +01:00
|
|
|
use crate::v2::ProductVariantId;
|
2022-05-08 09:47:05 +02:00
|
|
|
|
2022-05-10 22:32:22 +02:00
|
|
|
#[derive(Debug, Hash, thiserror::Error)]
|
2022-05-06 11:47:18 +02:00
|
|
|
pub enum TransformError {
|
|
|
|
#[error("Given value is below minimal value")]
|
|
|
|
BelowMinimal,
|
|
|
|
#[error("Given value is not valid day flag")]
|
|
|
|
NotDay,
|
|
|
|
#[error("Given value is not valid email address")]
|
|
|
|
NotEmail,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type RecordId = i32;
|
|
|
|
|
2022-05-12 16:05:58 +02:00
|
|
|
macro_rules! category_svg {
|
|
|
|
($name: expr) => {
|
|
|
|
concat!("/svg/", $name, ".svg")
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-11-28 17:00:19 +01:00
|
|
|
pub struct CategoryMapper;
|
|
|
|
|
|
|
|
impl CategoryMapper {
|
|
|
|
pub fn db_into_api(
|
|
|
|
name: ProductCategory,
|
|
|
|
categories: &[crate::v2::Category],
|
|
|
|
) -> Option<crate::api::Category> {
|
|
|
|
categories
|
|
|
|
.iter()
|
|
|
|
.find(|category| category.name.as_str() == name.as_str())
|
|
|
|
.map(
|
|
|
|
|crate::v2::Category {
|
|
|
|
id,
|
|
|
|
parent_id,
|
|
|
|
name,
|
|
|
|
key,
|
|
|
|
svg,
|
|
|
|
}| crate::api::Category {
|
|
|
|
id: id.clone(),
|
|
|
|
parent_id: parent_id.clone(),
|
|
|
|
name: name.clone(),
|
|
|
|
key: key.clone(),
|
|
|
|
svg: svg.clone(),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2022-05-11 15:56:41 +02:00
|
|
|
|
2022-11-29 15:18:31 +01:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(rename_all = "snake_case"))]
|
|
|
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Default, Display, Deserialize, Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub enum OrderItemState {
|
|
|
|
#[default]
|
|
|
|
#[display(fmt = "Poprawny")]
|
|
|
|
Valid,
|
|
|
|
#[display(fmt = "Niedostępny")]
|
|
|
|
OutOfStock,
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(rename_all = "snake_case"))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Display, Deserialize, Serialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub enum OrderStatus {
|
|
|
|
#[display(fmt = "Potwierdzone")]
|
|
|
|
Confirmed,
|
|
|
|
#[display(fmt = "Odebrane")]
|
|
|
|
Delivered,
|
|
|
|
#[display(fmt = "Opłacone")]
|
|
|
|
Payed,
|
|
|
|
#[display(fmt = "Anulowane")]
|
|
|
|
Cancelled,
|
|
|
|
#[display(fmt = "Wymaga zwrotu płatności")]
|
|
|
|
RequireRefund,
|
|
|
|
#[display(fmt = "Płatność zwrócona")]
|
|
|
|
Refunded,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(rename_all = "snake_case"))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Display, Deserialize, Serialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub enum Role {
|
|
|
|
#[display(fmt = "Adminitrator")]
|
|
|
|
Admin,
|
|
|
|
#[display(fmt = "Użytkownik")]
|
|
|
|
User,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<&str> for Role {
|
|
|
|
fn eq(&self, other: &&str) -> bool {
|
|
|
|
self.as_str() == *other
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Role {
|
|
|
|
pub fn as_str(&self) -> &str {
|
|
|
|
match self {
|
|
|
|
Role::Admin => "Admin",
|
|
|
|
Role::User => "User",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Display, Deserialize, Serialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub enum QuantityUnit {
|
|
|
|
#[cfg_attr(feature = "db", sqlx(rename = "g"))]
|
|
|
|
Gram,
|
|
|
|
#[cfg_attr(feature = "db", sqlx(rename = "dkg"))]
|
|
|
|
Decagram,
|
|
|
|
#[cfg_attr(feature = "db", sqlx(rename = "kg"))]
|
|
|
|
Kilogram,
|
|
|
|
#[cfg_attr(feature = "db", sqlx(rename = "piece"))]
|
|
|
|
Piece,
|
|
|
|
}
|
|
|
|
|
2022-05-12 20:33:16 +02:00
|
|
|
impl QuantityUnit {
|
|
|
|
pub fn name(self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
Self::Gram => "Gram",
|
|
|
|
Self::Decagram => "Decagram",
|
|
|
|
Self::Kilogram => "Kilogram",
|
|
|
|
Self::Piece => "Piece",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn short_name(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
Self::Gram => "g",
|
|
|
|
Self::Decagram => "dkg",
|
|
|
|
Self::Kilogram => "kg",
|
|
|
|
Self::Piece => "piece",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(rename_all = "snake_case"))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Display, Deserialize, Serialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub enum PaymentMethod {
|
|
|
|
PayU,
|
|
|
|
PaymentOnTheSpot,
|
|
|
|
}
|
|
|
|
|
2022-05-19 16:13:27 +02:00
|
|
|
impl Default for PaymentMethod {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::PaymentOnTheSpot
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(rename_all = "snake_case"))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Display, Deserialize, Serialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub enum ShoppingCartState {
|
|
|
|
Active,
|
|
|
|
Closed,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(rename_all = "snake_case"))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Copy, Clone, Debug, Hash, Display, Deserialize, Serialize, PartialEq, Eq)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub enum Audience {
|
|
|
|
Web,
|
|
|
|
Mobile,
|
|
|
|
Feed,
|
|
|
|
AdminPanel,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<&str> for Audience {
|
|
|
|
fn eq(&self, other: &&str) -> bool {
|
|
|
|
self.as_str() == *other
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Audience {
|
|
|
|
pub fn as_str(&self) -> &str {
|
|
|
|
match self {
|
|
|
|
Audience::Web => "Web",
|
|
|
|
Audience::Mobile => "Mobile",
|
|
|
|
Audience::Feed => "Feed",
|
|
|
|
Audience::AdminPanel => "AdminPanel",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(rename_all = "snake_case"))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Copy, Clone, Debug, Display, Deserialize, Serialize, PartialEq, Eq)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub enum AccountState {
|
|
|
|
Active,
|
|
|
|
Suspended,
|
|
|
|
Banned,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Audience {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::Web
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-06 15:09:13 +02:00
|
|
|
#[derive(
|
2022-06-13 16:16:19 +02:00
|
|
|
Default,
|
|
|
|
Debug,
|
|
|
|
Copy,
|
|
|
|
Clone,
|
|
|
|
Hash,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
|
|
|
Eq,
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Deref,
|
|
|
|
From,
|
2022-06-06 15:09:13 +02:00
|
|
|
)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Price(NonNegative);
|
|
|
|
|
2022-06-05 17:44:47 +02:00
|
|
|
impl Price {
|
|
|
|
pub fn from_u32(price: u32) -> Self {
|
|
|
|
Self(NonNegative(price as i32))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-16 16:08:14 +02:00
|
|
|
impl ops::Mul<Quantity> for Price {
|
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
fn mul(self, rhs: Quantity) -> Self::Output {
|
|
|
|
Self(NonNegative(rhs.0 .0 * self.0 .0))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-11 16:32:07 +01:00
|
|
|
pub trait Ranged: Sized + From<u32> + Copy {
|
|
|
|
fn in_range(self, range: Range<u32>) -> Self {
|
|
|
|
let v = self.into_raw().try_into().unwrap_or(range.start);
|
|
|
|
v.max(range.start).min(range.end).into()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn into_raw(self) -> i32;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
|
|
|
#[derive(
|
2022-11-17 16:56:08 +01:00
|
|
|
Debug, Copy, Clone, Hash, PartialOrd, PartialEq, Eq, Serialize, Deserialize, Deref, From,
|
2022-11-11 16:32:07 +01:00
|
|
|
)]
|
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Limit(NonNegative);
|
|
|
|
|
2022-11-17 16:56:08 +01:00
|
|
|
impl Default for Limit {
|
|
|
|
fn default() -> Self {
|
|
|
|
200.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-11 16:32:07 +01:00
|
|
|
impl From<u32> for Limit {
|
|
|
|
fn from(value: u32) -> Self {
|
|
|
|
Self::from_u32(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Ranged for Limit {
|
|
|
|
fn into_raw(self) -> i32 {
|
|
|
|
self.0 .0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Limit {
|
|
|
|
pub fn from_u32(price: u32) -> Self {
|
|
|
|
Self(NonNegative(price as i32))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
|
|
|
#[derive(
|
|
|
|
Default,
|
|
|
|
Debug,
|
|
|
|
Copy,
|
|
|
|
Clone,
|
|
|
|
Hash,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
|
|
|
Eq,
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Deref,
|
|
|
|
From,
|
|
|
|
)]
|
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Offset(NonNegative);
|
|
|
|
|
|
|
|
impl From<u32> for Offset {
|
|
|
|
fn from(value: u32) -> Self {
|
|
|
|
Self::from_u32(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Ranged for Offset {
|
|
|
|
fn into_raw(self) -> i32 {
|
|
|
|
self.0 .0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Offset {
|
|
|
|
pub fn from_u32(price: u32) -> Self {
|
|
|
|
Self(NonNegative(price as i32))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Copy, Clone, Hash, Deref, From)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Quantity(NonNegative);
|
|
|
|
|
2022-05-16 20:29:48 +02:00
|
|
|
impl Quantity {
|
|
|
|
pub fn from_u32(v: u32) -> Self {
|
|
|
|
Self(NonNegative(v.try_into().unwrap_or_default()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-16 16:08:14 +02:00
|
|
|
impl ops::Add for Quantity {
|
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
fn add(self, rhs: Self) -> Self::Output {
|
|
|
|
Self(self.0 + rhs.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ops::Sub for Quantity {
|
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
|
|
Self(self.0 - rhs.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
impl TryFrom<i32> for Quantity {
|
|
|
|
type Error = TransformError;
|
|
|
|
|
|
|
|
fn try_from(value: i32) -> Result<Self, Self::Error> {
|
|
|
|
Ok(Self(value.try_into()?))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq, Deref, From, Display)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Login(String);
|
|
|
|
|
2022-05-09 16:17:27 +02:00
|
|
|
impl Login {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-05-29 13:36:25 +02:00
|
|
|
#[derive(
|
2022-06-13 16:16:19 +02:00
|
|
|
Serialize, Debug, Clone, Default, PartialOrd, PartialEq, Eq, Deref, DerefMut, From, Display,
|
2022-05-29 13:36:25 +02:00
|
|
|
)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Email(String);
|
|
|
|
|
2022-05-15 10:30:15 +02:00
|
|
|
impl Email {
|
|
|
|
pub fn invalid_empty() -> Self {
|
|
|
|
Self("".into())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-29 13:36:25 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
|
|
|
#[derive(
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Debug,
|
|
|
|
Clone,
|
|
|
|
Default,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
2022-06-13 16:16:19 +02:00
|
|
|
Eq,
|
2022-05-29 13:36:25 +02:00
|
|
|
Deref,
|
|
|
|
DerefMut,
|
|
|
|
From,
|
|
|
|
Display,
|
|
|
|
)]
|
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Phone(String);
|
|
|
|
|
|
|
|
impl Phone {
|
|
|
|
pub fn invalid_empty() -> Self {
|
|
|
|
Self("".into())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
impl FromStr for Email {
|
|
|
|
type Err = TransformError;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
if validator::validate_email(s) {
|
|
|
|
Ok(Self(String::from(s)))
|
|
|
|
} else {
|
|
|
|
Err(TransformError::NotEmail)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'de> serde::Deserialize<'de> for Email {
|
|
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
|
|
where
|
|
|
|
D: Deserializer<'de>,
|
|
|
|
{
|
|
|
|
struct EmailVisitor {}
|
|
|
|
impl<'v> Visitor<'v> for EmailVisitor {
|
|
|
|
type Value = String;
|
|
|
|
|
|
|
|
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
|
|
|
|
formatter.write_str("valid e-mail address")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: Error,
|
|
|
|
{
|
|
|
|
if validator::validate_email(s) {
|
|
|
|
Ok(String::from(s))
|
|
|
|
} else {
|
|
|
|
Err(E::custom("this is not email address"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(Email(deserializer.deserialize_str(EmailVisitor {})?))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(
|
|
|
|
Default, Debug, PartialEq, Eq, PartialOrd, Copy, Clone, Hash, Serialize, Deref, Display,
|
|
|
|
)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct NonNegative(i32);
|
|
|
|
|
2022-05-18 09:48:01 +02:00
|
|
|
impl ops::Add for NonNegative {
|
2022-05-16 16:08:14 +02:00
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
fn add(self, rhs: Self) -> Self::Output {
|
|
|
|
Self(self.0 + rhs.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-18 09:48:01 +02:00
|
|
|
impl ops::Sub for NonNegative {
|
2022-05-16 16:08:14 +02:00
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
|
|
Self((self.0 - rhs.0).max(0))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
impl TryFrom<i32> for NonNegative {
|
|
|
|
type Error = TransformError;
|
|
|
|
|
|
|
|
fn try_from(value: i32) -> Result<Self, Self::Error> {
|
|
|
|
if value < 0 {
|
|
|
|
Err(TransformError::BelowMinimal)
|
|
|
|
} else {
|
|
|
|
Ok(Self(value))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'de> serde::Deserialize<'de> for NonNegative {
|
|
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
|
|
where
|
|
|
|
D: Deserializer<'de>,
|
|
|
|
{
|
|
|
|
struct NonNegativeVisitor;
|
|
|
|
impl<'v> Visitor<'v> for NonNegativeVisitor {
|
|
|
|
type Value = i32;
|
|
|
|
|
|
|
|
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
|
|
|
|
formatter.write_str("value equal or greater than 0")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: Error,
|
|
|
|
{
|
|
|
|
if v >= 0 {
|
|
|
|
Ok(v)
|
|
|
|
} else {
|
|
|
|
Err(E::custom("Value must be equal or greater than 0"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: Error,
|
|
|
|
{
|
|
|
|
let v = v
|
|
|
|
.try_into()
|
|
|
|
.map_err(|_| E::custom("Value must be equal or greater than 0"))?;
|
|
|
|
if v >= 0 {
|
|
|
|
Ok(v)
|
|
|
|
} else {
|
|
|
|
Err(E::custom("Value must be equal or greater than 0"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: Error,
|
|
|
|
{
|
|
|
|
let v = v
|
|
|
|
.try_into()
|
|
|
|
.map_err(|_| E::custom("Value must be equal or greater than 0"))?;
|
|
|
|
Ok(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: Error,
|
|
|
|
{
|
|
|
|
let v = v
|
|
|
|
.try_into()
|
|
|
|
.map_err(|_| E::custom("Value must be equal or greater than 0"))?;
|
|
|
|
Ok(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(NonNegative(
|
|
|
|
deserializer.deserialize_i32(NonNegativeVisitor)?,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-06 15:09:13 +02:00
|
|
|
#[derive(
|
2022-06-13 16:16:19 +02:00
|
|
|
Debug, Copy, Clone, Hash, PartialOrd, PartialEq, Eq, Serialize, Deserialize, Display, From,
|
2022-06-06 15:09:13 +02:00
|
|
|
)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(rename_all = "lowercase")]
|
|
|
|
pub enum Day {
|
2022-06-08 15:22:43 +02:00
|
|
|
Monday = 1,
|
2022-05-06 11:47:18 +02:00
|
|
|
Tuesday = 1 << 1,
|
|
|
|
Wednesday = 1 << 2,
|
|
|
|
Thursday = 1 << 3,
|
|
|
|
Friday = 1 << 4,
|
|
|
|
Saturday = 1 << 5,
|
|
|
|
Sunday = 1 << 6,
|
|
|
|
}
|
|
|
|
|
2022-05-12 16:05:58 +02:00
|
|
|
impl Day {
|
|
|
|
pub fn name(&self) -> &str {
|
|
|
|
match self {
|
|
|
|
Self::Monday => "Monday",
|
|
|
|
Self::Tuesday => "Tuesday",
|
|
|
|
Self::Wednesday => "Wednesday",
|
|
|
|
Self::Thursday => "Thursday",
|
|
|
|
Self::Friday => "Friday",
|
|
|
|
Self::Saturday => "Saturday",
|
|
|
|
Self::Sunday => "Sunday",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn short_name(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
Self::Monday => "Mon",
|
|
|
|
Self::Tuesday => "Tue",
|
|
|
|
Self::Wednesday => "Wed",
|
|
|
|
Self::Thursday => "Thu",
|
|
|
|
Self::Friday => "Fri",
|
|
|
|
Self::Saturday => "Sat",
|
|
|
|
Self::Sunday => "Sun",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-08 15:22:43 +02:00
|
|
|
impl BitOr for Day {
|
|
|
|
type Output = Days;
|
|
|
|
|
|
|
|
fn bitor(self, rhs: Self) -> Self::Output {
|
|
|
|
Days(vec![self, rhs])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
impl TryFrom<i32> for Day {
|
|
|
|
type Error = TransformError;
|
|
|
|
|
|
|
|
fn try_from(value: i32) -> Result<Self, Self::Error> {
|
|
|
|
if value == (Day::Monday as i32) {
|
|
|
|
Ok(Day::Monday)
|
|
|
|
} else if value == (Day::Tuesday as i32) {
|
|
|
|
Ok(Day::Tuesday)
|
|
|
|
} else if value == (Day::Wednesday as i32) {
|
|
|
|
Ok(Day::Wednesday)
|
|
|
|
} else if value == (Day::Thursday as i32) {
|
|
|
|
Ok(Day::Thursday)
|
|
|
|
} else if value == (Day::Friday as i32) {
|
|
|
|
Ok(Day::Friday)
|
|
|
|
} else if value == (Day::Saturday as i32) {
|
|
|
|
Ok(Day::Saturday)
|
|
|
|
} else if value == (Day::Sunday as i32) {
|
|
|
|
Ok(Day::Sunday)
|
|
|
|
} else {
|
|
|
|
Err(TransformError::NotDay)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Hash, Debug, PartialOrd, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
2022-06-05 17:44:47 +02:00
|
|
|
pub struct Days(pub Vec<Day>);
|
2022-05-06 11:47:18 +02:00
|
|
|
|
2022-06-08 15:22:43 +02:00
|
|
|
impl BitOr<Day> for Days {
|
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
fn bitor(mut self, rhs: Day) -> Self::Output {
|
|
|
|
self.0.push(rhs);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-18 09:48:01 +02:00
|
|
|
impl ops::Deref for Days {
|
2022-05-12 16:05:58 +02:00
|
|
|
type Target = Vec<Day>;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg(feature = "db")]
|
|
|
|
impl<'q> ::sqlx::encode::Encode<'q, sqlx::Postgres> for Days
|
|
|
|
where
|
|
|
|
i32: ::sqlx::encode::Encode<'q, sqlx::Postgres>,
|
|
|
|
{
|
|
|
|
fn encode_by_ref(
|
|
|
|
&self,
|
|
|
|
buf: &mut <sqlx::Postgres as ::sqlx::database::HasArguments<'q>>::ArgumentBuffer,
|
|
|
|
) -> ::sqlx::encode::IsNull {
|
2022-06-08 15:22:43 +02:00
|
|
|
let value = self.0.iter().fold(0, |memo, v| memo | *v as i32);
|
2022-05-06 11:47:18 +02:00
|
|
|
|
|
|
|
<i32 as ::sqlx::encode::Encode<sqlx::Postgres>>::encode_by_ref(&value, buf)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn size_hint(&self) -> usize {
|
|
|
|
<i32 as ::sqlx::encode::Encode<sqlx::Postgres>>::size_hint(&Default::default())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "db")]
|
|
|
|
impl<'r> ::sqlx::decode::Decode<'r, sqlx::Postgres> for Days
|
|
|
|
where
|
|
|
|
i32: ::sqlx::decode::Decode<'r, sqlx::Postgres>,
|
|
|
|
{
|
|
|
|
fn decode(
|
|
|
|
value: <sqlx::Postgres as ::sqlx::database::HasValueRef<'r>>::ValueRef,
|
2022-05-18 15:40:50 +02:00
|
|
|
) -> Result<Self, Box<dyn ::std::error::Error + 'static + Send + Sync>> {
|
2022-05-06 11:47:18 +02:00
|
|
|
let value = <i32 as ::sqlx::decode::Decode<'r, sqlx::Postgres>>::decode(value)?;
|
|
|
|
Ok(Days(
|
2022-05-11 15:56:41 +02:00
|
|
|
(0..7)
|
2022-05-06 11:47:18 +02:00
|
|
|
.into_iter()
|
2022-05-11 15:56:41 +02:00
|
|
|
.filter_map(|n| Day::try_from(value & 1 << n).ok())
|
2022-05-06 11:47:18 +02:00
|
|
|
.collect(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "db")]
|
|
|
|
impl sqlx::Type<sqlx::Postgres> for Days
|
|
|
|
where
|
|
|
|
i32: ::sqlx::Type<sqlx::Postgres>,
|
|
|
|
{
|
|
|
|
fn type_info() -> <sqlx::Postgres as ::sqlx::Database>::TypeInfo {
|
|
|
|
<i32 as ::sqlx::Type<sqlx::Postgres>>::type_info()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn compatible(ty: &<sqlx::Postgres as ::sqlx::Database>::TypeInfo) -> bool {
|
|
|
|
<i32 as ::sqlx::Type<sqlx::Postgres>>::compatible(ty)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-09 16:17:27 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Deref, Display)]
|
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct ResetToken(String);
|
|
|
|
|
|
|
|
impl ResetToken {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-05-15 10:30:15 +02:00
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, Deref, From, Display)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Password(String);
|
|
|
|
|
2022-05-08 09:47:05 +02:00
|
|
|
impl Password {
|
|
|
|
pub fn new<S: Into<String>>(pass: S) -> Self {
|
|
|
|
Self(pass.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-05-15 10:30:15 +02:00
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, Deref, From, Display)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct PasswordConfirmation(String);
|
|
|
|
|
2022-05-15 10:30:15 +02:00
|
|
|
impl PasswordConfirmation {
|
|
|
|
pub fn new<S: Into<String>>(pass: S) -> Self {
|
|
|
|
Self(pass.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Deref, From, Display)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct PassHash(String);
|
|
|
|
|
2022-05-17 08:23:39 +02:00
|
|
|
impl PassHash {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
impl PartialEq<PasswordConfirmation> for Password {
|
|
|
|
fn eq(&self, other: &PasswordConfirmation) -> bool {
|
|
|
|
self.0 == other.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-05-29 13:36:25 +02:00
|
|
|
#[derive(
|
2022-06-13 16:16:19 +02:00
|
|
|
Serialize, Deserialize, Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Deref, Display, From,
|
2022-05-29 13:36:25 +02:00
|
|
|
)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct AccountId(RecordId);
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
2022-05-06 11:47:18 +02:00
|
|
|
pub struct FullAccount {
|
|
|
|
pub id: AccountId,
|
|
|
|
pub email: Email,
|
|
|
|
pub login: Login,
|
|
|
|
pub pass_hash: PassHash,
|
|
|
|
pub role: Role,
|
|
|
|
pub customer_id: uuid::Uuid,
|
|
|
|
pub state: AccountState,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-05-10 16:20:37 +02:00
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
2022-05-06 11:47:18 +02:00
|
|
|
pub struct Account {
|
|
|
|
pub id: AccountId,
|
|
|
|
pub email: Email,
|
|
|
|
pub login: Login,
|
|
|
|
pub role: Role,
|
|
|
|
pub customer_id: uuid::Uuid,
|
|
|
|
pub state: AccountState,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<FullAccount> for Account {
|
|
|
|
fn from(
|
|
|
|
FullAccount {
|
|
|
|
id,
|
|
|
|
email,
|
|
|
|
login,
|
|
|
|
pass_hash: _,
|
|
|
|
role,
|
|
|
|
customer_id,
|
|
|
|
state,
|
|
|
|
}: FullAccount,
|
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
id,
|
|
|
|
email,
|
|
|
|
login,
|
|
|
|
role,
|
|
|
|
customer_id,
|
|
|
|
state,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-06 15:09:13 +02:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Deref, From)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct ProductId(RecordId);
|
|
|
|
|
2022-05-13 15:24:11 +02:00
|
|
|
impl Display for ProductId {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
|
|
f.write_fmt(format_args!("{}", self.0))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Deref, Display, From)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct ProductName(String);
|
|
|
|
|
2022-05-13 15:24:11 +02:00
|
|
|
impl ProductName {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_inner(self) -> String {
|
|
|
|
self.0
|
|
|
|
}
|
2022-11-06 19:50:51 +01:00
|
|
|
|
2022-11-07 16:28:51 +01:00
|
|
|
pub fn as_str(&self) -> &str {
|
2022-11-06 19:50:51 +01:00
|
|
|
&self.0
|
|
|
|
}
|
2022-05-13 15:24:11 +02:00
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Deref, Display, From)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct ProductShortDesc(String);
|
|
|
|
|
2022-05-12 22:10:17 +02:00
|
|
|
impl ProductShortDesc {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
2022-05-13 15:24:11 +02:00
|
|
|
|
|
|
|
pub fn into_inner(self) -> String {
|
|
|
|
self.0
|
|
|
|
}
|
2022-11-06 19:50:51 +01:00
|
|
|
|
2022-11-07 16:28:51 +01:00
|
|
|
pub fn as_str(&self) -> &str {
|
2022-11-06 19:50:51 +01:00
|
|
|
&self.0
|
|
|
|
}
|
2022-05-12 22:10:17 +02:00
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Deref, Display, From)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct ProductLongDesc(String);
|
|
|
|
|
2022-05-13 15:24:11 +02:00
|
|
|
impl ProductLongDesc {
|
|
|
|
pub fn into_inner(self) -> String {
|
|
|
|
self.0
|
|
|
|
}
|
2022-11-06 19:50:51 +01:00
|
|
|
|
2022-11-07 16:28:51 +01:00
|
|
|
pub fn as_str(&self) -> &str {
|
2022-11-06 19:50:51 +01:00
|
|
|
&self.0
|
|
|
|
}
|
2022-05-13 15:24:11 +02:00
|
|
|
}
|
|
|
|
|
2022-05-12 22:10:17 +02:00
|
|
|
impl ProductLongDesc {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Deref, Display, From)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
2022-11-28 17:00:19 +01:00
|
|
|
pub struct ProductCategory(pub String);
|
2022-05-06 11:47:18 +02:00
|
|
|
|
2022-05-08 09:47:05 +02:00
|
|
|
impl ProductCategory {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
2022-11-06 19:50:51 +01:00
|
|
|
|
2022-11-07 16:28:51 +01:00
|
|
|
pub fn as_str(&self) -> &str {
|
2022-11-06 19:50:51 +01:00
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
pub struct Product {
|
|
|
|
pub id: ProductId,
|
|
|
|
pub name: ProductName,
|
|
|
|
pub short_description: ProductShortDesc,
|
|
|
|
pub long_description: ProductLongDesc,
|
|
|
|
pub category: Option<ProductCategory>,
|
|
|
|
pub price: Price,
|
|
|
|
pub deliver_days_flag: Days,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct StockId(pub RecordId);
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
pub struct Stock {
|
|
|
|
pub id: StockId,
|
|
|
|
pub product_id: ProductId,
|
|
|
|
pub quantity: Quantity,
|
|
|
|
pub quantity_unit: QuantityUnit,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-09 15:28:15 +02:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Display, Deref)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
2022-05-23 14:11:56 +02:00
|
|
|
pub struct OrderAddressId(RecordId);
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-09 15:28:15 +02:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Display, Deref)]
|
2022-05-23 14:11:56 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct OrderId(RecordId);
|
2022-05-06 11:47:18 +02:00
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-09 15:28:15 +02:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Display, Deref)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
2022-05-23 14:11:56 +02:00
|
|
|
pub struct ExtOrderId(String);
|
2022-05-06 11:47:18 +02:00
|
|
|
|
2022-06-09 15:28:15 +02:00
|
|
|
impl ExtOrderId {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_inner(self) -> String {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-23 14:11:56 +02:00
|
|
|
pub struct Order {
|
|
|
|
pub id: OrderId,
|
2022-06-10 15:15:12 +02:00
|
|
|
/// Optional customer account id
|
|
|
|
pub buyer_id: Option<AccountId>,
|
|
|
|
/// Order status
|
2022-05-06 11:47:18 +02:00
|
|
|
pub status: OrderStatus,
|
2022-06-10 15:15:12 +02:00
|
|
|
/// ID send to external payment service as an identifier
|
2022-05-06 11:47:18 +02:00
|
|
|
pub order_ext_id: uuid::Uuid,
|
2022-06-10 15:15:12 +02:00
|
|
|
/// ID received from external payment service as an identifier
|
2022-05-06 11:47:18 +02:00
|
|
|
pub service_order_id: Option<String>,
|
2022-06-10 15:15:12 +02:00
|
|
|
/// Optional notes given by customer
|
2022-05-19 14:03:18 +02:00
|
|
|
pub checkout_notes: Option<String>,
|
2022-06-10 15:15:12 +02:00
|
|
|
/// Delivery address
|
2022-05-23 14:11:56 +02:00
|
|
|
pub address_id: OrderAddressId,
|
2022-05-06 11:47:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
|
|
|
#[derive(Serialize, Deserialize)]
|
2022-06-06 16:07:49 +02:00
|
|
|
pub struct PublicOrder {
|
2022-05-23 14:11:56 +02:00
|
|
|
pub id: OrderId,
|
2022-06-10 15:15:12 +02:00
|
|
|
pub buyer_id: Option<AccountId>,
|
2022-05-06 11:47:18 +02:00
|
|
|
pub status: OrderStatus,
|
2022-05-19 14:03:18 +02:00
|
|
|
pub checkout_notes: String,
|
2022-05-23 14:11:56 +02:00
|
|
|
pub address_id: OrderAddressId,
|
2022-05-06 11:47:18 +02:00
|
|
|
}
|
|
|
|
|
2022-06-06 16:07:49 +02:00
|
|
|
impl From<Order> for PublicOrder {
|
2022-05-06 11:47:18 +02:00
|
|
|
fn from(
|
2022-05-23 14:11:56 +02:00
|
|
|
Order {
|
2022-05-06 11:47:18 +02:00
|
|
|
id,
|
|
|
|
buyer_id,
|
|
|
|
status,
|
|
|
|
order_ext_id: _,
|
|
|
|
service_order_id: _,
|
2022-05-19 14:03:18 +02:00
|
|
|
checkout_notes,
|
2022-05-23 14:11:56 +02:00
|
|
|
address_id,
|
|
|
|
}: Order,
|
2022-05-06 11:47:18 +02:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
id,
|
|
|
|
buyer_id,
|
|
|
|
status,
|
2022-05-19 14:03:18 +02:00
|
|
|
checkout_notes: checkout_notes.unwrap_or_default(),
|
2022-05-23 14:11:56 +02:00
|
|
|
address_id,
|
2022-05-06 11:47:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Deref)]
|
2022-05-06 11:47:18 +02:00
|
|
|
pub struct OrderItemId(pub RecordId);
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
pub struct OrderItem {
|
|
|
|
pub id: OrderItemId,
|
|
|
|
pub product_id: ProductId,
|
2022-05-23 14:11:56 +02:00
|
|
|
pub order_id: OrderId,
|
2022-05-06 11:47:18 +02:00
|
|
|
pub quantity: Quantity,
|
|
|
|
pub quantity_unit: QuantityUnit,
|
2022-11-29 15:18:31 +01:00
|
|
|
pub state: OrderItemState,
|
2022-05-06 11:47:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Serialize, Deserialize, PartialEq, Eq, Copy, Clone, Debug, Deref, Display)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct ShoppingCartId(pub RecordId);
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
pub struct ShoppingCart {
|
|
|
|
pub id: ShoppingCartId,
|
|
|
|
pub buyer_id: AccountId,
|
|
|
|
pub payment_method: PaymentMethod,
|
|
|
|
pub state: ShoppingCartState,
|
2022-05-19 14:03:18 +02:00
|
|
|
pub checkout_notes: Option<String>,
|
2022-05-06 11:47:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(PartialEq, Eq, Copy, Clone, Debug, Serialize, Deserialize, Deref, Display)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct ShoppingCartItemId(RecordId);
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
pub struct ShoppingCartItem {
|
2022-05-18 16:10:39 +02:00
|
|
|
pub id: ShoppingCartItemId,
|
2022-11-28 17:00:19 +01:00
|
|
|
pub product_id: ProductId,
|
2022-11-23 16:03:58 +01:00
|
|
|
pub product_variant_id: ProductVariantId,
|
2022-05-06 11:47:18 +02:00
|
|
|
pub shopping_cart_id: ShoppingCartId,
|
|
|
|
pub quantity: Quantity,
|
|
|
|
pub quantity_unit: QuantityUnit,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ShoppingCartItem {
|
|
|
|
pub fn quantity(&self) -> Quantity {
|
|
|
|
self.quantity
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Deref, Display, Debug)]
|
2022-05-06 11:47:18 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct TokenId(RecordId);
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-06 11:47:18 +02:00
|
|
|
pub struct Token {
|
|
|
|
pub id: TokenId,
|
|
|
|
pub customer_id: uuid::Uuid,
|
|
|
|
pub role: Role,
|
|
|
|
/// iss (issuer): Issuer of the JWT
|
|
|
|
pub issuer: String,
|
|
|
|
/// sub (subject): Subject of the JWT (the user)
|
|
|
|
pub subject: i32,
|
|
|
|
/// aud (audience): Recipient for which the JWT is intended
|
|
|
|
pub audience: Audience,
|
|
|
|
/// exp (expiration time): Time after which the JWT expires
|
|
|
|
pub expiration_time: chrono::NaiveDateTime,
|
|
|
|
/// nbt (not before time): Time before which the JWT must not be accepted
|
|
|
|
/// for processing
|
|
|
|
pub not_before_time: chrono::NaiveDateTime,
|
|
|
|
/// iat (issued at time): Time at which the JWT was issued; can be used to
|
|
|
|
/// determine age of the JWT,
|
|
|
|
pub issued_at_time: chrono::NaiveDateTime,
|
|
|
|
/// jti (JWT ID): Unique identifier; can be used to prevent the JWT from
|
|
|
|
/// being replayed (allows a token to be used only once)
|
|
|
|
pub jwt_id: uuid::Uuid,
|
|
|
|
}
|
|
|
|
|
2022-05-17 08:23:39 +02:00
|
|
|
impl Token {
|
|
|
|
pub fn account_id(&self) -> AccountId {
|
|
|
|
AccountId(self.subject)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Deref, Display, From)]
|
2022-05-10 16:20:37 +02:00
|
|
|
pub struct AccessTokenString(String);
|
|
|
|
|
|
|
|
impl AccessTokenString {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<RefreshTokenString> for AccessTokenString {
|
|
|
|
fn from(r: RefreshTokenString) -> Self {
|
|
|
|
Self(r.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Deref, Display, From)]
|
2022-05-10 16:20:37 +02:00
|
|
|
pub struct RefreshTokenString(String);
|
|
|
|
|
|
|
|
impl From<AccessTokenString> for RefreshTokenString {
|
|
|
|
fn from(r: AccessTokenString) -> Self {
|
|
|
|
Self(r.0)
|
|
|
|
}
|
|
|
|
}
|
2022-05-06 11:47:18 +02:00
|
|
|
|
2022-05-10 16:20:37 +02:00
|
|
|
impl RefreshTokenString {
|
2022-05-09 16:17:27 +02:00
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 16:02:38 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Deref, Display, From)]
|
2022-05-06 16:02:38 +02:00
|
|
|
pub struct LocalPath(String);
|
|
|
|
|
2022-05-09 16:17:27 +02:00
|
|
|
impl LocalPath {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Deref, Display, From)]
|
2022-05-09 16:17:27 +02:00
|
|
|
pub struct UniqueName(String);
|
|
|
|
|
|
|
|
impl UniqueName {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 11:47:18 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Deref, Display, From)]
|
2022-05-06 11:47:18 +02:00
|
|
|
pub struct FileName(String);
|
2022-05-06 16:02:38 +02:00
|
|
|
|
2022-05-08 09:47:05 +02:00
|
|
|
impl FileName {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 16:02:38 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-06 15:09:13 +02:00
|
|
|
#[derive(
|
2022-06-13 16:16:19 +02:00
|
|
|
Debug,
|
|
|
|
Copy,
|
|
|
|
Clone,
|
|
|
|
Hash,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
|
|
|
Eq,
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Deref,
|
|
|
|
Display,
|
|
|
|
From,
|
2022-06-06 15:09:13 +02:00
|
|
|
)]
|
2022-05-06 16:02:38 +02:00
|
|
|
pub struct PhotoId(RecordId);
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Hash, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Deref, Display, From)]
|
2022-05-06 16:02:38 +02:00
|
|
|
pub struct ProductPhotoId(RecordId);
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-06 16:02:38 +02:00
|
|
|
pub struct Photo {
|
|
|
|
pub id: PhotoId,
|
|
|
|
pub local_path: LocalPath,
|
|
|
|
pub file_name: FileName,
|
2022-05-09 16:17:27 +02:00
|
|
|
pub unique_name: UniqueName,
|
2022-05-06 16:02:38 +02:00
|
|
|
}
|
|
|
|
|
2022-05-08 14:59:59 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-08 14:59:59 +02:00
|
|
|
pub struct ProductLinkedPhoto {
|
2022-06-06 15:09:13 +02:00
|
|
|
pub photo_id: PhotoId,
|
2022-05-08 14:59:59 +02:00
|
|
|
pub local_path: LocalPath,
|
|
|
|
pub file_name: FileName,
|
2022-05-09 16:17:27 +02:00
|
|
|
pub unique_name: UniqueName,
|
2022-05-08 14:59:59 +02:00
|
|
|
pub product_id: ProductId,
|
|
|
|
}
|
|
|
|
|
2022-05-06 16:02:38 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-06 16:02:38 +02:00
|
|
|
pub struct ProductPhoto {
|
|
|
|
pub id: ProductPhotoId,
|
|
|
|
pub product_id: ProductId,
|
|
|
|
pub photo_id: PhotoId,
|
|
|
|
}
|
2022-05-18 09:48:01 +02:00
|
|
|
|
2022-05-18 15:40:50 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
2022-05-18 09:48:01 +02:00
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub enum ShippingMethod {
|
2022-05-18 15:40:50 +02:00
|
|
|
/// Build-in InPost shipping
|
2022-05-18 09:48:01 +02:00
|
|
|
InPost,
|
2022-05-18 15:40:50 +02:00
|
|
|
/// Shop owner will ship product manually
|
|
|
|
Manual,
|
2022-05-18 09:48:01 +02:00
|
|
|
}
|
2022-05-19 16:13:27 +02:00
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-05-29 13:36:25 +02:00
|
|
|
#[derive(
|
2022-06-13 16:16:19 +02:00
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Debug,
|
|
|
|
Copy,
|
|
|
|
Clone,
|
|
|
|
Hash,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
|
|
|
Eq,
|
|
|
|
Deref,
|
|
|
|
Display,
|
|
|
|
From,
|
2022-05-29 13:36:25 +02:00
|
|
|
)]
|
2022-05-19 16:13:27 +02:00
|
|
|
pub struct AddressId(RecordId);
|
|
|
|
|
2022-05-29 13:36:25 +02:00
|
|
|
impl AddressId {
|
|
|
|
pub fn new(id: RecordId) -> Self {
|
|
|
|
Self(id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-19 16:13:27 +02:00
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-05-29 13:36:25 +02:00
|
|
|
#[derive(
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Debug,
|
|
|
|
Clone,
|
|
|
|
Default,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
2022-06-13 16:16:19 +02:00
|
|
|
Eq,
|
2022-05-29 13:36:25 +02:00
|
|
|
Deref,
|
|
|
|
DerefMut,
|
|
|
|
From,
|
|
|
|
Display,
|
|
|
|
)]
|
2022-05-19 16:13:27 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Name(String);
|
|
|
|
|
|
|
|
impl Name {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-05-29 13:36:25 +02:00
|
|
|
#[derive(
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Debug,
|
|
|
|
Clone,
|
|
|
|
Default,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
2022-06-13 16:16:19 +02:00
|
|
|
Eq,
|
2022-05-29 13:36:25 +02:00
|
|
|
Deref,
|
|
|
|
DerefMut,
|
|
|
|
From,
|
|
|
|
Display,
|
|
|
|
)]
|
2022-05-19 16:13:27 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Street(String);
|
|
|
|
|
|
|
|
impl Street {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-05-29 13:36:25 +02:00
|
|
|
#[derive(
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Debug,
|
|
|
|
Clone,
|
|
|
|
Default,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
2022-06-13 16:16:19 +02:00
|
|
|
Eq,
|
2022-05-29 13:36:25 +02:00
|
|
|
Deref,
|
|
|
|
DerefMut,
|
|
|
|
From,
|
|
|
|
Display,
|
|
|
|
)]
|
2022-05-19 16:13:27 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct City(String);
|
|
|
|
|
|
|
|
impl City {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-05-29 13:36:25 +02:00
|
|
|
#[derive(
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Debug,
|
|
|
|
Clone,
|
|
|
|
Default,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
2022-06-13 16:16:19 +02:00
|
|
|
Eq,
|
2022-05-29 13:36:25 +02:00
|
|
|
Deref,
|
|
|
|
DerefMut,
|
|
|
|
From,
|
|
|
|
Display,
|
|
|
|
)]
|
2022-05-19 16:13:27 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Country(String);
|
|
|
|
|
|
|
|
impl Country {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
2022-05-29 13:36:25 +02:00
|
|
|
#[derive(
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Debug,
|
|
|
|
Clone,
|
|
|
|
Default,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
2022-06-13 16:16:19 +02:00
|
|
|
Eq,
|
2022-05-29 13:36:25 +02:00
|
|
|
Deref,
|
|
|
|
DerefMut,
|
|
|
|
From,
|
|
|
|
Display,
|
|
|
|
)]
|
2022-05-19 16:13:27 +02:00
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct Zip(String);
|
|
|
|
|
|
|
|
impl Zip {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
2022-05-23 14:11:56 +02:00
|
|
|
pub struct AccountAddress {
|
2022-05-19 16:13:27 +02:00
|
|
|
pub id: AddressId,
|
|
|
|
pub name: Name,
|
|
|
|
pub email: Email,
|
2022-05-29 13:36:25 +02:00
|
|
|
pub phone: Phone,
|
2022-05-19 16:13:27 +02:00
|
|
|
pub street: Street,
|
|
|
|
pub city: City,
|
|
|
|
pub country: Country,
|
|
|
|
pub zip: Zip,
|
|
|
|
pub account_id: AccountId,
|
2022-05-23 14:11:56 +02:00
|
|
|
pub is_default: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
2022-06-13 16:16:19 +02:00
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
2022-05-23 14:11:56 +02:00
|
|
|
pub struct OrderAddress {
|
|
|
|
pub id: OrderAddressId,
|
|
|
|
pub name: Name,
|
|
|
|
pub email: Email,
|
|
|
|
pub street: Street,
|
|
|
|
pub city: City,
|
|
|
|
pub country: Country,
|
|
|
|
pub zip: Zip,
|
2022-06-08 15:22:43 +02:00
|
|
|
pub phone: Phone,
|
2022-05-19 16:13:27 +02:00
|
|
|
}
|
2022-11-28 17:00:19 +01:00
|
|
|
|
|
|
|
pub mod v2 {
|
|
|
|
use derive_more::{Deref, Display, From};
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
|
|
use crate::NonNegative;
|
|
|
|
pub use crate::{
|
|
|
|
Day, Days, FileName, Limit, LocalPath, Offset, PhotoId, Price, ProductCategory, ProductId,
|
|
|
|
ProductLongDesc, ProductName, ProductPhotoId, ProductShortDesc, Quantity, QuantityUnit,
|
|
|
|
RecordId, ShoppingCartId, StockId, UniqueName,
|
|
|
|
};
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
|
|
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Deref, Display, From)]
|
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct ProductVariantName(String);
|
|
|
|
|
|
|
|
impl ProductVariantName {
|
|
|
|
pub fn new<S: Into<String>>(s: S) -> Self {
|
|
|
|
Self(s.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_inner(self) -> String {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_str(&self) -> &str {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Deref, From)]
|
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct ProductVariantId(pub RecordId);
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
|
|
|
|
pub struct DetailedProductVariant {
|
|
|
|
pub id: ProductVariantId,
|
|
|
|
pub name: ProductVariantName,
|
|
|
|
pub short_description: ProductShortDesc,
|
|
|
|
pub long_description: ProductLongDesc,
|
|
|
|
pub price: Price,
|
|
|
|
pub quantity_unit: QuantityUnit,
|
|
|
|
|
|
|
|
pub stocks: Vec<Stock>,
|
|
|
|
|
|
|
|
pub photos: Vec<crate::api::Photo>,
|
|
|
|
|
|
|
|
pub available: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
|
|
|
|
pub struct DetailedProduct {
|
|
|
|
pub id: ProductId,
|
|
|
|
pub name: ProductName,
|
|
|
|
pub category: Option<crate::api::Category>,
|
|
|
|
pub deliver_days_flag: Days,
|
|
|
|
pub variants: Vec<DetailedProductVariant>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DetailedProduct {
|
|
|
|
pub fn variant_for(&self, variant_id: ProductVariantId) -> Option<&DetailedProductVariant> {
|
|
|
|
self.variants.iter().find(|v| v.id == variant_id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
pub struct Product {
|
|
|
|
pub id: ProductId,
|
|
|
|
pub name: ProductName,
|
|
|
|
pub category: Option<ProductCategory>,
|
|
|
|
pub deliver_days_flag: Days,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
pub struct ProductVariant {
|
|
|
|
pub id: ProductVariantId,
|
|
|
|
pub product_id: ProductId,
|
|
|
|
pub name: ProductVariantName,
|
|
|
|
pub short_description: ProductShortDesc,
|
|
|
|
pub long_description: ProductLongDesc,
|
|
|
|
pub price: Price,
|
|
|
|
pub quantity_unit: QuantityUnit,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
pub struct Stock {
|
|
|
|
pub id: StockId,
|
|
|
|
pub product_variant_id: ProductVariantId,
|
|
|
|
pub quantity: Quantity,
|
|
|
|
pub quantity_unit: QuantityUnit,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
pub struct Photo {
|
|
|
|
pub id: PhotoId,
|
|
|
|
pub local_path: LocalPath,
|
|
|
|
pub file_name: FileName,
|
|
|
|
pub unique_name: UniqueName,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
pub struct ProductLinkedPhoto {
|
|
|
|
pub photo_id: PhotoId,
|
|
|
|
pub local_path: LocalPath,
|
|
|
|
pub file_name: FileName,
|
|
|
|
pub unique_name: UniqueName,
|
|
|
|
pub product_variant_id: ProductVariantId,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
pub struct ProductPhoto {
|
|
|
|
pub id: ProductPhotoId,
|
|
|
|
pub product_variant_id: ProductVariantId,
|
|
|
|
pub photo_id: PhotoId,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
|
|
|
#[derive(
|
|
|
|
Debug,
|
|
|
|
Clone,
|
2022-11-29 11:11:04 +01:00
|
|
|
Copy,
|
2022-11-28 17:00:19 +01:00
|
|
|
Default,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
|
|
|
Eq,
|
|
|
|
Hash,
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Deref,
|
|
|
|
From,
|
|
|
|
Display,
|
|
|
|
)]
|
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct CategoryId(NonNegative);
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
|
|
|
#[derive(
|
|
|
|
Debug,
|
|
|
|
Clone,
|
|
|
|
Default,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
|
|
|
Eq,
|
|
|
|
Hash,
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Deref,
|
|
|
|
From,
|
|
|
|
Display,
|
|
|
|
)]
|
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct CategoryName(pub String);
|
|
|
|
|
|
|
|
impl<'s> From<&'s str> for CategoryName {
|
|
|
|
fn from(value: &'s str) -> Self {
|
|
|
|
Self(value.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
|
|
|
#[derive(
|
|
|
|
Debug,
|
|
|
|
Clone,
|
|
|
|
Default,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
|
|
|
Eq,
|
|
|
|
Hash,
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Deref,
|
|
|
|
From,
|
|
|
|
Display,
|
|
|
|
)]
|
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct CategoryKey(pub String);
|
|
|
|
|
|
|
|
impl<'s> From<&'s str> for CategoryKey {
|
|
|
|
fn from(value: &'s str) -> Self {
|
|
|
|
Self(value.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
|
|
|
#[cfg_attr(feature = "db", sqlx(transparent))]
|
|
|
|
#[derive(
|
|
|
|
Debug,
|
|
|
|
Clone,
|
|
|
|
Default,
|
|
|
|
PartialOrd,
|
|
|
|
PartialEq,
|
|
|
|
Eq,
|
|
|
|
Hash,
|
|
|
|
Serialize,
|
|
|
|
Deserialize,
|
|
|
|
Deref,
|
|
|
|
From,
|
|
|
|
Display,
|
|
|
|
)]
|
|
|
|
#[serde(transparent)]
|
|
|
|
pub struct CategorySvg(pub String);
|
|
|
|
|
|
|
|
impl<'s> From<&'s str> for CategorySvg {
|
|
|
|
fn from(value: &'s str) -> Self {
|
|
|
|
Self(value.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
pub struct Category {
|
|
|
|
pub id: CategoryId,
|
|
|
|
pub parent_id: Option<CategoryId>,
|
|
|
|
pub name: CategoryName,
|
|
|
|
pub key: CategoryKey,
|
|
|
|
pub svg: CategorySvg,
|
|
|
|
}
|
|
|
|
}
|