Custom actions

Shop Floor Production (BC)  •  Article  •  8/27/2026  • 

Custom actions allow you to add buttons and menu items to Shop Floor Production screens via a per-tenant extension (PTE). When a user selects a custom action, the app passes the action's code back to Business Central, where your subscriber runs the associated logic.

Supported screens

Custom actions can be added to the following screens:

  • Production Order overview
  • Component list (consumption)
  • Output list

Register custom actions

To make a custom action available on a screen, subscribe to the relevant registration event. Each screen has its own event. In your subscriber, append one or more CustomAction objects to the ActionsArray parameter.

SFPBCCustomActions14FDW.Codeunit.al

[IntegrationEvent(false, false)]
local procedure OnGetProductionOrderCustomActions(ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10]; var ActionsArray: JsonArray)
begin
end;

[IntegrationEvent(false, false)]
local procedure OnGetConsumptionCustomActions(ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10]; var ActionsArray: JsonArray)
begin
end;

[IntegrationEvent(false, false)]
local procedure OnGetOutputCustomActions(ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10]; var ActionsArray: JsonArray)
begin
end;

ProdOrderNo, ProdOrderLineNo, RoutingNo, and OperationNo represent the production order operation currently open in the app. Use these to conditionally show actions based on the record.

CustomAction object

Each entry in ActionsArray must be a JsonObject with the following fields:

FieldTypeDescription
captionTextThe label displayed in the app for this action.
actionCodeTextA unique identifier for this action. This value is passed back to Business Central when the action is selected.
isPromotedBooleanWhen true, the action is rendered as a standalone button. When false, it appears in the overflow (kebab) menu. Only the first promoted action per screen receives a dedicated button.
refetchActiveQueriesBooleanWhen true, the app refreshes its displayed data after the action completes. Set to true if the action modifies data shown on the screen.

Run custom actions

When a user selects a custom action, the app fires the following event, passing back the actionCode you defined during registration:

SFPBCCustomActions14FDW.Codeunit.al

[IntegrationEvent(false, false)]
local procedure OnCallCustomAction(CustomAction: Text; ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10])
begin
end;

Use a case statement on CustomAction to identify which action was selected and run the appropriate logic.

Example

The following example registers two actions on the Output screen and handles their execution:

[EventSubscriber(ObjectType::Codeunit, Codeunit::SFPBCCustomActions14FDW, OnGetOutputCustomActions, '', false, false)]
local procedure PopulateOutputActions(ProdOrderNo: Code[20]; ProdOrderLineNo: Integer; RoutingNo: Code[20]; OperationNo: Code[10]; var ActionsArray: JsonArray)
var
    ShowMessageLbl: Label 'Show Message';
    ThrowErrorLbl: Label 'Throw Error';
begin
    ActionsArray.Add(AddCustomAction(ShowMessageLbl, 'ShowMessageAction', true, true));
    ActionsArray.Add(AddCustomAction(ThrowErrorLbl, 'ThrowErrorAction', false, false));
end;

local procedure AddCustomAction(Caption: Text; Action: Text; Promoted: Boolean; RefetchActiveQueries: Boolean) ActionObject: JsonObject
begin
    Clear(ActionObject);
    ActionObject.Add('caption', Caption);
    ActionObject.Add('actionCode', Action);
    ActionObject.Add('isPromoted', Promoted);
    ActionObject.Add('refetchActiveQueries', RefetchActiveQueries);
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::SFPBCCustomActions14FDW, OnCallCustomAction, '', false, false)]
local procedure ExecuteCustomAction(CustomAction: Text; ProdOrderNo: Code[20])
var
    ActionCalledMsg: Label 'Production Order (%1) called custom action: %2', Comment = '%1 = Production Order No., %2 = the action code';
    ActionFailedErr: Label 'Custom action gives an error.';
begin
    case CustomAction of
        'ShowMessageAction':
            Message(ActionCalledMsg, ProdOrderNo, CustomAction);
        'ThrowErrorAction':
            Error(ActionFailedErr);
    end;
end;

Appearance

All actions defined for a screen are accessible through a three-dot (kebab) menu in the top-right corner of the screen. For the first action marked isPromoted, a separate button is added to the screen directly, reducing the number of clicks required to execute it.