import {z} from 'zod' export type GetApiQuickbooksDesktopReportsBudgetSummaryArgs = {'Conductor-End-User-Id': string, reportType: 'balance_sheet_budget_overview' | 'balance_sheet_budget_vs_actual' | 'profit_and_loss_budget_overview' | 'profit_and_loss_budget_performance' | 'profit_and_loss_budget_vs_actual', reportDateFrom?: string | undefined, reportDateTo?: string | undefined, reportDateMacro?: ('all' | 'today' | 'this_week' | 'this_week_to_date' | 'this_month' | 'this_month_to_date' | 'this_quarter' | 'this_quarter_to_date' | 'this_year' | 'this_year_to_date' | 'yesterday' | 'last_week' | 'last_week_to_date' | 'last_month' | 'last_month_to_date' | 'last_quarter' | 'last_quarter_to_date' | 'last_year' | 'last_year_to_date' | 'next_week' | 'next_four_weeks' | 'next_month' | 'next_quarter' | 'next_year') | undefined, fiscalYear: number, budgetCriterion?: ('accounts' | 'accounts_and_classes' | 'accounts_and_customers') | undefined, classIds?: Array | undefined, classFullNames?: Array | undefined, summarizeColumnsBy?: ('class' | 'customer' | 'date') | undefined, summarizeRowsBy?: ('account' | 'class' | 'customer') | undefined}; export type GetApiQuickbooksDesktopReportsBudgetSummaryOptions = {baseUrl?: string | undefined, BearerAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const qbdReport = z.object({objectType: z.literal("qbd_report"), category: z.enum(["general_summary", "general_detail", "aging", "budget_summary", "job", "time", "custom_detail", "custom_summary", "payroll_detail", "payroll_summary"]), reportType: z.enum(["balance_sheet_by_class", "balance_sheet_previous_year_comparison", "balance_sheet_standard", "balance_sheet_summary", "customer_balance_summary", "expense_by_vendor_summary", "income_by_customer_summary", "inventory_stock_status_by_item", "inventory_stock_status_by_vendor", "income_tax_summary", "inventory_valuation_summary", "inventory_valuation_summary_by_site", "lot_number_in_stock_by_site", "physical_inventory_worksheet", "profit_and_loss_by_class", "profit_and_loss_by_job", "profit_and_loss_previous_year_comparison", "profit_and_loss_standard", "profit_and_loss_ytd_comparison", "purchase_by_item_summary", "purchase_by_vendor_summary", "sales_by_customer_summary", "sales_by_item_summary", "sales_by_sales_representative_summary", "sales_tax_liability", "sales_tax_revenue_summary", "serial_number_in_stock_by_site", "trial_balance", "vendor_balance_summary", "1099_detail", "audit_trail", "balance_sheet_detail", "check_detail", "customer_balance_detail", "deposit_detail", "estimates_by_job", "expense_by_vendor_detail", "general_ledger", "income_by_customer_detail", "income_tax_detail", "inventory_valuation_detail", "job_progress_invoices_vs_estimates", "journal", "missing_checks", "open_invoices", "open_purchase_orders", "open_purchase_orders_by_job", "open_sales_order_by_customer", "open_sales_order_by_item", "pending_sales", "profit_and_loss_detail", "purchase_by_item_detail", "purchase_by_vendor_detail", "sales_by_customer_detail", "sales_by_item_detail", "sales_by_sales_representative_detail", "transaction_detail_by_account", "transaction_list_by_customer", "transaction_list_by_date", "transaction_list_by_vendor", "unpaid_bills_detail", "unbilled_costs_by_job", "vendor_balance_detail", "ap_aging_detail", "ap_aging_summary", "ar_aging_detail", "ar_aging_summary", "collections_report", "balance_sheet_budget_overview", "balance_sheet_budget_vs_actual", "profit_and_loss_budget_overview", "profit_and_loss_budget_performance", "profit_and_loss_budget_vs_actual", "item_estimates_vs_actuals", "item_profitability", "job_estimates_vs_actuals_detail", "job_estimates_vs_actuals_summary", "job_profitability_detail", "job_profitability_summary", "time_by_item", "time_by_job_detail", "time_by_job_summary", "time_by_name", "custom_transaction_detail", "custom_summary", "employee_state_taxes_detail", "payroll_item_detail", "payroll_review_detail", "payroll_transaction_detail", "payroll_transactions_by_payee", "employee_earnings_summary", "payroll_liability_balances", "payroll_summary"]), title: z.string().nullable(), subtitle: z.string().nullable(), basis: z.enum(["accrual", "cash", "none"]).nullable(), rowCount: z.number().nullable(), columnCount: z.number().nullable(), columnTitleRowCount: z.number().nullable(), columns: z.array(z.object({columnId: z.string(), columnType: z.string(), dataType: z.string().nullable(), titles: z.array(z.object({rowNumber: z.number(), value: z.string().nullable()}))})), rows: z.array(z.discriminatedUnion("kind", [z.object({kind: z.literal("text"), rowNumber: z.number(), text: z.string().nullable()}), z.object({kind: z.literal("data"), rowNumber: z.number(), rowDescriptor: z.object({type: z.string().nullable(), value: z.string().nullable()}).nullable(), cells: z.array(z.object({columnId: z.string(), value: z.string().nullable(), dataType: z.string().nullable()}))}), z.object({kind: z.literal("subtotal"), rowNumber: z.number(), rowDescriptor: z.object({type: z.string().nullable(), value: z.string().nullable()}).nullable(), cells: z.array(z.object({columnId: z.string(), value: z.string().nullable(), dataType: z.string().nullable()}))}), z.object({kind: z.literal("total"), rowNumber: z.number(), rowDescriptor: z.object({type: z.string().nullable(), value: z.string().nullable()}).nullable(), cells: z.array(z.object({columnId: z.string(), value: z.string().nullable(), dataType: z.string().nullable()}))})]))}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Retrieve a budget summary report * * GET /quickbooks-desktop/reports/budget-summary */ export const getApiQuickbooksDesktopReportsBudgetSummary = async (args: GetApiQuickbooksDesktopReportsBudgetSummaryArgs, options?: GetApiQuickbooksDesktopReportsBudgetSummaryOptions) => { const {baseUrl = "https://api.conductor.is/v1", fetch: fetchFn = fetch, BearerAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args['Conductor-End-User-Id'] != null) headers.set("Conductor-End-User-Id", String(args['Conductor-End-User-Id'])) if (args.reportType != null) query.append("reportType", String(args.reportType)) if (args.reportDateFrom != null) query.append("reportDateFrom", String(args.reportDateFrom)) if (args.reportDateTo != null) query.append("reportDateTo", String(args.reportDateTo)) if (args.reportDateMacro != null) query.append("reportDateMacro", String(args.reportDateMacro)) if (args.fiscalYear != null) query.append("fiscalYear", String(args.fiscalYear)) if (args.budgetCriterion != null) query.append("budgetCriterion", String(args.budgetCriterion)) for (const item of args.classIds ?? []) query.append("classIds", String(item)) for (const item of args.classFullNames ?? []) query.append("classFullNames", String(item)) if (args.summarizeColumnsBy != null) query.append("summarizeColumnsBy", String(args.summarizeColumnsBy)) if (args.summarizeRowsBy != null) query.append("summarizeRowsBy", String(args.summarizeRowsBy)) if (BearerAuth !== undefined) headers.set('authorization', `Bearer ${BearerAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/quickbooks-desktop/reports/budget-summary${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(qbdReport, await res.json()) };