This document describes the published integration events that external extensions can subscribe to when taking a dependency on the Progress Payment Invoicing app.
Dependency setup #
In your extension’s app.json, add a dependency on the Progress Payment app:
"dependencies": [
{
"id": "ff22fe04-69d8-41bc-aa92-e99608e2df5b",
"name": "Progress Payment Invoicing",
"publisher": "APC Dynamics",
"version": "1.0.29.0"
}
]
IntegrationEvent reference #
OnAfterSetTempSalesLine – Pre-set the default amount on the Sales Progress Payment dialog #
Publisher object: Report 14168210 ( apePostSalesProgPmt )
[IntegrationEvent(false, false)]
local procedure OnAfterSetTempSalesLine(SalesHeader: Record "Sales Header"; var TempSalesLine: Record "Sales Line")
When it fires: Immediately after the report initialises the temporary sales line used to back the amount fields on the Progress Payment posting dialog ( OnOpenPage ). At this point the dialog has not been shown to the user yet.
Purpose: Allows a subscriber to pre-populate the Progress Payment amount field, for example by calculating a customer-specific default percentage of the order amount.
How to use TempSalesLine to set the amount:
| To set… | Validate this field | Request page field updated |
|---|---|---|
| Amount excl. VAT | TempSalesLine.Validate(Amount, <value>) | Enter Progress Payment Amount |
| Amount incl. VAT | TempSalesLine.Validate("Amount Including VAT", <value>) | Progress Payment Amount incl. VAT (VAT) / Progress Payment Amount incl. Tax (Sales Tax) |
Setting either field causes the dialog to open with that value pre-filled. The user can still change it before posting.
Example: customer-specific default percentage:
[EventSubscriber(ObjectType::Report, Report::apePostSalesProgPmt, 'OnAfterSetTempSalesLine', '', false, false)]
local procedure OnAfterSetTempSalesLine_DefaultPct(SalesHeader: Record "Sales Header"; var TempSalesLine: Record "Sales Line")
var
CustProgPmtPct: Record "My Customer Prog Pmt Pct"; // table that stores the customer pct.
DefaultAmt: Decimal;
begin
if not CustProgPmtPct.Get(SalesHeader."Sell-to Customer No.") then
exit;
SalesHeader.CalcFields(Amount);
DefaultAmt := SalesHeader.Amount * (CustProgPmtPct.DefaultPercent / 100);
TempSalesLine.Validate(Amount, DefaultAmt);
end;
OnAfterSetTempPurchLine – Pre-set the default amount on the Purchase Progress
Payment dialog #
Publisher object: Report 14168204 ( apePostPurchProgPmt )
[IntegrationEvent(false, false)]
local procedure OnAfterSetTempPurchLine(PurchaseHeader: Record "Purchase Header"; var TempPurchLine: Record "Purchase Line")
When it fires: Immediately after the report initializes the temporary purchase line used to back the amount fields on the Progress Payment posting dialog (OnOpenPage).
Purpose: Allows a subscriber to pre-populate the Progress Payment amount field, for example by calculating a vendor-specific default percentage of the order amount.
How to use TempPurchLine to set the amount:
| To set… | Validate this field | Request page field updated |
|---|---|---|
| Amount excl. VAT | TempPurchLine.Validate("Direct Unit Cost", <value>) | Enter Progress Payment Amount |
| Amount incl. VAT | TempPurchLine.Validate("Amount Including VAT", <value>) | Progress Payment Amount incl. VAT (VAT) / Progress Payment Amount incl. Tax (Sales Tax) |
Setting either field causes the dialog to open with that value pre-filled. The user can still change it before posting.
Example: vendor-specific default percentage:
[EventSubscriber(ObjectType::Report, Report::apePostPurchProgPmt, 'OnAfterSetTempPurchLine', '', false, false)]
local procedure OnAfterSetTempPurchLine_DefaultPct(PurchaseHeader: Record "Purchase Header"; var TempPurchLine: Record "Purchase Line")
var
VendProgPmtPct: Record "My Vendor Prog Pmt Pct"; // your own table
DefaultAmt: Decimal;
begin
if not VendProgPmtPct.Get(PurchaseHeader."Buy-from Vendor No.") then
exit;
PurchaseHeader.CalcFields(Amount);
DefaultAmt := PurchaseHeader.Amount * (VendProgPmtPct.DefaultPercent / 100);
TempPurchLine.Validate("Direct Unit Cost", DefaultAmt);
end;
OnBeforeCheckProgPaidPreShipError – Override the ship-blocking error (Sales) #
Publisher object: Codeunit 14168210 ( apeSalesCheck )
[IntegrationEvent(false, false)]
local procedure OnBeforeCheckProgPaidPreShipError(SalesHeader: Record "Sales Header"; AmtNotPaid: Decimal; var IsHandled: Boolean)
When it fires: Just before the app raises Error(...) to block a sales shipment because the order has unpaid progress payments. Only fires when Check Prog. Pmt. when Shipping is enabled in setup.
Purpose: Allows a subscriber to bypass the hard error with a warning, or implement custom logic (e.g., allow certain customers to ship with open progress payment balances).
Parameters:
| Parameter | var | Description |
|---|---|---|
SalesHeader | no | The sales order being shipped. |
AmtNotPaid | no | The total outstanding progress payment balance on this order. |
IsHandled | yes | Set to true to suppress the error. You are then responsible for any user feedback. |
Example: show a warning instead of an error:
[EventSubscriber(ObjectType::Codeunit, Codeunit::apeSalesCheck, 'OnBeforeCheckProgPaidPreShipError', '', false, false)]
local procedure OnBeforeCheckProgPaidPreShipError_Warn(SalesHeader: Record "Sales Header"; AmtNotPaid: Decimal; var IsHandled: Boolean)
begin
IsHandled := true;
Message('Warning: Order %1 has an outstanding progress payment balance of %2. The shipment has been posted.', SalesHeader."No.", AmtNotPaid);
end;
OnBeforeCheckProgPaidPreRcptError – Override the receipt-blocking error (Purchase) #
Publisher object: Codeunit 14168220 ( apePurchCheck )
[IntegrationEvent(false, false)]
local procedure OnBeforeCheckProgPaidPreRcptError(PurchHeader: Record "Purchase Header"; AmtNotPaid: Decimal; var IsHandled: Boolean)
When it fires: Just before the app raises Error(...) to block a purchase receipt because the order has unpaid progress payments. Only fires when Check Prog. Pmt. when Receiving is enabled in setup.
Purpose: Allows a subscriber to bypass the hard error with a warning, or implement custom logic (e.g., allow certain vendors to receive with open progress payment balances).
Parameters:
| Parameter | var | Description |
|---|---|---|
PurchHeader | no | The purchase order being received. |
AmtNotPaid | no | The total outstanding progress payment balance on this order. |
IsHandled | yes | Set to true to suppress the error. You are then responsible for any user feedback. |
Example: show a warning instead of an error:
[EventSubscriber(ObjectType::Codeunit, Codeunit::apePurchCheck, 'OnBeforeCheckProgPaidPreRcptError', '', false, false)]
local procedure OnBeforeCheckProgPaidPreRcptError_Warn(PurchHeader: Record "Purchase Header"; AmtNotPaid: Decimal; var IsHandled: Boolean)
begin
IsHandled := true;
Message('Warning: Order %1 has an outstanding progress payment balance of %2. The receipt has been posted.', PurchHeader."No.", AmtNotPaid);
end;
OnBeforeCheckProgPaidError – Override the invoice-blocking error (Sales) #
Publisher object: Codeunit 14168210 ( apeSalesCheck )
[IntegrationEvent(false, false)]
local procedure OnBeforeCheckProgPaidError(SalesHeader: Record "Sales Header"; AmtNotPaid: Decimal; var IsHandled: Boolean)
When it fires: Just before the app raises Error(...) to block a sales invoice because the order has unpaid progress payments. Only fires when Check Prog. Pmt. when Invoicing is enabled in setup.
Purpose: Allows a subscriber to bypass the hard error with a warning, or implement custom logic (e.g., allow certain customers to invoice with open progress payment balances).
Parameters:
| Parameter | var | Description |
|---|---|---|
SalesHeader | no | The sales order being invoiced. |
AmtNotPaid | no | The total outstanding progress payment balance on this order. |
IsHandled | yes | Set to true to suppress the error. You are then responsible for any user feedback. |
Example: show a warning instead of an error:
[EventSubscriber(ObjectType::Codeunit, Codeunit::apeSalesCheck, 'OnBeforeCheckProgPaidError', '', false, false)]
local procedure OnBeforeCheckProgPaidError_Warn(SalesHeader: Record "Sales Header"; AmtNotPaid: Decimal; var IsHandled: Boolean)
begin
IsHandled := true;
Message('Warning: Order %1 has an outstanding progress payment balance of %2.', SalesHeader."No.", AmtNotPaid);
end;
OnBeforeCheckProgPaidError – Override the invoice-blocking error (Purchase) #
Publisher object: Codeunit 14168220 ( apePurchCheck )
[IntegrationEvent(false, false)]
local procedure OnBeforeCheckProgPaidError(PurchHeader: Record "Purchase Header"; AmtNotPaid: Decimal; var IsHandled: Boolean)
When it fires: Just before the app raises Error(...) to block a purchase receipt because the order has unpaid progress payments. Only fires when Check Prog. Pmt. when Invoicing (Purchase) is enabled in setup.
Purpose: Allows a subscriber to bypass the hard error with a warning, or implement custom logic (e.g., allow certain vendors to receive with open progress payment balances).
Parameters:
| Parameter | var | Description |
|---|---|---|
PurchHeader | no | The purchase order being received. |
AmtNotPaid | no | The total outstanding progress payment balance on this order. |
IsHandled | yes | Set to true to suppress the error. You are then responsible for any user feedback. |
Example: show a warning instead of an error:
[EventSubscriber(ObjectType::Codeunit, Codeunit::apePurchCheck, 'OnBeforeCheckProgPaidError', '', false, false)]
local procedure OnBeforeCheckProgPaidError_Warn(PurchHeader: Record "Purchase Header"; AmtNotPaid: Decimal; var IsHandled: Boolean)
begin
IsHandled := true;
Message('Warning: Order %1 has an outstanding progress payment balance of %2.', PurchHeader."No.", AmtNotPaid);
end;
Summary table #
| Event | Publisher object | Side | IsHandled pattern |
|---|---|---|---|
OnAfterSetTempSalesLine | Report 14168210 | Sales | N/A |
OnAfterSetTempPurchLine | Report 14168204 | Purchase | N/A |
OnBeforeCheckProgPaidPreShipError | Codeunit 14168210 | Sales | Yes |
OnBeforeCheckProgPaidPreRcptError | Codeunit 14168220 | Purchase | Yes |
OnBeforeCheckProgPaidError (Sales) | Codeunit 14168210 | Sales | Yes |
OnBeforeCheckProgPaidError (Purchase) | Codeunit 14168220 | Purchase | Yes |
Notes #
- All events use
[IntegrationEvent(false, false)]. NeitherSkipOnMissingLicensenorSkipOnMissingPermissionare set. - The
IsHandledguard pattern means the first subscriber to setIsHandled := truewins. If multiple extensions subscribe, execution order is not guaranteed; coordinate with other dependent apps accordingly. - The amount pre-set events (
OnAfterSetTempSalesLine/OnAfterSetTempPurchLine) fire duringOnOpenPageof the report, before the user interacts with the dialog. They do not prevent the user from changing the value before posting.

