use super::PROVIDER_KEY;
use super::StripePaymentProcessor;
use super::find_customer_for_account::find_customer_for_account;
use crate::models::metadata;
use crate::{payments::Error, pbbson::Model};
use std::collections::HashMap;
use std::str::FromStr;
use stripe_core::customer::CreateCustomer;
pub(super) async fn sync<B: Clone + FromStr + Send + Sync + ToString>(
this: &StripePaymentProcessor<B>,
account: &Model,
accounts_bucket: B,
) -> Result<Model, Error> {
match find_customer_for_account(this, account).await {
Ok(_customer) => return Ok(account.clone()),
Err(err) => {
if let Error::NotFound(_) = err {
} else {
return Err(err);
}
}
}
let account_id = account.id().map_err(|e| Error::internal(e.to_string()))?;
let customer = {
let mut metadata = HashMap::new();
metadata.insert("accountId".to_string(), account_id.clone());
let mut req = CreateCustomer::new().metadata(metadata);
if let Ok(email) = account.get_str("email") {
req = req.email(email.to_string())
}
if let Ok(name) = account.get_str("name") {
req = req.name(name.to_string());
}
req.send(&this.client).await.map_err(|e| {
log::error!(err:? = e, req:?; "Failed to create Stripe customer");
Error::from(e)
})?
};
log::info!(account_id, stripe_customer_id = customer.id.as_str(); "Created Stripe customer");
let mut account = account.clone();
let account_has_changed = {
if let Some(stripe_customer_id) = metadata::find_string(&account, "metadata", PROVIDER_KEY, "customerId") {
customer.id.as_str() == stripe_customer_id
} else {
metadata::set(
&mut account,
"metadata",
PROVIDER_KEY,
"customerId",
customer.id.as_str().into(),
);
true
}
};
if account_has_changed {
let new_account = this
.config_store
.update(accounts_bucket, account.clone())
.await
.map_err(|e| Error::internal(e.to_string()))?;
new_account.clone_into(&mut account);
let account_id = account.id().map_err(|e| Error::internal(e.to_string()))?;
log::info!(account_id, stripe_customer_id = customer.id.as_str(); "Updated account metadata to reference Stripe customer");
}
Ok(account)
}