Point Currencies and Balances
GadgetSphere’s members collect one currency, GSPTS, worth RM 1.00 per 100 points at the counter.
A second currency is possible — the record allows any number — but every earning rule, every
balance and every redemption is per currency, so add one only when you want a wallet the first
one must not mix with.
The currency record
PTS CCY Module in Membership Admin writes
bl_crm_membership_points_currency: a code, a name, a conversion rate, a point-to-point cross-over
conversion flag and a status. PTS to CCY Config writes bl_crm_membership_points_to_currency_rate:
one point currency, one money currency, a rate — the number the till uses when it turns points into
ringgit. A PTS to PTS Config route exists for point-currency-to-point-currency rates; its menu
entry is commented out, so there is no working conversion between currencies today.
Where points come from
Every earning is a row in bl_crm_membership_points_txn_line with a source. The sources the
backend has:
| Source | What creates the line |
|---|---|
| A sales document at the counter or on account | When a document of the company’s configured type reaches the configured posting status and carries a member, each line that has a point_amount and a point_currency becomes one REWARD (positive) or REDEEM (negative) line. The defaults are INTERNAL_SALES_ORDER at FINAL; a company overrides them in its MEMBER_POINT configuration (set through the company API — no screen). The point amount on the line comes from a Pricebook Point treatment |
| An e-commerce order | CP_COMMERCE_MEMBER_POINTS_UPDATE_PROCESSOR and BLG_MEMBER_POINT_SCHEDULED_REWARD_PRIMARY_PROCESSOR run the same document check on cart orders and write the same lines |
| A Commission Scheme | The scheduled membership-points run evaluates active schemes against the company’s award document type and turns the Membership Points treatment into lines, valid from the document date for the treatment’s validity days |
| A scanned third-party receipt | OCR Cash Bill evaluates a price book’s Point treatment against the extracted lines and writes lines |
| A person | Add Point Adjustment on the member form (source ADMIN_MANUAL_POINTS_ASSIGNMENT, positive or negative, with an item, a validity window and a DISPLAY / HIDDEN flag) and Upload Member Point Transaction from CSV |
| A birthday | MEMBER_BIRTHDAY_GIFT_PROCESSOR, when scheduled with gift_type = POINTS: a point amount in a currency, valid for points_validity_in_months, to the classes in member_class_guids |
If the document is later voided, VoidMembershipPointsProcessor deletes the lots and contra rows
its lines created, and if the member’s balance is now short of what was voided it writes an
adjustment line for the difference.
Line, lot, balance
Three tables answer three different questions:
| Question | Table | How it is kept |
|---|---|---|
| What happened? | bl_crm_membership_points_txn_line | One row per earn, redemption, expiry or adjustment: txn_type REWARD, REDEEM, EXPIRY (and CF / BF written by recalculation), points_value, date_valid_from / date_valid_to, the document and line it came from, display_type |
| How many are still valid, and until when? | bl_crm_membership_points_ctrl_acc | One row per earning lot with balance_amount, date_start, date_end and next_expiry_date_check; each redemption is recorded against the lots it drew down in bl_crm_membership_points_ctrl_contra_details |
| What is the total? | bl_crm_membership_points_current_balance | One row per member and currency with point_balance, recomputed by the update processor after every line |
The API exposes the difference: GET …/membership-points-txn/balance/{card_no} returns the
valid balance from the lots, GET …/current-balance/query the running total. A member’s
Point Transaction tab shows the lines; the Points Expiry tab shows the lots. When the two disagree,
the recalculation queue in Membership Admin rebuilds lots and balance from the lines.
Nothing posts to the ledger
ServerDocTypes declares INTERNAL_MEMBERSHIP_POINT_REWARD(0,0) and
INTERNAL_MEMBERSHIP_POINT_REDEEM(0,0) — no amount, no quantity — and JournalPostingTypeHandler
has no membership entry. Earning 120 points on a RM 1,200 laptop changes three membership tables and
no GL account. Redeeming 2,000 points on the next bill reaches the ledger only as part of that cash
bill — a points settlement line, or a points-discount line using the MEMBER_POINT_DISCOUNT item —
and that posting is POS General’s, not this module’s.
If GadgetSphere’s accountant wants a points liability on the balance sheet, it is a manual journal
from the balance report, not something the module maintains.
Related
- Points expiry — what happens to a lot on its end date.
- Points setup — the currency and the rate, in order.