1use chrono::{DateTime, Utc};
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6use crate::core::*;
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
13pub struct TransportationRfq {
14 pub request_id: String,
16
17 pub mode: TransportMode,
19 pub service_level: Option<String>,
20
21 pub equipment: Option<Equipment>,
23
24 pub consignor: Address,
26 pub consignee: Address,
28
29 pub stops: Vec<LegStop>,
31
32 pub cargo: CargoSummary,
34
35 pub requested_pickup: TimeWindow,
37 pub requested_delivery: TimeWindow,
38
39 pub accessorials: Vec<Accessorial>,
41
42 pub references: HashMap<String, String>,
44}
45
46#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
48pub struct TransportationRqState {
49 pub request_id: String,
51
52 pub status: TransportStatus,
54
55 pub mode: TransportMode,
57 pub service_level: Option<String>,
58
59 pub equipment: Option<Equipment>,
61
62 pub consignor: Address,
64 pub consignee: Address,
66
67 pub stops: Vec<LegStop>,
69
70 pub cargo: CargoSummary,
72
73 pub pickup: StepTiming,
75 pub delivery: StepTiming,
76
77 pub accessorials: Vec<Accessorial>,
79
80 pub references: HashMap<String, String>,
82
83 pub rate: Option<UnitRate>,
85
86 pub events: Vec<TransportEvent>,
88}
89
90impl From<TransportationRfq> for TransportationRqState {
91 fn from(value: TransportationRfq) -> Self {
92 TransportationRqState {
93 request_id: value.request_id,
94 status: TransportStatus::RfqSent,
95 mode: value.mode,
96 service_level: value.service_level,
97 equipment: value.equipment,
98 consignor: value.consignor,
99 consignee: value.consignee,
100 stops: value.stops,
101 cargo: value.cargo,
102 pickup: StepTiming::requested(value.requested_pickup),
103 delivery: StepTiming::requested(value.requested_delivery),
104 accessorials: value.accessorials,
105 references: value.references,
106 rate: None,
107 events: Vec::new(),
108 }
109 }
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
114pub enum TransportStatus {
115 Draft,
117 RfqSent,
119 BidSent,
121 Awarded,
123 Booked,
125 InTransit,
127 Completed,
129 Cancelled,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Copy)]
134pub enum TransportMode {
135 Road,
136 Air,
137 Ocean,
138 Rail,
139 Multimodal,
140}
141
142#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
144pub struct StepTiming {
145 pub requested: Option<TimeWindow>,
147 pub planned: Option<TimeWindow>,
149 pub estimated: Option<DateTime<Utc>>,
151 pub actual: Option<DateTime<Utc>>,
153}
154
155impl StepTiming {
156 pub fn requested(tw: TimeWindow) -> Self {
157 StepTiming {
158 requested: Some(tw),
159 planned: None,
160 estimated: None,
161 actual: None,
162 }
163 }
164
165 pub fn set_plan(&mut self, tw: TimeWindow) {
166 self.planned = Some(tw);
167 }
168
169 pub fn set_estimate(&mut self, date: DateTime<Utc>) {
170 self.estimated = Some(date);
171 }
172
173 pub fn set_actual(&mut self, date: DateTime<Utc>) {
174 self.actual = Some(date);
175 }
176}
177
178#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
180pub struct TimeWindow {
181 pub earliest_utc: DateTime<Utc>,
182 pub latest_utc: DateTime<Utc>,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
187pub struct LegStop {
188 pub sequence: u32,
189 pub location: Address,
190 pub arrival: Option<StepTiming>,
192 pub departure: Option<StepTiming>,
194 pub notes: Option<String>,
196}
197
198#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
200pub struct CargoSummary {
201 pub pieces: u32,
203 pub gross_weight_kg: f32,
205 pub volume_m3: Option<f32>,
207 pub dangerous_goods: bool,
209 pub commodity_description: Option<String>,
211 pub codes: Option<HashMap<String, String>>,
213}
214
215#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
217pub struct Equipment {
218 pub type_code: String,
220 pub temperature_c: Option<(f32, f32)>,
222 pub extrinsic: Option<HashMap<String, String>>,
224}
225
226#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
228pub enum Accessorial {
229 TailLift,
231 InsidePickup,
232 InsideDelivery,
233 Appointment,
235 Hazardous,
237 TempControl,
239 Customs,
241 Residential,
243 Detention,
245 WhiteGlove,
247 Other(String),
249}
250
251#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
253pub struct TransportEvent {
254 pub code: TransportEventCode,
255 pub timestamp: DateTime<Utc>,
256 pub source: Option<String>,
258 pub note: Option<String>,
259}
260
261#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
262pub enum TransportEventCode {
263 PickupPlanned,
264 PickupEtaUpdated,
265 PickupActual,
266 DepartureActual,
267 ArrivalEtaUpdated,
268 ArrivalActual,
269 DeliveryPlanned,
270 DeliveryEtaUpdated,
271 DeliveryActual,
272 ProofOfDeliveryAvailable,
273 Exception,
274}