quickbooks-types

Crates.ioquickbooks-types
lib.rsquickbooks-types
version0.1.1
created_at2025-11-12 22:55:13.011505+00
updated_at2025-11-13 01:54:36.279572+00
descriptionType definitions for QuickBooks Online API
homepage
repositoryhttps://github.com/exotik850/quickbooks-types
max_upload_size
id1930066
size358,318
(Exotik850)

documentation

README

QuickBooks Online Types for Rust

The quickbooks-types crate provides strongly typed Rust models for QuickBooks Online (QBO) API entities and report types. It focuses on data structures, validation helpers, and report parameter builders. Network access and API calls are intentionally out of scope—use your preferred HTTP client alongside these types.

  • Crate: quickbooks-types
  • Version: 0.1.1
  • License: MIT

QuickBooks API docs: https://developer.intuit.com/app/developer/qbo/docs/get-started


Status and scope

This crate:

  • Defines data models for common QBO entities (e.g., Invoice, Customer, Vendor, Item, etc.)
  • Provides traits that capture operation preconditions such as can_create, can_full_update, can_sparse_update, etc.
  • Includes helper types for lines, references, taxes, contact info, and metadata
  • Implements a reports module with rich report parameter builders and types
  • Offers optional ergonomics via a builder feature, and an optional reports+Polars integration feature

This crate does not:

  • Make HTTP requests
  • Provide an async runtime or HTTP client
  • Offer a general SQL-like query builder for QBO entities

Installation

[dependencies]
quickbooks-types = "0.1.1"

Optional features:

  • builder: derive Builder types and add convenience constructors for top-level entities
  • polars: enable report parsing helpers that integrate with Polars (exposes reports::QBPolarsError)

Examples:

[dependencies]
quickbooks-types = { version = "0.1.1", features = ["builder"] }
# or
quickbooks-types = { version = "0.1.1", features = ["polars"] }

Modules and re-exports

  • Entities re-exported at crate root:
    • Account, Attachable, Bill, BillPayment, CompanyInfo, Customer, Employee, Estimate, Invoice, Item, Payment, Preferences, SalesReceipt, Vendor
  • Nested modules:
    • common: shared value types (e.g., NtRef, MetaData, contact and address types, taxes)
    • reports: report data structures and parameter builders
      • reports::types: report enum-like structs and <Report>Params
      • reports::params: reusable parameter enums and typed IDs
      • reports::models: report models (e.g., Report, Row, ColData)
      • reports::polars (feature = "polars"): Polars integration

Quick start: Entities

Basic construction and serialization of an invoice:

use chrono::NaiveDate;
use serde_json;
use quickbooks_types::{Invoice, Line, LineDetail, SalesItemLineDetail};
use quickbooks_types::common::NtRef;

// minimal invoice with one sales item line
let invoice = Invoice {
    customer_ref: Some(NtRef::from(("John Doe", "CUST-123"))),
    txn_date: NaiveDate::from_ymd_opt(2024, 10, 1),
    line: Some(vec![
        Line {
            amount: Some(100.0),
            line_detail: LineDetail::SalesItemLineDetail(SalesItemLineDetail {
                item_ref: Some(NtRef::from(("Widget A", "ITEM-001"))),
                qty: Some(1.0),
                unit_price: Some(100.0),
                ..Default::default()
            }),
            ..Default::default()
        }
    ]),
    ..Default::default()
};

let json = serde_json::to_string_pretty(&invoice).unwrap();
println!("{json}");

Operation checks (traits):

use quickbooks_types::{Invoice, QBCreatable, QBReadable, QBDeletable, QBFullUpdatable};

let mut invoice = Invoice::default();
assert!(!invoice.can_create()); // missing required fields (customer_ref + line)

invoice.customer_ref = Some(("John Doe", "CUST-123").into());
invoice.line = Some(vec![]);
assert!(!invoice.can_create()); // line must be a non-empty collection with amounts

// simulate entity read from QBO
invoice.id = Some("123".into());
invoice.sync_token = Some("2".into());
assert!(invoice.can_read());          // ID is set
assert!(!invoice.can_full_update());  // still fails creation rules

// deletion requires "has_read" (ID + sync_token)
assert!(invoice.can_delete());

Convert entities to references (NtRef):

use quickbooks_types::{Customer, QBToRef};

let mut customer = Customer::default();
customer.id = Some("CUST-123".into());
customer.display_name = Some("John Doe".into());

let customer_ref = customer.to_ref().unwrap();
// customer_ref.name == Some("John Doe"), customer_ref.value == Some("CUST-123")

Builder feature

Enable the builder feature to get derived builders for most entity types and a convenience ::new() associated function for top-level entities (e.g., Invoice::new() returns an InvoiceBuilder).

[dependencies]
quickbooks-types = { version = "0.1.1", features = ["builder"] }
use chrono::NaiveDate;
use quickbooks_types::common::NtRef;
use quickbooks_types::{Invoice, LineDetail, QBCreatable};
use quickbooks_types::{LineBuilder, SalesItemLineDetailBuilder};

