iVendNextDevelopers Request a sandbox

Set up fifty stores from one file — the estate roll-out recipe

You describe a whole chain of stores in one file, and a small tool makes the shop match it: price lists, promotions, permissions and receipt formats, store by store. This recipe is for a retailer with many stores and several regions that must be set up the same way, changed together, and checked afterwards — or for the partner or team serving that retailer.

Reference implementation: samples/s8_estate_rollout/ (estate.json is the whole estate; rollout.py has four verbs; standard library only). It reuses the pieces of two other recipes — the receipt format by configuration (recipes/receipt_format.md), the reason switches (recipes/configure_no_code.md).

When to use it. When more than a handful of stores must carry the same set-up, and every change must reach all of them and be checked.

Steps

  1. Write the file. estate.json names: regions (a price list, a price per item, one promotion, a manager each) · stores (a code, a region, a receipt format, a cashier) · the reference profile new till profiles are cloned from · the warehouse defaults every store carries · estate-wide switches and reason codes. A real customer keeps it in their own repository and edits it by hand; generate_estate.py only writes 51 stores for the sample.

    Per… The roll-out makes
    region a Price List and its Item Prices · one promotion, limited to that region's stores · a manager user with the manager role
    store a Warehouse (with the outlet defaults below) · a till profile cloned from the reference profile (its warehouse, price list and receipt format set) · a cashier user with the cashier role and user permissions on that profile and warehouse
    estate the reason switch(es) in Retail Setting and the reason codes
  2. See what would change: plan. It lists what apply would change, object by object and field by field (update POS Profile: PP EST N005 {"print_format": ["Gift Receipt", "mPOS Receipt"]}). It writes nothing. It names a blocker (a receipt format, item or role the shop does not have), and apply refuses until it is gone.

    PP_BASE=https://shop.example PP_KEY=… PP_SECRET=… python3 samples/s8_estate_rollout/rollout.py plan|apply|verify|remove --estate estate.json
    
  3. Make the shop match the file: apply. It is idempotent: a second apply creates, updates and deletes nothing.

  4. Check it: verify. It reads everything back and compares it with the file. It exits 1 and names every difference if a store was edited by hand, or if something with the estate's prefix is not in the file (an orphan: a warehouse, a profile, a price list, an Item Price — one dropped from the file, or a second row for the same item and list —, a promotion, a user or a reason code).

  5. Take it out: remove. It removes the estate in reverse order. A record a booked sale points at cannot be deleted (the shop keeps its history): it is retired (disabled) and the line says so. A later apply switches it back on instead of making it twice. A record that can be neither deleted nor retired is listed under kept, never skipped silently.

One comparison drives plan, apply and verify, so the plan, the writes and the read-back cannot disagree.

What the shop requires (and the file carries)

Limits to know before you start

Technical notes

What was measured

The shop's requirements above were measured on our test bench (the engine derives a profile's price list from its warehouse); the file now carries them.

Proven on the bench

The recipe is proven on our test bench.

Bounds, stated

This page in the kit