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