use crate::config::{Client, Response};
use crate::ids::{CouponId, CustomerId, OrderId};
use crate::params::{Expand, Expandable, List, Metadata, Object, RangeQuery, Timestamp};
use crate::resources::{
Charge, Currency, Customer, OrderItem, OrderReturn, Shipping, ShippingParams,
};
use serde_derive::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Order {
pub id: OrderId,
pub amount: i64,
#[serde(skip_serializing_if = "Option::is_none")]
pub amount_returned: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub application: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub application_fee: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub charge: Option<Expandable<Charge>>,
pub created: Timestamp,
pub currency: Currency,
#[serde(skip_serializing_if = "Option::is_none")]
pub customer: Option<Expandable<Customer>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub external_coupon_code: Option<String>,
pub items: Vec<OrderItem>,
pub livemode: bool,
pub metadata: Metadata,
#[serde(default)]
pub returns: List<OrderReturn>,
#[serde(skip_serializing_if = "Option::is_none")]
pub selected_shipping_method: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shipping: Option<Shipping>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shipping_methods: Option<Vec<ShippingMethod>>,
pub status: OrderStatus,
#[serde(skip_serializing_if = "Option::is_none")]
pub status_transitions: Option<StatusTransitions>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated: Option<Timestamp>,
#[serde(skip_serializing_if = "Option::is_none")]
pub upstream_id: Option<String>,
}
impl Order {
pub fn list(client: &Client, params: ListOrders<'_>) -> Response<List<Order>> {
client.get_query("/orders", ¶ms)
}
pub fn create(client: &Client, params: CreateOrder<'_>) -> Response<Order> {
client.post_form("/orders", ¶ms)
}
pub fn retrieve(client: &Client, id: &OrderId, expand: &[&str]) -> Response<Order> {
client.get_query(&format!("/orders/{}", id), &Expand { expand })
}
pub fn update(client: &Client, id: &OrderId, params: UpdateOrder<'_>) -> Response<Order> {
client.post_form(&format!("/orders/{}", id), ¶ms)
}
}
impl Object for Order {
type Id = OrderId;
fn id(&self) -> Self::Id {
self.id.clone()
}
fn object(&self) -> &'static str {
"order"
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ShippingMethod {
pub amount: i64,
pub currency: Currency,
#[serde(skip_serializing_if = "Option::is_none")]
pub delivery_estimate: Option<DeliveryEstimate>,
pub description: String,
pub id: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DeliveryEstimate {
#[serde(skip_serializing_if = "Option::is_none")]
pub date: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub earliest: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub latest: Option<String>,
#[serde(rename = "type")]
pub type_: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StatusTransitions {
#[serde(skip_serializing_if = "Option::is_none")]
pub canceled: Option<Timestamp>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fulfiled: Option<Timestamp>,
#[serde(skip_serializing_if = "Option::is_none")]
pub paid: Option<Timestamp>,
#[serde(skip_serializing_if = "Option::is_none")]
pub returned: Option<Timestamp>,
}
#[derive(Clone, Debug, Serialize)]
pub struct CreateOrder<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub coupon: Option<CouponId>,
pub currency: Currency,
#[serde(skip_serializing_if = "Option::is_none")]
pub customer: Option<CustomerId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<&'a str>,
#[serde(skip_serializing_if = "Expand::is_empty")]
pub expand: &'a [&'a str],
#[serde(skip_serializing_if = "Option::is_none")]
pub items: Option<Vec<OrderItemParams>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shipping: Option<ShippingParams>,
}
impl<'a> CreateOrder<'a> {
pub fn new(currency: Currency) -> Self {
CreateOrder {
coupon: Default::default(),
currency,
customer: Default::default(),
email: Default::default(),
expand: Default::default(),
items: Default::default(),
metadata: Default::default(),
shipping: Default::default(),
}
}
}
#[derive(Clone, Debug, Serialize, Default)]
pub struct ListOrders<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub created: Option<RangeQuery<Timestamp>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub customer: Option<CustomerId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ending_before: Option<OrderId>,
#[serde(skip_serializing_if = "Expand::is_empty")]
pub expand: &'a [&'a str],
#[serde(skip_serializing_if = "Option::is_none")]
pub ids: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub starting_after: Option<OrderId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<OrderStatusFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status_transitions: Option<ListOrdersStatusTransitions>,
#[serde(skip_serializing_if = "Option::is_none")]
pub upstream_ids: Option<Vec<String>>,
}
impl<'a> ListOrders<'a> {
pub fn new() -> Self {
ListOrders {
created: Default::default(),
customer: Default::default(),
ending_before: Default::default(),
expand: Default::default(),
ids: Default::default(),
limit: Default::default(),
starting_after: Default::default(),
status: Default::default(),
status_transitions: Default::default(),
upstream_ids: Default::default(),
}
}
}
#[derive(Clone, Debug, Serialize, Default)]
pub struct UpdateOrder<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub coupon: Option<CouponId>,
#[serde(skip_serializing_if = "Expand::is_empty")]
pub expand: &'a [&'a str],
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
#[serde(skip_serializing_if = "Option::is_none")]
pub selected_shipping_method: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shipping: Option<ShippingParams>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<OrderStatus>,
}
impl<'a> UpdateOrder<'a> {
pub fn new() -> Self {
UpdateOrder {
coupon: Default::default(),
expand: Default::default(),
metadata: Default::default(),
selected_shipping_method: Default::default(),
shipping: Default::default(),
status: Default::default(),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ListOrdersStatusTransitions {
#[serde(skip_serializing_if = "Option::is_none")]
pub canceled: Option<RangeQuery<Timestamp>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fulfilled: Option<RangeQuery<Timestamp>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub paid: Option<RangeQuery<Timestamp>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub returned: Option<RangeQuery<Timestamp>>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OrderItemParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub amount: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub currency: Option<Currency>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quantity: Option<u64>,
#[serde(rename = "type")]
#[serde(skip_serializing_if = "Option::is_none")]
pub type_: Option<OrderItemParamsType>,
}
#[derive(Copy, Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum OrderItemParamsType {
Discount,
Shipping,
Sku,
Tax,
}
impl OrderItemParamsType {
pub fn as_str(self) -> &'static str {
match self {
OrderItemParamsType::Discount => "discount",
OrderItemParamsType::Shipping => "shipping",
OrderItemParamsType::Sku => "sku",
OrderItemParamsType::Tax => "tax",
}
}
}
impl AsRef<str> for OrderItemParamsType {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl std::fmt::Display for OrderItemParamsType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
self.as_str().fmt(f)
}
}
#[derive(Copy, Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum OrderStatus {
Canceled,
Created,
Fulfilled,
Paid,
Returned,
}
impl OrderStatus {
pub fn as_str(self) -> &'static str {
match self {
OrderStatus::Canceled => "canceled",
OrderStatus::Created => "created",
OrderStatus::Fulfilled => "fulfilled",
OrderStatus::Paid => "paid",
OrderStatus::Returned => "returned",
}
}
}
impl AsRef<str> for OrderStatus {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl std::fmt::Display for OrderStatus {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
self.as_str().fmt(f)
}
}
#[derive(Copy, Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum OrderStatusFilter {
Created,
Fulfilled,
Paid,
Refunded,
}
impl OrderStatusFilter {
pub fn as_str(self) -> &'static str {
match self {
OrderStatusFilter::Created => "created",
OrderStatusFilter::Fulfilled => "fulfilled",
OrderStatusFilter::Paid => "paid",
OrderStatusFilter::Refunded => "refunded",
}
}
}
impl AsRef<str> for OrderStatusFilter {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl std::fmt::Display for OrderStatusFilter {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
self.as_str().fmt(f)
}
}