Objective
- Align ACH payment status in the product with how internal and bank-timeline language is used: customers and ops often read “Paid” as funds received / settled, while the app today treats processor acceptance as paid.
- Reduce confusion when CardPointe / Guardian has accepted an ACH (
respstatA, mapped tocompleted) but settlement / funding may still be days out—decision needed on the exact cutover (e.g. label-only vssettled-gated “Paid”). - Keep finance and support trust high by making pending vs completed semantics predictable for ACH without breaking card or manual payment flows.
Background
Product feedback: ACH rows show Paid soon after processing, while typical ACH settlement can take multiple business days; users expect something like Pending until funds are actually received.
Slack context: Message from ryan (Slack)
Today’s mapping:
mapGuardianToStatusinattik-backend/src/util/functions/payments/paymentStatusMapping.tsmaps GuardianrespstatAtocompletedon thePaymentdocument (attik-backend/src/models/paymentSchema.ts).Today’s UI:
getPaymentDisplayInfoinattik-frontend/src/util/functions/payments/pacStatusHelpers.tsshows the “Paid” chip whenpayment.status === 'completed'orguardian.status === 'A', and does not branch onpayment.settledortype === 'ach'.Settlement already exists on the model:
Payment.settled(seepaymentSchema.ts) is the normalized “funds / settlement” signal (Guardian usessetlstat, etc.). Batch surfaces (e.g.attik-frontend/src/app/tools/payments/batches/PaymentBatchesClient.tsx) already reason about settled vs awaiting for operations; the client invoice / pay-beta payment list path above does not use the same distinction for the per-payment chip.Backend nuance:
attik-backend/src/util/functions/guardian/checkPaymentStatus.tsand related funding logic treat ACH as needing/funding(and return codes) for true outcomes; inquire semantics for ACH are documented as misleading for bank-level returns—so “Paid” in the UI is not equivalent to “all ACH risk is over.”
Scope
Backend
attik-backend/src/models/paymentSchema.ts—status,settled,type,guardian(e.g.status,achReturnCode, funding metadata).attik-backend/src/util/functions/payments/paymentStatusMapping.ts—mapGuardianToStatus,GUARDIAN_SUCCESS_STATUSES(A→completed).attik-backend/src/util/functions/guardian/checkPaymentStatus.ts— whensettledis set and how it relates to funding / ACH returns (authoritative paths for ACH lifecycle).attik-backend/src/util/functions/guardian/settlementStatus.ts(referenced frompaymentSchema) —calculateSettledStatusand related helpers.- Decision needed: Whether
completedshould remain gateway-success andsettleddrives “Paid” copy, orstatusitself should stay pending longer for ACH (implications fortotalPaid, locks, QB / streams).
Frontend
attik-frontend/src/util/functions/payments/pacStatusHelpers.ts—getPaymentDisplayInfo(central label: Paid / Pending).attik-frontend/src/app/client/job/[slug]/pay-beta/PaymentBetaClient.tsx— payment rows usegetPaymentDisplayInfofor chips.attik-frontend/src/app/client/job/[slug]/pay/PaymentHistoryList.tsx— overlapping payment history UX (may need consistency).attik-frontend/src/util/functions/payments/settlementStatusMapping.ts— existing settlement vocabulary for reuse or alignment.attik-frontend/src/app/tools/payments/batches/— reference behavior for settled / awaiting language; decision needed on parity with staff batch views vs customer portal.
Product / architecture
- Decision needed: Canonical meaning of “Paid” for ACH (accepted at processor vs deposited vs irreversible).
- Decision needed: Copy-only (e.g. “Processing”, “Submitted”) vs data changes to
status/settledgating.
References
- Slack — ACH paid vs funds received
- CardPointe / Guardian ACH and funding docs (integrator-facing): use Fiserv / CardPointe ACH & funding references as needed for
setlstat,/funding, return codes (see comments incheckPaymentStatus.ts/paymentStatusMapping.ts).