1use chrono::NaiveDate;
2use rust_decimal::Decimal;
3use serde::Serialize;
4
5use crate::enums::{CurrencyCode, InvoiceCreateStatus, InvoiceDiscountType, InvoiceSendMethod};
6
7#[derive(Debug, Clone, Serialize)]
9#[serde(rename_all = "camelCase")]
10pub struct InvoiceCreateInput {
11 pub business_id: String,
12 pub customer_id: String,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 pub status: Option<InvoiceCreateStatus>,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 pub currency: Option<CurrencyCode>,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub title: Option<String>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub subhead: Option<String>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub invoice_number: Option<String>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub po_number: Option<String>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub invoice_date: Option<NaiveDate>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub due_date: Option<NaiveDate>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub exchange_rate: Option<Decimal>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub items: Option<Vec<InvoiceCreateItemInput>>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub discounts: Option<Vec<InvoiceDiscountInput>>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub memo: Option<String>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub footer: Option<String>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub disable_credit_card_payments: Option<bool>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 pub disable_bank_payments: Option<bool>,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 pub disable_amex_payments: Option<bool>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub item_title: Option<String>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub unit_title: Option<String>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub price_title: Option<String>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub amount_title: Option<String>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub hide_name: Option<bool>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub hide_description: Option<bool>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub hide_unit: Option<bool>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub hide_price: Option<bool>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub hide_amount: Option<bool>,
63}
64
65impl InvoiceCreateInput {
66 pub fn new(
67 business_id: impl Into<String>,
68 customer_id: impl Into<String>,
69 ) -> Self {
70 Self {
71 business_id: business_id.into(),
72 customer_id: customer_id.into(),
73 status: None,
74 currency: None,
75 title: None,
76 subhead: None,
77 invoice_number: None,
78 po_number: None,
79 invoice_date: None,
80 due_date: None,
81 exchange_rate: None,
82 items: None,
83 discounts: None,
84 memo: None,
85 footer: None,
86 disable_credit_card_payments: None,
87 disable_bank_payments: None,
88 disable_amex_payments: None,
89 item_title: None,
90 unit_title: None,
91 price_title: None,
92 amount_title: None,
93 hide_name: None,
94 hide_description: None,
95 hide_unit: None,
96 hide_price: None,
97 hide_amount: None,
98 }
99 }
100
101 pub fn status(mut self, v: InvoiceCreateStatus) -> Self {
102 self.status = Some(v);
103 self
104 }
105 pub fn items(mut self, v: Vec<InvoiceCreateItemInput>) -> Self {
106 self.items = Some(v);
107 self
108 }
109 pub fn invoice_date(mut self, v: NaiveDate) -> Self {
110 self.invoice_date = Some(v);
111 self
112 }
113 pub fn due_date(mut self, v: NaiveDate) -> Self {
114 self.due_date = Some(v);
115 self
116 }
117 pub fn memo(mut self, v: impl Into<String>) -> Self {
118 self.memo = Some(v.into());
119 self
120 }
121 pub fn footer(mut self, v: impl Into<String>) -> Self {
122 self.footer = Some(v.into());
123 self
124 }
125 pub fn discounts(mut self, v: Vec<InvoiceDiscountInput>) -> Self {
126 self.discounts = Some(v);
127 self
128 }
129}
130
131#[derive(Debug, Clone, Serialize)]
133#[serde(rename_all = "camelCase")]
134pub struct InvoiceCreateItemInput {
135 pub product_id: String,
136 #[serde(skip_serializing_if = "Option::is_none")]
137 pub description: Option<String>,
138 #[serde(skip_serializing_if = "Option::is_none")]
139 pub quantity: Option<Decimal>,
140 #[serde(skip_serializing_if = "Option::is_none")]
141 pub unit_price: Option<Decimal>,
142 #[serde(skip_serializing_if = "Option::is_none")]
143 pub taxes: Option<Vec<InvoiceCreateItemTaxInput>>,
144}
145
146impl InvoiceCreateItemInput {
147 pub fn new(product_id: impl Into<String>) -> Self {
148 Self {
149 product_id: product_id.into(),
150 description: None,
151 quantity: None,
152 unit_price: None,
153 taxes: None,
154 }
155 }
156
157 pub fn quantity(mut self, v: Decimal) -> Self {
158 self.quantity = Some(v);
159 self
160 }
161 pub fn unit_price(mut self, v: Decimal) -> Self {
162 self.unit_price = Some(v);
163 self
164 }
165 pub fn description(mut self, v: impl Into<String>) -> Self {
166 self.description = Some(v.into());
167 self
168 }
169}
170
171#[derive(Debug, Clone, Serialize)]
173#[serde(rename_all = "camelCase")]
174pub struct InvoiceCreateItemTaxInput {
175 pub sales_tax_id: String,
176}
177
178impl InvoiceCreateItemTaxInput {
179 pub fn new(sales_tax_id: impl Into<String>) -> Self {
180 Self {
181 sales_tax_id: sales_tax_id.into(),
182 }
183 }
184}
185
186#[derive(Debug, Clone, Serialize)]
188#[serde(rename_all = "camelCase")]
189pub struct InvoiceDiscountInput {
190 pub discount_type: InvoiceDiscountType,
191 #[serde(skip_serializing_if = "Option::is_none")]
192 pub name: Option<String>,
193 #[serde(skip_serializing_if = "Option::is_none")]
194 pub amount: Option<Decimal>,
195 #[serde(skip_serializing_if = "Option::is_none")]
196 pub percentage: Option<Decimal>,
197}
198
199impl InvoiceDiscountInput {
200 pub fn fixed(amount: Decimal) -> Self {
201 Self {
202 discount_type: InvoiceDiscountType::Fixed,
203 name: None,
204 amount: Some(amount),
205 percentage: None,
206 }
207 }
208
209 pub fn percentage(pct: Decimal) -> Self {
210 Self {
211 discount_type: InvoiceDiscountType::Percentage,
212 name: None,
213 amount: None,
214 percentage: Some(pct),
215 }
216 }
217
218 pub fn name(mut self, v: impl Into<String>) -> Self {
219 self.name = Some(v.into());
220 self
221 }
222}
223
224#[derive(Debug, Clone, Serialize)]
226#[serde(rename_all = "camelCase")]
227pub struct InvoicePatchInput {
228 pub id: String,
229 #[serde(skip_serializing_if = "Option::is_none")]
230 pub customer_id: Option<String>,
231 #[serde(skip_serializing_if = "Option::is_none")]
232 pub status: Option<InvoiceCreateStatus>,
233 #[serde(skip_serializing_if = "Option::is_none")]
234 pub title: Option<String>,
235 #[serde(skip_serializing_if = "Option::is_none")]
236 pub invoice_date: Option<NaiveDate>,
237 #[serde(skip_serializing_if = "Option::is_none")]
238 pub due_date: Option<NaiveDate>,
239 #[serde(skip_serializing_if = "Option::is_none")]
240 pub items: Option<Vec<InvoiceCreateItemInput>>,
241 #[serde(skip_serializing_if = "Option::is_none")]
242 pub memo: Option<String>,
243 #[serde(skip_serializing_if = "Option::is_none")]
244 pub footer: Option<String>,
245 #[serde(skip_serializing_if = "Option::is_none")]
246 pub po_number: Option<String>,
247 #[serde(skip_serializing_if = "Option::is_none")]
248 pub invoice_number: Option<String>,
249 #[serde(skip_serializing_if = "Option::is_none")]
250 pub discounts: Option<Vec<InvoiceDiscountInput>>,
251}
252
253impl InvoicePatchInput {
254 pub fn new(id: impl Into<String>) -> Self {
255 Self {
256 id: id.into(),
257 customer_id: None,
258 status: None,
259 title: None,
260 invoice_date: None,
261 due_date: None,
262 items: None,
263 memo: None,
264 footer: None,
265 po_number: None,
266 invoice_number: None,
267 discounts: None,
268 }
269 }
270
271 pub fn memo(mut self, v: impl Into<String>) -> Self {
272 self.memo = Some(v.into());
273 self
274 }
275 pub fn items(mut self, v: Vec<InvoiceCreateItemInput>) -> Self {
276 self.items = Some(v);
277 self
278 }
279}
280
281#[derive(Debug, Clone, Serialize)]
283#[serde(rename_all = "camelCase")]
284pub struct InvoiceDeleteInput {
285 pub invoice_id: String,
286}
287
288#[derive(Debug, Clone, Serialize)]
290#[serde(rename_all = "camelCase")]
291pub struct InvoiceCloneInput {
292 pub invoice_id: String,
293}
294
295#[derive(Debug, Clone, Serialize)]
297#[serde(rename_all = "camelCase")]
298pub struct InvoiceApproveInput {
299 pub invoice_id: String,
300}
301
302#[derive(Debug, Clone, Serialize)]
304#[serde(rename_all = "camelCase")]
305pub struct InvoiceMarkSentInput {
306 pub invoice_id: String,
307 pub send_method: InvoiceSendMethod,
308 #[serde(skip_serializing_if = "Option::is_none")]
309 pub sent_at: Option<chrono::DateTime<chrono::Utc>>,
310}
311
312#[derive(Debug, Clone, Serialize)]
314#[serde(rename_all = "camelCase")]
315pub struct InvoiceSendInput {
316 pub invoice_id: String,
317 pub to: Vec<String>,
318 #[serde(skip_serializing_if = "Option::is_none")]
319 pub subject: Option<String>,
320 #[serde(skip_serializing_if = "Option::is_none")]
321 pub message: Option<String>,
322 pub attach_pdf: bool,
323 #[serde(skip_serializing_if = "Option::is_none")]
324 pub from_address: Option<String>,
325 #[serde(skip_serializing_if = "Option::is_none")]
326 pub cc_myself: Option<bool>,
327}
328
329impl InvoiceSendInput {
330 pub fn new(invoice_id: impl Into<String>, to: Vec<String>) -> Self {
331 Self {
332 invoice_id: invoice_id.into(),
333 to,
334 subject: None,
335 message: None,
336 attach_pdf: true,
337 from_address: None,
338 cc_myself: None,
339 }
340 }
341
342 pub fn subject(mut self, v: impl Into<String>) -> Self {
343 self.subject = Some(v.into());
344 self
345 }
346 pub fn message(mut self, v: impl Into<String>) -> Self {
347 self.message = Some(v.into());
348 self
349 }
350}