Transactions - POS & Sales Processing

Domain: Transactions Location: api/nextango/apps/transactions/ Last Updated: 2026-07-08

Overview

The Transactions app handles the complete POS transaction lifecycle from cart creation through payment processing, returns, and cash drawer management. Features immutable line items for audit compliance, inventory reservations, promotional discount integration, store credit management, and an eight-state transaction state machine.

Core Documentation

FileDescription
models.mdSaleTransaction, SaleLineItem, Return, StoreCredit, CashDrawer models
serializers.mdTransaction API serializers and validation
views.mdAll transaction API endpoints and workflows
services.mdTransactionService, ReturnService, CashDrawerService
signals.mdTransaction lifecycle signals and automation
examples.mdUsage examples and patterns

Key Features

Transaction Processing

  • Complete transaction lifecycle - Cart → Items → Payment → Complete
  • Immutable line items - Audit-compliant transaction records
  • Transaction state machine - Pending → Processing → Completed → Voided
  • Transaction locking - Prevent concurrent modifications
  • Idempotency support - Safe retry of failed operations
  • Multi-terminal support - Multiple POS terminals per store

Line Item Management

  • Immutable snapshots - Product data frozen at transaction time
  • Quantity tracking - Accurate quantity per line item
  • Discount integration - Line-level and transaction-level discounts
  • Tax calculation - Automated tax calculation per line
  • Price overrides - Manager-approved price adjustments

Inventory Integration

  • Inventory reservations - Hold inventory during transaction
  • Automatic release - Release on void or timeout
  • Stock validation - Prevent overselling
  • Zone-based inventory - Track inventory by store zone

Return Processing

  • Return transactions - Full and partial returns
  • Return line items - Item-level return tracking
  • Refund methods - Original payment, store credit, exchange
  • Restocking fees - Configurable restocking fees
  • Return reasons - Track return reasons for analytics

Store Credit System

  • Store credit creation - From returns or promotions
  • Balance tracking - Current balance and transaction history
  • Expiration dates - Configurable expiration policies
  • Partial redemption - Use partial credit amounts
  • Credit transfers - Transfer between customers (optional)

Cash Drawer Management

  • Cash drawer events - Open, close, reconcile operations
  • Cash tracking - Expected vs actual amounts
  • Variance reporting - Track cash discrepancies
  • Employee accountability - Track who handled cash
  • Shift reconciliation - End-of-shift cash verification

Promotional Integration

  • Promo code application - Apply discount codes
  • Stackable discounts - Multiple promotions per transaction
  • BOGO support - Buy one get one promotions
  • Discount validation - Automatic eligibility validation
  • Promotion tracking - Analytics on promotion usage

Pickup Order Management (Updated December 2025)

  • Pickup scheduling - Schedule pickups with time windows via PickupViewSet
  • Pickup status tracking - Pending → Ready → Picked Up / Expired / Cancelled
  • End-of-day expiration - Unclaimed pickups automatically expire
  • Inventory release - Expired/cancelled pickups release reserved inventory
  • Store-specific handling - Respects store closing hours and timezone
  • Return to inventory - Configurable returnToInventory behavior per store
  • Pickup cancellation - Customer-facing cancellation with reason tracking
  • Today's pickups dashboard - Grouped by status with summary counts

Pay-at-Pickup (Added December 2025)

  • Payment timing options - immediate or at_pickup payment collection
  • Deferred payment flow - Reserve inventory, pay at store
  • Partial payment tracking - Track deposits and remaining balance
  • Payment collection at pickup - Complete payment when customer arrives

Customer Cancellation (Added December 2025)

  • Order cancellation - Customer-initiated order cancellation
  • Cancellation tracking - cancelledAt, cancellationReason, cancelledBy fields
  • Distinct from void - Customer cancellation vs staff void operations
  • Inventory release - Automatic release on cancellation

Receipt & Email Notifications (Added December 2025)

  • Receipt email service - ReceiptEmailService for branded HTML/text receipts
  • Order ready notifications - Async email when pickup is marked ready
  • Payment status aware - Shows "Paid in Full" or "Balance Due"
  • Dual email provider - Supports Resend and Hostinger SMTP
  • Customer notification tracking - customer_notified_at timestamp on pickups

