use crate::{DbExecutor, DbResult, models::shared::CountResult};
use serde::Serialize;
use sqlx::{postgres::PgQueryResult, prelude::FromRow};
use utoipa::ToSchema;
pub type UserId = String;
#[derive(Debug, Clone, Serialize, FromRow, ToSchema, sqlx::Type, PartialEq, Eq)]
#[sqlx(type_name = "docbox_user")]
pub struct User {
pub id: String,
pub name: Option<String>,
pub image_id: Option<String>,
}
impl User {
pub async fn store(
db: impl DbExecutor<'_>,
id: UserId,
name: Option<String>,
image_id: Option<String>,
) -> DbResult<User> {
sqlx::query(
r#"
INSERT INTO "docbox_users" ("id", "name", "image_id")
VALUES ($1, $2, $3)
ON CONFLICT ("id")
DO UPDATE SET "name" = EXCLUDED."name", "image_id" = EXCLUDED."image_id"
"#,
)
.bind(id.as_str())
.bind(name.as_ref())
.bind(image_id.as_ref())
.execute(db)
.await?;
Ok(User { id, name, image_id })
}
pub async fn find(db: impl DbExecutor<'_>, id: &str) -> DbResult<Option<User>> {
sqlx::query_as(r#"SELECT * FROM "docbox_users" WHERE "id" = $1"#)
.bind(id)
.fetch_optional(db)
.await
}
pub async fn query(db: impl DbExecutor<'_>, offset: u64, limit: u64) -> DbResult<Vec<User>> {
sqlx::query_as(
r#"
SELECT * FROM "docbox_users"
ORDER BY "id" DESC
OFFSET $1 LIMIT $2"#,
)
.bind(offset as i64)
.bind(limit as i64)
.fetch_all(db)
.await
}
pub async fn total(db: impl DbExecutor<'_>) -> DbResult<i64> {
let result: CountResult =
sqlx::query_as(r#"SELECT COUNT(*) as "count" FROM "docbox_users""#)
.fetch_one(db)
.await?;
Ok(result.count)
}
pub async fn delete(self, db: impl DbExecutor<'_>) -> DbResult<PgQueryResult> {
sqlx::query(r#"DELETE FROM "docbox_users" WHERE "id" = $1"#)
.bind(self.id)
.execute(db)
.await
}
}