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}