1use std::collections::HashMap;
6use std::ops::Range;
7
8use reqwest::Method;
9use serde::Serialize;
10use serde_with::skip_serializing_none;
11
12use crate::entities::{Duration, Money, Price, PriceQuantity, UnitPriceOverride};
13use crate::enums::{CatalogType, CountryCodeSupported, CurrencyCode, Interval, Status, TaxMode};
14use crate::ids::{PriceID, ProductID};
15use crate::{Paddle, Result};
16
17#[skip_serializing_none]
19#[derive(Serialize)]
20pub struct PricesList<'a> {
21 #[serde(skip)]
22 client: &'a Paddle,
23 after: Option<PriceID>,
24 #[serde(serialize_with = "crate::comma_separated")]
25 id: Option<Vec<PriceID>>,
26 #[serde(serialize_with = "crate::comma_separated")]
27 include: Option<Vec<String>>,
28 order_by: Option<String>,
29 per_page: Option<usize>,
30 #[serde(serialize_with = "crate::comma_separated")]
31 product_id: Option<Vec<ProductID>>,
32 status: Option<Status>,
33 recurring: Option<bool>,
34 r#type: Option<CatalogType>,
35}
36
37impl<'a> PricesList<'a> {
38 pub fn new(client: &'a Paddle) -> Self {
39 Self {
40 client,
41 after: None,
42 id: None,
43 include: None,
44 order_by: None,
45 per_page: None,
46 product_id: None,
47 status: None,
48 recurring: None,
49 r#type: None,
50 }
51 }
52
53 pub fn after(&mut self, price_id: impl Into<PriceID>) -> &mut Self {
55 self.after = Some(price_id.into());
56 self
57 }
58
59 pub fn ids(&mut self, price_ids: impl IntoIterator<Item = impl Into<PriceID>>) -> &mut Self {
61 self.id = Some(price_ids.into_iter().map(Into::into).collect());
62 self
63 }
64
65 pub fn include(&mut self, includes: impl IntoIterator<Item = impl Into<String>>) -> &mut Self {
67 self.include = Some(includes.into_iter().map(Into::into).collect());
68 self
69 }
70
71 pub fn order_by_asc(&mut self, field: &str) -> &mut Self {
73 self.order_by = Some(format!("{}[ASC]", field));
74 self
75 }
76
77 pub fn order_by_desc(&mut self, field: &str) -> &mut Self {
79 self.order_by = Some(format!("{}[DESC]", field));
80 self
81 }
82
83 pub fn per_page(&mut self, entities_per_page: usize) -> &mut Self {
88 self.per_page = Some(entities_per_page);
89 self
90 }
91
92 pub fn product_ids(
94 &mut self,
95 product_ids: impl IntoIterator<Item = impl Into<ProductID>>,
96 ) -> &mut Self {
97 self.product_id = Some(product_ids.into_iter().map(Into::into).collect());
98 self
99 }
100
101 pub fn status(&mut self, status: Status) -> &mut Self {
103 self.status = Some(status);
104 self
105 }
106
107 pub fn recurring(&mut self, value: bool) -> &mut Self {
109 self.recurring = Some(value);
110 self
111 }
112
113 pub fn r#type(&mut self, catalog_type: CatalogType) -> &mut Self {
115 self.r#type = Some(catalog_type);
116 self
117 }
118
119 pub async fn send(&self) -> Result<Vec<Price>> {
121 self.client.send(self, Method::GET, "/prices").await
122 }
123}
124
125#[skip_serializing_none]
127#[derive(Serialize)]
128pub struct PricesCreate<'a> {
129 #[serde(skip)]
130 client: &'a Paddle,
131 description: String,
132 product_id: ProductID,
133 unit_price: Money,
134 r#type: Option<CatalogType>,
135 name: Option<String>,
136 billing_cycle: Option<Duration>,
137 trial_period: Option<Duration>,
138 tax_mode: TaxMode,
139 unit_price_overrides: Option<Vec<UnitPriceOverride>>,
140 quantity: Option<PriceQuantity>,
141 custom_data: Option<HashMap<String, String>>,
142}
143
144impl<'a> PricesCreate<'a> {
145 pub fn new(
146 client: &'a Paddle,
147 product_id: impl Into<ProductID>,
148 description: impl Into<String>,
149 amount: u64,
150 currency: CurrencyCode,
151 ) -> Self {
152 Self {
153 client,
154 description: description.into(),
155 product_id: product_id.into(),
156 unit_price: Money {
157 amount: amount.to_string(),
158 currency_code: currency,
159 },
160 r#type: None,
161 name: None,
162 billing_cycle: None,
163 trial_period: None,
164 tax_mode: TaxMode::AccountSetting,
165 unit_price_overrides: None,
166 quantity: None,
167 custom_data: None,
168 }
169 }
170
171 pub fn catalog_type(&mut self, catalog_type: CatalogType) -> &mut Self {
173 self.r#type = Some(catalog_type);
174 self
175 }
176
177 pub fn name(&mut self, name: impl Into<String>) -> &mut Self {
179 self.name = Some(name.into());
180 self
181 }
182
183 pub fn billing_cycle(&mut self, frequency: u64, interval: Interval) -> &mut Self {
185 self.billing_cycle = Some(Duration {
186 interval,
187 frequency,
188 });
189
190 self
191 }
192
193 pub fn trial_period(&mut self, frequency: u64, interval: Interval) -> &mut Self {
195 self.trial_period = Some(Duration {
196 interval,
197 frequency,
198 });
199
200 self
201 }
202
203 pub fn tax_mode(&mut self, tax_mode: TaxMode) -> &mut Self {
206 self.tax_mode = tax_mode;
207 self
208 }
209
210 pub fn add_unit_price_override(
216 &mut self,
217 country_codes: impl IntoIterator<Item = CountryCodeSupported>,
218 amount: u64,
219 currency: CurrencyCode,
220 ) -> &mut Self {
221 if self.unit_price_overrides.is_none() {
222 self.unit_price_overrides = Some(vec![]);
223 }
224
225 self.unit_price_overrides
226 .as_mut()
227 .unwrap()
228 .push(UnitPriceOverride {
229 country_codes: country_codes.into_iter().collect(),
230 unit_price: Money {
231 amount: amount.to_string(),
232 currency_code: currency,
233 },
234 });
235
236 self
237 }
238
239 pub fn set_unit_price_overrides(&mut self, overrides: Vec<UnitPriceOverride>) -> &mut Self {
247 self.unit_price_overrides = Some(overrides);
248 self
249 }
250
251 pub fn quantity(&mut self, range: Range<u64>) -> &mut Self {
253 self.quantity = Some(PriceQuantity {
254 minimum: range.start,
255 maximum: range.end,
256 });
257 self
258 }
259
260 pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
262 self.custom_data = Some(custom_data);
263 self
264 }
265
266 pub async fn send(&self) -> Result<Price> {
268 self.client.send(self, Method::POST, "/prices").await
269 }
270}
271
272#[skip_serializing_none]
274#[derive(Serialize)]
275pub struct PriceGet<'a> {
276 #[serde(skip)]
277 client: &'a Paddle,
278 #[serde(skip)]
279 price_id: PriceID,
280 #[serde(serialize_with = "crate::comma_separated")]
281 include: Option<Vec<String>>,
282}
283
284impl<'a> PriceGet<'a> {
285 pub fn new(client: &'a Paddle, price_id: impl Into<PriceID>) -> Self {
286 Self {
287 client,
288 price_id: price_id.into(),
289 include: None,
290 }
291 }
292
293 pub fn include(&mut self, entities: impl IntoIterator<Item = impl AsRef<str>>) -> &mut Self {
295 self.include = Some(
296 entities
297 .into_iter()
298 .map(|s| s.as_ref().to_string())
299 .collect(),
300 );
301 self
302 }
303
304 pub async fn send(&self) -> Result<Price> {
306 self.client
307 .send(
308 self,
309 Method::GET,
310 &format!("/prices/{}", self.price_id.as_ref()),
311 )
312 .await
313 }
314}
315
316#[skip_serializing_none]
318#[derive(Serialize)]
319pub struct PriceUpdate<'a> {
320 #[serde(skip)]
321 client: &'a Paddle,
322 #[serde(skip)]
323 price_id: PriceID,
324 description: Option<String>,
325 r#type: Option<CatalogType>,
326 name: Option<String>,
327 billing_cycle: Option<Duration>,
328 trial_period: Option<Duration>,
329 tax_mode: Option<TaxMode>,
330 unit_price: Option<Money>,
331 unit_price_overrides: Option<Vec<UnitPriceOverride>>,
332 quantity: Option<PriceQuantity>,
333 status: Option<Status>,
334 custom_data: Option<HashMap<String, String>>,
335}
336
337impl<'a> PriceUpdate<'a> {
338 pub fn new(client: &'a Paddle, price_id: impl Into<PriceID>) -> Self {
339 Self {
340 client,
341 price_id: price_id.into(),
342 description: None,
343 r#type: None,
344 name: None,
345 billing_cycle: None,
346 trial_period: None,
347 tax_mode: None,
348 unit_price: None,
349 unit_price_overrides: None,
350 quantity: None,
351 status: None,
352 custom_data: None,
353 }
354 }
355
356 pub fn description(&mut self, description: impl Into<String>) -> &mut Self {
358 self.description = Some(description.into());
359 self
360 }
361
362 pub fn catalog_type(&mut self, catalog_type: CatalogType) -> &mut Self {
364 self.r#type = Some(catalog_type);
365 self
366 }
367
368 pub fn name(&mut self, name: impl Into<String>) -> &mut Self {
370 self.name = Some(name.into());
371 self
372 }
373
374 pub fn billing_cycle(&mut self, frequency: u64, interval: Interval) -> &mut Self {
376 self.billing_cycle = Some(Duration {
377 interval,
378 frequency,
379 });
380
381 self
382 }
383
384 pub fn trial_period(&mut self, frequency: u64, interval: Interval) -> &mut Self {
386 self.trial_period = Some(Duration {
387 interval,
388 frequency,
389 });
390
391 self
392 }
393
394 pub fn tax_mode(&mut self, tax_mode: TaxMode) -> &mut Self {
396 self.tax_mode = Some(tax_mode);
397 self
398 }
399
400 pub fn unit_price(&mut self, amount: u64, currency: CurrencyCode) -> &mut Self {
402 self.unit_price = Some(Money {
403 amount: amount.to_string(),
404 currency_code: currency,
405 });
406 self
407 }
408
409 pub fn add_unit_price_override(
411 &mut self,
412 country_codes: impl IntoIterator<Item = CountryCodeSupported>,
413 amount: u64,
414 currency: CurrencyCode,
415 ) -> &mut Self {
416 if self.unit_price_overrides.is_none() {
417 self.unit_price_overrides = Some(vec![]);
418 }
419
420 self.unit_price_overrides
421 .as_mut()
422 .unwrap()
423 .push(UnitPriceOverride {
424 country_codes: country_codes.into_iter().collect(),
425 unit_price: Money {
426 amount: amount.to_string(),
427 currency_code: currency,
428 },
429 });
430
431 self
432 }
433
434 pub fn set_unit_price_overrides(&mut self, overrides: Vec<UnitPriceOverride>) -> &mut Self {
436 self.unit_price_overrides = Some(overrides);
437 self
438 }
439
440 pub fn quantity(&mut self, range: Range<u64>) -> &mut Self {
442 self.quantity = Some(PriceQuantity {
443 minimum: range.start,
444 maximum: range.end,
445 });
446 self
447 }
448
449 pub fn status(&mut self, status: Status) -> &mut Self {
451 self.status = Some(status);
452 self
453 }
454
455 pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
457 self.custom_data = Some(custom_data);
458 self
459 }
460
461 pub async fn send(&self) -> Result<Price> {
463 self.client
464 .send(
465 self,
466 Method::PATCH,
467 &format!("/prices/{}", self.price_id.as_ref()),
468 )
469 .await
470 }
471}