OUT-3604: QBO bank deposits for automatic bank reconciliation#227
OUT-3604: QBO bank deposits for automatic bank reconciliation#227SandipBajracharya merged 6 commits intofeature/stripe-fees-and-depositfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
When payments are received, optionally create QBO Bank Deposits that match the net amount deposited to the customer's bank (after Stripe fees), enabling automatic bank transaction matching. Payments are routed through Undeposited Funds, then a Bank Deposit moves the net amount to the bank account with the fee recorded as a negative line. This is behind a new opt-in bankDepositFeeFlag setting that requires absorbedFeeFlag to also be enabled. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…elector - Add GET endpoint for QBO bank accounts (/setting/bank-account) - Consolidate bankAccountRef write into settings POST endpoint (single API call) - Fix missing undepositedFundsAccountRef/bankAccountRef in token refresh and action - Fix deposit payload: add required TxnLineId to LinkedTxn - Fix Undeposited Funds lookup: query by AccountSubType instead of getOrCreate - Replace inline type with PaymentSucceededResponseType in handleBankDepositFlow - Add Sentry breadcrumbs and structured logging to bank deposit flow - Move deposit log after API call, use CustomLogger - Make PrivateNote optional in deposit schema - Add bankAccountRef to SettingRequestSchema and InvoiceSettingType - Add design doc for IntuitAPI token refresh (future ticket) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Wrap qb_settings + qb_portal_connections writes in db.transaction to prevent partial state (bankDepositFeeFlag=true with bankAccountRef=null) - Add null guard on paidSyncLog.amount before division in handleBankDepositFlow - Add invoiceNumber to failed DEPOSITED sync log for future resync support Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f1c86b7 to
801e818
Compare
| qbTokenInfo: IntuitAPITokensType, | ||
| ) { | ||
| await sleep(7000) // Payment succeed event can sometimes trigger before invoice created. | ||
| await sleep(20000) // Payment succeed event can sometimes trigger before invoice created. |
There was a problem hiding this comment.
7 seconds to 20 seconds is a huge bump. does this effect the performance of the application?
There was a problem hiding this comment.
New deposit flow requires invoice to be paid otherwise the flow fails. Bumped sleep to 20 sec to be very sure that invoice.paid event is complete. Since those syncs run at background, I think we have to compromise speed with accuracy.
| if (typeof val.bankDepositFeeFlag !== 'boolean') { | ||
| ctx.addIssue({ | ||
| path: ['bankDepositFeeFlag'], | ||
| code: z.ZodIssueCode.custom, | ||
| message: 'bankDepositFeeFlag is required when type is invoice', | ||
| }) | ||
| } |
There was a problem hiding this comment.
dont we need extra validation here? bankDepositFeeFlag is dependent on absorbedFeeFlag and bankAccountRef is dependent on bankDepositFeeFlag. We can add a validation here so that bankDepositFeeFlag requires absorbedFeeFlag, and bankAccountRef requires bankDepositFeeFlag.
There was a problem hiding this comment.
Correct but for now we are only releasing this feature to specific portals so adding validation here might make things more rigid. Instead we are handling this case in controller for now after checking if the portal accessing the resource is eligible for the feature
Undeposited Funds is a QBO system account that always exists and cannot be deleted. Caching its ID in qb_portal_connections was unnecessary. - Add getUndepositedFundsAccountId() on IntuitAPI (live lookup by subtype) - Call it directly in invoice.service.ts instead of checkAndUpdateAccountStatus - Remove undepositedFundsAccountRef from schema, type, and all plumbing - Remove UndepositedFunds from AccountTypeObj, updateAccountMapping, restoreAccountRef - Reuse single IntuitAPI instance in webhookInvoicePaid - Update migration: drop undeposited_funds_account_ref column addition Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
756dbc6 to
20bbcb9
Compare
4e05836
into
feature/stripe-fees-and-deposit
Summary
bankDepositFeeFlagsetting (requiresabsorbedFeeFlagto also be enabled)GET /api/quickbooks/setting/bank-accountendpoint to fetch QBO bank accountsbankAccountRefwrite toqb_portal_connectionsatomically with flag updatesundepositedFundsAccountRef/bankAccountRefin token refresh pathAccountSubTypequery (not getOrCreate)TxnLineIdpaidSyncLog.amountbefore deposit creationTest plan
absorbedFeeFlag+bankDepositFeeFlagin settingsinvoice.paidwebhook routes QBO Payment to Undeposited Fundspayment.succeededwebhook creates a Bank Deposit (gross - fee = net)🤖 Generated with Claude Code