Voucher Management Applet V2
Define the vouchers your counter and web store accept, and issue a ticket for each serial number. A voucher posts nothing of its own; it reaches the ledger only through the sales document it is used on. Nothing expires tickets on a schedule, and redemption does not check the dates, so a ticket past its date still reads as valid.
Overview
The Voucher Management applet is where a marketing or customer-service user defines vouchers — a settlement voucher worth a fixed amount, a discount voucher with a treatment formula, a rewards voucher that awards points, or a product voucher — and the tickets (serial numbers) issued under each one. It generates, imports, assigns, cancels and traces serials, keeps the scan log of ticket-based events, runs recurring voucher templates on a schedule, and links vouchers to CP Commerce websites. The applet is master data: the counter and the storefront redeem a ticket against a sales document, and the ticket’s status changes on that document’s back.
Where it fits
| Direction | Applet | How it connects |
|---|---|---|
| Upstream | Doc Item Maintenance | A Voucher item (COUPON item type) records voucher stock in / out; its Voucher Details tab links the item to a voucher header. The item’s abbreviation / prefix groups items for this applet |
| Upstream | Membership Admin | Member classes and member labels picked by the Doc Hdr rules; the MEMBER_BIRTHDAY_GIFT_PROCESSOR can assign vouchers (vouchers_to_assign) to members on their birthday |
| Upstream | Organisation, Customer | Company and branch rules; a ticket is assigned to an entity, a membership, a login subject or a basic contact |
| Downstream | POS General, Sales Invoice (Internal) | The counter looks a serial up, lists the customer’s available and redeemable vouchers, and settles or discounts the bill with them (VOUCHER / COUPON settlement types; POS_VOUCHER_INVENTORY changes how the counter tests a scanned serial — see Settings in other applets) |
| Downstream | CP Commerce Admin | The website’s Voucher Management tab and this applet’s Website Link tab edit the same website–voucher links; the storefront offers the vouchers linked to it, and a signed-in customer sees their own |
| Downstream | Sales Report | Voucher Redemption report — redeemed serials by date, voucher, branch, document and entity |
| Sibling | Scheduler | Where the coupon processors (serial generation, recurring creation) are put on a crontab |
Screens and menus
Route root: applets/tnt/wavelet/voucher-management-applet-v2/. Sidebar: Voucher, Ticket, Scanned Event, Recurring Voucher, Import Tickets; Settings: Field Settings, Default Selection, Webhook, Feature Visibility, permission-set / user / team / role permission listings; Personalization: Default Selection, Sidebar.
Screenshots were removed from this page: every capture showed a real person’s photo avatar and staff names used as voucher codes, so the 29 images are quarantined; replacements need a clean demo tenant.
Voucher
Voucher Listing → + opens Voucher Create with two tabs: Details and, for DISCOUNT and REWARDS, Treatment Value (DISCOUNT shows the Product and For All sub-tabs; REWARDS shows For All only; SETTLEMENT hides the tab). Rules, images, tickets, website links and audit need a saved voucher: reopen it from the listing.
Voucher Edit has seven tabs, in the order set under Default Selection: Details, Treatment Value (hidden for settlement vouchers), Apply Rules, Image, Ticket Management, Website Link, Audit. Ticket Management, Website Link and Audit load lazily.
- Apply Rules has three builders — Rules - Doc Hdr, Rules - Multi Line, Rules - Single Line — each with a Rules Logic (And / Or) and a Negation Logic (Enabled / Disabled) selector above the rule grid.
- Ticket Management shows counts of vouchers generated, assigned and redeemed, then the ticket grid: Serial Number, Assignee, Assigned To, Customer Code, Redeem Invoice No, Redeem Invoice Date, Validity, Cancellation, Redeemable Status, Redeemable Date From / To, Created Date, Modified Date. + opens a three-tab dialog: Generate Ticket (Max Quantity), Import Ticket, Ticket Files Listing. Opening a serial shows voucher code and name, serial number, softpin, assignment and redemption status, dates, and Cancel / Activate buttons.
- Website Link lists linked website code, name and modified date, with add and remove.
- Audit lists date, user, action and event code.
- Print batch-prints selected vouchers through the sales-invoice Jasper endpoint (
gen-doc/internal-sales-invoices/batch-print-multi-format-jasper-pdf).
Ticket
Ticket Listing columns: Voucher Code, Voucher Name, Serial Number, Redeemed Branch, Redeemable Status, Redeemed Date, Assignment Status, Assigned To, Validity, Cancellation, Created Date, Modified Date. Ticket Create: select a voucher (code and name fill read-only), enter the Serial Number and set Assignment, Validity, Cancellation and Redeemable status. Ticket Edit has Details (adds read-only URL Key, Activation Pin, Created / Modified By and Date) and Ticket History — the serial’s stock trace: Serial Number, Location, Code, Transaction Description, Transaction Date, Document, Server Doc Type, Entity, Reference, Quantity, Amount, MA Cost, Posting Status, Remarks. The history remaps backend descriptions to Stocked in, Awarded to customer and Redeemed.
Scanned Event
Listing: Serial Number, Item Name, Email, Phone, Scan Date, Reward Points, User Type, Status, Remarks, Shipping Address, Attachment. Opening a row shows Details (serial, item, contact details, reward points, user type, status, remarks, activation pin, audit fields; Shipping Address editable for customer-type rows) and Attchment (sic) — image records with created / updated dates.
Recurring Voucher
A voucher template meant to be turned into vouchers on a schedule — today the scheduled run creates none (see Recurring vouchers under Lifecycle). Create has Details and Treatment Value; voucher types SETTLEMENT, DISCOUNT, REWARDS; quantity types FIXED and DYNAMIC only. A Recurring ? checkbox reveals a recurrence editor that stores an RRULE; Start Date and End Date bound it. The create form has no Event Period, Redemption Period or website picker. Edit has Details, Treatment Value, Apply Rules, Image — no Ticket Management, Website Link or Audit.
Import Tickets
Upload Master Data: drag and drop a .csv, preview, ADD; a Sample Format link downloads the template (the file is named MasterData_Upload_Category.csv, a name copied from another applet’s import). The listing shows File Name, File Size, Format, Status, Process Status, User Error Message, dates and creator. Opening a file shows Main (file type, name, size, import format, process status, status, error message) and Checking — one row per line with Voucher Code, Serial No, Soft Pin, Validity / Assignment / Redemption / Cancellation Status and a Short Error Message, each with its own error column.
Configuration
Before you can use it
| Prerequisite | Where | Why |
|---|---|---|
| Company, branch, location | Organisation | Company and Branch rules; Default Selection branch / location |
A COUPON-type item per voucher that is sold or stocked, linked on its Voucher Details tab | Doc Item Maintenance | Ticket History is the item’s stock trace; POS scans the item |
| Member classes and labels, if rules use them | Membership Admin | Doc Hdr rule types MEMBER_CLASS, MEMBER_LABEL |
| Websites, if vouchers are exposed online | CP Commerce Admin | Add Voucher To CP-Com and the Website Link tab |
VOUCHER / COUPON settlement methods per branch | POS General → Settlement Method Settings | A settlement voucher is redeemed as a settlement-method line |
| Coupon API permissions (below) with the user’s targets | Settings → permission listings | Create, update, read and softpin access |
Applet settings
Settings are applet-local: this applet’s own Field Settings screen (not the shared one) and its own Default Selection. Tenant admins change them; Personalization → Default Selection is per user.
| Setting | Screen | What it controls | Default | Proofs |
|---|---|---|---|---|
ENABLE_MULTIPLE_TICKET | Field Settings | When off, a FIXED voucher that already has one ticket hides the + in Ticket Management | off (null) | rendered, persisted, consumed |
ENABLE_EDIT_VOUCHER_CODE | Field Settings | Voucher Code stays editable after creation; otherwise the control is disabled on edit | off | rendered, persisted, consumed |
DEFAULT_TIMEZONE | Default Selection | Timezone for the Event Period / Redemption Period pickers and the date-range rule forms | empty | shown, saved and used |
VOUCHER_DETAILS_TAB_ORDER | Default Selection (drag list) | Order of the seven Voucher Edit tabs; new tabs are appended | code order | declared, rendered, persisted, consumed |
DEFAULT_BRANCH, DEFAULT_LOCATION, DEFAULT_COMPANY | Default Selection / Personalization | Saved with the settings, and used by nothing outside the settings screens (DEFAULT_COMPANY is filled in from the branch) | empty | shown, saved — not used |
Field Settings also carries HIDE_VOUCHER_TYPE_REWARD and HIDE_VOUCHER_TYPE_DISCOUNT, which take REWARDS or DISCOUNT out of the Voucher Type list on the create form. Either one also takes out PRODUCT, because the shortened lists were written before PRODUCT existed; with both on, only SETTLEMENT is left and it is preselected. If you sell product vouchers, leave both off. The four Field Settings keys exist only on that screen. The applet’s other settings — the sales-document family (INCLUDE_*, SST / WHT, custom statuses, HIDE_UNIT_PRICE_*, HIDE_*_TAB, employee levels, PRINTABLE …) — were inherited from a document-applet template; nothing shows them and nothing uses them.
Document behaviour settings
Not applicable — vouchers are master data. Behaviour that is fixed in the code is under Lifecycle and effects.
Settings in other applets that control this applet
| Setting | Where it is set | Effect here |
|---|---|---|
Settlement methods of type VOUCHER / COUPON | POS General → Settlement Method Settings | Whether a settlement voucher can be taken at the counter |
POS_VOUCHER_INVENTORY | POS General → Field Settings | Changes the test the counter’s voucher payment applies to a scanned serial; either way only a SETTLEMENT voucher is accepted. Off: the ticket must be unredeemed, valid, uncancelled, activated on or before today, inside its redeemable dates, and assigned (or, for a voucher that allows anonymous use, not assigned). On: the ticket must have been sold — its serial is on a sales invoice or cash bill line — and not already taken as a settlement on a receipt voucher, besides being unredeemed, valid and inside its redeemable dates. Use on when you sell stocked gift vouchers over the counter and accept them later. Either way a serial that fails these tests shows only Invalid Voucher Number!, every serial in one payment must come from the same voucher, and each counts at the voucher’s face value. |
Website Voucher Management tab; hideVoucherManagement | CP Commerce Admin | Which vouchers a storefront offers; whether the tile is shown on the Webstore dashboard |
Feature visibility / permissions
API permissions: TNT_LOG_COUPON_OWNER / ADMIN / MEMBER, TNT_API_COUPON_CREATE / UPDATE / DELETE / READ, TNT_API_COUPON_ENCRYPTED_SOFTPIN_UPDATE / READ; API_TNT_DM_ERP_COUPON_EVENT_* and the API_TNT_DM_ERP_COUPON_LINE_SCAN_EVENT_* family for events and scan events; website links use the CMS coupon-link permissions. No screen in the applet is restricted, the permission screens are the shared ones, and the applet has no client-side permissions of its own.
Fields
Voucher — Details (create; the same fields on edit minus the create-only blocks)
| Field | Meaning | Required | Notes |
|---|---|---|---|
| Voucher Code | Business key | Yes | Disabled on edit unless ENABLE_EDIT_VOUCHER_CODE. The code and the Voucher Name are saved trimmed and in capitals, whatever you type; a code already in use is refused with Voucher already Exists |
| Voucher Type | SETTLEMENT, DISCOUNT, REWARDS, PRODUCT | No (form) | PRODUCT added 2026-06; Field Settings can hide DISCOUNT / REWARDS |
| Face Value Amount | Fixed value | No | Default 0; shown for SETTLEMENT |
| Quantity Type | FIXED, DYNAMIC, IMPORT, INVENTORY | No | FIXED shows Total Voucher Ticket To Be Generated (required in the template) |
| Status | ACTIVE / INACTIVE | — | Default ACTIVE |
| Voucher Limit Per Customer | How many tickets a signed-in customer can claim from your web store’s voucher list; the list stops showing the voucher to them once they have claimed that many | No | Default 1. It is not checked when a ticket is redeemed at the counter or when the bill is finalised |
| Daily Limit | Read only when the till adds a promotion’s free gift by itself: past the limit the till refuses the gift line with Exceeded daily coupon redeem limit. | No | Default 0, which sets no limit. It is not checked when a cashier redeems a ticket or when the bill is finalised |
| Currency | Value currency | No | Default MYR |
| Allow Anonymous | Claim and redeem without an assigned entity | No | Tooltip: “Allow the user to claim and redeem the coupon on the Checkout page” |
| Is Shipping Voucher | Offer it against delivery charges online | No | The CP Commerce storefront’s checkout lists a ticked voucher in its Shipping Fee Vouchers block and applies it to the cart’s delivery-charge line; the block appears only when the cart carries the website’s shipping-fee item. Nothing else acts on it: the backend only lets a voucher search filter by it, and POS General does not read it |
| Softpin / Activation Pin / URL Key / Prefix | Optional security and serial controls, each with a length (default 6); Prefix adds a prefix code and the serial character length; URL Key adds a URL Redirection Configuration | No | No length bounds are enforced in the form |
| Event Period, Redemption Period | Start / end date-times | No | Create form only; shown in DEFAULT_TIMEZONE |
| Add Voucher To CP-Com | Website multi-select | No | Create form only; afterwards use Website Link. The links are saved by a second call after the voucher is created, so if that call fails you see Error Voucher Linking while the voucher itself exists with no links — add them on the Website Link tab. Typing in the search box does not narrow the list; scroll it instead (it loads up to 500 websites) |
The form also takes a free-text Voucher Name, a Description — the line the CP Commerce checkout prints under the voucher’s name on its voucher cards — and rich-text Terms and Conditions.
Treatment Value. For All: Price Source (qty_base Base Quantity, amount_std Standard Amount, price_unit_cost, amount_net, amount_txn), Operator (MULTIPLY, ABSOLUTE, ADD, SUBTRACT), Value, Min Spend, Max Discount Value, Auto Apply to All Child Items; a points block — Customer Points Value, Customer Points Expires Within (days), Retailer Points Value, Retailer Points Expires Within (days), Point Currency. Product: one row per searched item — Item Name, Item Code, Price Source, Operator, Value, Max Discount Value, Min Spend, plus the same points block.
Apply Rules. Doc Hdr rule types: EVENT_DATE (Event Date Range), REDEMPTION_DATE (Redemption Date Range, with a DAYS / MONTHS / YEARS unit), ENTITY_TYPE, MEMBER_CLASS, MEMBER_LABEL, COMPANY, BRANCH, DELIVERY_REGION. Multi Line and Single Line share one list: ITEM, ITEM_CATEGORY, ITEM_CODE_REG_EX, ITEM_NAME_REG_EX, ITEM_CATEGORY_CODE_REG_EX, ITEM_CATEGORY_NAME_REG_EX. Multi Line evaluates across matched lines; Single Line judges each matched line alone.
Ticket. Assignment Status ASSIGNED / UNASSIGNED; Validity Status VALID / INVALID (the backend also sets EXPIRED); Cancellation Status UNCANCELLED / CANCELLED; Redeemable Status UNREDEEMED / REDEEMED.
Import Tickets CSV — the columns the importer reads: VOUCHER_CODE, SERIAL_NUMBER, SOFT_PIN, VALIDITY_STATUS, ASSIGNMENT_STATUS, REDEMPTION_STATUS, CANCELLATION_STATUS, CODE, NAME.
Recurring Voucher. As the standard Details minus the date periods and website picker, plus Recurring ?, Start Date, End Date and the recurrence rule; one treatment form rather than the Product / For All split.
Lifecycle and effects
Master data — no posting. A voucher is not a document: selling, redeeming or expiring one posts nothing by itself, and there is no voucher liability or breakage account. A voucher’s sale, redemption or expiry reaches the ledger only through the sales document it is on, under that document’s own journal.
What a voucher holds. The voucher itself, one ticket per serial number (with its assignment / validity / redemption / cancellation status, redeemable dates, softpin, url key and activation pin), files and attachments, events, import batches, scan events and merchant links; recurring vouchers are kept as templates.
Statuses of a ticket are the four independent flags above; there is no state machine. A ticket’s validity is set to EXPIRED one at a time, or in bulk by the expiry check, which expires every ticket whose redeemable-to date has passed. Nothing runs the expiry check on a schedule: until something calls it, a ticket past its date still reads as valid.
Redemption. When a document is finalised, the redemption step looks at its voucher lines of point type REDEEM that name a voucher and a ticket: a PRODUCT voucher must be on a goods line and a SETTLEMENT voucher on a settlement line, otherwise the line is skipped; unless the voucher allows anonymous use, the ticket must be assigned to the document’s customer. It considers only tickets whose validity is VALID and that are not already redeemed or cancelled, and only those inside their redeemable-from and redeemable-to dates at that moment; a ticket outside its dates is left unredeemed, with no message on the document. Redeeming a serial directly (from the back office, a merchant, the storefront or a signed-in customer) is different: it checks only that the ticket is not already redeemed — not the dates or the validity — and the single-serial call also sets the ticket’s redeemable-to date to the moment of redemption. Because nothing moves a ticket to EXPIRED on its own (above), the dates are the only guard on the document path, and there is none on the direct one.
Background jobs: COUPON_REDEMPTION_PROCESSOR (marks the tickets on a finalised document as redeemed), COUPON_SELLING_PROCESSOR and COUPON_PURCHASING_PROCESSOR (record the tickets a document sells or buys), COUPON_SCHEDULER_PROCESSOR (generates serials and softpins for a voucher), RECURRING_COUPON_CREATION_PROCESSOR and the voucher import jobs. Whether a company’s FINAL starts the selling, purchasing and redemption jobs depends on your tenant’s trigger configuration — treat “automatic on FINAL” as unconfirmed for your tenant, and check a finalised document’s tickets before relying on it.
Recurring vouchers. RECURRING_COUPON_CREATION_PROCESSOR is meant to work out each template’s recurrence from its last run (or its start date) and create the voucher as if it had been created by hand, and its own note says to run it no more than once a day. Today it creates no vouchers: it selects only templates whose start date is still in the future and whose end date has already passed, which no ordinary template is, and its due-date test compares the last run with the last run plus the interval while nothing records a last run. Scheduling it is harmless and does nothing. Until that changes, make each period’s voucher by hand (or by import) on the voucher listing, from the same settings.
Scanned events. Scanning a QR voucher records a scan event, and later steps update its status and give the reward. The screens are generic; the processing behind them is not, and needs setting up with BigLedger before you use it.
Related applets
- Voucher Management — the earlier build behind the other registry row.
- POS General and Sales Invoice (Internal) — where tickets are redeemed against a document.
- Doc Item Maintenance — the
COUPONitem and its Voucher Details tab. - CP Commerce Admin — website links and storefront redemption.
- Membership Admin — member classes and labels for rules; birthday voucher assignment.
- Sales Report — the Voucher Redemption report.
- Scheduler — crontab for the coupon processors.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| + disappears in Ticket Management after the first ticket | ENABLE_MULTIPLE_TICKET off and quantity type FIXED | Turn the setting on, or use DYNAMIC |
| Voucher Code cannot be changed on edit | ENABLE_EDIT_VOUCHER_CODE off (default) | Field Settings |
DISCOUNT, REWARDS or PRODUCT missing from Voucher Type | HIDE_VOUCHER_TYPE_DISCOUNT / _REWARD on — either one also drops PRODUCT | Field Settings |
| Setting a ticket’s validity through the API fails with Is Not Implemented | Only EXPIRED is implemented on serial-numbers/validation/{lineGuid} | Set other statuses on the ticket form |
Tickets past their redeemable date still show VALID | The bulk expiry check is an endpoint, not a scheduled job | Call serial-numbers/validation/expiry-checking, or schedule a caller |
Ticket redeemed at the counter but still UNREDEEMED | The redemption processor did not run for that document, or the voucher was on the wrong line type (SETTLEMENT needs a settlement-method line, PRODUCT a PNS line), or the line is assigned to another entity and the voucher does not allow anonymous use | Check the document’s lines and the company’s job-template subscriptions; GET …/coupons/redeem/{guid} runs the step by hand |
| Voucher or coupon rejected at POS | For a free gift the till adds by itself, the voucher’s Daily Limit is reached (Exceeded daily coupon redeem limit.); otherwise no Doc Hdr rule passes | Daily Limit on the voucher; Apply Rules |
| Import fails on the Checking tab | CSV does not match the nine importer columns, or a serial already exists | Download the Sample Format and match the header exactly |
Recurring vouchers never appear, though RECURRING_COUPON_CREATION_PROCESSOR is scheduled | The run selects no template today (see Recurring vouchers) | Create each period’s voucher by hand or by import |
| Event Period dates shift by hours | DEFAULT_TIMEZONE empty or wrong | Default Selection |
| Voucher edit shows the previous voucher’s details | Store not reset between edits (repo issue #10, fixed 2025-12) | Update the applet |