2 min readAug 11, 2026by jakub
Changelog
Current version: 1.0.0
1.0.0 — 2026-07-30
First release, incorporating the full transactional-hardening review cycle.
Run bin/magento setup:upgrade, flush all caches AND restart
PHP-FPM/opcache before serving traffic — postings verify that their
idempotency key persisted and refuse to commit against a stale schema.
Schema (additive)
qoliber_rewardpoints_transaction.idempotency_key(unique) — at-most-once business postings, enforced by the database.qoliber_rewardpoints_transaction.gross_amount— signed processed points next to the grantedamount(cap/clamp forfeits are visible and can never be re-awarded).qoliber_rewardpoints_balance.points_debt— refund revocations survive a zero balance; future credits settle debt before becoming spendable.- New transaction status
4(RESERVED) and actionpending_marker. - Point-value columns are
BIGINT(amount,remaining,gross_amount,balance,pending_balance,points_debt,lifetime_earned) — no practical accumulation ceiling.
Behaviour
- Spent points are RESERVED before payment placement: an insufficient balance aborts checkout before any payment call; failed submits release the reservation; an hourly cron resolves stranded reservations by their order's fate (existing order → settle, cancelled/missing → release).
- Every order/invoice/creditmemo/promo posting carries an idempotency key; replayed or concurrent events post exactly once.
- Expiry debits exactly the surviving overdue remainders under the balance lock; reminder emails aggregate current remainders per customer.
- Dynamic-price bundles earn through their child rows (checkout-time safe).
- CSV import: complete prevalidation (all-or-nothing), batch/row idempotency
(re-running a file resumes), notifications off,
--dry-runon the CLI; imports post under theimportledger action (previouslyadmin_adjust), and enforce the same maximum-adjustment magnitude bound as manual adjustments. - Reconciliation understands reservations and points debt;
--fixre-derives each balance under its row lock, and also reports FIFO-remainder drift. - Order cancellation compensates (restores spent points, cancels the pending
earn) only AFTER the cancellation is durably committed, via an
OrderManagementInterface::cancelafter-plugin. A failed order save can no longer leave an active order with points already refunded; a compensation failure surfaces and is reported by reconciliation as an unrestored cancelled order. - Concurrency-safe reward caps: the referral signup daily cap runs under a
per-advocate lock, and the once-per-product review award is keyed on
(customer, website, product)so the unique index enforces it atomically. - Reward-points history resolves the pooled balance owner, matching the balance read — B2B shared pools see the shared ledger, not just the acting member's rows.
Packaging
qoliber/reward-points-graph-qlrequires core^1.0and the GraphQL modules whose schema types it extends.- Uninstall removes the invoice/creditmemo columns.