From 8d574ba7ff4a3e65eff9c982615fa32d1ab1b3ac Mon Sep 17 00:00:00 2001 From: leonardo1229 Date: Fri, 20 Mar 2026 06:06:20 -0500 Subject: [PATCH 1/2] feat: add refund module (TC-4) --- src/payments/refund.js | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/payments/refund.js diff --git a/src/payments/refund.js b/src/payments/refund.js new file mode 100644 index 0000000..2b0f926 --- /dev/null +++ b/src/payments/refund.js @@ -0,0 +1,49 @@ +/** + * refund.js — Refund processing + */ + +const REFUND_REASONS = ['duplicate', 'fraudulent', 'customer_request', 'product_issue']; +const REFUND_STATUSES = ['pending', 'approved', 'rejected', 'processed']; + +function createRefund({ orderId, amount, reason, requestedBy } = {}) { + if (!orderId) throw new TypeError('orderId is required'); + if (typeof amount !== 'number' || amount <= 0) throw new RangeError('amount must be a positive number'); + if (!REFUND_REASONS.includes(reason)) throw new RangeError(`reason must be one of: ${REFUND_REASONS.join(', ')}`); + if (!requestedBy) throw new TypeError('requestedBy is required'); + + return { + id: `ref_${Date.now()}`, + orderId, + amount: parseFloat(amount.toFixed(2)), + reason, + requestedBy, + status: 'pending', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; +} + +function approveRefund(refund, approvedBy) { + if (refund.status !== 'pending') throw new Error(`Cannot approve a refund in status: ${refund.status}`); + return { ...refund, status: 'approved', approvedBy, updatedAt: new Date().toISOString() }; +} + +function rejectRefund(refund, rejectedBy, rejectionNote = '') { + if (refund.status !== 'pending') throw new Error(`Cannot reject a refund in status: ${refund.status}`); + return { ...refund, status: 'rejected', rejectedBy, rejectionNote, updatedAt: new Date().toISOString() }; +} + +function processRefund(refund) { + if (refund.status !== 'approved') throw new Error('Only approved refunds can be processed'); + return { ...refund, status: 'processed', processedAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; +} + +function isFullRefund(refund, originalAmount) { + return refund.amount >= originalAmount; +} + +function summarize(refund) { + return `Refund ${refund.id}: $${refund.amount.toFixed(2)} for order ${refund.orderId} [${refund.status}] — ${refund.reason}`; +} + +module.exports = { createRefund, approveRefund, rejectRefund, processRefund, isFullRefund, summarize, REFUND_REASONS, REFUND_STATUSES }; From 7c4134ae59d5e7013345ad8e3072a294082ff8d5 Mon Sep 17 00:00:00 2001 From: leonardo1229 Date: Fri, 20 Mar 2026 06:07:26 -0500 Subject: [PATCH 2/2] updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b42602..da55378 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,3 +12,5 @@ All notable changes to this project will be documented in this file. - Config module: database configuration by environment - Production config YAML - Watchflow governance rules + +tried tc-4 \ No newline at end of file