Running the Notification Service
Relevant source files
The following files were used as context for generating this wiki page:The Notification Service is a standalone background process designed to work alongside the main POS application. Its primary purpose is to monitor the inventory database (pos_inventory.db) and send timely alerts and reports via Telegram. This allows for proactive inventory management and provides daily business insights without needing to manually check the POS system.
The service operates independently and performs two main functions: it polls the database for products that have reached zero stock and sends an immediate notification, and it generates and sends a daily sales report at a configured time. It uses its own state-tracking database (notification_state.db) to prevent sending duplicate alerts for the same events.
System Architecture
The service is a multi-threaded Python application that reads from the main POS database, communicates with the Telegram API, and maintains its own state in a separate SQLite database. It is designed to be run continuously in the background on the same machine as the POS system or on any machine that has access to the pos_inventory.db file.
The following diagram illustrates the high-level architecture of the notification service and its interactions with other components.
Setup and Configuration
Before running the service, some initial setup is required to install dependencies and configure credentials.
1. Installation
The install_dependencies.bat script automates the setup process. It performs the following actions:
- Checks if Python is installed and accessible in the system's PATH.
- Installs the required Python packages (
requests,pytz) fromrequirements.txt. - Creates a
logsdirectory for the service's log files. - Checks for the existence of
config.jsonand provides instructions if it's missing.
Sources: install_dependencies.bat, requirements.txt
2. Configuration
The service is configured via a config.json file. You must copy config.example.json to config.json and populate it with your specific settings.
The table below details the available configuration options.
| Section | Key | Description | Default Value |
|---|---|---|---|
telegram | bot_token | The API token for your Telegram bot, obtained from @BotFather. | "123...-EXAMPLE" |
telegram | chat_id | The ID of the Telegram chat where notifications will be sent. | "123456789" |
polling | zero_stock_interval_seconds | How often (in seconds) to check for zero-stock products. | 300 |
polling | health_check_interval_seconds | How often (in seconds) to log a health check message. | 60 |
daily_report | send_time | The time of day (HH:MM) to send the daily report. | "08:00" |
daily_report | timezone | The timezone for the report scheduler. | "America/Mexico_City" |
daily_report | top_products_count | The number of top-selling products to include in the report. | 10 |
daily_report | metric | The metric for ranking top products (quantity or revenue). | "quantity" |
database | pos_db_path | The file path to the main POS inventory database. | "pos_inventory.db" |
database | state_db_path | The file path for the service's state-tracking database. | "notification_state.db" |
logging | log_level | The minimum level of logs to output to the console. | "INFO" |
logging | log_file | Path to the main log file. | "logs/notification_service.log" |
logging | error_log_file | Path to the error-specific log file. | "logs/notification_errors.log" |
logging | max_bytes | Maximum size of a log file in bytes before rotation. | 10485760 (10 MB) |
logging | backup_count | Number of old log files to keep. | 5 |
notifications | out_of_stock | Contains settings for out-of-stock alerts. | {...} |
notifications | daily_report | Contains settings for daily reports. | {...} |
Sources: config.example.json, notification_service.py:539-551
3. Configuration Testing
The test_telegram.py script can be used to verify that the Telegram bot_token and chat_id in config.json are correct. It attempts to connect to the Telegram API and send a test message.
python test_telegram.py
This script will:
- Load
config.json. - Validate the bot token by calling the
/getMeAPI endpoint. - Send a sample "out of stock" alert to the configured chat ID.
Sources: test_telegram.py, run_service.bat:16-19
Running the Service
The service can be run directly from the source code if Python is installed, or as a pre-compiled executable.
From Source
The run_service.bat script is the recommended way to start the service from the source code. It checks for config.json and then executes notification_service.py with the Python interpreter.
run_service.bat
A console window will appear, indicating that the service is running. This window must remain open for the service to continue monitoring. Pressing Ctrl+C in the window will gracefully shut down the service.
Sources: run_service.bat, notification_service.py:739-742
As an Executable
For deployment on machines without a Python environment, the build_notification_exe.bat script uses PyInstaller to package the service into a single executable file, dist\TelegramNotifications.exe.
The script performs the following steps:
- Cleans previous build artifacts.
- Runs
pyinstallerwith options to create a single, console-based executable. - Specifies hidden imports (
requests,pytz) to ensure they are included in the package.
To run the compiled service, place TelegramNotifications.exe in the same directory as pos_inventory.db and config.json, and then execute it.
Sources: build_notification_exe.bat, README_Notifications.txt
Core Components
The service logic in notification_service.py is structured into several classes, each with a distinct responsibility.
This diagram shows the relationships between the main classes.
Sources: notification_service.py
NotificationService
This is the main orchestrator class. It initializes all other components, loads the configuration, and sets up logging. Its start() method launches three background threads for the service's core functions:
zero_stock_monitor: Periodically checks for out-of-stock products.daily_report_scheduler: Triggers the daily report at the configured time.health_monitor: Logs a simple "OK" message periodically to show the service is alive.
It also handles graceful shutdown signals (SIGINT, SIGTERM) to ensure threads can finish their current work.
Sources: notification_service.py:534-742
TelegramNotifier
This class encapsulates all communication with the Telegram API. It constructs and sends messages based on templates defined in config.json. Key methods include:
send_message(): The core method for sending a text message. It includes a retry mechanism with exponential backoff to handle network errors.send_out_of_stock_alert(): Formats and sends a notification for a zero-stock product.send_daily_report(): Formats and sends the daily sales summary.
Sources: notification_service.py:414-531
POSDatabaseReader
This class provides read-only access to the main Point of Sale database (pos_inventory.db). It is responsible for querying product and sales data. To avoid locking conflicts with the main POS GUI application, all database connections are made with a 5-second timeout.
Key methods:
get_zero_stock_products(): Retrieves all products wherequantity = 0.get_top_selling_products(): Gathers sales data for a given date to find the best-selling items.get_total_sales(): Calculates summary sales statistics for a given date.
Sources: notification_service.py:228-361, pos_app.py:27-410
StateTracker
This class manages a private SQLite database (notification_state.db) to track which notifications have already been sent. This prevents spamming the user with duplicate alerts. It maintains three tables to track state.
Sources: notification_service.py:28-225
Database Interaction
The service interacts with two separate SQLite databases.
notification_state.db
This database is owned and managed exclusively by the notification service. It stores the state of sent notifications.
The schema is defined and initialized by the StateTracker.init_database() method.
This diagram shows the three tables in the state database.
notified_products: Stores the IDs of products for which a zero-stock alert has been sent.daily_report_log: Logs when daily reports were successfully sent to prevent sending more than one per day.service_state: A key-value table for storing generic service metadata.
Sources: notification_service.py:35-66
pos_inventory.db
This is the main database for the POS application. The notification service accesses it in a read-only capacity to retrieve inventory and sales data. The relevant tables are:
products: Queried to find products withquantity = 0and to get product details for reports.sales: Queried to generate daily sales statistics.
Sources: notification_service.py:246-252, 303-322, pos_app.py:27-47, 52-62
Functional Flows
The service's primary operations run in separate threads.
Zero-Stock Monitoring
This flow is executed by the zero_stock_monitor thread. It runs in a loop, polling the database at the interval defined by zero_stock_interval_seconds.
This sequence shows the process of checking for new zero-stock items, sending alerts only for those not previously notified, and cleaning up the notified list if a product is restocked.
Sources: notification_service.py:601-622
Daily Report Generation
This flow is managed by the daily_report_scheduler thread. It checks the time every 30 seconds and triggers a report when the current time matches the send_time configured in config.json.
This sequence illustrates how the scheduler ensures the report is sent only once per day at the correct time.
Sources: notification_service.py:624-673
Logging
The service implements a robust logging system configured via the logging section of config.json.
- Console Logging: Outputs
INFOlevel messages to the console window where the service is running. - File Logging:
logs/notification_service.log: A detailed log file containingDEBUGlevel messages and above. It includes timestamps, logger names, and function/line numbers.logs/notification_errors.log: A separate file that only capturesERRORlevel messages and above, making it easy to isolate problems.
- Log Rotation: Log files are automatically rotated when they reach the
max_bytessize, and abackup_countnumber of old logs are preserved.
Sources: notification_service.py:553-598