let invoice = Invoice::new()
    .customer_ref(NtRef::from(("John Doe", "CUST-123")))
    .txn_date(NaiveDate::from_ymd_opt(2024, 10, 1).unwrap())
    .line(vec![
        LineBuilder::default()
            .amount(100.0)
            .line_detail(LineDetail::SalesItemLineDetail(
                SalesItemLineDetailBuilder::default()
                    .item_ref(NtRef::from(("Widget A", "ITEM-001")))
                    .qty(1.0)
                    .unit_price(100.0)
                    .build()
                    .unwrap(),
            ))
            .build()
            .unwrap(),
    ])
    .build()
    .unwrap();

assert!(invoice.can_create());

Attachable convenience (builder):

use quickbooks_types::Attachable;

#[cfg(feature = "builder")]
{
    use quickbooks_types::AttachableBuilder;

    // AttachableBuilder::file(...) sets file_path, derives file_name and content_type from extension
    let attachable = Attachable::new()
        .note("Invoice backup")
        // .file(&std::path::Path::new("docs/invoice.pdf"))?
        .build();

    assert!(attachable.is_ok());
}

Reports

The reports module provides:

  • Richly-typed report models: reports::models::{Report, Row, ColData, ...}
  • Strongly-typed parameter builders per report: reports::types::<Report>Params
  • Common enums and ID wrappers for parameters: reports::params::*

Build a query string for a report:

use chrono::NaiveDate;
use quickbooks_types::reports::types::*;
use quickbooks_types::reports::params::*;

let balance_sheet = BalanceSheetParams::new()
    .accounting_method(AccountingMethod::Cash)
    .start_date(NaiveDate::from_ymd_opt(2024, 1, 1).unwrap())
    .end_date(NaiveDate::from_ymd_opt(2024, 12, 31).unwrap())
    .date_macro(DateMacro::ThisFiscalYear)
    .summarize_column_by(SummarizeColumnBy::Month);

println!("{}", balance_sheet.to_query_string());
// -> accounting_method=Cash&start_date=2024-01-01&end_date=2024-12-31&date_macro=This Fiscal Year&summarize_column_by=Month

Another example:

use chrono::NaiveDate;
use quickbooks_types::reports::types::*;
use quickbooks_types::reports::params::*;

let ap_aging = APAgingDetailParams::new()
    .as_of_date(NaiveDate::from_ymd_opt(2024, 6, 30).unwrap())
    .aging_method(AgingMethod::Current)
    .vendor(VendorId(789))
    .column("Name")
    .column("DueDate")
    .column("Amount");

println!("{}", ap_aging.to_query_string());

Parsing a report result:

use quickbooks_types::reports::models::Report;

let json = r#"{
  "Header": { "ReportName": "BalanceSheet" },
  "Columns": { "Column": [ { "ColTitle": "Total", "ColType": "Money" } ] },
  "Rows": { "Row": [] }
}"#;

let report: Report = serde_json::from_str(json).unwrap();
assert_eq!(report.name(), Some("BalanceSheet"));

Polars integration (feature = "polars"):

  • Enables reports::polars helpers and reports::QBPolarsError
  • Provide your own conversion to Polars DataFrames depending on your use case

Entities included

Top-level entities for which QBItem is implemented and a Display impl is provided:

  • Account, Attachable, Bill, BillPayment, CompanyInfo, Customer, Employee, Estimate, Invoice, Item, Payment, Preferences, SalesReceipt, Vendor

Supporting value types (non-exhaustive):

  • common: NtRef, MetaData, Addr, Email, PhoneNumber, WebAddr, TxnTaxDetail, LinkedTxn, and others
  • line: Line, LineDetail and its variants (e.g., SalesItemLineDetail, SubTotalLineDetail, etc.), LineField (alias for Vec<Line>)

Operation traits (selected):

  • QBCreatable: can_create(&self) -> bool – entity meets required fields for creation
  • QBReadable: can_read(&self) -> bool – true if ID is present
  • QBDeletable: can_delete(&self) -> bool – default requires both ID and sync_token
  • QBFullUpdatable: can_full_update(&self) -> bool – type-specific requirements
  • QBSparseUpdateable: can_sparse_update(&self) -> bool – typically can_full_update() + sparse == true
  • QBVoidable: can_void(&self) -> bool – default requires both ID and sync_token
  • QBSendable / QBPDFable: marker traits for entities that can be emailed / retrieved as PDF in QBO
  • QBToRef: to_ref(&self) -> Result<NtRef, QBTypeError> – convert to reference usable in other entities

Note: These methods validate local preconditions only; they do not contact QBO.


Errors

use quickbooks_types::QBTypeError;

#[derive(Debug, thiserror::Error)]
pub enum QBTypeError {
    #[cfg(feature = "builder")]
    #[error("Error validating QB Object in builder: {0}")]
    ValidationError(String),

    #[error("Missing field in QB Object: {0}")]
    MissingField(&'static str),

    #[error("QB Item could not be referenced!")]
    QBToRefError,
}

Tips

  • IDs and sync_token are required for delete and void operations (has_read() check)
  • Builders (feature = "builder") return Result<_, QBTypeError> on build()
  • Some enums contain placeholder or minimal variants where the QBO surface is large; open an issue or PR to extend as needed

Contributing

Issues and PRs are welcome. If you need additional entities, fields, or extended report handling, feel free to propose a change.


License

MIT. See the LICENSE file for details.

Commit count: 0

cargo fmt