use crate::Database;
use stateset_core::{
CreateInvoice, CreateInvoiceItem, Invoice, InvoiceFilter, InvoiceItem,
RecordInvoicePayment, Result, UpdateInvoice,
};
use std::sync::Arc;
use uuid::Uuid;
pub struct Invoices {
db: Arc<dyn Database>,
}
impl Invoices {
pub(crate) fn new(db: Arc<dyn Database>) -> Self {
Self { db }
}
pub fn create(&self, input: CreateInvoice) -> Result<Invoice> {
self.db.invoices().create(input)
}
pub fn get(&self, id: Uuid) -> Result<Option<Invoice>> {
self.db.invoices().get(id)
}
pub fn get_by_number(&self, invoice_number: &str) -> Result<Option<Invoice>> {
self.db.invoices().get_by_number(invoice_number)
}
pub fn update(&self, id: Uuid, input: UpdateInvoice) -> Result<Invoice> {
self.db.invoices().update(id, input)
}
pub fn list(&self, filter: InvoiceFilter) -> Result<Vec<Invoice>> {
self.db.invoices().list(filter)
}
pub fn for_customer(&self, customer_id: Uuid) -> Result<Vec<Invoice>> {
self.db.invoices().for_customer(customer_id)
}
pub fn for_order(&self, order_id: Uuid) -> Result<Vec<Invoice>> {
self.db.invoices().for_order(order_id)
}
pub fn send(&self, id: Uuid) -> Result<Invoice> {
self.db.invoices().send(id)
}
pub fn mark_viewed(&self, id: Uuid) -> Result<Invoice> {
self.db.invoices().mark_viewed(id)
}
pub fn void(&self, id: Uuid) -> Result<Invoice> {
self.db.invoices().void(id)
}
pub fn write_off(&self, id: Uuid) -> Result<Invoice> {
self.db.invoices().write_off(id)
}
pub fn dispute(&self, id: Uuid) -> Result<Invoice> {
self.db.invoices().dispute(id)
}
pub fn add_item(&self, invoice_id: Uuid, item: CreateInvoiceItem) -> Result<InvoiceItem> {
self.db.invoices().add_item(invoice_id, item)
}
pub fn update_item(
&self,
item_id: Uuid,
input: CreateInvoiceItem,
) -> Result<InvoiceItem> {
self.db.invoices().update_item(item_id, input)
}
pub fn remove_item(&self, item_id: Uuid) -> Result<()> {
self.db.invoices().remove_item(item_id)
}
pub fn get_items(&self, invoice_id: Uuid) -> Result<Vec<InvoiceItem>> {
self.db.invoices().get_items(invoice_id)
}
pub fn record_payment(&self, id: Uuid, payment: RecordInvoicePayment) -> Result<Invoice> {
self.db.invoices().record_payment(id, payment)
}
pub fn get_overdue(&self) -> Result<Vec<Invoice>> {
self.db.invoices().get_overdue()
}
pub fn recalculate(&self, id: Uuid) -> Result<Invoice> {
self.db.invoices().recalculate(id)
}
pub fn count(&self, filter: InvoiceFilter) -> Result<u64> {
self.db.invoices().count(filter)
}
pub fn customer_balance(&self, customer_id: Uuid) -> Result<rust_decimal::Decimal> {
let invoices = self.for_customer(customer_id)?;
let balance = invoices
.iter()
.map(|inv| inv.total - inv.amount_paid)
.sum();
Ok(balance)
}
}