1use serde::{Deserialize, Serialize};
4
5use crate::{
6 bounded_market_query_limit, LiabilityCoverageClass, SignedLiabilityAutoBindDecision,
7 SignedLiabilityBoundCoverage, SignedLiabilityPlacement, SignedLiabilityPricingAuthority,
8 SignedLiabilityQuoteRequest, SignedLiabilityQuoteResponse, MAX_LIABILITY_MARKET_WORKFLOW_LIMIT,
9};
10
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
12#[serde(rename_all = "camelCase")]
13pub struct LiabilityMarketWorkflowQuery {
14 #[serde(default, skip_serializing_if = "Option::is_none")]
15 pub quote_request_id: Option<String>,
16 #[serde(default, skip_serializing_if = "Option::is_none")]
17 pub provider_id: Option<String>,
18 #[serde(default, skip_serializing_if = "Option::is_none")]
19 pub agent_subject: Option<String>,
20 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub jurisdiction: Option<String>,
22 #[serde(default, skip_serializing_if = "Option::is_none")]
23 pub coverage_class: Option<LiabilityCoverageClass>,
24 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub currency: Option<String>,
26 #[serde(default, skip_serializing_if = "Option::is_none")]
27 pub limit: Option<usize>,
28}
29
30impl Default for LiabilityMarketWorkflowQuery {
31 fn default() -> Self {
32 Self {
33 quote_request_id: None,
34 provider_id: None,
35 agent_subject: None,
36 jurisdiction: None,
37 coverage_class: None,
38 currency: None,
39 limit: Some(50),
40 }
41 }
42}
43
44impl LiabilityMarketWorkflowQuery {
45 #[must_use]
46 pub fn limit_or_default(&self) -> usize {
47 bounded_market_query_limit(self.limit, MAX_LIABILITY_MARKET_WORKFLOW_LIMIT)
48 }
49
50 #[must_use]
51 pub fn normalized(&self) -> Self {
52 let mut normalized = self.clone();
53 normalized.limit = Some(self.limit_or_default());
54 normalized.provider_id = self
55 .provider_id
56 .as_ref()
57 .map(|value| value.trim().to_string());
58 normalized.quote_request_id = self
59 .quote_request_id
60 .as_ref()
61 .map(|value| value.trim().to_string());
62 normalized.agent_subject = self
63 .agent_subject
64 .as_ref()
65 .map(|value| value.trim().to_string());
66 normalized.jurisdiction = self
67 .jurisdiction
68 .as_ref()
69 .map(|value| value.trim().to_ascii_lowercase());
70 normalized.currency = self
71 .currency
72 .as_ref()
73 .map(|value| value.trim().to_ascii_uppercase());
74 normalized
75 }
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
79#[serde(rename_all = "camelCase")]
80pub struct LiabilityMarketWorkflowRow {
81 pub quote_request: SignedLiabilityQuoteRequest,
82 #[serde(default, skip_serializing_if = "Option::is_none")]
83 pub latest_quote_response: Option<SignedLiabilityQuoteResponse>,
84 #[serde(default, skip_serializing_if = "Option::is_none")]
85 pub pricing_authority: Option<SignedLiabilityPricingAuthority>,
86 #[serde(default, skip_serializing_if = "Option::is_none")]
87 pub latest_auto_bind_decision: Option<SignedLiabilityAutoBindDecision>,
88 #[serde(default, skip_serializing_if = "Option::is_none")]
89 pub placement: Option<SignedLiabilityPlacement>,
90 #[serde(default, skip_serializing_if = "Option::is_none")]
91 pub bound_coverage: Option<SignedLiabilityBoundCoverage>,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
95#[serde(rename_all = "camelCase")]
96pub struct LiabilityMarketWorkflowSummary {
97 pub matching_requests: u64,
98 pub returned_requests: u64,
99 pub quote_responses: u64,
100 pub quoted_responses: u64,
101 pub declined_responses: u64,
102 pub pricing_authorities: u64,
103 pub auto_bind_decisions: u64,
104 pub auto_bound_decisions: u64,
105 pub manual_review_decisions: u64,
106 pub denied_decisions: u64,
107 pub placements: u64,
108 pub bound_coverages: u64,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
112#[serde(rename_all = "camelCase")]
113pub struct LiabilityMarketWorkflowReport {
114 pub schema: String,
115 pub generated_at: u64,
116 pub query: LiabilityMarketWorkflowQuery,
117 pub summary: LiabilityMarketWorkflowSummary,
118 pub workflows: Vec<LiabilityMarketWorkflowRow>,
119}