use cot::db::{Auto, ForeignKey, model}; /// 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, Deleted, } impl VisitStatus { pub fn as_str(&self) -> &'static str { match self { Self::Scheduled => "scheduled", Self::Completed => "completed", Self::Cancelled => "cancelled", Self::Deleted => "deleted", } } } /// 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, pub name: String, pub phone: Option, pub email: Option, pub comment: Option, /// new | in_progress | converted | rejected pub status: String, pub client_id: Option>, 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, pub name: String, pub phone: Option, pub email: Option, pub address: Option, pub notes: Option, /// 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, /// 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, pub client_id: ForeignKey, pub user_id: ForeignKey, pub visit_date: chrono::NaiveDate, pub time_start: String, pub time_end: String, pub notes: Option, /// Public notes visible to client on their portal. pub public_notes: Option, /// Feedback text from client via portal. pub client_feedback: Option, /// scheduled | completed | cancelled | deleted 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, pub client_id: ForeignKey, pub visit_id: Option>, pub file_path: String, /// photo | video pub file_type: String, pub caption: Option, /// 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, #[model(unique)] pub login: String, pub password_hash: String, pub display_name: Option, pub telegram_chat_id: Option, pub telegram_notifications: Option, /// active | archived pub status: String, pub created_at: chrono::NaiveDateTime, pub updated_at: chrono::NaiveDateTime, } /// A testimonial/review displayed on the landing page. #[derive(Debug, Clone)] #[model] pub struct Testimonial { #[model(primary_key)] pub id: Auto, pub text: String, /// Optional short note (e.g. client name, pet type). pub author_note: Option, /// Optional image path. pub image_path: Option, /// active | hidden pub status: String, pub sort_order: i32, pub created_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, #[model(unique)] pub key: String, pub value: String, pub updated_at: chrono::NaiveDateTime, } /// A browser Web Push subscription belonging to a client device. #[derive(Debug, Clone)] #[model] pub struct PushSubscription { #[model(primary_key)] pub id: Auto, pub client_id: ForeignKey, #[model(unique)] pub endpoint: String, pub p256dh: String, pub auth: String, pub language: String, /// active | archived pub status: String, pub created_at: chrono::NaiveDateTime, pub updated_at: chrono::NaiveDateTime, }