use std::collections::HashMap;
use reqwest::Method;
use serde::Serialize;
use serde_with::skip_serializing_none;
use crate::entities::Product;
use crate::enums::{CatalogType, Status, TaxCategory};
use crate::ids::ProductID;
use crate::paginated::Paginated;
use crate::{Paddle, Result};
#[skip_serializing_none]
#[derive(Serialize)]
pub struct ProductsList<'a> {
#[serde(skip)]
client: &'a Paddle,
after: Option<ProductID>,
#[serde(serialize_with = "crate::comma_separated")]
id: Option<Vec<ProductID>>,
#[serde(serialize_with = "crate::comma_separated")]
include: Option<Vec<String>>,
order_by: Option<String>,
per_page: Option<usize>,
status: Option<Status>,
#[serde(serialize_with = "crate::comma_separated")]
tax_category: Option<Vec<TaxCategory>>,
r#type: Option<CatalogType>,
}
impl<'a> ProductsList<'a> {
pub fn new(client: &'a Paddle) -> Self {
Self {
client,
after: None,
id: None,
include: None,
order_by: None,
per_page: None,
status: None,
tax_category: None,
r#type: None,
}
}
pub fn after(&mut self, product_id: impl Into<ProductID>) -> &mut Self {
self.after = Some(product_id.into());
self
}
pub fn ids(
&mut self,
product_ids: impl IntoIterator<Item = impl Into<ProductID>>,
) -> &mut Self {
self.id = Some(product_ids.into_iter().map(|i| i.into()).collect());
self
}
pub fn include(&mut self, entities: impl IntoIterator<Item = impl AsRef<str>>) -> &mut Self {
self.include = Some(
entities
.into_iter()
.map(|s| s.as_ref().to_string())
.collect(),
);
self
}
pub fn order_by_asc(&mut self, field: &str) -> &mut Self {
self.order_by = Some(format!("{}[ASC]", field));
self
}
pub fn order_by_desc(&mut self, field: &str) -> &mut Self {
self.order_by = Some(format!("{}[DESC]", field));
self
}
pub fn per_page(&mut self, entities_per_page: usize) -> &mut Self {
self.per_page = Some(entities_per_page);
self
}
pub fn status(&mut self, status: Status) -> &mut Self {
self.status = Some(status);
self
}
pub fn tax_category(
&mut self,
tax_categories: impl IntoIterator<Item = TaxCategory>,
) -> &mut Self {
self.tax_category = Some(tax_categories.into_iter().collect());
self
}
pub fn catalog_type(&mut self, catalog_type: CatalogType) -> &mut Self {
self.r#type = Some(catalog_type);
self
}
pub fn send(&self) -> Paginated<'_, Vec<Product>> {
Paginated::new(self.client, "/products", self)
}
}
#[skip_serializing_none]
#[derive(Serialize)]
pub struct ProductCreate<'a> {
#[serde(skip)]
client: &'a Paddle,
name: String,
tax_category: TaxCategory,
description: Option<String>,
r#type: Option<CatalogType>,
image_url: Option<String>,
custom_data: Option<HashMap<String, String>>,
}
impl<'a> ProductCreate<'a> {
pub fn new(client: &'a Paddle, name: impl Into<String>, tax_category: TaxCategory) -> Self {
Self {
client,
name: name.into(),
tax_category,
description: None,
r#type: None,
image_url: None,
custom_data: None,
}
}
pub fn description(&mut self, description: impl Into<String>) -> &mut Self {
self.description = Some(description.into());
self
}
pub fn catalog_type(&mut self, catalog_type: CatalogType) -> &mut Self {
self.r#type = Some(catalog_type);
self
}
pub fn image_url(&mut self, image_url: impl Into<String>) -> &mut Self {
self.image_url = Some(image_url.into());
self
}
pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
self.custom_data = Some(custom_data);
self
}
pub async fn send(&self) -> Result<Product> {
self.client.send(self, Method::POST, "/products").await
}
}
#[skip_serializing_none]
#[derive(Serialize)]
pub struct ProductGet<'a> {
#[serde(skip)]
client: &'a Paddle,
#[serde(skip)]
product_id: ProductID,
#[serde(serialize_with = "crate::comma_separated")]
include: Option<Vec<String>>,
}
impl<'a> ProductGet<'a> {
pub fn new(client: &'a Paddle, product_id: impl Into<ProductID>) -> Self {
Self {
client,
product_id: product_id.into(),
include: None,
}
}
pub fn include(&mut self, entities: impl IntoIterator<Item = impl AsRef<str>>) -> &mut Self {
self.include = Some(
entities
.into_iter()
.map(|s| s.as_ref().to_string())
.collect(),
);
self
}
pub async fn send(&self) -> Result<Product> {
self.client
.send(
self,
Method::GET,
&format!("/products/{}", self.product_id.as_ref()),
)
.await
}
}
#[skip_serializing_none]
#[derive(Serialize)]
pub struct ProductUpdate<'a> {
#[serde(skip)]
client: &'a Paddle,
#[serde(skip)]
product_id: ProductID,
name: Option<String>,
description: Option<String>,
r#type: Option<CatalogType>,
tax_category: Option<TaxCategory>,
image_url: Option<String>,
custom_data: Option<HashMap<String, String>>,
status: Option<Status>,
}
impl<'a> ProductUpdate<'a> {
pub fn new(client: &'a Paddle, product_id: impl Into<ProductID>) -> Self {
Self {
client,
product_id: product_id.into(),
name: None,
description: None,
r#type: None,
tax_category: None,
image_url: None,
custom_data: None,
status: None,
}
}
pub fn name(&mut self, name: impl Into<String>) -> &mut Self {
self.name = Some(name.into());
self
}
pub fn description(&mut self, description: impl Into<String>) -> &mut Self {
self.description = Some(description.into());
self
}
pub fn catalog_type(&mut self, catalog_type: CatalogType) -> &mut Self {
self.r#type = Some(catalog_type);
self
}
pub fn tax_category(&mut self, tax_category: TaxCategory) -> &mut Self {
self.tax_category = Some(tax_category);
self
}
pub fn image_url(&mut self, image_url: impl Into<String>) -> &mut Self {
self.image_url = Some(image_url.into());
self
}
pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
self.custom_data = Some(custom_data);
self
}
pub fn status(&mut self, status: Status) -> &mut Self {
self.status = Some(status);
self
}
pub async fn send(&self) -> Result<Product> {
self.client
.send(
self,
Method::PATCH,
&format!("/products/{}", self.product_id.as_ref()),
)
.await
}
}