syrup_rail_postgres/subscription_billing_service/
subscriber_mutation.rs1use super::*;
2
3const BILLING_LOCK_TIMEOUT: Duration = Duration::from_millis(250);
4
5impl SubscriptionBillingService {
6 pub async fn cancel(
14 &self,
15 command: CancelSubscription,
16 ) -> Result<CancelSubscriptionOutcome, SubscriptionBillingServiceError> {
17 self.admit_subscriber_mutation(
18 command.billing_scope_id(),
19 command.subscriber_id(),
20 EndUserMutationOperation::SubscriptionCancel,
21 )
22 .await?;
23
24 let mut transaction = self
25 .coordinator
26 .begin(
27 BillingEventSubject::new(command.billing_scope_id(), command.subscriber_id()),
28 BILLING_LOCK_TIMEOUT,
29 )
30 .await?;
31 let outcome = match crate::cancellation::cancel_subscription_on_connection(
32 transaction.connection(),
33 &command,
34 )
35 .await
36 {
37 Ok(outcome) => outcome,
38 Err(error) => {
39 let _ = transaction.rollback().await;
40 return Err(error.into());
41 }
42 };
43 if let CancelSubscriptionOutcome::Canceled { event, .. } = &outcome
44 && let Err(error) = transaction.append_event(event).await
45 {
46 let _ = transaction.rollback().await;
47 return Err(error.into());
48 }
49 transaction.commit().await?;
50 Ok(outcome)
51 }
52
53 pub async fn claim_discount(
59 &self,
60 command: SubscriptionDiscountClaim,
61 ) -> Result<SubscriptionDiscountClaimOutcome, SubscriptionBillingServiceError> {
62 self.admit_subscriber_mutation(
63 command.billing_scope_id(),
64 command.subscriber_id(),
65 EndUserMutationOperation::SubscriptionDiscountClaim,
66 )
67 .await?;
68
69 let mut transaction = self
70 .pool
71 .begin()
72 .await
73 .map_err(provider_free_transaction_error)?;
74 let outcome = match crate::discounts::claim_subscription_discount_on_connection(
75 &mut transaction,
76 self.offers.as_ref(),
77 &command,
78 )
79 .await
80 {
81 Ok(outcome) => outcome,
82 Err(error) => {
83 let _ = transaction.rollback().await;
84 return Err(error.into());
85 }
86 };
87 transaction
88 .commit()
89 .await
90 .map_err(provider_free_transaction_error)?;
91 Ok(outcome)
92 }
93
94 pub async fn clear_discount(
100 &self,
101 command: ClearSubscriptionDiscount,
102 ) -> Result<SubscriptionDiscountClearOutcome, SubscriptionBillingServiceError> {
103 self.admit_subscriber_mutation(
104 command.billing_scope_id(),
105 command.subscriber_id(),
106 EndUserMutationOperation::SubscriptionDiscountClear,
107 )
108 .await?;
109
110 let mut transaction = self
111 .pool
112 .begin()
113 .await
114 .map_err(provider_free_transaction_error)?;
115 let outcome = match crate::discounts::clear_subscription_discount_on_connection(
116 &mut transaction,
117 command.billing_scope_id(),
118 command.subscriber_id(),
119 command.plan_key(),
120 )
121 .await
122 {
123 Ok(outcome) => outcome,
124 Err(error) => {
125 let _ = transaction.rollback().await;
126 return Err(error.into());
127 }
128 };
129 transaction
130 .commit()
131 .await
132 .map_err(provider_free_transaction_error)?;
133 Ok(outcome)
134 }
135}
136
137#[cfg(test)]
138mod tests;