Skip to content

Reimbursement: sync as QBO Bill#111

Merged
hhff merged 3 commits into
mainfrom
reimbursement-qbo-sync
Jun 13, 2026
Merged

Reimbursement: sync as QBO Bill#111
hhff merged 3 commits into
mainfrom
reimbursement-qbo-sync

Conversation

@hhff

@hhff hhff commented Jun 13, 2026

Copy link
Copy Markdown
Member

Summary

Makes `Reimbursement` follow the same QBO Bill lifecycle as every other payable host (ContributorPayout, ContributorAdjustment, ProfitShare, Trueup, PayStub). Previously reimbursements never pushed to QBO and were settled by hand via a matching negative ContributorAdjustment booked off-platform — that made them invisible to the QBO vendor record.

Changes

  • Migration adds `qbo_bill_id` (string) + index to `reimbursements`
  • `Reimbursement` includes `SyncsAsQboBill` and implements the contract: `bill_txn_date`, `bill_description`, `bill_doc_number_code` (`"RB"`)
  • Acceptance toggle in `app/admin/contributors.rb`:
    • Accept → `sync_qbo_bill!` (best-effort; logs Rails error on failure so the admin can retry)
    • Deny → `detach_and_destroy_qbo_bill` so the books stay aligned
  • New rake task `reimbursements:backfill_qbo_bills` pushes existing accepted-but-unsynced rows. Idempotent; silently skips contributors lacking a `ContributorQboVendor` mapping.

QBO account routing

Uses the default "Contractors - Client Services" category (same as other hosts). If a different expense category is wanted later, override `Reimbursement#find_qbo_account!`.

Rollout

  1. Merge + deploy
  2. Run `bundle exec rake reimbursements:backfill_qbo_bills` once on production
  3. Going forward, every Accept push automatically syncs the Bill

Test plan

  • CI green
  • Accept a new reimbursement on staging → confirm a QBO Bill is created against the contributor's vendor record
  • Deny that reimbursement → confirm the QBO Bill is detached + destroyed
  • Run the backfill rake on staging → confirm existing accepted rows get qbo_bill_id populated

🤖 Generated with Claude Code

hhff added 3 commits June 13, 2026 19:23
Reimbursements were the one payable host that didn't sync to QuickBooks —
they sat in Stacks balance forever and were historically settled via a
matching negative ContributorAdjustment booked off-platform. This makes
reimbursements follow the same lifecycle as ContributorPayout, Trueup,
ProfitShare, ContributorAdjustment, and PayStub:

  • New qbo_bill_id column on reimbursements
  • include SyncsAsQboBill
  • bill_txn_date / bill_description / bill_doc_number_code ("RB")

Toggle-acceptance hook now:
  • Accept  → r.sync_qbo_bill!  (best-effort; logs on Deel/QBO failure)
  • Deny   → r.detach_and_destroy_qbo_bill

For existing accepted reimbursements:

  bundle exec rake reimbursements:backfill_qbo_bills

The rake task is idempotent — it only pushes rows with qbo_bill_id NULL,
and silently skips contributors without a ContributorQboVendor mapping.

QBO account routing uses the default "Contractors - Client Services";
override Reimbursement#find_qbo_account! if a different expense category
is wanted (e.g., Reimbursable Expenses).
@hhff hhff merged commit 2709433 into main Jun 13, 2026
1 check passed
@hhff hhff mentioned this pull request Jun 14, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant