mod entities;
pub use entities::{
Client, Contact, Credit, Expense, Invoice, InvoiceItem, Payment, Product, Project, Quote, Task,
Vendor,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Data<T> {
pub data: T,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Paginated<T> {
#[serde(default = "Vec::new")]
pub data: Vec<T>,
#[serde(default)]
pub meta: Option<Meta>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct Meta {
pub pagination: Option<Pagination>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct Pagination {
pub total: Option<u64>,
pub count: Option<u64>,
pub per_page: Option<u64>,
pub current_page: Option<u64>,
pub total_pages: Option<u64>,
}
pub(crate) mod de {
use serde::{Deserialize, Deserializer};
use serde_json::Value;
pub(crate) fn f64_flexible<'de, D>(deserializer: D) -> Result<f64, D::Error>
where
D: Deserializer<'de>,
{
Ok(match Value::deserialize(deserializer)? {
Value::Number(number) => number.as_f64().unwrap_or_default(),
Value::String(text) => text.trim().parse().unwrap_or_default(),
_ => 0.0,
})
}
pub(crate) fn i64_opt_flexible<'de, D>(deserializer: D) -> Result<Option<i64>, D::Error>
where
D: Deserializer<'de>,
{
Ok(match Value::deserialize(deserializer)? {
Value::Number(number) => number.as_i64(),
Value::String(text) => text.trim().parse().ok(),
_ => None,
})
}
}