The extension points' kinds
Part 2 of 7 · 7. Manifests
Each record goes through the product's own checks when it is installed; a refusal there comes back in the product's words, and nothing is left. The full contract of each extension point, its limits and its refusals included, is in the kit's contracts/.
Back: StepsNext: Reports, reminders, settings records and multi-select fields
extension_subscriptions— your service for one extension point:key(your name for it),point(desk_action,page,check,capture,doccheck,fulfil,pricefor a module's service only, orpayer),label(1–40 characters),endpoint_url(https, listed inallowed_urls),timeout_seconds(at most 10; a scan or quantity-change capture at most 3; a payer at most 5),down_answer(what the till does when your service is down; each extension point lists its own), and for a page itspage_…settings andpage_roles.- A check before payment takes one setting:
fill_attributes, the sale details its answer may fill (1 to 10 different names, each a sale detail your manifest declares or the retailer already has;{"fill_attributes": ["Rx Date"]}). How a fill works: the check page, Filling sale details. At most three checks answer one POS Profile, and together they may take at most ten seconds. Whether a manager may approve past a check (may_approve), the POS Profiles it serves, and Send each line's lot and serial number (check_send_lots) are the retailer's to set, never a manifest's. - A capture names its event in
settings:scan(withitem_groups, at most 50, or anitem_field, or both),customer_add,customer_select(an existing customer put on a sale), orqty_change(the quantity of a line changes; the scan's filter,item_groupsor anitem_field). One service answers each event. A capture may also answernotice: the item, customer or quantity goes on and the cashier reads your sentence (chapter 9). The till draws a button that opens a partner page beside a notice, and the retailer sets thatpageon the capture in iVendNext Desk once both are installed (the capture page, section 3). - A document check (
doccheck) names insettingsthe one record type it checks (record_type: a submitted back-office type such as Purchase Order, never a till sale), the fields sent (send_fields, the Desk action's grammar),on_validate(truechecks a draft's save too) andfill_fields(at most 10 fields your answer may fill). A fill field must be one the retailer added, and a field your manifest adds counts: put it incustom_fieldsand name it here. Its down answer isallow_and_flag,refuseorask. At most three services check one record type. - Fulfil at sale (
fulfil) names insettingsthe items your service makes a code for:item_groups(a group and every group below it; at most 50), anitem_field(an Item field that is set), or both. Its down answer is alwayswait(a paid sale is never undone, so the receipt waits for your code); its time to answer is 5 seconds unless raised, at most 10. The calls, the answers and your two promises are on the fulfil page. - A payer (
payer) may carry insettingsthe sale details sent as the prescription (prescription: up to three ofreference,prescriber,prescriber_licence) and the role that may bill a claim back (bill_back_role). Its down answer is alwaysno_cover. The clearing mode is the retailer's to pick, so a manifest carryingclearing_modeis refused, and the payer stays off until the retailer names it. The calls are on the payer page and in chapter 9. - A module's service has
transport: "wasm"and names, inmodule, thekeyof a module in the same manifest'sextension_modules: same extension point, no address and no secret. - The install makes each secret, named
<app>:sub:<key>. Its one consent is each service's, and the service serves every store; a record's Enabled box stays the retailer's off switch.
- A check before payment takes one setting:
desk_actions— a button on a Desk record: the record type, label, roles, when it shows (on_draft,states,conditions), itsinputsandsend_fields, andservice: thekeyof one of yourdesk_actionsubscriptions in the same manifest (the installer makes the subscription first). A service the manifest does not install is refused, and so is the roleGuestorAll.save_rules— a rule checked on every save of a record type, the retailer's own (an Item, a Customer, a sale) or yours:rule_nameand the rule's settings.- The ten kinds (
pattern,length,derived,unique_in_rows,threshold,required_when,locked_in_state,unique_across,role_for_action,count_per_day), the keys each one takes, andmode(refuseorflag) are on the product's save rules page. Read it before you write a rule. What to know:- A rule is on from the install. A role rule (
role_for_action) stays off until the customer names the role, because the app's roles are created empty and it would stop everyone. Add"enabled": 0to keep any rule off. An update keeps each rule's switch. - Rules run in
sequenceorder (lowest first, then by name), each one after the one before has written its value. So a derived value can feed the next rule: months × 30 into shelf days (scale), the expiry date into days left (days_until, which reads a date), the days left over the shelf days into a percent, a threshold on the percent. Give each rule in the chain asequencehigher than its source's. unique_acrossandrole_for_action.unique_across: a value on no other active record of the type, within up to threescope_fields(a list, for example["customer_group"]).role_for_action: anaction(submitorcancel) only a person holding one ofbypass_rolesmay take, when every condition holds; its conditions read the document's header, never its rows. Both are lists in a manifest, asbypass_rolesis. The save-rules example installs one of each.count_per_day,derived,thresholdandrequired_when.count_per_day: no more thancap(1 to 10,000) records a day per value ofscope_field(a store, say), by the calendar day ofday_field, counted when a save newly meets its 0 to 3conditions; its conditions, and only its, may usein(up to 10 values separated by commas; numbers on a number field). It never sits on a sale or a day close, and should never sit on a record a sale or the day close writes (a payment, loyalty points, a coupon's count, a layaway's order, a delivery note, the day's roll-up invoice): its lock is held to each sale's commit and every till would wait. An approval a manager gives offline is not counted.derivedhassum_rowsandcount_rows(source_tablenames one table of the record; the figure goes on the record's own header, a sum into a Float or Percent field) anddays_between(two Date or Datetime fields;creationmay be the first, on a rule without a table); each writes only a field the retailer added, namedcustom_…or with your package's prefix.percentanddays_betweenclear their figure when a source is empty (andpercenton a zero base).thresholdhasjudge_on_change: 1(judged only when the record is new, submitted, or the value changed) and a limit read from a settings record:value_from_typeandvalue_from_name(a record type your package installed, a settings record or one row of an ordinary type, or Stock, Selling or Buying Settings; a single's name is its record type),value_field(an Int, Float or Percent field) androles_field(the one role that may pass it). A 0 or a missing record there means the rule's ownvalue, sovaluestays required; whoever the retailer lets write that record tunes the limit without opening the rule.required_whenon a table's rows may read the header: a condition onparent.⟨field⟩(a transfer's rows name their request). A derived rule that cannot be worked out flags and never refuses.- Order and bounds the product states. Give a derived rule, and a limit judged at every save, a
sequenceafter the rules that write its sources (a limit judged on change runs after every derived rule anyway). Never make a figure a limit judges mandatory, and never make a batch's dates required by a save rule: a receipt makes its batch before the dates are filled, so a batch is judged at its first later save. The whole list is on the save rules page, §7. - A rule may name only a field that exists when it is installed. A workflow in the same manifest is made first, so a rule may read its
workflow_state.
- A rule is on from the install. A role rule (
- Refused: the role
GuestorAllinbypass_roles; a message carrying markup (the product shows it as the refusal). - On a sale the product lets a rule only flag, never refuse: a sale the customer paid for is never stopped.
- The ten kinds (
fiscal_readers— one per site: your outside service's result on the sale (the fiscal reader page).- What you declare. You add the result fields to POS Invoice in
custom_fields, declared Small Text unless your reader searches by them (the sale has little room left, above), No Copy, allow-on-submit, at their own permission level (permlevel, the only place a manifest writes one; a field limited to roles gets a level the installer picks, later in this chapter), and name them, with, if you have them, a QR field and a seal field, each Data, Small Text, Text or Long Text (a manifest cannot make a Code field, so an XML-form seal keeps its form only if the retailer changes that field to Code after the install), which the receipt prints for a cleared or reported sale; the map from your values to CLEARED, REPORTED or PENDING;writer_roleandwriter_level(that level);writer_users(short keys). - What the installer makes, in this order: the fields, the role, its one permission row (read and write at its level, nothing at level 0), one integration user per key, then the reader, switched off, serving every company on the site. Nothing it makes reaches a sale yet, and no key leaves the install.
- The integration user is made at
<key>.<app>@integration.invalid. It works through the API only (it can never sign in to Desk, and no one can give it a password or another role); a site at its user limit refuses the install, naming the licence. It holds your writer role and nothing else: if the site gives it any other role, the install is refused and removed. It has no API key until the retailer makes one. - Refused: a
writer_leveloutside 1 to 9, a result field that is not in yourcustom_fieldsor sits at another level, a QR or seal field that does not hold text, and limiting a result field to roles. Warned, not refused: level 1 (the retailer's Accounts Manager already writes POS Invoice there), a field without No Copy or allow-on-submit. - Before install the retailer turns on Clearance required for its country. The reader serves every company on a site, so keep to one company per site.
- After install the retailer:
- gives the role read, write and submit at level 0 (your service reads and saves a submitted sale; with them it can change any level-0 field a submitted sale allows, and submit a draft);
- generates the integration user's API key (User → Generate Keys) and hands it to you, as for any connected app (the integration user recipe);
- switches the reader on.
- At uninstall the role goes, and with it every grant naming it: the retailer's own level-0 row for it on POS Invoice, and the role on any user or role profile it was given to. The product checks the writer rule then, and on every read: fields above level 0, No Copy, no other role writing their level, the role held by your users only. The installer reports whether it holds.
- What you declare. You add the result fields to POS Invoice in
scan_sources— a table of the retailer's own unit codes that the till's scan reads when it finds nothing else. You name the table (record_type, your own record type or the retailer's), its code field (barcode_field, unique, so one code names one unit), the field linking to Item (item_from), optionally the fields for batch, serial, status and warehouse, the statuses a unit can be sold in (available_values), andcapture_as(a sale detail the unit's code then rides on, which needs a status field so a returned unit can be sold again). Nothing leaves the retailer's iVendNext (the scan source page).field_rules— rows on a till theme the retailer already has (theme, the name of a POS Studio theme):surface(the till screen),field,action(hide, relabel, require or show), and for relabel and show alabelof at most 40 characters, with an optionallanguage. What each screen and field takes is on the Field rules page.showoncustomer_createasks for one of the retailer's own Customer fields (an ID number, a date of birth) on the new-customer sheet and the till's customer edit, at most three per theme. To make one required, add a save rule (required_when). The field rules page says which field types the till asks for (§7e).- A field rule has no switch. A rule that requires a field is enforced by the server at once; hide, relabel and show reach every till on that theme at its next start. Plan it as a change to the theme. A theme that came with the till takes none: name one the retailer saved as its own.
- To undo one, the retailer removes the row from the theme's Fields tab. The theme must exist before install.
list_marks(manifest version 2) — a coloured label on a row of a retailer's Desk list, shown when the row's values say so (On promotion in green on the product list):record_type, 1 to 3conditions(field,operator,value; the operators=,!=,>,>=,<,<=,is set,is not set, a comparison reading numbers only),label(1 to 24 characters, plain text, no space before or after),colour(green,blue,orange,red,grayorpurple) andsequence(when two marks match, the lower shows). It is display only: a mark saves or refuses nothing, and no script of yours runs in Desk. A user who may not read every field a mark reads never receives it, and the report view shows no label (the list mark page).extension_modules(manifest version 2) — a module our certify service signed, for the check before payment or pricing:key(lower-case letters, digits and underscores; your service names the module by it),point,version(a whole number from 1),metered: true,sha256andcertificate(from the module's certificate file) andwasm(the module's bytes in base64, at most 256 KB). Its service is anextension_subscriptionsentry withtransport: "wasm"that names the key (above); pricing takes a module only. One module per partner and extension point in a manifest. A version is used once on a site: installing the app again, or shipping a fix, needs a higher module version. Size: the install screen takes a module up to 256 KB, but the App library serves a manifest of at most 256 KB, so a library app's module stays near 190 KB. Only the service has a switch; the module itself has none.- Refused:
max_discount_percenton its service: a pricing service installs at 0, and the retailer raises it. At install the retailer's iVendNext refuses a module our certify service did not sign, and one iVendNext has recalled. - Withdrawing it is the retailer's, as for a module added in Desk (the Wasm kit).
- Refused:
- Export: the uninstall's export also holds these records as the retailer left them, never a secret. A reinstall gives back your manifest's own copy.
Back: StepsNext: Reports, reminders, settings records and multi-select fields