POS Gateway - Broadcast Utilities

Location: api/nextango/apps/pos_gateway/utils/broadcast.py Last Updated: 2026-07-09

Overview

WebSocketBroadcaster is a static utility class that sends real-time events to connected POS terminals over Django Channels. It bridges domain services (transactions, payments) and WebSocket infrastructure: a domain service calls a broadcast method after completing business logic, and every connected terminal in the relevant store receives the notification without the domain service needing to know anything about Channels or consumer classes.

Every broadcast targets the store_{store_id} group, which every TerminalConsumer in that store has joined (see Consumers). The methods themselves are not called from pos_gateway's own service layer. They are called from transactions/signals.py's _broadcast_transaction_update() and _broadcast_return_processed() handlers, which run on SaleTransaction and Return save. This is the concrete example referenced in Signals: the transactions domain owns the signal, and it calls into the gateway's broadcaster rather than the gateway reacting to its own signal.


Broadcast Methods

broadcast_transaction_created(transaction, store_id): sends a transaction_created event with transaction_id, status, and total_amount.

broadcast_transaction_updated(transaction, store_id, updates=None): sends a transaction_updated event with transaction_id, status, and an updates dict describing what changed.

broadcast_transaction_completed(transaction, store_id, payment_method=None): sends a transaction_completed event with transaction_id, total_amount, and payment_method.

broadcast_return_processed(return_record, store_id): sends a return_processed event with return_id, the original transaction ID, and the refund amount.

broadcast_inventory_update(variant_sku, store_id, available_quantity, reserved_quantity): sends an inventory_update event with the SKU and current available/reserved quantities.

broadcast_system_notification(store_id, message, severity='info'): sends a system_notification event with a free-text message and severity (info, warning, error, critical).


Design Notes

Every method is fire-and-forget: if the channel layer is not configured or group_send() raises, the exception is caught and logged, and the caller's business logic continues unaffected. A transaction completes successfully even if the broadcast that would notify other terminals fails.

async_to_sync bridges the async channel_layer.group_send() call into the synchronous context of a Django service or view, since broadcasting is triggered from ordinary synchronous code paths, not from within an async consumer.

The type field in each message maps to a method name on the receiving consumer: type: 'transaction_completed' causes Channels to call TerminalConsumer.transaction_completed(event) on every consumer instance in the target group. This is standard Django Channels dispatch, not custom routing in this module.


  • Consumers: the TerminalConsumer event handlers that receive these broadcasts
  • Services: gateway services that call these broadcast methods
  • Infrastructure: channel layer (Redis) configuration

Was this page helpful?