domain/boarding/deposit.rs
1//! Boarding deposit rules that keep confirmation policy deterministic.
2//!
3//! A deposit can block confirmation without letting an agent collect money or waive fees by itself:
4//!
5//! ```
6//! use domain::{boarding, money, payment, policy};
7//!
8//! let deposit_amount = money::Money::new(
9//! money::MinorUnits::try_new(5_000).unwrap(),
10//! money::Currency::Usd,
11//! );
12//! let policy = boarding::deposit::Policy::new(
13//! boarding::DepositRule::Required { amount: deposit_amount.clone() },
14//! boarding::PaymentTiming::DueAtBooking,
15//! );
16//!
17//! let readiness = policy.readiness_for_confirmation(None);
18//! assert_eq!(
19//! readiness,
20//! boarding::deposit::ConfirmationReadiness::Blocked {
21//! blocker: boarding::deposit::Blocker::DepositRequired,
22//! review_gate: policy::ReviewGate::RefundOrDepositException,
23//! }
24//! );
25//!
26//! let paid = payment::Deposit::paid(
27//! deposit_amount,
28//! payment::Reference::try_new("fixture-gateway-reference").unwrap(),
29//! );
30//! assert_eq!(
31//! policy.readiness_for_confirmation(Some(&paid)),
32//! boarding::deposit::ConfirmationReadiness::Ready,
33//! );
34//! ```
35
36use super::*;
37use crate::{payment, policy};
38
39#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
40/// Deposit-collection policy used before confirming a boarding reservation.
41pub struct Policy {
42 rule: DepositRule,
43 timing: PaymentTiming,
44}
45
46impl Policy {
47 /// Creates a deposit policy from the resort rule and payment timing.
48 pub const fn new(rule: DepositRule, timing: PaymentTiming) -> Self {
49 Self { rule, timing }
50 }
51
52 /// Determines whether a reservation may be confirmed from deposit evidence or must route to exception review.
53 pub fn readiness_for_confirmation(
54 &self,
55 deposit: Option<&payment::Deposit>,
56 ) -> ConfirmationReadiness {
57 match (
58 &self.rule,
59 self.timing,
60 deposit.map(payment::Deposit::status),
61 ) {
62 (DepositRule::NotRequired, _, _) => ConfirmationReadiness::Ready,
63 (
64 DepositRule::Required { .. },
65 _,
66 Some(payment::DepositStatus::Paid | payment::DepositStatus::WaivedByManager),
67 ) => ConfirmationReadiness::Ready,
68 (DepositRule::Required { .. }, PaymentTiming::DueAtBooking, _) => {
69 ConfirmationReadiness::Blocked {
70 blocker: Blocker::DepositRequired,
71 review_gate: policy::ReviewGate::RefundOrDepositException,
72 }
73 }
74 (DepositRule::Required { .. }, _, _) => ConfirmationReadiness::Ready,
75 }
76 }
77}
78
79#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
80/// Deposit readiness result for boarding reservation confirmation.
81pub enum ConfirmationReadiness {
82 /// Deposit policy is satisfied, waived by manager, or not required for confirmation.
83 Ready,
84 /// Confirmation is blocked until staff collect a deposit or approve an exception.
85 Blocked {
86 /// Operational reason confirmation cannot proceed automatically.
87 blocker: Blocker,
88 /// Manager or billing gate required to override the blocked deposit state.
89 review_gate: policy::ReviewGate,
90 },
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
94/// Reasons deposit policy can block boarding confirmation.
95pub enum Blocker {
96 /// Deposit must be collected before the booking is secure.
97 DepositRequired,
98 /// A payment reference is missing, so staff cannot verify that the deposit was collected.
99 ReferenceMissing,
100}