first commit
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::db::models::{ContactCandidate, NewContactCandidate};
|
||||
use crate::db::{Db, Page, Pagination, db_error};
|
||||
use crate::error::AppResult;
|
||||
|
||||
pub async fn upsert(db: &Db, input: &NewContactCandidate) -> AppResult<ContactCandidate> {
|
||||
let client = db.client().await?;
|
||||
let row = client
|
||||
.query_one(
|
||||
"INSERT INTO contact_candidates (
|
||||
run_id, interviewee_id, origin_id, crawl_page_id, contact_type,
|
||||
raw_value, normalized_value, proposed_relationship_kind, proposed_label,
|
||||
evidence, confidence, ai_call_id
|
||||
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12)
|
||||
ON CONFLICT (run_id, interviewee_id, origin_id, contact_type, normalized_value)
|
||||
DO UPDATE SET
|
||||
raw_value = EXCLUDED.raw_value,
|
||||
proposed_relationship_kind = COALESCE(EXCLUDED.proposed_relationship_kind, contact_candidates.proposed_relationship_kind),
|
||||
proposed_label = COALESCE(EXCLUDED.proposed_label, contact_candidates.proposed_label),
|
||||
evidence = CASE WHEN EXCLUDED.confidence >= contact_candidates.confidence THEN EXCLUDED.evidence ELSE contact_candidates.evidence END,
|
||||
confidence = GREATEST(contact_candidates.confidence, EXCLUDED.confidence),
|
||||
ai_call_id = COALESCE(EXCLUDED.ai_call_id, contact_candidates.ai_call_id)
|
||||
RETURNING *",
|
||||
&[
|
||||
&input.run_id,
|
||||
&input.interviewee_id,
|
||||
&input.origin_id,
|
||||
&input.crawl_page_id,
|
||||
&input.contact_type,
|
||||
&input.raw_value,
|
||||
&input.normalized_value,
|
||||
&input.proposed_relationship_kind,
|
||||
&input.proposed_label,
|
||||
&input.evidence,
|
||||
&input.confidence,
|
||||
&input.ai_call_id,
|
||||
],
|
||||
)
|
||||
.await
|
||||
.map_err(db_error)?;
|
||||
ContactCandidate::from_row(&row).map_err(db_error)
|
||||
}
|
||||
|
||||
pub async fn get(db: &Db, id: Uuid) -> AppResult<Option<ContactCandidate>> {
|
||||
let client = db.client().await?;
|
||||
client
|
||||
.query_opt("SELECT * FROM contact_candidates WHERE id = $1", &[&id])
|
||||
.await
|
||||
.map_err(db_error)?
|
||||
.map(|row| ContactCandidate::from_row(&row))
|
||||
.transpose()
|
||||
.map_err(db_error)
|
||||
}
|
||||
|
||||
pub async fn list_for_review(
|
||||
db: &Db,
|
||||
run_id: Option<Uuid>,
|
||||
interviewee_id: Option<Uuid>,
|
||||
status: Option<&str>,
|
||||
pagination: Pagination,
|
||||
) -> AppResult<Page<ContactCandidate>> {
|
||||
let client = db.client().await?;
|
||||
let predicate = "($1::uuid IS NULL OR run_id = $1)
|
||||
AND ($2::uuid IS NULL OR interviewee_id = $2)
|
||||
AND ($3::text IS NULL OR status = $3)";
|
||||
let total_sql = format!("SELECT count(*)::bigint FROM contact_candidates WHERE {predicate}");
|
||||
let total: i64 = client
|
||||
.query_one(&total_sql, &[&run_id, &interviewee_id, &status])
|
||||
.await
|
||||
.map_err(db_error)?
|
||||
.get(0);
|
||||
let list_sql = format!(
|
||||
"SELECT * FROM contact_candidates WHERE {predicate}
|
||||
ORDER BY CASE status WHEN 'needs_review' THEN 0 WHEN 'pending' THEN 1 ELSE 2 END,
|
||||
confidence DESC, created_at
|
||||
LIMIT $4 OFFSET $5"
|
||||
);
|
||||
let rows = client
|
||||
.query(
|
||||
&list_sql,
|
||||
&[
|
||||
&run_id,
|
||||
&interviewee_id,
|
||||
&status,
|
||||
&pagination.limit,
|
||||
&pagination.offset,
|
||||
],
|
||||
)
|
||||
.await
|
||||
.map_err(db_error)?;
|
||||
let items = rows
|
||||
.iter()
|
||||
.map(ContactCandidate::from_row)
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(db_error)?;
|
||||
Ok(Page::new(items, total, pagination))
|
||||
}
|
||||
|
||||
pub async fn decide(
|
||||
db: &Db,
|
||||
id: Uuid,
|
||||
status: &str,
|
||||
accepted_contact_id: Option<Uuid>,
|
||||
rejection_reason: Option<&str>,
|
||||
) -> AppResult<Option<ContactCandidate>> {
|
||||
let client = db.client().await?;
|
||||
client
|
||||
.query_opt(
|
||||
"UPDATE contact_candidates SET
|
||||
status = $2,
|
||||
accepted_contact_id = $3,
|
||||
rejection_reason = $4
|
||||
WHERE id = $1 RETURNING *",
|
||||
&[&id, &status, &accepted_contact_id, &rejection_reason],
|
||||
)
|
||||
.await
|
||||
.map_err(db_error)?
|
||||
.map(|row| ContactCandidate::from_row(&row))
|
||||
.transpose()
|
||||
.map_err(db_error)
|
||||
}
|
||||
Reference in New Issue
Block a user