Initial commit: aplicatie de cantarire si etichetare

Aplicatie Flask + SQLite pentru productie alimentara: cantarirea
componentelor unui produs finit si tiparirea etichetei prin QZ Tray.

- produse finite (retete) formate din componente cantarite
- designer vizual de etichete (mm/px, zona sigura, campuri variabile,
  cod QR cu continut din mai multe bucati)
- legare produs finit -> sablon de eticheta
- navigare pe doua taburi: Cantarire / Setari
- administrare: componente, produse finite, sabloane, campuri, istoric
- backup, resetare baza de date, checklist de pregatire, /healthz
- CLI de administrare si serviciu systemd pentru productie
- vendor/syncpulse-scale-bridge (GPL-3.0-or-later) pentru citirea cantarului
This commit is contained in:
2026-10-18 23:38:45 +03:00
commit bff6d70b17
107 changed files with 21428 additions and 0 deletions
+117
View File
@@ -0,0 +1,117 @@
-- Schema SQLite: produse finite din 1..N componente cantarite.
PRAGMA foreign_keys = ON;
-- Componentele cantarite (materii prime / semifabricate).
CREATE TABLE IF NOT EXISTS components (
id INTEGER PRIMARY KEY AUTOINCREMENT,
code TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
unit TEXT NOT NULL DEFAULT 'g',
description TEXT NOT NULL DEFAULT '',
active INTEGER NOT NULL DEFAULT 1,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
-- Produsul finit: reteta si ordinea componentelor.
CREATE TABLE IF NOT EXISTS recipes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
code TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
unit TEXT NOT NULL DEFAULT 'g',
target_weight REAL,
note TEXT NOT NULL DEFAULT '',
active INTEGER NOT NULL DEFAULT 1,
-- Sablonul de eticheta folosit pentru acest produs finit.
template_id INTEGER REFERENCES label_templates(id) ON DELETE SET NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS recipe_components (
id INTEGER PRIMARY KEY AUTOINCREMENT,
recipe_id INTEGER NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
position INTEGER NOT NULL,
component_id INTEGER REFERENCES components(id) ON DELETE SET NULL,
name TEXT NOT NULL DEFAULT '',
target_weight REAL,
UNIQUE(recipe_id, position)
);
CREATE INDEX IF NOT EXISTS idx_recipe_components_recipe ON recipe_components(recipe_id, position);
-- Un pachet = o eticheta de produs finit.
CREATE TABLE IF NOT EXISTS packages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at TEXT NOT NULL,
completed_at TEXT,
status TEXT NOT NULL DEFAULT 'open', -- open | done | void
recipe_id INTEGER REFERENCES recipes(id) ON DELETE SET NULL,
recipe_code TEXT NOT NULL DEFAULT '',
recipe_name TEXT NOT NULL DEFAULT '',
unit TEXT NOT NULL DEFAULT 'g',
target_weight REAL,
total_weight REAL,
operator TEXT NOT NULL DEFAULT '',
lot TEXT NOT NULL DEFAULT '',
notes TEXT NOT NULL DEFAULT '',
template_id INTEGER REFERENCES label_templates(id) ON DELETE SET NULL,
printed_at TEXT,
print_count INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_packages_status ON packages(status);
CREATE INDEX IF NOT EXISTS idx_packages_completed ON packages(completed_at DESC);
-- Cantaririle pachetului, in ordinea retetei.
CREATE TABLE IF NOT EXISTS package_items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
package_id INTEGER NOT NULL REFERENCES packages(id) ON DELETE CASCADE,
position INTEGER NOT NULL,
component_id INTEGER,
component_code TEXT NOT NULL DEFAULT '',
component_name TEXT NOT NULL,
weight REAL NOT NULL,
unit TEXT NOT NULL,
target_weight REAL,
stable INTEGER NOT NULL DEFAULT 1,
source TEXT NOT NULL DEFAULT 'manual', -- manual | scale
scale_profile TEXT NOT NULL DEFAULT '',
raw_hex TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL,
UNIQUE(package_id, position)
);
CREATE INDEX IF NOT EXISTS idx_package_items_package ON package_items(package_id, position);
CREATE TABLE IF NOT EXISTS label_templates (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
width_mm REAL NOT NULL DEFAULT 100,
height_mm REAL NOT NULL DEFAULT 60,
body_html TEXT NOT NULL,
css TEXT NOT NULL DEFAULT '',
design_json TEXT NOT NULL DEFAULT '',
is_default INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
-- Campuri variabile proprii, disponibile in designer langa cele fixe.
-- `template` este text liber cu referinte {{campiexistent}} la campurile fixe.
CREATE TABLE IF NOT EXISTS label_fields (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key TEXT NOT NULL UNIQUE,
label TEXT NOT NULL,
template TEXT NOT NULL DEFAULT '',
active INTEGER NOT NULL DEFAULT 1,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_label_fields_active ON label_fields(active, label);
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);