1use chrono::NaiveDate;
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6use turnframe_core::event::ExternalStatus;
7use turnframe_core::operation::Money;
8use uuid::Uuid;
9
10use crate::workflows::trip::state::{NewExtra, Payer, TripTraveler};
11
12pub mod operations {
14 pub const OPEN: &str = "trip.open";
16 pub const SET_NAME: &str = "trip.set_name";
18 pub const SET_TRAVEL_DATE: &str = "trip.set_travel_date";
20 pub const ADD_EXTRA: &str = "trip.add_extra";
22 pub const ASSIGN_PAYER: &str = "trip.assign_payer";
24 pub const CHANGE_EXTRA: &str = "trip.change_extra";
26 pub const SET_TRAVELER: &str = "trip.set_traveler";
28 pub const CHANGE_TRAVELER: &str = "trip.change_traveler";
30 pub const PROTECT_LEG: &str = "trip.protect_leg";
32 pub const REQUEST_REBOOKING: &str = "trip.request_rebooking";
34 pub const REBOOK: &str = "trip.rebook";
36 pub const WITHDRAW: &str = "trip.withdraw";
38 pub const ACKNOWLEDGE_CARD: &str = "trip.acknowledge_card";
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
48#[serde(rename_all = "snake_case")]
49#[non_exhaustive]
50pub enum TripCommand {
51 Open,
53 OpenFor {
55 traveler: TripTraveler,
57 },
58 SetName {
60 value: String,
62 },
63 SetTravelDate {
65 value: NaiveDate,
67 },
68 AddExtra {
70 extra: NewExtra,
72 },
73 AssignPayer {
75 extra_id: Uuid,
77 payer: Payer,
79 },
80 ChangeExtra {
82 extra_id: Uuid,
84 #[serde(default, skip_serializing_if = "Option::is_none")]
86 description: Option<String>,
87 #[serde(default, skip_serializing_if = "Option::is_none")]
89 quantity: Option<u32>,
90 #[serde(default, skip_serializing_if = "Option::is_none")]
92 unit_price_cents: Option<i64>,
93 },
94 ChangeTraveler {
97 traveler: TripTraveler,
99 },
100 ProtectLeg {
102 leg: u32,
104 },
105 Requote {
107 leg: u32,
109 flight: String,
111 departs: String,
113 fare_difference_cents: i64,
115 },
116 RequestRebooking {
118 leg: u32,
120 },
121 Rebook,
123 Withdraw,
125 RecordAirlineOutcome {
127 status: ExternalStatus,
129 #[serde(default, skip_serializing_if = "Option::is_none")]
131 ticket_number: Option<String>,
132 #[serde(default, skip_serializing_if = "Option::is_none")]
134 reason_code: Option<String>,
135 },
136}
137
138#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
140#[serde(rename_all = "snake_case")]
141#[non_exhaustive]
142pub enum TripEvent {
143 Opened,
145 NameSet {
147 value: String,
149 },
150 TravelDateSet {
152 value: NaiveDate,
154 },
155 ExtraAdded {
157 extra_id: Uuid,
159 description: String,
161 quantity: u32,
163 unit_price_cents: i64,
165 },
166 PayerAssigned {
168 extra_id: Uuid,
170 payer: Payer,
172 },
173 ExtraChanged {
175 extra_id: Uuid,
177 #[serde(default, skip_serializing_if = "Option::is_none")]
179 description: Option<String>,
180 #[serde(default, skip_serializing_if = "Option::is_none")]
182 quantity: Option<u32>,
183 #[serde(default, skip_serializing_if = "Option::is_none")]
185 unit_price_cents: Option<i64>,
186 },
187 TravelerChanged {
189 #[serde(default, skip_serializing_if = "Option::is_none")]
191 previous_traveler_id: Option<Uuid>,
192 traveler_id: Uuid,
194 #[serde(default)]
196 display_name: String,
197 },
198 LegProtected {
200 leg: u32,
202 },
203 OfferQuoted {
205 leg: u32,
207 flight: String,
209 departs: String,
211 fare_difference_cents: i64,
213 },
214 RebookingRequested {
216 leg: u32,
218 },
219 RebookingSent,
221 Withdrawn,
223 AirlineOutcomeRecorded {
225 status: ExternalStatus,
227 #[serde(default, skip_serializing_if = "Option::is_none")]
229 ticket_number: Option<String>,
230 #[serde(default, skip_serializing_if = "Option::is_none")]
232 reason_code: Option<String>,
233 },
234}
235
236impl TripEvent {
237 #[must_use]
239 pub fn event_type(&self) -> &'static str {
240 match self {
241 Self::Opened => "trip.opened",
242 Self::NameSet { .. } => "trip.name_set",
243 Self::TravelDateSet { .. } => "trip.travel_date_set",
244 Self::ExtraAdded { .. } => "trip.extra_added",
245 Self::PayerAssigned { .. } => "trip.payer_assigned",
246 Self::ExtraChanged { .. } => "trip.extra_changed",
247 Self::TravelerChanged { .. } => "trip.traveler_changed",
248 Self::LegProtected { .. } => "trip.leg_protected",
249 Self::OfferQuoted { .. } => "trip.offer_quoted",
250 Self::RebookingRequested { .. } => "trip.rebooking_requested",
251 Self::RebookingSent => "trip.rebooking_sent",
252 Self::Withdrawn => "trip.withdrawn",
253 Self::AirlineOutcomeRecorded { .. } => "trip.airline_outcome_recorded",
254 }
255 }
256}
257
258#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
260#[serde(deny_unknown_fields)]
261pub struct SetNameArgs {
262 pub value: String,
264}
265
266#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
268#[serde(deny_unknown_fields)]
269pub struct SetTravelDateArgs {
270 pub value: NaiveDate,
272}
273
274#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
276#[serde(deny_unknown_fields)]
277pub struct AddExtraArgs {
278 pub description: String,
280 pub quantity: u32,
282 pub unit_price: Money,
284}
285
286#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
288#[serde(deny_unknown_fields)]
289pub struct AssignPayerArgs {
290 pub extra: u32,
292 pub payer: Payer,
294}
295
296#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
298#[serde(deny_unknown_fields)]
299pub struct ChangeExtraArgs {
300 pub extra: u32,
302 #[serde(default)]
304 pub description: Option<String>,
305 #[serde(default)]
307 pub quantity: Option<u32>,
308 #[serde(default)]
310 pub unit_price: Option<Money>,
311}
312
313#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
315#[serde(deny_unknown_fields)]
316pub struct OpenArgs {
317 #[serde(default)]
319 pub traveler: Option<TravelerRecord>,
320}
321
322#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
324#[serde(deny_unknown_fields)]
325pub struct SetTravelerArgs {
326 pub traveler: TravelerRecord,
328}
329
330#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
332pub struct TravelerRecord {
333 pub case_id: String,
335 #[serde(default)]
337 pub label: Option<String>,
338}
339
340#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
342#[serde(deny_unknown_fields)]
343pub struct ChangeTravelerArgs {
344 pub traveler: String,
346}
347
348#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
350#[serde(deny_unknown_fields)]
351pub struct LegArgs {
352 pub leg: u32,
354}