.. include:: ../variables.rst .. _challenges-points-ledger: Points Ledger ============= The Points Ledger is |APPNAME|'s permanent record of every point transaction in the system. Each row is an atomic, immutable event -- the current balance for any participant is simply the sum of their ledger rows. .. figure:: /images/challenges/lightmode/points-ledger.png :align: center :width: 100 % |br| Opening the page ---------------- Left menu: :blue:`Challenges` ▸ :blue:`Points Ledger`. Reading the table ----------------- Each row represents one point transaction: .. list-table:: :header-rows: 1 :widths: 20 80 * - Column - Meaning * - **Date** - When the transaction was recorded. * - **Challenge** - The challenge that awarded the points, or blank for manual adjustments / redemptions. * - **Participant Type / ID** - Who received (or spent) the points: 0 = Facility, 1 = Unit, 2 = Auditor, 3 = HCP Type, 4 = Team. * - **Points** - Signed integer. Positive = earned or adjusted up, negative = redeemed, expired, or adjusted down. * - **Notes** - Free-text comment. For close-driven grants this is the challenge name. For redemptions it's whatever the admin typed at redemption time. .. figure:: /images/challenges/lightmode/points-ledger-row.png :align: center :width: 80 % |br| Reasons ------- The ``reason`` column distinguishes four kinds of transaction: .. list-table:: :header-rows: 1 :widths: 20 20 60 * - Code - Name - When it's used * - ``0`` - Earned - Written on challenge close for every winner. Always positive. Unique per (challenge, participant). * - ``1`` - Redeemed - Written when an administrator spends a participant's points via the redemption endpoint. Always negative. * - ``2`` - Expired - Written when a points-expiry policy ages out old points. Always negative. * - ``3`` - Adjusted - Manual correction by an administrator. Can be positive or negative (e.g. to restore points that were redeemed in error, or to deduct for a rules violation). Pagination and filtering ------------------------ * **Participant type** dropdown filters to a single type. * Table is paginated. Use :blue:`Load More` at the bottom to append more rows. The header shows ``N of M`` so you always know when you're looking at a truncated view. * The **Total Points** chip shows the sum of *all* points for the current filter, not just the visible rows. Redeeming points ---------------- An administrator can spend a participant's balance via ``POST /challenges/points/spend``: .. code-block:: none POST /challenges/points/spend?participanttype=2&participantid=42&points=25¬es=$25+gift+card The server enforces: * ``points`` must be positive (the server stores it as negative). * ``reason`` defaults to 1 (Redeemed); pass ``&reason=2`` to expire or ``&reason=3`` to adjust. * The participant's current balance must be ≥ the requested amount. A lower balance returns HTTP 409 with the current balance in the error message. A successful response returns ``{"success":true,"newbalance":}``. Auditing balance history ------------------------ To see the full history for one participant, use the :ref:`challenges-participant-profile` page. It shows the lifetime earned, lifetime spent, current balance, all badges, active challenges, and the 20 most recent ledger rows on a single screen.