use crate::{
client::SpapiClient,
models::{
self,
product_fees_v0::{
FeesEstimateByIdRequest, FeesEstimateRequest, GetMyFeesEstimateRequest, IdType,
MoneyType, OptionalFulfillmentProgram, PriceToEstimateFees,
},
sellers::{GetAccountResponse, GetMarketplaceParticipationsResponse},
},
};
use anyhow::Result;
impl SpapiClient {
pub async fn get_my_fees_estimate_for_asin(
&self,
asin: &str,
body: models::product_fees_v0::GetMyFeesEstimateRequest,
) -> Result<models::product_fees_v0::GetMyFeesEstimateResponse> {
let configuration = self.create_configuration().await?;
let guard = self
.limiter()
.wait("/products/fees/v0/items/feesEstimate", 1.0, 2)
.await?;
let res = crate::apis::product_fees_v0::get_my_fees_estimate_for_asin(&configuration, asin, body)
.await?;
guard.mark_response().await;
Ok(res)
}
pub async fn get_my_fees_estimate_for_sku(
&self,
seller_sku: &str,
body: models::product_fees_v0::GetMyFeesEstimateRequest,
) -> Result<models::product_fees_v0::GetMyFeesEstimateResponse> {
let configuration = self.create_configuration().await?;
let guard = self
.limiter()
.wait("/products/fees/v0/listings/feesEstimate", 1.0, 2)
.await?;
let res =
crate::apis::product_fees_v0::get_my_fees_estimate_for_sku(&configuration, seller_sku, body)
.await?;
guard.mark_response().await;
Ok(res)
}
pub async fn get_my_fees_estimates(
&self,
body: Vec<models::product_fees_v0::FeesEstimateByIdRequest>,
) -> Result<Vec<models::product_fees_v0::FeesEstimateResult>> {
let configuration = self.create_configuration().await?;
let guard = self
.limiter()
.wait("/products/fees/v0/feesEstimate", 0.5, 1)
.await?;
let res = crate::apis::product_fees_v0::get_my_fees_estimates(&configuration, body).await?;
guard.mark_response().await;
Ok(res)
}
pub async fn get_fee_for_asin(
&self,
asin: &str,
price: f64,
is_amazon_fulfilled: bool,
marketplace_id: &str,
) -> Result<f64> {
let request = GetMyFeesEstimateRequest {
fees_estimate_request: Some(Box::new(FeesEstimateRequest {
marketplace_id: marketplace_id.to_string(),
is_amazon_fulfilled: Some(is_amazon_fulfilled),
price_to_estimate_fees: Box::new(PriceToEstimateFees {
listing_price: Box::new(MoneyType {
currency_code: Some("USD".to_string()),
amount: Some(price),
}),
shipping: None,
points: None,
}),
identifier: asin.to_string(),
optional_fulfillment_program: Some(OptionalFulfillmentProgram::FbaCore),
})),
};
let response = self.get_my_fees_estimate_for_asin(asin, request).await?;
if let Some(payload) = response.payload {
if let Some(result) = payload.fees_estimate_result {
if result.status == Some("Success".to_string()) {
if let Some(estimate) = result.fees_estimate {
if let Some(total_fees) = estimate.total_fees_estimate {
return Ok(total_fees.amount.unwrap_or(0.0));
}
}
}
}
}
Err(anyhow::anyhow!(
"Failed to get fee estimate for ASIN: {}",
asin
))
}
pub async fn get_fees_for_asins(
&self,
asins_with_prices: Vec<(String, f64)>,
is_amazon_fulfilled: bool,
marketplace_id: &str,
) -> Result<Vec<(String, f64)>> {
let requests: Vec<FeesEstimateByIdRequest> = asins_with_prices
.iter()
.map(|(asin, price)| FeesEstimateByIdRequest {
fees_estimate_request: Some(Box::new(FeesEstimateRequest {
marketplace_id: marketplace_id.to_string(),
is_amazon_fulfilled: Some(is_amazon_fulfilled),
price_to_estimate_fees: Box::new(PriceToEstimateFees {
listing_price: Box::new(MoneyType {
currency_code: Some("USD".to_string()),
amount: Some(*price),
}),
shipping: None,
points: None,
}),
identifier: asin.clone(),
optional_fulfillment_program: None,
})),
id_type: IdType::Asin,
id_value: asin.clone(),
})
.collect();
let results = self.get_my_fees_estimates(requests).await?;
let mut fees: Vec<(String, f64)> = Vec::new();
for result in results {
if let Some(identifier) = result.fees_estimate_identifier {
let asin = identifier.id_value.unwrap_or_default();
let fee = if result.status == Some("Success".to_string()) {
if let Some(estimate) = result.fees_estimate {
if let Some(total_fees) = estimate.total_fees_estimate {
total_fees.amount.unwrap_or(0.0)
} else {
0.0
}
} else {
0.0
}
} else {
0.0
};
fees.push((asin, fee));
}
}
Ok(fees)
}
pub async fn get_fee_for_sku(
&self,
sku: &str,
price: f64,
is_amazon_fulfilled: bool,
marketplace_id: &str,
) -> Result<f64> {
let request = GetMyFeesEstimateRequest {
fees_estimate_request: Some(Box::new(FeesEstimateRequest {
marketplace_id: marketplace_id.to_string(),
is_amazon_fulfilled: Some(is_amazon_fulfilled),
price_to_estimate_fees: Box::new(PriceToEstimateFees {
listing_price: Box::new(MoneyType {
currency_code: Some("USD".to_string()),
amount: Some(price),
}),
shipping: None,
points: None,
}),
identifier: sku.to_string(),
optional_fulfillment_program: Some(OptionalFulfillmentProgram::FbaCore),
})),
};
let response = self.get_my_fees_estimate_for_sku(sku, request).await?;
if let Some(payload) = response.payload {
if let Some(result) = payload.fees_estimate_result {
if result.status == Some("Success".to_string()) {
if let Some(estimate) = result.fees_estimate {
if let Some(total_fees) = estimate.total_fees_estimate {
return Ok(total_fees.amount.unwrap_or(0.0));
}
}
}
}
}
Err(anyhow::anyhow!(
"Failed to get fee estimate for SKU: {}",
sku
))
}
pub async fn get_fees_for_skus(
&self,
skus_with_prices: Vec<(String, f64)>,
is_amazon_fulfilled: bool,
marketplace_id: &str,
) -> Result<Vec<(String, f64)>> {
let requests: Vec<FeesEstimateByIdRequest> = skus_with_prices
.iter()
.map(|(sku, price)| FeesEstimateByIdRequest {
fees_estimate_request: Some(Box::new(FeesEstimateRequest {
marketplace_id: marketplace_id.to_string(),
is_amazon_fulfilled: Some(is_amazon_fulfilled),
price_to_estimate_fees: Box::new(PriceToEstimateFees {
listing_price: Box::new(MoneyType {
currency_code: Some("USD".to_string()),
amount: Some(*price),
}),
shipping: None,
points: None,
}),
identifier: sku.clone(),
optional_fulfillment_program: None,
})),
id_type: IdType::SellerSku,
id_value: sku.clone(),
})
.collect();
let results = self.get_my_fees_estimates(requests).await?;
let mut fees: Vec<(String, f64)> = Vec::new();
for result in results {
if let Some(identifier) = result.fees_estimate_identifier {
let sku = identifier.id_value.unwrap_or_default();
let fee = if result.status == Some("Success".to_string()) {
if let Some(estimate) = result.fees_estimate {
if let Some(total_fees) = estimate.total_fees_estimate {
total_fees.amount.unwrap_or(0.0)
} else {
0.0
}
} else {
0.0
}
} else {
0.0
};
fees.push((sku, fee));
}
}
Ok(fees)
}
}