Skip to main content

stateset_core/errors/
shipping.rs

1//! Shipping-domain errors.
2
3use uuid::Uuid;
4
5/// Errors specific to shipping and shipment operations.
6///
7/// # Example
8///
9/// ```rust
10/// use stateset_core::errors::ShippingError;
11///
12/// let err = ShippingError::not_found(uuid::Uuid::nil());
13/// assert!(err.to_string().contains("not found"));
14/// ```
15#[derive(Debug, thiserror::Error)]
16#[non_exhaustive]
17pub enum ShippingError {
18    /// Shipment with the given ID was not found.
19    #[error("shipment not found: {0}")]
20    NotFound(Uuid),
21
22    /// Carrier rejected the shipment request.
23    #[error("carrier error: {reason}")]
24    CarrierError {
25        /// The carrier name.
26        carrier: String,
27        /// The reason for rejection.
28        reason: String,
29    },
30
31    /// Invalid tracking number format.
32    #[error("invalid tracking number: {0}")]
33    InvalidTrackingNumber(String),
34
35    /// Extensibility.
36    #[error(transparent)]
37    Other(Box<dyn std::error::Error + Send + Sync>),
38}
39
40impl ShippingError {
41    /// Convenience constructor for `NotFound`.
42    #[inline]
43    #[track_caller]
44    #[must_use]
45    pub const fn not_found(id: Uuid) -> Self {
46        Self::NotFound(id)
47    }
48
49    /// Convenience constructor for `CarrierError`.
50    #[track_caller]
51    pub fn carrier_error(carrier: impl Into<String>, reason: impl Into<String>) -> Self {
52        Self::CarrierError { carrier: carrier.into(), reason: reason.into() }
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn not_found_display() {
62        let err = ShippingError::not_found(Uuid::nil());
63        assert!(err.to_string().contains("not found"));
64    }
65
66    #[test]
67    fn carrier_error_display() {
68        let err = ShippingError::carrier_error("FedEx", "address invalid");
69        assert!(err.to_string().contains("address invalid"));
70    }
71
72    #[test]
73    fn converts_to_commerce_error() {
74        use crate::errors::CommerceError;
75
76        let ship_err = ShippingError::not_found(Uuid::nil());
77        let commerce_err: CommerceError = ship_err.into();
78        assert!(commerce_err.is_not_found());
79    }
80}