tango/models/protest.rs
1//! `ProtestRecord` — typed response from `GET /api/protests/{case_id}/`.
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::HashMap;
6
7/// A bid-protest case record.
8///
9/// Returned by [`Client::get_protest`](crate::Client::get_protest). Fields
10/// match the server's shape preset for the detail endpoint; unknown fields
11/// fall through to [`extra`](Self::extra).
12#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
13pub struct ProtestRecord {
14 /// Internal Tango identifier for the case.
15 #[serde(default, skip_serializing_if = "Option::is_none")]
16 pub case_id: Option<String>,
17
18 /// Source-system case number (e.g. GAO file number).
19 #[serde(default, skip_serializing_if = "Option::is_none")]
20 pub case_number: Option<String>,
21
22 /// Human-readable title.
23 #[serde(default, skip_serializing_if = "Option::is_none")]
24 pub title: Option<String>,
25
26 /// Source system: `"gao"`, `"cofc"` or `"sba_oha"` (lowercase).
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub source_system: Option<String>,
29
30 /// Outcome: `"Denied"`, `"Dismissed"`, `"Withdrawn"` or `"Sustained"`; SBA OHA adds `"Granted"`, `"Remanded"`, `"Reversed"` and `"Vacated"`. `None` while a case is pending.
31 #[serde(default, skip_serializing_if = "Option::is_none")]
32 pub outcome: Option<String>,
33
34 /// ISO date the protest was filed.
35 #[serde(default, skip_serializing_if = "Option::is_none")]
36 pub filed_date: Option<String>,
37
38 /// ISO date the protest was decided, when present.
39 #[serde(default, skip_serializing_if = "Option::is_none")]
40 pub decision_date: Option<String>,
41
42 /// Forward-compatible bucket for any unrecognized fields the server adds.
43 #[serde(flatten)]
44 pub extra: HashMap<String, Value>,
45}