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.

Settings › System › Business Rules screen with a 5% over-receipt tolerance rule

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.

New rule form with the result of a 90-day simulation

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.

Simulating the ISO 9001 baseline pack on Settings › Business Rules, showing the per-rule result

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.

TypeParametersScopeWhenWithout configuration
Over-receipt tolerance
sur_reception
pct_max, abs_max, illimiteeTenant, supplier, itemOn entryNo limit applies
Field required at status
champ_requis_statut
table, statut, champsTenantOn closeNo field required
Closed period
periode_close
tables, bloquer_closingTenantOn closeNo period is controlled
Customer credit limit
limite_credit_client
tolerance_pct, inclure_commandes, modeTenant, customerOn closeNo check, even if a credit limit is set
Amount-based approval
approbation_montant
paliers seuil:rôle, modeTenant, supplierOn closeThe historic purchase-request grid applies (5,000 → purchasing, 50,000 → purchasing management)
Required workflow
workflow_requis
tables, modeTenantOn closeNo 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.

TypeField
SuppliersBank account, bank, SWIFT/BIC, credit limit, blocked flag, payment terms and method
CustomersCredit limit, blocked flag, payment terms and method
ItemsCost price, sale price, purchase price, weighted average cost, last purchase price, blocked flag
User rightsRead, create, update, delete, module
ProfilesRole, 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.

Settings > Logged fields screen, Suppliers section, with bank, blocked flag, credit limit and payment fields, each active by default

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.

History tab on the supplier record, bank details masked except the last 4 digits

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}.

Document Flow panel on an invoice, showing the originating quote it was converted from

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…).

Example refusal
{
  "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)."
}
CodeMeans
ligne_sans_prixA document line has no price
ligne_sans_quantiteA document line has no quantity
sur_receptionThe received quantity exceeds the allowed tolerance
referentiel_bloqueThe party or item involved is blocked
periode_closeThe accounting period involved is under closing
limite_credit_depasseeThe customer is over their credit limit
approbation_requiseThe amount requires approval before closing
workflow_requisAn active approval workflow has no approved instance
document_figeThe document is locked and can no longer be edited
totaux_incoherentsThe document totals don't match its lines
document_introuvableThe referenced document doesn't exist or is no longer accessible
droit_insuffisantThe 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.