use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
use super::common::{MetaData, NtRef};
#[cfg(feature = "builder")]
use crate::error::QBTypeError;
use crate::{QBCreatable, QBFullUpdatable, QBItem};
#[skip_serializing_none]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Default)]
#[serde(rename_all = "PascalCase", default)]
#[cfg_attr(
feature = "builder",
derive(Builder),
builder(default, build_fn(error = "QBTypeError"), setter(into, strip_option))
)]
pub struct Item {
pub id: Option<String>,
pub sync_token: Option<String>,
#[serde(skip_serializing)]
pub meta_data: Option<MetaData>,
pub active: Option<bool>,
pub asset_account_ref: Option<NtRef>,
pub description: Option<String>,
#[serde(rename = "domain")]
pub domain: Option<String>,
pub expense_account_ref: Option<NtRef>,
pub fully_qualified_name: Option<String>,
pub income_account_ref: Option<NtRef>,
pub inv_start_date: Option<NaiveDate>,
pub sales_tax_included: Option<bool>,
pub sales_tax_code_ref: Option<NtRef>,
pub class_ref: Option<NtRef>,
pub source: Option<String>,
pub purchase_tax_included: Option<bool>,
pub reorder_point: Option<f64>,
pub purchase_dec: Option<String>,
pub pref_vendor_ref: Option<NtRef>,
pub purchase_tax_code_ref: Option<NtRef>,
pub purchase_cost: Option<f64>,
pub parent_ref: Option<NtRef>,
pub tax_classification_ref: Option<NtRef>,
pub item_category_type: Option<String>,
#[serde(rename = "Type")]
pub item_type: Option<ItemType>,
pub level: Option<i64>,
pub name: Option<String>,
pub purchase_desc: Option<String>,
pub qty_on_hand: Option<i64>,
pub sku: Option<String>,
#[serde(rename = "sparse")]
pub sparse: Option<bool>,
pub sub_item: Option<bool>,
pub taxable: Option<bool>,
pub track_qty_on_hand: Option<bool>,
pub unit_price: Option<f64>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Default)]
pub enum ItemType {
Inventory,
Service,
#[default]
NonInventory,
}
impl QBCreatable for Item {
fn can_create(&self) -> bool {
self.name.is_some()
&& self.expense_account_ref.is_some()
&& match self.item_type.as_ref() {
Some(typ) => match *typ {
ItemType::Inventory => {
self.income_account_ref.is_some()
&& self.asset_account_ref.is_some()
&& self.inv_start_date.is_some()
&& self.qty_on_hand.is_some()
}
ItemType::Service => self.income_account_ref.is_some(),
ItemType::NonInventory => true,
},
None => self.asset_account_ref.is_some(),
}
}
}
impl QBFullUpdatable for Item {
fn can_full_update(&self) -> bool {
self.has_read() && self.name.is_some()
}
}