Electronic Approval
Connect an App record action to Nexia Electronic Approval by shipping a binding, document schema, and slot widget together.
Send an existing App record through Electronic Approval and apply the outcome to that record. Start with a protected Resource and its submission action; Create a Resource provides that baseline.
Connect the action
- Publish an
ApprovalFormBindingDescriptorandApprovalDocumentSchemafromAppDescriptorContribution::appDescriptors(). Chooselinkfor an existing record orcreatewhen submission creates it. The schema contains the evidence the approver will read. - Add the matching Add a Slot Widget in
approval.composer.business_form, usingApprovalBusinessFormSlotPropsV2. Its key must equalformWidgetKey, and its registered component must exist. - Implement the protected App submission with the Electronic Approval contracts. Validate the subject, current actor, organization, payload, and idempotency identity before calling the host. Persist a durable handoff when the App and host transactions cannot commit together.
- Consume the committed outcome through the App's event handler. Recheck the subject and current domain state; apply the effect once. Approval records a decision, while your App owns the record transition.
The binding in packages/assets/src/Descriptors/AssetApprovalDescriptors.php uses the same action identity for the form and submission permission. This constructor-valid example expands its asset_movement/submit pair:
new \Nexia\AppDescriptors\ApprovalFormBindingDescriptor(
appKey: 'assets',
resourceKey: 'asset_movement',
actionKey: 'submit',
labelKey: 'assets.approval.asset_movement.submit.label',
entryModes: ['link'],
formWidgetKey: 'assets.asset_movement.submit',
documentSchemaKey: 'assets.asset_movement',
descriptionKey: 'assets.approval.asset_movement.submit.description',
);This declares a binding; it does not create the schema, component, or protected action. Ship those together. When submitPermissionKey is omitted, the permission is the derived binding key, here assets.asset_movement.submit.
Confirm the result
In an operational tenant, the authorized actor can select the published business template, load the App form, and submit the record. The approver sees the frozen evidence. A repeated submission must converge to the same handoff, and replaying the outcome must not repeat the business effect. A forbidden actor must fail even when calling the App endpoint directly.
packages/assets/tests/Feature/AssetBoundApprovalSubmissionTest.php is an existing integration example. Use Test an App for the test workflow and Handle events and jobs for durable delivery.
Templates, lifecycle, and Process
A code binding exposes an App capability. A tenant-owned Approval Form Template selects that binding and supplies editable presentation/routing configuration; publishing one does not install the App or grant its permissions. Approval form presets are tenant scoped.
Deprecate a binding before removing it: Deprecated blocks new selection while existing references resolve; Removed stops resolution. Exact descriptor fields, replay semantics, document snapshots, attachment evidence, and host results belong in Electronic Approval contracts.
For follow-up work in BPMN, use Business Process. For a recipient signing an immutable document, use Electronic Signature. If discovery succeeds but the form is blank, check the binding/widget/component keys together before changing authorization.
Connect the approval requirement setting
Publishing a binding does not block direct execution. Declare supportsRequirementPolicy: true only after both direct and approval-submission paths for the same operation apply ApprovalRequirements::required(bindingKey, legalEntityKey, default, contextKey) and block unapproved effects when required. Never trust a browser-supplied approval_required flag or create a separate policy table for every Resource.
For purchase-request submission, ProcurementApprovalDescriptors publishes procurement.purchase_request.submit, and SubmitProcurementApproval::required() reads the shared requirement. Direct execution and the Process handler use the same submission service. create starts a new submission and link submits an existing document; neither permits committed business effects before required approval. Internal draft persistence is separate from business finalization.
Administrator setup sequence
- In Approval → Form templates, create a business form for the operation and choose company-wide or Legal Entity ownership.
- Set the form's Line selection mode to a designated line or submitter selection, then publish it. Selecting a line does not determine whether approval is required.
- In Approval → Operation requirements, choose the App and scope. Enabling required approval needs a published form and a usable line-selection mode. Use that operation's form-setup link when preparation is missing.
- Compare direct-screen and Process execution for the same actor and operation using the results below. Check new executions after configuration changes; do not overwrite in-flight approval snapshots with a new policy.
Resolution order and results
Conditional operations resolve the latest explicit value in this order: Legal Entity condition → Legal Entity default → company condition → company default → App business rule. Clearing an override records a new revision that falls through to the next source, rather than restoring an older value. The settings screen shows the inherited source and effective result.
| Setting | New operation execution | Composer and existing history |
|---|---|---|
| Approval required | The App blocks unapproved effects and uses formal submission | Submit through a compatible business form; approval outcomes determine final effects |
| Approval not required | The App executes its direct path with authorization and domain validation | Hide that new composer entry; retain existing cases and in-flight snapshots |
| No explicit override | Inherit through the precedence above, finally using the App rule | Narrower conditions that still require approval retain their entry path |
Expose configurable domain conditions and defaults through ApprovalRequirementContextProvider. Return entity-owned conditions only for that entity. Use requirementPolicyLegalEntityScoped: false for company-owned rules and requirementPolicyContextsOnly: true when only condition-specific settings are allowed. See Electronic Approval contracts for the exact contract.
When a Process obtains its approval line
A form's designated line resolves under the actual execution context at submission. When submitter selection has no line yet and the Work Action supports supportsLinePreparation, Core creates a preparation task for the execution actor and resumes the same operation after completion. Preparation is not approval. The handler submits an actual case and returns waitingForApproval(...) to await its outcome. Missing context or an unavailable assignee never causes automatic success.
Follow the purchase flow in Business Process to connect proposal inputs, optional review, draft creation, and approval-outcome branches. Model changes and cancellations as separate operations and new approvals; never rewrite the original case's approval evidence.