use client::Client;
use error::Error;
use params::{Identifiable, List, Metadata, RangeQuery, Timestamp};
use resources::{Currency, Discount, Plan};
use serde_qs as qs;
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct InvoiceParams<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub application_fee: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub customer: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub statement_descriptor: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tax_percent: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub closed: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub forgiven: Option<bool>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct InvoiceLineItemParams<'a> {
#[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 customer: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub discountable: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub invoice: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription: Option<bool>,
}
#[derive(Clone, Debug, Default, Serialize)]
pub struct InvoiceUpcomingParams<'a> {
pub customer: &'a str,
#[serde(skip_serializing_if = "Option::is_none")]
pub coupon: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_items: Option<SubscriptionItemParams<'a>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_prorate: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_proration_date: Option<Timestamp>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_tax_percent: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription_trial_end: Option<Timestamp>,
}
#[derive(Clone, Debug, Serialize)]
pub struct SubscriptionItemParams<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub deleted: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
#[serde(skip_serializing_if = "Option::is_none")]
pub plan: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quantity: Option<u64>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Period {
pub start: Timestamp,
pub end: Timestamp,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InvoiceLineItem {
pub id: String,
pub amount: i64,
pub currency: Currency,
pub description: Option<String>,
pub discountable: bool,
pub livemode: bool,
pub metadata: Metadata,
pub period: Period,
pub plan: Option<Plan>,
pub proration: bool,
pub quantity: Option<u64>,
pub subscription: Option<String>,
pub subscription_item: Option<String>,
#[serde(default)]
#[serde(rename = "type")]
pub item_type: String,
}
impl Identifiable for InvoiceLineItem {
fn id(&self) -> &str {
&self.id
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Invoice {
pub id: Option<String>,
pub amount_due: u64,
pub application_fee: Option<u64>,
pub attempt_count: u64,
pub attempted: bool,
pub charge: Option<String>,
pub closed: bool,
pub currency: Currency,
pub customer: String,
pub date: Timestamp,
pub description: Option<String>,
pub discount: Option<Discount>,
pub ending_balance: Option<i64>,
pub forgiven: bool,
pub lines: List<InvoiceLineItem>,
pub livemode: bool,
pub metadata: Metadata,
pub next_payment_attempt: Option<Timestamp>,
pub paid: bool,
pub period_end: Timestamp,
pub period_start: Timestamp,
pub receipt_number: Option<String>,
pub starting_balance: i64,
pub statment_descriptor: Option<String>,
pub subscription: Option<String>,
pub subscription_proration_date: Option<Timestamp>,
pub subtotal: i64,
pub tax: Option<i64>,
pub tax_percent: Option<f64>,
pub total: i64,
pub webhooks_delivered_at: Option<Timestamp>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct InvoiceListParams<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
pub customer: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub date: Option<RangeQuery<Timestamp>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ending_before: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub starting_after: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription: Option<&'a str>,
}
impl Invoice {
pub fn create(client: &Client, params: InvoiceParams) -> Result<Invoice, Error> {
client.post("/invoices", params)
}
pub fn retrieve(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
client.get(&format!("/invoices/{}", invoice_id))
}
pub fn upcoming(client: &Client, params: InvoiceUpcomingParams) -> Result<Invoice, Error> {
client.get(&format!("/invoices/upcoming?{}", qs::to_string(¶ms)?))
}
pub fn pay(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
client.post_empty(&format!("/invoices/{}/pay", invoice_id))
}
pub fn update(
client: &Client,
invoice_id: &str,
params: InvoiceParams,
) -> Result<Invoice, Error> {
client.post(&format!("/invoices/{}", invoice_id), ¶ms)
}
pub fn list(client: &Client, params: InvoiceListParams) -> Result<List<Invoice>, Error> {
client.get(&format!("/invoices?{}", qs::to_string(¶ms)?))
}
}
impl InvoiceLineItem {
pub fn create(
client: &Client,
params: InvoiceLineItemParams,
) -> Result<InvoiceLineItem, Error> {
client.post(&format!("/invoiceitems"), ¶ms)
}
}
impl List<Invoice> {
pub fn get_all(self, client: &Client) -> Result<Vec<Invoice>, Error> {
let mut data = Vec::new();
let mut next = self;
loop {
if next.has_more {
let resp = next.next(&client)?;
data.extend(next.data);
next = resp;
} else {
data.extend(next.data);
break;
}
}
Ok(data)
}
pub fn next(&self, client: &Client) -> Result<List<Invoice>, Error> {
if let Some(last) = self.data.last() {
if let Some(last_id) = &last.id {
List::get_next(client, &self.url, last_id)
} else {
Err(Error::Unexpected("Cannot fetch List data - Stripe returned Invoice with no ID"))
}
} else {
Ok(List {
data: Vec::new(),
has_more: false,
total_count: self.total_count,
url: self.url.clone()
})
}
}
}