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