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