Prepaid Cards
The Prepaid Cards page lets you mint batches of recharge cards and redeem them against subscribers. Each card is a code + PIN pair that carries a monetary value, a number of days, an optional service, and an optional quota refill. Redeeming a card extends the subscriber’s expiry, optionally switches their service, optionally resets their quota counters, and records a transaction.
This is the page to open when an ISP sells physical/printed recharge cards through shops, or when a reseller wants to top customers up without touching their balance directly.
How to get here
Section titled “How to get here”Sidebar → Prepaid Cards. Direct URL: /prepaid.
Requires prepaid.view. Resellers see only cards belonging to their own reseller (and their sub-resellers’) unless they have prepaid.view_all, in which case they see every card.
Layout
Section titled “Layout”| Section | What it shows |
|---|---|
| Toolbar | ”Prepaid Cards” title, Redeem Card button, Generate Cards button |
| Batches overview | Up to 4 batch stat-cards: batch ID, active count, total count, used count, and a Delete Unused button per batch |
| Filter bar | Status dropdown (All / Available / Used), Batch dropdown (All Batches or a specific batch) |
| Cards table | Code, PIN, Value, Days, Service, Status, Batch, Actions |
| Pagination | Server-side, shown when there is more than one page |
The cards table is paginated server-side: 25 cards per page by default, capped at 100. Cards are listed newest-first (created_at DESC).
Generating a batch
Section titled “Generating a batch”Click Generate Cards to open the generate modal. Cards are always created as a batch — even a batch of one. The batch is stamped with an auto-generated ID of the form BATCH-<unix-timestamp>, and each card is numbered within the batch.
The generate form sends these fields:
| Field | Meaning | Notes |
|---|---|---|
| Count | How many cards to mint | Required. Must be between 1 and 1000. |
| Days | Days added to the subscriber’s expiry on redemption | Optional. 0 = no expiry change. |
| Service | Service the subscriber is switched to on redemption | Optional. “No service change” leaves the subscriber’s service untouched. |
| Prefix | Prefix prepended to each generated code | Optional, up to 6 characters, upper-cased in the UI. |
| Value | Monetary value recorded on the redemption transaction | Sent by the API; defaults to 0. |
| Quota refill | Whether redemption resets quota usage | Sent by the API; any value greater than 0 triggers a quota reset on redemption. |
| Code length | Length of the generated code | Below 8 it falls back to 12. |
| PIN length | Length of the numeric PIN | Below 4 it falls back to 4. |
Codes are random hex (optionally with the PREFIX- in front); PINs are random digits. Both are generated with a cryptographic random source.
On success the API returns the new batch_id, the count, and the full list of generated cards (codes and PINs included) so they can be printed or exported.
Redeeming a card
Section titled “Redeeming a card”Click Redeem Card to open the redeem modal. It asks for:
- Card Code — the card’s code.
- PIN — the card’s PIN.
- Subscriber ID — the numeric ID of the subscriber to apply the card to.
The redeem handler looks the card up by exact code + PIN. If no card matches, it returns “Invalid card code or PIN”.
Before applying anything it runs these checks, in order:
- Already used — if
is_usedis true, redemption is rejected (“Card has already been used”). - Inactive — if
is_activeis false, redemption is rejected (“Card is not active”). - Expired — if the card has an expiry date and it is in the past (in the tenant’s timezone), redemption is rejected (“Card has expired”).
- Card ownership — a reseller may only redeem their own cards (or a sub-reseller’s), unless they have
prepaid.view_all. Otherwise “Access denied”. - Subscriber found — the target subscriber must exist.
- Subscriber ownership — the target subscriber must be inside the caller’s reseller tree.
If all checks pass, redemption runs as a single database transaction:
- The card is claimed with a guarded update (
WHERE is_used = false). If a concurrent request already claimed it, the claim affects 0 rows and the whole redemption aborts with “Card has already been used” — so the grant can never apply twice. - The subscriber is updated based on what the card carries:
- Days — if the card has days, they are added to the subscriber’s expiry. If the current expiry is already in the past, the days are added from “now” instead.
- Service — if the card has a service, the subscriber is switched to it.
- Quota refill — if the card has a quota refill, the subscriber’s
daily_quota_usedandmonthly_quota_usedare reset to0.
- A transaction record is created (type “prepaid card”) for the card’s value, attributed to the card’s reseller and linked to the subscriber, with a description noting the card code.
On success the response echoes the card’s value, days, and quota.
Statuses
Section titled “Statuses”Each card carries two flags that drive its status:
| Flag | Meaning |
|---|---|
is_used | Set to true the moment a card is successfully redeemed, along with the redeeming subscriber and the redemption time. |
is_active | Whether the card is enabled. New cards are active. An inactive card cannot be redeemed. |
In the table the Status column shows:
| Badge | Condition |
|---|---|
| Available | is_used = false (green badge) |
| Used | is_used = true (gray badge) |
The Status filter maps Available → is_used = false and Used → is_used = true.
Deleting cards
Section titled “Deleting cards”There are two ways to remove cards, and both only ever touch unused cards:
- Delete a single card — the per-row Delete button (shown only for available cards). A used card cannot be deleted (“Cannot delete used cards”).
- Delete unused in a batch — the Delete Unused button on a batch stat-card removes every unused card in that batch and reports how many were deleted. Used cards in the batch are left intact.
This keeps redeemed cards on record (with their value transaction) while letting you clear out unsold stock.
Batches overview
Section titled “Batches overview”The batch stat-cards summarise each batch:
- Total — every card in the batch.
- Used — cards where
is_used = true. - Active — cards that are unused (
is_used = false) and enabled (is_active = true) — i.e. still sellable/redeemable.
The page also exposes a batches list used to populate the Batch filter dropdown.
Permissions
Section titled “Permissions”| Permission | Effect |
|---|---|
prepaid.view | Page loads; list cards, batches, and a single card. |
prepaid.view_all | Reseller sees every card and can redeem any card, not just their own tree’s. |
prepaid.create | Generate new card batches. |
prepaid.edit | Redeem a card against a subscriber. |
prepaid.delete | Delete a single unused card or all unused cards in a batch. |
Admins have all permissions. A reseller with no permission group assigned also has all permissions (backward compatibility); a reseller with a group only has what the group grants.
Related pages
Section titled “Related pages”- Subscribers — redemption applies to a subscriber by ID; find the ID here.
- Services & Plans — a card can switch the subscriber to a chosen service on redemption.
- Billing & Invoices — each redemption writes a “prepaid card” transaction for the card’s value.
- Resellers — cards are scoped to the reseller tree;
prepaid.view_allwidens that scope. - FUP Counters — a card’s quota refill resets the subscriber’s daily and monthly usage.