Files
rezervovator/src/backend/data.rs
T

377 lines
8.7 KiB
Rust
Raw Normal View History

2023-09-22 21:26:13 +02:00
//use chrono::{NaiveDate, NaiveTime, Weekday};
//use rust_decimal::Decimal;
#![allow(unused_variables)]
use std::fmt::Display;
use chrono::{NaiveTime, Weekday};
use lazy_static::lazy_static;
use regex::Regex;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
2023-09-22 21:26:13 +02:00
//use uuid::Uuid;
use validator::{Validate, ValidationError};
use crate::error::AppError;
2023-09-22 21:26:13 +02:00
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ApiResponse<T> {
Data(T),
Error(String)
}
2023-09-15 13:55:01 +02:00
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Validate, Default)]
#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))]
pub struct Company {
id: i32,
#[validate(length(min = 1,message = "Name cannot be empty"))]
pub name: String,
#[validate(length(min = 1,message = "Street cannot be empty"))]
pub street: String,
#[validate(length(min = 1,message = "House number cannot be empty"))]
pub house_number: String,
pub zip_code: String,
pub city: String,
}
impl Company {
pub fn id(&self) -> i32 {
self.id
}
}
2023-09-22 21:26:13 +02:00
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Validate, Default)]
#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))]
pub struct User {
2023-09-22 21:26:13 +02:00
id: i32,
pub login: String,
pub password: String,
pub full_name: Option<String>,
#[validate(email(message = "Enter valid email address"))]
2023-09-22 21:26:13 +02:00
pub email: Option<String>,
pub admin: bool,
pub get_emails: bool,
}
impl User {
pub fn id(&self) -> i32 {
self.id
}
}
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Validate, Default)]
pub struct UserProfile {
#[validate(length(min = 1,message = "Username cannot be empty"))]
login: String,
#[validate(must_match(other = "password_ver", message = "Passwords doesn't match"))]
password: Option<String>,
password_ver: Option<String>,
full_name: String,
#[validate(email(message = "Enter valid email address"))]
email: String,
get_emails: Option<String>,
admin: Option<String>
}
impl UserProfile {
pub fn login(&self) -> &str {
&self.login
}
pub fn full_name(&self) -> &str {
&self.full_name
}
pub fn email(&self) -> &str {
&self.email
}
pub fn get_emails(&self) -> bool {
self.get_emails.is_some()
}
pub fn admin(&self) -> bool {
self.admin.is_some()
}
pub fn password(&self) -> &Option<String> {
&self.password
}
}
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Validate, Default)]
pub struct PwdChange {
login: String,
old_password: String,
#[validate(length(min = 1, message = "Enter new password"),
must_match(other = "password_ver", message = "Passwords doesn't match"))]
password: String,
password_ver: String
}
impl PwdChange {
pub fn login(&self) -> &str {
&self.login
}
pub fn old_password(&self) -> &str {
&self.old_password
}
pub fn password(&self) -> &str {
&self.password
}
pub fn password_ver(&self) -> &str {
&self.password_ver
}
}
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Default)]
#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))]
pub struct OpeningHour {
id: i32,
pub day: i32,
pub from: NaiveTime,
pub to: NaiveTime,
pub discount: Option<i32>
}
impl OpeningHour {
pub fn id(&self) -> i32 {
self.id
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DayHours(pub Vec<DayHour>);
impl DayHours {
pub fn try_new(hours: &str) -> Result<Self, AppError> {
if hours.is_empty() {
return Ok(Self(Vec::new()))
}
let times = hours.split(",")
.map(|h| h.trim())
.map(|h| DayHour::try_from(h))
.collect::<Vec<_>>();
if times.contains(&Err(AppError::HourParseError)) {
return Err(AppError::HourParseError)
}
Ok(Self(times.into_iter().map(|h| h.unwrap()).collect()))
}
pub fn hours(&self) -> &Vec<DayHour> {
&self.0
}
}
impl Display for DayHours {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.0.is_empty() {
return write!(f, "{}", "".to_string())
}
let str = self.0.iter().map(|h| {
let discount = if let Some(d) = h.discount() {
format!(" ({})", d).to_string()
} else { "".to_string() };
format!("{} - {}{}", h.from().format("%H:%M"), h.to().format("%H:%M"), discount).to_string()
})
.collect::<Vec<String>>()
.join(", ");
write!(f, "{}", str)
}
}
#[derive(Eq, PartialEq, Serialize, Deserialize, Clone, Debug)]
pub struct DayHour {
from: NaiveTime,
to: NaiveTime,
discount: Option<i32>
}
impl DayHour {
pub fn new(from: NaiveTime, to: NaiveTime, discount: Option<i32>) -> Self {
Self { from, to, discount }
}
pub fn from(&self) -> NaiveTime {
self.from
}
pub fn to(&self) -> NaiveTime {
self.to
}
pub fn discount(&self) -> Option<i32> {
self.discount
}
}
impl TryFrom<String> for DayHour {
type Error = AppError;
fn try_from(value: String) -> Result<Self, Self::Error> {
value.as_str().try_into()
}
}
impl TryFrom<&str> for DayHour {
type Error = AppError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if value.is_empty() {
return Err(AppError::HourParseError)
}
let times = value.split("-")
.map(|t| t.trim()).collect::<Vec<_>>();
if times.len() != 2 {
return Err(AppError::HourParseError)
}
let from = NaiveTime::parse_from_str(times.get(0).unwrap(), "%H:%M");
let to = NaiveTime::parse_from_str(times.get(1).unwrap(), "%H:%M");
if from.is_err() || to.is_err() {
return Err(AppError::HourParseError)
}
Ok(DayHour {
from: from.unwrap(),
to: to.unwrap(),
discount: None
})
}
}
fn validate_hours(value: &WeekHours) -> Result<(), ValidationError> {
if value.hours().is_empty() {
return Ok(())
}
if let Ok(h) = DayHours::try_new(value.hours()) {
for hr in h.hours() {
if hr.from() >= hr.to() { return Err(ValidationError::new("TO_BEFORE_FROM")) }
}
Ok(())
} else {
Ok(())
}
}
lazy_static! {
static ref RE_HOURS: Regex = Regex::new(r"^$|(^\d{2}:\d{2} ?- ?\d{2}:\d{2} ?(\(\d+\))?,? ?)+").unwrap();
}
#[derive(Clone, Serialize, Deserialize, Debug, Validate)]
#[validate(schema(function = "validate_hours", message = "Time 'to' must be after time 'from'"))]
pub struct WeekHours {
day: Weekday,
#[validate(regex(path = "RE_HOURS", message = "Hours must be in HH:MM - HH:MM format"))]
hours: String
}
impl Default for WeekHours {
fn default() -> Self {
Self {
day: Weekday::Mon,
hours: String::default()
}
}
}
impl WeekHours {
pub fn new(day: Weekday, hours: Vec<DayHour>) -> Self {
Self {
day,
hours: DayHours(hours).to_string()
}
}
pub fn day(&self) -> Weekday {
self.day
}
pub fn hours(&self) -> &str {
&self.hours
}
}
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Default)]
#[cfg_attr(feature = "ssr", derive(sqlx::Type))]
#[cfg_attr(feature = "ssr", sqlx(type_name = "slot_type"))]
pub enum SlotType {
Quarter,
Half,
#[default]
Hour,
Day
}
fn def_true() -> bool {
true
}
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Validate, Default)]
#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))]
pub struct ResProperty {
id: i32,
#[validate(length(min = 1,message = "Name cannot be empty"))]
pub name: String,
pub description: String,
pub price: Decimal,
pub slot: SlotType,
#[serde(default = "def_true")]
pub allow_multi: bool,
#[serde(default = "def_true")]
pub active: bool
}
impl ResProperty {
pub fn id(&self) -> i32 {
self.id
}
}
/*
pub enum MessageType {
NewReservation,
NewReservationCust,
ReservationApp,
ReservationCanceled,
}
pub struct Message {
id: u16,
msg_type: MessageType,
subject: String,
text: String,
}
pub struct Customer {
id: u128,
full_name: String,
email: String,
phone: String,
discount: u8
}
pub enum ReservationState {
New,
Approved,
Canceled,
}
pub struct Reservation {
id: u128,
from: NaiveTime,
to: NaiveTime,
property: Property,
}
pub struct ReservationSum {
id: u128,
uuid: Uuid,
date: NaiveDate,
items: Vec<Reservation>,
customer: Customer,
price: Decimal,
state: ReservationState,
2023-09-22 21:26:13 +02:00
}*/