2026-03-17 20:42:51 +01:00
|
|
|
use chrono::{DateTime, Utc};
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use sqlx::{FromRow, PgPool};
|
|
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize, FromRow)]
|
|
|
|
|
pub struct Application {
|
|
|
|
|
pub id: Uuid,
|
2026-07-19 16:34:00 +05:30
|
|
|
pub reference_number: String,
|
2026-03-17 20:42:51 +01:00
|
|
|
pub job_id: Uuid,
|
2026-04-13 00:29:44 +02:00
|
|
|
pub applicant_user_id: Uuid,
|
|
|
|
|
pub cover_note: Option<String>,
|
|
|
|
|
pub status: String,
|
2026-03-17 20:42:51 +01:00
|
|
|
pub applied_at: DateTime<Utc>,
|
|
|
|
|
pub updated_at: DateTime<Utc>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
|
pub struct CreateApplicationPayload {
|
|
|
|
|
pub job_id: Uuid,
|
2026-04-13 00:29:44 +02:00
|
|
|
pub applicant_user_id: Uuid,
|
|
|
|
|
pub cover_note: Option<String>,
|
2026-03-17 20:42:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct ApplicationRepository;
|
|
|
|
|
|
|
|
|
|
impl ApplicationRepository {
|
|
|
|
|
pub async fn create(
|
|
|
|
|
pool: &PgPool,
|
|
|
|
|
payload: CreateApplicationPayload,
|
|
|
|
|
) -> Result<Application, sqlx::Error> {
|
2026-04-09 07:40:15 +02:00
|
|
|
let app = sqlx::query_as::<_, Application>(
|
2026-03-17 20:42:51 +01:00
|
|
|
r#"
|
2026-04-13 00:29:44 +02:00
|
|
|
INSERT INTO job_applications (job_id, applicant_user_id, cover_note)
|
|
|
|
|
VALUES ($1, $2, $3)
|
2026-03-17 20:42:51 +01:00
|
|
|
RETURNING *
|
|
|
|
|
"#,
|
|
|
|
|
)
|
2026-04-09 07:40:15 +02:00
|
|
|
.bind(payload.job_id)
|
2026-04-13 00:29:44 +02:00
|
|
|
.bind(payload.applicant_user_id)
|
|
|
|
|
.bind(payload.cover_note)
|
2026-03-17 20:42:51 +01:00
|
|
|
.fetch_one(pool)
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
Ok(app)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result<Option<Application>, sqlx::Error> {
|
2026-04-13 00:29:44 +02:00
|
|
|
sqlx::query_as::<_, Application>("SELECT * FROM job_applications WHERE id = $1")
|
2026-04-09 07:40:15 +02:00
|
|
|
.bind(id)
|
2026-03-17 20:42:51 +01:00
|
|
|
.fetch_optional(pool)
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn list_by_job_id(
|
|
|
|
|
pool: &PgPool,
|
|
|
|
|
job_id: Uuid,
|
|
|
|
|
status: Option<String>,
|
|
|
|
|
page: i64,
|
|
|
|
|
limit: i64,
|
|
|
|
|
) -> Result<Vec<Application>, sqlx::Error> {
|
|
|
|
|
let offset = (page - 1) * limit;
|
2026-04-09 07:40:15 +02:00
|
|
|
let apps = sqlx::query_as::<_, Application>(
|
2026-03-17 20:42:51 +01:00
|
|
|
r#"
|
2026-04-13 00:29:44 +02:00
|
|
|
SELECT * FROM job_applications
|
2026-03-17 20:42:51 +01:00
|
|
|
WHERE job_id = $1 AND ($2::VARCHAR IS NULL OR status = $2)
|
|
|
|
|
ORDER BY applied_at DESC
|
|
|
|
|
LIMIT $3 OFFSET $4
|
|
|
|
|
"#,
|
|
|
|
|
)
|
2026-04-09 07:40:15 +02:00
|
|
|
.bind(job_id)
|
|
|
|
|
.bind(status)
|
|
|
|
|
.bind(limit)
|
|
|
|
|
.bind(offset)
|
2026-03-17 20:42:51 +01:00
|
|
|
.fetch_all(pool)
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
Ok(apps)
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-13 00:29:44 +02:00
|
|
|
pub async fn list_by_user_id(
|
2026-03-17 20:42:51 +01:00
|
|
|
pool: &PgPool,
|
2026-04-13 00:29:44 +02:00
|
|
|
applicant_user_id: Uuid,
|
2026-03-17 20:42:51 +01:00
|
|
|
page: i64,
|
|
|
|
|
limit: i64,
|
|
|
|
|
) -> Result<Vec<Application>, sqlx::Error> {
|
|
|
|
|
let offset = (page - 1) * limit;
|
2026-04-09 07:40:15 +02:00
|
|
|
let apps = sqlx::query_as::<_, Application>(
|
2026-03-17 20:42:51 +01:00
|
|
|
r#"
|
2026-04-13 00:29:44 +02:00
|
|
|
SELECT * FROM job_applications
|
|
|
|
|
WHERE applicant_user_id = $1
|
2026-03-17 20:42:51 +01:00
|
|
|
ORDER BY applied_at DESC
|
|
|
|
|
LIMIT $2 OFFSET $3
|
|
|
|
|
"#,
|
|
|
|
|
)
|
2026-04-13 00:29:44 +02:00
|
|
|
.bind(applicant_user_id)
|
2026-04-09 07:40:15 +02:00
|
|
|
.bind(limit)
|
|
|
|
|
.bind(offset)
|
2026-03-17 20:42:51 +01:00
|
|
|
.fetch_all(pool)
|
|
|
|
|
.await?;
|
|
|
|
|
Ok(apps)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn update_status(
|
|
|
|
|
pool: &PgPool,
|
|
|
|
|
id: Uuid,
|
|
|
|
|
status: &str,
|
|
|
|
|
) -> Result<Application, sqlx::Error> {
|
2026-04-09 07:40:15 +02:00
|
|
|
let app = sqlx::query_as::<_, Application>(
|
2026-04-13 00:29:44 +02:00
|
|
|
"UPDATE job_applications SET status = $1, updated_at = NOW() WHERE id = $2 RETURNING *",
|
2026-03-17 20:42:51 +01:00
|
|
|
)
|
2026-04-09 07:40:15 +02:00
|
|
|
.bind(status)
|
|
|
|
|
.bind(id)
|
2026-03-17 20:42:51 +01:00
|
|
|
.fetch_one(pool)
|
|
|
|
|
.await?;
|
|
|
|
|
Ok(app)
|
|
|
|
|
}
|
|
|
|
|
}
|