# `Teya.POSLink.Receipt`
[🔗](https://github.com/sgerrand/ex_teya/blob/v0.4.0/lib/teya/poslink/receipt.ex#L1)

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_PRINTED` → `ENQUEUED` → `PRINTING` → `PRINTED` | `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.

# `create`

```elixir
@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`

```elixir
@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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
