OUT-3604: Stripe payout → batched QBO bank deposit#266
Merged
Conversation
drizzle's migrate() runs all pending files in a single transaction, which
fails when one migration adds an enum value and a later one uses it in DDL
("unsafe use of new value"). Add migratePerFile (one commit per journal
entry) and a db:migrate runner, and switch build.sh to use it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…otency index Add PAYOUT entity + SETTLED event, the bank_deposit_fee_flag and bank_account_ref columns (schema + migration together), extend the one-shot unique index and claimWebhookEvent predicate to cover payout/settled (byte-equivalent), and add getSuccessfulPaidPaymentIds. Stale payout claims flip terminal (no resync path). Retire the unused DEPOSITED enum value. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add QBDepositResponseSchema and refactor _createDeposit to the standard
assertNotQBFault + Zod-parse pattern (returning a typed response), and
parse the Undeposited Funds lookup, removing untyped {} property access.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add AccountTypeObj.Bank so checkAndUpdateAccountStatus reactivates an archived bank account; a deleted one throws (never auto-restore a deposit destination). Thread bankAccountRef through every IntuitAPITokensType construction site (extractTokens, getRefreshedQbTokenInfo, auth exchange + emptyTokens, getPortalTokens, rename-accounts cmd) so the now-required field is always populated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Handle payout.reconciliation_completed: resolve each invoice to its QBO Payment, assert sum(gross)-sum(fee)==netAmount in cents, and create one Bank Deposit (N payment lines + one fee line). Abort with a FAILED log on refund lines, negative aggregate fee, duplicate/unresolved invoices, or a mismatch. Reshape createBankDepositForPayment to the batched N-line form, drop the never-shipped per-payment deposit path (payment.succeeded no-ops in batched mode), and skip payouts in the resync dispatcher for now. On invoice.paid, route the QBO Payment through Undeposited Funds when batched mode is on (DepositToAccountRef) so the payout deposit can link and sweep it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR adds payout-level Stripe reconciliation through batched QuickBooks Bank Deposits. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (2): Last reviewed commit: "fix(OUT-3604): serialize per-file migrat..." | Re-trigger Greptile |
Greptile PR #266 review: - migratePerFile now wraps its loop in a Postgres advisory lock so concurrent deploy runners can't race the same pending migration (e.g. one dropping an index before the other's DROP). - globalSetup now applies migrations via migratePerFile instead of drizzle's batched migrate(), so a fresh integration DB can apply the enum-add-then-use sequence (was failing at setup). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collaborator
Author
|
@greptileai re-review whole feature |
SandipBajracharya
changed the base branch from
master
to
feature/payout-reconciliation
July 23, 2026 05:16
priosshrsth
requested changes
Jul 23, 2026
- invoice.service: simplify Undeposited-Funds ref to a ternary. - payment.service: type paymentLines and build the fee line via push when feeTotal > 0 instead of a spread. - webhook.service: accumulate gross/fee cents in a single reduce. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
On
payout.reconciliation_completed, create one QBO Bank Deposit per Stripe payout whose net matches the bank-feed entry, so QBO auto-suggests a one-click reconciliation match. Replaces the never-shipped per-payment deposit path.Assembly listens to Stripe's
payout.reconciliation_completed, resolves each charge to a Copilot invoice, and forwards an enriched webhook. This app resolves each invoice → QBO Payment viaqb_sync_logs, assertssum(gross) − sum(fee) == payout.netAmount(in cents), and creates one Bank Deposit: N payment-linked lines + one negative aggregated-fee line.Commits
db:migrate) — drizzle batches all pending migrations into one transaction, which breaks enum-add-then-use;migratePerFileapplies one file per transaction (wired intobuild.sh).PAYOUT/SETTLED, thebank_deposit_fee_flag+bank_account_refcolumns (schema + migration together), the one-shot unique index +claimWebhookEventpredicate extended forpayout/settled,getSuccessfulPaidPaymentIds.QBDepositResponseSchema+assertNotQBFault/Zod-parse.AccountTypeObj.Bank(reactivate archived, throw on deleted),bankAccountRefthreaded through all token-construction sites.payment.succeededno-op in batched mode,invoice.paid→ Undeposited Funds routing, resync skip for payouts.Behavior (
bankDepositFeeFlagon)invoice.paidpayment.succeededpayout.reconciliation_completedAborts with a FAILED log (never a partial/unbalanced deposit) on: refund lines, negative aggregate fee, duplicate/unresolved invoices, or a sum mismatch.
Notes / follow-ups
captureWebhookEventGETharness) are managed separately and are not in these commits.shouldRetry: false) — no cron resync path yet; auto-recovery + the settings UI (bank-account picker, dedicated toggle) are tracked in OUT-4003.🤖 Generated with Claude Code