Business Rules and Control
How the portal refuses before it writes, how the consultant sets thresholds and scopes, and how to read the log of sensitive changes.
The principle
AVIA ERP refuses before it writes. A goods receipt beyond the allowed tolerance, a document closed against a fiscal period under closing, an amount above a customer's credit limit: the portal blocks the operation before it touches the database, never after the fact.
Every refusal carries a stable code, a message in the user's own language stating the problem and what to do about it, and actionable parameters (the threshold exceeded, the missing field, the period involved…). The exact shape is detailed further down this page.
The consultant who deploys AVIA ERP configures thresholds and scopes — never hard-coded business logic. Each rule type stays tested code; what changes from one client to the next is the values. Before activating a rule, it is simulated against the real documents of the last 90 days: how many would have been evaluated, how many would have been blocked.
In numbers: 16 rule types plus the risk-threshold type, 10 ready-made packs (4 by trade, 4 normative, plus management-control and internal-control packs), analytical dimensions (affair / department / cost center) with required-dimension and forbidden-combination rules, and lot/serial traceability from receiving through to the serial record.
Settings › Business Rules
The Business Rules screen
The screen lives under Settings → System → Business Rules. It lists active rules with their type, scope, target, parameters, when they apply, creation date and status.

The list of active rules: type, scope, target, parameters, when it applies, and status.
Create a rule
The creation form is generated from the type catalog (GET /api/v1/rules/types): choosing a type automatically shows its possible scopes (tenant, supplier, item or customer depending on the type) and its own parameters.
Simulate before activating
The Simulate on the last 90 days button replays the entered parameters against the period's real documents, without changing anything, and shows how many documents were evaluated and how many would have been blocked.

Before activating a rule, it is simulated against the real documents of the last 90 days.
Disable, never delete
The toggle calls a plain PUT that sets active to false: the rule stops applying but stays in the record, reversible at any time. A rule is never deleted.
A ?module= filter narrows the list to one module — that is what the Rules for this module link follows from Settings → Purchasing.
Packs by trade
Ready-made rule packs exist by trade (textile, precision machining, wiring and metalwork, transport and logistics) through GET /api/v1/rules/packs. They can be simulated, then applied: rules are inserted disabled, to be switched on one by one after review. Applying an already-applied pack does not duplicate anything.

Simulate a pack before applying it: evaluated / blocked per rule, on the last 90 days.
Available rule types
Rule type catalog
Six rule types cover the common control points. For each one, this table gives the possible scope, when the rule applies and, most importantly, the behaviour when no rule is configured for that type — the default a tenant gets before configuring anything.
| Type | Parameters | Scope | When | Without configuration |
|---|---|---|---|---|
Over-receipt tolerancesur_reception | pct_max, abs_max, illimitee | Tenant, supplier, item | On entry | No limit applies |
Field required at statuschamp_requis_statut | table, statut, champs | Tenant | On close | No field required |
Closed periodperiode_close | tables, bloquer_closing | Tenant | On close | No period is controlled |
Customer credit limitlimite_credit_client | tolerance_pct, inclure_commandes, mode | Tenant, customer | On close | No check, even if a credit limit is set |
Amount-based approvalapprobation_montant | paliers seuil:rôle, mode | Tenant, supplier | On close | The historic purchase-request grid applies (5,000 → purchasing, 50,000 → purchasing management) |
Required workflowworkflow_requis | tables, mode | Tenant | On close | No approval required |
For amount-based approval, tiers are declared as threshold:role, for example 5000:achat, 50000:directeur_achat. Without a configured rule, the historic purchase-request grid keeps applying: 5,000 triggers a purchasing approval, 50,000 a purchasing-management approval. Period-close depends on the fiscal periods configured under Finance; required workflow only fires when an approval workflow is actually active for the document — with no active workflow, closing is unaffected.
Change history
What gets logged
Every change to a field declared sensitive is logged: field, old value, new value, author and date. The mechanism relies on a declaration table (sensitive_fields) and a log table (field_changes), fed by a generic trigger — a newly declared field is logged without any extra application code.
| Type | Field |
|---|---|
| Suppliers | Bank account, bank, SWIFT/BIC, credit limit, blocked flag, payment terms and method |
| Customers | Credit limit, blocked flag, payment terms and method |
| Items | Cost price, sale price, purchase price, weighted average cost, last purchase price, blocked flag |
| User rights | Read, create, update, delete, module |
| Profiles | Role, department, active or not |
Declare an additional field
A consultant declares an additional field to log through the sensitive-fields resource, on the sibling Logged fields page (next to Business Rules under Settings → System): pick the table (suppliers, customers, items, employees, profiles, user rights) and the field. A declared field can also be turned off without losing the history already written.

