QuickBooks 2-Way Invoice Synchronization

v0.1.0

Certified 2-way sync for QuickBooks Online and Desktop, zero-PHI accounting payload, idempotency, and consent gating.

QuickBooks 2-Way Invoice Synchronization

The QuickBooks Synchronization bounded context connects clinical dental procedures directly to Intuit QuickBooks (quickbooks.intuit.com). It provides certified 2-way invoice and payment synchronization for both QuickBooks Online and QuickBooks Desktop while enforcing zero-PHI compliance and patient billing consent gates.


Integration Architecture & Scope

The QuickBooks integration is dedicated strictly to itemized dental patient billing and payment receipts. Practice inventory, scheduling, odontograms, and clinical EMR data remain strictly managed within Obelawium:

[Chairside Operatory Encounter Completed]
                   |
     (LedgerService::charge())
                   v
        [DentalInvoice Created]
                   |
         Has Active Billing Consent?
         (ConsentType::BILLING)
         /                   \
       NO                     YES
       |                       |
[Blocked by Consent]      [Zero-PHI Payload Extracted]
(Audit Flag Raised)            |
                               v
                     [Idempotent Sync Job]
                               |
              +----------------+----------------+
              |                                 |
              v                                 v
   [QuickBooks Online]                 [QuickBooks Desktop]
   (REST OAuth 2.0 API)              (Intuit Web Connector QWC)

Zero-PHI Compliance Invariant

Because accounting platforms are outside the clinic’s internal healthcare compliance boundary, Obelawium Dental enforces a strict Zero-PHI Transmission Rule:

Permitted in QuickBooks PayloadStrictly Prohibited (Filtered Out)
ADA/CDT Code (e.g. CDT: D2740)Patient First or Last Name
Standard CDT DescriptionPatient Social Security Number (SSN)
Unit Price & QuantityDate of Birth or Age
Invoice Total & Insurance ShareClinical Chart Notes or Diagnostics
Opaque Ledger Reference (e.g. INV-9041)Medical History & Health Alerts
External QuickBooks Customer ID TokenRadiographs or Odontogram Findings

Before any invoice payload is compiled or transmitted to Intuit, QuickBooksSyncService validates that the patient has granted active consent for third-party accounting:

$hasConsent = ium()->dental()->patients()->hasActiveConsent($invoice->patient_id, ConsentType::BILLING)
    || ium()->dental()->patients()->hasActiveConsent($invoice->patient_id, ConsentType::THIRD_PARTY_PAYMENT);

if (! $hasConsent) {
    // Record BLOCKED_BY_CONSENT status and throw exception
    throw QuickBooksSyncException::consentMissing($invoiceId);
}

If consent was not granted or was subsequently revoked, the sync job enters BLOCKED_BY_CONSENT status, halting the transmission until formal authorization is provided.


QuickBooks Online vs Desktop Support

1. QuickBooks Online (QBO)

  • Authenticates via secure Intuit REST OAuth 2.0 protocol.
  • Directly creates itemized SalesItemLineDetail records against the practice’s QuickBooks Realm.
  • Immediate real-time response.

2. QuickBooks Desktop (QBD)

  • Compatible with QuickBooks Pro, Premier, and Enterprise editions.
  • Communicates asynchronously via the standard Intuit Web Connector (QWC) XML pipeline.
  • Synchronizes when the clinic accountant runs the scheduled Web Connector queue.

Idempotency & Duplicate Prevention

Every sync job requires an idempotency_key (e.g. hash('invoice-' . $invoiceId . '-' . $version)). If network timeouts or webhook retries trigger a duplicate call, the service returns the existing QuickBooksSyncJob without re-posting to QuickBooks:

use Obelaw\Ium\Dental\Enums\QuickBooksSyncStatus;

enum QuickBooksSyncStatus: string
{
    case PENDING = 'pending';
    case SYNCING = 'syncing';
    case SYNCED = 'synced';
    case BLOCKED_BY_CONSENT = 'blocked_by_consent';
    case FAILED = 'failed';
}

Fluent Service Operations

All synchronization actions are invoked via ium()->dental()->quickBooks():

1. Syncing a Dental Invoice

use Obelaw\Ium\Dental\Data\SyncQuickBooksInvoiceDto;

$syncJob = ium()->dental()->quickBooks()->syncInvoice(SyncQuickBooksInvoiceDto::from([
    'invoice_id' => $invoice->id,
    'idempotency_key' => 'INV-SYNC-' . $invoice->id . '-' . time(),
    'is_desktop_qwc' => false, // Set true for QuickBooks Desktop Web Connector
    'actor_id' => 'USER-BILLING-01',
]));

echo $syncJob->sync_status->value; // 'synced'
echo $syncJob->qbo_transaction_id; // 'QB-TXN-QBO-6789ABCD'

2. Syncing Payment Receipts

When copays or insurance claims are posted to the patient ledger, synchronize the payment receipt to mark the invoice paid inside QuickBooks:

$paymentJob = ium()->dental()->quickBooks()->syncPayment(
    paymentId: $payment->id,
    actorId: 'USER-BILLING-01'
);

3. Reviewing Sync Audit History

$history = ium()->dental()->quickBooks()->getSyncHistory(
    resourceType: 'invoice',
    resourceId: $invoice->id
);

foreach ($history as $job) {
    echo "Attempt {$job->attempts}: {$job->sync_status->value} at {$job->synced_at}\n";
}

Emitted Domain Events

Event ClassTriggerPayload
QuickBooksInvoiceSyncedDispatched when an invoice is successfully acknowledged by Intuit.QuickBooksSyncJob $job