fix: convert all SQLx macros to runtime API, remove SQLX_OFFLINE requirement
This commit is contained in:
parent
58eff5ce63
commit
83c62a1c5e
52 changed files with 553 additions and 572 deletions
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin catering_services
|
RUN cargo build --release --bin catering_services
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
|
||||||
async fn list_catering_services(
|
async fn list_catering_services(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let services = sqlx::query_as!(
|
let services = sqlx::query_as::<_, CateringServiceProfile>(
|
||||||
CateringServiceProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, business_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, business_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM catering_service_profiles
|
FROM catering_service_profiles
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 100
|
LIMIT 100
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(&state.pool)
|
.fetch_all(&state.pool)
|
||||||
.await
|
.await
|
||||||
|
|
@ -61,15 +60,14 @@ async fn get_catering_service(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
Path(id): Path<Uuid>,
|
Path(id): Path<Uuid>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let service = sqlx::query_as!(
|
let service = sqlx::query_as::<_, CateringServiceProfile>(
|
||||||
CateringServiceProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, business_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, business_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM catering_service_profiles
|
FROM catering_service_profiles
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
"#,
|
"#,
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin companies
|
RUN cargo build --release --bin companies
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin cron
|
RUN cargo build --release --bin cron
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin customers
|
RUN cargo build --release --bin customers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,7 @@ pub fn router() -> Router<AppState> {
|
||||||
async fn list_leads(
|
async fn list_leads(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let requirements = sqlx::query_as!(
|
let requirements = sqlx::query_as::<_, Requirement>(
|
||||||
Requirement,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, customer_id, profession_key, title, description, location, budget,
|
SELECT id, customer_id, profession_key, title, description, location, budget,
|
||||||
preferred_date, extra_data_json, status, rejection_reason, request_count, accepted_count,
|
preferred_date, extra_data_json, status, rejection_reason, request_count, accepted_count,
|
||||||
|
|
@ -49,7 +48,7 @@ async fn list_leads(
|
||||||
FROM requirements
|
FROM requirements
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 100
|
LIMIT 100
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(&state.pool)
|
.fetch_all(&state.pool)
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin developers
|
RUN cargo build --release --bin developers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
|
||||||
async fn list_developers(
|
async fn list_developers(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let developers = sqlx::query_as!(
|
let developers = sqlx::query_as::<_, DeveloperProfile>(
|
||||||
DeveloperProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM developer_profiles
|
FROM developer_profiles
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 100
|
LIMIT 100
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(&state.pool)
|
.fetch_all(&state.pool)
|
||||||
.await
|
.await
|
||||||
|
|
@ -61,15 +60,14 @@ async fn get_developer(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
Path(id): Path<Uuid>,
|
Path(id): Path<Uuid>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let developer = sqlx::query_as!(
|
let developer = sqlx::query_as::<_, DeveloperProfile>(
|
||||||
DeveloperProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM developer_profiles
|
FROM developer_profiles
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
"#,
|
"#,
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin employees
|
RUN cargo build --release --bin employees
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin fitness_trainers
|
RUN cargo build --release --bin fitness_trainers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
|
||||||
async fn list_fitness_trainers(
|
async fn list_fitness_trainers(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let trainers = sqlx::query_as!(
|
let trainers = sqlx::query_as::<_, FitnessTrainerProfile>(
|
||||||
FitnessTrainerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM fitness_trainer_profiles
|
FROM fitness_trainer_profiles
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 100
|
LIMIT 100
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(&state.pool)
|
.fetch_all(&state.pool)
|
||||||
.await
|
.await
|
||||||
|
|
@ -61,15 +60,14 @@ async fn get_fitness_trainer(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
Path(id): Path<Uuid>,
|
Path(id): Path<Uuid>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let trainer = sqlx::query_as!(
|
let trainer = sqlx::query_as::<_, FitnessTrainerProfile>(
|
||||||
FitnessTrainerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM fitness_trainer_profiles
|
FROM fitness_trainer_profiles
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
"#,
|
"#,
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin gateway
|
RUN cargo build --release --bin gateway
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin graphic_designers
|
RUN cargo build --release --bin graphic_designers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
|
||||||
async fn list_graphic_designers(
|
async fn list_graphic_designers(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let designers = sqlx::query_as!(
|
let designers = sqlx::query_as::<_, GraphicDesignerProfile>(
|
||||||
GraphicDesignerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM graphic_designer_profiles
|
FROM graphic_designer_profiles
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 100
|
LIMIT 100
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(&state.pool)
|
.fetch_all(&state.pool)
|
||||||
.await
|
.await
|
||||||
|
|
@ -61,15 +60,14 @@ async fn get_graphic_designer(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
Path(id): Path<Uuid>,
|
Path(id): Path<Uuid>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let designer = sqlx::query_as!(
|
let designer = sqlx::query_as::<_, GraphicDesignerProfile>(
|
||||||
GraphicDesignerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM graphic_designer_profiles
|
FROM graphic_designer_profiles
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
"#,
|
"#,
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin job_seekers
|
RUN cargo build --release --bin job_seekers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin makeup_artists
|
RUN cargo build --release --bin makeup_artists
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
|
||||||
async fn list_makeup_artists(
|
async fn list_makeup_artists(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let artists = sqlx::query_as!(
|
let artists = sqlx::query_as::<_, MakeupArtistProfile>(
|
||||||
MakeupArtistProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM makeup_artist_profiles
|
FROM makeup_artist_profiles
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 100
|
LIMIT 100
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(&state.pool)
|
.fetch_all(&state.pool)
|
||||||
.await
|
.await
|
||||||
|
|
@ -61,15 +60,14 @@ async fn get_makeup_artist(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
Path(id): Path<Uuid>,
|
Path(id): Path<Uuid>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let artist = sqlx::query_as!(
|
let artist = sqlx::query_as::<_, MakeupArtistProfile>(
|
||||||
MakeupArtistProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM makeup_artist_profiles
|
FROM makeup_artist_profiles
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
"#,
|
"#,
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin payments
|
RUN cargo build --release --bin payments
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use std::net::SocketAddr;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use sqlx::postgres::PgPool;
|
use sqlx::postgres::PgPool;
|
||||||
|
use sqlx::FromRow;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct AppState {
|
struct AppState {
|
||||||
|
|
@ -57,6 +58,18 @@ struct PaymentStatusResponse {
|
||||||
currency: String,
|
currency: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, FromRow)]
|
||||||
|
struct PricingPackageRow {
|
||||||
|
tracecoins_amount: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, FromRow)]
|
||||||
|
struct PaymentRow {
|
||||||
|
id: Uuid,
|
||||||
|
user_id: Uuid,
|
||||||
|
tracecoins_credited: i32,
|
||||||
|
}
|
||||||
|
|
||||||
async fn create_order(
|
async fn create_order(
|
||||||
auth: AuthUser,
|
auth: AuthUser,
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
|
|
@ -69,10 +82,10 @@ async fn create_order(
|
||||||
let package_id = Uuid::parse_str(package_id_str).map_err(|_| (StatusCode::BAD_REQUEST, "Invalid package id".to_string()))?;
|
let package_id = Uuid::parse_str(package_id_str).map_err(|_| (StatusCode::BAD_REQUEST, "Invalid package id".to_string()))?;
|
||||||
|
|
||||||
// Fetch package to get tracecoins amount
|
// Fetch package to get tracecoins amount
|
||||||
let package = sqlx::query!(
|
let package = sqlx::query_as::<_, PricingPackageRow>(
|
||||||
"SELECT tracecoins_amount FROM pricing_packages WHERE id = $1 AND is_active = true",
|
"SELECT tracecoins_amount FROM pricing_packages WHERE id = $1 AND is_active = true",
|
||||||
package_id
|
|
||||||
)
|
)
|
||||||
|
.bind(package_id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
@ -118,14 +131,14 @@ async fn create_order(
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
// Insert payment record
|
// Insert payment record
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"INSERT INTO payments (user_id, package_id, razorpay_order_id, amount_inr, tracecoins_credited, status) VALUES ($1, $2, $3, $4, $5, 'PENDING')",
|
"INSERT INTO payments (user_id, package_id, razorpay_order_id, amount_inr, tracecoins_credited, status) VALUES ($1, $2, $3, $4, $5, 'PENDING')",
|
||||||
auth.user_id,
|
|
||||||
package_id,
|
|
||||||
order_id,
|
|
||||||
payload.amount as i64,
|
|
||||||
tracecoins_credited
|
|
||||||
)
|
)
|
||||||
|
.bind(auth.user_id)
|
||||||
|
.bind(package_id)
|
||||||
|
.bind(&order_id)
|
||||||
|
.bind(payload.amount as i64)
|
||||||
|
.bind(tracecoins_credited)
|
||||||
.execute(&state.pool)
|
.execute(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
@ -173,10 +186,10 @@ async fn verify_payment(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find pending payment by razorpay_order_id
|
// Find pending payment by razorpay_order_id
|
||||||
let payment = sqlx::query!(
|
let payment = sqlx::query_as::<_, PaymentRow>(
|
||||||
"SELECT id, user_id, tracecoins_credited FROM payments WHERE razorpay_order_id = $1 AND status = 'PENDING'",
|
"SELECT id, user_id, tracecoins_credited FROM payments WHERE razorpay_order_id = $1 AND status = 'PENDING'",
|
||||||
payload.order_id
|
|
||||||
)
|
)
|
||||||
|
.bind(&payload.order_id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
@ -192,41 +205,41 @@ async fn verify_payment(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update payment status to SUCCESS
|
// Update payment status to SUCCESS
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"UPDATE payments SET status = 'SUCCESS', verified_at = NOW(), razorpay_payment_id = $1 WHERE id = $2",
|
"UPDATE payments SET status = 'SUCCESS', verified_at = NOW(), razorpay_payment_id = $1 WHERE id = $2",
|
||||||
payload.payment_id,
|
|
||||||
payment.id
|
|
||||||
)
|
)
|
||||||
|
.bind(&payload.payment_id)
|
||||||
|
.bind(payment.id)
|
||||||
.execute(&state.pool)
|
.execute(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
||||||
// Credit wallet (increase balance)
|
// Credit wallet (increase balance)
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"INSERT INTO tracecoin_wallets (user_id, balance, reserved) VALUES ($1, $2, 0) ON CONFLICT (user_id) DO UPDATE SET balance = tracecoin_wallets.balance + excluded.balance",
|
"INSERT INTO tracecoin_wallets (user_id, balance, reserved) VALUES ($1, $2, 0) ON CONFLICT (user_id) DO UPDATE SET balance = tracecoin_wallets.balance + excluded.balance",
|
||||||
payment.user_id,
|
|
||||||
payment.tracecoins_credited
|
|
||||||
)
|
)
|
||||||
|
.bind(payment.user_id)
|
||||||
|
.bind(payment.tracecoins_credited)
|
||||||
.execute(&state.pool)
|
.execute(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
||||||
// Get wallet id for ledger
|
// Get wallet id for ledger
|
||||||
match sqlx::query_scalar!(
|
match sqlx::query_scalar::<_, Uuid>(
|
||||||
"SELECT id FROM tracecoin_wallets WHERE user_id = $1",
|
"SELECT id FROM tracecoin_wallets WHERE user_id = $1",
|
||||||
payment.user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(payment.user_id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(Some(wallet_id)) => {
|
Ok(Some(wallet_id)) => {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"INSERT INTO tracecoin_ledger (wallet_id, type, amount, reason, reference_id) VALUES ($1, 'CREDIT', $2, $3, $4)",
|
"INSERT INTO tracecoin_ledger (wallet_id, type, amount, reason, reference_id) VALUES ($1, 'CREDIT', $2, $3, $4)",
|
||||||
wallet_id,
|
|
||||||
payment.tracecoins_credited as i64,
|
|
||||||
"PURCHASE",
|
|
||||||
payment.id
|
|
||||||
)
|
)
|
||||||
|
.bind(wallet_id)
|
||||||
|
.bind(payment.tracecoins_credited as i64)
|
||||||
|
.bind("PURCHASE")
|
||||||
|
.bind(payment.id)
|
||||||
.execute(&state.pool)
|
.execute(&state.pool)
|
||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
|
|
@ -235,17 +248,17 @@ async fn verify_payment(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send notification to user about successful purchase
|
// Send notification to user about successful purchase
|
||||||
let _ = sqlx::query!(
|
let _ = sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO notifications (user_id, title, body, type, reference_id)
|
INSERT INTO notifications (user_id, title, body, type, reference_id)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
"#,
|
"#,
|
||||||
payment.user_id,
|
|
||||||
"Tracecoins Purchased Successfully",
|
|
||||||
format!("Your {} Tracecoin package has been credited to your wallet.", payment.tracecoins_credited),
|
|
||||||
"PAYMENT",
|
|
||||||
payment.id
|
|
||||||
)
|
)
|
||||||
|
.bind(payment.user_id)
|
||||||
|
.bind("Tracecoins Purchased Successfully")
|
||||||
|
.bind(format!("Your {} Tracecoin package has been credited to your wallet.", payment.tracecoins_credited))
|
||||||
|
.bind("PAYMENT")
|
||||||
|
.bind(payment.id)
|
||||||
.execute(&state.pool)
|
.execute(&state.pool)
|
||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin photographers
|
RUN cargo build --release --bin photographers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
|
||||||
async fn list_photographers(
|
async fn list_photographers(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let photographers = sqlx::query_as!(
|
let photographers = sqlx::query_as::<_, PhotographerProfile>(
|
||||||
PhotographerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM photographer_profiles
|
FROM photographer_profiles
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 100
|
LIMIT 100
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(&state.pool)
|
.fetch_all(&state.pool)
|
||||||
.await
|
.await
|
||||||
|
|
@ -61,15 +60,14 @@ async fn get_photographer(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
Path(id): Path<Uuid>,
|
Path(id): Path<Uuid>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let photographer = sqlx::query_as!(
|
let photographer = sqlx::query_as::<_, PhotographerProfile>(
|
||||||
PhotographerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM photographer_profiles
|
FROM photographer_profiles
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
"#,
|
"#,
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin social_media_managers
|
RUN cargo build --release --bin social_media_managers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
|
||||||
async fn list_social_media_managers(
|
async fn list_social_media_managers(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let managers = sqlx::query_as!(
|
let managers = sqlx::query_as::<_, SocialMediaManagerProfile>(
|
||||||
SocialMediaManagerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM social_media_manager_profiles
|
FROM social_media_manager_profiles
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 100
|
LIMIT 100
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(&state.pool)
|
.fetch_all(&state.pool)
|
||||||
.await
|
.await
|
||||||
|
|
@ -61,15 +60,14 @@ async fn get_social_media_manager(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
Path(id): Path<Uuid>,
|
Path(id): Path<Uuid>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let manager = sqlx::query_as!(
|
let manager = sqlx::query_as::<_, SocialMediaManagerProfile>(
|
||||||
SocialMediaManagerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM social_media_manager_profiles
|
FROM social_media_manager_profiles
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
"#,
|
"#,
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin tutors
|
RUN cargo build --release --bin tutors
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,14 +43,13 @@ pub fn router() -> Router<ProfessionState> {
|
||||||
async fn list_tutors(
|
async fn list_tutors(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let tutors = sqlx::query_as!(
|
let tutors = sqlx::query_as::<_, TutorProfile>(
|
||||||
TutorProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM tutor_profiles
|
FROM tutor_profiles
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 100
|
LIMIT 100
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(&state.pool)
|
.fetch_all(&state.pool)
|
||||||
.await
|
.await
|
||||||
|
|
@ -64,15 +63,14 @@ async fn get_tutor(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
Path(id): Path<Uuid>,
|
Path(id): Path<Uuid>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let tutor = sqlx::query_as!(
|
let tutor = sqlx::query_as::<_, TutorProfile>(
|
||||||
TutorProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM tutor_profiles
|
FROM tutor_profiles
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
"#,
|
"#,
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin ugc_content_creators
|
RUN cargo build --release --bin ugc_content_creators
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin users
|
RUN cargo build --release --bin users
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./
|
||||||
COPY crates ./crates
|
COPY crates ./crates
|
||||||
COPY apps ./apps
|
COPY apps ./apps
|
||||||
|
|
||||||
ENV SQLX_OFFLINE=true
|
|
||||||
ENV CARGO_BUILD_JOBS=2
|
ENV CARGO_BUILD_JOBS=2
|
||||||
RUN cargo build --release --bin video_editors
|
RUN cargo build --release --bin video_editors
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
|
||||||
async fn list_video_editors(
|
async fn list_video_editors(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let editors = sqlx::query_as!(
|
let editors = sqlx::query_as::<_, VideoEditorProfile>(
|
||||||
VideoEditorProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM video_editor_profiles
|
FROM video_editor_profiles
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 100
|
LIMIT 100
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(&state.pool)
|
.fetch_all(&state.pool)
|
||||||
.await
|
.await
|
||||||
|
|
@ -61,15 +60,14 @@ async fn get_video_editor(
|
||||||
State(state): State<ProfessionState>,
|
State(state): State<ProfessionState>,
|
||||||
Path(id): Path<Uuid>,
|
Path(id): Path<Uuid>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||||
let editor = sqlx::query_as!(
|
let editor = sqlx::query_as::<_, VideoEditorProfile>(
|
||||||
VideoEditorProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at
|
||||||
FROM video_editor_profiles
|
FROM video_editor_profiles
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
"#,
|
"#,
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;
|
||||||
|
|
|
||||||
|
|
@ -31,18 +31,17 @@ impl ApplicationRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
payload: CreateApplicationPayload,
|
payload: CreateApplicationPayload,
|
||||||
) -> Result<Application, sqlx::Error> {
|
) -> Result<Application, sqlx::Error> {
|
||||||
let app = sqlx::query_as!(
|
let app = sqlx::query_as::<_, Application>(
|
||||||
Application,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO applications (job_id, job_seeker_id, cover_letter, resume_url)
|
INSERT INTO applications (job_id, job_seeker_id, cover_letter, resume_url)
|
||||||
VALUES ($1, $2, $3, $4)
|
VALUES ($1, $2, $3, $4)
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
payload.job_id,
|
|
||||||
payload.job_seeker_id,
|
|
||||||
payload.cover_letter,
|
|
||||||
payload.resume_url
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.job_id)
|
||||||
|
.bind(payload.job_seeker_id)
|
||||||
|
.bind(payload.cover_letter)
|
||||||
|
.bind(payload.resume_url)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -50,7 +49,8 @@ impl ApplicationRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result<Option<Application>, sqlx::Error> {
|
pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result<Option<Application>, sqlx::Error> {
|
||||||
sqlx::query_as!(Application, "SELECT * FROM applications WHERE id = $1", id)
|
sqlx::query_as::<_, Application>("SELECT * FROM applications WHERE id = $1")
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -63,19 +63,18 @@ impl ApplicationRepository {
|
||||||
limit: i64,
|
limit: i64,
|
||||||
) -> Result<Vec<Application>, sqlx::Error> {
|
) -> Result<Vec<Application>, sqlx::Error> {
|
||||||
let offset = (page - 1) * limit;
|
let offset = (page - 1) * limit;
|
||||||
let apps = sqlx::query_as!(
|
let apps = sqlx::query_as::<_, Application>(
|
||||||
Application,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT * FROM applications
|
SELECT * FROM applications
|
||||||
WHERE job_id = $1 AND ($2::VARCHAR IS NULL OR status = $2)
|
WHERE job_id = $1 AND ($2::VARCHAR IS NULL OR status = $2)
|
||||||
ORDER BY applied_at DESC
|
ORDER BY applied_at DESC
|
||||||
LIMIT $3 OFFSET $4
|
LIMIT $3 OFFSET $4
|
||||||
"#,
|
"#,
|
||||||
job_id,
|
|
||||||
status,
|
|
||||||
limit,
|
|
||||||
offset
|
|
||||||
)
|
)
|
||||||
|
.bind(job_id)
|
||||||
|
.bind(status)
|
||||||
|
.bind(limit)
|
||||||
|
.bind(offset)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -89,18 +88,17 @@ impl ApplicationRepository {
|
||||||
limit: i64,
|
limit: i64,
|
||||||
) -> Result<Vec<Application>, sqlx::Error> {
|
) -> Result<Vec<Application>, sqlx::Error> {
|
||||||
let offset = (page - 1) * limit;
|
let offset = (page - 1) * limit;
|
||||||
let apps = sqlx::query_as!(
|
let apps = sqlx::query_as::<_, Application>(
|
||||||
Application,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT * FROM applications
|
SELECT * FROM applications
|
||||||
WHERE job_seeker_id = $1
|
WHERE job_seeker_id = $1
|
||||||
ORDER BY applied_at DESC
|
ORDER BY applied_at DESC
|
||||||
LIMIT $2 OFFSET $3
|
LIMIT $2 OFFSET $3
|
||||||
"#,
|
"#,
|
||||||
job_seeker_id,
|
|
||||||
limit,
|
|
||||||
offset
|
|
||||||
)
|
)
|
||||||
|
.bind(job_seeker_id)
|
||||||
|
.bind(limit)
|
||||||
|
.bind(offset)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(apps)
|
Ok(apps)
|
||||||
|
|
@ -111,22 +109,21 @@ impl ApplicationRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
status: &str,
|
status: &str,
|
||||||
) -> Result<Application, sqlx::Error> {
|
) -> Result<Application, sqlx::Error> {
|
||||||
let app = sqlx::query_as!(
|
let app = sqlx::query_as::<_, Application>(
|
||||||
Application,
|
|
||||||
"UPDATE applications SET status = $1, updated_at = NOW() WHERE id = $2 RETURNING *",
|
"UPDATE applications SET status = $1, updated_at = NOW() WHERE id = $2 RETURNING *",
|
||||||
status,
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(status)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(app)
|
Ok(app)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn mark_contact_viewed(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> {
|
pub async fn mark_contact_viewed(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"UPDATE applications SET contact_viewed = true WHERE id = $1",
|
"UPDATE applications SET contact_viewed = true WHERE id = $1",
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -30,19 +30,19 @@ pub struct CateringServiceRepository;
|
||||||
|
|
||||||
impl CateringServiceRepository {
|
impl CateringServiceRepository {
|
||||||
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<CateringServiceProfile>, sqlx::Error> {
|
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<CateringServiceProfile>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, CateringServiceProfile>(
|
||||||
CateringServiceProfile,
|
|
||||||
r#"SELECT id, user_id, business_name, bio, location,
|
r#"SELECT id, user_id, business_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at
|
status, created_at, updated_at
|
||||||
FROM catering_service_profiles WHERE user_id = $1"#,
|
FROM catering_service_profiles WHERE user_id = $1"#,
|
||||||
user_id
|
)
|
||||||
).fetch_optional(pool).await
|
.bind(user_id)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertCateringServiceProfilePayload) -> Result<CateringServiceProfile, sqlx::Error> {
|
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertCateringServiceProfilePayload) -> Result<CateringServiceProfile, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, CateringServiceProfile>(
|
||||||
CateringServiceProfile,
|
|
||||||
r#"INSERT INTO catering_service_profiles (user_id, business_name, bio, location, custom_data)
|
r#"INSERT INTO catering_service_profiles (user_id, business_name, bio, location, custom_data)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
ON CONFLICT (user_id) DO UPDATE SET
|
ON CONFLICT (user_id) DO UPDATE SET
|
||||||
|
|
@ -54,7 +54,13 @@ impl CateringServiceRepository {
|
||||||
RETURNING id, user_id, business_name, bio, location,
|
RETURNING id, user_id, business_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at"#,
|
status, created_at, updated_at"#,
|
||||||
user_id, p.business_name, p.bio, p.location, p.custom_data
|
)
|
||||||
).fetch_one(pool).await
|
.bind(user_id)
|
||||||
|
.bind(p.business_name)
|
||||||
|
.bind(p.bio)
|
||||||
|
.bind(p.location)
|
||||||
|
.bind(p.custom_data)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,7 @@ impl CompanyRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
) -> Result<Option<CompanyProfile>, sqlx::Error> {
|
) -> Result<Option<CompanyProfile>, sqlx::Error> {
|
||||||
let profile = sqlx::query_as!(
|
let profile = sqlx::query_as::<_, CompanyProfile>(
|
||||||
CompanyProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT
|
SELECT
|
||||||
id, user_id, company_name, registration_number, industry,
|
id, user_id, company_name, registration_number, industry,
|
||||||
|
|
@ -69,8 +68,8 @@ impl CompanyRepository {
|
||||||
FROM company_profiles
|
FROM company_profiles
|
||||||
WHERE user_id = $1
|
WHERE user_id = $1
|
||||||
"#,
|
"#,
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -82,8 +81,7 @@ impl CompanyRepository {
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
payload: UpsertCompanyProfilePayload,
|
payload: UpsertCompanyProfilePayload,
|
||||||
) -> Result<CompanyProfile, sqlx::Error> {
|
) -> Result<CompanyProfile, sqlx::Error> {
|
||||||
let profile = sqlx::query_as!(
|
let profile = sqlx::query_as::<_, CompanyProfile>(
|
||||||
CompanyProfile,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO company_profiles (
|
INSERT INTO company_profiles (
|
||||||
user_id, company_name, registration_number, industry, website_url,
|
user_id, company_name, registration_number, industry, website_url,
|
||||||
|
|
@ -119,22 +117,22 @@ impl CompanyRepository {
|
||||||
free_job_slots, purchased_job_slots, free_contact_views, purchased_contact_views,
|
free_job_slots, purchased_job_slots, free_contact_views, purchased_contact_views,
|
||||||
created_at, updated_at
|
created_at, updated_at
|
||||||
"#,
|
"#,
|
||||||
user_id,
|
|
||||||
payload.company_name,
|
|
||||||
payload.registration_number,
|
|
||||||
payload.industry,
|
|
||||||
payload.website_url,
|
|
||||||
payload.employee_count,
|
|
||||||
payload.business_type,
|
|
||||||
payload.gst_number,
|
|
||||||
payload.contact_name,
|
|
||||||
payload.contact_email,
|
|
||||||
payload.contact_phone,
|
|
||||||
payload.address_line1,
|
|
||||||
payload.city,
|
|
||||||
payload.state,
|
|
||||||
payload.postal_code
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.bind(payload.company_name)
|
||||||
|
.bind(payload.registration_number)
|
||||||
|
.bind(payload.industry)
|
||||||
|
.bind(payload.website_url)
|
||||||
|
.bind(payload.employee_count)
|
||||||
|
.bind(payload.business_type)
|
||||||
|
.bind(payload.gst_number)
|
||||||
|
.bind(payload.contact_name)
|
||||||
|
.bind(payload.contact_email)
|
||||||
|
.bind(payload.contact_phone)
|
||||||
|
.bind(payload.address_line1)
|
||||||
|
.bind(payload.city)
|
||||||
|
.bind(payload.state)
|
||||||
|
.bind(payload.postal_code)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -145,8 +143,7 @@ impl CompanyRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
) -> Result<CompanyProfile, sqlx::Error> {
|
) -> Result<CompanyProfile, sqlx::Error> {
|
||||||
let profile = sqlx::query_as!(
|
let profile = sqlx::query_as::<_, CompanyProfile>(
|
||||||
CompanyProfile,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE company_profiles
|
UPDATE company_profiles
|
||||||
SET status = 'PENDING_REVIEW', updated_at = NOW()
|
SET status = 'PENDING_REVIEW', updated_at = NOW()
|
||||||
|
|
@ -159,8 +156,8 @@ impl CompanyRepository {
|
||||||
free_job_slots, purchased_job_slots, free_contact_views, purchased_contact_views,
|
free_job_slots, purchased_job_slots, free_contact_views, purchased_contact_views,
|
||||||
created_at, updated_at
|
created_at, updated_at
|
||||||
"#,
|
"#,
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,20 +82,19 @@ impl ConfigRepository {
|
||||||
payload: CreateOnboardingConfigPayload,
|
payload: CreateOnboardingConfigPayload,
|
||||||
) -> Result<OnboardingConfig, sqlx::Error> {
|
) -> Result<OnboardingConfig, sqlx::Error> {
|
||||||
// Soft-disable previous active configs for this role
|
// Soft-disable previous active configs for this role
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
UPDATE onboarding_configs
|
UPDATE onboarding_configs
|
||||||
SET is_active = false
|
SET is_active = false
|
||||||
WHERE role_id = $1 AND is_active = true
|
WHERE role_id = $1 AND is_active = true
|
||||||
"#,
|
"#,
|
||||||
payload.role_id
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.role_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Insert new config
|
// Insert new config
|
||||||
let config = sqlx::query_as!(
|
let config = sqlx::query_as::<_, OnboardingConfig>(
|
||||||
OnboardingConfig,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO onboarding_configs (role_id, schema_json, version, is_active)
|
INSERT INTO onboarding_configs (role_id, schema_json, version, is_active)
|
||||||
VALUES (
|
VALUES (
|
||||||
|
|
@ -106,9 +105,9 @@ impl ConfigRepository {
|
||||||
)
|
)
|
||||||
RETURNING id, role_id, schema_json, version, is_active, updated_at
|
RETURNING id, role_id, schema_json, version, is_active, updated_at
|
||||||
"#,
|
"#,
|
||||||
payload.role_id,
|
|
||||||
payload.schema_json
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.role_id)
|
||||||
|
.bind(payload.schema_json)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -119,15 +118,14 @@ impl ConfigRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
role_id: Uuid,
|
role_id: Uuid,
|
||||||
) -> Result<OnboardingConfig, sqlx::Error> {
|
) -> Result<OnboardingConfig, sqlx::Error> {
|
||||||
let config = sqlx::query_as!(
|
let config = sqlx::query_as::<_, OnboardingConfig>(
|
||||||
OnboardingConfig,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, role_id, schema_json, version, is_active, updated_at
|
SELECT id, role_id, schema_json, version, is_active, updated_at
|
||||||
FROM onboarding_configs
|
FROM onboarding_configs
|
||||||
WHERE role_id = $1 AND is_active = true
|
WHERE role_id = $1 AND is_active = true
|
||||||
"#,
|
"#,
|
||||||
role_id
|
|
||||||
)
|
)
|
||||||
|
.bind(role_id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -137,8 +135,7 @@ impl ConfigRepository {
|
||||||
pub async fn get_all_onboarding_configs(
|
pub async fn get_all_onboarding_configs(
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
) -> Result<Vec<OnboardingConfigListItem>, sqlx::Error> {
|
) -> Result<Vec<OnboardingConfigListItem>, sqlx::Error> {
|
||||||
let configs = sqlx::query_as!(
|
let configs = sqlx::query_as::<_, OnboardingConfigListItem>(
|
||||||
OnboardingConfigListItem,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT
|
SELECT
|
||||||
c.id, c.role_id, r.key as role_key,
|
c.id, c.role_id, r.key as role_key,
|
||||||
|
|
@ -146,7 +143,7 @@ impl ConfigRepository {
|
||||||
FROM onboarding_configs c
|
FROM onboarding_configs c
|
||||||
JOIN roles r ON c.role_id = r.id
|
JOIN roles r ON c.role_id = r.id
|
||||||
ORDER BY c.updated_at DESC
|
ORDER BY c.updated_at DESC
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
@ -158,16 +155,15 @@ impl ConfigRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
role_key: &str,
|
role_key: &str,
|
||||||
) -> Result<OnboardingConfig, sqlx::Error> {
|
) -> Result<OnboardingConfig, sqlx::Error> {
|
||||||
let config = sqlx::query_as!(
|
let config = sqlx::query_as::<_, OnboardingConfig>(
|
||||||
OnboardingConfig,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT c.id, c.role_id, c.schema_json, c.version, c.is_active, c.updated_at
|
SELECT c.id, c.role_id, c.schema_json, c.version, c.is_active, c.updated_at
|
||||||
FROM onboarding_configs c
|
FROM onboarding_configs c
|
||||||
JOIN roles r ON c.role_id = r.id
|
JOIN roles r ON c.role_id = r.id
|
||||||
WHERE r.key = $1 AND c.is_active = true
|
WHERE r.key = $1 AND c.is_active = true
|
||||||
"#,
|
"#,
|
||||||
role_key.to_uppercase()
|
|
||||||
)
|
)
|
||||||
|
.bind(role_key.to_uppercase())
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -179,21 +175,20 @@ impl ConfigRepository {
|
||||||
payload: CreateDashboardConfigPayload,
|
payload: CreateDashboardConfigPayload,
|
||||||
) -> Result<DashboardConfig, sqlx::Error> {
|
) -> Result<DashboardConfig, sqlx::Error> {
|
||||||
// Soft-disable previous active configs for this role
|
// Soft-disable previous active configs for this role
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
UPDATE dashboard_configs
|
UPDATE dashboard_configs
|
||||||
SET is_active = false
|
SET is_active = false
|
||||||
WHERE role_id = $1 AND audience = $2::text AND is_active = true
|
WHERE role_id = $1 AND audience = $2::text AND is_active = true
|
||||||
"#,
|
"#,
|
||||||
payload.role_id,
|
|
||||||
payload.audience
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.role_id)
|
||||||
|
.bind(&payload.audience)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Insert new config
|
// Insert new config
|
||||||
let config = sqlx::query_as!(
|
let config = sqlx::query_as::<_, DashboardConfig>(
|
||||||
DashboardConfig,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO dashboard_configs (role_id, audience, config_json, version, is_active)
|
INSERT INTO dashboard_configs (role_id, audience, config_json, version, is_active)
|
||||||
VALUES (
|
VALUES (
|
||||||
|
|
@ -205,10 +200,10 @@ impl ConfigRepository {
|
||||||
)
|
)
|
||||||
RETURNING id, role_id, audience, config_json, version, is_active, updated_at
|
RETURNING id, role_id, audience, config_json, version, is_active, updated_at
|
||||||
"#,
|
"#,
|
||||||
payload.role_id,
|
|
||||||
payload.audience,
|
|
||||||
payload.config_json
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.role_id)
|
||||||
|
.bind(&payload.audience)
|
||||||
|
.bind(payload.config_json)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -220,16 +215,15 @@ impl ConfigRepository {
|
||||||
role_id: Uuid,
|
role_id: Uuid,
|
||||||
audience: &str,
|
audience: &str,
|
||||||
) -> Result<DashboardConfig, sqlx::Error> {
|
) -> Result<DashboardConfig, sqlx::Error> {
|
||||||
let config = sqlx::query_as!(
|
let config = sqlx::query_as::<_, DashboardConfig>(
|
||||||
DashboardConfig,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, role_id, audience, config_json, version, is_active, updated_at
|
SELECT id, role_id, audience, config_json, version, is_active, updated_at
|
||||||
FROM dashboard_configs
|
FROM dashboard_configs
|
||||||
WHERE role_id = $1 AND audience = $2 AND is_active = true
|
WHERE role_id = $1 AND audience = $2 AND is_active = true
|
||||||
"#,
|
"#,
|
||||||
role_id,
|
|
||||||
audience
|
|
||||||
)
|
)
|
||||||
|
.bind(role_id)
|
||||||
|
.bind(audience)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -239,8 +233,7 @@ impl ConfigRepository {
|
||||||
pub async fn get_all_dashboard_configs(
|
pub async fn get_all_dashboard_configs(
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
) -> Result<Vec<DashboardConfigListItem>, sqlx::Error> {
|
) -> Result<Vec<DashboardConfigListItem>, sqlx::Error> {
|
||||||
let configs = sqlx::query_as!(
|
let configs = sqlx::query_as::<_, DashboardConfigListItem>(
|
||||||
DashboardConfigListItem,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT
|
SELECT
|
||||||
c.id, c.role_id, r.key as role_key, c.audience,
|
c.id, c.role_id, r.key as role_key, c.audience,
|
||||||
|
|
@ -248,7 +241,7 @@ impl ConfigRepository {
|
||||||
FROM dashboard_configs c
|
FROM dashboard_configs c
|
||||||
JOIN roles r ON c.role_id = r.id
|
JOIN roles r ON c.role_id = r.id
|
||||||
ORDER BY c.updated_at DESC
|
ORDER BY c.updated_at DESC
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
@ -261,17 +254,16 @@ impl ConfigRepository {
|
||||||
role_key: &str,
|
role_key: &str,
|
||||||
audience: &str,
|
audience: &str,
|
||||||
) -> Result<DashboardConfig, sqlx::Error> {
|
) -> Result<DashboardConfig, sqlx::Error> {
|
||||||
let config = sqlx::query_as!(
|
let config = sqlx::query_as::<_, DashboardConfig>(
|
||||||
DashboardConfig,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT c.id, c.role_id, c.audience, c.config_json, c.version, c.is_active, c.updated_at
|
SELECT c.id, c.role_id, c.audience, c.config_json, c.version, c.is_active, c.updated_at
|
||||||
FROM dashboard_configs c
|
FROM dashboard_configs c
|
||||||
JOIN roles r ON c.role_id = r.id
|
JOIN roles r ON c.role_id = r.id
|
||||||
WHERE r.key = $1 AND c.audience = $2 AND c.is_active = true
|
WHERE r.key = $1 AND c.audience = $2 AND c.is_active = true
|
||||||
"#,
|
"#,
|
||||||
role_key.to_uppercase(),
|
|
||||||
audience
|
|
||||||
)
|
)
|
||||||
|
.bind(role_key.to_uppercase())
|
||||||
|
.bind(audience)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -283,20 +275,19 @@ impl ConfigRepository {
|
||||||
payload: CreateRuntimeConfigPayload,
|
payload: CreateRuntimeConfigPayload,
|
||||||
) -> Result<RuntimeConfig, sqlx::Error> {
|
) -> Result<RuntimeConfig, sqlx::Error> {
|
||||||
// Soft-disable previous active configs for this role
|
// Soft-disable previous active configs for this role
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
UPDATE runtime_configs
|
UPDATE runtime_configs
|
||||||
SET is_active = false
|
SET is_active = false
|
||||||
WHERE role_id = $1 AND is_active = true
|
WHERE role_id = $1 AND is_active = true
|
||||||
"#,
|
"#,
|
||||||
payload.role_id
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.role_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Insert new config
|
// Insert new config
|
||||||
let config = sqlx::query_as!(
|
let config = sqlx::query_as::<_, RuntimeConfig>(
|
||||||
RuntimeConfig,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO runtime_configs (role_id, config_json, version, is_active)
|
INSERT INTO runtime_configs (role_id, config_json, version, is_active)
|
||||||
VALUES (
|
VALUES (
|
||||||
|
|
@ -307,9 +298,9 @@ impl ConfigRepository {
|
||||||
)
|
)
|
||||||
RETURNING id, role_id, config_json, version, is_active, updated_at
|
RETURNING id, role_id, config_json, version, is_active, updated_at
|
||||||
"#,
|
"#,
|
||||||
payload.role_id,
|
|
||||||
payload.config_json
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.role_id)
|
||||||
|
.bind(payload.config_json)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -320,15 +311,14 @@ impl ConfigRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
role_id: Uuid,
|
role_id: Uuid,
|
||||||
) -> Result<RuntimeConfig, sqlx::Error> {
|
) -> Result<RuntimeConfig, sqlx::Error> {
|
||||||
let config = sqlx::query_as!(
|
let config = sqlx::query_as::<_, RuntimeConfig>(
|
||||||
RuntimeConfig,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, role_id, config_json, version, is_active, updated_at
|
SELECT id, role_id, config_json, version, is_active, updated_at
|
||||||
FROM runtime_configs
|
FROM runtime_configs
|
||||||
WHERE role_id = $1 AND is_active = true
|
WHERE role_id = $1 AND is_active = true
|
||||||
"#,
|
"#,
|
||||||
role_id
|
|
||||||
)
|
)
|
||||||
|
.bind(role_id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -339,16 +329,15 @@ impl ConfigRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
role_key: &str,
|
role_key: &str,
|
||||||
) -> Result<RuntimeConfig, sqlx::Error> {
|
) -> Result<RuntimeConfig, sqlx::Error> {
|
||||||
let config = sqlx::query_as!(
|
let config = sqlx::query_as::<_, RuntimeConfig>(
|
||||||
RuntimeConfig,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT rc.id, rc.role_id, rc.config_json, rc.version, rc.is_active, rc.updated_at
|
SELECT rc.id, rc.role_id, rc.config_json, rc.version, rc.is_active, rc.updated_at
|
||||||
FROM runtime_configs rc
|
FROM runtime_configs rc
|
||||||
JOIN roles r ON rc.role_id = r.id
|
JOIN roles r ON rc.role_id = r.id
|
||||||
WHERE r.key = $1 AND rc.is_active = true
|
WHERE r.key = $1 AND rc.is_active = true
|
||||||
"#,
|
"#,
|
||||||
role_key.to_uppercase()
|
|
||||||
)
|
)
|
||||||
|
.bind(role_key.to_uppercase())
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,7 @@ impl CustomerRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
) -> Result<Option<CustomerProfile>, sqlx::Error> {
|
) -> Result<Option<CustomerProfile>, sqlx::Error> {
|
||||||
let profile = sqlx::query_as!(
|
let profile = sqlx::query_as::<_, CustomerProfile>(
|
||||||
CustomerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT
|
SELECT
|
||||||
id, user_id, full_name, phone, city, area, preferred_professions,
|
id, user_id, full_name, phone, city, area, preferred_professions,
|
||||||
|
|
@ -49,8 +48,8 @@ impl CustomerRepository {
|
||||||
FROM customer_profiles
|
FROM customer_profiles
|
||||||
WHERE user_id = $1
|
WHERE user_id = $1
|
||||||
"#,
|
"#,
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -62,8 +61,7 @@ impl CustomerRepository {
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
payload: UpsertCustomerProfilePayload,
|
payload: UpsertCustomerProfilePayload,
|
||||||
) -> Result<CustomerProfile, sqlx::Error> {
|
) -> Result<CustomerProfile, sqlx::Error> {
|
||||||
let profile = sqlx::query_as!(
|
let profile = sqlx::query_as::<_, CustomerProfile>(
|
||||||
CustomerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO customer_profiles (
|
INSERT INTO customer_profiles (
|
||||||
user_id, full_name, phone, city, area, preferred_professions, bio, custom_data, status
|
user_id, full_name, phone, city, area, preferred_professions, bio, custom_data, status
|
||||||
|
|
@ -87,15 +85,15 @@ impl CustomerRepository {
|
||||||
active_requirement_count, status, bio, experience_years, custom_data,
|
active_requirement_count, status, bio, experience_years, custom_data,
|
||||||
created_at, updated_at
|
created_at, updated_at
|
||||||
"#,
|
"#,
|
||||||
user_id,
|
|
||||||
payload.full_name,
|
|
||||||
payload.phone,
|
|
||||||
payload.city,
|
|
||||||
payload.area,
|
|
||||||
&payload.preferred_professions.unwrap_or_default(),
|
|
||||||
payload.bio,
|
|
||||||
payload.custom_data
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.bind(payload.full_name)
|
||||||
|
.bind(payload.phone)
|
||||||
|
.bind(payload.city)
|
||||||
|
.bind(payload.area)
|
||||||
|
.bind(payload.preferred_professions.unwrap_or_default())
|
||||||
|
.bind(payload.bio)
|
||||||
|
.bind(payload.custom_data)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -107,11 +105,11 @@ impl CustomerRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
delta: i32,
|
delta: i32,
|
||||||
) -> Result<(), sqlx::Error> {
|
) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"UPDATE customer_profiles SET active_requirement_count = active_requirement_count + $1 WHERE id = $2",
|
"UPDATE customer_profiles SET active_requirement_count = active_requirement_count + $1 WHERE id = $2",
|
||||||
delta,
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(delta)
|
||||||
|
.bind(id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -121,8 +119,7 @@ impl CustomerRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
) -> Result<CustomerProfile, sqlx::Error> {
|
) -> Result<CustomerProfile, sqlx::Error> {
|
||||||
let profile = sqlx::query_as!(
|
let profile = sqlx::query_as::<_, CustomerProfile>(
|
||||||
CustomerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE customer_profiles
|
UPDATE customer_profiles
|
||||||
SET status = 'PENDING_REVIEW', updated_at = NOW()
|
SET status = 'PENDING_REVIEW', updated_at = NOW()
|
||||||
|
|
@ -132,8 +129,8 @@ impl CustomerRepository {
|
||||||
active_requirement_count, status, bio, experience_years, custom_data,
|
active_requirement_count, status, bio, experience_years, custom_data,
|
||||||
created_at, updated_at
|
created_at, updated_at
|
||||||
"#,
|
"#,
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,19 @@ pub struct DeveloperRepository;
|
||||||
|
|
||||||
impl DeveloperRepository {
|
impl DeveloperRepository {
|
||||||
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<DeveloperProfile>, sqlx::Error> {
|
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<DeveloperProfile>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, DeveloperProfile>(
|
||||||
DeveloperProfile,
|
|
||||||
r#"SELECT id, user_id, display_name, bio, location,
|
r#"SELECT id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at
|
status, created_at, updated_at
|
||||||
FROM developer_profiles WHERE user_id = $1"#,
|
FROM developer_profiles WHERE user_id = $1"#,
|
||||||
user_id
|
)
|
||||||
).fetch_optional(pool).await
|
.bind(user_id)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertDeveloperProfilePayload) -> Result<DeveloperProfile, sqlx::Error> {
|
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertDeveloperProfilePayload) -> Result<DeveloperProfile, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, DeveloperProfile>(
|
||||||
DeveloperProfile,
|
|
||||||
r#"INSERT INTO developer_profiles (user_id, display_name, bio, location, custom_data)
|
r#"INSERT INTO developer_profiles (user_id, display_name, bio, location, custom_data)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
ON CONFLICT (user_id) DO UPDATE SET
|
ON CONFLICT (user_id) DO UPDATE SET
|
||||||
|
|
@ -52,7 +52,13 @@ impl DeveloperRepository {
|
||||||
RETURNING id, user_id, display_name, bio, location,
|
RETURNING id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at"#,
|
status, created_at, updated_at"#,
|
||||||
user_id, p.display_name, p.bio, p.location, p.custom_data
|
)
|
||||||
).fetch_one(pool).await
|
.bind(user_id)
|
||||||
|
.bind(p.display_name)
|
||||||
|
.bind(p.bio)
|
||||||
|
.bind(p.location)
|
||||||
|
.bind(p.custom_data)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,8 @@ impl EmployeeRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> {
|
pub async fn delete(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!("DELETE FROM employees WHERE id = $1", id)
|
sqlx::query("DELETE FROM employees WHERE id = $1")
|
||||||
|
.bind(id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,19 @@ pub struct FitnessTrainerRepository;
|
||||||
|
|
||||||
impl FitnessTrainerRepository {
|
impl FitnessTrainerRepository {
|
||||||
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<FitnessTrainerProfile>, sqlx::Error> {
|
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<FitnessTrainerProfile>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, FitnessTrainerProfile>(
|
||||||
FitnessTrainerProfile,
|
|
||||||
r#"SELECT id, user_id, display_name, bio, location,
|
r#"SELECT id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at
|
status, created_at, updated_at
|
||||||
FROM fitness_trainer_profiles WHERE user_id = $1"#,
|
FROM fitness_trainer_profiles WHERE user_id = $1"#,
|
||||||
user_id
|
)
|
||||||
).fetch_optional(pool).await
|
.bind(user_id)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertFitnessTrainerProfilePayload) -> Result<FitnessTrainerProfile, sqlx::Error> {
|
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertFitnessTrainerProfilePayload) -> Result<FitnessTrainerProfile, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, FitnessTrainerProfile>(
|
||||||
FitnessTrainerProfile,
|
|
||||||
r#"INSERT INTO fitness_trainer_profiles (user_id, display_name, bio, location, custom_data)
|
r#"INSERT INTO fitness_trainer_profiles (user_id, display_name, bio, location, custom_data)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
ON CONFLICT (user_id) DO UPDATE SET
|
ON CONFLICT (user_id) DO UPDATE SET
|
||||||
|
|
@ -52,7 +52,13 @@ impl FitnessTrainerRepository {
|
||||||
RETURNING id, user_id, display_name, bio, location,
|
RETURNING id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at"#,
|
status, created_at, updated_at"#,
|
||||||
user_id, p.display_name, p.bio, p.location, p.custom_data
|
)
|
||||||
).fetch_one(pool).await
|
.bind(user_id)
|
||||||
|
.bind(p.display_name)
|
||||||
|
.bind(p.bio)
|
||||||
|
.bind(p.location)
|
||||||
|
.bind(p.custom_data)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,19 @@ pub struct GraphicDesignerRepository;
|
||||||
|
|
||||||
impl GraphicDesignerRepository {
|
impl GraphicDesignerRepository {
|
||||||
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<GraphicDesignerProfile>, sqlx::Error> {
|
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<GraphicDesignerProfile>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, GraphicDesignerProfile>(
|
||||||
GraphicDesignerProfile,
|
|
||||||
r#"SELECT id, user_id, display_name, bio, location,
|
r#"SELECT id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at
|
status, created_at, updated_at
|
||||||
FROM graphic_designer_profiles WHERE user_id = $1"#,
|
FROM graphic_designer_profiles WHERE user_id = $1"#,
|
||||||
user_id
|
)
|
||||||
).fetch_optional(pool).await
|
.bind(user_id)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertGraphicDesignerProfilePayload) -> Result<GraphicDesignerProfile, sqlx::Error> {
|
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertGraphicDesignerProfilePayload) -> Result<GraphicDesignerProfile, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, GraphicDesignerProfile>(
|
||||||
GraphicDesignerProfile,
|
|
||||||
r#"INSERT INTO graphic_designer_profiles (user_id, display_name, bio, location, custom_data)
|
r#"INSERT INTO graphic_designer_profiles (user_id, display_name, bio, location, custom_data)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
ON CONFLICT (user_id) DO UPDATE SET
|
ON CONFLICT (user_id) DO UPDATE SET
|
||||||
|
|
@ -52,7 +52,13 @@ impl GraphicDesignerRepository {
|
||||||
RETURNING id, user_id, display_name, bio, location,
|
RETURNING id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at"#,
|
status, created_at, updated_at"#,
|
||||||
user_id, p.display_name, p.bio, p.location, p.custom_data
|
)
|
||||||
).fetch_one(pool).await
|
.bind(user_id)
|
||||||
|
.bind(p.display_name)
|
||||||
|
.bind(p.bio)
|
||||||
|
.bind(p.location)
|
||||||
|
.bind(p.custom_data)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,7 @@ pub struct JobRepository;
|
||||||
|
|
||||||
impl JobRepository {
|
impl JobRepository {
|
||||||
pub async fn create(pool: &PgPool, payload: CreateJobPayload) -> Result<Job, sqlx::Error> {
|
pub async fn create(pool: &PgPool, payload: CreateJobPayload) -> Result<Job, sqlx::Error> {
|
||||||
let job = sqlx::query_as!(
|
let job = sqlx::query_as::<_, Job>(
|
||||||
Job,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO jobs (
|
INSERT INTO jobs (
|
||||||
company_id, title, category, description, location,
|
company_id, title, category, description, location,
|
||||||
|
|
@ -66,17 +65,17 @@ impl JobRepository {
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
payload.company_id,
|
|
||||||
payload.title,
|
|
||||||
payload.category,
|
|
||||||
payload.description,
|
|
||||||
payload.location,
|
|
||||||
payload.job_type.unwrap_or_else(|| "FULL_TIME".to_string()),
|
|
||||||
payload.salary_min,
|
|
||||||
payload.salary_max,
|
|
||||||
payload.experience_years,
|
|
||||||
&payload.skills.unwrap_or_default()
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.company_id)
|
||||||
|
.bind(payload.title)
|
||||||
|
.bind(payload.category)
|
||||||
|
.bind(payload.description)
|
||||||
|
.bind(payload.location)
|
||||||
|
.bind(payload.job_type.unwrap_or_else(|| "FULL_TIME".to_string()))
|
||||||
|
.bind(payload.salary_min)
|
||||||
|
.bind(payload.salary_max)
|
||||||
|
.bind(payload.experience_years)
|
||||||
|
.bind(payload.skills.unwrap_or_default())
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -84,7 +83,8 @@ impl JobRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result<Option<Job>, sqlx::Error> {
|
pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result<Option<Job>, sqlx::Error> {
|
||||||
sqlx::query_as!(Job, "SELECT * FROM jobs WHERE id = $1", id)
|
sqlx::query_as::<_, Job>("SELECT * FROM jobs WHERE id = $1")
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -97,19 +97,18 @@ impl JobRepository {
|
||||||
limit: i64,
|
limit: i64,
|
||||||
) -> Result<Vec<Job>, sqlx::Error> {
|
) -> Result<Vec<Job>, sqlx::Error> {
|
||||||
let offset = (page - 1) * limit;
|
let offset = (page - 1) * limit;
|
||||||
let jobs = sqlx::query_as!(
|
let jobs = sqlx::query_as::<_, Job>(
|
||||||
Job,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT * FROM jobs
|
SELECT * FROM jobs
|
||||||
WHERE company_id = $1 AND ($2::VARCHAR IS NULL OR status = $2)
|
WHERE company_id = $1 AND ($2::VARCHAR IS NULL OR status = $2)
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT $3 OFFSET $4
|
LIMIT $3 OFFSET $4
|
||||||
"#,
|
"#,
|
||||||
company_id,
|
|
||||||
status,
|
|
||||||
limit,
|
|
||||||
offset
|
|
||||||
)
|
)
|
||||||
|
.bind(company_id)
|
||||||
|
.bind(status)
|
||||||
|
.bind(limit)
|
||||||
|
.bind(offset)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -121,8 +120,7 @@ impl JobRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
payload: UpdateJobPayload,
|
payload: UpdateJobPayload,
|
||||||
) -> Result<Job, sqlx::Error> {
|
) -> Result<Job, sqlx::Error> {
|
||||||
let job = sqlx::query_as!(
|
let job = sqlx::query_as::<_, Job>(
|
||||||
Job,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE jobs SET
|
UPDATE jobs SET
|
||||||
title = COALESCE($1, title),
|
title = COALESCE($1, title),
|
||||||
|
|
@ -138,17 +136,17 @@ impl JobRepository {
|
||||||
WHERE id = $10
|
WHERE id = $10
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
payload.title,
|
|
||||||
payload.category,
|
|
||||||
payload.description,
|
|
||||||
payload.location,
|
|
||||||
payload.job_type,
|
|
||||||
payload.salary_min,
|
|
||||||
payload.salary_max,
|
|
||||||
payload.experience_years,
|
|
||||||
payload.skills.as_deref(),
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.title)
|
||||||
|
.bind(payload.category)
|
||||||
|
.bind(payload.description)
|
||||||
|
.bind(payload.location)
|
||||||
|
.bind(payload.job_type)
|
||||||
|
.bind(payload.salary_min)
|
||||||
|
.bind(payload.salary_max)
|
||||||
|
.bind(payload.experience_years)
|
||||||
|
.bind(payload.skills)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -160,12 +158,11 @@ impl JobRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
status: &str,
|
status: &str,
|
||||||
) -> Result<Job, sqlx::Error> {
|
) -> Result<Job, sqlx::Error> {
|
||||||
let job = sqlx::query_as!(
|
let job = sqlx::query_as::<_, Job>(
|
||||||
Job,
|
|
||||||
"UPDATE jobs SET status = $1, updated_at = NOW() WHERE id = $2 RETURNING *",
|
"UPDATE jobs SET status = $1, updated_at = NOW() WHERE id = $2 RETURNING *",
|
||||||
status,
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(status)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(job)
|
Ok(job)
|
||||||
|
|
@ -176,17 +173,16 @@ impl JobRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
admin_user_id: Uuid,
|
admin_user_id: Uuid,
|
||||||
) -> Result<Job, sqlx::Error> {
|
) -> Result<Job, sqlx::Error> {
|
||||||
let job = sqlx::query_as!(
|
let job = sqlx::query_as::<_, Job>(
|
||||||
Job,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE jobs
|
UPDATE jobs
|
||||||
SET status = 'LIVE', approved_at = NOW(), approved_by = $1, rejection_reason = NULL, updated_at = NOW()
|
SET status = 'LIVE', approved_at = NOW(), approved_by = $1, rejection_reason = NULL, updated_at = NOW()
|
||||||
WHERE id = $2
|
WHERE id = $2
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
admin_user_id,
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(admin_user_id)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(job)
|
Ok(job)
|
||||||
|
|
@ -197,17 +193,16 @@ impl JobRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
reason: Option<String>,
|
reason: Option<String>,
|
||||||
) -> Result<Job, sqlx::Error> {
|
) -> Result<Job, sqlx::Error> {
|
||||||
let job = sqlx::query_as!(
|
let job = sqlx::query_as::<_, Job>(
|
||||||
Job,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE jobs
|
UPDATE jobs
|
||||||
SET status = 'REJECTED', rejection_reason = $1, approved_at = NULL, approved_by = NULL, updated_at = NOW()
|
SET status = 'REJECTED', rejection_reason = $1, approved_at = NULL, approved_by = NULL, updated_at = NOW()
|
||||||
WHERE id = $2
|
WHERE id = $2
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
reason,
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(reason)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(job)
|
Ok(job)
|
||||||
|
|
@ -217,19 +212,19 @@ impl JobRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
company_id: Uuid,
|
company_id: Uuid,
|
||||||
) -> Result<i64, sqlx::Error> {
|
) -> Result<i64, sqlx::Error> {
|
||||||
let count = sqlx::query!(
|
let count = sqlx::query_scalar::<_, i64>(
|
||||||
r#"
|
r#"
|
||||||
SELECT COUNT(*) as "count!"
|
SELECT COUNT(*)
|
||||||
FROM jobs
|
FROM jobs
|
||||||
WHERE company_id = $1
|
WHERE company_id = $1
|
||||||
AND created_at >= date_trunc('month', now())
|
AND created_at >= date_trunc('month', now())
|
||||||
AND status != 'REJECTED'
|
AND status != 'REJECTED'
|
||||||
"#,
|
"#,
|
||||||
company_id
|
|
||||||
)
|
)
|
||||||
|
.bind(company_id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(count.count)
|
Ok(count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,7 @@ impl JobSeekerRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
) -> Result<Option<JobSeekerProfile>, sqlx::Error> {
|
) -> Result<Option<JobSeekerProfile>, sqlx::Error> {
|
||||||
let profile = sqlx::query_as!(
|
let profile = sqlx::query_as::<_, JobSeekerProfile>(
|
||||||
JobSeekerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT
|
SELECT
|
||||||
id, user_id, full_name, location, summary, experience_years,
|
id, user_id, full_name, location, summary, experience_years,
|
||||||
|
|
@ -50,8 +49,8 @@ impl JobSeekerRepository {
|
||||||
FROM job_seeker_profiles
|
FROM job_seeker_profiles
|
||||||
WHERE user_id = $1
|
WHERE user_id = $1
|
||||||
"#,
|
"#,
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -63,8 +62,7 @@ impl JobSeekerRepository {
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
payload: UpsertJobSeekerProfilePayload,
|
payload: UpsertJobSeekerProfilePayload,
|
||||||
) -> Result<JobSeekerProfile, sqlx::Error> {
|
) -> Result<JobSeekerProfile, sqlx::Error> {
|
||||||
let profile = sqlx::query_as!(
|
let profile = sqlx::query_as::<_, JobSeekerProfile>(
|
||||||
JobSeekerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO job_seeker_profiles (
|
INSERT INTO job_seeker_profiles (
|
||||||
user_id, full_name, location, summary, experience_years,
|
user_id, full_name, location, summary, experience_years,
|
||||||
|
|
@ -86,16 +84,16 @@ impl JobSeekerRepository {
|
||||||
skills, resume_url, active_application_count, status, bio, custom_data,
|
skills, resume_url, active_application_count, status, bio, custom_data,
|
||||||
created_at, updated_at
|
created_at, updated_at
|
||||||
"#,
|
"#,
|
||||||
user_id,
|
|
||||||
payload.full_name,
|
|
||||||
payload.location,
|
|
||||||
payload.summary,
|
|
||||||
payload.experience_years.unwrap_or(0),
|
|
||||||
&payload.skills.unwrap_or_default(),
|
|
||||||
payload.resume_url,
|
|
||||||
payload.bio,
|
|
||||||
payload.custom_data
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.bind(payload.full_name)
|
||||||
|
.bind(payload.location)
|
||||||
|
.bind(payload.summary)
|
||||||
|
.bind(payload.experience_years.unwrap_or(0))
|
||||||
|
.bind(payload.skills.unwrap_or_default())
|
||||||
|
.bind(payload.resume_url)
|
||||||
|
.bind(payload.bio)
|
||||||
|
.bind(payload.custom_data)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -107,11 +105,11 @@ impl JobSeekerRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
delta: i32,
|
delta: i32,
|
||||||
) -> Result<(), sqlx::Error> {
|
) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"UPDATE job_seeker_profiles SET active_application_count = active_application_count + $1 WHERE id = $2",
|
"UPDATE job_seeker_profiles SET active_application_count = active_application_count + $1 WHERE id = $2",
|
||||||
delta,
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(delta)
|
||||||
|
.bind(id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -121,8 +119,7 @@ impl JobSeekerRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
) -> Result<JobSeekerProfile, sqlx::Error> {
|
) -> Result<JobSeekerProfile, sqlx::Error> {
|
||||||
let profile = sqlx::query_as!(
|
let profile = sqlx::query_as::<_, JobSeekerProfile>(
|
||||||
JobSeekerProfile,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE job_seeker_profiles
|
UPDATE job_seeker_profiles
|
||||||
SET status = 'PENDING_REVIEW', updated_at = NOW()
|
SET status = 'PENDING_REVIEW', updated_at = NOW()
|
||||||
|
|
@ -132,12 +129,11 @@ impl JobSeekerRepository {
|
||||||
skills, resume_url, active_application_count, status, bio, custom_data,
|
skills, resume_url, active_application_count, status, bio, custom_data,
|
||||||
created_at, updated_at
|
created_at, updated_at
|
||||||
"#,
|
"#,
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(profile)
|
Ok(profile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,17 +31,16 @@ impl LeadRequestRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
payload: CreateLeadRequestPayload,
|
payload: CreateLeadRequestPayload,
|
||||||
) -> Result<LeadRequest, sqlx::Error> {
|
) -> Result<LeadRequest, sqlx::Error> {
|
||||||
let req = sqlx::query_as!(
|
let req = sqlx::query_as::<_, LeadRequest>(
|
||||||
LeadRequest,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO lead_requests (requirement_id, professional_id, expires_at)
|
INSERT INTO lead_requests (requirement_id, professional_id, expires_at)
|
||||||
VALUES ($1, $2, $3)
|
VALUES ($1, $2, $3)
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
payload.requirement_id,
|
|
||||||
payload.professional_id,
|
|
||||||
payload.expires_at
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.requirement_id)
|
||||||
|
.bind(payload.professional_id)
|
||||||
|
.bind(payload.expires_at)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -49,7 +48,8 @@ impl LeadRequestRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result<Option<LeadRequest>, sqlx::Error> {
|
pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result<Option<LeadRequest>, sqlx::Error> {
|
||||||
sqlx::query_as!(LeadRequest, "SELECT * FROM lead_requests WHERE id = $1", id)
|
sqlx::query_as::<_, LeadRequest>("SELECT * FROM lead_requests WHERE id = $1")
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -61,18 +61,17 @@ impl LeadRequestRepository {
|
||||||
limit: i64,
|
limit: i64,
|
||||||
) -> Result<Vec<LeadRequest>, sqlx::Error> {
|
) -> Result<Vec<LeadRequest>, sqlx::Error> {
|
||||||
let offset = (page - 1) * limit;
|
let offset = (page - 1) * limit;
|
||||||
let reqs = sqlx::query_as!(
|
let reqs = sqlx::query_as::<_, LeadRequest>(
|
||||||
LeadRequest,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT * FROM lead_requests
|
SELECT * FROM lead_requests
|
||||||
WHERE requirement_id = $1
|
WHERE requirement_id = $1
|
||||||
ORDER BY requested_at DESC
|
ORDER BY requested_at DESC
|
||||||
LIMIT $2 OFFSET $3
|
LIMIT $2 OFFSET $3
|
||||||
"#,
|
"#,
|
||||||
requirement_id,
|
|
||||||
limit,
|
|
||||||
offset
|
|
||||||
)
|
)
|
||||||
|
.bind(requirement_id)
|
||||||
|
.bind(limit)
|
||||||
|
.bind(offset)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -84,17 +83,16 @@ impl LeadRequestRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
status: &str,
|
status: &str,
|
||||||
) -> Result<LeadRequest, sqlx::Error> {
|
) -> Result<LeadRequest, sqlx::Error> {
|
||||||
let req = sqlx::query_as!(
|
let req = sqlx::query_as::<_, LeadRequest>(
|
||||||
LeadRequest,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE lead_requests
|
UPDATE lead_requests
|
||||||
SET status = $1, resolved_at = NOW(), updated_at = NOW()
|
SET status = $1, resolved_at = NOW(), updated_at = NOW()
|
||||||
WHERE id = $2
|
WHERE id = $2
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
status,
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(status)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(req)
|
Ok(req)
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,19 @@ pub struct MakeupArtistRepository;
|
||||||
|
|
||||||
impl MakeupArtistRepository {
|
impl MakeupArtistRepository {
|
||||||
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<MakeupArtistProfile>, sqlx::Error> {
|
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<MakeupArtistProfile>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, MakeupArtistProfile>(
|
||||||
MakeupArtistProfile,
|
|
||||||
r#"SELECT id, user_id, display_name, bio, location,
|
r#"SELECT id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at
|
status, created_at, updated_at
|
||||||
FROM makeup_artist_profiles WHERE user_id = $1"#,
|
FROM makeup_artist_profiles WHERE user_id = $1"#,
|
||||||
user_id
|
)
|
||||||
).fetch_optional(pool).await
|
.bind(user_id)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertMakeupArtistProfilePayload) -> Result<MakeupArtistProfile, sqlx::Error> {
|
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertMakeupArtistProfilePayload) -> Result<MakeupArtistProfile, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, MakeupArtistProfile>(
|
||||||
MakeupArtistProfile,
|
|
||||||
r#"INSERT INTO makeup_artist_profiles (user_id, display_name, bio, location, custom_data)
|
r#"INSERT INTO makeup_artist_profiles (user_id, display_name, bio, location, custom_data)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
ON CONFLICT (user_id) DO UPDATE SET
|
ON CONFLICT (user_id) DO UPDATE SET
|
||||||
|
|
@ -52,7 +52,13 @@ impl MakeupArtistRepository {
|
||||||
RETURNING id, user_id, display_name, bio, location,
|
RETURNING id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at"#,
|
status, created_at, updated_at"#,
|
||||||
user_id, p.display_name, p.bio, p.location, p.custom_data
|
)
|
||||||
).fetch_one(pool).await
|
.bind(user_id)
|
||||||
|
.bind(p.display_name)
|
||||||
|
.bind(p.bio)
|
||||||
|
.bind(p.location)
|
||||||
|
.bind(p.custom_data)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,17 +41,16 @@ impl OnboardingStateRepository {
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
role_id: Uuid,
|
role_id: Uuid,
|
||||||
) -> Result<Option<OnboardingState>, sqlx::Error> {
|
) -> Result<Option<OnboardingState>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, OnboardingState>(
|
||||||
OnboardingState,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, role_id, status, progress_json,
|
SELECT id, user_id, role_id, status, progress_json,
|
||||||
completed_at, created_at, updated_at
|
completed_at, created_at, updated_at
|
||||||
FROM onboarding_states
|
FROM onboarding_states
|
||||||
WHERE user_id = $1 AND role_id = $2
|
WHERE user_id = $1 AND role_id = $2
|
||||||
"#,
|
"#,
|
||||||
user_id,
|
|
||||||
role_id,
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.bind(role_id)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -63,8 +62,7 @@ impl OnboardingStateRepository {
|
||||||
role_id: Uuid,
|
role_id: Uuid,
|
||||||
progress: &Value,
|
progress: &Value,
|
||||||
) -> Result<OnboardingState, sqlx::Error> {
|
) -> Result<OnboardingState, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, OnboardingState>(
|
||||||
OnboardingState,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO onboarding_states (user_id, role_id, status, progress_json)
|
INSERT INTO onboarding_states (user_id, role_id, status, progress_json)
|
||||||
VALUES ($1, $2, 'IN_PROGRESS', $3)
|
VALUES ($1, $2, 'IN_PROGRESS', $3)
|
||||||
|
|
@ -78,10 +76,10 @@ impl OnboardingStateRepository {
|
||||||
RETURNING id, user_id, role_id, status, progress_json,
|
RETURNING id, user_id, role_id, status, progress_json,
|
||||||
completed_at, created_at, updated_at
|
completed_at, created_at, updated_at
|
||||||
"#,
|
"#,
|
||||||
user_id,
|
|
||||||
role_id,
|
|
||||||
progress,
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.bind(role_id)
|
||||||
|
.bind(progress)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -93,8 +91,7 @@ impl OnboardingStateRepository {
|
||||||
role_id: Uuid,
|
role_id: Uuid,
|
||||||
final_answers: &Value,
|
final_answers: &Value,
|
||||||
) -> Result<OnboardingState, sqlx::Error> {
|
) -> Result<OnboardingState, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, OnboardingState>(
|
||||||
OnboardingState,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO onboarding_states (user_id, role_id, status, progress_json, completed_at)
|
INSERT INTO onboarding_states (user_id, role_id, status, progress_json, completed_at)
|
||||||
VALUES ($1, $2, 'COMPLETED', $3, NOW())
|
VALUES ($1, $2, 'COMPLETED', $3, NOW())
|
||||||
|
|
@ -106,10 +103,10 @@ impl OnboardingStateRepository {
|
||||||
RETURNING id, user_id, role_id, status, progress_json,
|
RETURNING id, user_id, role_id, status, progress_json,
|
||||||
completed_at, created_at, updated_at
|
completed_at, created_at, updated_at
|
||||||
"#,
|
"#,
|
||||||
user_id,
|
|
||||||
role_id,
|
|
||||||
final_answers,
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.bind(role_id)
|
||||||
|
.bind(final_answers)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -120,14 +117,14 @@ impl OnboardingStateRepository {
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
role_id: Uuid,
|
role_id: Uuid,
|
||||||
) -> Result<bool, sqlx::Error> {
|
) -> Result<bool, sqlx::Error> {
|
||||||
let status = sqlx::query_scalar!(
|
let status = sqlx::query_scalar::<_, String>(
|
||||||
r#"
|
r#"
|
||||||
SELECT status FROM onboarding_states
|
SELECT status FROM onboarding_states
|
||||||
WHERE user_id = $1 AND role_id = $2
|
WHERE user_id = $1 AND role_id = $2
|
||||||
"#,
|
"#,
|
||||||
user_id,
|
|
||||||
role_id,
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.bind(role_id)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(status.map(|s| s == "COMPLETED").unwrap_or(false))
|
Ok(status.map(|s| s == "COMPLETED").unwrap_or(false))
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,19 @@ pub struct PhotographerRepository;
|
||||||
|
|
||||||
impl PhotographerRepository {
|
impl PhotographerRepository {
|
||||||
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<PhotographerProfile>, sqlx::Error> {
|
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<PhotographerProfile>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, PhotographerProfile>(
|
||||||
PhotographerProfile,
|
|
||||||
r#"SELECT id, user_id, display_name, bio, location,
|
r#"SELECT id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at
|
status, created_at, updated_at
|
||||||
FROM photographer_profiles WHERE user_id = $1"#,
|
FROM photographer_profiles WHERE user_id = $1"#,
|
||||||
user_id
|
)
|
||||||
).fetch_optional(pool).await
|
.bind(user_id)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertPhotographerProfilePayload) -> Result<PhotographerProfile, sqlx::Error> {
|
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertPhotographerProfilePayload) -> Result<PhotographerProfile, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, PhotographerProfile>(
|
||||||
PhotographerProfile,
|
|
||||||
r#"INSERT INTO photographer_profiles (user_id, display_name, bio, location, custom_data)
|
r#"INSERT INTO photographer_profiles (user_id, display_name, bio, location, custom_data)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
ON CONFLICT (user_id) DO UPDATE SET
|
ON CONFLICT (user_id) DO UPDATE SET
|
||||||
|
|
@ -52,7 +52,13 @@ impl PhotographerRepository {
|
||||||
RETURNING id, user_id, display_name, bio, location,
|
RETURNING id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at"#,
|
status, created_at, updated_at"#,
|
||||||
user_id, p.display_name, p.bio, p.location, p.custom_data
|
)
|
||||||
).fetch_one(pool).await
|
.bind(user_id)
|
||||||
|
.bind(p.display_name)
|
||||||
|
.bind(p.bio)
|
||||||
|
.bind(p.location)
|
||||||
|
.bind(p.custom_data)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -116,11 +116,10 @@ pub struct ProfessionalRepository;
|
||||||
|
|
||||||
impl ProfessionalRepository {
|
impl ProfessionalRepository {
|
||||||
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Professional, sqlx::Error> {
|
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Professional, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, Professional>(
|
||||||
Professional,
|
|
||||||
"SELECT * FROM professionals WHERE user_id = $1",
|
"SELECT * FROM professionals WHERE user_id = $1",
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -132,48 +131,44 @@ impl ProfessionalRepository {
|
||||||
limit: i64,
|
limit: i64,
|
||||||
) -> Result<Vec<Requirement>, sqlx::Error> {
|
) -> Result<Vec<Requirement>, sqlx::Error> {
|
||||||
let offset = (page - 1) * limit;
|
let offset = (page - 1) * limit;
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, Requirement>(
|
||||||
Requirement,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT * FROM requirements
|
SELECT * FROM requirements
|
||||||
WHERE profession_key = $1 AND status = 'OPEN' AND (expires_at IS NULL OR expires_at > NOW())
|
WHERE profession_key = $1 AND status = 'OPEN' AND (expires_at IS NULL OR expires_at > NOW())
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT $2 OFFSET $3
|
LIMIT $2 OFFSET $3
|
||||||
"#,
|
"#,
|
||||||
profession_key,
|
|
||||||
limit,
|
|
||||||
offset
|
|
||||||
)
|
)
|
||||||
|
.bind(profession_key)
|
||||||
|
.bind(limit)
|
||||||
|
.bind(offset)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_portfolio(pool: &PgPool, professional_id: Uuid) -> Result<Vec<PortfolioItem>, sqlx::Error> {
|
pub async fn get_portfolio(pool: &PgPool, professional_id: Uuid) -> Result<Vec<PortfolioItem>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, PortfolioItem>(
|
||||||
PortfolioItem,
|
|
||||||
"SELECT * FROM portfolio_items WHERE professional_id = $1 ORDER BY created_at DESC",
|
"SELECT * FROM portfolio_items WHERE professional_id = $1 ORDER BY created_at DESC",
|
||||||
professional_id
|
|
||||||
)
|
)
|
||||||
|
.bind(professional_id)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_services(pool: &PgPool, professional_id: Uuid) -> Result<Vec<Service>, sqlx::Error> {
|
pub async fn get_services(pool: &PgPool, professional_id: Uuid) -> Result<Vec<Service>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, Service>(
|
||||||
Service,
|
|
||||||
"SELECT * FROM services WHERE professional_id = $1 AND is_active = true ORDER BY name ASC",
|
"SELECT * FROM services WHERE professional_id = $1 AND is_active = true ORDER BY name ASC",
|
||||||
professional_id
|
|
||||||
)
|
)
|
||||||
|
.bind(professional_id)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_wallet(pool: &PgPool, user_id: Uuid) -> Result<Wallet, sqlx::Error> {
|
pub async fn get_wallet(pool: &PgPool, user_id: Uuid) -> Result<Wallet, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, Wallet>(
|
||||||
Wallet,
|
|
||||||
"SELECT * FROM tracecoin_wallets WHERE user_id = $1",
|
"SELECT * FROM tracecoin_wallets WHERE user_id = $1",
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -566,11 +561,10 @@ impl ProfessionalRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
) -> Result<Professional, sqlx::Error> {
|
) -> Result<Professional, sqlx::Error> {
|
||||||
let prof = sqlx::query_as!(
|
let prof = sqlx::query_as::<_, Professional>(
|
||||||
Professional,
|
|
||||||
"SELECT * FROM professionals WHERE user_id = $1",
|
"SELECT * FROM professionals WHERE user_id = $1",
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -578,16 +572,15 @@ impl ProfessionalRepository {
|
||||||
return Err(sqlx::Error::Protocol(format!("Professional profile is already {}", prof.status).into()));
|
return Err(sqlx::Error::Protocol(format!("Professional profile is already {}", prof.status).into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let prof = sqlx::query_as!(
|
let prof = sqlx::query_as::<_, Professional>(
|
||||||
Professional,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE professionals
|
UPDATE professionals
|
||||||
SET status = 'PENDING_REVIEW', updated_at = NOW()
|
SET status = 'PENDING_REVIEW', updated_at = NOW()
|
||||||
WHERE user_id = $1
|
WHERE user_id = $1
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,7 @@ impl RequirementRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
payload: CreateRequirementPayload,
|
payload: CreateRequirementPayload,
|
||||||
) -> Result<Requirement, sqlx::Error> {
|
) -> Result<Requirement, sqlx::Error> {
|
||||||
let req = sqlx::query_as!(
|
let req = sqlx::query_as::<_, Requirement>(
|
||||||
Requirement,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO requirements (
|
INSERT INTO requirements (
|
||||||
customer_id, profession_key, title, description, location,
|
customer_id, profession_key, title, description, location,
|
||||||
|
|
@ -64,15 +63,15 @@ impl RequirementRepository {
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
payload.customer_id,
|
|
||||||
payload.profession_key,
|
|
||||||
payload.title,
|
|
||||||
payload.description,
|
|
||||||
payload.location,
|
|
||||||
payload.budget,
|
|
||||||
payload.preferred_date,
|
|
||||||
payload.extra_data_json
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.customer_id)
|
||||||
|
.bind(payload.profession_key)
|
||||||
|
.bind(payload.title)
|
||||||
|
.bind(payload.description)
|
||||||
|
.bind(payload.location)
|
||||||
|
.bind(payload.budget)
|
||||||
|
.bind(payload.preferred_date)
|
||||||
|
.bind(payload.extra_data_json)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -80,7 +79,8 @@ impl RequirementRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result<Option<Requirement>, sqlx::Error> {
|
pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result<Option<Requirement>, sqlx::Error> {
|
||||||
sqlx::query_as!(Requirement, "SELECT * FROM requirements WHERE id = $1", id)
|
sqlx::query_as::<_, Requirement>("SELECT * FROM requirements WHERE id = $1")
|
||||||
|
.bind(id)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -92,18 +92,17 @@ impl RequirementRepository {
|
||||||
limit: i64,
|
limit: i64,
|
||||||
) -> Result<Vec<Requirement>, sqlx::Error> {
|
) -> Result<Vec<Requirement>, sqlx::Error> {
|
||||||
let offset = (page - 1) * limit;
|
let offset = (page - 1) * limit;
|
||||||
let reqs = sqlx::query_as!(
|
let reqs = sqlx::query_as::<_, Requirement>(
|
||||||
Requirement,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT * FROM requirements
|
SELECT * FROM requirements
|
||||||
WHERE customer_id = $1
|
WHERE customer_id = $1
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT $2 OFFSET $3
|
LIMIT $2 OFFSET $3
|
||||||
"#,
|
"#,
|
||||||
customer_id,
|
|
||||||
limit,
|
|
||||||
offset
|
|
||||||
)
|
)
|
||||||
|
.bind(customer_id)
|
||||||
|
.bind(limit)
|
||||||
|
.bind(offset)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -115,8 +114,7 @@ impl RequirementRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
payload: UpdateRequirementPayload,
|
payload: UpdateRequirementPayload,
|
||||||
) -> Result<Requirement, sqlx::Error> {
|
) -> Result<Requirement, sqlx::Error> {
|
||||||
let req = sqlx::query_as!(
|
let req = sqlx::query_as::<_, Requirement>(
|
||||||
Requirement,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE requirements SET
|
UPDATE requirements SET
|
||||||
title = COALESCE($1, title),
|
title = COALESCE($1, title),
|
||||||
|
|
@ -129,14 +127,14 @@ impl RequirementRepository {
|
||||||
WHERE id = $7
|
WHERE id = $7
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
payload.title,
|
|
||||||
payload.description,
|
|
||||||
payload.location,
|
|
||||||
payload.budget,
|
|
||||||
payload.preferred_date,
|
|
||||||
payload.extra_data_json,
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.title)
|
||||||
|
.bind(payload.description)
|
||||||
|
.bind(payload.location)
|
||||||
|
.bind(payload.budget)
|
||||||
|
.bind(payload.preferred_date)
|
||||||
|
.bind(payload.extra_data_json)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -148,29 +146,29 @@ impl RequirementRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
status: &str,
|
status: &str,
|
||||||
) -> Result<Requirement, sqlx::Error> {
|
) -> Result<Requirement, sqlx::Error> {
|
||||||
let req = sqlx::query_as!(
|
let req = sqlx::query_as::<_, Requirement>(
|
||||||
Requirement,
|
|
||||||
"UPDATE requirements SET status = $1, updated_at = NOW() WHERE id = $2 RETURNING *",
|
"UPDATE requirements SET status = $1, updated_at = NOW() WHERE id = $2 RETURNING *",
|
||||||
status,
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(status)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(req)
|
Ok(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn increment_request_count(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> {
|
pub async fn increment_request_count(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!("UPDATE requirements SET request_count = request_count + 1 WHERE id = $1", id)
|
sqlx::query("UPDATE requirements SET request_count = request_count + 1 WHERE id = $1")
|
||||||
|
.bind(id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn increment_accepted_count(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> {
|
pub async fn increment_accepted_count(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"UPDATE requirements SET accepted_count = accepted_count + 1 WHERE id = $1",
|
"UPDATE requirements SET accepted_count = accepted_count + 1 WHERE id = $1",
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -180,16 +178,15 @@ impl RequirementRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
) -> Result<Requirement, sqlx::Error> {
|
) -> Result<Requirement, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, Requirement>(
|
||||||
Requirement,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE requirements
|
UPDATE requirements
|
||||||
SET accepted_count = accepted_count + 1, updated_at = NOW()
|
SET accepted_count = accepted_count + 1, updated_at = NOW()
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -199,17 +196,16 @@ impl RequirementRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
admin_user_id: Uuid,
|
admin_user_id: Uuid,
|
||||||
) -> Result<Requirement, sqlx::Error> {
|
) -> Result<Requirement, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, Requirement>(
|
||||||
Requirement,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE requirements
|
UPDATE requirements
|
||||||
SET status = 'OPEN', approved_at = NOW(), approved_by = $1, rejection_reason = NULL, updated_at = NOW()
|
SET status = 'OPEN', approved_at = NOW(), approved_by = $1, rejection_reason = NULL, updated_at = NOW()
|
||||||
WHERE id = $2
|
WHERE id = $2
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
admin_user_id,
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(admin_user_id)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -219,17 +215,16 @@ impl RequirementRepository {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
reason: Option<String>,
|
reason: Option<String>,
|
||||||
) -> Result<Requirement, sqlx::Error> {
|
) -> Result<Requirement, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, Requirement>(
|
||||||
Requirement,
|
|
||||||
r#"
|
r#"
|
||||||
UPDATE requirements
|
UPDATE requirements
|
||||||
SET status = 'REJECTED', rejection_reason = $1, approved_at = NULL, approved_by = NULL, updated_at = NOW()
|
SET status = 'REJECTED', rejection_reason = $1, approved_at = NULL, approved_by = NULL, updated_at = NOW()
|
||||||
WHERE id = $2
|
WHERE id = $2
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"#,
|
"#,
|
||||||
reason,
|
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(reason)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,17 +27,16 @@ impl RoleRepository {
|
||||||
pool: &sqlx::PgPool,
|
pool: &sqlx::PgPool,
|
||||||
payload: CreateRolePayload,
|
payload: CreateRolePayload,
|
||||||
) -> Result<Role, sqlx::Error> {
|
) -> Result<Role, sqlx::Error> {
|
||||||
let role = sqlx::query_as!(
|
let role = sqlx::query_as::<_, Role>(
|
||||||
Role,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO roles (key, name, audience)
|
INSERT INTO roles (key, name, audience)
|
||||||
VALUES ($1, $2, $3)
|
VALUES ($1, $2, $3)
|
||||||
RETURNING id, key, name, audience, is_active, created_at
|
RETURNING id, key, name, audience, is_active, created_at
|
||||||
"#,
|
"#,
|
||||||
payload.key,
|
|
||||||
payload.name,
|
|
||||||
payload.audience
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.key)
|
||||||
|
.bind(payload.name)
|
||||||
|
.bind(payload.audience)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -45,13 +44,12 @@ impl RoleRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_all(pool: &sqlx::PgPool) -> Result<Vec<Role>, sqlx::Error> {
|
pub async fn get_all(pool: &sqlx::PgPool) -> Result<Vec<Role>, sqlx::Error> {
|
||||||
let roles = sqlx::query_as!(
|
let roles = sqlx::query_as::<_, Role>(
|
||||||
Role,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, key, name, audience, is_active, created_at
|
SELECT id, key, name, audience, is_active, created_at
|
||||||
FROM roles
|
FROM roles
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
"#
|
"#,
|
||||||
)
|
)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
@ -60,15 +58,14 @@ impl RoleRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_by_key(pool: &sqlx::PgPool, key: &str) -> Result<Role, sqlx::Error> {
|
pub async fn get_by_key(pool: &sqlx::PgPool, key: &str) -> Result<Role, sqlx::Error> {
|
||||||
let role = sqlx::query_as!(
|
let role = sqlx::query_as::<_, Role>(
|
||||||
Role,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, key, name, audience, is_active, created_at
|
SELECT id, key, name, audience, is_active, created_at
|
||||||
FROM roles
|
FROM roles
|
||||||
WHERE key = $1
|
WHERE key = $1
|
||||||
"#,
|
"#,
|
||||||
key
|
|
||||||
)
|
)
|
||||||
|
.bind(key)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,19 @@ pub struct SocialMediaManagerRepository;
|
||||||
|
|
||||||
impl SocialMediaManagerRepository {
|
impl SocialMediaManagerRepository {
|
||||||
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<SocialMediaManagerProfile>, sqlx::Error> {
|
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<SocialMediaManagerProfile>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, SocialMediaManagerProfile>(
|
||||||
SocialMediaManagerProfile,
|
|
||||||
r#"SELECT id, user_id, display_name, bio, location,
|
r#"SELECT id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at
|
status, created_at, updated_at
|
||||||
FROM social_media_manager_profiles WHERE user_id = $1"#,
|
FROM social_media_manager_profiles WHERE user_id = $1"#,
|
||||||
user_id
|
)
|
||||||
).fetch_optional(pool).await
|
.bind(user_id)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertSocialMediaManagerProfilePayload) -> Result<SocialMediaManagerProfile, sqlx::Error> {
|
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertSocialMediaManagerProfilePayload) -> Result<SocialMediaManagerProfile, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, SocialMediaManagerProfile>(
|
||||||
SocialMediaManagerProfile,
|
|
||||||
r#"INSERT INTO social_media_manager_profiles (user_id, display_name, bio, location, custom_data)
|
r#"INSERT INTO social_media_manager_profiles (user_id, display_name, bio, location, custom_data)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
ON CONFLICT (user_id) DO UPDATE SET
|
ON CONFLICT (user_id) DO UPDATE SET
|
||||||
|
|
@ -52,7 +52,13 @@ impl SocialMediaManagerRepository {
|
||||||
RETURNING id, user_id, display_name, bio, location,
|
RETURNING id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at"#,
|
status, created_at, updated_at"#,
|
||||||
user_id, p.display_name, p.bio, p.location, p.custom_data
|
)
|
||||||
).fetch_one(pool).await
|
.bind(user_id)
|
||||||
|
.bind(p.display_name)
|
||||||
|
.bind(p.bio)
|
||||||
|
.bind(p.location)
|
||||||
|
.bind(p.custom_data)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,19 @@ pub struct TutorRepository;
|
||||||
|
|
||||||
impl TutorRepository {
|
impl TutorRepository {
|
||||||
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<TutorProfile>, sqlx::Error> {
|
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<TutorProfile>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, TutorProfile>(
|
||||||
TutorProfile,
|
|
||||||
r#"SELECT id, user_id, display_name, bio, location,
|
r#"SELECT id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at
|
status, created_at, updated_at
|
||||||
FROM tutor_profiles WHERE user_id = $1"#,
|
FROM tutor_profiles WHERE user_id = $1"#,
|
||||||
user_id
|
)
|
||||||
).fetch_optional(pool).await
|
.bind(user_id)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertTutorProfilePayload) -> Result<TutorProfile, sqlx::Error> {
|
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertTutorProfilePayload) -> Result<TutorProfile, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, TutorProfile>(
|
||||||
TutorProfile,
|
|
||||||
r#"INSERT INTO tutor_profiles (user_id, display_name, bio, location, custom_data)
|
r#"INSERT INTO tutor_profiles (user_id, display_name, bio, location, custom_data)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
ON CONFLICT (user_id) DO UPDATE SET
|
ON CONFLICT (user_id) DO UPDATE SET
|
||||||
|
|
@ -52,7 +52,13 @@ impl TutorRepository {
|
||||||
RETURNING id, user_id, display_name, bio, location,
|
RETURNING id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at"#,
|
status, created_at, updated_at"#,
|
||||||
user_id, p.display_name, p.bio, p.location, p.custom_data
|
)
|
||||||
).fetch_one(pool).await
|
.bind(user_id)
|
||||||
|
.bind(p.display_name)
|
||||||
|
.bind(p.bio)
|
||||||
|
.bind(p.location)
|
||||||
|
.bind(p.custom_data)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,19 @@ pub struct UgcContentCreatorRepository;
|
||||||
|
|
||||||
impl UgcContentCreatorRepository {
|
impl UgcContentCreatorRepository {
|
||||||
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<UgcContentCreatorProfile>, sqlx::Error> {
|
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<UgcContentCreatorProfile>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, UgcContentCreatorProfile>(
|
||||||
UgcContentCreatorProfile,
|
|
||||||
r#"SELECT id, user_id, display_name, bio, location,
|
r#"SELECT id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at
|
status, created_at, updated_at
|
||||||
FROM ugc_content_creator_profiles WHERE user_id = $1"#,
|
FROM ugc_content_creator_profiles WHERE user_id = $1"#,
|
||||||
user_id
|
)
|
||||||
).fetch_optional(pool).await
|
.bind(user_id)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertUgcContentCreatorProfilePayload) -> Result<UgcContentCreatorProfile, sqlx::Error> {
|
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertUgcContentCreatorProfilePayload) -> Result<UgcContentCreatorProfile, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, UgcContentCreatorProfile>(
|
||||||
UgcContentCreatorProfile,
|
|
||||||
r#"INSERT INTO ugc_content_creator_profiles (user_id, display_name, bio, location, custom_data)
|
r#"INSERT INTO ugc_content_creator_profiles (user_id, display_name, bio, location, custom_data)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
ON CONFLICT (user_id) DO UPDATE SET
|
ON CONFLICT (user_id) DO UPDATE SET
|
||||||
|
|
@ -52,7 +52,13 @@ impl UgcContentCreatorRepository {
|
||||||
RETURNING id, user_id, display_name, bio, location,
|
RETURNING id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at"#,
|
status, created_at, updated_at"#,
|
||||||
user_id, p.display_name, p.bio, p.location, p.custom_data
|
)
|
||||||
).fetch_one(pool).await
|
.bind(user_id)
|
||||||
|
.bind(p.display_name)
|
||||||
|
.bind(p.bio)
|
||||||
|
.bind(p.location)
|
||||||
|
.bind(p.custom_data)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,7 @@ pub struct UserRepository;
|
||||||
|
|
||||||
impl UserRepository {
|
impl UserRepository {
|
||||||
pub async fn create(pool: &PgPool, payload: CreateUserPayload) -> Result<User, sqlx::Error> {
|
pub async fn create(pool: &PgPool, payload: CreateUserPayload) -> Result<User, sqlx::Error> {
|
||||||
let user = sqlx::query_as!(
|
let user = sqlx::query_as::<_, User>(
|
||||||
User,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO users (full_name, email, phone, password_hash, email_verified, phone_verified)
|
INSERT INTO users (full_name, email, phone, password_hash, email_verified, phone_verified)
|
||||||
VALUES ($1, $2, $3, $4, false, false)
|
VALUES ($1, $2, $3, $4, false, false)
|
||||||
|
|
@ -61,11 +60,11 @@ impl UserRepository {
|
||||||
reset_password_token, reset_password_expires_at,
|
reset_password_token, reset_password_expires_at,
|
||||||
created_at, updated_at, deleted_at
|
created_at, updated_at, deleted_at
|
||||||
"#,
|
"#,
|
||||||
payload.full_name,
|
|
||||||
payload.email.to_lowercase(),
|
|
||||||
payload.phone as Option<String>,
|
|
||||||
payload.password_hash,
|
|
||||||
)
|
)
|
||||||
|
.bind(payload.full_name)
|
||||||
|
.bind(payload.email.to_lowercase())
|
||||||
|
.bind(payload.phone)
|
||||||
|
.bind(payload.password_hash)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -73,8 +72,7 @@ impl UserRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_by_email(pool: &PgPool, email: &str) -> Result<User, sqlx::Error> {
|
pub async fn get_by_email(pool: &PgPool, email: &str) -> Result<User, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, User>(
|
||||||
User,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, email, password_hash, full_name, phone,
|
SELECT id, email, password_hash, full_name, phone,
|
||||||
email_verified, phone_verified, status,
|
email_verified, phone_verified, status,
|
||||||
|
|
@ -84,15 +82,14 @@ impl UserRepository {
|
||||||
FROM users
|
FROM users
|
||||||
WHERE email = $1 AND deleted_at IS NULL
|
WHERE email = $1 AND deleted_at IS NULL
|
||||||
"#,
|
"#,
|
||||||
email.to_lowercase()
|
|
||||||
)
|
)
|
||||||
|
.bind(email.to_lowercase())
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result<User, sqlx::Error> {
|
pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result<User, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, User>(
|
||||||
User,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, email, password_hash, full_name, phone,
|
SELECT id, email, password_hash, full_name, phone,
|
||||||
email_verified, phone_verified, status,
|
email_verified, phone_verified, status,
|
||||||
|
|
@ -102,15 +99,15 @@ impl UserRepository {
|
||||||
FROM users
|
FROM users
|
||||||
WHERE id = $1 AND deleted_at IS NULL
|
WHERE id = $1 AND deleted_at IS NULL
|
||||||
"#,
|
"#,
|
||||||
id
|
|
||||||
)
|
)
|
||||||
|
.bind(id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all approved role keys for a user (e.g. ["COMPANY", "JOB_SEEKER"])
|
/// Returns all approved role keys for a user (e.g. ["COMPANY", "JOB_SEEKER"])
|
||||||
pub async fn get_user_role_keys(pool: &PgPool, user_id: Uuid) -> Result<Vec<String>, sqlx::Error> {
|
pub async fn get_user_role_keys(pool: &PgPool, user_id: Uuid) -> Result<Vec<String>, sqlx::Error> {
|
||||||
let rows = sqlx::query_scalar!(
|
let rows = sqlx::query_scalar::<_, String>(
|
||||||
r#"
|
r#"
|
||||||
SELECT r.key
|
SELECT r.key
|
||||||
FROM user_roles ur
|
FROM user_roles ur
|
||||||
|
|
@ -118,8 +115,8 @@ impl UserRepository {
|
||||||
WHERE ur.user_id = $1 AND ur.status = 'APPROVED'
|
WHERE ur.user_id = $1 AND ur.status = 'APPROVED'
|
||||||
ORDER BY ur.approved_at ASC
|
ORDER BY ur.approved_at ASC
|
||||||
"#,
|
"#,
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -133,24 +130,23 @@ impl UserRepository {
|
||||||
token: &str,
|
token: &str,
|
||||||
expires_at: DateTime<Utc>,
|
expires_at: DateTime<Utc>,
|
||||||
) -> Result<(), sqlx::Error> {
|
) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
UPDATE users
|
UPDATE users
|
||||||
SET email_verification_token = $1, email_verification_expires_at = $2, updated_at = NOW()
|
SET email_verification_token = $1, email_verification_expires_at = $2, updated_at = NOW()
|
||||||
WHERE id = $3
|
WHERE id = $3
|
||||||
"#,
|
"#,
|
||||||
token,
|
|
||||||
expires_at,
|
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(token)
|
||||||
|
.bind(expires_at)
|
||||||
|
.bind(user_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_by_verification_token(pool: &PgPool, token: &str) -> Result<User, sqlx::Error> {
|
pub async fn get_by_verification_token(pool: &PgPool, token: &str) -> Result<User, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, User>(
|
||||||
User,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, email, password_hash, full_name, phone,
|
SELECT id, email, password_hash, full_name, phone,
|
||||||
email_verified, phone_verified, status,
|
email_verified, phone_verified, status,
|
||||||
|
|
@ -160,17 +156,17 @@ impl UserRepository {
|
||||||
FROM users
|
FROM users
|
||||||
WHERE email_verification_token = $1 AND deleted_at IS NULL
|
WHERE email_verification_token = $1 AND deleted_at IS NULL
|
||||||
"#,
|
"#,
|
||||||
token
|
|
||||||
)
|
)
|
||||||
|
.bind(token)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_email_verified(pool: &PgPool, user_id: Uuid) -> Result<(), sqlx::Error> {
|
pub async fn set_email_verified(pool: &PgPool, user_id: Uuid) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"UPDATE users SET email_verified = true, email_verification_token = NULL, email_verification_expires_at = NULL, updated_at = NOW() WHERE id = $1",
|
"UPDATE users SET email_verified = true, email_verification_token = NULL, email_verification_expires_at = NULL, updated_at = NOW() WHERE id = $1",
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -182,24 +178,23 @@ impl UserRepository {
|
||||||
token: &str,
|
token: &str,
|
||||||
expires_at: DateTime<Utc>,
|
expires_at: DateTime<Utc>,
|
||||||
) -> Result<(), sqlx::Error> {
|
) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
UPDATE users
|
UPDATE users
|
||||||
SET reset_password_token = $1, reset_password_expires_at = $2, updated_at = NOW()
|
SET reset_password_token = $1, reset_password_expires_at = $2, updated_at = NOW()
|
||||||
WHERE id = $3
|
WHERE id = $3
|
||||||
"#,
|
"#,
|
||||||
token,
|
|
||||||
expires_at,
|
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(token)
|
||||||
|
.bind(expires_at)
|
||||||
|
.bind(user_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_by_reset_token(pool: &PgPool, token: &str) -> Result<User, sqlx::Error> {
|
pub async fn get_by_reset_token(pool: &PgPool, token: &str) -> Result<User, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, User>(
|
||||||
User,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, email, password_hash, full_name, phone,
|
SELECT id, email, password_hash, full_name, phone,
|
||||||
email_verified, phone_verified, status,
|
email_verified, phone_verified, status,
|
||||||
|
|
@ -209,39 +204,39 @@ impl UserRepository {
|
||||||
FROM users
|
FROM users
|
||||||
WHERE reset_password_token = $1 AND deleted_at IS NULL
|
WHERE reset_password_token = $1 AND deleted_at IS NULL
|
||||||
"#,
|
"#,
|
||||||
token
|
|
||||||
)
|
)
|
||||||
|
.bind(token)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn clear_reset_token(pool: &PgPool, user_id: Uuid) -> Result<(), sqlx::Error> {
|
pub async fn clear_reset_token(pool: &PgPool, user_id: Uuid) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"UPDATE users SET reset_password_token = NULL, reset_password_expires_at = NULL, updated_at = NOW() WHERE id = $1",
|
"UPDATE users SET reset_password_token = NULL, reset_password_expires_at = NULL, updated_at = NOW() WHERE id = $1",
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_password(pool: &PgPool, user_id: Uuid, password_hash: &str) -> Result<(), sqlx::Error> {
|
pub async fn update_password(pool: &PgPool, user_id: Uuid, password_hash: &str) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"UPDATE users SET password_hash = $1, updated_at = NOW() WHERE id = $2",
|
"UPDATE users SET password_hash = $1, updated_at = NOW() WHERE id = $2",
|
||||||
password_hash,
|
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(password_hash)
|
||||||
|
.bind(user_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_status(pool: &PgPool, user_id: Uuid, status: &str) -> Result<(), sqlx::Error> {
|
pub async fn update_status(pool: &PgPool, user_id: Uuid, status: &str) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"UPDATE users SET status = $1, updated_at = NOW() WHERE id = $2",
|
"UPDATE users SET status = $1, updated_at = NOW() WHERE id = $2",
|
||||||
status,
|
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(status)
|
||||||
|
.bind(user_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -253,17 +248,16 @@ impl UserRepository {
|
||||||
token_hash: &str,
|
token_hash: &str,
|
||||||
expires_at: DateTime<Utc>,
|
expires_at: DateTime<Utc>,
|
||||||
) -> Result<RefreshToken, sqlx::Error> {
|
) -> Result<RefreshToken, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, RefreshToken>(
|
||||||
RefreshToken,
|
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO refresh_tokens (user_id, token_hash, expires_at)
|
INSERT INTO refresh_tokens (user_id, token_hash, expires_at)
|
||||||
VALUES ($1, $2, $3)
|
VALUES ($1, $2, $3)
|
||||||
RETURNING id, user_id, token_hash, expires_at, revoked, created_at
|
RETURNING id, user_id, token_hash, expires_at, revoked, created_at
|
||||||
"#,
|
"#,
|
||||||
user_id,
|
|
||||||
token_hash,
|
|
||||||
expires_at
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.bind(token_hash)
|
||||||
|
.bind(expires_at)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
@ -272,8 +266,7 @@ impl UserRepository {
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
token_hash: &str,
|
token_hash: &str,
|
||||||
) -> Result<RefreshToken, sqlx::Error> {
|
) -> Result<RefreshToken, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, RefreshToken>(
|
||||||
RefreshToken,
|
|
||||||
r#"
|
r#"
|
||||||
SELECT id, user_id, token_hash, expires_at, revoked, created_at
|
SELECT id, user_id, token_hash, expires_at, revoked, created_at
|
||||||
FROM refresh_tokens
|
FROM refresh_tokens
|
||||||
|
|
@ -281,27 +274,27 @@ impl UserRepository {
|
||||||
AND revoked = false
|
AND revoked = false
|
||||||
AND expires_at > NOW()
|
AND expires_at > NOW()
|
||||||
"#,
|
"#,
|
||||||
token_hash
|
|
||||||
)
|
)
|
||||||
|
.bind(token_hash)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn revoke_refresh_token(pool: &PgPool, token_hash: &str) -> Result<(), sqlx::Error> {
|
pub async fn revoke_refresh_token(pool: &PgPool, token_hash: &str) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"UPDATE refresh_tokens SET revoked = true WHERE token_hash = $1",
|
"UPDATE refresh_tokens SET revoked = true WHERE token_hash = $1",
|
||||||
token_hash
|
|
||||||
)
|
)
|
||||||
|
.bind(token_hash)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn revoke_all_for_user(pool: &PgPool, user_id: Uuid) -> Result<(), sqlx::Error> {
|
pub async fn revoke_all_for_user(pool: &PgPool, user_id: Uuid) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!(
|
sqlx::query(
|
||||||
"UPDATE refresh_tokens SET revoked = true WHERE user_id = $1",
|
"UPDATE refresh_tokens SET revoked = true WHERE user_id = $1",
|
||||||
user_id
|
|
||||||
)
|
)
|
||||||
|
.bind(user_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,19 @@ pub struct VideoEditorRepository;
|
||||||
|
|
||||||
impl VideoEditorRepository {
|
impl VideoEditorRepository {
|
||||||
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<VideoEditorProfile>, sqlx::Error> {
|
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<VideoEditorProfile>, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, VideoEditorProfile>(
|
||||||
VideoEditorProfile,
|
|
||||||
r#"SELECT id, user_id, display_name, bio, location,
|
r#"SELECT id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at
|
status, created_at, updated_at
|
||||||
FROM video_editor_profiles WHERE user_id = $1"#,
|
FROM video_editor_profiles WHERE user_id = $1"#,
|
||||||
user_id
|
)
|
||||||
).fetch_optional(pool).await
|
.bind(user_id)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertVideoEditorProfilePayload) -> Result<VideoEditorProfile, sqlx::Error> {
|
pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertVideoEditorProfilePayload) -> Result<VideoEditorProfile, sqlx::Error> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as::<_, VideoEditorProfile>(
|
||||||
VideoEditorProfile,
|
|
||||||
r#"INSERT INTO video_editor_profiles (user_id, display_name, bio, location, custom_data)
|
r#"INSERT INTO video_editor_profiles (user_id, display_name, bio, location, custom_data)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
ON CONFLICT (user_id) DO UPDATE SET
|
ON CONFLICT (user_id) DO UPDATE SET
|
||||||
|
|
@ -52,7 +52,13 @@ impl VideoEditorRepository {
|
||||||
RETURNING id, user_id, display_name, bio, location,
|
RETURNING id, user_id, display_name, bio, location,
|
||||||
custom_data,
|
custom_data,
|
||||||
status, created_at, updated_at"#,
|
status, created_at, updated_at"#,
|
||||||
user_id, p.display_name, p.bio, p.location, p.custom_data
|
)
|
||||||
).fetch_one(pool).await
|
.bind(user_id)
|
||||||
|
.bind(p.display_name)
|
||||||
|
.bind(p.bio)
|
||||||
|
.bind(p.location)
|
||||||
|
.bind(p.custom_data)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue