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