Actions and results
What each Master Data button and automatic behaviour does, with worked numbers and what the system refuses.
On this page (38)
DashboardPartiesParty recordParty record > Registrations & banksBank and tax changesDuplicates and mergesTemplates and variantsTemplate recordAttributesBarcodesCustomer item codesSupplier item codesTracking policies and mediaSite defaultsAccount mappingsSubstitutesCataloguesImportsData qualityField securityReportsReferencesMaster Data featuresMaster Data field settingsContacts listCustomer 360Record credit review dialogCustom fieldsCountries / States / CitiesProducts listProduct recordProduct barcode lookupDuplicate ProductStock on handProduct categoriesUnits of measureVariant attributesBrands / Product groups / Manufacturers
Dashboard
| Action | When | What you do | What happens |
|---|---|---|---|
| Tiles match the registers | Some parties, a pending change, an open duplicate, templates in several stages | Open the dashboard; compare each tile with Parties (Released tab), Bank and tax changes (Awaiting), Duplicates, Templates tabs | Parties = released releases; shared count = parties released to more than one company; Changes awaiting = proposed requests; Duplicate candidates = open pairs (+ proposed merges); Templates by lifecycle add up to the template count |
| Adopt existing partners as parties (backfill) | Company with 3 partners that have no party; user with mdm.steward | Press 'Adopt 3 partners as parties' | 3 parties PTY-xxxxxx created, each released to this company and pointing at its partner; a partner with a tax id gets an active unverified VAT registration; button disappears; audit 'mdm.parties.backfilled'. Two partners with the same TRN become two parties (not merged) |
Parties
| Action | When | What you do | What happens |
|---|---|---|---|
| Create a party | mdm.steward | New party: Legal name 'Test Trading LLC', Roles Customer + Vendor, B2B, Registration 100123456700003, AE; Save | Record opens PTY-xxxxxx; a partner of kind 'both' with an auto code is created in this company; Registrations tab shows VAT AE 100123456700003 active; the new partner is scanned for duplicates at once |
| Repeat create is idempotent | Network tools; same Idempotency-Key | Send the same New party request twice with one key (API); then the same key with another legal name | Second call returns the same id with repeated=true, no second party; different body -> 409 'This idempotency key was already used for a different request.' |
| Tabs and filters | Parties in released, suspended, archived | Click each tab; search by registration number; sort by Updated | Counts on the tabs match; search finds by code, name and registration; paging works |
Party record
| Action | When | What you do | What happens |
|---|---|---|---|
| Edit identity of an unshared party | Party released to this company only | Edit identity: change Trading name and Website; Save | Saved; revision +1; the partner's name / Arabic name stay in step with the party; event 'master version changed' |
| Rename a shared party | Party released to two companies; user without mdm.release | Edit identity: change Legal name; Save | Refused 'Renaming a party released to several companies needs the mdm.release permission.'; with mdm.release it saves and BOTH companies' partners show the new name |
| Partner rename follows / is blocked | Party A released to one company; party B shared | In Contacts / Customers rename partner A; then try to rename partner B | A: the party's legal name follows the partner. B: refused '<code> is the account of party PTY-..., which other companies share: change its legal name or tax number in Master Data.' |
| Release to another company | User member of company 2 with mdm.release there | Release to a company -> choose company 2 -> Release | 'Released.'; company 2 gets its own partner (own code, terms 0 days) for the same party; Companies tab lists both; 'Shared' now Yes; releasing again -> 'The party is already released to that company.' |
| Suspend, archive, reinstate here | Released party | Suspend here; then Reinstate; then Archive here (confirm) | Status chip follows; archive sets the partner inactive (documents stay, new ones refused); when no release is left un-archived the party itself becomes archived; Reinstate makes partner and party active again |
| Add contact and address | Party open | Add contact (name, email, whatsapp); Add address: shipping, line 1, AE, Dubai, Dubai | Both listed on their tabs; counts on the smart buttons increase; a city outside the emirate is refused with the geography message |
| Companies tab hides other companies | Party released to company 2 where you are NOT a member | Open the Companies tab | Only this company (and companies you belong to) are named; company 2 is not shown |
Party record > Registrations & banks
| Action | When | What you do | What happens |
|---|---|---|---|
| Propose a bank account | mdm.steward | Propose (bank): Test Bank PJSC, IBAN AE07 0331 2345 6789 0123 456, SWIFT TESTAEAD, AED, proof ref; Propose | Message 'Proposed as MCR-000001; somebody else decides it under Change requests.'; nothing added to Bank accounts yet; request state proposed, domain finance, a 64-character hash |
| Propose a registration | Party with no active AE VAT | Propose (registration): VAT, AE, 100123456700003, valid from 2026-10-01 | Request MCR-xxxxxx, domain tax, proposed; registration not active until approved |
Bank and tax changes
| Action | When | What you do | What happens |
|---|---|---|---|
| Approve a bank change | Request proposed by user A; user B with mdm.finance.approve | As B open the request; Approve this exact proposal | State approved; a new active bank account with approved time and the request's hash; if it replaced one (update), the old account becomes retired - never edited in place; event raised |
| Proposer cannot decide own request | Request proposed by A; A also holds mdm.finance.approve (or is superuser) | As A open it and Approve | Refused 'Somebody other than the person who prepared this change must decide it.' - superusers too |
| Wrong approver domain | Bank request; user with only mdm.tax.approve | Approve | Refused 'Deciding a bank account change needs mdm.finance.approve.'; for a registration without tax approval: 'Deciding a registration change needs mdm.tax.approve.' |
| Approval bound to the hash | A request open in B's dialog | Via API send decide with approve=true and a different payload_hash | Refused 'The proposal you are approving is not the one on record; reload it and review it again.'; nothing applied |
| Reject needs a reason | Proposed request; approver B | Reject -> leave the prompt empty -> OK; then Reject with a reason | Empty: 'Say why it is rejected.'; with reason: state rejected, note stored, nothing applied |
| Already decided | An approved request | Via API decide it again | Refused 'This request is already approved.' |
| Primary VAT approval updates the partners | Approved registration request VAT AE for a party released to two companies | Approve; open the party and both partners | Party registration = new number; every released partner's tax id = new number; the old registration (if update) retired |
| A newer proposal makes the older one stale | Open update request for bank account X | Propose another update for the same account X | The first request becomes 'stale' (visible under All); only the newest can be decided |
Duplicates and merges
| Action | When | What you do | What happens |
|---|---|---|---|
| Scan finds duplicates by rule | Partners: P1 and P2 same TRN; P3 and P4 'Test Trading LLC' / 'TEST TRADING' same mobile; P5 and P6 same email only | Scan partners | 'N pairs found.' P1/P2 reason 'same registration number' confidence 90; P3/P4 'same name, same phone' 80 (LLC / Trading words ignored); P5/P6 NOT listed - an email alone is never a duplicate |
| Scan also pairs products | Two active products with the same barcode; two with the same name | Scan | Product pairs listed: 'same barcode' 90, 'same name' 50 |
| Placeholder keys are skipped | More than 50 partners named 'Walk-in customer' | Scan | No pairs for that name; the scan response lists it in too_common |
| Not a duplicate | Open pair | Not a duplicate | Pair state dismissed, leaves the open list; a later scan does not reopen it |
| Propose a merge | Open pair P3/P4, no documents conflict | Propose merge -> survivor P3 -> Propose | Merge MRG-000001 proposed; Documents moved shows the count of documents and payments pointing at P4 (an impact count); Conflicts '—' |
| Apply a merge | Merge proposed by A; B with mdm.merge.approve | As B Approve (confirm) | State applied; P4 inactive; an alias resolves P4's id to P3 (/mdm/resolve/partner/<P4 id> returns P3); P4's release archived and, if its party has no other live release, party marked merged into P3's party; the P3/P4 pair 'merged', other pairs with P4 dismissed; P4's existing invoices stay on P4 |
| Merge refused for different registrations | Pair P1/P2 where P2's TRN was corrected to another number | Propose merge | Refused 'Their registration numbers differ: they are two legal entities, and are not merged. Correct the wrong one instead.' |
| Merge decided by its proposer | Merge proposed by A; A has mdm.merge.approve | As A Approve | Refused 'Somebody other than the person who prepared this merge must decide it.' |
Templates and variants
| Action | When | What you do | What happens |
|---|---|---|---|
| Create a template | Attributes SIZE (S,M,L) and COLOUR (RED,BLUE) exist; product.manage | New template TSHIRT, Goods, category, unit, axes SIZE + COLOUR, price 50, cost 20; Save | Record opens in Draft; Validate button shown; no variants |
Template record
| Action | When | What you do | What happens |
|---|---|---|---|
| Lifecycle draft -> validated -> approved -> released | Template created by user A | A: Validate. A: Approve. B (mdm.steward): Approve. B: Release | Validate ok (needs category and base unit for goods). A's Approve refused 'Somebody other than the person who prepared this template must decide it.' (the validator also counts as preparer). B approves; Release makes every variant product active and 'Sellable' |
| Validate needs category and unit | Goods template without category and unit | Validate | Refused 'Give the template a base unit and a category before validating it.' |
| Out-of-order step | Draft template | Via API post /release | Refused 'A draft template cannot be released.' |
| Generate all variants (attribute matrix) | TSHIRT with SIZE (S,M,L) x COLOUR (RED,BLUE), draft | Generate all variants; then Generate again | First: '6 variants created.' SKUs TSHIRT-S-RED ... TSHIRT-L-BLUE, each its own product with price 50 / cost 20, Sellable 'Not until released'. Second: '0 variants created.' |
| Matrix limit | Axes whose values multiply to more than 500 (e.g. 26 x 20) | Generate all variants | Refused 'That is more than 500 variants; narrow the values first.'; nothing created |
| Add one variant and duplicate combination | TSHIRT with M/RED existing | Add one variant SIZE=M, COLOUR=RED | 409 'TSHIRT already has the variant SIZE=M|COLOUR=RED.'; a new combination (e.g. a new value XL) is created; after release it is active at once |
| Archive a template | Released template with variants | Archive (confirm) | Lifecycle archived; every variant product inactive (closed to new documents); history unchanged; Generate and Add variant no longer offered; archive again via API -> 'It is already archived.' |
| Locked after variants | Template with variants, draft | Via API PUT a different base unit or axes | Refused 'The template has variants; its type and base unit are fixed.' / 'The template has variants; its axes are fixed.'; a released template -> 'Only a draft or validated template is edited; reopen it.' |
Attributes
| Action | When | What you do | What happens |
|---|---|---|---|
| Create a list attribute with values | mdm.steward | New attribute SIZE, list, variant axis, values 'S, M, L' | Listed with values S, M, L; the attribute also appears in the product form's variant attributes (lookup kind attribute) |
Barcodes
| Action | When | What you do | What happens |
|---|---|---|---|
| GTIN check digit | A product | Register EAN13 6291000000013; then 6291000000014; then '629100000001' | First saved active. Second 'The check digit is wrong.' (sum of digits x3/x1 from the right: check = (10 - total mod 10) mod 10). Third 'An EAN13 code is 13 digits.' |
| One scanner identity | 6291000000013 registered to product A; product B has its own barcode 6291000000020 | Register 6291000000013 for B; then 6291000000020 for A | Both refused '<code> already identifies <product>.' - registered, product and packaging barcodes are checked against each other |
| Non-GTIN symbologies | A product | Register CODE128 'ABC-123' and QR 'https://example.com/p/1' | Saved without a length or check-digit check |
Customer item codes
| Action | When | What you do | What happens |
|---|---|---|---|
| Customer code is unique per customer and private | Customers C1, C2 | Add C1 code 'X1' -> product A; add C2 code 'X1' -> product B; add C1 'X1' again | C1 and C2 may both use X1; the repeat refused '<C1 code> already uses X1 for a product.'; lookup API with C2 + X1 returns product B only |
Supplier item codes
| Action | When | What you do | What happens |
|---|---|---|---|
| Supplier code | Supplier S1 | New code S1 / 'SUP-1' / product A; repeat it | First saved; repeat refused '<S1 code> already uses SUP-1.' |
Tracking policies and media
| Action | When | What you do | What happens |
|---|---|---|---|
| Propose and activate a policy (no stock) | Goods product with no lots; user A product.manage + mdm.steward | Propose version: lot, expiry, manufacture date, expiry 365, best before 300, removal 30, alert 60; Activate | v1 draft then active; the product's tracking = lot and expiry on; proposing v2 and activating it marks v1 superseded |
| Lot default dates from the policy | Active policy above; receive a lot with manufacture date 2026-10-01 and no dates | Receive the lot in Inventory; open the lot | Expiry 2027-10-01 (+365); best before 2027-07-28 (expiry minus 365-300 = 65 days); removal 2027-09-01 (expiry - 30); alert 2027-08-02 (expiry - 60). Dates typed on the receipt are never replaced |
| Tracking change with lots in stock | Product with 2 lots in stock, tracking lot; policy v2 tracking serial proposed by A with a 10-character plan | A: Activate; then rewrite the plan (20+ chars) as a new version and A activates; then B activates | Short plan refused '<code> has lots in stock. Write the reviewed conversion plan...'; A on own version refused 'Somebody other than the person who prepared this tracking change must decide it.'; B succeeds. The product form itself refuses tracking change: '<code> has lots in stock. Change its tracking through a tracking policy with a reviewed conversion plan.' |
| Upload product media | A product | Upload a 2000x1500 JPEG; then an SVG | JPEG kept as PNG scaled to 1600x1200, shown with size and audience 'channel'; SVG refused 'SVG and other markup are not accepted; upload a PNG, JPEG or WebP picture.' |
Site defaults
| Action | When | What you do | What happens |
|---|---|---|---|
| New version supersedes | Product A at Main warehouse v1 min 10 max 100 | New version: min 20 max 200 reorder point 40 lead 7 | v2 active, v1 superseded; list shows both; max 0 is allowed (no maximum) |
Account mappings
| Action | When | What you do | What happens |
|---|---|---|---|
| Draft and activate a mapping | User A product.manage; user B mdm.finance.approve | A: New mapping category 'Test cat', sales 4000 (income), stock 1300 (asset). B: Activate | Draft MAP-000001 v1, then active; previous active mapping of that category superseded; the category's stock account = 1300 |
| Activation checks account kinds | Draft with stock account = an income account | B: Activate | Refused '<code> <name> is an income account; the stock account must be asset.'; a non-posting or inactive account -> '<code> is not an active posting account.' |
| Maker-checker on mappings | Draft by A; A holds mdm.finance.approve | A: Activate | Refused 'Somebody other than the person who prepared this account mapping must decide it.'; user without the permission: 'Activating an account mapping is Finance's decision (mdm.finance.approve).' |
Substitutes
| Action | When | What you do | What happens |
|---|---|---|---|
| Propose and approve a substitute | User A product.manage; user B mdm.steward | A: New substitute A -> B ratio 2, one way. A: Approve. B: Approve | Draft; A's approve refused 'Somebody other than the person who prepared this substitute must decide it.'; B approves -> approved; approve again -> 'This substitute is already approved.' |
| Use on a confirmed order (API) | Approved A -> B ratio 2; confirmed sales order line A qty 10 at AED 50, 4 delivered | POST /mdm/substitutions with the substitute, order and line | A Sales change order is requested: line A reduced to 4, add B qty 12 (6 open x 2) at AED 25.00 (50 / 2); substitution 'requested' until another person approves the change order; an unapproved or expired substitute -> 'This substitute is not approved for that product today; it cannot be used.' |
Catalogues
| Action | When | What you do | What happens |
|---|---|---|---|
| Publish a product | Catalogue WEB; released, sold product at price 50 | Open WEB -> choose the product -> Publish | Row published v1 with price 50.00; Published count 1; public GET /api/v1/catalogue/<key>/products lists code, names, unit, price, tax rate, barcode, channel images - no cost |
| Payload is a snapshot | Product published at 50 | Change the product price to 60; read the public API; then Publish again | Public API still 50.00 (v1) until republished; after Publish it shows 60.00 as v2 |
| Withdraw and checkout check | Two published products P-A 10.50, P-B 5.00 | Public checkout lines P-A x2, P-B x1; Withdraw P-B; checkout again | First: subtotal 26.00 (2 x 10.50 + 1 x 5.00). After withdraw: 'P-B is not available in this catalogue.'; GET products/P-B -> 404 'Product not found.' |
| Unsellable products not published | An inactive product (e.g. a variant of an unreleased template) | Publish it | Refused 'Only an active product that is sold can be published.' |
Imports
| Action | When | What you do | What happens |
|---|---|---|---|
| Preview with errors | mdm.import; units 'Unit' active | Upload CSV of products: row1 valid; row2 empty name; row3 same code as row1; row4 unit 'Box9'; row5 price 'abc' | Batch IMP-000001 previewed: 5 rows, 1 valid, 4 quarantined-to-be; problems 'name: missing', 'code: <code> appears twice in the file', "unit: 'Box9' is not an active unit of measure", "price: 'abc' is not a number"; NOTHING written to products yet |
| Commit valid rows only | The batch above | Write 1 valid rows | State committed; Written 1; the invalid rows state quarantined; the product exists; commit again -> 'This import is already committed.' |
| Discard | A previewed batch | Discard | State discarded; nothing written; Discard / Write buttons gone |
| Partner import | CSV partners: code blank, name, kind both, market consumer, tax_id | Upload with Import = Partners; Write | Partner created with an auto code; kind 'vendor' -> 'kind: customer, supplier or both'; existing code -> 'code: <code> is already a partner' |
| Row refused at commit | A valid-looking row the product save refuses (e.g. barcode taken between preview and commit) | Commit | That row quarantined with the save's reason added to its problems; other rows still written |
Data quality
| Action | When | What you do | What happens |
|---|---|---|---|
| Completeness arithmetic | 10 active products; rule products.barcode; 3 lack a barcode; one of them has an approved exception | Open Data quality and the Completeness report | Totals: 7 complete, 1 excepted, 2 incomplete of 10; the excepted row shows its reason; dashboard tile 'Complete products' = 7 |
| Exception maker-checker | Missing row; user A proposes an exception | A: Exception with reason; A: Approve; B: Approve | Proposed - record still counts missing; A's approve refused 'Somebody other than the person who prepared this exception must decide it.'; B approves -> excepted |
| Exception expiry | Approved exception Until yesterday (company local date) | Reload the report | The record is missing again |
Field security
| Action | When | What you do | What happens |
|---|---|---|---|
| Hide a custom field from a role | Product custom field 'origin'; user X without mdm.steward | Restrict origin: read permission mdm.steward, exportable off; X opens the product and exports the list | X does not see origin on the record, list or export; a steward sees it but it is not in exports |
| Write restriction keeps the value | origin restricted with write permission mdm.steward; X can edit products | X edits the product changing origin; Save | Save succeeds; origin keeps its stored value |
Reports
| Action | When | What you do | What happens |
|---|---|---|---|
| Each report runs | Data in each area | Open the six reports | Columns as listed; totals above; UOM audit shows the Unit conversions card; flags shown as ticks / crosses |
| UOM and barcode audit flags | A product barcode with a bad check digit made before this module; a dimension with two ratio-1 units | Open UOM and barcode audit | Bad code: Check digit ✗, bad_check_digit count 1; duplicate codes: Unique ✗ with both holders; dimension problem '2 reference units' |
References
| Action | When | What you do | What happens |
|---|---|---|---|
| Offer / withdraw a language or time zone | Languages list | Withdraw 'fr'; then Offer it | Offered flag toggles; withdrawn entries are no longer offered for new use (deployment-wide) |
Master Data features
| Action | When | What you do | What happens |
|---|---|---|---|
| Switching a feature off | Company admin | Turn off 'Governed imports'; open Master Data; try an import via API; re-enable | Imports menu disappears; upload refused 'Governed imports is disabled for this company.'; existing batches still readable via GET; back on -> works |
Master Data field settings
| Action | When | What you do | What happens |
|---|---|---|---|
| Required Trading name | Field setting Trading name = Required | New party without Trading name | Refused 'Trading name is required.'; set to Hidden: a value sent on New party refused 'Trading name is turned off.' |
Contacts list
| Action | When | What you do | What happens |
|---|---|---|---|
| Open, search, filter, group | Several test contacts, some archived | Open Contacts; search part of a name, then an email; remove the Active filter; filter Type = Supplier; group by Market; sort by Code | Matching rows only; archived rows appear only without the Active filter; tallies by type match the rows; 80 rows a page with paging |
| Open a contact by link | Contact CUST-00001 exists | Open a contact; copy the address bar (/contacts/contacts/CUST-00001); paste in a new tab | The same record opens directly (by code); a code that does not exist answers 'Record not found.' |
Customer 360
| Action | When | What you do | What happens |
|---|---|---|---|
| Create a company customer | partner.manage (and, today, company admin to see New) | New contact; Legal Name 'Test Trading LLC'; Entity Company; Country UAE, Emirate Dubai; Contact Type Customer; Save | Saved; record opens; code auto CUST-nnnnn when left blank; status Active; History shows the creation; Contacts list shows it |
| Create an individual (B2C) customer | New contact; Entity Type Individual; Market Consumer (B2C); name 'Test Person'; mobile +971500000003; Save | Saved as an individual; list Market column shows B2C | |
| Create a supplier | New contact; Contact Type Vendor; name 'Test Supplier LLC'; Save; open a new RFQ | Saved with kind supplier; it is offered as supplier on purchase documents and NOT as customer on sales documents ('Choose an active customer or supplier for this document.' if forced) | |
| Customer & vendor | Set Contact Type Customer & vendor; save; use it on a quotation and on an RFQ | Accepted on both sides; header chip 'Customer & vendor'; summary counts both receivable and payable | |
| Code rules | New contact with code 'cust-test01'; save; then try to change the code by API | Stored as CUST-TEST01; the code box is disabled after save; API change refused 'Customer code cannot change after creation.' | |
| Required fields refused | New contact; clear Legal Name; Save | Refused 'Name: Enter valid text (maximum 160 characters).'; the screen opens the tab of the refused field | |
| Edit and save, change history | A test customer | Edit; change phone, payment days 30, risk Medium; Save; open History tab | Saved; 'Saved.'; History rows list each changed field with old and new value, user and time |
| Discard unsaved changes | Edit; change the name; press Back to list | Prompt 'Discard unsaved customer changes?' with Keep editing / Discard changes; Discard leaves the stored record unchanged | |
| Edit conflict | Same customer open in two browsers | Save a change in browser A; then save a different change in browser B | Browser B is refused 'This record changed. Reload it before saving.'; nothing of B is written |
| Archive and restore | A customer with no open work | More > Archive; check the list; More > Restore | Archived: disappears from the default list, status chip Archived, cannot be chosen on new documents ('Choose an active customer or supplier for this document.'); Restore brings it back |
| Registered needs a TRN | Tax Registration = Registered; leave VAT Number / TRN empty; Save; then enter 100000000000003 and save | First save refused 'Tax id: Enter a tax registration ID for a registered customer.'; second saves; header chip 'VAT: 100000000000003' | |
| Address book | Addresses & Contacts: Add address; Purpose Billing; Country UAE; Emirate Dubai; City Business Bay; second address Delivery; mark Billing primary; Save | Both saved; only one primary; Sales & Delivery > Default Ship-To lists both rows | |
| Address validation | Add an address with country UAE but no emirate; Save. Then pick Dubai with a Sharjah city | Refused 'Choose the emirate for this address.'; then 'Choose a city or area that belongs to the selected state.' | |
| Contact persons | Add person 'Test Buyer', role Procurement, email buyer@example.test, preferred WhatsApp, primary; add a second with email 'x@y'; Save | Refused 'Enter a valid contact-person email.'; fix the email; saved with one primary person | |
| Add a bank account | partner.manage + partner.bank.reveal | Finance & Credit: Add bank account; Bank 'Test Bank PJSC'; IBAN 'ae07 0331 2345 6789 0123 456'; SWIFT TESTAEADXXX; Save | Saved with IBAN stored AE070331234567890123456 (spaces removed, upper case); first row primary; status Unverified; audit records the change |
| Bank validation | IBAN 'AE12'; then SWIFT 'TEST'; then two primary rows (API); then 11 bank rows (API) | 'Enter a valid IBAN (country, check digits, then the account).' / 'Enter an 8 or 11 character SWIFT / BIC.' / 'Only one bank account can be primary.' / 'Use at most 10 bank accounts.' | |
| Payment terms | Payment term 'Net 30' exists | Choose Payment Terms Net 30; also set days 45; Save; raise an invoice | Saved; the invoice due date follows the chosen term; with no term chosen it is invoice date + payment days (e.g. 1 Oct + 45 = 15 Nov 2026) |
| Payment days range | Payment terms (days) = 400; Save | Refused 'Payment days: Payment terms must be 0–365 days.' | |
| Credit exposure arithmetic | Customer with Credit limit 50,000 (Finite); one confirmed order of 10 units x AED 1,000, 10% discount, VAT 5%, not delivered; one posted invoice AED 15,000 not due | Open Finance & Credit > Credit Exposure | Open Sales Orders = 10 x 1,000 x 0.90 x 1.05 = 9,450.00; Open Invoices 15,000.00; Total Exposure 24,450.00; Available 25,550.00; Utilisation 48.9%; status Good (green) |
| Utilisation bands | Same customer | Raise exposure to 35,000 then 46,000 then 51,000 | 35,000 = 70.0% -> Watch (amber); 46,000 = 92.0% -> Limit near (red meter above 90); 51,000 = 102.0% -> Limit exceeded; available -1,000.00 shown red |
| Temporary limit | Base 50,000; today 2 Oct 2026 (Dubai) | Temporary Limit 10,000 valid 2026-10-01 to 2026-10-31; Save. Then set valid 2026-11-01 to 2026-11-30 | First: Temporary Limit 10,000, Effective Limit 60,000. Second: temporary shows '—', effective back to 50,000. Without dates refused 'A temporary credit limit needs the dates it is valid between.' |
| Credit check on order confirm (Hard block) | Limit 50,000, exposure 35,000, policy Hard block | Create and confirm a sales order of AED 20,000 incl. VAT | Refused 'Credit check: This takes exposure to 55000.00, 5000.00 over the limit of 50000.00.' (an approved credit override in Finance > Credit control can release it) |
| Credit check under Warn only / No credit check | Same numbers | Policy Warn only, confirm; then policy No credit check, confirm | Warn only: order confirms with a warning naming the excess; No credit check: no warning |
| Limit mode Not set / Unlimited / Blocked | Customer without a limit figure | Leave limit blank (Not set) under Hard block and confirm an order; then Unlimited; then Blocked | Not set: status 'No limit set', refused 'No credit limit is set for this customer, so this sale has no credit to draw on.'; Unlimited: allowed ('Credit is unlimited by decision and nothing is overdue.'); Blocked: refused 'Credit is blocked for this customer.' |
| Zero limit is zero credit | Limit 0, mode Finite, policy Hard block | Confirm any order | Status Limit exceeded 'The credit limit is zero, so no credit is available.'; the order is refused - 0 never means unlimited |
| Overdue status | An invoice due 10 days ago, AED 3,000 open | Open the record | Status Overdue: '3000.00 is overdue, the oldest by 10 days.'; Overdue tile shows the amount in warning colour |
| Transaction hold by type | A customer with a draft order and a draft invoice | Controls & History: Hold Type Sales orders, reason 'Test hold'; Save; confirm the order; post the invoice | Confirm refused 'Customer transaction hold: Sales orders. Test hold'; the invoice still posts. With All transactions both refused (purchase side too). Header note 'Hold: Sales orders' |
| Blocked and blacklisted | Overview: Blacklist on with reason 'Test'; Save; confirm a sales order. Then Blacklist off, Blocked on | Refused '<name> is blacklisted: Test.'; then '<name> is blocked.' ; credit status Blocked; refunds and reversals stay possible | |
| Hold needs a reason | Hold Type Invoices, no reason; Save. Then On Hold switch on with no reason | 'Enter a reason for the transaction hold.' / 'Enter a reason for the hold.' | |
| Registered documents and expiry | Saved customer; today 2 Oct 2026 | Documents: Add Trade License expiring 2026-12-31; VAT Certificate expiring 2026-09-30; Attach a PDF to the first; Save | Trade License status 'Expiring · 90d'; VAT Certificate 'Expired'; a third expiring in 2027-06 shows Valid; the PDF opens from the row and appears under All Files |
| Logo | Saved customer | Overview: Upload Logo (PNG) | Saved at once without Edit; shown on the Overview; a non-image refused 'The logo must be an image uploaded to this company.' |
| KPI tiles and drill-down | Customer with orders and invoices | Click Total Receivable, Overdue, Open Sales Orders, Open Invoices | Each opens the right list filtered to this customer; figures equal the open items list (foreign-currency items in AED at their frozen rate) |
| More menu shortcuts | More > New quotation; More > Sales orders; More > Open items and statement | A new quotation opens; the lists open filtered by the customer name | |
| A print template for partners exists | Print > (partner document type) | Preview opens for this contact; Print disabled while editing | |
| Pager | Several contacts on the list page | Open a contact; use Next / Previous | Moves through the list page in order; hidden while editing |
| Custom field on contacts | Admin defined a required text field 'Emirates branch' | Create a contact without it; then with it | Refused 'Emirates branch is required.'; then saved; the field appears as an optional column on the list |
Record credit review dialog
| Action | When | What you do | What happens |
|---|---|---|---|
| Record a credit review | Limit 50,000, risk Medium; credit.limit.reveal | Finance & Credit > Record credit review; limit 75,000; risk Low; reason; next review 2027-04-01; Record review | Limit becomes 75,000, risk Low, Last Credit Review today, Reviewed by you; a row in Credit Review History with old 50,000.00, new 75,000.00, exposure at the time; it cannot be edited or deleted (a form save keeps it) |
| Review needs a reason | Open the dialog; leave Reason empty | Record review button stays disabled; API without reason refused 'Reason: Enter valid text (maximum 240 characters).' |
Custom fields
| Action | When | What you do | What happens |
|---|---|---|---|
| Add a custom field | Company administrator | Add custom field; Applies to Contacts; Key 'emirates_branch'; Label; Type Text; Save; add the same key again | Created; shown on the contact General tab; the second refused 'That key is already used on this model.' |
Countries / States / Cities
| Action | When | What you do | What happens |
|---|---|---|---|
| Geography masters | Administrator | Create country ZZ 'Testland', division name Province; a state TST under it; a city and an area within the city | All saved; the address picker for Testland is labelled Province; an area without a city refused 'An area needs the city it belongs to.' |
Products list
| Action | When | What you do | What happens |
|---|---|---|---|
| Search, filter and open | Some products, one with a picture | Search by barcode; filter Type; show the Barcode column; open a row | Correct rows; thumbnails for products with a picture; On hand shows '—' for services |
Product record
| Action | When | What you do | What happens |
|---|---|---|---|
| Create a stocked product | product.manage; unit 'Unit', category 'Furniture', tax code VAT5 | New product; code TST-1001; name; type Stocked goods; unit Unit; category; price 899; cost 450; Taxes VAT5; Save | Saved 'Saved successfully'; opens read-only; Tax % 5.00; Inventory, Logistics tabs present; list shows the row |
| Create a service | New product; type Service; price 300; Save | Saved with kind service; no Inventory / Manufacturing / Logistics tabs; On Hand and Forecast smart buttons hidden; Manufacturing toggle refused if forced | |
| Product type locks | A goods product on a confirmed sales order; another goods product with 5 on hand | Change the first to Service; change the second to Non-stocked goods | First: 'This product is already on documents, so it cannot switch between stocked and non-stocked. Create a new product instead.'; second: 'This product has stock. Set on-hand quantity to zero before making it a service or non-stocked item.' |
| Edit conflict | Product open in two browsers | Save price change in A, then cost change in B | B refused 'This record changed. Reload it before saving.' |
| Archive, discontinue, restore | Status Discontinued; Save; then More > Archive; then Restore | Discontinued: chip Discontinued, Active for Purchase off and locked ('A discontinued product is not bought.'), RFQ refused 'This product is disabled for this document type.'; Archived: new documents refuse 'Archived products cannot be added.'; Restore: Active | |
| Price and cost history | product.cost.view | Change price 899 -> 949 and cost 450 -> 470; Save; open Sales & Pricing and Controls & History | Price History rows: Sales price 899.00 -> 949.00 and Standard cost 450.00 -> 470.00 with user; change history lists both fields |
| Multiple tax codes | Tax codes VAT5 (5%) and a test levy LEVY2 (2%) for sale | Taxes: VAT5 + LEVY2; Save; then remove both | Combined rate 7.00% and Tax % 7.00 on the list; documents use 7%; removing all sets 0.00% ('No tax') |
| Cost hidden without permission | User without product.cost.view | Open a product; edit price; Save | Standard Cost shows '•••', Accounting tab says it is for people who may see cost, supplier Quoted Cost column hidden; the save does not change the cost |
| Unit of measure and base unit | Units kg (weight, 1) and g (weight, 0.001) | Choose unit g; look at Base Unit; post a receipt; try to change the unit | Base Unit shows kg; after the product is used the change is refused '<CODE> is already on posted documents or stock moves, so its base unit is fixed...' |
| Generate and print barcode | Product in edit with no barcode | Click the barcode button; Save; click it again; Labels 24; Print | A 13-digit in-store EAN starting 2 with a correct check digit; after save the button opens Print Barcode Labels; a page of 24 Code 128 labels opens; count 200 is printed as 120 |
| Barcode uniqueness | Product A has barcode 6291000000017 | Give product B the same primary barcode; then as B's alternate; then as B's packaging barcode | '6291000000017 already identifies A.' / 'Barcode and PLU values must be unique across products.' (both other cases) |
| Scale barcode setup | PLU 12345; Scale mode Embedded weight; prefix 21; decimals 3; Save. Then PLU 123 | Saved; with PLU 123 refused 'Scale barcodes require a two-digit prefix and five-digit PLU.' | |
| Variants to products | Parent TST-1001 price 899, cost 450 | Variants: Color Red SKU TST-1001-RED price diff 50 cost diff 20; Color Blue SKU TST-1001-BLU; Save; click Create product on each | Message 'Product TST-1001-RED created.'; new product name 'Test Office Chair - Red', price 949.00, cost 470.00, own stock; Blue 899 / 450; the row links to the variant product; a second click refused 'This variant already has its product.' |
| Variant refusals | Two rows with the same SKU; a row with attribute 'Shade' (API); create a product before saving the row; a SKU equal to an existing product code | 'Each variant needs its own SKU.' / 'Shade is not a variant attribute. Add it under Configuration > Variant attributes.' / button shows 'Save first' / 'Another product already uses this SKU as its code.' | |
| Supplier references and preferred supplier | Two supplier contacts | Purchase tab: add both; mark one Preferred with quoted cost 420; Save; More > Create purchase | Saved; the dialog pre-selects the preferred supplier; Create RFQ opens a draft RFQ at 420.00 for qty 1; a customer-only contact refused 'Choose a supplier contact.' |
| Packaging | Add Carton qty 6 with barcode; Pallet qty 240; Save | Saved; a scan of the carton barcode adds 6 units; duplicate names refused 'Packaging names must be unique per product.' | |
| Quick sale | document.draft; product sale enabled | More > Create sale; customer; quantity 5; Create quotation | A draft quotation opens with 5 x sales price and the sales description; a product with Can be Sold off has no Create sale (API refuses 'This product is not for sale.') |
| Stock figures and reordering rule | Goods product: 10 on hand in Main, 2 reserved, incoming PO 5, outgoing order 3; inventory.operate | Open Inventory tab; add rule Main min 10 max 50; Save rule | On Hand 10, Reserved 2, Available 8, Incoming 5, Outgoing 3, Forecast 12 (10+5-3); stock by warehouse; rule listed; min 50 max 10 refused 'Maximum must not be below minimum.' |
| Tracking change locked by stock | Product with 4 on hand, tracking none | Set tracking Lot; Save | Refused 'Set on-hand quantity to zero before changing tracking or valuation scope.'; at zero stock it saves |
| Expiry needs lot tracking | Tracking none, Expiry Management on (API); then tracking Lot + expiry + shelf life 365 | 'Expiry management requires lot tracking.'; with Lot it saves; FEFO removal can be chosen | |
| Category accounts and overrides | Category Furniture costing FIFO, stock account 1300; product.cost.view | Accounting tab: look at Valuation; set COGS override to a test COGS account; receive and sell 1 unit | Costing method FIFO and accounts inherited from the category; the sale's cost of goods posts to the override; Revenue override is marked 'recorded' and not used yet |
| Share product with another company | You hold product.manage in companies A and B | General > Company Access: tick B; Apply sharing; set B's cost 455 and price 925; edit the name in A | 'Shared with B'; B has a linked copy with its own cost 455 / price 925; renaming in A also renames in B; cost and stock stay per company; unticking B with stock refused '<B> still holds stock of <CODE>; it stays shared until that stock is zero.' |
| Product documents | Saved product | Documents: type Datasheet, upload a 1 MB PDF; then remove it | Listed with type, size and date; download works; removal asks the current revision and records history; a 12 MB file refused 'Keep a document under 10 MB.' |
| Product image save | Edit; drop a 1 MB PNG; Save; then a 3 MB JPEG; Save | 1 MB saved and shown in the list thumbnail; 3 MB passes the screen check (5 MB) but the server refuses: 'Product saved; the image was not. Save again. Images must be no larger than 2 MB.' | |
| Print product sheet | Print > Product sheet | An HTML product sheet opens in a new tab with code, name, prices allowed to you | |
| Smart button drill-downs | Product with sales and purchases | Click On Hand, Forecast, Sales, Purchases | Each dialog shows the figures behind the count with a link to the full list filtered by the product code; Forecast below zero shows in warning colour |
Product barcode lookup
| Action | When | What you do | What happens |
|---|---|---|---|
| Scan resolves the product | Product with primary, alternate (Supplier) and packaging Carton = 6 | Look up each code (scanner field / GET product-barcodes/{code}) | Primary -> qty 1 source primary; alternate -> source supplier; carton barcode -> source packaging, unit Carton, quantity 6; unknown -> 'No product has this barcode.' |
Duplicate Product
| Action | When | What you do | What happens |
|---|---|---|---|
| Duplicate a product | TST-1001 with barcode, variants, suppliers, packaging | More > Duplicate product; leave code blank; tick Copy purchasing and Copy packaging; Duplicate | New product TST-1001-COPY 'Test Office Chair (copy)' opens; price and cost 0 (pricing not ticked); suppliers and packaging copied but packaging barcodes blank; no primary barcode, PLU, alternates or variants; picture copied |
Stock on hand
| Action | When | What you do | What happens |
|---|---|---|---|
| Stock on hand report | Goods products with receipts | Catalogue > Reporting > Stock on hand; switch to Pivot | One row per goods product with On hand, Standard cost and Stock value (from the valuation layers, equal to the product On Hand); services not listed; pivot adds them up. Check a company with more than 80 products |
Product categories
| Action | When | What you do | What happens |
|---|---|---|---|
| Category tree and costing | reference.manage | New category OFFICE; New category CHAIRS with parent OFFICE, costing FIFO; then set OFFICE's parent to CHAIRS | Both saved; the loop refused 'Category hierarchy cannot contain a cycle.'; Products smart button opens products searched by the category name |
Units of measure
| Action | When | What you do | What happens |
|---|---|---|---|
| Unit ratio frozen once used | Unit 'g' (weight 0.001) used by a product | Change its ratio to 0.01 | Refused 'A unit used by products cannot be redefined. Create a new unit.'; an unused unit changes |
Variant attributes
| Action | When | What you do | What happens |
|---|---|---|---|
| Default and new attributes | A new test company | Open Variant attributes; add 'Voltage'; add 'color' again; rename 'Color' after a product uses it | Six defaults appear on first open (Color, Size, Material, Capacity, Pack size, Flavor); Voltage offered on the Variants tab; 'There is already a variant attribute with this name.'; 'A variant attribute used by products cannot be renamed. Archive it and add a new one.' |
Brands / Product groups / Manufacturers
| Action | When | What you do | What happens |
|---|---|---|---|
| Archive a master in use | A brand used by products | Archive the brand; open a product using it; open a new product | The existing product keeps and still saves its brand; the archived brand is not offered on the new product; (API) choosing it refused 'Select an active master of the correct type.' |