1use std::collections::HashMap;
6
7use reqwest::Method;
8use serde::Serialize;
9use serde_with::skip_serializing_none;
10
11use crate::entities::{CreditBalance, Customer, CustomerPortalSession};
12use crate::enums::Status;
13use crate::ids::{CustomerID, SubscriptionID};
14use crate::paginated::Paginated;
15use crate::{Paddle, Result};
16
17#[skip_serializing_none]
19#[derive(Serialize)]
20pub struct CustomersList<'a> {
21 #[serde(skip)]
22 client: &'a Paddle,
23 after: Option<CustomerID>,
24 #[serde(serialize_with = "crate::comma_separated")]
25 email: Option<Vec<String>>,
26 #[serde(serialize_with = "crate::comma_separated")]
27 id: Option<Vec<CustomerID>>,
28 order_by: Option<String>,
29 per_page: Option<usize>,
30 search: Option<String>,
31 status: Option<Status>,
32}
33
34impl<'a> CustomersList<'a> {
35 pub fn new(client: &'a Paddle) -> Self {
36 Self {
37 client,
38 after: None,
39 email: None,
40 id: None,
41 order_by: None,
42 per_page: None,
43 search: None,
44 status: None,
45 }
46 }
47
48 pub fn after(&mut self, customer_id: impl Into<CustomerID>) -> &mut Self {
50 self.after = Some(customer_id.into());
51 self
52 }
53
54 pub fn emails(&mut self, emails: impl IntoIterator<Item = impl AsRef<str>>) -> &mut Self {
56 self.email = Some(emails.into_iter().map(|s| s.as_ref().to_string()).collect());
57 self
58 }
59
60 pub fn ids(
62 &mut self,
63 customer_ids: impl IntoIterator<Item = impl Into<CustomerID>>,
64 ) -> &mut Self {
65 self.id = Some(customer_ids.into_iter().map(Into::into).collect());
66 self
67 }
68
69 pub fn order_by_asc(&mut self, field: &str) -> &mut Self {
71 self.order_by = Some(format!("{}[ASC]", field));
72 self
73 }
74
75 pub fn order_by_desc(&mut self, field: &str) -> &mut Self {
77 self.order_by = Some(format!("{}[DESC]", field));
78 self
79 }
80
81 pub fn per_page(&mut self, entities_per_page: usize) -> &mut Self {
86 self.per_page = Some(entities_per_page);
87 self
88 }
89
90 pub fn search(&mut self, term: impl Into<String>) -> &mut Self {
92 self.search = Some(term.into());
93 self
94 }
95
96 pub fn status(&mut self, status: Status) -> &mut Self {
98 self.status = Some(status);
99 self
100 }
101
102 pub fn send(&self) -> Paginated<Vec<Customer>> {
104 Paginated::new(self.client, "/customers", self)
105 }
106}
107
108#[skip_serializing_none]
110#[derive(Serialize)]
111pub struct CustomerCreate<'a> {
112 #[serde(skip)]
113 client: &'a Paddle,
114 email: String,
115 name: Option<String>,
116 custom_data: Option<HashMap<String, String>>,
117 locale: Option<String>,
118}
119
120impl<'a> CustomerCreate<'a> {
121 pub fn new(client: &'a Paddle, email: String) -> Self {
122 Self {
123 client,
124 email,
125 name: None,
126 custom_data: None,
127 locale: None,
128 }
129 }
130
131 pub fn name(&mut self, name: impl Into<String>) -> &mut Self {
133 self.name = Some(name.into());
134 self
135 }
136
137 pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
139 self.custom_data = Some(custom_data);
140 self
141 }
142
143 pub fn locale(&mut self, locale: impl Into<String>) -> &mut Self {
145 self.locale = Some(locale.into());
146 self
147 }
148
149 pub async fn send(&self) -> Result<Customer> {
151 self.client.send(self, Method::POST, "/customers").await
152 }
153}
154
155#[derive(Serialize)]
157pub struct CustomerGet<'a> {
158 #[serde(skip)]
159 client: &'a Paddle,
160 #[serde(skip)]
161 customer_id: CustomerID,
162}
163
164impl<'a> CustomerGet<'a> {
165 pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
166 Self {
167 client,
168 customer_id: customer_id.into(),
169 }
170 }
171
172 pub async fn send(&self) -> Result<Customer> {
174 self.client
175 .send(
176 self,
177 Method::GET,
178 &format!("/customers/{}", self.customer_id.as_ref()),
179 )
180 .await
181 }
182}
183
184#[skip_serializing_none]
186#[derive(Serialize)]
187pub struct CustomerUpdate<'a> {
188 #[serde(skip)]
189 client: &'a Paddle,
190 #[serde(skip)]
191 customer_id: CustomerID,
192 name: Option<String>,
193 email: Option<String>,
194 status: Option<Status>,
195 custom_data: Option<HashMap<String, String>>,
196 locale: Option<String>,
197}
198
199impl<'a> CustomerUpdate<'a> {
200 pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
201 Self {
202 client,
203 customer_id: customer_id.into(),
204 name: None,
205 email: None,
206 status: None,
207 custom_data: None,
208 locale: None,
209 }
210 }
211
212 pub fn name(&mut self, name: impl Into<String>) -> &mut Self {
214 self.name = Some(name.into());
215 self
216 }
217
218 pub fn email(&mut self, email: impl Into<String>) -> &mut Self {
220 self.email = Some(email.into());
221 self
222 }
223
224 pub fn status(&mut self, status: Status) -> &mut Self {
226 self.status = Some(status);
227 self
228 }
229
230 pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
232 self.custom_data = Some(custom_data);
233 self
234 }
235
236 pub fn locale(&mut self, locale: impl Into<String>) -> &mut Self {
238 self.locale = Some(locale.into());
239 self
240 }
241
242 pub async fn send(&self) -> Result<Customer> {
244 self.client
245 .send(
246 self,
247 Method::PATCH,
248 &format!("/customers/{}", self.customer_id.as_ref()),
249 )
250 .await
251 }
252}
253
254#[skip_serializing_none]
256#[derive(Serialize)]
257pub struct CustomerCreditBalances<'a> {
258 #[serde(skip)]
259 client: &'a Paddle,
260 #[serde(skip)]
261 customer_id: CustomerID,
262}
263
264impl<'a> CustomerCreditBalances<'a> {
265 pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
266 Self {
267 client,
268 customer_id: customer_id.into(),
269 }
270 }
271
272 pub async fn send(&self) -> Result<Vec<CreditBalance>> {
274 self.client
275 .send(
276 self,
277 Method::GET,
278 &format!("/customers/{}/credit-balances", self.customer_id.as_ref()),
279 )
280 .await
281 }
282}
283
284#[skip_serializing_none]
286#[derive(Serialize)]
287pub struct PortalSessionCreate<'a> {
288 #[serde(skip)]
289 client: &'a Paddle,
290 #[serde(skip)]
291 customer_id: CustomerID,
292 subscription_ids: Option<Vec<SubscriptionID>>,
293}
294
295impl<'a> PortalSessionCreate<'a> {
296 pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
297 Self {
298 client,
299 customer_id: customer_id.into(),
300 subscription_ids: None,
301 }
302 }
303
304 pub fn subscription_ids(
306 &mut self,
307 subscription_ids: impl IntoIterator<Item = impl Into<SubscriptionID>>,
308 ) -> &mut Self {
309 self.subscription_ids = Some(subscription_ids.into_iter().map(Into::into).collect());
310 self
311 }
312
313 pub async fn send(&self) -> Result<CustomerPortalSession> {
315 self.client
316 .send(
317 self,
318 Method::POST,
319 &format!("/customers/{}/portal-sessions", self.customer_id.as_ref()),
320 )
321 .await
322 }
323}