Skip to main content

commerce_theory/
forecasting.rs

1use crate::dropshipping::*;
2use crate::foundation::*;
3use crate::post_purchase::*;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7pub enum Confidence {
8    Low,
9    Medium,
10    High,
11}
12
13#[must_use]
14pub const fn confidence_allows_auto_replenish(confidence: Confidence) -> bool {
15    matches!(confidence, Confidence::Medium | Confidence::High)
16}
17
18domain_struct! {
19    pub struct DemandForecast {
20        sku: Sku,
21        expected_units: Quantity,
22        confidence: Confidence,
23        horizon_days: Days,
24    }
25}
26
27domain_struct! {
28    #[allow(clippy::struct_field_names)]
29    pub struct SupplierQualityMetrics {
30        defect_rate_bps: Nat,
31        late_shipment_rate_bps: Nat,
32        cancellation_rate_bps: Nat,
33    }
34}
35
36domain_struct! {
37    #[allow(clippy::struct_field_names)]
38    pub struct SupplierRiskPolicy {
39        max_defect_rate_bps: Nat,
40        max_late_shipment_rate_bps: Nat,
41        max_cancellation_rate_bps: Nat,
42    }
43}
44
45#[derive(Clone, Debug, PartialEq, Eq)]
46#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
47pub struct ApprovedSupplierQuality {
48    pub(crate) supplier: DropshipSupplier,
49    pub(crate) metrics: SupplierQualityMetrics,
50    pub(crate) policy: SupplierRiskPolicy,
51}
52
53impl ApprovedSupplierQuality {
54    pub fn try_new(
55        supplier: DropshipSupplier,
56        metrics: SupplierQualityMetrics,
57        policy: SupplierRiskPolicy,
58    ) -> DomainResult<Self> {
59        if metrics.defect_rate_bps > policy.max_defect_rate_bps
60            || metrics.late_shipment_rate_bps > policy.max_late_shipment_rate_bps
61            || metrics.cancellation_rate_bps > policy.max_cancellation_rate_bps
62        {
63            return Err(ValidationError::Invariant(
64                "supplier quality metrics exceed policy",
65            ));
66        }
67        Ok(Self {
68            supplier,
69            metrics,
70            policy,
71        })
72    }
73}
74
75pub(crate) const fn _post_purchase_anchor(_: Option<SubscriptionLifecycleStatus>) {}
76
77impl_getters!(ApprovedSupplierQuality {
78    supplier: DropshipSupplier,
79    metrics: SupplierQualityMetrics,
80    policy: SupplierRiskPolicy,
81});