1use std::collections::HashMap;
6
7use reqwest::Method;
8use serde::Serialize;
9use serde_with::skip_serializing_none;
10
11use crate::entities::Product;
12use crate::enums::{CatalogType, Status, TaxCategory};
13use crate::ids::ProductID;
14use crate::{Paddle, Result};
15
16#[skip_serializing_none]
18#[derive(Serialize)]
19pub struct ProductsList<'a> {
20 #[serde(skip)]
21 client: &'a Paddle,
22 after: Option<ProductID>,
23 #[serde(serialize_with = "crate::comma_separated")]
24 id: Option<Vec<ProductID>>,
25 #[serde(serialize_with = "crate::comma_separated")]
26 include: Option<Vec<String>>,
27 order_by: Option<String>,
28 per_page: Option<usize>,
29 status: Option<Status>,
30 #[serde(serialize_with = "crate::comma_separated")]
31 tax_category: Option<Vec<TaxCategory>>,
32 r#type: Option<CatalogType>,
33}
34
35impl<'a> ProductsList<'a> {
36 pub fn new(client: &'a Paddle) -> Self {
37 Self {
38 client,
39 after: None,
40 id: None,
41 include: None,
42 order_by: None,
43 per_page: None,
44 status: None,
45 tax_category: None,
46 r#type: None,
47 }
48 }
49
50 pub fn after(&mut self, product_id: impl Into<ProductID>) -> &mut Self {
52 self.after = Some(product_id.into());
53 self
54 }
55
56 pub fn ids(
58 &mut self,
59 product_ids: impl IntoIterator<Item = impl Into<ProductID>>,
60 ) -> &mut Self {
61 self.id = Some(product_ids.into_iter().map(|i| i.into()).collect());
62 self
63 }
64
65 pub fn include(&mut self, entities: impl IntoIterator<Item = impl AsRef<str>>) -> &mut Self {
67 self.include = Some(
68 entities
69 .into_iter()
70 .map(|s| s.as_ref().to_string())
71 .collect(),
72 );
73 self
74 }
75
76 pub fn order_by_asc(&mut self, field: &str) -> &mut Self {
78 self.order_by = Some(format!("{}[ASC]", field));
79 self
80 }
81
82 pub fn order_by_desc(&mut self, field: &str) -> &mut Self {
84 self.order_by = Some(format!("{}[DESC]", field));
85 self
86 }
87
88 pub fn per_page(&mut self, entities_per_page: usize) -> &mut Self {
93 self.per_page = Some(entities_per_page);
94 self
95 }
96
97 pub fn status(&mut self, status: Status) -> &mut Self {
99 self.status = Some(status);
100 self
101 }
102
103 pub fn tax_category(
105 &mut self,
106 tax_categories: impl IntoIterator<Item = TaxCategory>,
107 ) -> &mut Self {
108 self.tax_category = Some(tax_categories.into_iter().collect());
109 self
110 }
111
112 pub fn catalog_type(&mut self, catalog_type: CatalogType) -> &mut Self {
114 self.r#type = Some(catalog_type);
115 self
116 }
117
118 pub async fn send(&self) -> Result<Vec<Product>> {
120 self.client.send(self, Method::GET, "/products").await
121 }
122}
123
124#[skip_serializing_none]
126#[derive(Serialize)]
127pub struct ProductCreate<'a> {
128 #[serde(skip)]
129 client: &'a Paddle,
130 name: String,
131 tax_category: TaxCategory,
132 description: Option<String>,
133 r#type: Option<CatalogType>,
134 image_url: Option<String>,
135 custom_data: Option<HashMap<String, String>>,
136}
137
138impl<'a> ProductCreate<'a> {
139 pub fn new(client: &'a Paddle, name: impl Into<String>, tax_category: TaxCategory) -> Self {
140 Self {
141 client,
142 name: name.into(),
143 tax_category,
144 description: None,
145 r#type: None,
146 image_url: None,
147 custom_data: None,
148 }
149 }
150
151 pub fn description(&mut self, description: impl Into<String>) -> &mut Self {
153 self.description = Some(description.into());
154 self
155 }
156
157 pub fn catalog_type(&mut self, catalog_type: CatalogType) -> &mut Self {
159 self.r#type = Some(catalog_type);
160 self
161 }
162
163 pub fn image_url(&mut self, image_url: impl Into<String>) -> &mut Self {
165 self.image_url = Some(image_url.into());
166 self
167 }
168
169 pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
171 self.custom_data = Some(custom_data);
172 self
173 }
174
175 pub async fn send(&self) -> Result<Product> {
177 self.client.send(self, Method::POST, "/products").await
178 }
179}
180
181#[skip_serializing_none]
183#[derive(Serialize)]
184pub struct ProductGet<'a> {
185 #[serde(skip)]
186 client: &'a Paddle,
187 #[serde(skip)]
188 product_id: ProductID,
189 #[serde(serialize_with = "crate::comma_separated")]
190 include: Option<Vec<String>>,
191}
192
193impl<'a> ProductGet<'a> {
194 pub fn new(client: &'a Paddle, product_id: impl Into<ProductID>) -> Self {
195 Self {
196 client,
197 product_id: product_id.into(),
198 include: None,
199 }
200 }
201
202 pub fn include(&mut self, entities: impl IntoIterator<Item = impl AsRef<str>>) -> &mut Self {
204 self.include = Some(
205 entities
206 .into_iter()
207 .map(|s| s.as_ref().to_string())
208 .collect(),
209 );
210 self
211 }
212
213 pub async fn send(&self) -> Result<Product> {
215 self.client
216 .send(
217 self,
218 Method::GET,
219 &format!("/products/{}", self.product_id.as_ref()),
220 )
221 .await
222 }
223}
224
225#[skip_serializing_none]
227#[derive(Serialize)]
228pub struct ProductUpdate<'a> {
229 #[serde(skip)]
230 client: &'a Paddle,
231 #[serde(skip)]
232 product_id: ProductID,
233 name: Option<String>,
234 description: Option<String>,
235 r#type: Option<CatalogType>,
236 tax_category: Option<TaxCategory>,
237 image_url: Option<String>,
238 custom_data: Option<HashMap<String, String>>,
239 status: Option<Status>,
240}
241
242impl<'a> ProductUpdate<'a> {
243 pub fn new(client: &'a Paddle, product_id: impl Into<ProductID>) -> Self {
244 Self {
245 client,
246 product_id: product_id.into(),
247 name: None,
248 description: None,
249 r#type: None,
250 tax_category: None,
251 image_url: None,
252 custom_data: None,
253 status: None,
254 }
255 }
256
257 pub fn name(&mut self, name: impl Into<String>) -> &mut Self {
259 self.name = Some(name.into());
260 self
261 }
262
263 pub fn description(&mut self, description: impl Into<String>) -> &mut Self {
265 self.description = Some(description.into());
266 self
267 }
268
269 pub fn catalog_type(&mut self, catalog_type: CatalogType) -> &mut Self {
271 self.r#type = Some(catalog_type);
272 self
273 }
274
275 pub fn tax_category(&mut self, tax_category: TaxCategory) -> &mut Self {
277 self.tax_category = Some(tax_category);
278 self
279 }
280
281 pub fn image_url(&mut self, image_url: impl Into<String>) -> &mut Self {
283 self.image_url = Some(image_url.into());
284 self
285 }
286
287 pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
289 self.custom_data = Some(custom_data);
290 self
291 }
292
293 pub fn status(&mut self, status: Status) -> &mut Self {
295 self.status = Some(status);
296 self
297 }
298
299 pub async fn send(&self) -> Result<Product> {
301 self.client
302 .send(
303 self,
304 Method::PATCH,
305 &format!("/products/{}", self.product_id.as_ref()),
306 )
307 .await
308 }
309}