Pickup Modification (Added December 2025)

  • Cart-compatible format - Load pickups for POS modification
  • Payment balance tracking - Total paid, balance due in response
  • Line item details - Product name, variant name, image URLs
  • Verification info - Customer email, phone, name for pickup

API Endpoints

URL mounting: nextango/urls.py:144 mounts this app's urls.py at /transactions/ ahead of the root router, so /transactions/returns/, /transactions/line-items/, /transactions/sale-transactions/, /transactions/fulfillments/, /transactions/shipments/, /transactions/pickup/, and the analytics endpoints below all resolve through that app-local router. The root router additionally registers TransactionViewSet at top-level /transactions/ (list/detail/custom actions), plus top-level /sale-transactions/, /returns/, /return-line-items/, /sale-line-items/, and /cash-drawer/. Full endpoint-by-endpoint detail, including which registration backs each path: views.md.

Transaction Management

EndpointMethodDescriptionDoc Reference
/transactions/POSTCreate new transactionviews.md
/transactions/{id}/GETGet transaction detailsviews.md
/transactions/{id}/add_item/POSTAdd line item to transactionviews.md
/transactions/{id}/remove_item/POSTRemove line itemviews.md
/transactions/{id}/update_quantity/POSTUpdate line item quantityviews.md

Discount & Payment

EndpointMethodDescriptionDoc Reference
/transactions/{id}/apply_promo_code/POSTApply promotional codeviews.md
/transactions/{id}/remove_promo_code/POSTRemove promo codeviews.md
/transactions/{id}/process_payment/POSTProcess paymentviews.md
/transactions/{id}/complete/POSTComplete transactionviews.md
/transactions/{id}/void/POSTVoid transactionviews.md

Returns Management

EndpointMethodDescriptionDoc Reference
/returns/GET, POSTReturn operations (also reachable at /transactions/returns/)views.md
/returns/{id}/GET, PUT, PATCHReturn details and updatesviews.md
/returns/process_return/POSTProcess return and refundviews.md
/returns/{id}/cancel_return/POSTCancel a pending returnviews.md

Store Credit

There is no StoreCredit ViewSet or URL. StoreCredit has a model and serializer, but records are created and read only through ReturnService when a return's refund method is store_credit; there is no /store-credits/ endpoint. See Models and Services.

Cash Drawer

EndpointMethodDescriptionDoc Reference
/cash-drawer/open/POSTOpen cash drawerviews.md
/cash-drawer/close/POSTClose cash drawerviews.md
/cash-drawer/add_cash/POSTRecord cash-in (pay-in)views.md
/cash-drawer/remove_cash/POSTRecord cash-out (pay-out)views.md
/cash-drawer/status/GETCurrent drawer state for a store/registerviews.md
/cash-drawer/till_count/POSTRecord mid-shift till countviews.md

Pickup Management

EndpointMethodDescriptionDoc Reference
/transactions/pickup/available-slots/GETGet available pickup time slotspickup.md
/transactions/pickup/schedule/POSTCreate pickup schedulepickup.md
/transactions/pickup/{id}/mark-ready/POSTMark order ready for pickuppickup.md
/transactions/pickup/{id}/complete/POSTComplete pickup handoffpickup.md
/transactions/pickup/{id}/cancel/POSTCancel pickup orderpickup.md
/transactions/pickup/{id}/for-modification/GETGet pickup for cart modificationpickup.md
/transactions/pickup/store/{store_id}/pending/GETGet store's pending pickups (with date filter)pickup.md
/transactions/pickup/store/{store_id}/today/GETGet today's pickups by statuspickup.md

Analytics (staff only)

EndpointMethodDescription
/transactions/analytics/summary/GETRevenue, tax, discount, and order-count summary
/transactions/analytics/over-time/GETRevenue and order-count time series
/transactions/analytics/by-source/GETBreakdown by source_system
/transactions/analytics/by-fulfillment/GETBreakdown by fulfillmentMethod
/transactions/analytics/by-payment-method/GETBreakdown by payment method
/transactions/analytics/fulfillment/GETFulfillment-operations metrics
/transactions/analytics/returns/GETReturn-rate and refund-value metrics

Receipt & Notifications

