init
Build and Publish / Build and Publish Docker Image (push) Successful in 1m12s

This commit is contained in:
Ultradesu
2026-04-29 17:49:07 +03:00
commit ff32e6bbaf
36 changed files with 9595 additions and 0 deletions
+487
View File
@@ -0,0 +1,487 @@
//! Generated by cot CLI 0.6.0 on 2026-04-29 10:36:47+00:00
#[derive(Debug, Copy, Clone)]
pub(super) struct Migration;
impl ::cot::db::migrations::Migration for Migration {
const APP_NAME: &'static str = "web-petting";
const MIGRATION_NAME: &'static str = "m_0001_initial";
const DEPENDENCIES: &'static [::cot::db::migrations::MigrationDependency] = &[];
const OPERATIONS: &'static [::cot::db::migrations::Operation] = &[
::cot::db::migrations::Operation::create_model()
.table_name(::cot::db::Identifier::new("web_petting__user"))
.fields(
&[
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("id"),
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::TYPE,
)
.auto()
.primary_key()
.set_null(
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("login"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE)
.unique(),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("password_hash"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("display_name"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<Option<String> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("status"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("created_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("updated_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::NULLABLE,
),
],
)
.build(),
::cot::db::migrations::Operation::create_model()
.table_name(::cot::db::Identifier::new("web_petting__setting"))
.fields(
&[
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("id"),
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::TYPE,
)
.auto()
.primary_key()
.set_null(
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("key"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE)
.unique(),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("value"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("updated_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::NULLABLE,
),
],
)
.build(),
::cot::db::migrations::Operation::create_model()
.table_name(::cot::db::Identifier::new("web_petting__client"))
.fields(
&[
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("id"),
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::TYPE,
)
.auto()
.primary_key()
.set_null(
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("name"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("phone"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<Option<String> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("email"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<Option<String> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("address"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<Option<String> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("notes"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<Option<String> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("media_token"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE)
.unique(),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("status"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("created_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("updated_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::NULLABLE,
),
],
)
.build(),
::cot::db::migrations::Operation::create_model()
.table_name(::cot::db::Identifier::new("web_petting__visit"))
.fields(
&[
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("id"),
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::TYPE,
)
.auto()
.primary_key()
.set_null(
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("client_id"),
<cot::db::ForeignKey<
crate::models::Client,
> as ::cot::db::DatabaseField>::TYPE,
)
.foreign_key(
<crate::models::Client as ::cot::db::Model>::TABLE_NAME,
<crate::models::Client as ::cot::db::Model>::PRIMARY_KEY_NAME,
::cot::db::ForeignKeyOnDeletePolicy::Restrict,
::cot::db::ForeignKeyOnUpdatePolicy::Restrict,
)
.set_null(
<cot::db::ForeignKey<
crate::models::Client,
> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("scheduled_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("duration_minutes"),
<Option<i32> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<Option<i32> as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("notes"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<Option<String> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("status"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("created_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("updated_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::NULLABLE,
),
],
)
.build(),
::cot::db::migrations::Operation::create_model()
.table_name(::cot::db::Identifier::new("web_petting__media"))
.fields(
&[
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("id"),
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::TYPE,
)
.auto()
.primary_key()
.set_null(
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("client_id"),
<cot::db::ForeignKey<
crate::models::Client,
> as ::cot::db::DatabaseField>::TYPE,
)
.foreign_key(
<crate::models::Client as ::cot::db::Model>::TABLE_NAME,
<crate::models::Client as ::cot::db::Model>::PRIMARY_KEY_NAME,
::cot::db::ForeignKeyOnDeletePolicy::Restrict,
::cot::db::ForeignKeyOnUpdatePolicy::Restrict,
)
.set_null(
<cot::db::ForeignKey<
crate::models::Client,
> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("visit_id"),
<Option<
cot::db::ForeignKey<crate::models::Visit>,
> as ::cot::db::DatabaseField>::TYPE,
)
.foreign_key(
<crate::models::Visit as ::cot::db::Model>::TABLE_NAME,
<crate::models::Visit as ::cot::db::Model>::PRIMARY_KEY_NAME,
::cot::db::ForeignKeyOnDeletePolicy::Restrict,
::cot::db::ForeignKeyOnUpdatePolicy::Restrict,
)
.set_null(
<Option<
cot::db::ForeignKey<crate::models::Visit>,
> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("file_path"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("file_type"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("caption"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<Option<String> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("status"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("created_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::NULLABLE,
),
],
)
.build(),
::cot::db::migrations::Operation::create_model()
.table_name(::cot::db::Identifier::new("web_petting__lead"))
.fields(
&[
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("id"),
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::TYPE,
)
.auto()
.primary_key()
.set_null(
<cot::db::Auto<i64> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("name"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("phone"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<Option<String> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("email"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<Option<String> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("comment"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<Option<String> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("status"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("client_id"),
<Option<
cot::db::ForeignKey<crate::models::Client>,
> as ::cot::db::DatabaseField>::TYPE,
)
.foreign_key(
<crate::models::Client as ::cot::db::Model>::TABLE_NAME,
<crate::models::Client as ::cot::db::Model>::PRIMARY_KEY_NAME,
::cot::db::ForeignKeyOnDeletePolicy::Restrict,
::cot::db::ForeignKeyOnUpdatePolicy::Restrict,
)
.set_null(
<Option<
cot::db::ForeignKey<crate::models::Client>,
> as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("created_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::NULLABLE,
),
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("updated_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
)
.set_null(
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::NULLABLE,
),
],
)
.build(),
];
}
#[derive(::core::fmt::Debug)]
#[::cot::db::model(model_type = "migration")]
struct _Client {
#[model(primary_key)]
pub id: cot::db::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,
/// active | archived
pub status: String,
pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime,
}
#[derive(::core::fmt::Debug)]
#[::cot::db::model(model_type = "migration")]
struct _Lead {
#[model(primary_key)]
pub id: cot::db::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<cot::db::ForeignKey<crate::models::Client>>,
pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime,
}
#[derive(::core::fmt::Debug)]
#[::cot::db::model(model_type = "migration")]
struct _Media {
#[model(primary_key)]
pub id: cot::db::Auto<i64>,
pub client_id: cot::db::ForeignKey<crate::models::Client>,
pub visit_id: Option<cot::db::ForeignKey<crate::models::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,
}
#[derive(::core::fmt::Debug)]
#[::cot::db::model(model_type = "migration")]
struct _Setting {
#[model(primary_key)]
pub id: cot::db::Auto<i64>,
#[model(unique)]
pub key: String,
pub value: String,
pub updated_at: chrono::NaiveDateTime,
}
#[derive(::core::fmt::Debug)]
#[::cot::db::model(model_type = "migration")]
struct _User {
#[model(primary_key)]
pub id: cot::db::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,
}
#[derive(::core::fmt::Debug)]
#[::cot::db::model(model_type = "migration")]
struct _Visit {
#[model(primary_key)]
pub id: cot::db::Auto<i64>,
pub client_id: cot::db::ForeignKey<crate::models::Client>,
pub scheduled_at: chrono::NaiveDateTime,
pub duration_minutes: Option<i32>,
pub notes: Option<String>,
/// scheduled | completed | cancelled
pub status: String,
pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime,
}
+88
View File
@@ -0,0 +1,88 @@
//! Migration: update Visit model for scheduling + add Client.color
//! Visit: Remove scheduled_at, duration_minutes; Add user_id, visit_date, time_start, time_end
//! Client: Add color
#[derive(Debug, Copy, Clone)]
pub(super) struct Migration;
impl ::cot::db::migrations::Migration for Migration {
const APP_NAME: &'static str = "web-petting";
const MIGRATION_NAME: &'static str = "m_0002_visit_schedule";
const DEPENDENCIES: &'static [::cot::db::migrations::MigrationDependency] = &[
::cot::db::migrations::MigrationDependency::migration("web-petting", "m_0001_initial"),
];
const OPERATIONS: &'static [::cot::db::migrations::Operation] = &[
// Add color to client (nullable for existing rows)
::cot::db::migrations::Operation::add_field()
.table_name(::cot::db::Identifier::new("web_petting__client"))
.field(
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("color"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<Option<String> as ::cot::db::DatabaseField>::NULLABLE)
)
.build(),
// Remove old visit fields
::cot::db::migrations::Operation::remove_field()
.table_name(::cot::db::Identifier::new("web_petting__visit"))
.field(::cot::db::migrations::Field::new(
::cot::db::Identifier::new("scheduled_at"),
<chrono::NaiveDateTime as ::cot::db::DatabaseField>::TYPE,
))
.build(),
::cot::db::migrations::Operation::remove_field()
.table_name(::cot::db::Identifier::new("web_petting__visit"))
.field(::cot::db::migrations::Field::new(
::cot::db::Identifier::new("duration_minutes"),
<Option<i32> as ::cot::db::DatabaseField>::TYPE,
).set_null(<Option<i32> as ::cot::db::DatabaseField>::NULLABLE))
.build(),
// Add new fields
::cot::db::migrations::Operation::add_field()
.table_name(::cot::db::Identifier::new("web_petting__visit"))
.field(
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("user_id"),
<cot::db::ForeignKey<crate::models::User> as ::cot::db::DatabaseField>::TYPE,
)
.foreign_key(
<crate::models::User as ::cot::db::Model>::TABLE_NAME,
<crate::models::User as ::cot::db::Model>::PRIMARY_KEY_NAME,
::cot::db::ForeignKeyOnDeletePolicy::Restrict,
::cot::db::ForeignKeyOnUpdatePolicy::Restrict,
)
.set_null(<cot::db::ForeignKey<crate::models::User> as ::cot::db::DatabaseField>::NULLABLE)
)
.build(),
::cot::db::migrations::Operation::add_field()
.table_name(::cot::db::Identifier::new("web_petting__visit"))
.field(
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("visit_date"),
<chrono::NaiveDate as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<chrono::NaiveDate as ::cot::db::DatabaseField>::NULLABLE)
)
.build(),
::cot::db::migrations::Operation::add_field()
.table_name(::cot::db::Identifier::new("web_petting__visit"))
.field(
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("time_start"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE)
)
.build(),
::cot::db::migrations::Operation::add_field()
.table_name(::cot::db::Identifier::new("web_petting__visit"))
.field(
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("time_end"),
<String as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<String as ::cot::db::DatabaseField>::NULLABLE)
)
.build(),
];
}
+23
View File
@@ -0,0 +1,23 @@
//! Migration: add client_feedback to Visit
#[derive(Debug, Copy, Clone)]
pub(super) struct Migration;
impl ::cot::db::migrations::Migration for Migration {
const APP_NAME: &'static str = "web-petting";
const MIGRATION_NAME: &'static str = "m_0003_visit_feedback";
const DEPENDENCIES: &'static [::cot::db::migrations::MigrationDependency] = &[
::cot::db::migrations::MigrationDependency::migration("web-petting", "m_0002_visit_schedule"),
];
const OPERATIONS: &'static [::cot::db::migrations::Operation] = &[
::cot::db::migrations::Operation::add_field()
.table_name(::cot::db::Identifier::new("web_petting__visit"))
.field(
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("client_feedback"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<Option<String> as ::cot::db::DatabaseField>::NULLABLE)
)
.build(),
];
}
@@ -0,0 +1,23 @@
//! Migration: add public_notes to Visit
#[derive(Debug, Copy, Clone)]
pub(super) struct Migration;
impl ::cot::db::migrations::Migration for Migration {
const APP_NAME: &'static str = "web-petting";
const MIGRATION_NAME: &'static str = "m_0004_visit_public_notes";
const DEPENDENCIES: &'static [::cot::db::migrations::MigrationDependency] = &[
::cot::db::migrations::MigrationDependency::migration("web-petting", "m_0003_visit_feedback"),
];
const OPERATIONS: &'static [::cot::db::migrations::Operation] = &[
::cot::db::migrations::Operation::add_field()
.table_name(::cot::db::Identifier::new("web_petting__visit"))
.field(
::cot::db::migrations::Field::new(
::cot::db::Identifier::new("public_notes"),
<Option<String> as ::cot::db::DatabaseField>::TYPE,
)
.set_null(<Option<String> as ::cot::db::DatabaseField>::NULLABLE)
)
.build(),
];
}