The approval workflow engine handles sales, purchase and journal approvals out of the box. Extensions can plug their own documents into it: a custom event ("courier shipment released"), a custom response, and the approval entries, delegation and notifications that come free. How the engine fits together and the four subscribers it takes to add your document to it.
Users like approvals. They do not like a second approval system built by an extension when the standard one is already configured with their approvers, delegations and email notifications. The workflow engine is extensible for exactly this: your document can raise an event the engine understands, and the standard approval responses can act on it.
A workflow is a sequence of steps; each step is a workflow event (something happened: "approval of a sales document is requested") followed by one or more workflow responses (do something: "create an approval request", "send notification", "release the document"). Events and responses are registered in a library by function name; the Workflow Event Handling and Workflow Response Handling codeunits hold Microsoft's. The approval entries table records who must approve, the status, delegation and due dates; the Approvals Mgmt. codeunit creates and processes them; the Workflow Management codeunit matches a raised event to active workflows and runs the responses.
Four subscribers and one call.
codeunit 50130 "CON Shipment Workflow"
{
var
SendForApprovalEventTok: Label 'CONSHIPMENTSENDFORAPPROVAL', Locked = true;
SendForApprovalDescTxt: Label 'Approval of a courier shipment is requested.';
// 1. register the event in the library
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Event Handling", OnAddWorkflowEventsToLibrary, '', false, false)]
local procedure AddEvents()
var
WorkflowEventHandling: Codeunit "Workflow Event Handling";
begin
WorkflowEventHandling.AddEventToLibrary(SendForApprovalEventTok, Database::"CON Courier Shipment", SendForApprovalDescTxt, 0, false);
end;
// 2. say which standard responses may follow it (create approval request, send notification...)
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Response Handling", OnAddWorkflowResponsePredecessorsToLibrary, '', false, false)]
local procedure AddPredecessors(ResponseFunctionName: Code[128])
var
WorkflowResponseHandling: Codeunit "Workflow Response Handling";
begin
case ResponseFunctionName of
WorkflowResponseHandling.CreateApprovalRequestsCode(),
WorkflowResponseHandling.SendApprovalRequestForApprovalCode():
WorkflowResponseHandling.AddResponsePredecessor(ResponseFunctionName, SendForApprovalEventTok);
end;
end;
// 3. let Approvals Mgmt. open/set status on your record
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Approvals Mgmt.", OnSetStatusToPendingApproval, '', false, false)]
local procedure SetPending(RecRef: RecordRef; var Variant: Variant; var IsHandled: Boolean)
var
Shipment: Record "CON Courier Shipment";
begin
if RecRef.Number Database::"CON Courier Shipment" then exit;
RecRef.SetTable(Shipment);
Shipment.Validate(Status, Shipment.Status::"Pending Approval");
Shipment.Modify(true);
Variant := Shipment;
IsHandled := true;
end;
// 4. and populate the approval entry's details (amount, salesperson for limits)
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Approvals Mgmt.", OnPopulateApprovalEntryArgument, '', false, false)]
local procedure Populate(var RecRef: RecordRef; var ApprovalEntryArgument: Record "Approval Entry"; WorkflowStepInstance: Record "Workflow Step Instance")
begin
if RecRef.Number Database::"CON Courier Shipment" then exit;
ApprovalEntryArgument."Document Type" := ApprovalEntryArgument."Document Type"::Order;
// amount, currency, salesperson as needed for approval limits
end;
}
Then your "Send Approval Request" action raises it:
WorkflowManagement.HandleEvent(SendForApprovalEventTok, Shipment);
Mirror the pattern for cancel and for "released" (so the standard "release document" response can set your status back), and add OnReleaseDocument / OnOpenDocument subscribers so the standard responses can call your Mgt. codeunit.
The approval entries page and FactBox, approval limits by user, delegation and substitutes, due dates and overdue notifications, email and in-client notifications via the standard notification setup, the Requests to Approve list on the role centre, and the workflow designer where the administrator can add conditions ("only if weight over 500kg") without code. Ship a workflow template too (subscribe to OnAddWorkflowTemplatesToLibrary) so the administrator starts from a working one.