1use std::borrow::Cow;
2
3use super::params::{
4 AccountId, AccountingMethod, AgingMethod, ArPaid, AttachmentType, Cleared, CustomerId,
5 DateMacro, HasValue, ItemId, Printed, SortOrder, SummarizeColumnBy, TermId, VendorId,
6};
7use chrono::NaiveDate;
8
9pub trait QBReportParams {
11 fn params(&self) -> impl Iterator<Item = (&'static str, Cow<'_, str>)>;
12 fn to_query_string(&self) -> String {
13 self.params()
14 .map(|(name, value)| format!("{name}={value}"))
15 .collect::<Vec<_>>()
16 .join("&")
17 }
18}
19
20pub trait QBReportType {
22 type QueryParams: QBReportParams;
23 fn url_name(&self) -> &'static str;
24}
25
26use paste::paste;
27
28macro_rules! impl_report_type {
29 ($(
30 $report_ty:ident, $url_name:expr, [$($param:tt),* $(,)?]; $(($doc:expr))?
31 )*
32 $(;)?) => {
33 $(
34
35 paste! {
36 #[doc = "Type to represent the `" $report_ty "` report in quickbooks:\n\nAPI Reference:\n<https://developer.intuit.com/app/developer/qbo/docs/api/accounting/report-entities/" [<$report_ty:lower>] ">\n\n" $($doc)?]
37 pub struct $report_ty;
38
39 impl QBReportType for $report_ty {
40 type QueryParams = [<$report_ty Params>];
41 fn url_name(&self) -> &'static str {
42 $url_name
43 }
44 }
45
46 #[derive(Debug, Default)]
47 #[allow(non_snake_case)]
48 #[doc = "Parameters for the `" $report_ty "` report.\n\n" $($doc)?]
49 pub struct [<$report_ty Params>] {
50 $(
51 pub $param: Option<impl_report_type!(@param_type $param)>,
52 )*
53 }
54
55 impl [<$report_ty Params>] {
56 #[must_use]
57 pub fn new() -> Self {
58 Self {
59 $(
60 $param: None,
61 )*
62 }
63 }
64
65 $(
66 impl_report_type!(@param_method $param);
67 )*
68
69 fn iter_params(&self) -> impl Iterator<Item = (&'static str, Option<Cow<'_, str>>)> {
70 [
71 $(
72 (stringify!($param), self.$param.as_ref().map(|p| p.value())),
73 )*
74 ]
75 .into_iter()
76 }
77 }
78
79 impl QBReportParams for [<$report_ty Params>] {
80 fn params(&self) -> impl Iterator<Item = (&'static str, Cow<'_, str>)> {
81 self.iter_params().filter_map(|(name, value)| {
82 value.map(|v| (name, v))
83 })
84 }
85 }
86 }
87 )+
88 };
89
90 (@param_method_vec $param:tt, $id_type:ty) => {
92 #[must_use]
93 pub fn $param(mut self, param: impl Into<$id_type>) -> Self {
94 if let Some(ref mut vec) = self.$param {
95 vec.push(param.into());
96 } else {
97 self.$param = Some(vec![param.into()]);
98 }
99 self
100 }
101
102 paste! {
103 #[must_use]
104 pub fn [<$param s>](mut self, params: Vec<$id_type>) -> Self {
105 self.$param = Some(params);
106 self
107 }
108 }
109 };
110
111 (@param_method vendor) => { impl_report_type!(@param_method_vec vendor, VendorId); };
113 (@param_method customer) => { impl_report_type!(@param_method_vec customer, CustomerId); };
114 (@param_method term) => { impl_report_type!(@param_method_vec term, TermId); };
115 (@param_method item) => { impl_report_type!(@param_method_vec item, ItemId); };
116 (@param_method account) => { impl_report_type!(@param_method_vec account, AccountId); };
117 (@param_method source_account) => { impl_report_type!(@param_method_vec source_account, AccountId); };
118 (@param_method columns) => {
120 #[must_use]
121 pub fn columns(mut self, params: Vec<String>) -> Self {
122 self.columns = Some(params);
123 self
124 }
125
126 #[must_use]
127 pub fn column(mut self, param: impl Into<String>) -> Self {
128 if let Some(ref mut vec) = self.columns {
129 vec.push(param.into());
130 } else {
131 self.columns = Some(vec![param.into()]);
132 }
133 self
134 }
135 };
136
137 (@param_method $param:tt) => {
139 #[must_use]
140 pub fn $param(mut self, param: impl Into<impl_report_type!(@param_type $param)>) -> Self {
141 self.$param = Some(param.into());
142 self
143 }
144 };
145
146 (@param_type vendor) => { Vec<VendorId> };
148 (@param_type customer) => { Vec<CustomerId> };
149 (@param_type term) => { Vec<TermId> };
150 (@param_type item) => { Vec<ItemId> };
151 (@param_type account) => { Vec<AccountId> };
152 (@param_type columns) => { Vec<String> };
153 (@param_type source_account) => { Vec<AccountId> };
154 (@param_type accounting_method) => { AccountingMethod };
155 (@param_type date_macro) => { DateMacro };
156 (@param_type start_date) => { NaiveDate };
157 (@param_type end_date) => { NaiveDate };
158 (@param_type summarize_column_by) => { SummarizeColumnBy };
159 (@param_type as_of_date) => { NaiveDate };
160 (@param_type aging_method) => { AgingMethod };
161 (@param_type arpaid) => { ArPaid };
162 (@param_type qzurl) => { String };
163 (@param_type department) => { String };
164 (@param_type report_date) => { NaiveDate };
165 (@param_type sort_order) => { SortOrder };
166 (@param_type shipvia) => { String };
167 (@param_type end_duedate) => { NaiveDate };
168 (@param_type start_duedate) => { NaiveDate };
169 (@param_type custom1) => { String };
170 (@param_type custom2) => { String };
171 (@param_type custom3) => { String };
172 (@param_type num_periods) => { u32 };
173 (@param_type past_due) => { String };
174 (@param_type aging_period) => { String };
175 (@param_type adjusted_gain_loss) => { String };
176 (@param_type class) => { String };
177 (@param_type sort_by) => { String };
178 (@param_type attachment_type) => { AttachmentType };
179 (@param_type with_qbo_identifier) => { bool };
180 (@param_type add_due_date) => { String };
181 (@param_type account_type) => { String };
182 (@param_type end_svcdate) => { NaiveDate };
183 (@param_type svcdate_macro) => { DateMacro };
184 (@param_type start_svcdate) => { NaiveDate };
185 (@param_type group_by) => { String };
186 (@param_type payment_method) => { String };
187 (@param_type employee) => { String };
188 (@param_type agency_id) => { String };
189 (@param_type duedate_macro) => { DateMacro };
190 (@param_type bothamount) => { String };
191 (@param_type transaction_type) => { String };
192 (@param_type docnum) => { String };
193 (@param_type start_moddate) => { NaiveDate };
194 (@param_type source_account_type) => { String };
195 (@param_type start_createdate) => { NaiveDate };
196 (@param_type memo) => { String };
197 (@param_type appaid) => { String };
198 (@param_type moddate_macro) => { String };
199 (@param_type printed) => { Printed };
200 (@param_type createdate_macro) => { String };
201 (@param_type cleared) => { Cleared };
202 (@param_type end_createdate) => { NaiveDate };
203 (@param_type name) => { String };
204 (@param_type end_moddate) => { NaiveDate };
205
206 (@param_type $param:tt) => { compile_error!(
207 "Unsupported parameter type for report"
208 ) };
209
210 () => {}
211}
212
213impl_report_type!(
214 AccountListDetail, "AccountList", [
215 accounting_method,
216 date_macro,
217 start_date,
218 end_date,
219 summarize_column_by,
220 ]; ("List of accounts with details")
221
222 APAgingDetail, "AgedPayableDetail", [
223 as_of_date,
224 aging_method,
225 vendor,
226 columns
227 ];
228
229 APAgingSummary, "AgedPayables", [
230 customer,
231 qzurl,
232 vendor,
233 date_macro,
234 department,
235 report_date,
236 sort_order,
237 aging_method
238 ];
239
240 ARAgingDetail, "AgedReceivableDetail", [
241 customer,
242 shipvia,
243 term,
244 end_duedate,
245 start_duedate,
246 custom1,
247 custom2,
248 custom3,
249 report_date,
250 num_periods,
251 aging_method,
252 past_due,
253 aging_period,
254 columns
255 ];
256
257 ARAgingSummary, "AgedReceivables", [
258 customer,
259 qzurl,
260 date_macro,
261 aging_method,
262 report_date,
263 sort_order,
264 department
265 ];
266
267 BalanceSheet, "BalanceSheet", [
268 customer,
269 qzurl,
270 end_date,
271 accounting_method,
272 date_macro,
273 adjusted_gain_loss,
274 class,
275 item,
276 sort_order,
277 summarize_column_by,
278 department,
279 vendor,
280 start_date
281 ];
282
283 CashFlow, "CashFlow", [
284 customer,
285 vendor,
286 end_date,
287 date_macro,
288 class,
289 item,
290 sort_order,
291 summarize_column_by,
292 department,
293 start_date
294 ];
295
296 CustomerBalance, "CustomerBalance", [
297 customer,
298 accounting_method,
299 date_macro,
300 arpaid,
301 report_date,
302 sort_order,
303 summarize_column_by,
304 department
305 ];
306
307 CustomerBalanceDetail, "CustomerBalanceDetail", [
308 customer,
309 shipvia,
310 term,
311 end_duedate,
312 start_duedate,
313 custom1,
314 custom2,
315 custom3,
316 arpaid,
317 report_date,
318 sort_order,
319 aging_method,
320 department
321 ];
322
323 CustomerIncome, "CustomerIncome", [
324 customer,
325 term,
326 accounting_method,
327 end_date,
328 date_macro,
329 class,
330 sort_order,
331 summarize_column_by,
332 department,
333 start_date,
334 vendor
335 ];
336
337 FECReport, "FECReport", [
338 attachment_type,
339 with_qbo_identifier,
340 start_date,
341 end_date,
342 add_due_date
343 ];
344
345 GeneralLedger, "GeneralLedger", [
346 customer,
347 account,
348 accounting_method,
349 source_account,
350 end_date,
351 date_macro,
352 account_type,
353 sort_by,
354 sort_order,
355 start_date,
356 summarize_column_by,
357 class,
358 item,
359 department,
360 vendor,
361 columns
362 ];
363
364 GeneralLedgerFR, "GeneralLedgerFR", [
365 customer,
366 account,
367 accounting_method,
368 source_account,
369 end_date,
370 date_macro,
371 account_type,
372 sort_by,
373 sort_order,
374 start_date,
375 summarize_column_by,
376 class,
377 vendor
378 ];
379
380 InventoryValuationDetail, "InventoryValuationDetail", [
381 end_date,
382 end_svcdate,
383 date_macro,
384 svcdate_macro,
385 start_svcdate,
386 group_by,
387 start_date,
388 columns
389 ];
390
391 InventoryValuationSummary, "InventoryValuationSummary", [
392 qzurl,
393 date_macro,
394 item,
395 report_date,
396 sort_order,
397 summarize_column_by
398 ];
399
400 JournalReport, "JournalReport", [
401 end_date,
402 date_macro,
403 sort_by,
404 sort_order,
405 start_date,
406 columns
407 ];
408
409 ProfitAndLoss, "ProfitAndLoss", [
410 customer,
411 qzurl,
412 accounting_method,
413 end_date,
414 date_macro,
415 adjusted_gain_loss,
416 class,
417 item,
418 sort_order,
419 summarize_column_by,
420 department,
421 vendor,
422 start_date
423 ];
424
425 ProfitAndLossDetail, "ProfitAndLossDetail", [
426 customer,
427 account,
428 accounting_method,
429 end_date,
430 date_macro,
431 adjusted_gain_loss,
432 class,
433 sort_by,
434 payment_method,
435 sort_order,
436 employee,
437 department,
438 vendor,
439 account_type,
440 start_date,
441 columns
442 ];
443
444 SalesByClassSummary, "ClassSales", [
445 customer,
446 accounting_method,
447 end_date,
448 date_macro,
449 class,
450 item,
451 summarize_column_by,
452 department,
453 start_date
454 ];
455
456 SalesByCustomer, "CustomerSales", [
457 customer,
458 qzurl,
459 accounting_method,
460 end_date,
461 date_macro,
462 class,
463 item,
464 sort_order,
465 summarize_column_by,
466 department,
467 start_date
468 ];
469
470 SalesByDepartment, "DepartmentSales", [
471 customer,
472 accounting_method,
473 end_date,
474 date_macro,
475 class,
476 item,
477 sort_order,
478 summarize_column_by,
479 department,
480 start_date
481 ];
482
483 SalesByProduct, "ItemSales", [
484 customer,
485 end_duedate,
486 accounting_method,
487 end_date,
488 date_macro,
489 start_duedate,
490 class,
491 item,
492 sort_order,
493 summarize_column_by,
494 department,
495 start_date
496 ];
497
498 TaxSummary, "TaxSummary", [
499 agency_id,
500 accounting_method,
501 end_date,
502 date_macro,
503 sort_order,
504 start_date
505 ];
506
507 TransactionList, "TransactionList", [
508 date_macro,
509 payment_method,
510 duedate_macro,
511 arpaid,
512 bothamount,
513 transaction_type,
514 docnum,
515 start_moddate,
516 source_account_type,
517 group_by,
518 start_date,
519 department,
520 start_duedate,
521 columns,
522 end_duedate,
523 vendor,
524 end_date,
525 memo,
526 appaid,
527 moddate_macro,
528 printed,
529 createdate_macro,
530 cleared,
531 customer,
532 qzurl,
533 term,
534 end_createdate,
535 name,
536 sort_by,
537 sort_order,
538 start_createdate,
539 end_moddate
540 ];
541
542 TransactionListByCustomer, "TransactionListByCustomer", [
543 date_macro,
544 payment_method,
545 duedate_macro,
546 arpaid,
547 bothamount,
548 transaction_type,
549 docnum,
550 start_moddate,
551 source_account_type,
552 group_by,
553 start_date,
554 department,
555 start_duedate,
556 columns,
557 end_duedate,
558 end_date,
559 memo,
560 appaid,
561 moddate_macro,
562 printed,
563 createdate_macro,
564 cleared,
565 customer,
566 qzurl,
567 term,
568 end_createdate,
569 name,
570 sort_by,
571 sort_order,
572 start_createdate,
573 end_moddate
574 ];
575
576 TransactionListByVendor, "TransactionListByVendor", [
577 date_macro,
578 payment_method,
579 duedate_macro,
580 arpaid,
581 bothamount,
582 transaction_type,
583 docnum,
584 start_moddate,
585 source_account_type,
586 group_by,
587 start_date,
588 department,
589 start_duedate,
590 columns,
591 end_duedate,
592 vendor,
593 end_date,
594 memo,
595 appaid,
596 moddate_macro,
597 printed,
598 createdate_macro,
599 cleared,
600 qzurl,
601 term,
602 end_createdate,
603 name,
604 sort_by,
605 sort_order,
606 start_createdate,
607 end_moddate
608 ];
609
610 TransactionListWithSplits, "TransactionListWithSplits", [
611 docnum,
612 name,
613 end_date,
614 date_macro,
615 payment_method,
616 source_account_type,
617 transaction_type,
618 group_by,
619 sort_by,
620 sort_order,
621 start_date,
622 columns
623 ];
624
625 TrialBalance, "TrialBalance", [
626 accounting_method,
627 end_date,
628 date_macro,
629 sort_order,
630 summarize_column_by,
631 start_date
632 ];
633
634 VendorBalance, "VendorBalance", [
635 qzurl,
636 accounting_method,
637 date_macro,
638 appaid,
639 report_date,
640 sort_order,
641 summarize_column_by,
642 department,
643 vendor
644 ];
645
646 VendorBalanceDetail, "VendorBalanceDetail", [
647 term,
648 accounting_method,
649 date_macro,
650 appaid,
651 report_date,
652 sort_order,
653 summarize_column_by,
654 department,
655 vendor,
656 columns,
657 duedate_macro,
658 start_duedate,
659 end_duedate
660 ];
661
662 VendorExpenses, "VendorExpenses", [
663 customer,
664 vendor,
665 end_date,
666 date_macro,
667 class,
668 sort_order,
669 summarize_column_by,
670 department,
671 accounting_method,
672 start_date
673 ];
674);