Home / Architecture

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.

PySide6 SQLAlchemy Local SQLite

 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.

PySide6 REST/JSON Local DB

 Central Hub — GATE

Runs centrally. Provides multi-tenant APIs, company/store/terminal hierarchy, integration gateway, and web portal for management.

Django DRF PostgreSQL

SaleFlex.PyPOS — Application Layers

PyPOS is structured in seven clearly separated layers. Each layer communicates only with adjacent layers.

UI Layer
Dynamic Forms Virtual Keyboard NumPad SaleList PaymentList TabControl DataGrid AmountTable
Event Layer
GeneralEvent SaleEvent PaymentEvent ClosureEvent ProductEvent CustomerEvent CampaignEvent WarehouseEvent
Business Logic
VatService SaleService PaymentService LoyaltyEarnService LoyaltyRedemptionService CampaignService CouponActivationService CustomerSegmentService
Integration
GateSyncService GatePullService SyncWorker (QThread) BaseERPConnector BasePaymentGateway BaseCampaignConnector
Peripherals
CashDrawer POSPrinter (ESC/P) LineDisplay BarcodeScanner Scale CustomerDisplay
Data Access
100+ SQLAlchemy Models AutoSave Descriptors CRUD Base Temp / Permanent Split SyncQueueItem
Cache & DB
pos_data (reference cache) product_data (product cache) ActiveCampaignCache SQLite / PostgreSQL
Cross-cutting concerns: 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

  1. Store-floor operations (sales, payments, closures) are executed in PyPOS.
  2. Store-level data management, reporting, and local coordination are handled by OFFICE.
  3. Cross-store scope, central API flows, and integration gateway are coordinated by GATE.
  4. 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.

PyPOS Local SQLite

 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.

PyPOS OFFICE REST/JSON

 Gate-Connected

Full stack. GATE provides multi-tenant APIs, centralized integration, remote access, and optional third-party adapters. Best for multi-store chains.

PyPOS OFFICE GATE ERP / PSP

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 ACTIVE document is automatically restored and the sale UI re-opened.