FCORE_BASE namespace. Instead of writing logic in trigger files, you write small handler classes — trigger units — and register each one against an object through Custom Metadata. The framework decides which units run, in what order, and whether to run at all.
This design gives you a few things for free:
- A single, predictable execution path for every object’s automation.
- Per-object, per-handler, per-user, and org-wide on/off switches without code changes.
- A clean separation between automation logic and validation logic.
Writing a Trigger
A trigger file contains exactly one line. It constructs aFCORE_BASE.TriggerExecutor for the object’s SObjectType and calls execute(). Never put logic in the trigger file itself — the executor delegates to your registered trigger units.
FCORE_BASE.TriggerExecutor exposes:
TriggerExecutor(SObjectType)— constructor; pass the object’sSObjectType.execute()— runs every enabled trigger unit registered for that object, in order, for the current trigger context.
Writing a Trigger Unit
A trigger unit is an Apex class that extends the abstract classFCORE_BASE.TriggerUnit. By convention its name ends in TU. Override only the contexts your unit needs — every context method is a global virtual void with an empty default implementation.
Available Contexts
Use
bulkBefore() and bulkAfter() to do shared, query-once setup (for example, loading related records) that the per-context methods then consume — this keeps your unit bulk-safe.
Registering a Trigger Unit
Registration uses two Custom Metadata types. When you reference them from Apex or in metadata files, the API names carry theFCORE_BASE__ namespace prefix.
FCORE_BASE__Trigger__mdt — one record per object
This record enables the framework for an object and is the anchor that trigger units link to.
FCORE_BASE__Trigger_Unit__mdt — one record per handler
This record registers a single trigger unit class against an object’s Trigger__mdt record.
A
Trigger_Unit__mdt record looks like this:
Ordering
Trigger units for one object run in ascendingFCORE_BASE__Order__c — a unit with Order 10 runs before a unit with Order 20. Leave gaps between values (10, 20, 30, …) so you can slot a new unit between two existing ones later without renumbering everything.
Turning Triggers Off
Bypass is layered. Each layer is independent, and the framework checks them in this sequence — any one of them stops a unit from running:Disabling for the Current Transaction
FCORE_BASE.TriggerExecutor.TRIGGER_CONTEXT is a TriggerContext you can use to suppress automation programmatically — for example, around a data fix in an anonymous block or a one-off script. These changes apply only to the current transaction; re-enable as soon as the protected DML is done.
TRIGGER_CONTEXT exposes these methods, each taking a String:
disableSObject(String)/enableSObject(String)— toggle every unit for one object.disableClass(String)/enableClass(String)— toggle one unit by class name.disableValidations()/enableValidations()— toggle validation units as a group (see below).
Validation Triggers
Validation-only logic belongs in its own kind of unit. A validation unit extendsFCORE_BASE.ValidationTriggerUnit — an abstract subclass of TriggerUnit — and registers through the same Trigger_Unit__mdt records as any other unit. By convention its name ends in VTU.
Keeping validations in their own units means you can switch them off as a group without touching the automation units that should keep running.
- Metadata gate:
FCORE_BASE__Org_Setting__mdt.Global_Validations_Enabled__c— whenfalse, everyValidationTriggerUnitis skipped. - Runtime gate:
FCORE_BASE.TriggerExecutor.TRIGGER_CONTEXT.disableValidations()/enableValidations()— suppress validation units for the current transaction (for example, during a data migration).
addError() directly:
ValidationTriggerUnit, both Global_Validations_Enabled__c and disableValidations() skip it automatically — you do not need to add your own enabled check. See Utility Functions for the full set of ValidationUtils helpers.
Prefer a Validation Trigger Unit Over a Declarative Validation Rule
When you need new validation logic, build it as aValidationTriggerUnit rather than a declarative Salesforce Validation Rule. A validation trigger unit gives you two things a Validation Rule cannot:
- Ordering —
FCORE_BASE__Trigger_Unit__mdt.FCORE_BASE__Order__cpositions your validation relative to every other trigger unit on the object, including other validations. - Programmatic disable —
FCORE_BASE.TriggerExecutor.TRIGGER_CONTEXT.disableValidations()and the per-handlerFCORE_BASE__Trigger_Unit__mdt.FCORE_BASE__Is_Enabled__cfield can turn the check off for a single transaction or a single handler, without a metadata deployment.
Active checkbox — it cannot be reordered against other automation, and disabling it for one transaction (for example, during a data migration) means deactivating it org-wide first.
Gating a Declarative Validation Rule
If a declarative Validation Rule is still the right tool — for example, a simple field check on a standard object with no accompanying Apex — gate it onGlobal_Validations_Enabled__c too, so it can be disabled the same way as validation trigger units. Every validation rule shipped with fusionCore follows this pattern (for example PricebookEntry.Block_Standard_Price_Change).
Add the gate as another AND condition if your formula already uses the AND() function:
&& operator if your formula is written with infix logic:
Unlike a
ValidationTriggerUnit, a declarative Validation Rule does not gate on Global_Validations_Enabled__c automatically — you must add the condition yourself. The flag also only gates the rule at runtime; it has no effect on ordering. If ordering matters, build the check as a ValidationTriggerUnit instead.
