AgentStack
SKILL verified MIT Self-run

Bc Approval Workflow Generator

skill-fernandoartalf-al-copilot-skills-collection-bc-approval-workflow-generator · by fernandoartalf

>-

No reviews yet
0 installs
10 views
0.0% view→install

Install

$ agentstack add skill-fernandoartalf-al-copilot-skills-collection-bc-approval-workflow-generator

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Bc Approval Workflow Generator? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Business Central Approval Workflow Generator

Overview

Generates all AL objects required to integrate a Business Central entity (standard or custom table) into the built-in Workflow approval engine. The generated code follows the pattern used by standard BC approvals (Purchase Orders, Sales Orders) and subscribes to the same event hooks.

Quick Start

Example requests:

  • "Create an approval workflow for Statistical Account"
  • "Add approval process to my custom Job Request table"
  • "Generate send/cancel approval actions for the Transfer Order card"
  • "Implement approval workflow on the Vendor Card"

Prerequisites

  • Available object IDs from app.jsonidRanges
  • Project affix from app.jsonaffixes
  • The target table must already exist (standard or custom)
  • Knowledge of which page(s) display the entity (Card and/or List)

Interview — Mandatory Questions

Before generating any code the skill MUST ask the user the following questions using vscode_askQuestions. Do NOT proceed until every answer is collected.

Question 1 — Target entity

> Which table should have the approval workflow?

If the user already mentioned the entity, confirm it. Otherwise present a free-text input. Validate the table exists in the workspace or is a known standard BC table.

Question 2 — Table type

> Is this a custom table you own, or a standard BC table that you will > extend via table extension?

| Option | Impact | |---|---| | Custom table | Field added directly; OnDelete trigger in table | | Standard table (extension) | Field added via tableextension; OnBeforeDelete trigger |

Question 3 — Related sub-tables (lock-down)

> Does this entity have related sub-tables (e.g. lines on a document) > that should be locked (Editable = false) when the approval status is > not Open?

If Yes, ask for the sub-table name(s) and the page part(s) that display them. The generator will add Editable property binding on those subpage parts.

Question 4 — Pages

> Which pages should receive the Send / Cancel Approval Request actions?

Present options:

  • Card page only
  • List page only
  • Both Card and List (default / recommended)

Ask for the exact page names if not obvious from the entity name.

Question 5 — Approver routing

> Which approver routing should the workflow template default to?

| Option | Description | |---|---| | Direct Approver | Routes to the user's direct approver in Approval User Setup (default) | | First Qualified Approver | Routes to the first user with sufficient approval limit | | Approver Chain | Routes through the full approval hierarchy | | Specific User | Always routes to a fixed user |

Code Generation Steps

Step 1 — Read project metadata

  1. Read app.json to obtain idRanges, affixes, name, publisher.
  2. Determine the affix (e.g. BCS).
  3. Allocate object IDs for: Enum, Codeunit (Approval Mgmt.), Codeunit

(Workflow Setup), and optionally Table Extension / Page Extensions.

Step 2 — Determine naming

Derive names from the entity name and project affix:

| Artefact | Naming pattern | Example (entity = Statistical Account, affix = BCS) | |---|---|---| | Enum | Appr. Status | BCS Stat. Acc. Appr. Status | | Table Extension | | BCS Statistical Account | | Approval Mgmt. CU | Approval Mgmt. | BCS Stat. Acc. Approval Mgmt. | | Workflow Setup CU | Workflow Setup | BCS Stat. Acc. Workflow Setup | | Page Extension (Card) | Card | BCS Statistical Account Card | | Page Extension (List) | List | BCS Statistical Account List |

Step 3 — Determine folder structure

Place generated files under the appropriate feature folder:

Custom table (you own the table and page objects):

/
├── Enum/
│   └── ApprStatus.Enum.al
├── Table/
│   └── .Table.al        (add field + OnDelete)
├── Page/
│   ├── Card.Page.al     (add actions + triggers)
│   └── List.Page.al
└── Codeunit/
    ├── ApprovalMgmt.Codeunit.al
    └── WorkflowSetup.Codeunit.al

