use std::{fmt, str::FromStr};
use chrono::{DateTime, Utc};
use thiserror::Error;
use crate::{
ActorId, BillingPeriod, BillingScopeId, ChargeAmount, CurrencyCode, DiscountClaimId,
GatewayAccountMode, PastDueAccessPolicy, PaymentMethodId, PlanKey, RenewalFailurePolicy,
SubscriberId, SubscriptionGrantId, SubscriptionId, SubscriptionPeriodRule, SubscriptionPhase,
SubscriptionStatus,
};
pub use access::{
BillingDeletionBlockers, DeletionBlockerQuery, Entitlement, EntitlementGuard, EntitlementQuery,
MissingSubscriptionAction, PastDueAccess, PastDueAction, ScrubSubscriberBillingData,
ScrubbedBillingRows, classify_past_due_access,
};
pub use discount::{
AppliedSubscriptionDiscount, LimitedDiscountMonths, PercentOffBasisPoints,
PositiveDiscountCents, SavedSubscriptionDiscount, SubscriptionDiscountCode,
SubscriptionDiscountDuration, SubscriptionDiscountError, SubscriptionDiscountKind,
SubscriptionDiscountSnapshot,
};
pub use grant::{
SubscriptionGrant, SubscriptionGrantCreation, SubscriptionGrantCreationOutcome,
SubscriptionGrantError, SubscriptionGrantKind, SubscriptionGrantKindParseError,
SubscriptionGrantReason, SubscriptionGrantReasonError, SubscriptionGrantRecord,
SubscriptionGrantRecordError, SubscriptionGrantRevocation, SubscriptionGrantRevocationOutcome,
};
mod access;
mod discount;
mod grant;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Subscription {
id: SubscriptionId,
plan_key: PlanKey,
status: SubscriptionStatus,
phase: SubscriptionPhase,
required_gateway_account_mode: GatewayAccountMode,
payment_method_id: PaymentMethodId,
recurring_charge: ChargeAmount,
recurring_period: SubscriptionPeriodRule,
renewal_failure: RenewalFailurePolicy,
current_period: BillingPeriod,
next_renewal_at: DateTime<Utc>,
next_payment_attempt_at: Option<DateTime<Utc>>,
}
impl Subscription {
#[allow(clippy::too_many_arguments)]
pub const fn new(
id: SubscriptionId,
plan_key: PlanKey,
status: SubscriptionStatus,
phase: SubscriptionPhase,
required_gateway_account_mode: GatewayAccountMode,
payment_method_id: PaymentMethodId,
recurring_charge: ChargeAmount,
recurring_period: SubscriptionPeriodRule,
renewal_failure: RenewalFailurePolicy,
current_period: BillingPeriod,
next_renewal_at: DateTime<Utc>,
next_payment_attempt_at: Option<DateTime<Utc>>,
) -> Self {
Self {
id,
plan_key,
status,
phase,
required_gateway_account_mode,
payment_method_id,
recurring_charge,
recurring_period,
renewal_failure,
current_period,
next_renewal_at,
next_payment_attempt_at,
}
}
pub const fn id(&self) -> SubscriptionId {
self.id
}
pub const fn plan_key(&self) -> &PlanKey {
&self.plan_key
}
pub const fn status(&self) -> SubscriptionStatus {
self.status
}
pub const fn phase(&self) -> SubscriptionPhase {
self.phase
}
pub const fn required_gateway_account_mode(&self) -> GatewayAccountMode {
self.required_gateway_account_mode
}
pub const fn payment_method_id(&self) -> PaymentMethodId {
self.payment_method_id
}
pub const fn recurring_charge(&self) -> ChargeAmount {
self.recurring_charge
}
pub const fn recurring_period(&self) -> SubscriptionPeriodRule {
self.recurring_period
}
pub const fn renewal_failure(&self) -> &RenewalFailurePolicy {
&self.renewal_failure
}
pub const fn current_period(&self) -> &BillingPeriod {
&self.current_period
}
pub const fn next_renewal_at(&self) -> &DateTime<Utc> {
&self.next_renewal_at
}
pub const fn next_payment_attempt_at(&self) -> Option<&DateTime<Utc>> {
self.next_payment_attempt_at.as_ref()
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CancelSubscription {
billing_scope_id: BillingScopeId,
subscriber_id: SubscriberId,
plan_key: PlanKey,
}
impl CancelSubscription {
pub const fn new(
billing_scope_id: BillingScopeId,
subscriber_id: SubscriberId,
plan_key: PlanKey,
) -> Self {
Self {
billing_scope_id,
subscriber_id,
plan_key,
}
}
pub const fn billing_scope_id(&self) -> BillingScopeId {
self.billing_scope_id
}
pub const fn subscriber_id(&self) -> SubscriberId {
self.subscriber_id
}
pub const fn plan_key(&self) -> &PlanKey {
&self.plan_key
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum CancelSubscriptionOutcome {
Canceled {
subscription: Subscription,
event: crate::BillingEvent,
},
AlreadyCanceled(Subscription),
BlockedByRenewal,
BlockedByPaymentMethodUpdate,
NotFound,
}
#[cfg(test)]
mod tests;