use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ListPendingReviewsQuery {
pub tenant_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sort: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reason: Option<ReviewReason>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub page: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub page_size: Option<u32>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ListPendingReviewsResponse {
#[serde(default)]
pub items: Vec<PendingReviewDto>,
pub total: u64,
pub page: u32,
pub page_size: u32,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ReviewSummaryResponse {
pub total_pending: u64,
#[serde(default)]
pub by_reason: BTreeMap<String, u64>,
#[serde(default)]
pub by_sort: BTreeMap<String, u64>,
pub high_confidence_count: u64,
pub low_confidence_count: u64,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ReviewStatus {
#[default]
Pending,
Approved,
Rejected,
Corrected,
Merged,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReviewActionResponse {
pub success: bool,
pub status: ReviewStatus,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub term_id: Option<String>,
pub message: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ReExtractResponse {
pub entities_extracted: u64,
pub entities_changed: u64,
pub pending_review_count: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddPendingReviewResponse {
pub review_id: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BulkReviewResponse {
pub success_count: u64,
pub failure_count: u64,
#[serde(default)]
pub succeeded_ids: Vec<String>,
#[serde(default)]
pub failed_ids: Vec<(String, String)>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ReviewReason {
AmbiguousSort,
LowConfidence,
MultipleCandidates,
UnknownSort,
ConflictingFeatures,
MissingRequiredFeatures,
ManualRequest,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ConflictResolution {
KeepExisting,
UseNew,
Merge,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReviewCandidateMatchDto {
pub display_name: String,
#[serde(default)]
pub features: BTreeMap<String, serde_json::Value>,
pub similarity: f64,
pub sort: String,
pub term_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SortSuggestionDto {
pub sort_name: String,
pub confidence: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PendingReviewDto {
#[serde(default)]
pub candidates: Vec<ReviewCandidateMatchDto>,
pub entity_id: String,
pub reason: String,
pub sort: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddPendingReviewRequest {
#[serde(default)]
pub candidates: Vec<ReviewCandidateMatchDto>,
pub confidence: f64,
pub entity_id: String,
#[serde(default)]
pub features: BTreeMap<String, serde_json::Value>,
pub owner_id: String,
pub reason: ReviewReason,
pub sort: String,
#[serde(default)]
pub sort_suggestions: Vec<SortSuggestionDto>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_document: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_text: Option<String>,
pub tenant_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApproveEntityRequest {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub notes: Option<String>,
pub review_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BulkApproveRequest {
pub review_ids: Vec<String>,
pub reviewed_by: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BulkMergeRequest {
pub review_ids: Vec<String>,
pub reviewed_by: String,
pub target_term_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BulkRejectRequest {
pub reason: String,
pub review_ids: Vec<String>,
pub reviewed_by: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CorrectEntityRequest {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub features: Option<BTreeMap<String, serde_json::Value>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub notes: Option<String>,
pub review_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sort: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MergeEntityRequest {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub conflict_resolution: Option<ConflictResolution>,
pub review_id: String,
pub target_term_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReExtractRequest {
pub document_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extraction_strategy: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub focus_sorts: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub instructions: Option<String>,
pub tenant_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RejectEntityRequest {
pub reason: String,
pub review_id: String,
}