> This page is for Product Documentation.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.navipartner.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.navipartner.com/_mcp/server.

# Print receipts with a custom codeunit

> Use a custom print codeunit to generate sales receipts and other line-based printouts, with full control over the content and as many receipt variants as you need.

NP Retail can print sales receipts from a custom print codeunit instead of a print template. This is the recommended approach for sales receipts and other line-based outputs (such as Z/X reports and kitchen prints), because it gives you full control over the content and lets you define as many receipt variants as you need — for example, a business copy, a customer copy, and a *Bewirtungsbeleg*.

You build this entirely from your own extension (PTE), with no change to NP Retail core. The print codeunits are ordinary AL codeunits with `TableNo = "NPR POS Entry"`, written just like NP Retail's standard receipt codeunit (`6248348 "NPR Static Sales Receipt"`). A full reference implementation is available in the [<ins>sales-receipt-print-codeunit-example</ins>](https://github.com/navipartner/sales-receipt-print-codeunit-example) repository.

> **Note:** This approach applies to tenants that have switched to the **New Sales Receipt Experience** in NP Retail. Because NP Retail's underlying tables are `Access = Internal`, custom codeunits read receipt data through the public facade codeunit `NPR ReceiptPrintUtilities`.

## Clearing up a common misconception

The single **Codeunit ID** field on **Report Selection - Retail** is only the *auto-print-on-sale* hook — it is not the only way to run a receipt codeunit. Under the hood, NP Retail simply calls `Codeunit.Run(<your codeunit>, <POS Entry>)`, and a POS action can make that same call itself, as many times and from as many buttons as you want.

In other words, there is no "one codeunit only" limit. The auto-print field handles the receipt printed automatically after each sale, and your own POS actions handle any additional variants you print on demand.

## How receipt dispatch works

When a sale is finalized, NP Retail reads the **Report Selection - Retail** row for **Sales Receipt (POS Entry)** (the unit-specific row by **Register No.** if one exists, otherwise the blank row) and resolves what to print in this priority order:

1. **Print Template** is set → the template is run (the legacy path, blocked once the New Sales Receipt Experience is enabled).
2. **Report ID** is set → the report is run.
3. **Codeunit ID** is set → the codeunit is invoked with the POS Entry (a `RecordRef`) bound to `Rec` in `OnRun`.

To print from a custom codeunit, set only the **Codeunit ID** and leave **Report ID** and **Print Template** empty, since those take precedence.

## Print a business copy automatically after each sale

This is the standard auto-print pattern.

1. Write your business-copy print codeunit with `TableNo = "NPR POS Entry"`, modeled on the [<ins>example codeunit</ins>](https://github.com/navipartner/sales-receipt-print-codeunit-example).
2. Search for **Report Selection - Retail** in Business Central, and open the related link.
3. Filter to the **Sales Receipt (POS Entry)** report type.
4. On the target row, set the **Codeunit ID** to your codeunit, and leave **Report ID** and **Print Template** empty.

   > **Tip:** Set the **Register No.** to scope the codeunit to a specific till. Leave it blank to apply it to all units.

NP Retail then prints this receipt on every sale. Nothing else is required.

## Print customer copies and other variants on demand

For variants that are printed on demand — such as a customer copy or a *Bewirtungsbeleg* — do not reuse the standard **Print Receipt** action. Its setting only resolves to the standard or "large" receipt type, and that dispatch is internal. Instead, create your own POS action(s), which use only public, supported surface:

1. Implement the public `NPR IPOS Workflow` interface and register the action via an `enumextension` on the public, extensible `NPR POS Workflow` enum — the same way any custom POS button is built. See the [<ins>pos-action-example</ins>](https://github.com/navipartner/pos-action-example) repository.
2. In the action, get the current POS unit with `Setup.GetPOSUnit`.
3. Find the relevant POS Entry — the last one, or let the cashier pick — by filtering the public `NPR POS Entry` table.
4. Call `Codeunit.Run(<your customer-copy or Bewirtungsbeleg codeunit>, POSEntry)`.

Add one POS unit button per variant (for example, **Print customer copy** and **Print Bewirtungsbeleg**). You can also use a single action with an option parameter to choose the variant.

The variant codeunits are ordinary print codeunits (`TableNo = "NPR POS Entry"`), written just like the business copy. A *Bewirtungsbeleg* codeunit simply adds the extra header and text fields it requires.

## Reprint limits, logging, footer, and QR codes

Because the on-demand buttons bypass NP Retail's internal print path, the **Allow Printing Receipt Copy** reprint limit and the **POS Entry** output log are not applied automatically. The public `NPR ReceiptPrintUtilities` codeunit exposes helpers to restore that behavior and to match the standard receipt:

* `IsReprint(EntryNo)` — identifies reprint receipts, so you can gate on it to enforce reprint-limiting and logging.
* `AddReceiptFooterText(...)` — applies the configured receipt footer text.
* `ShowBarcodeAsQRCode(...)` — matches the standard receipt's barcode/QR behavior.

#### See also

* [<ins>Report selection</ins>](/product/retail-reports-selection)
* [<ins>Set up printing with codeunits</ins>](/product/retail-printing-codeunit-printing)
* [<ins>Create a simple receipt/line print template</ins>](/product/retail-printing-receipt-print-template)
* [<ins>Print template features</ins>](/product/retail-printing-template-tools)