Skip to content

Commit 2a3770e

Browse files
committed
feat(customer) added support for updating customer in the integration
1 parent 2cbb695 commit 2a3770e

3 files changed

Lines changed: 98 additions & 3 deletions

File tree

src/endpoints/customers.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::sync::Arc;
66

77
use crate::{
88
CreateCustomerRequest, CustomerResponseData, HttpClient, PaystackAPIError, PaystackResult,
9-
Response,
9+
Response, UpdateCustomerRequest,
1010
};
1111

1212
/// A struct to hold all the functions of the customers API endpoint
@@ -111,4 +111,33 @@ impl<T: HttpClient + Default> CustomersEndpoints<T> {
111111
Err(e) => Err(PaystackAPIError::Customer(e.to_string())),
112112
}
113113
}
114+
115+
/// Update a customer's details on your integration
116+
///
117+
/// It takes the following parameters:
118+
/// - `code`: The customer's code
119+
/// - `update_customer_request`: The data to update the customer with.
120+
/// It should be created with the `UpdateCustomerRequestBuilder` struct.
121+
pub async fn update_customer(
122+
&self,
123+
code: String,
124+
update_customer_request: UpdateCustomerRequest,
125+
) -> PaystackResult<CustomerResponseData> {
126+
let url = format!("{}/{}", self.base_url, code);
127+
let body = serde_json::to_value(update_customer_request)
128+
.map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
129+
130+
let response = self.http.put(&url, &self.key, &body).await;
131+
132+
match response {
133+
Ok(response) => {
134+
let parsed_response: Response<CustomerResponseData> =
135+
serde_json::from_str(&response)
136+
.map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
137+
138+
Ok(parsed_response)
139+
}
140+
Err(e) => Err(PaystackAPIError::Customer(e.to_string())),
141+
}
142+
}
114143
}

src/models/customer.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub struct CustomerResponseData {
3030
pub dedicated_account: Option<String>,
3131
}
3232

33+
/// This struct constains the data for creating a customer in your integration
3334
#[derive(Debug, Clone, Serialize, Default, Deserialize, Builder)]
3435
pub struct CreateCustomerRequest {
3536
/// Customer's email address
@@ -45,6 +46,20 @@ pub struct CreateCustomerRequest {
4546
pub phone: Option<String>,
4647
}
4748

49+
/// This struct constains the data for updating a customer in your integration
50+
#[derive(Debug, Clone, Serialize, Default, Deserialize, Builder)]
51+
pub struct UpdateCustomerRequest {
52+
/// Customer's first name
53+
#[builder(setter(strip_option), default)]
54+
pub first_name: Option<String>,
55+
/// Customer's last name
56+
#[builder(setter(strip_option), default)]
57+
pub last_name: Option<String>,
58+
/// Customer's phone number
59+
#[builder(setter(strip_option), default)]
60+
pub phone: Option<String>,
61+
}
62+
4863
#[cfg(test)]
4964
mod tests {
5065
use super::*;
@@ -64,7 +79,7 @@ mod tests {
6479
}
6580

6681
#[test]
67-
fn create_customer_with_invalid_data_fails() {
82+
fn build_customer_with_invalid_data_fails() {
6883
let first_name = "Zero".to_string();
6984
let last_name = "Sum".to_string();
7085
let phone = "+2348123456789".to_string();

tests/api/customer.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use fake::{
66
},
77
Fake,
88
};
9-
use paystack::CreateCustomerRequestBuilder;
9+
use paystack::{CreateCustomerRequestBuilder, UpdateCustomerRequestBuilder};
1010

1111
use crate::helpers::get_paystack_client;
1212

@@ -141,3 +141,54 @@ async fn can_fetch_customer_from_the_integration_with_customer_code() {
141141
assert_eq!(&res_data.email, &customer_data.email);
142142
assert_eq!(&res_data.customer_code, &customer_data.customer_code);
143143
}
144+
145+
// TODO: find a way to clean up customers in the integration after the test
146+
#[tokio::test]
147+
async fn can_modify_customer_information() {
148+
// Arrange
149+
let client = get_paystack_client();
150+
151+
// Act
152+
let body = CreateCustomerRequestBuilder::default()
153+
.email("test@email.com".to_string())
154+
.first_name("Old First Name".to_string())
155+
.last_name("Old Last Name".to_string())
156+
.build()
157+
.unwrap();
158+
let customer = client
159+
.customers
160+
.create_customer(body)
161+
.await
162+
.expect("unable to create customer");
163+
164+
let customer_data = customer.data.unwrap();
165+
166+
// Check that these fields don't exist
167+
assert!(customer.status);
168+
assert!(customer.message.contains("Customer created"));
169+
170+
// update customer
171+
let update_request = UpdateCustomerRequestBuilder::default()
172+
.first_name("New First Name".to_string())
173+
.last_name("New Last Name".to_string())
174+
.build()
175+
.unwrap();
176+
let updated_customer = client
177+
.customers
178+
.update_customer(customer_data.customer_code, update_request)
179+
.await
180+
.expect("unable to update customer");
181+
182+
// Assert
183+
let updated_customer_data = updated_customer.data.unwrap();
184+
assert!(updated_customer.status);
185+
assert!(updated_customer.message.contains("Customer updated"));
186+
assert_eq!(
187+
updated_customer_data.first_name,
188+
Some("New First Name".to_string())
189+
);
190+
assert_eq!(
191+
updated_customer_data.last_name,
192+
Some("New Last Name".to_string())
193+
)
194+
}

0 commit comments

Comments
 (0)