Voucher Lifecycles

Introduction

Each voucher generated by a voucher generator will be created with a voucher lifecycle instance. The voucher lifecycle used determines:

  1. The current state of the voucher.
  2. The transitions the voucher can make, from the current state.
  3. When automated transitions should occur.
  4. In what state voucher redemption are allowed.
  5. When the voucher must be removed from the voucher server database.

It is possible, using the OCS’s powerful lifecycle definition system, to configure unique voucher lifecycles, even different lifecycles for different types of voucher generated by a single voucher server.

A default voucher lifecycle is included with the voucher server. This lifecycle includes a generally useful set of states and state transitions:

default voucher lifecycle state machine

Default Lifecycle States & Transitions

In the default lifecycle shown above, the following states and state transitions will be available:

State Transition Description
Created The state each voucher starts in on creation. This state indicates the voucher has been created in the voucher server, the voucher is included in a print file, but is not yet made available for purchase and redemption.
Created activate This activate transition is used to move a voucher into the Active state once the voucher is ready to be made available for redemption.
Created lock The manual lock transition can be used to move an otherwise fine voucher into the Locked state to disallow the voucher from being activated and hence redeemed. This is useful when a range of vouchers in a batch is suspect and should be locked.
Created remove This is a manual transition to remove a previously created, by never activated, voucher. When using this transition, the voucher will be immediately deleted from the voucher server database.
Active The Active state is used when a voucher is available for redemption. On entering this state, the voucher’s redeemable flag is set to true.
Active redeem The redeem action is used by an external system to trigger the redemption of a voucher against a wallet. The wallet is expected to be provided in the request parameters for this lifecycle transition.
Active on timer An Active voucher will automatically be moved to Expired after 12 months where it is not redeemed.
Active lock The manual lock transition can be used to move an otherwise active voucher into the Locked state to disallow the voucher from being redeemed. This is useful when a range of vouchers in a batch is suspect and should be locked.
Locked A Locked voucher is one which has been determined to be lost, stolen or otherwise in an unknown (but unredeemed) state, and which because of this, should not be allowed to be redeemed without manual intervention. On entering this state, the voucher’s redeemable flag is set to false.
Locked reactivate A Locked voucher may be reactivated using the reactivate transition. This is used by operators to move a locked voucher back into a state which allows the voucher to be redeemed.
Locked on timer A Locked voucher will automatically be moved to Expired after 12 months of inactivity.
Locked remove The remove transition can be used to manually move a locked voucher to the Removing state if required.
Redeeming The Redeeming state is used for the short period when the server is redeeming a voucher against a wallet.
Redeeming redeemed The Redeemed event is used to move the voucher from the temporary Redeeming state to the Redeemed state. This transition is automatically performed by the voucher server after a voucher redemption completes successfully.
Redeeming on timer This state is temporary, and if not exited within a short period (by default, sixty seconds), will automatically exit into the Error state.
Redeemed The Redeemed state is used to indicate a voucher has been redeemed. A voucher in this state cannot be redeemed again.
Redeemed on timer remove A voucher in the Redeemed state will move to Removing and then be removed from the server automatically after 12 months. This can be forced by using the remove transition.
Error The Error state is used if a voucher redemption request failed to complete for sixty seconds. Vouchers are moved to the error state automatically.
Expired The Expired state is used after a voucher in the Active state is not redeemed for twelve months.
Expired on timer remove A voucher in the Expired state will move to Removing and then be removed from the server automatically after 12 months. This can be forced by using the remove transition.
Removing The Removing state is a temporary state used to transition between another state, and the voucher being removed from the voucher server and the voucher record itself being deleted from the database.

Default Voucher Lifecycle Document

The following JSON document defines the default voucher lifecycle used by the voucher server. This lifecycle can be loaded in to the voucher server and adjusted as required:

{
    "id": "default-voucher-lifecycle-v2.1.0", 
    "name": "Default Voucher Lifecycle",
    "description": "Lifecycle for all vouchers",
    "lifecycleclass": "voucher",
    "initial_state": "CREATED",
    "states": {
        "CREATED": {
            "description": "All vouchers begin in the created state.",
            "name": "Created",
            "transitions": [
                {
                    "id": "created_to_active",
                    "event": "activate",
                    "to_state": "ACTIVE"
                },
                {
                    "id": "created_to_lock",
                    "event": "lock",
                    "to_state": "LOCKED"
                },
                {
                    "id": "created_to_removing",
                    "event": "remove",
                    "to_state": "REMOVING"
                }
            ]
        },
        "ACTIVE": {
            "description": "Voucher available for redemption.",
            "name": "Active",
            "action": "voucher.setRedeemable(true); '200'",
            "transitions": [
                {
                    "id": "active_to_redeeming",
                    "event": "redeem",
                    "to_state": "REDEEMING"
                },
                {
                    "id": "active_to_expired",
                    "event": "timer",
                    "timer_reference": "state_entered_at",
                    "to_state": "EXPIRED",
                    "timer": {
                        "months": 12
                    }
                },
                {
                    "id": "active_to_lock",
                    "event": "lock",
                    "to_state": "LOCKED"
                }
            ]
        },
        "LOCKED": {
            "description": "Voucher locked - cannot be redeemed.",
            "name": "Locked",
            "action": "voucher.setRedeemable(false); '200'",
            "transitions": [
                {
                    "id": "locked_to_active",
                    "event": "reactivate",
                    "to_state": "ACTIVE"
                },
                {
                    "id": "locked_to_expired",
                    "event": "timer",
                    "to_state": "EXPIRED",
                    "timer_reference": "state_entered_at",
                    "timer": {
                        "months": 12
                    }
                },
                {
                    "id": "locked_to_removing",
                    "event": "remove",
                    "to_state": "REMOVING"
                }
            ]
        },
        "REDEEMING": {
            "description": "Voucher redemption attempt.",
            "name": "Redeeming",
            "action": "voucher.redeem(ocs.context().ancillaryInformation().getString('account')).map('redeemed');",
            "transitions": [
                {
                    "id": "redeeming_to_redeemed",
                    "event": "redeemed",
                    "to_state": "REDEEMED"
                },
                {
                    "event": "timer",
                    "timer_reference": "state_entered_at",
                    "to_state": "ERROR",
                    "timer": {
                        "seconds": 60
                    }
                }
            ]
        },
        "ERROR": {
            "description": "A voucher redemption error has occurred.",
            "name": "Error",
            "transitions": [
                {
                    "id": "error_to_active",
                    "event": "reactivate",
                    "to_state": "ACTIVE"
                }
            ]
        },
        "REDEEMED": {
            "description": "Voucher redeemed.",
            "name": "Redeemed",
            "transitions": [
                {
                    "id": "redeemed_to_removing",
                    "event": "remove",
                    "timer_reference": "state_entered_at",
                    "to_state": "REMOVING",
                    "timer": {
                        "months": 12
                    }
                }
            ]
        },
        "EXPIRED": {
            "description": "Voucher expired.",
            "name": "Expired",
            "action": "voucher.setRedeemable(false); '200'",
            "transitions": [
                {
                    "id": "expired_to_removing",
                    "event": "remove",
                    "timer_reference": "state_entered_at",
                    "to_state": "REMOVING",
                    "timer": {
                        "months": 12
                    }
                }
            ]
        },
        "REMOVING": {
            "description": "Voucher will be removed on entering this state.",
            "name": "Removing",
            "action": "lifecycle.delete()"
        }
    }
}