Files
ske087 bff6d70b17 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
2026-10-18 23:38:45 +03:00

83 lines
3.4 KiB
Python

#!/usr/bin/env python3
"""Pornirea aplicatiei de cantarire si etichetare.
python run.py # dezvoltare: http://127.0.0.1:5000
python run.py --host 0.0.0.0 # accesibil in reteaua locala
python run.py --production # server WSGI (waitress), fara debug
Variabile de mediu utile:
CANTARIRE_HOST, CANTARIRE_PORT, CANTARIRE_SERVER=waitress
CANTARIRE_SECRET_KEY cheia de sesiune (obligatorie in productie)
CANTARIRE_INSTANCE folderul de date (implicit ./instance)
"""
from __future__ import annotations
import argparse
import os
import sys
from cantarire import create_app
from cantarire.config import DEV_SECRET_KEY
def _print_banner(app, host: str, port: int, server: str, production: bool) -> None:
from cantarire import maintenance
status = maintenance.database_status()
summary = maintenance.readiness_summary()
shown = "127.0.0.1" if host in ("0.0.0.0", "::") else host
print(f"\nCantarire & etichetare - server {server}", flush=True)
print(f" URL http://{shown}:{port}/", flush=True)
print(f" Baza {status['path']} ({status['size_human']}, schema v{status['schema_version']})", flush=True)
print(f" Date {status['counts']['components']} componente / "
f"{status['counts']['recipes']} produse finite / "
f"{status['counts']['templates']} sabloane", flush=True)
if summary["ready"]:
print(" Pregatit: gata de cantarit.", flush=True)
else:
missing = ", ".join(item["label"] for item in summary["missing"])
print(f" De completat: {missing} (lista apare pe pagina principala)", flush=True)
if production and app.config.get("SECRET_KEY") == DEV_SECRET_KEY:
print(" ATENTIE: seteaza CANTARIRE_SECRET_KEY inainte de productie.", flush=True)
print(flush=True)
def main() -> int:
parser = argparse.ArgumentParser(description="Cantarire si etichetare")
parser.add_argument("--host", default=os.environ.get("CANTARIRE_HOST", ""))
parser.add_argument("--port", type=int, default=int(os.environ.get("CANTARIRE_PORT", "5000")))
parser.add_argument("--server", choices=("flask", "waitress"),
default=os.environ.get("CANTARIRE_SERVER", "flask"))
parser.add_argument("--production", action="store_true",
help="server WSGI (waitress), host 0.0.0.0, fara debug")
parser.add_argument("--debug", action="store_true", default=bool(os.environ.get("CANTARIRE_DEBUG")))
parser.add_argument("--quiet", action="store_true", help="nu afisa sumarul de pornire")
args = parser.parse_args()
production = args.production or args.server == "waitress"
host = args.host or ("0.0.0.0" if production else "127.0.0.1")
server = "waitress" if production else "flask"
debug = args.debug and not production
app = create_app()
if not args.quiet:
with app.app_context():
_print_banner(app, host, args.port, server, production)
if server == "waitress":
try:
from waitress import serve
except ImportError:
print("Lipseste waitress. Instaleaza: pip install -r requirements.txt", file=sys.stderr)
return 1
serve(app, host=host, port=args.port, threads=8, ident="cantarire")
return 0
app.run(host=host, port=args.port, debug=debug, threaded=True)
return 0
if __name__ == "__main__":
sys.exit(main())