Skip to main content

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}