POS Gateway - Serializers
Location: api/nextango/apps/pos_gateway/serializers.py
Last Updated: 2026-07-09
Overview
Every POS Gateway serializer subclasses plain DRF serializers.Serializer, not ModelSerializer. None of them expose a Django model directly; they validate the request or shape the response for a specific endpoint in Views.
Request Serializers
TerminalLoginSerializer validates a terminal login request for POST /pos/auth/terminal-login/: employee_id, pin_code (write-only, must be 4-6 numeric digits), store_id, terminal_id, all required.
TransactionCreateSerializer validates POST /pos/transactions/create/: store_id and employee_id required; line_items (a list of dicts, defaulting to empty), subtotal, tax_amount, total_amount, payment_method, tendered_amount, and change_due all optional.
SaleLineItemSerializer describes the shape of an individual line item dict inside line_items: product_variant_id, sku, quantity (1-999), unit_price, line_discount (default 0.00), total_price.
PaymentSerializer validates POST /pos/transactions/<transaction_id>/payment/ and supports two input patterns. The current pattern is payment_method_id (UUID) plus tendered_amount, with metadata and processor_transaction_id optional; a legacy pattern of method plus amount is also accepted for compatibility, with change_due and payment_data as optional legacy fields. The serializer's validate() requires either payment_method_id + tendered_amount or method + amount; for the legacy cash path it checks tendered_amount >= amount and computes change_due.
InventoryLookupSerializer (sku, barcode) and InventoryReservationSerializer (product_variant_id, sku, quantity, transaction_id) are defined but not wired to any current view. The inventory/lookup/ and inventory/reserve/ endpoints were removed during the gateway refactor; the POS frontend now calls the products API directly for barcode and SKU lookups.
ManagerApprovalRequestSerializer validates POST /pos/approvals/request/: request_type (one of discount, void, return, price_override, cash_drawer, refund), reason (required, max 500 chars), amount and details optional.
CashDrawerOperationSerializer validates POST /pos/cash-drawer/: operation (one of open, close, count, deposit), with amount, reason, and denominations optional. Only open is currently implemented by the view; the other three choices return 501 Not Implemented.
Response Serializers
TerminalSessionResponseSerializer shapes the login response: success required, with token, expires_at, session_id, user, store, employee, and message all optional. user, store, and employee accept null.
TransactionResponseSerializer shapes transaction creation and payment responses: success required, transaction, transaction_id, and error optional.
InventoryResponseSerializer, ReservationResponseSerializer, and ApprovalResponseSerializer follow the same success + optional payload/error pattern for the inventory (unused), reservation (unused), and approval-request flows respectively.
ApprovalStatusSerializer shapes the approval status poll response: request_id and status required, approved_by, approved_at, approval_reason, and error optional.
CashDrawerResponseSerializer shapes the cash drawer response: success required, drawer_operation and error optional.
ErrorResponseSerializer is a generic error shape: success (default False), error required, error_code and details optional. Not currently instantiated by any view; views build error dicts inline instead.
HealthCheckResponseSerializer shapes the health check response: status, timestamp, version, and services required; service_name, service_type, replaces, and performance_metrics optional.
Validation Notes
The PIN validator on TerminalLoginSerializer rejects non-digit input and enforces a 4-6 character length before the request ever reaches the authentication client. The payment serializer's cross-field validate() is the only other custom validation in the module; every other serializer relies on DRF's built-in field validators (min_value/max_value, max_length, choices, decimal precision).
pin_code on TerminalLoginSerializer is write_only, so it never appears in a serialized response even if echoed back accidentally.
Related Documentation
- Models: TerminalSession, ManagerApprovalRequest
- Views: endpoints that use these serializers
- Services: business logic that consumes validated data
- Authentication: JWT-based terminal authentication