EndpointMethodDescriptionDoc Reference
/transactions/{id}/send-receipt/POSTSend receipt email to customerviews.md

Full endpoint documentation: views.md

Architecture Highlights

Transaction State Machine

Transactions flow through a well-defined state machine:

PENDING ──────────────────────────────────────→ COMPLETED
   │                     ↑                          │
   │              PARTIALLY_PAID                    │
   │                     │                    REFUNDED / PARTIALLY_REFUNDED
   ↓                     │                          │
CANCELLED          (partial payment applied)        ↓
   or                                            VOIDED
VOIDED

States:

  • PENDING: Transaction created; no payment applied.
  • PARTIALLY_PAID: Partial payment received; balance outstanding. Set by PaymentService.apply_payment_to_transaction() when payment does not cover the full total. Layaway and pay-at-pickup deposits land here. Abandoned rows are voided by the cleanup_stale_partial_payments task.
  • COMPLETED: Fully paid. Set automatically when payment_balance reaches zero.
  • VOIDED: Staff-initiated cancellation (may require manager override). Distinct from customer cancellation.
  • CANCELLED: Customer-facing cancellation. Set with cancelledAt timestamp, cancellationReason, and cancelledBy FK. Inventory released automatically. Triggered via pickup or order cancellation flow.
  • REFUNDED: Fully refunded after completion.
  • PARTIALLY_REFUNDED: Partial refund applied; remaining amount settled.
  • PAYMENT_REQUIRES_ACTION: Card payment pending 3D Secure / Strong Customer Authentication. Abandoned rows are voided by the cleanup_stale_3ds_payments task.

Client note: Clients filtering by status must account for all 8 states. Omitting partially_paid, cancelled, or payment_requires_action will miss active outstanding orders, cancelled transactions, and payments pending authentication.

Read more: models.md, services.md

Immutable Line Items

Line items are immutable snapshots of product data at transaction time:

  • Product name, price, and details frozen
  • Prevents historical data inconsistency
  • Audit trail compliance
  • Accurate reporting regardless of product changes

Read more: models.md

Service Layer Architecture

Transaction logic is centralized in service classes:

  • TransactionService - Transaction lifecycle management
  • ReturnService - Return processing and refunds
  • CashDrawerService - Cash drawer operations
  • InventoryReservationService - Inventory hold logic

Read more: services.md

Signal-Based Integration

Signals coordinate cross-domain operations:

  • Inventory updates on transaction complete
  • Payment processing notifications
  • Analytics event tracking
  • Sanity CMS synchronization

Read more: signals.md

Getting Started

1. Understand the Models

Start with models.md to understand:

  • SaleTransaction (transaction_number, store, terminal, state)
  • SaleLineItem (product snapshot, quantity, price, discounts)
  • Return (original_transaction, return_reason, refund_method)
  • StoreCredit (customer, balance, expiration)
  • CashDrawerEvent (event_type, expected_amount, actual_amount)

2. Review Transaction Service

Read services.md to understand:

  • Transaction creation workflow
  • Line item management
  • Payment processing
  • Transaction completion
  • Void and refund logic

3. Explore Transaction Flows

Check views.md to learn:

  • Complete transaction API workflow
  • Return processing flow
  • Cash drawer reconciliation
  • Store credit redemption

4. Study Return Processing

Review services.md for:

  • Return creation and validation
  • Refund calculation logic
  • Inventory restocking
  • Store credit generation
  • Products - Product data, inventory, pricing
  • Payments - Payment processing integration
  • Promotions - Discount and promo code application
  • Stores - Store and terminal configuration
  • Users - Employee and customer references
  • POS Gateway - Real-time POS terminal integration
  • Integrations - Transaction synchronization

Key Architectural Decisions

  1. Immutable line items - Audit compliance and data integrity
  2. State machine pattern - Clear transaction lifecycle management
  3. Service layer - Business logic centralized, not in views/models
  4. Inventory reservations - Prevent overselling during checkout
  5. Transaction locking - Prevent concurrent modification issues
  6. Flexible returns - Support full, partial, and exchange returns
  7. Store credit system - Customer retention and refund flexibility

