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 #[serde(default, skip_serializing_if = "Option::is_none")]
167 payer: Option<Payer>,
168 },
169 PayerAssigned {
171 extra_id: Uuid,
173 payer: Payer,
175 },
176 ExtraChanged {
178 extra_id: Uuid,
180 #[serde(default, skip_serializing_if = "Option::is_none")]
182 description: Option<String>,
183 #[serde(default, skip_serializing_if = "Option::is_none")]
185 quantity: Option<u32>,
186 #[serde(default, skip_serializing_if = "Option::is_none")]
188 unit_price_cents: Option<i64>,
189 },
190 TravelerChanged {
192 #[serde(default, skip_serializing_if = "Option::is_none")]
194 previous_traveler_id: Option<Uuid>,
195 traveler_id: Uuid,
197 #[serde(default)]
199 display_name: String,
200 },
201 LegProtected {
203 leg: u32,
205 },
206 OfferQuoted {
208 leg: u32,
210 flight: String,
212 departs: String,
214 fare_difference_cents: i64,
216 },
217 RebookingRequested {
219 leg: u32,
221 },
222 RebookingSent,
224 Withdrawn,
226 AirlineOutcomeRecorded {
228 status: ExternalStatus,
230 #[serde(default, skip_serializing_if = "Option::is_none")]
232 ticket_number: Option<String>,
233 #[serde(default, skip_serializing_if = "Option::is_none")]
235 reason_code: Option<String>,
236 },
237}
238
239impl TripEvent {
240 #[must_use]
242 pub fn event_type(&self) -> &'static str {
243 match self {
244 Self::Opened => "trip.opened",
245 Self::NameSet { .. } => "trip.name_set",
246 Self::TravelDateSet { .. } => "trip.travel_date_set",
247 Self::ExtraAdded { .. } => "trip.extra_added",
248 Self::PayerAssigned { .. } => "trip.payer_assigned",
249 Self::ExtraChanged { .. } => "trip.extra_changed",
250 Self::TravelerChanged { .. } => "trip.traveler_changed",
251 Self::LegProtected { .. } => "trip.leg_protected",
252 Self::OfferQuoted { .. } => "trip.offer_quoted",
253 Self::RebookingRequested { .. } => "trip.rebooking_requested",
254 Self::RebookingSent => "trip.rebooking_sent",
255 Self::Withdrawn => "trip.withdrawn",
256 Self::AirlineOutcomeRecorded { .. } => "trip.airline_outcome_recorded",
257 }
258 }
259}
260
261#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
263#[serde(deny_unknown_fields)]
264pub struct SetNameArgs {
265 pub value: String,
267}
268
269#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
271#[serde(deny_unknown_fields)]
272pub struct SetTravelDateArgs {
273 pub value: NaiveDate,
275}
276
277#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
279#[serde(deny_unknown_fields)]
280pub struct AddExtraArgs {
281 pub description: String,
283 pub quantity: u32,
285 pub unit_price: Money,
287 #[serde(default)]
289 pub payer: Option<Payer>,
290}
291
292#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
294#[serde(deny_unknown_fields)]
295pub struct AssignPayerArgs {
296 pub extra: u32,
298 pub payer: Payer,
300}
301
302#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
304#[serde(deny_unknown_fields)]
305pub struct ChangeExtraArgs {
306 pub extra: u32,
308 #[serde(default)]
310 pub description: Option<String>,
311 #[serde(default)]
313 pub quantity: Option<u32>,
314 #[serde(default)]
316 pub unit_price: Option<Money>,
317}
318
319#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
321#[serde(deny_unknown_fields)]
322pub struct OpenArgs {
323 #[serde(default)]
325 pub traveler: Option<TravelerRecord>,
326}
327
328#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
330#[serde(deny_unknown_fields)]
331pub struct SetTravelerArgs {
332 pub traveler: TravelerRecord,
334}
335
336#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
338pub struct TravelerRecord {
339 pub case_id: String,
341 #[serde(default)]
343 pub label: Option<String>,
344}
345
346#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
348#[serde(deny_unknown_fields)]
349pub struct ChangeTravelerArgs {
350 pub traveler: String,
352}
353
354#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
356#[serde(deny_unknown_fields)]
357pub struct LegArgs {
358 pub leg: u32,
360}