Bitta Retail POS reference
Integration events
The integration events Bitta Retail POS publishes for partner extensions: posted-sale, receipt, print, kitchen and loyalty events, AL signatures and an example.
updated: applies-to: 1.0.0.141
Bitta Retail POS publishes integration events so a partner extension can react to posted sales, adjust consolidated documents, add data to receipts and take over printer delivery, without changing the app. This reference lists every event another extension can subscribe to, with its publisher object, its exact AL signature and when it runs. The app has no API pages, so these events are the way another extension hooks into it.
Which events count
The released app declares 27 [IntegrationEvent] publishers. 20 of them are subscribable by another extension:
| Group | Count | Subscribable |
|---|---|---|
Declared in codeunits with Access = Internal |
7 | No, another module cannot reference the publisher |
| Declared in public codeunits and tables | 20 | Yes |
All 20 use [IntegrationEvent(false, false)]: no sender parameter and no access to the publisher's global variables. Every publisher procedure is declared local, which is the standard form and does not restrict who may subscribe.
NOTE
The tables BAA POS Sale and BAA POS Print Queue are Access = Internal. Nine of the 20 events pass one of them as a parameter. An internal table cannot be referenced from another extension, so a subscriber to those events can work only with the other parameters. Test-compile your subscriber against the app before you rely on one of these events. The Notes column marks these events.
To subscribe, your extension must declare a dependency on Bitta Retail POS (publisher Bitta Apps, LLC, app id 0ff2eca6-ad74-438b-aea6-52af04afc216).
Posting events
These events relate to Consolidated posting and the End of Day run.
| Publisher | Event and signature | When it runs | Notes |
|---|---|---|---|
Codeunit 14292596 BAA POS Post Notify Events |
OnAfterPostPOSSale(NotificationID: Guid; POSSaleSystemId: Guid; POSSaleDocumentNo: Code[20]; PostedDocumentNo: Code[20]; SaleType: Enum "BAA POS Sale Type"; CompletionGeneration: Integer; EODRunID: Guid) |
After a POS sale is posted, delivered later by the BAA POS Post Notification Dispatch job queue entry, once per posted POS sale. | [CommitBehavior(CommitBehavior::Error)]: a Commit() in your subscriber raises an error. |
Codeunit 14292501 BAA POS Management |
OnBeforeBuiltInPostPOSSale(POSSaleSystemId: Guid; POSSaleDocumentNo: Code[20]; CompletionGeneration: Integer; PostingClaimID: Guid) |
Single-sale posting, after the posting claim is acquired and before the Business Central sales document is built. | Observation only: a subscriber cannot replace or skip the posting. |
Codeunit 14292501 BAA POS Management |
OnAfterCreateConsolidatedInvoice(var SalesHeader: Record "Sales Header") |
End of Day, once per consolidated group, after the Sales Header and lines are built and before standard posting. | You can adjust the document; the app revalidates it afterwards. An error rolls back that group only. |
How OnAfterPostPOSSale is delivered
OnAfterPostPOSSale is not raised inside the posting transaction. When the app finalizes a posted sale, it writes a notification row in the same transaction. The BAA POS Post Notification Dispatch job queue entry runs every minute, takes up to 50 due notifications per run and raises the event for each one in its own transaction.
- If your subscriber throws, the attempt is recorded as failed and retried after 1, 2, 4, 8, 16, 32 and 60 minutes.
- If the eighth attempt also fails, the notification becomes a dead letter. The app writes a
POST-NOTIFY-DEAD-LETTERevent (outcome FAILED, evidencePOST-NOTIFY-SUBSCRIBER-ERROR) to POS Audit Events and a publisher telemetry signal. See Audit and telemetry. - Delivery is at least once. Use
NotificationIDto make your subscriber idempotent. PostedDocumentNois the posted invoice or credit memo number. For an End of Day group, every POS sale in the group carries the same consolidated document number.
Receipt and completion events
These events relate to Print and reprint receipts and Receipt printers.
| Publisher | Event and signature | When it runs | Notes |
|---|---|---|---|
Codeunit 14292599 BAA POS Receipt Renderer |
OnAfterBuildSnapshot(POSSale: Record "BAA POS Sale"; var Snapshot: JsonObject) |
After the receipt snapshot JSON, including its display lines, is built and before it is serialized. | POSSale is internal. |
Codeunit 14292765 BAA POS Completion Runner |
OnBeforeReceiptDispatch(POSSale: Record "BAA POS Sale"; var IsHandled: Boolean) |
Before the automatic receipt is queued, when the completion runs without a register lease context. Set IsHandled to skip the built-in receipt. |
POSSale is internal. |
Codeunit 14292765 BAA POS Completion Runner |
OnBeforeCompletionTelemetry(POSSale: Record "BAA POS Sale"; var IsHandled: Boolean) |
Before the tender-completed telemetry signal. Set IsHandled to suppress it. |
POSSale is internal. |
Codeunit 14292765 BAA POS Completion Runner |
OnBeforeReceiptFailureEvidence(POSSale: Record "BAA POS Sale"; FailureText: Text) |
Before an unexpected automatic receipt failure is recorded for recovery. | POSSale is internal. |
Codeunit 14292765 BAA POS Completion Runner |
OnBeforeOutputFallbackTelemetry(OutputKind: Text[30]; FailureCategory: Text[100]) |
Before the sanitized fallback telemetry for a failed receipt or kitchen output. | Observation only. |
Print delivery events
| Publisher | Event and signature | When it runs | Notes |
|---|---|---|---|
Codeunit 14292707 BAA POS LAN Transport |
OnResolveLanPrinterEndpoint(TerminalID: Code[20]; StoreCode: Code[20]; var EndpointUrl: Text[250]; var UseStarWebPrnt: Boolean) |
Each time a LAN receipt or drawer pulse needs the printer address. | The app's own subscriber fills the terminal's LAN Printer Endpoint URL only when EndpointUrl is still blank, so your value wins. Every endpoint is revalidated against the HTTPS policy. |
Codeunit 14292760 BAA POS Print Router |
OnAfterReceiptClaimCommitted(ClaimedJob: Record "BAA POS Print Queue"; AttemptToken: Guid; var IsHandled: Boolean; var Accepted: Boolean; var ErrorText: Text) |
After a queued receipt job is claimed for delivery, before the built-in transport sends it. Raised inside a try function. | ClaimedJob is internal. |
Codeunit 14292601 BAA POS Print Mgmt |
OnAfterDrawerClaimCommitted(ClaimedJob: Record "BAA POS Print Queue"; AttemptToken: Guid; var IsHandled: Boolean; var Accepted: Boolean; var AcceptanceUnknown: Boolean; var FailureCategory: Text[100]; var ErrorText: Text) |
After a drawer-pulse job is claimed, before the built-in send. Raised inside a try function, so an error in your subscriber is contained. | ClaimedJob is internal. |
Kitchen output events
These events relate to Kitchen tickets and labels and Kitchen routing. Destination is a BAA POS Print Destination record, which is public.
| Publisher | Event and signature | When it runs | Notes |
|---|---|---|---|
Codeunit 14292761 BAA POS Kitchen Label Mgmt |
OnBeforeQueueKitchenLabels(POSSale: Record "BAA POS Sale"; var IsHandled: Boolean) |
Before kitchen labels are queued for a sale, when there is no register lease context. Raised inside a try function. | POSSale is internal. |
Codeunit 14292761 BAA POS Kitchen Label Mgmt |
OnBeforeQueueKitchenTickets(POSSale: Record "BAA POS Sale"; var IsHandled: Boolean) |
Before kitchen tickets are queued for a sale, when there is no register lease context. Raised inside a try function. | POSSale is internal. |
Codeunit 14292761 BAA POS Kitchen Label Mgmt |
OnBeforeQueueKitchenTicketCopy(Destination: Record "BAA POS Print Destination"; SnapshotText: Text; var IsHandled: Boolean; var Succeeded: Boolean; var ErrorText: Text) |
Before each rendered ticket copy is queued, when there is no register lease context. Set IsHandled and Succeeded to deliver it yourself. |
|
Codeunit 14292760 BAA POS Print Router |
OnBeforeSendKitchenTicketPrintNode(Destination: Record "BAA POS Print Destination"; Payload: Text; var IsHandled: Boolean; var Succeeded: Boolean; var ErrorText: Text) |
Before a kitchen ticket is sent to PrintNode. | |
Codeunit 14292760 BAA POS Print Router |
OnBeforeRunKitchenTicketReport(Destination: Record "BAA POS Print Destination"; SnapshotText: Text; CopyNo: Integer; TotalCopies: Integer; var IsHandled: Boolean; var Succeeded: Boolean; var ErrorText: Text) |
Before the kitchen ticket report prints to a BC Printer or runs in the browser. | |
Codeunit 14292760 BAA POS Print Router |
OnBeforeSendKitchenLabelPrintNode(Destination: Record "BAA POS Print Destination"; Payload: Text; RequestedCopies: Integer; var IsHandled: Boolean; var Succeeded: Boolean; var ErrorText: Text) |
Before a kitchen label is sent to PrintNode. | |
Codeunit 14292760 BAA POS Print Router |
OnBeforeRunKitchenLabelReport(Destination: Record "BAA POS Print Destination"; SnapshotText: Text; CopyNo: Integer; TotalCopies: Integer; RequestedCopies: Integer; var IsHandled: Boolean; var Succeeded: Boolean; var ErrorText: Text) |
Before the label report assigned to the destination runs. |
Loyalty and tender events
| Publisher | Event and signature | When it runs | Notes |
|---|---|---|---|
Codeunit 14292656 BAA POS Loyalty Mgmt |
OnAfterLoyaltyCompletionStage(Sale: Record "BAA POS Sale"; OperationId: Guid; Stage: Text[30]) |
Four times while loyalty activity for a completed sale is finalized, with Stage set to Ledger, Balances, Accounting and Activity. |
Sale is internal. See Loyalty programs. |
Table 14292650 BAA POS Tender Method |
OnCheckDeleteReferences(TenderMethod: Record "BAA POS Tender Method"; var IsReferenced: Boolean; var ReferencedBy: Text[100]) |
When someone deletes a tender method, after the built-in reference checks. Set IsReferenced to block the delete and ReferencedBy to name the reference in the error. |
The app's loyalty module uses this event itself. See Tender methods setup. |
Example: react to a posted sale
The subscriber below records each posted POS sale in a table of your own extension. It guards against a repeated delivery with NotificationID and does not call Commit().
codeunit 50110 "My POS Posted Sale Handler"
{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"BAA POS Post Notify Events", 'OnAfterPostPOSSale', '', false, false)]
local procedure HandlePostedPOSSale(NotificationID: Guid; POSSaleSystemId: Guid; POSSaleDocumentNo: Code[20]; PostedDocumentNo: Code[20]; SaleType: Enum "BAA POS Sale Type"; CompletionGeneration: Integer; EODRunID: Guid)
var
PostedSaleLog: Record "My POS Posted Sale Log";
begin
// Delivery is at least once: skip a notification that was already handled.
if PostedSaleLog.Get(NotificationID) then
exit;
PostedSaleLog.Init();
PostedSaleLog."Notification ID" := NotificationID;
PostedSaleLog."POS Document No." := POSSaleDocumentNo;
PostedSaleLog."Posted Document No." := PostedDocumentNo;
PostedSaleLog."Is Return" := SaleType = SaleType::Return;
PostedSaleLog."From End of Day" := not IsNullGuid(EODRunID);
PostedSaleLog.Insert(true);
// No Commit() here: the publisher uses CommitBehavior::Error.
end;
}
My POS Posted Sale Log stands for a table in your own extension with Notification ID (Guid) as its primary key. The codeunit number is a placeholder. The object name in Codeunit::"BAA POS Post Notify Events" is the codeunit's AL name; its file is named BAAPOSPostNotificationEvents.Codeunit.al, but the file name is not what you reference.
Related pages
- Consolidated posting for what End of Day builds before
OnAfterCreateConsolidatedInvoiceruns. - Print and reprint receipts for the receipt flow behind the completion and snapshot events.
- Kitchen routing for the destinations the kitchen events receive.
- Troubleshooting to check the installed version before you build against these events.