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::nullable::Nullable;
16use crate::{Paddle, Result};
17
18#[skip_serializing_none]
20#[derive(Serialize)]
21pub struct CustomersList<'a> {
22 #[serde(skip)]
23 client: &'a Paddle,
24 after: Option<CustomerID>,
25 #[serde(serialize_with = "crate::comma_separated")]
26 email: Option<Vec<String>>,
27 #[serde(serialize_with = "crate::comma_separated")]
28 id: Option<Vec<CustomerID>>,
29 order_by: Option<String>,
30 per_page: Option<usize>,
31 search: Option<String>,
32 status: Option<Status>,
33}
34
35impl<'a> CustomersList<'a> {
36 pub fn new(client: &'a Paddle) -> Self {
37 Self {
38 client,
39 after: None,
40 email: None,
41 id: None,
42 order_by: None,
43 per_page: None,
44 search: None,
45 status: None,
46 }
47 }
48
49 pub fn after(&mut self, customer_id: impl Into<CustomerID>) -> &mut Self {
51 self.after = Some(customer_id.into());
52 self
53 }
54
55 pub fn emails(&mut self, emails: impl IntoIterator<Item = impl AsRef<str>>) -> &mut Self {
57 self.email = Some(emails.into_iter().map(|s| s.as_ref().to_string()).collect());
58 self
59 }
60
61 pub fn ids(
63 &mut self,
64 customer_ids: impl IntoIterator<Item = impl Into<CustomerID>>,
65 ) -> &mut Self {
66 self.id = Some(customer_ids.into_iter().map(Into::into).collect());
67 self
68 }
69
70 pub fn order_by_asc(&mut self, field: &str) -> &mut Self {
72 self.order_by = Some(format!("{}[ASC]", field));
73 self
74 }
75
76 pub fn order_by_desc(&mut self, field: &str) -> &mut Self {
78 self.order_by = Some(format!("{}[DESC]", field));
79 self
80 }
81
82 pub fn per_page(&mut self, entities_per_page: usize) -> &mut Self {
87 self.per_page = Some(entities_per_page);
88 self
89 }
90
91 pub fn search(&mut self, term: impl Into<String>) -> &mut Self {
93 self.search = Some(term.into());
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 send(&self) -> Paginated<'_, Vec<Customer>> {
105 Paginated::new(self.client, "/customers", self)
106 }
107}
108
109#[skip_serializing_none]
111#[derive(Serialize)]
112pub struct CustomerCreate<'a> {
113 #[serde(skip)]
114 client: &'a Paddle,
115 email: String,
116 name: Option<String>,
117 custom_data: Option<HashMap<String, String>>,
118 locale: Option<String>,
119}
120
121impl<'a> CustomerCreate<'a> {
122 pub fn new(client: &'a Paddle, email: String) -> Self {
123 Self {
124 client,
125 email,
126 name: None,
127 custom_data: None,
128 locale: None,
129 }
130 }
131
132 pub fn name(&mut self, name: impl Into<String>) -> &mut Self {
134 self.name = Some(name.into());
135 self
136 }
137
138 pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
140 self.custom_data = Some(custom_data);
141 self
142 }
143
144 pub fn locale(&mut self, locale: impl Into<String>) -> &mut Self {
146 self.locale = Some(locale.into());
147 self
148 }
149
150 pub async fn send(&self) -> Result<Customer> {
152 self.client.send(self, Method::POST, "/customers").await
153 }
154}
155
156#[derive(Serialize)]
158pub struct CustomerGet<'a> {
159 #[serde(skip)]
160 client: &'a Paddle,
161 #[serde(skip)]
162 customer_id: CustomerID,
163}
164
165impl<'a> CustomerGet<'a> {
166 pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
167 Self {
168 client,
169 customer_id: customer_id.into(),
170 }
171 }
172
173 pub async fn send(&self) -> Result<Customer> {
175 self.client
176 .send(
177 self,
178 Method::GET,
179 &format!("/customers/{}", self.customer_id.as_ref()),
180 )
181 .await
182 }
183}
184
185#[derive(Serialize)]
187pub struct CustomerUpdate<'a> {
188 #[serde(skip)]
189 client: &'a Paddle,
190 #[serde(skip)]
191 customer_id: CustomerID,
192 #[serde(skip_serializing_if = "Nullable::is_unchanged")]
193 name: Nullable<String>,
194 #[serde(skip_serializing_if = "Nullable::is_unchanged")]
195 email: Nullable<String>,
196 #[serde(skip_serializing_if = "Nullable::is_unchanged")]
197 status: Nullable<Status>,
198 #[serde(skip_serializing_if = "Nullable::is_unchanged")]
199 custom_data: Nullable<HashMap<String, String>>,
200 #[serde(skip_serializing_if = "Nullable::is_unchanged")]
201 locale: Nullable<String>,
202}
203
204impl<'a> CustomerUpdate<'a> {
205 pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
206 Self {
207 client,
208 customer_id: customer_id.into(),
209 name: Nullable::Unchanged,
210 email: Nullable::Unchanged,
211 status: Nullable::Unchanged,
212 custom_data: Nullable::Unchanged,
213 locale: Nullable::Unchanged,
214 }
215 }
216
217 pub fn name(&mut self, name: impl Into<Nullable<String>>) -> &mut Self {
219 self.name = name.into();
220 self
221 }
222
223 pub fn email(&mut self, email: impl Into<Nullable<String>>) -> &mut Self {
225 self.email = email.into();
226 self
227 }
228
229 pub fn status(&mut self, status: impl Into<Nullable<Status>>) -> &mut Self {
231 self.status = status.into();
232 self
233 }
234
235 pub fn custom_data(
237 &mut self,
238 custom_data: impl Into<Nullable<HashMap<String, String>>>,
239 ) -> &mut Self {
240 self.custom_data = custom_data.into();
241 self
242 }
243
244 pub fn locale(&mut self, locale: impl Into<Nullable<String>>) -> &mut Self {
246 self.locale = locale.into();
247 self
248 }
249
250 pub async fn send(&self) -> Result<Customer> {
252 self.client
253 .send(
254 self,
255 Method::PATCH,
256 &format!("/customers/{}", self.customer_id.as_ref()),
257 )
258 .await
259 }
260}
261
262#[skip_serializing_none]
264#[derive(Serialize)]
265pub struct CustomerCreditBalances<'a> {
266 #[serde(skip)]
267 client: &'a Paddle,
268 #[serde(skip)]
269 customer_id: CustomerID,
270}
271
272impl<'a> CustomerCreditBalances<'a> {
273 pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
274 Self {
275 client,
276 customer_id: customer_id.into(),
277 }
278 }
279
280 pub async fn send(&self) -> Result<Vec<CreditBalance>> {
282 self.client
283 .send(
284 self,
285 Method::GET,
286 &format!("/customers/{}/credit-balances", self.customer_id.as_ref()),
287 )
288 .await
289 }
290}
291
292#[skip_serializing_none]
294#[derive(Serialize)]
295pub struct PortalSessionCreate<'a> {
296 #[serde(skip)]
297 client: &'a Paddle,
298 #[serde(skip)]
299 customer_id: CustomerID,
300 subscription_ids: Option<Vec<SubscriptionID>>,
301}
302
303impl<'a> PortalSessionCreate<'a> {
304 pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
305 Self {
306 client,
307 customer_id: customer_id.into(),
308 subscription_ids: None,
309 }
310 }
311
312 pub fn subscription_ids(
314 &mut self,
315 subscription_ids: impl IntoIterator<Item = impl Into<SubscriptionID>>,
316 ) -> &mut Self {
317 self.subscription_ids = Some(subscription_ids.into_iter().map(Into::into).collect());
318 self
319 }
320
321 pub async fn send(&self) -> Result<CustomerPortalSession> {
323 self.client
324 .send(
325 self,
326 Method::POST,
327 &format!("/customers/{}/portal-sessions", self.customer_id.as_ref()),
328 )
329 .await
330 }
331}