CPQ for Microsoft Dynamics 365 BC supports custom procedures that let you implement your own business logic and execute it dynamically through the CPQ framework. This topic explains how to create, register, and expose a custom procedure by using an example procedure that closes a Sales Order.
Prerequisites
-
Basic knowledge of AL development for Business Central
-
Access to the CPQ extension code
-
Understanding of CPQ query handling and event subscribers
Custom procedure workflow
Use the following process to create a custom procedure in CPQ for Business Central:
-
Create the custom procedure (for example,
DoCloseSalesOrder). -
Handle the procedure in
CustomGetValueProcedure. -
Register the procedure in
CustomProcedureManifest.
Step 1: Implement the custom procedure
Each custom procedure follows a standard structure:
-
Retrieve input parameters from the
CPQ Query Handler. -
Run the required business logic.
-
Return a result.
Example: Close a Sales Order
The following example demonstrates a custom procedure that closes an existing Sales Order.
local procedure DoCloseSalesOrder(QueryHandler: Codeunit "CPQ Query Handler") Result: Text;
var
SalesHeader: Record "Sales Header";
SalesNo: Text;
begin
SalesNo := QueryHandler.GetParameterValue(1);
// Validate that the sales order exists
if not SalesHeader.Get("Sales Document Type"::Order, SalesNo) then
exit('Error: Order not found');
// Update the sales order status
SalesHeader.Status := SalesHeader.Status::Released;
SalesHeader.Modify();
Commit();
Result := 'Order ' + SalesNo + ' has been closed';
end;
Step 2: Register the custom procedure
Register the custom procedure by subscribing to the CustomGetValueProcedure event. This enables CPQ to route a command to your custom procedure. Modify CustomGetValueProcedure to include your new function .
Handle the command in CustomGetValueProcedure
[EventSubscriber(ObjectType::Codeunit, Codeunit::"CPQ Procedure", 'CustomGetValueProcedure', '', true, true)]
local procedure CustomGetValueProcedure(QueryHandler: Codeunit "CPQ Query Handler"; var Result: Text; var IsHandled: Boolean)
begin
IsHandled := true;
case LowerCase(QueryHandler.GetQueryText()) of
'closesalesorder':
Result := DoCloseSalesOrder(QueryHandler);
else
IsHandled := false;
end;
end;
When CPQ receives the command closesalesorder, it calls DoCloseSalesOrder.
Step 3: Define the procedure manifest
Define the procedure in the manifest so CPQ can expose it as an available procedure, including its inputs and outputs.
Register the procedure and parameters
[EventSubscriber(ObjectType::Codeunit, Codeunit::"CPQ Procedure Manifest Handler", 'CustomProcedureManifest', '', true, true)]
local procedure CustomProcedureManifest(var ProcedureStore: Codeunit "CPQ Procedure Manifest Store")
begin
ProcedureStore.AddProcedureGetValue('CloseSalesOrder', 'Closes an existing Sales Order');
ProcedureStore.AddInputParameter('OrderNo', 'The order number to close', 'String', true);
ProcedureStore.AddOutputParameter('result', 'The status of the closed order');
end;
Manifest elements
-
AddProcedureGetValue: Registers the procedure name and description.
-
AddInputParameter: Defines the input parameter (Sales Order number).
-
AddOutputParameter: Defines the output returned by the procedure.