Files
web-petting/src/models.rs
T

199 lines
4.8 KiB
Rust
Raw Normal View History

2026-04-29 17:49:07 +03:00
use cot::db::{model, Auto, ForeignKey};
/// Lead status: new request from the website
/// new -> in_progress -> converted | rejected
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LeadStatus {
New,
InProgress,
Converted,
Rejected,
}
impl LeadStatus {
pub fn as_str(&self) -> &'static str {
match self {
Self::New => "new",
Self::InProgress => "in_progress",
Self::Converted => "converted",
Self::Rejected => "rejected",
}
}
}
/// Client status
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ClientStatus {
Active,
Archived,
}
impl ClientStatus {
pub fn as_str(&self) -> &'static str {
match self {
Self::Active => "active",
Self::Archived => "archived",
}
}
}
/// Visit status
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VisitStatus {
Scheduled,
Completed,
Cancelled,
}
impl VisitStatus {
pub fn as_str(&self) -> &'static str {
match self {
Self::Scheduled => "scheduled",
Self::Completed => "completed",
Self::Cancelled => "cancelled",
}
}
}
/// Media file type
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MediaType {
Photo,
Video,
}
impl MediaType {
pub fn as_str(&self) -> &'static str {
match self {
Self::Photo => "photo",
Self::Video => "video",
}
}
}
/// User (admin) status
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum UserStatus {
Active,
Archived,
}
impl UserStatus {
pub fn as_str(&self) -> &'static str {
match self {
Self::Active => "active",
Self::Archived => "archived",
}
}
}
// ---------------------------------------------------------------------------
// Models
// ---------------------------------------------------------------------------
/// A lead submitted via the public website form.
#[derive(Debug, Clone)]
#[model]
pub struct Lead {
#[model(primary_key)]
pub id: Auto<i64>,
pub name: String,
pub phone: Option<String>,
pub email: Option<String>,
pub comment: Option<String>,
/// new | in_progress | converted | rejected
pub status: String,
pub client_id: Option<ForeignKey<Client>>,
pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime,
}
/// A confirmed client created from a lead (or manually).
#[derive(Debug, Clone)]
#[model]
pub struct Client {
#[model(primary_key)]
pub id: Auto<i64>,
pub name: String,
pub phone: Option<String>,
pub email: Option<String>,
pub address: Option<String>,
pub notes: Option<String>,
/// Unique token for the public media page (client views photos/videos here).
#[model(unique)]
pub media_token: String,
/// Hex color for calendar display, e.g. "#7c6ed4"
pub color: Option<String>,
/// active | archived
pub status: String,
pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime,
}
/// A scheduled pet-sitting visit.
#[derive(Debug, Clone)]
#[model]
pub struct Visit {
#[model(primary_key)]
pub id: Auto<i64>,
pub client_id: ForeignKey<Client>,
pub user_id: ForeignKey<User>,
pub visit_date: chrono::NaiveDate,
pub time_start: String,
pub time_end: String,
pub notes: Option<String>,
/// Public notes visible to client on their portal.
pub public_notes: Option<String>,
/// Feedback text from client via portal.
pub client_feedback: Option<String>,
/// scheduled | completed | cancelled
pub status: String,
pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime,
}
/// A photo or video uploaded for a client (optionally tied to a visit).
#[derive(Debug, Clone)]
#[model]
pub struct Media {
#[model(primary_key)]
pub id: Auto<i64>,
pub client_id: ForeignKey<Client>,
pub visit_id: Option<ForeignKey<Visit>>,
pub file_path: String,
/// photo | video
pub file_type: String,
pub caption: Option<String>,
/// active | archived
pub status: String,
pub created_at: chrono::NaiveDateTime,
}
/// An admin user who can log in to manage the system.
#[derive(Debug, Clone)]
#[model]
pub struct User {
#[model(primary_key)]
pub id: Auto<i64>,
#[model(unique)]
pub login: String,
pub password_hash: String,
pub display_name: Option<String>,
/// active | archived
pub status: String,
pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime,
}
/// Global key-value settings (telegram_bot_token, telegram_chat_id, etc.).
#[derive(Debug, Clone)]
#[model]
pub struct Setting {
#[model(primary_key)]
pub id: Auto<i64>,
#[model(unique)]
pub key: String,
pub value: String,
pub updated_at: chrono::NaiveDateTime,
}