Loading repository data…
Loading repository data…
1966bc / repository
Inventarium - Laboratory inventory management system built with Python, Tkinter and SQLite. Track reagents, consumables, batches, expiration dates. Barcode support, FEFO management, purchase requests. Simple, fast, no server required.
A lightweight laboratory inventory management system built with Python and Tkinter.
Inventarium is designed for small laboratory teams who need a simple, fast, and reliable way to track consumables, reagents, and supplies. No complex setup, no web server, no cloud dependencies - just a straightforward desktop application with a local SQLite database.
| Dashboard | Warehouse |
|---|---|
| Stock overview, alerts, expiration tracking | Products, batches, labels management |
| Barcode Scanner | Deliveries |
|---|---|
| Scan labels, view details | Register deliveries, create batches |
Inventarium is developed and tested on Linux Debian 12 (Bookworm) with Python 3.11+.
In our laboratory (Mass Spectrometry Lab, Sant'Andrea University Hospital, Rome), Inventarium runs on 4 Windows 10 workstations as a standalone executable compiled with Nuitka and Python 3.7. The database is shared via network path on a folder called "Spettri" (Italian for both "spectra" and "ghosts" - fitting for a mass spec lab where inventory items occasionally... vanish 👻).
On Debian/Ubuntu, ensure you have the required packages:
sudo apt install python3 python3-venv python3-tk
Download the .deb package from Releases and install:
sudo apt install ./inventarium_0.1.1-1_all.deb
This installs Inventarium system-wide with all dependencies. Launch from the application menu (Science → Inventarium) or run inventarium from terminal.
git clone https://github.com/1966bc/inventarium.git
cd inventarium
python3 -m venv venv
source venv/bin/activate
Your prompt should now show (venv) at the beginning.
pip install -r requirements.txt
python3 inventarium.py
Every time you want to run Inventarium:
cd inventarium
source venv/bin/activate
python3 inventarium.py
pip install -r requirements.txt
python inventarium.py
Optional: If you prefer to use a virtual environment:
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt
python inventarium.py
Note: For production use, we recommend the standalone executable (see Build Standalone Executable) which requires no Python installation.
Inventarium uses SQLite - a single file database that requires no server setup.
On first run, if no database is found, a dialog will appear with options:
.db filesql/init.sqlThe sql/init.sql file contains the complete schema plus sample data:
To reset an existing database to demo data:
sqlite3 inventarium.db ".read sql/init.sql"
The database can be accessed directly via SQLite command line for queries, maintenance, and troubleshooting. A setconsole file in the sql/ folder provides pre-configured console settings.
Linux:
cd sql
sqlite3 -init setconsole ../inventarium.db
Windows:
Download sqlite3.exe from sqlite.org/download.html (Precompiled Binaries for Windows) and place it in the sql/ folder, then:
cd sql
.\sqlite3 -init setconsole ..\inventarium.db
For network databases, use the path from config.ini:
.\sqlite3 -init setconsole "\\server\share\inventarium.db"
The sql/ folder is organized by SQL statement type:
ddl/ - Schema changes (ALTER, CREATE)dml/ - Data manipulation (INSERT, UPDATE, DELETE)dql/ - Queries (SELECT)Run utility scripts with:
.read dql/check_pending.sql
.read dml/fix_pending.sql
For a complete reference of SQLite CLI commands and useful queries, see SQLITE_CLI.md.
On first run, if the database is not found, a dialog offers options to find an existing database or create a new one. The path is then saved to config.ini.
You can also edit config.ini manually:
[database]
path = sql/inventarium.db
[printer]
enabled = 1
name = BARCODE
path: Database location. For shared network access use //server/share/inventarium.dbenabled: Set to 0 to disable label printing on this workstationname: Label printer name (leave empty for system default)Alt+N - NewAlt+S - SaveAlt+C - Close/CancelEscape - Close windowinventarium/
├── inventarium.py # Application entry point
├── app_config.py # Configuration constants and functions
├── engine.py # Core engine (combines all mixins)
├── dbms.py # Database layer
├── controller.py # Domain queries
├── tools.py # Widget factories
├── i18n.py # Translations
├── views/ # GUI windows
│ ├── main.py # Main window
│ ├── config_dialog.py # First-run configuration
│ ├── warehouse.py # Inventory management
│ ├── products.py # Product list
│ └── ...
├── reports/ # Report generators
├── sql/ # Database scripts
│ ├── ddl/ # Schema changes (ALTER, CREATE)
│ ├── dml/ # Data manipulation (UPDATE, DELETE)
│ ├── dql/ # Queries (SELECT)
│ ├── init.sql # Schema + demo data
│ └── setconsole # SQLite CLI settings
└── images/ # Application icons
The application uses a mixin-based architecture where the Engine class combines:
DBMS - Database connection and query executionController - Domain-specific queriesTools - Tkinter widget factoriesLauncher - Cross-platform file openerAll views access the engine via self.engine = self.nametowidget(".").engine.
Inventarium implements several classic design patterns, making it a useful reference for learning software architecture:
| Pattern | Where | Purpose |
|---|---|---|
| Singleton | Engine (_EngineMeta), ParentView | Ensures single instance per window/engine |
| Mixin | Engine | Composition over inheritance |
| Template Method | ParentView, ChildView | Common structure for windows and dialogs |
| Registry | dict_instances | Global access to open windows |
| Builder | build_sql() | Dynamic SQL query construction |
| Observer | Engine (subscribe, notify) | Decoupled view communication |
Views communicate without knowing each other:
# In delivery.py (publisher)
self.engine.notify("stock_changed")
# In warehouse.py (subscriber)
self.engine.subscribe("stock_changed", self.on_stock_changed)
def on_stock_changed(self, data=None):
self.refresh_batches()
Engine uses a metaclass to guarantee a single instance. This is not strictly necessary since Engine is already instantiated once in App, but it's implemented for educational purposes:
class _EngineMeta(type):
_instance = None
def __call__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__call__(*args, **kwargs)
return cls._instance
class Engine(..., metaclass=_EngineMeta):
...
To create a standalone .exe that runs without Python installed:
pip install -r requirements.txt
pip install nuitka
build_on_windows.cmd
Requirements:
The executable is created in dist\inventarium.dist\. Copy the entire folder to distribute - no Python installation needed on target machines.
Contributions are welcome! Please feel free to submit issues or pull requests.
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
Giuseppe Costanzi (@1966bc)
HAL 9000 (Claude by Anthropic)
Built with Python, Tkinter, and SQLite. Keep it simple.