feat: Implement return and refund functionality in commerce module
CI / test (push) Successful in 10m27s
CI / test (push) Successful in 10m27s
- Added return request handling in return.controller.js - Implemented webhook handling for PayHere payments in webhook.controller.js - Created models for coupon redemptions, invoices, orders, order items, payments, payment attempts, payment webhook events, refunds, return items, and return requests. - Developed services for order management, payment processing, refunds, and returns. - Introduced validation schemas for payment and return requests. - Created migration scripts for new database tables related to orders, payments, refunds, and returns. - Added unit tests for order state transitions and PayHere provider functionality.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
# Orders and Payments API
|
||||
|
||||
All `/api/v1` customer endpoints derive ownership from authentication.
|
||||
|
||||
## Orders
|
||||
|
||||
- `POST /orders/from-checkout` converts an owned READY checkout. Conversion locks the checkout, verifies ACTIVE reservations, copies immutable snapshots, converts the cart, and is idempotent by unique checkout ID.
|
||||
- `GET /orders` and `GET /orders/:id` provide owner-scoped history/detail.
|
||||
- `POST /orders/:id/cancel` releases unpaid reservations. Paid orders require an explicit refund.
|
||||
- Admin: `GET /admin/orders`, `GET /admin/orders/:id`, cancel, and mark-processing action endpoints.
|
||||
|
||||
Legal transitions are centralized. Payment, order, and fulfillment status are separate.
|
||||
|
||||
## Payments and webhooks
|
||||
|
||||
- `POST /orders/:id/payment`, `GET /orders/:id/payment`
|
||||
- `POST /payments/webhooks/payhere` is unauthenticated at the session layer but requires the PayHere merchant hash.
|
||||
|
||||
Online browser redirects are never authoritative. A verified webhook must match local payment reference, currency, and DECIMAL amount. Unique provider event IDs make retries idempotent. A first successful event consumes each reservation once, records coupon redemption, marks payment/order paid, and issues invoice metadata. Failure does not consume inventory.
|
||||
|
||||
PayHere configuration uses `PAYHERE_MERCHANT_ID`, `PAYHERE_MERCHANT_SECRET`, and notify/return/cancel URLs. Stripe has an explicit disabled adapter until its official SDK and webhook secret are configured. No raw card or provider secret is accepted or returned.
|
||||
|
||||
## Invoices
|
||||
|
||||
- `GET /orders/:id/invoice` is owner-scoped.
|
||||
|
||||
Invoice numbers use the locked ReferenceNumber sequence. Invoice metadata is created once per paid order. PDF generation is reserved for the existing document worker integration; no second PDF/storage subsystem was introduced.
|
||||
|
||||
## Refunds
|
||||
|
||||
- `POST /admin/orders/:id/refunds` requires `payments.refund` and `Idempotency-Key`.
|
||||
|
||||
Requested item quantities and captured totals are locked and validated. A refund never restocks inventory automatically. Provider refund execution remains disabled until provider API credentials/workflows are validated.
|
||||
|
||||
## Returns
|
||||
|
||||
- Customer: `POST /orders/:orderId/returns`, `GET /returns`, `GET /returns/:id`.
|
||||
- Admin: list, approve, reject, mark-received, and complete actions.
|
||||
|
||||
The return window uses `RETURN_WINDOW_DAYS` (default 30). Quantity cannot exceed the remaining purchased quantity. Only accepted RESTOCKABLE items are added through the inventory service; damaged/non-restockable items are not. EXCHANGE records intent only.
|
||||
|
||||
Business credit purchasing is intentionally disabled: no locked credit ledger was added without an approved accounting policy. Delivery, loyalty, support AI, and analytics are outside Phase 7.
|
||||
@@ -417,3 +417,6 @@ Date: 2026-09-03. Inventory/reservation foundations, business pricing, promotion
|
||||
## Phase 6 Completion Update
|
||||
|
||||
Date: 2026-09-03. Module 06 is 91%, Module 08 is 84%, and Module 07 is revised to 86%. Authenticated cart is 92%, wishlist 92%, shipping 86%, checkout 88%, and reservation integration 90%. Nine models, a forward-only migration, owner-scoped shopping APIs, permission-protected shipping administration, server-authoritative totals, atomic inventory reservation composition, idempotent checkout creation, and bounded expiry/cancellation release are implemented. Verification passes 20 suites/95 tests and 258 JavaScript syntax checks. The migration was not executed. Before Phase 7, staging must precheck legacy shopping/shipping tables and address/currency compatibility, seed shipping configuration/permissions, apply migrations, and validate real multi-connection InnoDB concurrency plus multi-instance expiry behavior.
|
||||
## Phase 7 Completion Update
|
||||
|
||||
Date: 2026-09-09. Module 09 is 86%, Module 10 is 76%, and Module 13 is revised to 82%. Orders are 90%, payments 78%, invoices 72%, refunds 68%, returns 82%, coupon redemption 80%, and verified-purchase reviews 90%. Eleven commerce models, a forward-only migration, transactional checkout conversion, owner/admin APIs, explicit state machines, verified/idempotent webhook processing, payment-time inventory consumption, invoice sequencing, itemized refund validation, RMA handling, and return-only restocking were added. Migration and real provider/MySQL/document-worker validation remain staging requirements. Module 16 AI Customer Support Chatbot is intentionally excluded from this backend and planned as a separate service.
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
# ZUMRI Phase 7 Orders and Payments
|
||||
|
||||
## Objective
|
||||
Convert checkout snapshots into durable orders and establish authoritative payment, invoice, refund, and return lifecycles without delivery or rewards.
|
||||
|
||||
## Existing Components Reused
|
||||
Checkout snapshots, inventory reservations, pricing money helpers, coupons, ReferenceNumber, document infrastructure, audit queue, authentication, and permissions.
|
||||
|
||||
## Order Architecture
|
||||
Order/payment/fulfillment states are independent. Commercial and address/shipping details are immutable snapshots.
|
||||
|
||||
## Checkout Conversion
|
||||
The centralized transaction locks an owned READY checkout, verifies reservations, returns any existing order, copies items, and converts checkout/cart.
|
||||
|
||||
## Order State Machine
|
||||
Explicit transition sets reject illegal terminal-state transitions and arbitrary status patches.
|
||||
|
||||
## Order Snapshots
|
||||
Items retain product/variant IDs, reservation key, SKU, names, quantity, unit price, discount, total, currency, and limited metadata.
|
||||
|
||||
## Payment Architecture
|
||||
Payments retain immutable attempts. Only server/provider reconciliation changes authoritative financial state.
|
||||
|
||||
## Provider Adapters
|
||||
Generic payment logic delegates verification/parsing/initiation/refund/status behavior to provider modules.
|
||||
|
||||
## PayHere
|
||||
Merchant secrets are environmental. Browser redirects are non-authoritative; the notify hash, reference, amount, and currency must validate.
|
||||
|
||||
## Stripe
|
||||
An explicit disabled boundary is present. Integration awaits official SDK/configuration rather than accepting unverified callbacks.
|
||||
|
||||
## Webhook Verification
|
||||
Invalid signatures, currencies, amounts, and references are rejected.
|
||||
|
||||
## Webhook Idempotency
|
||||
Unique provider/event records and locked payment/order rows ensure duplicate success cannot repeat side effects.
|
||||
|
||||
## Inventory Consumption
|
||||
Checkout reserves; confirmed online payment consumes. Failed payment does not consume. Unpaid cancellation releases.
|
||||
|
||||
## Payment Reconciliation
|
||||
Webhook persistence supports reconciliation, but remote status polling is deferred until the enabled provider supplies a validated status API.
|
||||
|
||||
## Business Credit
|
||||
Disabled pending an approved immutable credit-ledger/accounting policy; concurrent unsafe balance mutation was not introduced.
|
||||
|
||||
## Invoice Architecture
|
||||
One invoice per order uses transaction-safe ReferenceNumber sequencing. The existing document worker remains the PDF integration point.
|
||||
|
||||
## Refund Architecture
|
||||
Idempotent itemized requests validate remaining quantity and captured amount. Provider processing is separate from request approval.
|
||||
|
||||
## Return/RMA Architecture
|
||||
Owner-scoped requests and explicit admin transitions track physical receipt/condition independently from refunds.
|
||||
|
||||
## Exchange Boundary
|
||||
EXCHANGE is recorded as resolution intent; no replacement order or fulfillment is created.
|
||||
|
||||
## Coupon Redemption
|
||||
Redemption occurs once on confirmed payment while the coupon row is locked. Full-refund restoration is deferred by policy.
|
||||
|
||||
## Verified Purchase Reviews
|
||||
Review creation derives verification only from an actual paid order containing the product.
|
||||
|
||||
## Permissions
|
||||
Orders read/manage/cancel, payments read/manage/refund, invoices read, and returns read/manage were added.
|
||||
|
||||
## Audit Events
|
||||
Order, payment creation, cancellation, refund request, return lifecycle, and admin operations reuse sanitized Phase 2 activity logging.
|
||||
|
||||
## Database Changes
|
||||
Forward-only migration `20260909070000` creates eleven commerce tables with unique references/idempotency and lifecycle indexes.
|
||||
|
||||
## Tests
|
||||
Unit tests cover order transitions, PayHere signature validation, forged notifications, secure return/refund inputs, and configurable return eligibility.
|
||||
|
||||
## Remaining Known Issues
|
||||
Real PayHere, refunds, document generation, migration, webhook delivery, and MySQL concurrency were not exercised. Refund approval/provider completion APIs and reconciliation polling require provider policy/configuration.
|
||||
|
||||
## Phase 8 Prerequisites
|
||||
Apply all migrations on restored staging, seed permissions, configure/validate PayHere sandbox, test concurrent duplicate webhooks, final-stock payment consumption, coupon quotas, invoice jobs, refund callbacks, and return restocking.
|
||||
|
||||
Module 16 AI Customer Support Chatbot is intentionally excluded and planned as a separate service.
|
||||
Reference in New Issue
Block a user