1use std::collections::HashMap;
6
7use chrono::{DateTime, Utc};
8use reqwest::Method;
9use serde::Serialize;
10use serde_with::skip_serializing_none;
11
12use crate::entities::Discount;
13use crate::enums::{CurrencyCode, DiscountType, Status};
14use crate::ids::DiscountID;
15use crate::paginated::Paginated;
16use crate::{Paddle, Result};
17
18#[skip_serializing_none]
20#[derive(Serialize)]
21pub struct DiscountsList<'a> {
22 #[serde(skip)]
23 client: &'a Paddle,
24 after: Option<DiscountID>,
25 #[serde(serialize_with = "crate::comma_separated")]
26 code: Option<Vec<String>>,
27 #[serde(serialize_with = "crate::comma_separated")]
28 id: Option<Vec<DiscountID>>,
29 order_by: Option<String>,
30 per_page: Option<usize>,
31 status: Option<Status>,
32}
33
34impl<'a> DiscountsList<'a> {
35 pub fn new(client: &'a Paddle) -> Self {
36 Self {
37 client,
38 after: None,
39 code: None,
40 id: None,
41 order_by: None,
42 per_page: None,
43 status: None,
44 }
45 }
46
47 pub fn after(&mut self, discount_id: impl Into<DiscountID>) -> &mut Self {
49 self.after = Some(discount_id.into());
50 self
51 }
52
53 pub fn codes(&mut self, codes: impl IntoIterator<Item = impl AsRef<str>>) -> &mut Self {
55 self.code = Some(codes.into_iter().map(|s| s.as_ref().to_string()).collect());
56 self
57 }
58
59 pub fn ids(
61 &mut self,
62 discount_ids: impl IntoIterator<Item = impl Into<DiscountID>>,
63 ) -> &mut Self {
64 self.id = Some(discount_ids.into_iter().map(Into::into).collect());
65 self
66 }
67
68 pub fn order_by_asc(&mut self, field: &str) -> &mut Self {
70 self.order_by = Some(format!("{}[ASC]", field));
71 self
72 }
73
74 pub fn order_by_desc(&mut self, field: &str) -> &mut Self {
76 self.order_by = Some(format!("{}[DESC]", field));
77 self
78 }
79
80 pub fn per_page(&mut self, entities_per_page: usize) -> &mut Self {
85 self.per_page = Some(entities_per_page);
86 self
87 }
88
89 pub fn status(&mut self, status: Status) -> &mut Self {
91 self.status = Some(status);
92 self
93 }
94
95 pub fn send(&self) -> Paginated<'_, Vec<Discount>> {
97 Paginated::new(self.client, "/discounts", self)
98 }
99}
100
101#[skip_serializing_none]
103#[derive(Serialize)]
104pub struct DiscountCreate<'a> {
105 #[serde(skip)]
106 client: &'a Paddle,
107 amount: String,
108 description: String,
109 r#type: DiscountType,
110 enabled_for_checkout: bool,
111 code: Option<String>,
112 currency_code: Option<CurrencyCode>,
113 recur: bool,
114 maximum_recurring_intervals: Option<u64>,
115 usage_limit: Option<u64>,
116 restrict_to: Option<Vec<String>>,
117 expires_at: Option<DateTime<Utc>>,
118 custom_data: Option<HashMap<String, String>>,
119}
120
121impl<'a> DiscountCreate<'a> {
122 pub fn new(
123 client: &'a Paddle,
124 amount: impl Into<String>,
125 description: impl Into<String>,
126 discount_type: DiscountType,
127 ) -> Self {
128 Self {
129 client,
130 amount: amount.into(),
131 description: description.into(),
132 r#type: discount_type,
133 enabled_for_checkout: false,
134 code: None,
135 currency_code: None,
136 recur: false,
137 maximum_recurring_intervals: None,
138 usage_limit: None,
139 restrict_to: None,
140 expires_at: None,
141 custom_data: None,
142 }
143 }
144
145 pub fn enabled_for_checkout(&mut self, enabled: bool) -> &mut Self {
147 self.enabled_for_checkout = enabled;
148 self
149 }
150
151 pub fn code(&mut self, code: impl Into<String>) -> &mut Self {
155 self.code = Some(code.into());
156 self
157 }
158
159 pub fn currency_code(&mut self, currency_code: CurrencyCode) -> &mut Self {
161 self.currency_code = Some(currency_code);
162 self
163 }
164
165 pub fn recur(&mut self, recur: bool) -> &mut Self {
167 self.recur = recur;
168 self
169 }
170
171 pub fn maximum_recurring_intervals(&mut self, maximum_recurring_intervals: u64) -> &mut Self {
173 self.maximum_recurring_intervals = Some(maximum_recurring_intervals);
174 self
175 }
176
177 pub fn usage_limit(&mut self, usage_limit: u64) -> &mut Self {
181 self.usage_limit = Some(usage_limit);
182 self
183 }
184
185 pub fn restrict_to(
187 &mut self,
188 restrict_to: impl IntoIterator<Item = impl AsRef<str>>,
189 ) -> &mut Self {
190 self.restrict_to = Some(
191 restrict_to
192 .into_iter()
193 .map(|s| s.as_ref().to_string())
194 .collect(),
195 );
196 self
197 }
198
199 pub fn expires_at(&mut self, expires_at: DateTime<Utc>) -> &mut Self {
203 self.expires_at = Some(expires_at);
204 self
205 }
206
207 pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
209 self.custom_data = Some(custom_data);
210 self
211 }
212
213 pub async fn send(&self) -> Result<Discount> {
215 self.client.send(self, Method::POST, "/discounts").await
216 }
217}
218
219#[derive(Serialize)]
221pub struct DiscountGet<'a> {
222 #[serde(skip)]
223 client: &'a Paddle,
224 #[serde(skip)]
225 discount_id: DiscountID,
226}
227
228impl<'a> DiscountGet<'a> {
229 pub fn new(client: &'a Paddle, discount_id: impl Into<DiscountID>) -> Self {
230 Self {
231 client,
232 discount_id: discount_id.into(),
233 }
234 }
235
236 pub async fn send(&self) -> Result<Discount> {
238 self.client
239 .send(
240 self,
241 Method::GET,
242 &format!("/discounts/{}", self.discount_id.as_ref()),
243 )
244 .await
245 }
246}
247
248#[skip_serializing_none]
250#[derive(Serialize)]
251pub struct DiscountUpdate<'a> {
252 #[serde(skip)]
253 client: &'a Paddle,
254 #[serde(skip)]
255 discount_id: DiscountID,
256 status: Option<Status>,
257 description: Option<String>,
258 enabled_for_checkout: Option<bool>,
259 code: Option<String>,
260 r#type: Option<DiscountType>,
261 amount: Option<String>,
262 currency_code: Option<CurrencyCode>,
263 recur: Option<bool>,
264 maximum_recurring_intervals: Option<u64>,
265 usage_limit: Option<u64>,
266 restrict_to: Option<Vec<String>>,
267 expires_at: Option<DateTime<Utc>>,
268 custom_data: Option<HashMap<String, String>>,
269}
270
271impl<'a> DiscountUpdate<'a> {
272 pub fn new(client: &'a Paddle, discount_id: impl Into<DiscountID>) -> Self {
273 Self {
274 client,
275 discount_id: discount_id.into(),
276 status: None,
277 description: None,
278 enabled_for_checkout: None,
279 code: None,
280 r#type: None,
281 amount: None,
282 currency_code: None,
283 recur: None,
284 maximum_recurring_intervals: None,
285 usage_limit: None,
286 restrict_to: None,
287 expires_at: None,
288 custom_data: None,
289 }
290 }
291
292 pub fn status(&mut self, status: Status) -> &mut Self {
294 self.status = Some(status);
295 self
296 }
297
298 pub fn description(&mut self, description: impl Into<String>) -> &mut Self {
300 self.description = Some(description.into());
301 self
302 }
303
304 pub fn enabled_for_checkout(&mut self, enabled: bool) -> &mut Self {
306 self.enabled_for_checkout = Some(enabled);
307 self
308 }
309
310 pub fn code(&mut self, code: impl Into<String>) -> &mut Self {
312 self.code = Some(code.into());
313 self
314 }
315
316 pub fn discount_type(&mut self, discount_type: DiscountType) -> &mut Self {
318 self.r#type = Some(discount_type);
319 self
320 }
321
322 pub fn amount(&mut self, amount: impl Into<String>) -> &mut Self {
324 self.amount = Some(amount.into());
325 self
326 }
327
328 pub fn currency_code(&mut self, currency_code: CurrencyCode) -> &mut Self {
330 self.currency_code = Some(currency_code);
331 self
332 }
333
334 pub fn recur(&mut self, recur: bool) -> &mut Self {
336 self.recur = Some(recur);
337 self
338 }
339
340 pub fn maximum_recurring_intervals(&mut self, maximum_recurring_intervals: u64) -> &mut Self {
344 self.maximum_recurring_intervals = Some(maximum_recurring_intervals);
345 self
346 }
347
348 pub fn usage_limit(&mut self, usage_limit: u64) -> &mut Self {
350 self.usage_limit = Some(usage_limit);
351 self
352 }
353
354 pub fn restrict_to(
356 &mut self,
357 restrict_to: impl IntoIterator<Item = impl AsRef<str>>,
358 ) -> &mut Self {
359 self.restrict_to = Some(
360 restrict_to
361 .into_iter()
362 .map(|s| s.as_ref().to_string())
363 .collect(),
364 );
365 self
366 }
367
368 pub fn expires_at(&mut self, expires_at: DateTime<Utc>) -> &mut Self {
372 self.expires_at = Some(expires_at);
373 self
374 }
375
376 pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
378 self.custom_data = Some(custom_data);
379 self
380 }
381
382 pub async fn send(&self) -> Result<Discount> {
384 self.client
385 .send(
386 self,
387 Method::PATCH,
388 &format!("/discounts/{}", self.discount_id.as_ref()),
389 )
390 .await
391 }
392}