Standard table (extend via tableextension / pageextension):

/
├── Enum/
│   └── ApprStatus.Enum.al
├── Table Extension/
│   └── .TableExt.al
├── Page Extension/
│   ├── Card.PageExt.al
│   └── List.PageExt.al
└── Codeunit/
    ├── ApprovalMgmt.Codeunit.al
    └── WorkflowSetup.Codeunit.al

Step 4 — Generate the Approval Status Enum

Create an enum with four values: Open, Pending Approval, Rejected, Approved. Mark as Extensible = true.

See: references/enum-template.md

Step 5 — Generate the Table / Table Extension

Add a field of the enum type with:

  • Editable = false
  • DataClassification = CustomerContent

Deletion guard logic:

  1. Blocks deletion if status is Approved or Pending Approval.
  2. Calls ApprovalsMgmt.DeleteApprovalEntries(Rec.RecordId).

Editability helper:

  • Add an ApprovalStatusAllowModify(): Boolean procedure that returns

false when status is Approved or Pending Approval, true otherwise. Pages use this to bind Editable on layout groups.

| Table type | Trigger | Template | |---|---|---| | Custom table | OnDelete directly in the table | references/custom-table-template.md | | Standard table | OnBeforeDelete in a tableextension | references/table-extension-template.md |

Step 6 — Generate the Approval Management Codeunit

This is the core object. It contains:

  1. Integration event publishersOnSend…ForApproval, OnCancel…ApprovalRequest
  2. ValidationCheck…ApprovalPossible, Is…ApprovalWorkflowEnabled
  3. Event code identifiersRun…Code(): Code[128]
  4. Event subscribers for workflow events — handle HandleEvent calls
  5. Event subscribers for the workflow library — register events and predecessors
  6. Event subscribers for approval entry — populate entry arguments
  7. Event subscribers for status updates — pending, approve, reject
  8. Event subscribers for response handling — release, open, response predecessors
  9. Card page mappingOnConditionalCardPageIDNotFound
  10. Set status to Open helperSet{Entity}StatusToOpen procedure

called from the Cancel action on pages to revert status

See: references/approval-mgmt-codeunit-template.md

Step 7 — Generate the Workflow Setup Codeunit

Subscribes to Workflow Setup events to register:

  1. A workflow category (short code + description)
  2. Table relations linking the entity to Approval Entry AND

Workflow Webhook Entry (for Power Automate integration)

  1. A workflow template with pre-configured steps
  2. UpdateMatrixData — inserts WF Event/Response Combination

records so the workflow editor shows all response options (Send Approval Request, Set Status to Pending Approval, Send Notification to Webhook, Cancel All Approval Requests) for the custom events. Without this, responses are missing from the workflow step configuration UI.

See: references/workflow-setup-codeunit-template.md

Step 8 — Generate Page / Page Extension(s)

For each target page (Card / List), add:

  1. The Approval Status field in layout (with StyleExpr)
  2. An Approval action group with Send / Cancel actions
  3. OnAfterGetRecord trigger logic for button enablement and page

editability via Rec.ApprovalStatusAllowModify() (custom table) or Rec.{Affix}ApprovalStatusAllowModify() (table extension)

  1. modify(General) { Editable = GPageEditable; } to lock the

General group when status is not Open — do NOT use CurrPage.Editable as it prevents approval action buttons from being clickable

  1. Cancel action calls ApprovalMgmt.Set{Entity}StatusToOpen(Rec)

to explicitly revert status

  1. If sub-tables are locked: Editable binding on subpage parts

| Page type | Template | |---|---| | Custom page (you own the page object) | references/custom-page-card-template.md | | Standard page (extend via pageextension) | references/page-extension-card-template.md |

Step 9 — Summary and next steps

After generating all files, present a summary:

Approval Workflow Generated for: [Entity Name]

Objects created:
- Enum [ID] "[Name]" — [file path]
- Table Extension [ID] "[Name]" — [file path]  (if applicable)
- Codeunit [ID] "[Name]" — [file path]
- Codeunit [ID] "[Name]" — [file path]
- Page Extension [ID] "[Name]" — [file path]
- Page Extension [ID] "[Name]" — [file path]