Logged fields screen: one row per declared field, table by table, with its toggle and declaration date.
It is read on the History tab of the supplier, customer or item record.

Every change to a sensitive field keeps the old value, the new value, the author and the date.
Bank values (account number, IBAN) stay masked except for the last 4 characters. An empty value and a missing one (NULL) are treated as equivalent so a save doesn't log a false change, and the author is set on every write path, including imports and the API.
Document flow
The Document Flow panel
"Where does this invoice come from?" The Document Flow panel answers by tracing the chain of conversions: quote, sales order, purchase order, goods receipt, invoice. Every conversion (quote → order, quote → invoice, order → work order, purchase request → order, receipt → supplier invoice…) adds a link in the document_links table, exposed by GET /api/v1/document-flow/{type}/{id}.

The flow traces back from quote to invoice; every conversion adds a link.
The same flow appears as a preview (factbox) on the invoice, supplier and purchase-order lists when a row is selected.
Rights per action and per read
Arm rights without surprises
Two settings control how rights are enforced: AUTH_GUARD_MODE for write actions and AUTH_GUARD_READ_MODE for reads, each with three values: off (no check), observe (the refusal is logged but let through) and enforce (the refusal actually blocks). Both default to off.
Arming happens module by module through AUTH_GUARD_ENFORCE_MODULES, a list shared between writes and reads. The volume of observed reads is sampled (AUTH_GUARD_READ_LOG_SAMPLE, 100 by default) to keep the logs from flooding.
Observe, fix, arm
GET /api/v1/admin/auth-guard/observations returns the current mode, the read mode, the modules already armed, and a count of the refusals that would have happened per module and per action. Recommended procedure: observe a representative period, fix the roles missing a legitimate right, then arm the module.
A right refusal, once armed, answers 403 with the code droit_insuffisant — actionable, unlike a plain generic error. A module outside the subscription answers 404: the user doesn't even know it exists.
What a refusal says
The shape of a refusal
Every refusal takes the same shape: { code, params, message }. The message is already translated into the user's language (French, English or Arabic); params carries the values useful for display or for a fix (threshold, field, period…).
{
"code": "limite_credit_depassee",
"params": { "client": "CL-00042", "limite": 15000, "encours": 15820 },
"message": "Customer CL-00042 is over their credit limit of 15,000 TND (outstanding 15,820 TND)."
}| Code | Means |
|---|---|
ligne_sans_prix | A document line has no price |
ligne_sans_quantite | A document line has no quantity |
sur_reception | The received quantity exceeds the allowed tolerance |
referentiel_bloque | The party or item involved is blocked |
periode_close | The accounting period involved is under closing |
limite_credit_depassee | The customer is over their credit limit |
approbation_requise | The amount requires approval before closing |
workflow_requis | An active approval workflow has no approved instance |
document_fige | The document is locked and can no longer be edited |
totaux_incoherents | The document totals don't match its lines |
document_introuvable | The referenced document doesn't exist or is no longer accessible |
droit_insuffisant | The user doesn't have the right to perform this action |
The copilot reads this same structured refusal to explain it in plain language and guide the user toward the fix — changing the received quantity, choosing another period, requesting an approval.
Seven sibling pages go deeper: the full type catalog (one sheet per type — parameters, refusal, simulation, normative reference), the packs by trade (rule-by-rule composition and a consultant checklist per pack), the deployment procedure on a new tenant (rights, condition and severity, sensitive fields, risk signals, the copilot), examples by sector (six journeys with the real clients named in the packs — textile, precision machining, cabling/metalwork, transport and logistics, management control, internal control), pilotage (role centers, factbox, action center, risk signals, affair report, copilot), the copilot (explaining a refusal, guided procedures, confirmed actions, what it never does), and status profiles (restricting without widening, a role per transition, simulation).
See Administration for user roles and API & Integrations for authentication.




