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.
Next Up
Main App
About 22 hours ago
Linear
Get notified by email when there are changes.
Next Up
Main App
About 22 hours ago
Linear
Get notified by email when there are changes.