wave-api 0.1.0

Typed Rust client for the Wave Accounting GraphQL API
Documentation
use chrono::NaiveDate;
use rust_decimal::Decimal;
use serde::Serialize;

use crate::enums::{CurrencyCode, InvoiceCreateStatus, InvoiceDiscountType, InvoiceSendMethod};

/// Input for creating an invoice.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoiceCreateInput {
    pub business_id: String,
    pub customer_id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<InvoiceCreateStatus>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub currency: Option<CurrencyCode>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub title: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub subhead: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub invoice_number: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub po_number: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub invoice_date: Option<NaiveDate>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub due_date: Option<NaiveDate>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub exchange_rate: Option<Decimal>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub items: Option<Vec<InvoiceCreateItemInput>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub discounts: Option<Vec<InvoiceDiscountInput>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub memo: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub footer: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub disable_credit_card_payments: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub disable_bank_payments: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub disable_amex_payments: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub item_title: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub unit_title: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub price_title: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub amount_title: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub hide_name: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub hide_description: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub hide_unit: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub hide_price: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub hide_amount: Option<bool>,
}

impl InvoiceCreateInput {
    pub fn new(
        business_id: impl Into<String>,
        customer_id: impl Into<String>,
    ) -> Self {
        Self {
            business_id: business_id.into(),
            customer_id: customer_id.into(),
            status: None,
            currency: None,
            title: None,
            subhead: None,
            invoice_number: None,
            po_number: None,
            invoice_date: None,
            due_date: None,
            exchange_rate: None,
            items: None,
            discounts: None,
            memo: None,
            footer: None,
            disable_credit_card_payments: None,
            disable_bank_payments: None,
            disable_amex_payments: None,
            item_title: None,
            unit_title: None,
            price_title: None,
            amount_title: None,
            hide_name: None,
            hide_description: None,
            hide_unit: None,
            hide_price: None,
            hide_amount: None,
        }
    }

    pub fn status(mut self, v: InvoiceCreateStatus) -> Self {
        self.status = Some(v);
        self
    }
    pub fn items(mut self, v: Vec<InvoiceCreateItemInput>) -> Self {
        self.items = Some(v);
        self
    }
    pub fn invoice_date(mut self, v: NaiveDate) -> Self {
        self.invoice_date = Some(v);
        self
    }
    pub fn due_date(mut self, v: NaiveDate) -> Self {
        self.due_date = Some(v);
        self
    }
    pub fn memo(mut self, v: impl Into<String>) -> Self {
        self.memo = Some(v.into());
        self
    }
    pub fn footer(mut self, v: impl Into<String>) -> Self {
        self.footer = Some(v.into());
        self
    }
    pub fn discounts(mut self, v: Vec<InvoiceDiscountInput>) -> Self {
        self.discounts = Some(v);
        self
    }
}

/// A line item on an invoice create/patch.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoiceCreateItemInput {
    pub product_id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub quantity: Option<Decimal>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub unit_price: Option<Decimal>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub taxes: Option<Vec<InvoiceCreateItemTaxInput>>,
}

impl InvoiceCreateItemInput {
    pub fn new(product_id: impl Into<String>) -> Self {
        Self {
            product_id: product_id.into(),
            description: None,
            quantity: None,
            unit_price: None,
            taxes: None,
        }
    }

    pub fn quantity(mut self, v: Decimal) -> Self {
        self.quantity = Some(v);
        self
    }
    pub fn unit_price(mut self, v: Decimal) -> Self {
        self.unit_price = Some(v);
        self
    }
    pub fn description(mut self, v: impl Into<String>) -> Self {
        self.description = Some(v.into());
        self
    }
}

/// Tax input for an invoice line item.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoiceCreateItemTaxInput {
    pub sales_tax_id: String,
}

impl InvoiceCreateItemTaxInput {
    pub fn new(sales_tax_id: impl Into<String>) -> Self {
        Self {
            sales_tax_id: sales_tax_id.into(),
        }
    }
}

/// Discount input for an invoice.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoiceDiscountInput {
    pub discount_type: InvoiceDiscountType,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub amount: Option<Decimal>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub percentage: Option<Decimal>,
}

impl InvoiceDiscountInput {
    pub fn fixed(amount: Decimal) -> Self {
        Self {
            discount_type: InvoiceDiscountType::Fixed,
            name: None,
            amount: Some(amount),
            percentage: None,
        }
    }

    pub fn percentage(pct: Decimal) -> Self {
        Self {
            discount_type: InvoiceDiscountType::Percentage,
            name: None,
            amount: None,
            percentage: Some(pct),
        }
    }

    pub fn name(mut self, v: impl Into<String>) -> Self {
        self.name = Some(v.into());
        self
    }
}

/// Input for patching an invoice.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoicePatchInput {
    pub id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub customer_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<InvoiceCreateStatus>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub title: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub invoice_date: Option<NaiveDate>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub due_date: Option<NaiveDate>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub items: Option<Vec<InvoiceCreateItemInput>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub memo: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub footer: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub po_number: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub invoice_number: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub discounts: Option<Vec<InvoiceDiscountInput>>,
}

impl InvoicePatchInput {
    pub fn new(id: impl Into<String>) -> Self {
        Self {
            id: id.into(),
            customer_id: None,
            status: None,
            title: None,
            invoice_date: None,
            due_date: None,
            items: None,
            memo: None,
            footer: None,
            po_number: None,
            invoice_number: None,
            discounts: None,
        }
    }

    pub fn memo(mut self, v: impl Into<String>) -> Self {
        self.memo = Some(v.into());
        self
    }
    pub fn items(mut self, v: Vec<InvoiceCreateItemInput>) -> Self {
        self.items = Some(v);
        self
    }
}

/// Input for deleting an invoice.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoiceDeleteInput {
    pub invoice_id: String,
}

/// Input for cloning an invoice.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoiceCloneInput {
    pub invoice_id: String,
}

/// Input for approving an invoice.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoiceApproveInput {
    pub invoice_id: String,
}

/// Input for marking an invoice as sent.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoiceMarkSentInput {
    pub invoice_id: String,
    pub send_method: InvoiceSendMethod,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub sent_at: Option<chrono::DateTime<chrono::Utc>>,
}

/// Input for sending an invoice via email.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoiceSendInput {
    pub invoice_id: String,
    pub to: Vec<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub subject: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub message: Option<String>,
    pub attach_pdf: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub from_address: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cc_myself: Option<bool>,
}

impl InvoiceSendInput {
    pub fn new(invoice_id: impl Into<String>, to: Vec<String>) -> Self {
        Self {
            invoice_id: invoice_id.into(),
            to,
            subject: None,
            message: None,
            attach_pdf: true,
            from_address: None,
            cc_myself: None,
        }
    }

    pub fn subject(mut self, v: impl Into<String>) -> Self {
        self.subject = Some(v.into());
        self
    }
    pub fn message(mut self, v: impl Into<String>) -> Self {
        self.message = Some(v.into());
        self
    }
}