Skip to content

Allow partial refunds when marking expenses as unpaid #8529

@Betree

Description

@Betree

See https://oficonsortium.slack.com/archives/GFH4N961L/p1768345588709949
Related: #5459

Problem Statement

When marking an expense as unpaid (e.g., when a bank transfer fails and funds are returned), the current interface provides a binary checkbox for "Also refund payment processor fees?". This works well for two scenarios:

  • Full refund including processor fees (checkbox checked)
  • Refund minus the original processor fees (checkbox unchecked)

However, this doesn't accommodate scenarios where the amount returned differs from these two options:

  1. Intermediary bank fees - Additional fees may be deducted by intermediary banks beyond the original processor fee, resulting in a partial return (e.g., $500 + $15 sent, but only $460 returned due to an additional $40 intermediary bank fee)
  2. No processor fees recorded initially - When an expense was paid with $0 processor fees recorded, but the failed transfer resulted in actual losses that need to be recorded

Currently, fiscal host admins must make manual ledger adjustments to reflect these losses, which is error-prone and doesn't maintain accurate records in the platform.

Proposed Solution

Replace the "Also refund payment processor fees?" checkbox with an "Amount refunded" number input that allows fiscal host admins to specify exactly how much money was actually returned.

UI Changes

Current:

  • ✅ Also refund payment processor fees?

Proposed:

  • Amount refunded: [input field] (prefilled with total expense amount)
  • Helper text: Original payment processor fee: $15.00 (shown if applicable)

Behavior

  1. Default value: Input is prefilled with the total expense amount (including original processor fees)
  2. Show original processor fee: Display the original processor fee amount as helper text below the input (if any processor fees were recorded)
  3. Allow partial refunds: Admin can reduce the amount to reflect actual funds returned
  4. Record the difference: The difference between the original amount and the refunded amount is recorded as a loss attributed to payment processor fees

Example Scenarios

Scenario 1: Full processor fee not refunded

  • Original expense: $500 + $15 fee = $515 total
  • Bank returns: $500 (keeps the $15 fee)
  • Admin enters: $500 in "Amount refunded"
  • Result: $15 recorded as payment processor fee loss

Scenario 2: Intermediary bank fee

  • Original expense: $500 + $15 fee = $515 total
  • Bank returns: $460 (intermediary bank took additional fees)
  • Admin enters: $460 in "Amount refunded"
  • Result: $55 recorded as payment processor fee loss ($15 original + $40 additional)

Scenario 3: Full refund (current default behavior)

  • Original expense: $500 + $15 fee = $515 total
  • Bank returns: $515 (full amount including fees)
  • Admin enters: $515 in "Amount refunded" (default)
  • Result: Full amount credited back to collective

Additional Context

From discussion with Lauren:

"There are times when the refund we receive is lower than initial amount sent because an intermediary bank also took a fee. So 500+15 out might result in 460 in the return"

Currently, when payment providers don't reimburse the full amount, fiscal hosts often cover the difference back to the collective, but this requires manual ledger adjustments outside the platform.

Acceptance Criteria

  • Replace checkbox with "Amount refunded" number input
  • Input is prefilled with total expense amount by default
  • Display original processor fee amount as helper text (if applicable)
  • Allow admin to enter any amount ≤ original expense amount
  • Correctly record the difference as payment processor fee loss in the ledger
  • Validate that refunded amount cannot exceed original expense amount
  • Refunded amount cannot be <= 0
  • Update backend logic to handle partial refunds

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

Status

No status

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions