1use crate::prelude::*;
2
3pub struct ContractsGroup<'a> {
5 pub(crate) esi: &'a Esi,
6}
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
10#[serde(rename_all = "snake_case")]
11pub enum ContractType {
12 Unknown,
14 ItemExchange,
16 Auction,
18 Courier,
20 Loan,
22 #[serde(other)]
24 Unrecognized,
25}
26
27#[derive(Debug, Clone, PartialEq, Deserialize)]
29#[allow(missing_docs)]
30pub struct PublicContract {
31 pub buyout: Option<f64>,
32 pub collateral: Option<f64>,
33 pub contract_id: i64,
34 pub date_expired: String,
35 pub date_issued: String,
36 pub days_to_complete: Option<i64>,
37 pub end_location_id: Option<i64>,
38 pub for_corporation: Option<bool>,
39 pub issuer_corporation_id: i64,
40 pub issuer_id: i64,
42 pub price: Option<f64>,
43 pub reward: Option<f64>,
44 pub start_location_id: Option<i64>,
45 pub title: Option<String>,
46 #[serde(rename = "type")]
47 pub contract_type: ContractType,
48 pub volume: Option<f64>,
49}
50
51#[derive(Debug, Clone, PartialEq, Deserialize)]
53#[allow(missing_docs)]
54pub struct PublicContractBid {
55 pub amount: f64,
56 pub bid_id: i64,
57 pub date_bid: String,
58}
59
60#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
62#[allow(missing_docs)]
63pub struct PublicContractItem {
64 pub is_blueprint_copy: Option<bool>,
65 pub is_included: bool,
66 pub item_id: Option<i64>,
67 pub material_efficiency: Option<i64>,
68 pub quantity: i64,
69 pub record_id: i64,
70 pub runs: Option<i64>,
71 pub time_efficiency: Option<i64>,
72 pub type_id: i64,
73}
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
77#[serde(rename_all = "snake_case")]
78pub enum ContractAvailability {
79 Public,
81 Personal,
83 Corporation,
85 Alliance,
87 #[serde(other)]
89 Unrecognized,
90}
91
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
94#[serde(rename_all = "snake_case")]
95pub enum ContractStatus {
96 Outstanding,
98 InProgress,
100 FinishedIssuer,
102 FinishedContractor,
104 Finished,
106 Cancelled,
108 Rejected,
110 Failed,
112 Deleted,
114 Reversed,
116 #[serde(other)]
118 Unrecognized,
119}
120
121#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
123pub struct Contract {
124 pub acceptor_id: i64,
127 pub assignee_id: i64,
129 pub availability: ContractAvailability,
131 pub buyout: Option<f64>,
133 pub collateral: Option<f64>,
135 pub contract_id: i64,
137 pub date_accepted: Option<String>,
139 pub date_completed: Option<String>,
141 pub date_expired: String,
143 pub date_issued: String,
145 pub days_to_complete: Option<i64>,
147 pub end_location_id: Option<i64>,
149 pub for_corporation: bool,
151 pub issuer_corporation_id: i64,
153 pub issuer_id: i64,
155 pub price: Option<f64>,
157 pub reward: Option<f64>,
159 pub start_location_id: Option<i64>,
161 pub status: ContractStatus,
163 pub title: Option<String>,
165 #[serde(rename = "type")]
167 pub contract_type: ContractType,
168 pub volume: Option<f64>,
170}
171
172#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
174pub struct ContractBid {
175 pub amount: f64,
177 pub bid_id: i64,
179 pub bidder_id: i64,
181 pub date_bid: String,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
187pub struct ContractItem {
188 pub is_included: bool,
190 pub is_singleton: bool,
192 pub quantity: i64,
194 pub raw_quantity: Option<i64>,
196 pub record_id: i64,
198 pub type_id: i64,
200}
201
202impl ContractsGroup<'_> {
203 api_get!(
204 get_public_contract_bids,
206 "GetContractsPublicBidsContractId",
207 RequestType::Public,
208 Vec<PublicContractBid>,
209 (contract_id: i64) => "{contract_id}";
210 Optional(page: i32) => "page"
211 );
212
213 api_get!(
214 get_public_contract_items,
216 "GetContractsPublicItemsContractId",
217 RequestType::Public,
218 Vec<PublicContractItem>,
219 (contract_id: i64) => "{contract_id}";
220 Optional(page: i32) => "page"
221 );
222
223 api_get!(
224 get_public_contracts,
226 "GetContractsPublicRegionId",
227 RequestType::Public,
228 Vec<PublicContract>,
229 (region_id: i64) => "{region_id}";
230 Optional(page: i32) => "page"
231 );
232
233 api_get!(
234 get_character_contracts,
236 "GetCharactersCharacterIdContracts",
237 RequestType::Authenticated,
238 Vec<Contract>,
239 (character_id: i64) => "{character_id}";
240 Optional(page: i32) => "page"
241 );
242
243 api_get!(
244 get_character_contract_bids,
246 "GetCharactersCharacterIdContractsContractIdBids",
247 RequestType::Authenticated,
248 Vec<ContractBid>,
249 (character_id: i64) => "{character_id}",
250 (contract_id: i64) => "{contract_id}"
251 );
252
253 api_get!(
254 get_character_contract_items,
256 "GetCharactersCharacterIdContractsContractIdItems",
257 RequestType::Authenticated,
258 Vec<ContractItem>,
259 (character_id: i64) => "{character_id}",
260 (contract_id: i64) => "{contract_id}"
261 );
262
263 api_get!(
264 get_corporation_contracts,
266 "GetCorporationsCorporationIdContracts",
267 RequestType::Authenticated,
268 Vec<Contract>,
269 (corporation_id: i64) => "{corporation_id}";
270 Optional(page: i32) => "page"
271 );
272
273 api_get!(
274 get_corporation_contract_bids,
276 "GetCorporationsCorporationIdContractsContractIdBids",
277 RequestType::Authenticated,
278 Vec<ContractBid>,
279 (corporation_id: i64) => "{corporation_id}",
280 (contract_id: i64) => "{contract_id}";
281 Optional(page: i32) => "page"
282 );
283
284 api_get!(
285 get_corporation_contract_items,
287 "GetCorporationsCorporationIdContractsContractIdItems",
288 RequestType::Authenticated,
289 Vec<ContractItem>,
290 (corporation_id: i64) => "{corporation_id}",
291 (contract_id: i64) => "{contract_id}"
292 );
293}
294
295#[cfg(test)]
296mod tests {
297 use super::{ContractType, PublicContract};
298
299 #[test]
300 fn test_parse_contract_and_unknown_type() {
301 let base = |kind: &str| {
302 format!(
303 r#"{{"contract_id": 1, "date_expired": "2026-01-02T00:00:00Z",
304 "date_issued": "2026-01-01T00:00:00Z", "issuer_corporation_id": 98000001,
305 "issuer_id": 2112000000, "type": "{kind}"}}"#
306 )
307 };
308 let known: PublicContract = serde_json::from_str(&base("item_exchange")).unwrap();
309 assert_eq!(known.contract_type, ContractType::ItemExchange);
310 let unknown: PublicContract = serde_json::from_str(&base("brand_new")).unwrap();
311 assert_eq!(unknown.contract_type, ContractType::Unrecognized);
312 }
313}
314
315#[cfg(test)]
316mod private_contract_tests {
317 use super::*;
318
319 #[test]
320 fn test_parse_private_contract() {
321 let json = r#"[{"acceptor_id": 0, "assignee_id": 2112625428, "availability": "personal",
322 "contract_id": 300000000, "date_expired": "e", "date_issued": "i",
323 "for_corporation": false, "issuer_corporation_id": 98000001, "issuer_id": 2112000000,
324 "status": "finished_issuer", "type": "courier", "reward": 1000.0},
325 {"acceptor_id": 0, "assignee_id": 0, "availability": "x", "contract_id": 1,
326 "date_expired": "e", "date_issued": "i", "for_corporation": true,
327 "issuer_corporation_id": 1, "issuer_id": 1, "status": "later", "type": "loan"}]"#;
328 let c: Vec<Contract> = serde_json::from_str(json).unwrap();
329 assert_eq!(c[0].status, ContractStatus::FinishedIssuer);
330 assert_eq!(c[0].availability, ContractAvailability::Personal);
331 assert_eq!(c[1].status, ContractStatus::Unrecognized);
332 assert_eq!(c[1].availability, ContractAvailability::Unrecognized);
333 }
334
335 #[test]
336 fn test_parse_bids_and_items() {
337 let b: Vec<ContractBid> = serde_json::from_str(
338 r#"[{"amount": 5.5, "bid_id": 1, "bidder_id": 2112000000, "date_bid": "d"}]"#,
339 )
340 .unwrap();
341 assert_eq!(b[0].bidder_id, 2_112_000_000);
342 let i: Vec<ContractItem> = serde_json::from_str(
343 r#"[{"is_included": true, "is_singleton": false, "quantity": 5000000000,
344 "record_id": 9, "type_id": 34}]"#,
345 )
346 .unwrap();
347 assert_eq!(i[0].quantity, 5_000_000_000);
348 assert_eq!(i[0].raw_quantity, None);
349 }
350}