Skip to main content

lago_types/requests/
coupon.rs

1use serde::{Deserialize, Serialize};
2
3use crate::filters::{common::ListFilters, coupon::CouponFilter};
4use crate::models::{CouponExpiration, CouponFrequency, CouponType, PaginationParams};
5
6/// Request parameters for retrieving a specific coupon.
7#[derive(Debug, Clone)]
8pub struct GetCouponRequest {
9    pub code: String,
10}
11
12impl GetCouponRequest {
13    /// Creates a new get coupon request.
14    ///
15    /// # Arguments
16    /// * `code` - The unique code of the coupon to retrieve
17    ///
18    /// # Returns
19    /// A new `GetCouponRequest` instance
20    pub fn new(code: String) -> Self {
21        Self { code }
22    }
23}
24
25/// Input for creating a coupon.
26///
27/// This struct contains the data needed to create a new coupon.
28#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct CreateCouponInput {
30    pub name: String,
31    pub code: String,
32    pub coupon_type: CouponType,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub amount_cents: Option<i64>,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub amount_currency: Option<String>,
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub percentage_rate: Option<String>,
39    pub frequency: CouponFrequency,
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub frequency_duration: Option<i32>,
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub reusable: Option<bool>,
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub limited_plans: Option<bool>,
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub plan_codes: Option<Vec<String>>,
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub limited_billable_metrics: Option<bool>,
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub billable_metric_codes: Option<Vec<String>>,
52    pub expiration: CouponExpiration,
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub expiration_at: Option<String>,
55}
56
57impl CreateCouponInput {
58    /// Creates a new fixed amount coupon input.
59    ///
60    /// # Arguments
61    /// * `name` - The name of the coupon
62    /// * `code` - The unique code for the coupon
63    /// * `amount_cents` - The discount amount in cents
64    /// * `amount_currency` - The currency code (e.g., "USD")
65    /// * `frequency` - The frequency of the coupon application
66    /// * `expiration` - The expiration policy for the coupon
67    ///
68    /// # Returns
69    /// A new `CreateCouponInput` instance for a fixed amount coupon
70    pub fn fixed_amount(
71        name: String,
72        code: String,
73        amount_cents: i64,
74        amount_currency: String,
75        frequency: CouponFrequency,
76        expiration: CouponExpiration,
77    ) -> Self {
78        Self {
79            name,
80            code,
81            coupon_type: CouponType::FixedAmount,
82            amount_cents: Some(amount_cents),
83            amount_currency: Some(amount_currency),
84            percentage_rate: None,
85            frequency,
86            frequency_duration: None,
87            reusable: None,
88            limited_plans: None,
89            plan_codes: None,
90            limited_billable_metrics: None,
91            billable_metric_codes: None,
92            expiration,
93            expiration_at: None,
94        }
95    }
96
97    /// Creates a new percentage coupon input.
98    ///
99    /// # Arguments
100    /// * `name` - The name of the coupon
101    /// * `code` - The unique code for the coupon
102    /// * `percentage_rate` - The discount percentage (e.g., "10.5" for 10.5%)
103    /// * `frequency` - The frequency of the coupon application
104    /// * `expiration` - The expiration policy for the coupon
105    ///
106    /// # Returns
107    /// A new `CreateCouponInput` instance for a percentage coupon
108    pub fn percentage(
109        name: String,
110        code: String,
111        percentage_rate: String,
112        frequency: CouponFrequency,
113        expiration: CouponExpiration,
114    ) -> Self {
115        Self {
116            name,
117            code,
118            coupon_type: CouponType::Percentage,
119            amount_cents: None,
120            amount_currency: None,
121            percentage_rate: Some(percentage_rate),
122            frequency,
123            frequency_duration: None,
124            reusable: None,
125            limited_plans: None,
126            plan_codes: None,
127            limited_billable_metrics: None,
128            billable_metric_codes: None,
129            expiration,
130            expiration_at: None,
131        }
132    }
133
134    /// Sets the frequency duration for recurring coupons.
135    ///
136    /// # Arguments
137    /// * `duration` - The number of billing periods the coupon applies to
138    ///
139    /// # Returns
140    /// The modified input instance for method chaining.
141    pub fn with_frequency_duration(mut self, duration: i32) -> Self {
142        self.frequency_duration = Some(duration);
143        self
144    }
145
146    /// Sets whether the coupon is reusable.
147    ///
148    /// # Arguments
149    /// * `reusable` - Whether the coupon can be applied multiple times
150    ///
151    /// # Returns
152    /// The modified input instance for method chaining.
153    pub fn with_reusable(mut self, reusable: bool) -> Self {
154        self.reusable = Some(reusable);
155        self
156    }
157
158    /// Limits the coupon to specific plans.
159    ///
160    /// # Arguments
161    /// * `plan_codes` - The plan codes this coupon applies to
162    ///
163    /// # Returns
164    /// The modified input instance for method chaining.
165    pub fn with_limited_plans(mut self, plan_codes: Vec<String>) -> Self {
166        self.limited_plans = Some(true);
167        self.plan_codes = Some(plan_codes);
168        self
169    }
170
171    /// Limits the coupon to specific billable metrics.
172    ///
173    /// # Arguments
174    /// * `billable_metric_codes` - The billable metric codes this coupon applies to
175    ///
176    /// # Returns
177    /// The modified input instance for method chaining.
178    pub fn with_limited_billable_metrics(mut self, billable_metric_codes: Vec<String>) -> Self {
179        self.limited_billable_metrics = Some(true);
180        self.billable_metric_codes = Some(billable_metric_codes);
181        self
182    }
183
184    /// Sets the expiration timestamp for the coupon (for TimeLimit expiration).
185    ///
186    /// # Arguments
187    /// * `expiration_at` - The expiration timestamp (ISO 8601 format)
188    ///
189    /// # Returns
190    /// The modified input instance for method chaining.
191    pub fn with_expiration_at(mut self, expiration_at: String) -> Self {
192        self.expiration_at = Some(expiration_at);
193        self
194    }
195}
196
197/// Request for creating a coupon.
198///
199/// This struct wraps the create coupon input in the expected API format.
200#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct CreateCouponRequest {
202    pub coupon: CreateCouponInput,
203}
204
205impl CreateCouponRequest {
206    /// Creates a new create coupon request.
207    ///
208    /// # Arguments
209    /// * `input` - The create coupon input data
210    ///
211    /// # Returns
212    /// A new `CreateCouponRequest` instance
213    pub fn new(input: CreateCouponInput) -> Self {
214        Self { coupon: input }
215    }
216}
217
218/// Request parameters for listing coupons.
219///
220/// This struct combines pagination parameters and coupon-specific filters
221/// to build a comprehensive request for retrieving coupon lists.
222#[derive(Debug, Clone)]
223pub struct ListCouponsRequest {
224    pub pagination: PaginationParams,
225    pub filters: CouponFilter,
226}
227
228impl ListCouponsRequest {
229    /// Creates a new empty list coupons request.
230    ///
231    /// # Returns
232    /// A new `ListCouponsRequest` instance with default pagination and no filters.
233    pub fn new() -> Self {
234        Self {
235            pagination: PaginationParams::default(),
236            filters: CouponFilter::default(),
237        }
238    }
239
240    /// Sets the pagination parameters for the request.
241    ///
242    /// # Arguments
243    /// * `pagination` - The pagination parameters to use
244    ///
245    /// # Returns
246    /// The modified request instance for method chaining.
247    pub fn with_pagination(mut self, pagination: PaginationParams) -> Self {
248        self.pagination = pagination;
249        self
250    }
251
252    /// Sets the coupon filters for the request.
253    ///
254    /// # Arguments
255    /// * `filters` - The coupon filters to apply
256    ///
257    /// # Returns
258    /// The modified request instance for method chaining.
259    pub fn with_filters(mut self, filters: CouponFilter) -> Self {
260        self.filters = filters;
261        self
262    }
263
264    /// Converts the request parameters into HTTP query parameters.
265    ///
266    /// # Returns
267    /// A vector of query parameter tuples containing both pagination and filter criteria.
268    pub fn to_query_params(&self) -> Vec<(&str, String)> {
269        let mut params = self.pagination.to_query_params();
270        params.extend(self.filters.to_query_params());
271        params
272    }
273}
274
275impl Default for ListCouponsRequest {
276    fn default() -> Self {
277        Self::new()
278    }
279}
280
281/// Request parameters for deleting a coupon.
282#[derive(Debug, Clone)]
283pub struct DeleteCouponRequest {
284    pub code: String,
285}
286
287impl DeleteCouponRequest {
288    /// Creates a new delete coupon request.
289    ///
290    /// # Arguments
291    /// * `code` - The unique code of the coupon to delete
292    ///
293    /// # Returns
294    /// A new `DeleteCouponRequest` instance
295    pub fn new(code: String) -> Self {
296        Self { code }
297    }
298}
299
300/// Input for updating a coupon.
301///
302/// This struct contains the data that can be updated on an existing coupon.
303#[derive(Debug, Clone, Serialize, Deserialize)]
304pub struct UpdateCouponInput {
305    #[serde(skip_serializing_if = "Option::is_none")]
306    pub name: Option<String>,
307    #[serde(skip_serializing_if = "Option::is_none")]
308    pub coupon_type: Option<CouponType>,
309    #[serde(skip_serializing_if = "Option::is_none")]
310    pub amount_cents: Option<i64>,
311    #[serde(skip_serializing_if = "Option::is_none")]
312    pub amount_currency: Option<String>,
313    #[serde(skip_serializing_if = "Option::is_none")]
314    pub percentage_rate: Option<String>,
315    #[serde(skip_serializing_if = "Option::is_none")]
316    pub frequency: Option<CouponFrequency>,
317    #[serde(skip_serializing_if = "Option::is_none")]
318    pub frequency_duration: Option<i32>,
319    #[serde(skip_serializing_if = "Option::is_none")]
320    pub reusable: Option<bool>,
321    #[serde(skip_serializing_if = "Option::is_none")]
322    pub limited_plans: Option<bool>,
323    #[serde(skip_serializing_if = "Option::is_none")]
324    pub plan_codes: Option<Vec<String>>,
325    #[serde(skip_serializing_if = "Option::is_none")]
326    pub limited_billable_metrics: Option<bool>,
327    #[serde(skip_serializing_if = "Option::is_none")]
328    pub billable_metric_codes: Option<Vec<String>>,
329    #[serde(skip_serializing_if = "Option::is_none")]
330    pub expiration: Option<CouponExpiration>,
331    #[serde(skip_serializing_if = "Option::is_none")]
332    pub expiration_at: Option<String>,
333}
334
335impl UpdateCouponInput {
336    /// Creates a new empty update coupon input.
337    ///
338    /// # Returns
339    /// A new `UpdateCouponInput` instance with all fields set to None.
340    pub fn new() -> Self {
341        Self {
342            name: None,
343            coupon_type: None,
344            amount_cents: None,
345            amount_currency: None,
346            percentage_rate: None,
347            frequency: None,
348            frequency_duration: None,
349            reusable: None,
350            limited_plans: None,
351            plan_codes: None,
352            limited_billable_metrics: None,
353            billable_metric_codes: None,
354            expiration: None,
355            expiration_at: None,
356        }
357    }
358
359    /// Sets the name for the coupon.
360    ///
361    /// # Arguments
362    /// * `name` - The new name for the coupon
363    ///
364    /// # Returns
365    /// The modified input instance for method chaining.
366    pub fn with_name(mut self, name: String) -> Self {
367        self.name = Some(name);
368        self
369    }
370
371    /// Sets the coupon type to fixed amount with the given values.
372    ///
373    /// # Arguments
374    /// * `amount_cents` - The discount amount in cents
375    /// * `amount_currency` - The currency code (e.g., "USD")
376    ///
377    /// # Returns
378    /// The modified input instance for method chaining.
379    pub fn with_fixed_amount(mut self, amount_cents: i64, amount_currency: String) -> Self {
380        self.coupon_type = Some(CouponType::FixedAmount);
381        self.amount_cents = Some(amount_cents);
382        self.amount_currency = Some(amount_currency);
383        self.percentage_rate = None;
384        self
385    }
386
387    /// Sets the coupon type to percentage with the given rate.
388    ///
389    /// # Arguments
390    /// * `percentage_rate` - The discount percentage (e.g., "10.5" for 10.5%)
391    ///
392    /// # Returns
393    /// The modified input instance for method chaining.
394    pub fn with_percentage_rate(mut self, percentage_rate: String) -> Self {
395        self.coupon_type = Some(CouponType::Percentage);
396        self.percentage_rate = Some(percentage_rate);
397        self.amount_cents = None;
398        self.amount_currency = None;
399        self
400    }
401
402    /// Sets the frequency for the coupon.
403    ///
404    /// # Arguments
405    /// * `frequency` - The frequency of the coupon application
406    ///
407    /// # Returns
408    /// The modified input instance for method chaining.
409    pub fn with_frequency(mut self, frequency: CouponFrequency) -> Self {
410        self.frequency = Some(frequency);
411        self
412    }
413
414    /// Sets the frequency duration for recurring coupons.
415    ///
416    /// # Arguments
417    /// * `duration` - The number of billing periods the coupon applies to
418    ///
419    /// # Returns
420    /// The modified input instance for method chaining.
421    pub fn with_frequency_duration(mut self, duration: i32) -> Self {
422        self.frequency_duration = Some(duration);
423        self
424    }
425
426    /// Sets whether the coupon is reusable.
427    ///
428    /// # Arguments
429    /// * `reusable` - Whether the coupon can be applied multiple times
430    ///
431    /// # Returns
432    /// The modified input instance for method chaining.
433    pub fn with_reusable(mut self, reusable: bool) -> Self {
434        self.reusable = Some(reusable);
435        self
436    }
437
438    /// Limits the coupon to specific plans.
439    ///
440    /// # Arguments
441    /// * `plan_codes` - The plan codes this coupon applies to
442    ///
443    /// # Returns
444    /// The modified input instance for method chaining.
445    pub fn with_limited_plans(mut self, plan_codes: Vec<String>) -> Self {
446        self.limited_plans = Some(true);
447        self.plan_codes = Some(plan_codes);
448        self
449    }
450
451    /// Limits the coupon to specific billable metrics.
452    ///
453    /// # Arguments
454    /// * `billable_metric_codes` - The billable metric codes this coupon applies to
455    ///
456    /// # Returns
457    /// The modified input instance for method chaining.
458    pub fn with_limited_billable_metrics(mut self, billable_metric_codes: Vec<String>) -> Self {
459        self.limited_billable_metrics = Some(true);
460        self.billable_metric_codes = Some(billable_metric_codes);
461        self
462    }
463
464    /// Sets the expiration policy for the coupon.
465    ///
466    /// # Arguments
467    /// * `expiration` - The expiration policy
468    ///
469    /// # Returns
470    /// The modified input instance for method chaining.
471    pub fn with_expiration(mut self, expiration: CouponExpiration) -> Self {
472        self.expiration = Some(expiration);
473        self
474    }
475
476    /// Sets the expiration timestamp for the coupon (for TimeLimit expiration).
477    ///
478    /// # Arguments
479    /// * `expiration_at` - The expiration timestamp (ISO 8601 format)
480    ///
481    /// # Returns
482    /// The modified input instance for method chaining.
483    pub fn with_expiration_at(mut self, expiration_at: String) -> Self {
484        self.expiration_at = Some(expiration_at);
485        self
486    }
487}
488
489impl Default for UpdateCouponInput {
490    fn default() -> Self {
491        Self::new()
492    }
493}
494
495/// Request for updating a coupon.
496///
497/// This struct wraps the update coupon input in the expected API format.
498#[derive(Debug, Clone, Serialize, Deserialize)]
499pub struct UpdateCouponRequest {
500    pub code: String,
501    pub coupon: UpdateCouponInput,
502}
503
504impl UpdateCouponRequest {
505    /// Creates a new update coupon request.
506    ///
507    /// # Arguments
508    /// * `code` - The unique code of the coupon to update
509    /// * `input` - The update coupon input data
510    ///
511    /// # Returns
512    /// A new `UpdateCouponRequest` instance
513    pub fn new(code: String, input: UpdateCouponInput) -> Self {
514        Self {
515            code,
516            coupon: input,
517        }
518    }
519}