Architecture Overview
SaleFlex follows a layered, modular architecture with clear separation of concerns — from the UI layer down to the database, and from the store floor up to the central cloud.
Ecosystem Boundary Model
Three applications, three distinct responsibilities, one coherent system.
Edge Client — PyPOS
Runs on the store floor. Handles local transaction execution, cashier-facing UI, payment processing, offline resilience, and peripheral hardware.
Store Operations Layer — OFFICE
Runs at the store level. Manages master data, operational reporting, and local coordination. Acts as in-store backup during connectivity loss.
Central Hub — GATE
Runs centrally. Provides multi-tenant APIs, company/store/terminal hierarchy, integration gateway, and web portal for management.
SaleFlex.PyPOS — Application Layers
PyPOS is structured in seven clearly separated layers. Each layer communicates only with adjacent layers.
core/logger.py (central logging via get_logger(__name__)) and
core/exceptions.py (SaleFlexError hierarchy) span every layer. All exceptions are chained with raise ... from e.
SaleFlex.GATE — Central Hub Architecture
GATE sits between edge clients and optional enterprise systems. Clients authenticate and call REST endpoints; the hub persists and routes data by company and store scope.
┌────────────────────────────────────────────────────────────────┐
│ Clients (HTTPS) │
│ SaleFlex.PyPOS · SaleFlex.KITCHEN · Mobile Apps │
└──────────────────────────┬─────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────┐
│ SaleFlex.GATE (Django) │
│ ┌─────────────┐ ┌──────────────────┐ ┌───────────────────┐ │
│ │ Django Admin│ │ REST API (DRF) │ │ Web UI / Portal │ │
│ │ /admin/ │ │ /api/v1/... │ │ / /dashboard/ │ │
│ └─────────────┘ └──────────────────┘ └───────────────────┘ │
│ │ │
│ ┌────────────────────────┴─────────────────────────────────┐ │
│ │ Domain: Merchant · Store · POS · Closure · Warehouse │ │
│ └────────────────────────┬─────────────────────────────────┘ │
└───────────────────────────┼────────────────────────────────────┘
│
┌─────────────────┼──────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────────┐
│ SQLite / │ │ ERP │ │ Loyalty / │
│ Postgres │ │ Adapters │ │ Campaign / │
│ (DB) │ │ (future) │ │ Payment │
└──────────┘ └──────────┘ └──────────────┘
Data and Control Flow
PyPOS
Sells & collects
OFFICE
Manages & reports
GATE
Orchestrates & routes
External Systems
ERP / Loyalty / PSP
- Store-floor operations (sales, payments, closures) are executed in PyPOS.
- Store-level data management, reporting, and local coordination are handled by OFFICE.
- Cross-store scope, central API flows, and integration gateway are coordinated by GATE.
- External ERP, loyalty, campaign, and payment adapters connect through GATE, keeping edge clients thin.
Deployment Profiles
Each profile is a strict superset of the previous one — start anywhere and grow incrementally.
Standalone
PyPOS only. No mandatory network dependency. Operates entirely on a local SQLite database. Ideal for a single terminal, a pop-up store, or initial evaluation.
Office-Connected
PyPOS + OFFICE. Store-level coordination, master data distribution, and local reporting. OFFICE acts as an in-store backup node even during internet outages.
Gate-Connected
Full stack. GATE provides multi-tenant APIs, centralized integration, remote access, and optional third-party adapters. Best for multi-store chains.
Architecture Principles
Offline Continuity
Store-level operations must continue regardless of network state. The offline outbox pattern (SyncQueueItem) queues all events locally before transmission.
REST/JSON Contracts
All inter-application communication uses REST APIs with JSON payloads — a stable, language-agnostic interface that makes future integrations straightforward.
Role Boundaries Align with Products
Cashier workflows live in PyPOS, manager workflows in OFFICE, and multi-tenant admin in GATE. Responsibilities do not bleed across products.
Temp / Permanent Transaction Split
PyPOS maintains temp models during active transactions and copies to permanent models only on completion — guaranteeing data integrity even on crash.
In-Memory Caching
pos_data and product_data caches load reference data once at startup, minimizing disk I/O on devices with limited write cycles.
Roadmap-Driven Evolution
Every repository ships its own roadmap. Architecture decisions and incomplete features are documented publicly so contributors know what is planned.
Document Management & Transaction Lifecycle
PyPOS uses a temp → permanent transaction model. Every sale starts as a draft document in temp models. On payment completion, the temp models are atomically copied to permanent models and the receipt is numbered.
- Transaction unique ID:
YYYYMMDD-{closure:04d}-{receipt:06d}— receipt numbers reset to 1 on each closure, so IDs are globally unique. - Suspend / Resume: SUSPEND saves the cart as a pending document; a new empty draft is created. SUSPENDED_SALES_MARKET lists all parked receipts.
- Cancellation: CANCEL voids the whole active document, marks it
CANCELLED, copies to permanent, and opens a fresh draft. - Crash recovery: On startup, any non-pending
ACTIVEdocument is automatically restored and the sale UI re-opened.