S14 — price-change approvals across stores
A chain wants a price change to need a yes — but a store manager's yes up to a limit, and head office's yes above it, with each store seeing only its own requests. This sample is S11 (one approval step, one shop) grown for a chain: it is for a developer, or a Custom Development team, who will copy it for anything that needs a manager's approval across stores.
When to use it: an approval whose approver depends on the store, and on how big the change is. For one shop with one approver, S11 is enough.
What happens
- A requester in a store asks for a price change: the item, the price list, the store, the new price, the reason. The store cannot be changed afterwards.
- The store manager of that store approves it. A manager of another store cannot even open it.
- Within the manager's limit (a percentage of the price now, set per manager in the shop), an outside service (
approvals_stores.py apply) applies it through the record API, once, with its own key. - Above the limit, the request waits. Head office approves it, and the service applies it. Head office may also approve straight from Requested.
- The shop's price row now holds the new price; the trail shows who approved at each step, and the service's own note.
Who may approve is a table in the shop
The shop's workflow cannot hold a limit, and a person holding the right roles can write a request's state straight in. So the service does not take the state's word: it reads the shop's approval-rule table (PP APS Approval Rule, one row per person: Store with a store and a limit, or Head Office), and believes an approval only if the person who gave it has the matching row. A person with no row, a row that is not whole, or a store row for another store is not believed: the check fails closed. Only the shop's administrator can write the table; a store manager cannot raise their own limit.
The files
| File | What it is |
|---|---|
manifest.json |
the request type (with its store), the approval-rule table, numbering, change tracking, the workflow of five states, every right written out |
approvals_stores.py |
apply and export (standard library): S11's service with the store limit and the authority check |
tests/test_s14.py |
33 laptop tests against an in-memory shop |
Recipe: recipes/approvals_stores.md. It is built on S11 (samples/s11_approvals/) and keeps every one of its safeguards.
What is refused, and why
- Everything S11 refuses: a request whose item, price list or price changed after it was raised; one with ten or more recorded changes; one approved by the person who raised it — here at each approval, not only the last.
- A request whose store changed after it was raised. The shop does not allow it; the service checks too.
- A change above the store manager's limit, approved only at the store. It waits for head office, and the report says so.
- A store approval whose price row changed afterwards. The limit was judged against a price that is gone; the manager rejects it and it is raised again (this stops a limit being climbed in steps).
- A head-office approval by someone with no head-office row. Even where the shop let them take the action because their roles allowed it.
- An approval by a person whose rule was removed since. The rules are read when the service runs.
Technical notes
Tested on our test bench on 2026-10-08, with two stores, a requester and a store manager in each, head office, the service, and three people holding two roles each. The run's id and checks are in the recipe. Not tried: two services at once, many requests at once, approvals across companies, an approver who is also the applier. A request names a price list, and the service does not tie the list to the store: where several stores share one list, one manager's approval changes every store's price; a shop with one list per store adds that check. The service's key can list the shop's users with their email and phone (the shop's default for any desk user).