quickbooks_types/models/
estimate.rs

1use chrono::NaiveDate;
2use serde::{Deserialize, Serialize};
3use serde_with::skip_serializing_none;
4
5use super::common::{Addr, CustomField, Email, LinkedTxn, MetaData, NtRef, TxnTaxDetail};
6#[cfg(feature = "builder")]
7use crate::error::QBTypeError;
8use crate::{
9    common::EmailStatus, LineField, QBCreatable, QBDeletable, QBFullUpdatable, QBItem, QBPDFable,
10    QBSendable, QBSparseUpdateable,
11};
12
13#[skip_serializing_none]
14#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Default)]
15#[serde(rename_all = "PascalCase", default)]
16#[cfg_attr(
17    feature = "builder",
18    derive(Builder),
19    builder(default, build_fn(error = "QBTypeError"), setter(into, strip_option))
20)]
21
22/// Estimate
23///
24/// Represents a proposal for a financial transaction between a business and its customer.
25/// It outlines proposed goods or services and their costs, which may later become an invoice.
26///
27/// API reference:
28/// <https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/estimate>
29pub struct Estimate {
30    /// The unique ID of the entity
31    pub id: Option<String>,
32    /// The unique sync token of the entity, used for concurrency control
33    pub sync_token: Option<String>,
34    /// Metadata about the entity
35    #[serde(skip_serializing)]
36    pub meta_data: Option<MetaData>,
37    /// Reference to the customer for the estimate
38    pub customer_ref: Option<NtRef>,
39    /// Reference to the currency for the estimate
40    pub currency_ref: Option<NtRef>,
41    /// Email address where the estimate should be sent
42    pub bill_email: Option<Email>,
43    /// Date of the estimate in YYYY-MM-DD format
44    pub txn_date: Option<NaiveDate>,
45    /// Address information for where items are shipped from
46    pub ship_from_addr: Option<Addr>,
47    /// Date the items are expected to ship
48    pub ship_date: Option<NaiveDate>,
49    /// Reference to the class for the estimate
50    pub class_ref: Option<NtRef>,
51    /// Custom fields for the estimate
52    pub custom_field: Option<Vec<CustomField>>,
53    /// Status indicating whether the estimate has been printed
54    pub print_status: Option<String>,
55    /// Indicates if the entity is a sparse object
56    #[serde(rename = "sparse")]
57    pub sparse: Option<bool>,
58    /// Reference to the sales terms for the estimate
59    pub sales_term_ref: Option<NtRef>,
60    /// Status of the transaction (e.g., "Pending", "Accepted")
61    pub txn_status: Option<String>,
62    /// Global tax calculation method
63    pub global_tax_calculation: Option<String>,
64    /// Date when the estimate was accepted by the customer
65    pub accepted_date: Option<NaiveDate>,
66    /// Date when the estimate expires
67    pub expiration_date: Option<NaiveDate>,
68    /// Due date for the estimate
69    pub due_date: Option<NaiveDate>,
70    /// Document number for the estimate
71    pub doc_number: Option<String>,
72    /// Private note for the estimate (not visible to customers)
73    pub private_note: Option<String>,
74    /// Customer memo for the estimate
75    pub customer_memo: Option<NtRef>,
76    /// Status indicating whether the estimate has been emailed
77    pub email_status: Option<EmailStatus>,
78    /// Tax details for the transaction
79    pub txn_tax_detail: Option<TxnTaxDetail>,
80    /// Line items for the estimate
81    pub line: Option<LineField>,
82    /// Information about transactions linked to this estimate
83    pub linked_txn: Option<Vec<LinkedTxn>>,
84    /// Name of the person who accepted the estimate
85    pub accepted_by: Option<String>,
86    /// Exchange rate for the currency
87    pub exchange_rate: Option<f64>,
88    /// Shipping address for the estimate
89    pub ship_addr: Option<Addr>,
90    /// Reference to the department for the estimate
91    pub department_ref: Option<NtRef>,
92    /// Reference to the shipping method for the estimate
93    pub ship_method_ref: Option<NtRef>,
94    /// Billing address for the estimate
95    pub bill_addr: Option<Addr>,
96    /// Indicates if tax should be applied after discount
97    pub apply_tax_after_discount: Option<bool>,
98    /// Total amount of the estimate
99    pub total_amt: Option<f64>,
100    /// Reference to recurring data for the estimate
101    pub recur_data_ref: Option<NtRef>,
102    /// Reference to tax exemption information
103    pub tax_exemption_ref: Option<NtRef>,
104    /// Total amount in home currency
105    pub home_total_amt: Option<f64>,
106    /// Indicates if the address is free-form (not structured)
107    pub free_form_address: Option<bool>,
108}
109
110impl QBCreatable for Estimate {
111    fn can_create(&self) -> bool {
112        self.line.is_some() && self.customer_ref.is_some()
113    }
114}
115
116impl QBDeletable for Estimate {}
117
118impl QBFullUpdatable for Estimate {
119    fn can_full_update(&self) -> bool {
120        if !self.has_read() || self.customer_ref.is_none() {
121            false
122        } else if let Some(EmailStatus::NeedToSend) = self.email_status.as_ref() {
123            self.bill_email.is_some()
124        } else {
125            true
126        }
127    }
128}
129
130impl QBSparseUpdateable for Estimate {
131    fn can_sparse_update(&self) -> bool {
132        self.can_full_update() && self.sparse.is_some_and(|x| x)
133    }
134}
135
136impl QBSendable for Estimate {}
137impl QBPDFable for Estimate {}