Rein processed a credit card refund on inspection 1008599788 and reports clicking Refund once, but the payments section shows two refunds for the same payment.
Rein suspects a double-click (mouse malfunction). No immediate customer action — client is checking with their bank. Rein is waiting before settling balance.
Likely bug — missing double-submit / concurrency protection on Guardian card refunds.
Code review shows the product intends to block duplicate refunds (payment.status === 'refunded', remaining refundable amount checks, queued-refund guard), but POST /guardian-payments/refund does not use idempotency keys or a payment-level lock. Two requests in quick succession can both pass validation, both call CardPointe, and both create Refund rows if the processor accepts both.
Frontend (GuardianRefundHubModal) sets isLoading / isDisabled on confirm, but has no synchronous in-flight guard — a fast double-click can fire two submits before React re-renders.
Key code paths:
attik-backend/src/routes/guardianPayments.ts — POST /refundattik-frontend/src/app/tools/inspections/[id]/components/GuardianRefundHubModal.tsxConfirm whether this incident was caused by the double-submit race (vs. e.g. principal + fee-only refund, or queued + immediate refund).
Ryan does not have access to refund request timestamps — needs a teammate with DB / logs / Guardian visibility to complete confirmation.
On inspection 1008599788, pull the two refund records for the affected Guardian card payment and compare:
createdAt on both Refund documents — milliseconds apart strongly suggests double-submitamount on each — two full principal refunds vs. principal + fee-only (refundFeeOnly: true, amount: 0)refundType / state — refund vs void, approved vs batched vs queuedguardianRefundId (CardPointe retref) — distinct values = two separate processor callsstatus and total refunded after both rowsguardian-payments/refund for the same paymentId — two POSTs within ~1suseRef in-flight guard; keep confirm disabled through success.Note alternative root cause (e.g. fee-only second row, queued processor path) and close or re-scope accordingly.
Please authenticate to join the conversation.
Completed
Main App
About 1 month ago
Linear
Get notified by email when there are changes.
Completed
Main App
About 1 month ago
Linear
Get notified by email when there are changes.