paddle_rust_sdk/
subscriptions.rs

1//! Builders for making requests to the Paddle API for subscription entities.
2//!
3//! See the [Paddle API](https://developer.paddle.com/api-reference/subscriptions/overview) documentation for more information.
4
5use chrono::prelude::*;
6use reqwest::Method;
7use serde::Serialize;
8use serde_with::skip_serializing_none;
9
10use crate::entities::{
11    BillingDetails, Subscription, SubscriptionDiscountEffectiveFrom, SubscriptionPreview,
12};
13use crate::enums::{
14    CollectionMode, CurrencyCode, EffectiveFrom, ProrationBillingMode, ScheduledChangeAction,
15    SubscriptionOnPaymentFailure, SubscriptionOnResume, SubscriptionStatus,
16};
17use crate::ids::{AddressID, BusinessID, CustomerID, PriceID, SubscriptionID};
18use crate::paginated::Paginated;
19use crate::transactions::TransactionItem;
20use crate::{Paddle, Result};
21
22/// Request builder for fetching subscriptions from Paddle API.
23#[skip_serializing_none]
24#[derive(Serialize)]
25pub struct SubscriptionsList<'a> {
26    #[serde(skip)]
27    client: &'a Paddle,
28    #[serde(serialize_with = "crate::comma_separated")]
29    address_id: Option<Vec<AddressID>>,
30    after: Option<SubscriptionID>,
31    collection_mode: Option<CollectionMode>,
32    #[serde(serialize_with = "crate::comma_separated")]
33    customer_id: Option<Vec<CustomerID>>,
34    #[serde(serialize_with = "crate::comma_separated")]
35    id: Option<Vec<SubscriptionID>>,
36    order_by: Option<String>,
37    per_page: Option<usize>,
38    #[serde(serialize_with = "crate::comma_separated")]
39    price_id: Option<Vec<PriceID>>,
40    #[serde(serialize_with = "crate::comma_separated_enum")]
41    scheduled_change_action: Option<Vec<ScheduledChangeAction>>,
42    #[serde(serialize_with = "crate::comma_separated_enum")]
43    status: Option<Vec<SubscriptionStatus>>,
44}
45
46impl<'a> SubscriptionsList<'a> {
47    pub fn new(client: &'a Paddle) -> Self {
48        Self {
49            client,
50            address_id: None,
51            after: None,
52            collection_mode: None,
53            customer_id: None,
54            id: None,
55            order_by: None,
56            per_page: None,
57            price_id: None,
58            scheduled_change_action: None,
59            status: None,
60        }
61    }
62
63    /// Return entities related to the specified addresses.
64    pub fn address_ids(
65        &mut self,
66        address_ids: impl IntoIterator<Item = impl Into<AddressID>>,
67    ) -> &mut Self {
68        self.address_id = Some(address_ids.into_iter().map(Into::into).collect());
69        self
70    }
71
72    /// Return entities after the specified Paddle ID when working with paginated endpoints. Used in the `meta.pagination.next` URL in responses for list operations.
73    pub fn after(&mut self, id: impl Into<SubscriptionID>) -> &mut Self {
74        self.after = Some(id.into());
75        self
76    }
77
78    /// Return entities that match the specified collection mode.
79    pub fn collection_mode(&mut self, mode: CollectionMode) -> &mut Self {
80        self.collection_mode = Some(mode);
81        self
82    }
83
84    /// Return entities related to the specified customers.
85    pub fn customer_id(
86        &mut self,
87        customer_ids: impl IntoIterator<Item = impl Into<CustomerID>>,
88    ) -> &mut Self {
89        self.customer_id = Some(customer_ids.into_iter().map(Into::into).collect());
90        self
91    }
92
93    /// Return only the IDs specified.
94    pub fn id(&mut self, ids: impl IntoIterator<Item = impl Into<SubscriptionID>>) -> &mut Self {
95        self.id = Some(ids.into_iter().map(Into::into).collect());
96        self
97    }
98
99    /// Order returned entities by the specified field. Valid fields for ordering: `id`
100    pub fn order_by_asc(&mut self, field: &str) -> &mut Self {
101        self.order_by = Some(format!("{}[ASC]", field));
102        self
103    }
104
105    /// Order returned entities by the specified field. Valid fields for ordering: `id`
106    pub fn order_by_desc(&mut self, field: &str) -> &mut Self {
107        self.order_by = Some(format!("{}[DESC]", field));
108        self
109    }
110
111    /// Set how many entities are returned per page. Paddle returns the maximum number of results if a number greater than the maximum is requested.
112    /// Check `meta.pagination.per_page` in the response to see how many were returned.
113    ///
114    /// Default: `50`; Maximum: `200`.
115    pub fn per_page(&mut self, entities_per_page: usize) -> &mut Self {
116        self.per_page = Some(entities_per_page);
117        self
118    }
119
120    /// Return entities related to the specified prices.
121    pub fn price_ids(
122        &mut self,
123        price_ids: impl IntoIterator<Item = impl Into<PriceID>>,
124    ) -> &mut Self {
125        self.price_id = Some(price_ids.into_iter().map(Into::into).collect());
126        self
127    }
128
129    /// Return subscriptions that have a scheduled changes.
130    pub fn scheduled_change_action(
131        &mut self,
132        actions: impl IntoIterator<Item = ScheduledChangeAction>,
133    ) -> &mut Self {
134        self.scheduled_change_action = Some(actions.into_iter().collect());
135        self
136    }
137
138    /// Return entities that match the specified subscription statuses.
139    pub fn status(&mut self, statuses: impl IntoIterator<Item = SubscriptionStatus>) -> &mut Self {
140        self.status = Some(statuses.into_iter().collect());
141        self
142    }
143
144    /// Returns a paginator for fetching pages of entities from Paddle
145    pub fn send(&self) -> Paginated<Vec<Subscription>> {
146        Paginated::new(self.client, "/subscriptions", self)
147    }
148}
149
150/// Request builder for fetching a specific subscription.
151#[skip_serializing_none]
152#[derive(Serialize)]
153pub struct SubscriptionGet<'a> {
154    #[serde(skip)]
155    client: &'a Paddle,
156    #[serde(skip)]
157    subscription_id: SubscriptionID,
158    #[serde(serialize_with = "crate::comma_separated")]
159    include: Option<Vec<String>>,
160}
161
162impl<'a> SubscriptionGet<'a> {
163    pub fn new(client: &'a Paddle, subscription_id: impl Into<SubscriptionID>) -> Self {
164        Self {
165            client,
166            subscription_id: subscription_id.into(),
167            include: None,
168        }
169    }
170
171    /// Include related entities in the response.
172    ///
173    /// ## Valid values are:
174    ///
175    /// - `next_transaction` - Include an object with a preview of the next transaction for this subscription. May include prorated charges that aren't yet billed and one-time charges.
176    /// - `recurring_transaction_details` - Include an object with a preview of the recurring transaction for this subscription. This is what the customer can expect to be billed when there are no prorated or one-time charges.
177    ///
178    pub fn include(&mut self, entities: impl IntoIterator<Item = impl AsRef<str>>) -> &mut Self {
179        self.include = Some(
180            entities
181                .into_iter()
182                .map(|s| s.as_ref().to_string())
183                .collect(),
184        );
185        self
186    }
187
188    /// Send the request to Paddle and return the response.
189    pub async fn send(&self) -> Result<Subscription> {
190        self.client
191            .send(
192                self,
193                Method::GET,
194                &format!("/subscriptions/{}", self.subscription_id.as_ref()),
195            )
196            .await
197    }
198}
199
200// Note: Unlike other structs we cannot use this directly for the preview request because we need to
201// serialize null values to indicate that they should be removed from the subscription preview.
202
203/// Request builder for getting a preview of changes to a subscription without actually applying them.
204///
205/// Typically used for previewing proration before making changes to a subscription.
206pub struct SubscriptionPreviewUpdate<'a> {
207    client: &'a Paddle,
208    subscription_id: SubscriptionID,
209    data: serde_json::Value,
210}
211
212impl<'a> SubscriptionPreviewUpdate<'a> {
213    pub fn new(client: &'a Paddle, subscription_id: impl Into<SubscriptionID>) -> Self {
214        Self {
215            client,
216            subscription_id: subscription_id.into(),
217            data: serde_json::json!({}),
218        }
219    }
220
221    /// The customer ID to use for the preview. Include to change the customer for a subscription.
222    pub fn customer_id(&mut self, customer_id: impl Into<CustomerID>) -> &mut Self {
223        self.data["customer_id"] = serde_json::json!(customer_id.into());
224        self
225    }
226
227    /// The address ID to use for the preview. Include to change the address for a subscription.
228    pub fn address_id(&mut self, address_id: impl Into<AddressID>) -> &mut Self {
229        self.data["address_id"] = serde_json::json!(address_id.into());
230        self
231    }
232
233    /// The business ID to use for the preview. Include to change the business for a subscription.
234    pub fn business_id(&mut self, business_id: impl Into<BusinessID>) -> &mut Self {
235        self.data["business_id"] = serde_json::json!(business_id.into());
236        self
237    }
238
239    /// Supported currency code. Include to change the currency that a subscription bills in.
240    ///
241    /// When changing `collection_mode` to `manual`, you may need to change currency code to `USD`, `EUR`, or `GBP`.
242    pub fn currency_code(&mut self, currency_code: CurrencyCode) -> &mut Self {
243        self.data["currency_code"] = serde_json::json!(currency_code);
244        self
245    }
246
247    /// Datetime of when this subscription is next scheduled to be billed. Include to change the next billing date.
248    pub fn next_billed_at(&mut self, next_billed_at: DateTime<Utc>) -> &mut Self {
249        self.data["next_billed_at"] = serde_json::json!(next_billed_at);
250        self
251    }
252
253    /// Details of the discount applied to this subscription. Include to add a discount to a subscription. None to remove a discount.
254    pub fn set_discount(
255        &mut self,
256        discount: Option<SubscriptionDiscountEffectiveFrom>,
257    ) -> &mut Self {
258        self.data["discount"] = serde_json::json!(discount);
259        self
260    }
261
262    /// How payment is collected for transactions created for this subscription. `automatic` for checkout, `manual` for invoices.
263    pub fn collection_mode(&mut self, mode: CollectionMode) -> &mut Self {
264        self.data["collection_mode"] = serde_json::json!(mode);
265        self
266    }
267
268    /// Details for invoicing. Required if `collection_mode` is `manual`. `None` if changing `collection_mode` to `automatic`.
269    pub fn billing_details(&mut self, billing_details: Option<BillingDetails>) -> &mut Self {
270        self.data["billing_details"] = serde_json::json!(billing_details);
271        self
272    }
273
274    /// Change that's scheduled to be applied to a subscription.
275    ///
276    /// When updating, you may only set to `null` to remove a scheduled change.
277    ///
278    /// Use the pause subscription, cancel subscription, and resume subscription operations to create scheduled changes.
279    pub fn unset_scheduled_change(&mut self) -> &mut Self {
280        self.data["scheduled_change"] = serde_json::json!(null);
281        self
282    }
283
284    /// List of items on this subscription. Only recurring items may be added. Send the complete list of items that should be on this subscription, including existing items to retain.
285    pub fn items(&mut self, items: impl IntoIterator<Item = TransactionItem>) -> &mut Self {
286        self.data["items"] = serde_json::json!(items.into_iter().collect::<Vec<_>>());
287        self
288    }
289
290    /// Your own structured key-value data.
291    pub fn custom_data(&mut self, custom_data: serde_json::Value) -> &mut Self {
292        self.data["custom_data"] = custom_data;
293        self
294    }
295
296    /// How Paddle should handle proration calculation for changes made to a subscription or its items. Required when making changes that impact billing.
297    ///
298    /// For automatically-collected subscriptions, responses may take longer than usual if a proration billing mode that collects for payment immediately is used.
299    pub fn proration_billing_mode(&mut self, mode: ProrationBillingMode) -> &mut Self {
300        self.data["proration_billing_mode"] = serde_json::json!(mode);
301        self
302    }
303
304    /// How Paddle should handle changes made to a subscription or its items if the payment fails during update. If omitted, defaults to `prevent_change`.
305    pub fn on_payment_failure(&mut self, mode: SubscriptionOnPaymentFailure) -> &mut Self {
306        self.data["on_payment_failure"] = serde_json::json!(mode);
307        self
308    }
309
310    /// Send the request to Paddle and return the response.
311    pub async fn send(&self) -> Result<SubscriptionPreview> {
312        self.client
313            .send(
314                &self.data,
315                Method::PATCH,
316                &format!("/subscriptions/{}/preview", self.subscription_id.as_ref()),
317            )
318            .await
319    }
320}
321
322// Note: Unlike other structs we cannot use this directly for the preview request because we need to
323// serialize null values to indicate that they should be removed from the subscription preview.
324
325/// Request builder for updating a subscription using its ID.
326///
327/// When making changes to items or the next billing date for a subscription, you must include the `proration_billing_mode` field to tell Paddle how to bill for those changes.
328///
329/// Send the complete list of items that you'd like to be on a subscription — including existing items. If you omit items, they're removed from the subscription.
330///
331/// For each item, send `price_id` and `quantity`. Paddle responds with the full price object for each price. If you're updating an existing item, you can omit the `quantity` if you don't want to update it.
332///
333/// If successful, your response includes a copy of the updated subscription entity. When an update results in an immediate charge, responses may take longer than usual while a payment attempt is processed.
334pub struct SubscriptionUpdate<'a> {
335    client: &'a Paddle,
336    subscription_id: SubscriptionID,
337    data: serde_json::Value,
338}
339
340impl<'a> SubscriptionUpdate<'a> {
341    pub fn new(client: &'a Paddle, subscription_id: impl Into<SubscriptionID>) -> Self {
342        Self {
343            client,
344            subscription_id: subscription_id.into(),
345            data: serde_json::json!({}),
346        }
347    }
348
349    /// The customer ID to use for the preview. Include to change the customer for a subscription.
350    pub fn customer_id(&mut self, customer_id: impl Into<CustomerID>) -> &mut Self {
351        self.data["customer_id"] = serde_json::json!(customer_id.into());
352        self
353    }
354
355    /// The address ID to use for the preview. Include to change the address for a subscription.
356    pub fn address_id(&mut self, address_id: impl Into<AddressID>) -> &mut Self {
357        self.data["address_id"] = serde_json::json!(address_id.into());
358        self
359    }
360
361    /// The business ID to use for the preview. Include to change the business for a subscription.
362    pub fn business_id(&mut self, business_id: impl Into<BusinessID>) -> &mut Self {
363        self.data["business_id"] = serde_json::json!(business_id.into());
364        self
365    }
366
367    /// Supported currency code. Include to change the currency that a subscription bills in.
368    ///
369    /// When changing `collection_mode` to `manual`, you may need to change currency code to `USD`, `EUR`, or `GBP`.
370    pub fn currency_code(&mut self, currency_code: CurrencyCode) -> &mut Self {
371        self.data["currency_code"] = serde_json::json!(currency_code);
372        self
373    }
374
375    /// Datetime of when this subscription is next scheduled to be billed. Include to change the next billing date.
376    pub fn next_billed_at(&mut self, next_billed_at: DateTime<Utc>) -> &mut Self {
377        self.data["next_billed_at"] = serde_json::json!(next_billed_at);
378        self
379    }
380
381    /// Details of the discount applied to this subscription. Include to add a discount to a subscription. None to remove a discount.
382    pub fn set_discount(
383        &mut self,
384        discount: Option<SubscriptionDiscountEffectiveFrom>,
385    ) -> &mut Self {
386        self.data["discount"] = serde_json::json!(discount);
387        self
388    }
389
390    /// How payment is collected for transactions created for this subscription. `automatic` for checkout, `manual` for invoices.
391    pub fn collection_mode(&mut self, mode: CollectionMode) -> &mut Self {
392        self.data["collection_mode"] = serde_json::json!(mode);
393        self
394    }
395
396    /// Details for invoicing. Required if `collection_mode` is `manual`. `None` if changing `collection_mode` to `automatic`.
397    pub fn billing_details(&mut self, billing_details: Option<BillingDetails>) -> &mut Self {
398        self.data["billing_details"] = serde_json::json!(billing_details);
399        self
400    }
401
402    /// Change that's scheduled to be applied to a subscription.
403    ///
404    /// When updating, you may only set to `null` to remove a scheduled change.
405    ///
406    /// Use the pause subscription, cancel subscription, and resume subscription operations to create scheduled changes.
407    pub fn unset_scheduled_change(&mut self) -> &mut Self {
408        self.data["scheduled_change"] = serde_json::json!(null);
409        self
410    }
411
412    /// List of items on this subscription. Only recurring items may be added. Send the complete list of items that should be on this subscription, including existing items to retain.
413    pub fn items(&mut self, items: impl IntoIterator<Item = TransactionItem>) -> &mut Self {
414        self.data["items"] = serde_json::json!(items.into_iter().collect::<Vec<_>>());
415        self
416    }
417
418    /// Your own structured key-value data.
419    pub fn custom_data(&mut self, custom_data: serde_json::Value) -> &mut Self {
420        self.data["custom_data"] = custom_data;
421        self
422    }
423
424    /// How Paddle should handle proration calculation for changes made to a subscription or its items. Required when making changes that impact billing.
425    ///
426    /// For automatically-collected subscriptions, responses may take longer than usual if a proration billing mode that collects for payment immediately is used.
427    pub fn proration_billing_mode(&mut self, mode: ProrationBillingMode) -> &mut Self {
428        self.data["proration_billing_mode"] = serde_json::json!(mode);
429        self
430    }
431
432    /// How Paddle should handle changes made to a subscription or its items if the payment fails during update. If omitted, defaults to `prevent_change`.
433    pub fn on_payment_failure(&mut self, mode: SubscriptionOnPaymentFailure) -> &mut Self {
434        self.data["on_payment_failure"] = serde_json::json!(mode);
435        self
436    }
437
438    /// Send the request to Paddle and return the response.
439    pub async fn send(&self) -> Result<Subscription> {
440        self.client
441            .send(
442                &self.data,
443                Method::PATCH,
444                &format!("/subscriptions/{}", self.subscription_id.as_ref()),
445            )
446            .await
447    }
448}
449
450/// Request builder for creating a preview of one-time charge for a subscription without billing that charge.
451#[skip_serializing_none]
452#[derive(Serialize)]
453pub struct SubscriptionOneTimeChargePreview<'a> {
454    #[serde(skip)]
455    client: &'a Paddle,
456    #[serde(skip)]
457    subscription_id: SubscriptionID,
458    effective_from: Option<EffectiveFrom>,
459    items: Vec<TransactionItem>,
460    on_payment_failure: Option<SubscriptionOnPaymentFailure>,
461}
462
463impl<'a> SubscriptionOneTimeChargePreview<'a> {
464    pub fn new(client: &'a Paddle, subscription_id: impl Into<SubscriptionID>) -> Self {
465        Self {
466            client,
467            subscription_id: subscription_id.into(),
468            effective_from: None,
469            items: Vec::default(),
470            on_payment_failure: None,
471        }
472    }
473
474    /// When one-time charges should be billed.
475    pub fn effective_from(&mut self, effective_from: EffectiveFrom) -> &mut Self {
476        self.effective_from = Some(effective_from);
477        self
478    }
479
480    /// List of one-time charges to bill for. Only prices where the `billing_cycle` is `null` may be added.
481    ///
482    /// You can charge for items that you've added to your catalog by passing the Paddle ID of an existing price entity, or you can charge for non-catalog items by passing a price object.
483    ///
484    /// Non-catalog items can be for existing products, or you can pass a product object as part of your price to charge for a non-catalog product.
485    pub fn items(&mut self, items: impl IntoIterator<Item = TransactionItem>) -> &mut Self {
486        self.items = items.into_iter().collect();
487        self
488    }
489
490    /// How Paddle should handle changes made to a subscription or its items if the payment fails during update. If omitted, defaults to `prevent_change`.
491    pub fn on_payment_failure(&mut self, mode: SubscriptionOnPaymentFailure) -> &mut Self {
492        self.on_payment_failure = Some(mode);
493        self
494    }
495
496    /// Send the request to Paddle and return the response.
497    pub async fn send(&self) -> Result<SubscriptionPreview> {
498        self.client
499            .send(
500                self,
501                Method::POST,
502                &format!(
503                    "/subscriptions/{}/charge/preview",
504                    self.subscription_id.as_ref()
505                ),
506            )
507            .await
508    }
509}
510
511/// Request builder for creating a new one-time charge for a subscription.
512#[skip_serializing_none]
513#[derive(Serialize)]
514pub struct SubscriptionOneTimeCharge<'a> {
515    #[serde(skip)]
516    client: &'a Paddle,
517    #[serde(skip)]
518    subscription_id: SubscriptionID,
519    effective_from: Option<EffectiveFrom>,
520    items: Vec<TransactionItem>,
521    on_payment_failure: Option<SubscriptionOnPaymentFailure>,
522}
523
524impl<'a> SubscriptionOneTimeCharge<'a> {
525    pub fn new(client: &'a Paddle, subscription_id: impl Into<SubscriptionID>) -> Self {
526        Self {
527            client,
528            subscription_id: subscription_id.into(),
529            effective_from: None,
530            items: Vec::default(),
531            on_payment_failure: None,
532        }
533    }
534
535    /// When one-time charges should be billed.
536    pub fn effective_from(&mut self, effective_from: EffectiveFrom) -> &mut Self {
537        self.effective_from = Some(effective_from);
538        self
539    }
540
541    /// List of one-time charges to bill for. Only prices where the `billing_cycle` is `null` may be added.
542    ///
543    /// You can charge for items that you've added to your catalog by passing the Paddle ID of an existing price entity, or you can charge for non-catalog items by passing a price object.
544    ///
545    /// Non-catalog items can be for existing products, or you can pass a product object as part of your price to charge for a non-catalog product.
546    pub fn items(&mut self, items: impl IntoIterator<Item = TransactionItem>) -> &mut Self {
547        self.items = items.into_iter().collect();
548        self
549    }
550
551    /// How Paddle should handle changes made to a subscription or its items if the payment fails during update. If omitted, defaults to `prevent_change`.
552    pub fn on_payment_failure(&mut self, mode: SubscriptionOnPaymentFailure) -> &mut Self {
553        self.on_payment_failure = Some(mode);
554        self
555    }
556
557    /// Send the request to Paddle and return the response.
558    pub async fn send(&self) -> Result<Subscription> {
559        self.client
560            .send(
561                self,
562                Method::POST,
563                &format!("/subscriptions/{}/charge", self.subscription_id.as_ref()),
564            )
565            .await
566    }
567}
568
569/// Request builder for pausing a subscription.
570#[skip_serializing_none]
571#[derive(Serialize)]
572pub struct SubscriptionPause<'a> {
573    #[serde(skip)]
574    client: &'a Paddle,
575    #[serde(skip)]
576    subscription_id: SubscriptionID,
577    effective_from: Option<EffectiveFrom>,
578    resume_at: Option<DateTime<Utc>>,
579    on_resume: Option<SubscriptionOnResume>,
580}
581
582impl<'a> SubscriptionPause<'a> {
583    pub fn new(client: &'a Paddle, subscription_id: impl Into<SubscriptionID>) -> Self {
584        Self {
585            client,
586            subscription_id: subscription_id.into(),
587            effective_from: None,
588            resume_at: None,
589            on_resume: None,
590        }
591    }
592
593    /// When this subscription change should take effect from.
594    ///
595    /// Defaults to `next_billing_period` for active subscriptions, which creates a `scheduled_change` to apply the subscription change at the end of the billing period.
596    pub fn effective_from(&mut self, effective_from: EffectiveFrom) -> &mut Self {
597        self.effective_from = Some(effective_from);
598        self
599    }
600
601    /// Datetime of when the paused subscription should resume. Omit to pause indefinitely until resumed.
602    pub fn resume_at(&mut self, datetime: DateTime<Utc>) -> &mut Self {
603        self.resume_at = Some(datetime);
604        self
605    }
606
607    /// How Paddle should set the billing period for the subscription when resuming. If omitted, defaults to `start_new_billing_period`.
608    pub fn on_resume(&mut self, value: SubscriptionOnResume) -> &mut Self {
609        self.on_resume = Some(value);
610        self
611    }
612
613    /// Send the request to Paddle and return the response.
614    pub async fn send(&self) -> Result<Subscription> {
615        self.client
616            .send(
617                self,
618                Method::POST,
619                &format!("/subscriptions/{}/pause", self.subscription_id.as_ref()),
620            )
621            .await
622    }
623}
624
625/// Request builder for resuming a subscription.
626#[skip_serializing_none]
627#[derive(Serialize)]
628pub struct SubscriptionResume<'a> {
629    #[serde(skip)]
630    client: &'a Paddle,
631    #[serde(skip)]
632    subscription_id: SubscriptionID,
633    // Defaults to `immediately` if omitted.
634    effective_from: Option<DateTime<Utc>>,
635    on_resume: Option<SubscriptionOnResume>,
636}
637
638impl<'a> SubscriptionResume<'a> {
639    pub fn new(client: &'a Paddle, subscription_id: impl Into<SubscriptionID>) -> Self {
640        Self {
641            client,
642            subscription_id: subscription_id.into(),
643            effective_from: None,
644            on_resume: None,
645        }
646    }
647
648    /// When this subscription change should take effect from.
649    ///
650    /// Defaults to `next_billing_period` for active subscriptions, which creates a `scheduled_change` to apply the subscription change at the end of the billing period.
651    pub fn effective_from(&mut self, effective_from: DateTime<Utc>) -> &mut Self {
652        self.effective_from = Some(effective_from);
653        self
654    }
655
656    /// How Paddle should set the billing period for the subscription when resuming. If omitted, defaults to `start_new_billing_period`.
657    pub fn on_resume(&mut self, value: SubscriptionOnResume) -> &mut Self {
658        self.on_resume = Some(value);
659        self
660    }
661
662    /// Send the request to Paddle and return the response.
663    pub async fn send(&self) -> Result<Subscription> {
664        self.client
665            .send(
666                self,
667                Method::POST,
668                &format!("/subscriptions/{}/resume", self.subscription_id.as_ref()),
669            )
670            .await
671    }
672}
673
674/// Request builder for resuming a subscription.
675#[skip_serializing_none]
676#[derive(Serialize)]
677pub struct SubscriptionCancel<'a> {
678    #[serde(skip)]
679    client: &'a Paddle,
680    #[serde(skip)]
681    subscription_id: SubscriptionID,
682    effective_from: Option<EffectiveFrom>,
683}
684
685impl<'a> SubscriptionCancel<'a> {
686    pub fn new(client: &'a Paddle, subscription_id: impl Into<SubscriptionID>) -> Self {
687        Self {
688            client,
689            subscription_id: subscription_id.into(),
690            effective_from: None,
691        }
692    }
693
694    /// When this subscription change should take effect from.
695    ///
696    /// Defaults to `next_billing_period` for active subscriptions, which creates a `scheduled_change` to apply the subscription change at the end of the billing period.
697    pub fn effective_from(&mut self, effective_from: EffectiveFrom) -> &mut Self {
698        self.effective_from = Some(effective_from);
699        self
700    }
701
702    /// Send the request to Paddle and return the response.
703    pub async fn send(&self) -> Result<Subscription> {
704        self.client
705            .send(
706                self,
707                Method::POST,
708                &format!("/subscriptions/{}/cancel", self.subscription_id.as_ref()),
709            )
710            .await
711    }
712}