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.
|
||||
Reference in New Issue
Block a user