Skip to content

feat: add refund reason handling to transaction updates and details#357

Open
Dprof-in-tech wants to merge 1 commit intomainfrom
feat-show-refund-reason-on-noblocks
Open

feat: add refund reason handling to transaction updates and details#357
Dprof-in-tech wants to merge 1 commit intomainfrom
feat-show-refund-reason-on-noblocks

Conversation

@Dprof-in-tech
Copy link
Collaborator

@Dprof-in-tech Dprof-in-tech commented Feb 4, 2026

Description

This pull request adds support for tracking and displaying the reason for refunded transactions throughout the application. It introduces a new refund_reason field to the transactions table, updates backend and frontend logic to handle this field, and ensures the refund reason is shown to users when relevant.

Database and API updates:

  • Added a refund_reason column to the transactions table to store the reason for refunds, and updated Supabase queries and API payloads to include this field when a transaction is refunded. [1] app/api/v1/transactions/[id]/route.tsL67-R79, [2] F239bae5L322R322, F239bae5L339R339, F239bae5L385R385, [3] [4]

Backend logic enhancements:

Frontend UI improvements:

  • Updated transaction details and list components to display the refund reason to users when a transaction has been refunded and a reason is available. [1] [2] [3] [4] [5]

Type and data structure updates:

  • Extended TypeScript types and interfaces to include refundReason and related fields, ensuring type safety across the application. [1] [2] [3] [4]

User experience enhancements:

  • Improved transaction status messaging and analytics tracking to include the refund reason, providing clearer feedback to users and more accurate event logging. [1] [2] [3]

References

closes #356

Testing

  • This change adds test coverage for new/changed/fixed functionality

Checklist

  • I have added documentation and tests for new/changed functionality in this PR
  • All active GitHub checks for tests, formatting, and security are passing
  • The correct base branch is being used, if not main

By submitting a PR, I agree to Paycrest's Contributor Code of Conduct and Contribution Guide.

Summary by CodeRabbit

Release Notes

  • New Features
    • Refunded transactions now display the reason for the refund across transaction details, lists, and status pages.
    • Refund reasons are captured and shown alongside transaction status to provide clearer visibility into why a transaction was refunded.

@Dprof-in-tech Dprof-in-tech requested a review from chibie as a code owner February 4, 2026 14:16
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

The changes implement refund reason tracking and display throughout the application. A new refund_reason column is added to the database schema. The API layers, backend routes, and type definitions are updated to handle the new field. State management captures and propagates refund reasons, and UI components render refund reasons for refunded transactions.

Changes

Cohort / File(s) Summary
Database Schema
supabase/migrations/20250204000000_add_refund_reason_to_transactions.sql
Added nullable refund_reason TEXT column to transactions table with descriptive comment.
Type Definitions
app/types.ts
Extended transaction-related types with optional refundReason/refund_reason fields: OrderDetailsData, TransactionHistory, TransactionCreateInput, TransactionUpdateInput, UpdateTransactionDetailsPayload. Added cancellationReasons to OrderDetailsData.
API Layer
app/api/aggregator.ts
Enhanced updateTransactionDetails to conditionally include refundReason in request payload alongside existing fields.
Backend Routes
app/api/v1/transactions/[id]/route.ts, app/api/v1/transactions/route.ts
PUT route updated to conditionally add refund_reason to update payload; POST route now captures refund_reason from request body, defaulting to null.
State Management
app/context/TransactionsContext.tsx
Added refund reason tracking during reconciliation by capturing cancellationReasons as joined string, detecting refund_reason changes, and propagating updates to backend and local state.
UI Components
app/components/transaction/TransactionDetails.tsx, app/components/transaction/TransactionList.tsx
Added conditional rendering of "Refund Reason" row in details view (two locations) and refund reason line in list view when status is "refunded" and refund_reason exists. Modified TransactionList layout to accommodate vertical grouping of time/status/refund reason.
Page Logic
app/pages/TransactionStatus.tsx
Added refundReason derivation from cancellationReasons for refunded transactions, included in API payload, analytics tracking, and UI render for refund message and receipt details.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰✨ A refund reason now takes flight,
Through databases and UI bright!
No more mystery when coins return,
The receipt now shows—oh what we've learned! 💚

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides a comprehensive overview of changes organized by category (database, backend, frontend, types, UX). However, the Testing section is completely empty with no description of testing approach. Add details to the Testing section describing how the changes were tested, including manual testing steps and confirmation of test coverage.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly and concisely summarizes the main change: adding refund reason handling to transaction updates and details throughout the application.
Linked Issues check ✅ Passed The PR successfully implements all coding requirements from issue #356: adds refund_reason database column, updates backend logic to handle the field, and displays refund reason in transaction details and lists only for refunded status.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing refund reason handling across the database, API, and UI layers. No unrelated modifications or scope creep detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-show-refund-reason-on-noblocks

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Reviews will stop working after February 8, 2026 if the new IP is not added to your allowlist.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/components/transaction/TransactionList.tsx (1)

