Skip to content

Make donation refund operations idempotent and safe under repeated requests #144

Description

@grantfox-oss

Context

The donation refund flow in src/services/donation.service.ts updates a donation to REFUNDED and decrements the campaign balance inside a transaction. Repeated refund requests or retries could create inconsistent state if the same refund action is triggered more than once.

Problem statement

Implement refund idempotency so that repeated refund requests do not cause inconsistent state or duplicate side effects.

Current behavior

  • src/services/donation.service.ts allows a refund to be attempted whenever the donation is in a confirmed state and the caller is authorized.
  • There is no explicit guard to ensure the refund operation is safely deduplicated if the same request is retried.

Required behavior

  • Repeated refund requests for the same donation should be handled safely and consistently.
  • The service should avoid double-decrementing campaign balances or applying duplicate refund state transitions.
  • The behavior should be explicit and testable.

Constraints

  • The change should preserve the existing donation refund API behavior.
  • The solution should remain compatible with the current transaction flow.

Acceptance criteria

  • Repeated refund requests for the same donation do not double-apply the refund.
  • The campaign balance is decremented only once for a single refund operation.
  • Unit tests cover duplicate refund requests and retry scenarios.

Out of scope

  • Implementing a broader accounting or ledger system.
  • Changing the donation refund API contract.

Hints and references

  • Review the transaction boundaries in the donation confirmation and refund flow and how the service currently handles state changes.

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions