EnakPoint can only be redeemed for vouchers now: it can no longer pay for
orders and is never cashed out (docs/enakgame-prd.md §3.2, EG-001,
EG-002). No order was ever paid with EnakPoint, so there is no data to
move.
Removed:
- POST /customer/wallet/payment-code, POST /customer/orders/:id/pay-with-points
and GET /orders/:id/point-payment/preview, with their processors,
repositories, services, handlers and tests.
- The point payment method type: paying, splitting and refunding with it,
the outlet filter on the method list, and the system-method guard.
- points and payment_code on CreatePayment; points_used and point_value
on payments; accepts_point_payment on the customer outlets.
- The outlet point_payment settings. A PUT that still sends them is
rejected as an unknown field.
- The EnakPoint split in the payment method analytics.
- PAYMENT and PAYMENT_REFUND from the wallet type rules. Tests that used
them as a generic EnakPoint debit use REWARD_REDEEM.
- The EnakPoint-paid part from the earning basis, which is
subtotal − discount again.
Migration 000102 drops the trigger, the point methods and their index,
the payments columns, and the outlet settings, and restores the method
type CHECK without point. payments.payment_method_id is ON DELETE
RESTRICT, so it fails rather than lose a payment made with EnakPoint.
The integration docs list the removed endpoints and fields, and the
EnakPoint & EnakCoin PRD and tasks note what is superseded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds earning at payment time (docs/prd-point-coin.md F3, PC-203).
An order becomes fully paid through UpdateOrder, CreatePayment and both
kinds of split bill. All of them now go through one OrderProcessorImpl
hook, onOrderPaid, called after the payment has committed; for
CreatePayment that is after its transaction, not from updateOrderStatus
inside it. The hook runs detached from the caller's transaction and from
the request being cancelled, and it runs synchronously so the order
response can show what was earned.
EarningProcessor.EarnForOrder skips orders that are not paid, are void,
have no customer, or whose customer is the walk-in customer or inactive.
It computes the earning with CalculateEarning, subtracting any part paid
with EnakPoint (none until phase 3), and credits each currency through the
wallet engine as EARN with key earn:{order_id}:{currency} and the settings
snapshot in metadata. A repeat, even concurrent, credits nothing more.
OnOrderPaid never fails the payment: errors and panics are logged.
EarningBackfillJob is the safety net: every 30 minutes it earns for orders
paid in the last three days that have no EARN row. It only looks at
outlets with earning switched on and pages by (updated_at, id), so orders
that correctly earned nothing cannot starve the ones that were missed.
Lots from earning never expire until the expiry model is decided (F12,
note N4). Adds the point payment method type constant, not yet accepted as
a payment method.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>