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.

Extension Management list with Bitta Retail POS by Bitta Apps, LLC installed and its version number shown
Check the installed version before you build against these events.

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-LETTER event (outcome FAILED, evidence POST-NOTIFY-SUBSCRIBER-ERROR) to POS Audit Events and a publisher telemetry signal. See Audit and telemetry.
  • Delivery is at least once. Use NotificationID to make your subscriber idempotent.
  • PostedDocumentNo is 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.
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.

// next step

Ready to try Bitta Retail POS?