306-324: ⚠️ Potential issue | 🟡 Minor

Inconsistent refund reason display between TransactionListItem and inline list rendering.

The TransactionListItem component (lines 80-105) now displays the refund reason for refunded transactions, but the inline transaction rendering in the main list (this section) does not include this feature. This creates an inconsistent user experience depending on which code path renders the transaction.

Consider adding the refund reason display here as well, or extracting the shared rendering logic to use TransactionListItem consistently.

🔧 Proposed fix to add refund reason display
                             <div className="flex items-center gap-x-2">
                               <span className="text-text-disabled dark:text-white/30">
                                 {new Date(
                                   transaction.created_at,
                                 ).toLocaleTimeString([], {
                                   hour: "2-digit",
                                   minute: "2-digit",
                                 })}
                               </span>
                               <span className="size-1 bg-icon-outline-disabled dark:bg-white/5"></span>
                               <span
                                 className={classNames(
                                   STATUS_COLOR_MAP[transaction.status] ||
                                     "text-text-secondary dark:text-white/50",
                                 )}
                               >
                                 {transaction.status}
                               </span>
                             </div>
+                            {transaction.status === "refunded" &&
+                              transaction.refund_reason &&
+                              transaction.refund_reason.trim() !== "" && (
+                                <span className="text-xs text-text-secondary dark:text-white/50 line-clamp-1">
+                                  {transaction.refund_reason}
+                                </span>
+                              )}
                           </div>
🧹 Nitpick comments (3)
app/api/aggregator.ts (1)

447-458: Consider updating the JSDoc to document the new refundReason parameter.

The function signature now accepts refundReason, but it's not documented in the JSDoc block above.

📝 Proposed JSDoc update
 /**
  * Updates the details of a transaction including status, hash, and time spent
  * `@param` {Object} params - The parameters object
  * `@param` {string} params.transactionId - The ID of the transaction to update
  * `@param` {string} params.status - The new status to set
  * `@param` {string} [params.txHash] - The transaction hash (optional)
  * `@param` {string} [params.timeSpent] - The time spent on the transaction (optional)
+ * `@param` {string} [params.refundReason] - The reason for refund when status is refunded (optional)
  * `@param` {string} params.accessToken - The access token for authentication
  * `@param` {string} params.walletAddress - The wallet address for authorization
  * `@returns` {Promise<SaveTransactionResponse>} The update response
  * `@throws` {Error} If the API request fails
  */
app/pages/TransactionStatus.tsx (1)

372-380: Inconsistent handling: uses first reason only, while saveTransactionData joins all reasons.

This uses only the first cancellation reason for analytics, whereas saveTransactionData (lines 225-228) joins all reasons. While this may be intentional (keeping analytics concise), consider aligning the approach or adding a comment explaining the difference.

Option: Use consistent handling or document the difference

If intentional, add a clarifying comment:

         } else if (transactionStatus === "refunded") {
+          // Use first reason for concise analytics tracking (full list stored in DB)
           const reason =
             orderDetails?.cancellationReasons?.length &&
             orderDetails.cancellationReasons[0]
               ? orderDetails.cancellationReasons[0]
               : "Transaction failed and refunded";
app/context/TransactionsContext.tsx (1)

139-153: Good change detection logic; minor redundancy on line 150.

The refundReasonChanged check correctly prevents unnecessary backend calls when the reason hasn't changed.

Line 150: refundReason ?? undefined is redundant since refundReason is already typed as string | undefined.

Simplify null coalescing
             await updateTransactionDetails({
               transactionId: tx.id,
               status: orderData.status,
               txHash: newTxHash,
-              refundReason: refundReason ?? undefined,
+              refundReason,
               accessToken,
               walletAddress,
             });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Display Refund Reason on Receipt

2 participants

Comments