Common Use Cases

  • POS sale - Create transaction, add items, apply discounts, process payment
  • Return processing - Process return, calculate refund, restock inventory
  • Store credit - Issue credit from return, redeem credit in transaction
  • Cash drawer - Open drawer, process cash transactions, reconcile at shift end
  • Promotional sales - Apply promo codes, calculate discounts, track usage
  • Manager overrides - Price adjustments, return approvals, void transactions
  • Multi-payment - Split payment across multiple payment methods
  • Transaction reporting - Sales analytics, tax reporting, audit trails

Service Methods

TransactionService

Transaction Lifecycle:

  • create_transaction(store, employee=None, customer=None, source_system=None) - Initialize transaction
  • add_product_to_transaction(transaction_id, product_variant_id, quantity, unit_price=None) - Add item and recalculate totals
  • add_product_to_transaction_without_recalc(transaction_id, product_variant_id, quantity, unit_price=None) - Add item without recalculating (batch creation path)
  • update_line_item_quantity(transaction_id, line_item_id, new_quantity) - Update quantity
  • remove_line_item(transaction_id, line_item_id) - Remove item from cart

Discounts & Payment:

  • apply_promo_code(transaction_id, promo_code, store_id=None) - Apply promotional discount
  • remove_promo_code(transaction_id, promo_code) - Remove discount
  • apply_line_item_discount(transaction_id, line_item_id, discount_amount, employee=None) - Apply manual line discount
  • complete_transaction(transaction_id, payment_method_id=None, amount_paid=None) - Run pre-completion compliance gates and finalize transaction
  • void_transaction(transaction_id, reason, employee=None) - Cancel transaction, reverse inventory, and refund succeeded payments
  • redeem_loyalty_points(transaction_id, points_to_redeem) - Apply loyalty points as a payment credit

Full detail: services.md.

ReturnService

Return Processing:

  • create_return(original_transaction_id, line_items, reason) - Create return
  • calculate_refund_amount(return_id) - Calculate refund
  • process_return(return_id, refund_method) - Process return and refund
  • approve_return(return_id, manager_id) - Manager approval
  • restock_inventory(return_id) - Return items to inventory

CashDrawerService

Drawer Operations:

  • open_drawer(terminal_id, employee_id, starting_cash) - Open drawer
  • close_drawer(drawer_id, ending_cash) - Close drawer
  • reconcile_drawer(drawer_id, actual_amounts) - Reconcile cash
  • calculate_variance(drawer_id) - Calculate cash variance
  • get_drawer_events(terminal_id, date_range) - Get drawer history

PickupService (Added December 2025)

Time Slot Generation:

  • generate_available_time_slots(store_id, start_date, num_days) - Get available pickup windows

Pickup Lifecycle:

  • create_pickup_schedule(fulfillment_id, scheduled_time, customer_notes) - Schedule pickup
  • mark_ready_for_pickup(pickup_schedule_id, prepared_by_user) - Mark as ready
  • complete_pickup(pickup_schedule_id, handed_off_by_user) - Complete handoff
  • cancel_pickup_order(pickup_schedule_id, cancellation_reason, cancelled_by_user) - Cancel pickup

Store Dashboard:

  • get_pending_pickups_for_store(store_id, scheduled_date) - Get pending pickups (with date filter)
  • get_ready_pickups_for_store(store_id) - Get ready pickups
  • get_todays_pickups_for_store(store_id) - Get today's pickups grouped by status
  • get_pickup_for_modification(pickup_schedule_id) - Get pickup in cart-compatible format

ReceiptEmailService (Added December 2025)

Receipt Emails:

  • send_receipt(transaction, to_email) - Send branded HTML receipt email
  • _build_receipt_html(transaction) - Generate HTML receipt content
  • _build_receipt_text(transaction) - Generate plain text receipt
  • _build_payment_html(transaction) - Payment details section

Email Provider Support:

  • Supports ORDER_EMAIL_PROVIDER environment variable
  • Resend API (default) or Hostinger SMTP

Full documentation: services.md

Next Steps

  1. Start with models.md - Understand the data structure
  2. Then services.md - Learn business logic and workflows
  3. Review views.md - Explore API endpoints
  4. Check signals.md - See transaction automation
  5. Study serializers.md - Understand validation and serialization

Was this page helpful?