use crate::domain::error::AppResult; use crate::infrastructure::db::DbPool; use serde::{Deserialize, Serialize}; use uuid::Uuid; #[derive(Debug, Serialize, Deserialize, sqlx::FromRow)] pub struct DisputeEvidence { pub evidence_id: Uuid, pub transaction_id: String, pub evidence_url: String, pub uploader_role: String, pub metadata: serde_json::Value, } pub struct ArbitrationService { pool: DbPool, } impl ArbitrationService { pub fn new(pool: DbPool) -> Self { Self { pool } } pub async fn upload_evidence( &self, transaction_id: &str, evidence_url: &str, role: &str, ) -> AppResult { let evidence_id = Uuid::new_v4(); sqlx::query( "INSERT INTO dispute_evidence (evidence_id, transaction_id, evidence_url, uploader_role) VALUES ($1, $2, $3, $4)" ) .bind(evidence_id) .bind(transaction_id) .bind(evidence_url) .bind(role) .execute(&self.pool) .await?; Ok(evidence_id) } pub async fn get_evidence_for_transaction( &self, transaction_id: &str, ) -> AppResult> { let evidence = sqlx::query_as::<_, DisputeEvidence>( r#"SELECT evidence_id, transaction_id, evidence_url, uploader_role, metadata FROM dispute_evidence WHERE transaction_id = $1"# ) .bind(transaction_id) .fetch_all(&self.pool) .await?; Ok(evidence) } pub async fn resolve_dispute( &self, transaction_id: &str, resolution: &str, // 'SETTLED', 'REVERSED' ) -> AppResult<()> { let status = match resolution { "SETTLED" => crate::domain::constants::ORDER_STATUS_SETTLED, "REVERSED" => "REVERSED", // New status _ => { return Err(crate::domain::error::AppError::BadRequest( "Invalid resolution".into(), )) } }; sqlx::query("UPDATE orders SET status = $1 WHERE transaction_id = $2") .bind(status) .bind(transaction_id) .execute(&self.pool) .await?; Ok(()) } }