iVendNextDevelopers Request a sandbox

Save rules: one tax id per customer group, and a submit kept for a role — the recipe

A save rule is the shop's own rule on a record type, held on every save from every door (Desk, an import, the API), with no service and no code: the shop's site checks it. Your manifest can carry save rules, installed switched off; the shop switches each on. This recipe shows the two kinds the POS app added with train T11 (2026-10-16), in one manifest that installs on a sandbox as it is. It is for an iVendNext Partner, or the CitiXsys Consulting Team.

Reference implementation: the manifest below, installed on our sandbox (see What was proven where). The product's save rules page lists all nine kinds, the keys each takes and every refusal in the product's words; chapter 7 says how a manifest carries them.

When to use it. The rule reads only the record itself (its header fields, never its rows) and needs nothing from outside the shop. For a rule that needs your system's data before a document is submitted, use a document check (recipe); for the till's sale, a check before payment (recipe).

Steps

  1. Write the rules in your manifest. scope_fields and bypass_roles are lists. rule_name starts with your prefix.

    {
     "manifest_version": 2,
     "app": "pp_svr",
     "prefix": "PP SVR",
     "title": "Two save rules: one tax id per customer group, purchase requests by a purchase manager",
     "version": "0.1.0",
     "publisher": "Partner Programme sample",
     "description": "Two save rules, installed switched off; the shop switches each on. One: a customer's tax id is on no other active customer of the same customer group (a second one is refused when it is saved). Two: a Material Request of type Purchase is submitted only by a person holding Purchase Manager, from Desk, an import or the API; any other submit is refused. Nothing leaves the shop and no service is called.",
     "save_rules": [
      {"rule_name": "PP SVR One tax id per group", "record_type": "Customer", "kind": "unique_across", "field": "tax_id",
       "scope_fields": ["customer_group"], "mode": "refuse"},
      {"rule_name": "PP SVR Purchase requests by a purchase manager", "record_type": "Material Request", "kind": "role_for_action",
       "action": "submit", "bypass_roles": ["Purchase Manager"], "mode": "refuse",
       "conditions": [{"field": "material_request_type", "operator": "=", "value": "Purchase"}]}
     ]
    }
    
    • unique_across: the value of field is on no other active record of the type with the same values in up to three scope_fields. Without scope_fields the value is unique across every record of the type.
    • role_for_action: the action (submit or cancel) is taken only by a person holding one of bypass_roles when every condition holds (0 to 3 conditions; none means every record). A second rule with "action": "cancel" keeps the cancel too.
  2. Check it on your machine: python3 tools/manifest/validate.py manifest.json takes it. A checker copy from before train T11 refuses scope_fields and action; take the kit's current copy.

  3. Install it on your sandbox (tools/deploy/deploy.py manifest.json, then --consent). Each rule arrives switched off: the shop opens Retail Save Rule and switches it on.

  4. Test it as the shop will meet it: a second customer with the same tax id in the same group is refused, in another group it is saved; a submit by someone without the role is refused, and by someone with it goes through.

What the user sees

What is refused, and why

When your service is down, and when the till is offline

Technical notes

Bounds

What was proven where

Needs this serves

This page in the kit