Teya.POSLink.Receipt (teya v0.4.0)

Copy Markdown View Source

POSLink receipt printing — send print jobs to a terminal's receipt printer.

A receipt request enqueues a print job on the terminal. The job transitions through: NOT_PRINTEDENQUEUEDPRINTINGPRINTED | FAILED.

Use create/2 to submit the receipt and subscribe_status/2 to receive real-time printer status updates via SSE.

Required OAuth scopes: poslink/receipt-requests/create, poslink/receipt-requests/id/status/get.

Task lifecycle

subscribe_status/2 returns {:ok, %Task{}} immediately. The task runs under Teya.TaskSupervisor with async_nolink, meaning:

  • The task is not linked to the caller — a task crash does not take down the calling process.
  • The supervisor does not restart the task if it exits.
  • If the caller process dies, the task continues running until the SSE stream ends or errors, then exits normally.
  • If the SSE stream disconnects (network error, server restart), the task sends {:poslink_receipt_error, id, reason} and exits. There is no automatic reconnection. Call subscribe_status/2 again to open a fresh stream.

Summary

Functions

Submits a receipt print request to a terminal.

Subscribes to real-time printer status updates for a receipt request via SSE.

Functions

create(params, opts \\ [])

@spec create(
  map(),
  keyword()
) :: {:ok, map()} | {:error, Teya.Error.t()}

Submits a receipt print request to a terminal.

Returns {:ok, response} containing the receipt_id and initial status ("NOT_PRINTED" or "ENQUEUED"). Use the returned receipt_id with subscribe_status/2 to stream printer status updates.

Required params

  • store_id — UUID of the store
  • terminal_id — UUID of the target terminal
  • content — the receipt content; a map with either:
    • %{"type" => "JSON", "data" => %{...}} for structured JSON receipts, or
    • %{"type" => "IMAGE", "data" => base64_string} for image receipts

Optional params

  • merchant_reference — caller-supplied reference (max 60 chars)

Options

  • :idempotency_key — override the auto-generated idempotency key

Examples

{:ok, %{"receipt_id" => id}} =
  Teya.POSLink.Receipt.create(%{
    "store_id"    => store_id,
    "terminal_id" => terminal_id,
    "content"     => %{"type" => "JSON", "data" => %{"total" => "£10.00"}}
  })

subscribe_status(receipt_id, pid \\ self())

@spec subscribe_status(String.t(), pid()) :: {:ok, Task.t()}

Subscribes to real-time printer status updates for a receipt request via SSE.

Spawns a supervised task under Teya.TaskSupervisor that opens the SSE stream for receipt_id and forwards parsed events as messages to pid (defaults to self()).

Messages sent to pid

  • {:poslink_receipt, id, event_type, data} — a status event where:
    • id is the receipt_id
    • event_type is "full" (complete snapshot) or "diff" (partial update)
    • data is the decoded JSON map (e.g. %{"status" => "PRINTED", ...})
  • {:poslink_receipt_error, id, reason} — the stream ended with an error; reason is a %Teya.Error{}, a transport exception, or :stream_timeout

Example

{:ok, _task} = Teya.POSLink.Receipt.subscribe_status(receipt_id)

receive do
  {:poslink_receipt, ^receipt_id, "full", %{"status" => "PRINTED"}} ->
    :ok

  {:poslink_receipt, ^receipt_id, _type, %{"status" => "FAILED"}} ->
    handle_print_failure()

  {:poslink_receipt_error, ^receipt_id, reason} ->
    handle_error(reason)
end