Post-publish setup:
1. Publish the extension
2. Navigate to Workflows → create workflow from template
3. Configure Approval User Setup
4. Enable the workflow
5. Test: Send → Approve / Reject / Delegate / Cancel

Event Subscriber Reference

The approval management codeunit must subscribe to these standard events:

| Standard Codeunit | Event | Purpose | |---|---|---| | Workflow Event Handling | OnAddWorkflowEventsToLibrary | Register send & cancel events | | Workflow Event Handling | OnAddWorkflowEventPredecessorsToLibrary | Chain events | | Approvals Mgmt. | OnPopulateApprovalEntryArgument | Fill Document No. / Table ID | | Approvals Mgmt. | OnSetStatusToPendingApproval | Status → Pending | | Approvals Mgmt. | OnApproveApprovalRequest | Status → Approved | | Approvals Mgmt. | OnRejectApprovalRequest | Status → Rejected | | Approvals Mgmt. | OnBeforeShowCommonApprovalStatus | Display message |

> CRITICAL: The OnBeforeShowCommonApprovalStatus event parameter > is named IsHandle (NOT IsHandled). Using the wrong name causes > the subscriber to silently fail to bind.

> CRITICAL: Use HasOpenOrPendingApprovalEntries in > OnApproveApprovalRequest (NOT HasOpenPendingApprovalEntries > which does not exist).

> CRITICAL: Variable declarations must be ordered by type: > Record, Report, Codeunit, XmlPort, Page, Query, then scalar types. > Place RecordRef after Codeunit variables.

| Standard Codeunit | Event | Purpose | |---|---|---| | Workflow Response Handling | OnReleaseDocument | Status → Approved | | Workflow Response Handling | OnOpenDocument | Status → Open | | Workflow Response Handling | OnAddWorkflowResponsePredecessorsToLibrary | Link responses | | Page Management | OnConditionalCardPageIDNotFound | Card page mapping | | Workflow Setup | OnAddWorkflowCategoriesToLibrary | Register category | | Workflow Setup | OnAfterInsertApprovalsTableRelations | Table → Approval Entry | | Workflow Setup | OnInsertWorkflowTemplates | Create template |

Rules

  1. Always use the project affix for all object and field names.
  2. Enum values must be: Open (0), Pending Approval (1), Rejected (2), Approved (3).
  3. The approval status field must be Editable = false.
  4. Event code identifiers (Code[128]) must be uppercase and unique.
  5. All Modify() calls in approval status updates must use Modify(true).
  6. The workflow category code must be ≤ 20 characters and Locked = true.
  7. If sub-tables need locking, bind Editable on the subpage part to the

header's approval status = Open.

  1. Follow the instruction files for naming, code style, and performance.
  2. Page editability: Use modify(General) { Editable = GPageEditable; }

where GPageEditable is set from Rec.ApprovalStatusAllowModify() in OnAfterGetRecord. Do NOT use CurrPage.Editable — it disables approval action buttons when the page is non-editable.

  1. Variable ordering: Declare variables in AL-required order:

Record → Report → Codeunit → XmlPort → Page → Query → scalar types. RecordRef goes after Codeunit.

  1. OnBeforeShowCommonApprovalStatus: The parameter is IsHandle

(NOT IsHandled). Using the wrong name silently breaks the binding.

  1. OnApproveApprovalRequest: Use HasOpenOrPendingApprovalEntries

(NOT HasOpenPendingApprovalEntries which does not exist).

  1. UpdateMatrixData: The Workflow Setup codeunit must insert

WF Event/Response Combination records so the workflow editor shows all response options for the custom events.

  1. Workflow Webhook Entry: Register a table relation from the entity

SystemId to Workflow Webhook Entry."Data ID" for Power Automate.

  1. Cancel action: Must explicitly call a Set{Entity}StatusToOpen

procedure on the Approval Mgmt. codeunit to revert the status.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.