Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add a domain type for customer_id #4705

Merged
merged 19 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 11 additions & 16 deletions crates/api_models/src/customers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use common_utils::{consts, crypto, custom_serde, pii};
use common_utils::{crypto, custom_serde, id_type, pii};
use masking::Secret;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
Expand All @@ -9,9 +9,8 @@ use crate::payments;
#[derive(Debug, Default, Clone, Deserialize, Serialize, ToSchema)]
pub struct CustomerRequest {
/// The identifier for the customer object. If not provided the customer ID will be autogenerated.
#[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
#[serde(default = "generate_customer_id")]
pub customer_id: String,
#[schema(value_type = Option<String>, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,
/// The identifier for the Merchant Account
Narayanbhat166 marked this conversation as resolved.
Show resolved Hide resolved
#[schema(max_length = 255, example = "y3oqhf46pyzuxjbcn2giaqnb44")]
#[serde(default = "unknown_merchant", skip)]
Expand Down Expand Up @@ -43,9 +42,9 @@ pub struct CustomerRequest {

#[derive(Debug, Clone, Serialize, ToSchema)]
pub struct CustomerResponse {
/// The identifier for the customer object. If not provided the customer ID will be autogenerated.
#[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: String,
/// The identifier for the customer object
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,
/// The customer's name
#[schema(max_length = 255, value_type = Option<String>, example = "Jon Test")]
pub name: crypto::OptionalEncryptableName,
Expand Down Expand Up @@ -78,16 +77,16 @@ pub struct CustomerResponse {
pub default_payment_method_id: Option<String>,
}

#[derive(Default, Clone, Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CustomerId {
pub customer_id: String,
pub customer_id: id_type::CustomerId,
}

#[derive(Default, Debug, Deserialize, Serialize, ToSchema)]
#[derive(Debug, Deserialize, Serialize, ToSchema)]
pub struct CustomerDeleteResponse {
/// The identifier for the customer object
#[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: String,
#[schema(value_type = String, max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,
/// Whether customer was deleted or not
#[schema(example = false)]
pub customer_deleted: bool,
Expand All @@ -99,10 +98,6 @@ pub struct CustomerDeleteResponse {
pub payment_methods_deleted: bool,
}

pub fn generate_customer_id() -> String {
common_utils::generate_id(consts::ID_LENGTH, "cus")
}

fn unknown_merchant() -> String {
String::from("merchant_unknown")
}
4 changes: 3 additions & 1 deletion crates/api_models/src/ephemeral_key.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use common_utils::id_type;
use serde;
use utoipa::ToSchema;

#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, Eq, PartialEq, ToSchema)]
pub struct EphemeralKeyCreateResponse {
/// customer_id to which this ephemeral key belongs to
pub customer_id: String,
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,
/// time at which this ephemeral key was created
pub created_at: i64,
/// time at which this ephemeral key would expire
Expand Down
6 changes: 3 additions & 3 deletions crates/api_models/src/events/customer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ impl ApiEventMetric for CustomerDeleteResponse {

impl ApiEventMetric for CustomerRequest {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Customer {
customer_id: self.customer_id.clone(),
})
self.customer_id
.clone()
.map(|customer_id| ApiEventsType::Customer { customer_id })
Comment on lines +15 to +17
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can store the new type inside ApiEvents as long as it implements valid serialization

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I have already added the new type for ApiEvents

customer_id: id_type::CustomerId,

The change here is that the mandatory field is made optional

}
}

Expand Down
29 changes: 15 additions & 14 deletions crates/api_models/src/payment_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use cards::CardNumber;
use common_utils::{
consts::SURCHARGE_PERCENTAGE_PRECISION_LENGTH,
crypto::OptionalEncryptableName,
pii,
id_type, pii,
types::{MinorUnit, Percentage, Surcharge},
};
use serde::de;
Expand Down Expand Up @@ -49,8 +49,8 @@ pub struct PaymentMethodCreate {
pub metadata: Option<pii::SecretSerdeValue>,

/// The unique identifier of the customer.
#[schema(example = "cus_meowerunwiuwiwqw")]
pub customer_id: Option<String>,
#[schema(value_type = Option<String>, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,

/// The card network
#[schema(example = "Visa")]
Expand Down Expand Up @@ -194,8 +194,8 @@ pub struct PaymentMethodResponse {
pub merchant_id: String,

/// The unique identifier of the customer.
#[schema(example = "cus_meowerunwiuwiwqw")]
pub customer_id: Option<String>,
#[schema(value_type = Option<String>, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,

/// The unique identifier of the Payment method
#[schema(example = "card_rGK4Vi5iSW70MY7J2mIg")]
Expand Down Expand Up @@ -846,8 +846,8 @@ pub struct CustomerDefaultPaymentMethodResponse {
#[schema(example = "card_rGK4Vi5iSW70MY7J2mIg")]
pub default_payment_method_id: Option<String>,
/// The unique identifier of the customer.
#[schema(example = "cus_meowerunwiuwiwqw")]
pub customer_id: String,
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,
/// The type of payment method use for the payment.
#[schema(value_type = PaymentMethod,example = "card")]
pub payment_method: api_enums::PaymentMethod,
Expand All @@ -866,8 +866,8 @@ pub struct CustomerPaymentMethod {
pub payment_method_id: String,

/// The unique identifier of the customer.
#[schema(example = "cus_meowerunwiuwiwqw")]
pub customer_id: String,
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,

/// The type of payment method use for the payment.
#[schema(value_type = PaymentMethod,example = "card")]
Expand Down Expand Up @@ -952,7 +952,8 @@ pub struct PaymentMethodId {

#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
pub struct DefaultPaymentMethod {
pub customer_id: String,
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,
pub payment_method_id: String,
}
//------------------------------------------------TokenizeService------------------------------------------------
Expand Down Expand Up @@ -1034,7 +1035,7 @@ pub struct TokenizedCardValue2 {
pub card_security_code: Option<String>,
pub card_fingerprint: Option<String>,
pub external_id: Option<String>,
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
pub payment_method_id: Option<String>,
}

Expand All @@ -1045,7 +1046,7 @@ pub struct TokenizedWalletValue1 {

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedWalletValue2 {
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
Expand All @@ -1055,7 +1056,7 @@ pub struct TokenizedBankTransferValue1 {

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedBankTransferValue2 {
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
Expand All @@ -1065,5 +1066,5 @@ pub struct TokenizedBankRedirectValue1 {

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedBankRedirectValue2 {
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
}
64 changes: 48 additions & 16 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use common_utils::{
consts::default_payments_list_limit,
crypto,
ext_traits::{ConfigExt, Encode},
id_type,
pii::{self, Email},
types::MinorUnit,
};
Expand Down Expand Up @@ -177,10 +178,34 @@ mod client_secret_tests {
}
}

#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema, PartialEq)]
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema, PartialEq)]
pub struct CustomerDetails {
/// The identifier for the customer.
pub id: String,
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub id: id_type::CustomerId,

/// The customer's name
#[schema(max_length = 255, value_type = Option<String>, example = "John Doe")]
pub name: Option<Secret<String>>,

/// The customer's email address
#[schema(max_length = 255, value_type = Option<String>, example = "johntest@test.com")]
pub email: Option<Email>,

/// The customer's phone number
#[schema(value_type = Option<String>, max_length = 10, example = "3141592653")]
pub phone: Option<Secret<String>>,

/// The country code for the customer's phone number
#[schema(max_length = 2, example = "+1")]
pub phone_country_code: Option<String>,
}

#[derive(Debug, serde::Serialize, Clone, ToSchema, PartialEq)]
pub struct CustomerDetailsResponse {
/// The identifier for the customer.
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub id: id_type::CustomerId,

/// The customer's name
#[schema(max_length = 255, value_type = Option<String>, example = "John Doe")]
Expand Down Expand Up @@ -277,9 +302,9 @@ pub struct PaymentsRequest {
/// Passing this object creates a new customer or attaches an existing customer to the payment
pub customer: Option<CustomerDetails>,

/// The identifier for the customer object.
#[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<String>,
/// The identifier for the customer
#[schema(value_type = Option<String>, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,

/// The customer's email address.
/// This field will be deprecated soon, use the customer object instead
Expand Down Expand Up @@ -762,7 +787,7 @@ pub struct VerifyRequest {
// The merchant_id is generated through api key
// and is later passed in the struct
pub merchant_id: Option<String>,
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
pub email: Option<Email>,
pub name: Option<Secret<String>>,
pub phone: Option<Secret<String>>,
Expand Down Expand Up @@ -3239,14 +3264,16 @@ pub struct PaymentsResponse {
/// The identifier for the customer object. If not provided the customer ID will be autogenerated.
/// This field will be deprecated soon. Please refer to `customer.id`
#[schema(
max_length = 255,
max_length = 64,
min_length = 1,
example = "cus_y3oqhf46pyzuxjbcn2giaqnb44",
deprecated
deprecated,
value_type = Option<String>,
)]
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,

/// Details of customer attached to this payment
pub customer: Option<CustomerDetails>,
pub customer: Option<CustomerDetailsResponse>,

/// A description of the payment
#[schema(example = "It's my first payment request")]
Expand Down Expand Up @@ -3534,8 +3561,13 @@ pub struct ExternalAuthenticationDetailsResponse {
#[serde(deny_unknown_fields)]
pub struct PaymentListConstraints {
/// The identifier for customer
#[schema(example = "cus_meowuwunwiuwiwqw")]
pub customer_id: Option<String>,
#[schema(
max_length = 64,
min_length = 1,
example = "cus_y3oqhf46pyzuxjbcn2giaqnb44",
value_type = Option<String>,
)]
pub customer_id: Option<id_type::CustomerId>,

/// A cursor for use in pagination, fetch the next list after some object
#[schema(example = "pay_fafa124123")]
Expand Down Expand Up @@ -3632,7 +3664,7 @@ pub struct PaymentListFilterConstraints {
/// The identifier for business profile
pub profile_id: Option<String>,
/// The identifier for customer
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
/// The limit on the number of objects. The default limit is 10 and max limit is 20
#[serde(default = "default_payments_list_limit")]
pub limit: u32,
Expand Down Expand Up @@ -3716,7 +3748,7 @@ pub struct VerifyResponse {
pub merchant_id: Option<String>,
// pub status: enums::VerifyStatus,
pub client_secret: Option<Secret<String>>,
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
pub email: crypto::OptionalEncryptableEmail,
pub name: crypto::OptionalEncryptableName,
pub phone: crypto::OptionalEncryptablePhone,
Expand All @@ -3738,7 +3770,7 @@ pub struct PaymentsRedirectionResponse {
pub struct MandateValidationFields {
pub recurring_details: Option<RecurringDetails>,
pub confirm: Option<bool>,
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
pub mandate_data: Option<MandateData>,
pub setup_future_usage: Option<api_enums::FutureUsage>,
pub off_session: Option<bool>,
Expand Down Expand Up @@ -3847,7 +3879,7 @@ pub struct PgRedirectResponse {
pub payment_id: String,
pub status: api_enums::IntentStatus,
pub gateway_id: String,
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
pub amount: Option<MinorUnit>,
}

Expand Down
18 changes: 9 additions & 9 deletions crates/api_models/src/payouts.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use cards::CardNumber;
use common_utils::{
consts::default_payouts_list_limit,
crypto,
crypto, id_type,
pii::{self, Email},
};
use masking::Secret;
Expand Down Expand Up @@ -86,8 +86,8 @@ pub struct PayoutCreateRequest {
pub billing: Option<payments::Address>,

/// The identifier for the customer object. If not provided the customer ID will be autogenerated.
#[schema(value_type = String, max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<String>,
#[schema(value_type = Option<String>, max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,

/// Set to true to confirm the payout without review, no further action required
#[schema(value_type = bool, example = true, default = false)]
Expand Down Expand Up @@ -314,7 +314,7 @@ pub struct Venmo {
pub telephone_number: Option<Secret<String>>,
}

#[derive(Debug, Default, ToSchema, Clone, Serialize)]
#[derive(Debug, ToSchema, Clone, Serialize)]
#[serde(deny_unknown_fields)]
pub struct PayoutCreateResponse {
/// Unique identifier for the payout. This ensures idempotency for multiple payouts
Expand Down Expand Up @@ -367,7 +367,7 @@ pub struct PayoutCreateResponse {

/// The identifier for the customer object. If not provided the customer ID will be autogenerated.
#[schema(value_type = String, max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: String,
pub customer_id: id_type::CustomerId,

/// Set to true to confirm the payout without review, no further action required
#[schema(value_type = bool, example = true, default = false)]
Expand Down Expand Up @@ -564,8 +564,8 @@ pub struct PayoutIndividualDetails {
#[serde(deny_unknown_fields)]
pub struct PayoutListConstraints {
/// The identifier for customer
#[schema(example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<String>,
#[schema(value_type = Option<String>, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,

/// A cursor for use in pagination, fetch the next list after some object
#[schema(example = "pay_fafa124123")]
Expand Down Expand Up @@ -605,8 +605,8 @@ pub struct PayoutListFilterConstraints {
/// The identifier for business profile
pub profile_id: Option<String>,
/// The identifier for customer
#[schema(example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<String>,
#[schema(value_type = Option<String>,example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,
/// The limit on the number of objects. The default limit is 10 and max limit is 20
#[serde(default = "default_payouts_list_limit")]
pub limit: u32,
Expand Down
2 changes: 1 addition & 1 deletion crates/cards/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fn test_card_expiration() {
// will panic on unwrap
let invalid_card_exp = CardExpiration::try_from((13, curr_year));

assert_eq!(*card_exp.get_month().peek(), 3);
assert_eq!(*card_exp.get_month().peek(), curr_month);
assert_eq!(*card_exp.get_year().peek(), curr_year);
assert!(!card_exp.is_expired().unwrap());

Expand Down
Loading
Loading