POS Application Internals (pos_app.py)
Relevant source files
The following files were used as context for generating this wiki page:The pos_app.py file contains a monolithic Point of Sale (POS) and inventory management system. It is built using Python's tkinter library for the graphical user interface and SQLite for data persistence. The application is designed as a single-file system for small retail operations, handling sales, inventory tracking, product management, and reporting.
The architecture consists of two primary classes: Database, which encapsulates all SQLite operations, and POSApplication, which manages the entire GUI and application logic. The system is event-driven, responding to user interactions like button clicks and barcode scans. It also includes features for data import from XLSX files and PDF generation for receipts and reports. An optional, separate notification service can monitor the database to send alerts.
Sources: CLAUDE.md, pos_app.py
Architecture
The application follows a two-class monolithic structure contained entirely within pos_app.py.
DatabaseClass: A data access layer that handles all interactions with thepos_inventory.dbSQLite database. It does not use an ORM, and each method opens and closes its own database connection.POSApplicationClass: The main application class responsible for building and managing thetkinterGUI. It orchestrates all user-facing logic, state management (like the in-memory shopping cart), and calls to theDatabaseclass.
Sources: CLAUDE.md:12-21, pos_app.py:18-19, 631-633
This diagram illustrates the main classes and their relationship.
Sources: pos_app.py:18, 631
Database System
The database logic is managed by the Database class, which interacts with a local SQLite file named pos_inventory.db.
Sources: pos_app.py:18-20
Database Schema
The database is initialized with four tables: products, sales, folio_counter, and migrations. The system includes logic to add missing columns (folio, cost, brand, product_barcode) to existing databases for backward compatibility.
Sources: pos_app.py:21-103
The following diagram shows the entity relationships within the database.
Sources: pos_app.py:25-103
products Table
Stores all inventory items. The barcode is the internal unique key, while product_barcode is the manufacturer's barcode.
| Column | Type | Constraints | Description |
|---|---|---|---|
id | INTEGER | PRIMARY KEY AUTOINCREMENT | Unique identifier for the product. |
barcode | TEXT | UNIQUE NOT NULL | Internal product code (Clave). |
product_barcode | TEXT | Manufacturer's barcode. | |
name | TEXT | NOT NULL | Product description. |
price | REAL | NOT NULL | Selling price. |
quantity | INTEGER | NOT NULL | Current stock level. |
category | TEXT | Product category. | |
brand | TEXT | Product brand. | |
cost | REAL | DEFAULT 0 | Cost of the product. |
Sources: pos_app.py:27-36, 64-75
sales Table
Records every item sold in a transaction. Multiple items can share the same folio to group them into a single sale.
| Column | Type | Constraints | Description |
|---|---|---|---|
id | INTEGER | PRIMARY KEY AUTOINCREMENT | Unique identifier for the sale record. |
folio | TEXT | Unique identifier for a single sales transaction. | |
product_id | INTEGER | FOREIGN KEY (products.id) | The ID of the product sold. |
quantity | INTEGER | Quantity of the product sold in this transaction. | |
total | REAL | Total price for this line item (price * quantity). | |
timestamp | TEXT | Timestamp of the sale. |
Sources: pos_app.py:40-50, 321-328
folio_counter Table
A simple singleton table to generate sequential, unique folio numbers for sales receipts.
| Column | Type | Constraints | Description |
|---|---|---|---|
id | INTEGER | PRIMARY KEY CHECK (id = 1) | Ensures only one row exists. |
current_folio | INTEGER | NOT NULL DEFAULT 0 | The last used folio number. |
Sources: pos_app.py:89-95, 309-320
Price Rounding and Migration
The application enforces rounding of all monetary values (price, cost) to one decimal place using the Decimal type for precision. A one-time migration script (migrate_prices_to_one_decimal) runs on startup to round existing data in the products table, tracking its completion in the migrations table to prevent re-execution.
Sources: pos_app.py:10-17, 105-139, 182, 1515-1516
GUI Application (POSApplication)
The POSApplication class initializes the main window and a ttk.Notebook to manage different sections of the application in tabs.
Sources: pos_app.py:631-643
| Tab Name | Description | Key Functions |
|---|---|---|
Venta/Salida de Inventario | The main Point of Sale interface for scanning products and processing sales. | scan_product, checkout, edit_cart_quantity |
Entrada y Busqueda de Inventario | The inventory management dashboard. Used for adding stock, searching, filtering, editing, and importing products. | scan_product_inventory, search_product, apply_filters, import_from_xlsx, edit_product_full |
Imprimir Ticket | Displays the last generated sales receipt and allows re-printing to PDF or copying to clipboard. | load_last_receipt, print_last_receipt, copy_last_receipt |
Reportes | Allows manual generation of daily sales reports for a specified date. | manual_generate_report, generate_sales_report_pdf |
Sources: pos_app.py:641-643, 663-664, 781-782, 893-894, 932-933
Core Workflows
Sales and Checkout Process
The sales process begins when a user scans a product barcode in the "Venta/Salida de Inventario" tab. The application searches for the product, adds it to an in-memory cart, and updates the display. The checkout process finalizes the sale, updates the database, and generates a receipt.
Sources: pos_app.py:1003-1039, 1689-1725
This sequence diagram shows the checkout flow.
Sources: pos_app.py:1689-1725
Product Search and Inventory Update
The application features a robust product search mechanism used in both sales and inventory management. It attempts to find a product using a multi-step process to provide flexibility.
Sources: pos_app.py:1003-1039, 1894-1935
This flowchart details the logic for finding a product from a scanned code.
Sources: pos_app.py:1003-1039, 1894-1935
Data Import from XLSX
Products can be bulk-imported or updated from an .xlsx file. The import_from_xlsx function reads a spreadsheet with expected columns, validates each row, and either creates a new product or updates an existing one based on the CLAVE (internal barcode).
The expected column order in the XLSX file is:
CLAVE, DESCRIPCION, COSTO, P/VENTA, CANTIDAD, CATEGORIA (optional), MARCA (optional), CODIGO DE BARRAS (optional).
Errors during import are collected and displayed to the user. If more than 10 errors occur, a detailed log file is created in the error_logs/ directory.
Sources: pos_app.py:1568-1687, build_exe.bat:29
Reporting and Output
The application generates two main types of files: PDF receipts for sales and PDF daily reports.
PDF Receipts
After each checkout, a receipt preview is shown. The user can save it as a PDF. The PDFs are designed to be compact, mimicking a thermal printer format (80mm width). Receipts are saved in a recibos folder, which is created on the user's Desktop if accessible, otherwise falling back to a local receipts folder.
Sources: pos_app.py:645-661, 1424-1490, 1618-1663
PDF Sales Reports
The "Reportes" tab allows for manual generation of a sales report for any given day. The report is an A4-sized PDF containing:
- A summary of sales (total transactions, items sold, revenue).
- A table of the top 10 best-selling products for that day.
- A list of all products currently with zero stock.
These reports are saved in a reports/ directory. There is also a scheduler that attempts to generate a report for the current day automatically at 3:00 PM.
Sources: pos_app.py:931-987, 1492-1616, 2099-2113
Dependencies and Deployment
The application relies on several external libraries.
fpdf2: For generating PDF receipts and reports.openpyxl: For reading product data from.xlsxfiles.requests: Used by the optional notification service.pytz: Used by the optional notification service for timezone handling.
Sources: requirements.txt
A build_exe.bat script is provided to package the application into a single executable file (POS_TioAdan.exe) using PyInstaller. This simplifies distribution, as only the .exe file is needed. The script handles cleaning previous builds and explicitly includes hidden imports required by the application.
Sources: build_exe.bat
External Notification Service
The repository includes a separate, optional notification_service.py. This is a standalone script that runs in the background to monitor the pos_inventory.db file. It is not part of the main pos_app.py execution.
Its key functions are:
- Polling the database at a configurable interval (e.g., every 5 minutes).
- Sending a Telegram notification when a product's quantity reaches zero.
- Sending a daily sales summary to a Telegram chat.
- Using its own state database (
notification_state.db) to avoid sending duplicate alerts.
This service interacts with the main application's database in a read-only capacity.
Sources: notification_service.py, README_Notifications.txt, test_telegram.py