bff6d70b17
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
114 lines
3.7 KiB
Python
114 lines
3.7 KiB
Python
"""Administrarea campurilor variabile proprii (custom.*).
|
|
|
|
Un camp propriu este un text care poate include alte campuri fixe, de exemplu
|
|
`Tel. {{company.phone}}`. La randarea etichetei, textul este expandat cu
|
|
valorile reale ale pachetului.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from flask import (Blueprint, jsonify, flash, redirect, render_template, request, url_for)
|
|
|
|
from .. import designer
|
|
from ..repositories import (
|
|
ValidationError,
|
|
count_label_field_usage,
|
|
create_label_field,
|
|
delete_label_field,
|
|
get_label_field,
|
|
list_label_fields,
|
|
update_label_field,
|
|
)
|
|
|
|
bp = Blueprint("fields", __name__, url_prefix="/campuri")
|
|
|
|
|
|
def _form_context(field: dict, *, is_new: bool) -> dict:
|
|
return {
|
|
"field": field,
|
|
"is_new": is_new,
|
|
"catalog": [
|
|
{"key": key, "label": label, "sample": sample}
|
|
for key, label, sample in designer.FIELD_CATALOG
|
|
],
|
|
"max_label": designer.MAX_CUSTOM_LABEL,
|
|
"max_template": designer.MAX_CUSTOM_TEMPLATE,
|
|
}
|
|
|
|
|
|
@bp.get("")
|
|
def index():
|
|
rows = list_label_fields(include_inactive=True)
|
|
for row in rows:
|
|
row["usage"] = count_label_field_usage(row["key"])
|
|
row["preview"] = designer.expand_custom(
|
|
row.get("template") or "",
|
|
designer.apply_custom_fields(designer.demo_fields(), [row]),
|
|
)
|
|
return render_template("fields/list.html", fields=rows)
|
|
|
|
|
|
@bp.route("/nou", methods=["GET", "POST"])
|
|
def create():
|
|
if request.method == "POST":
|
|
data = dict(request.form)
|
|
try:
|
|
designer.validate_custom_field(data)
|
|
create_label_field(data)
|
|
flash("Campul a fost adaugat.", "success")
|
|
return redirect(url_for("fields.index"))
|
|
except ValidationError as exc:
|
|
flash(str(exc), "error")
|
|
return render_template("fields/form.html", **_form_context(data, is_new=True))
|
|
return render_template("fields/form.html",
|
|
**_form_context({"active": 1}, is_new=True))
|
|
|
|
|
|
@bp.route("/<int:field_id>/editare", methods=["GET", "POST"])
|
|
def edit(field_id: int):
|
|
field = get_label_field(field_id)
|
|
if field is None:
|
|
flash("Campul nu exista.", "error")
|
|
return redirect(url_for("fields.index"))
|
|
|
|
if request.method == "POST":
|
|
data = dict(request.form)
|
|
try:
|
|
designer.validate_custom_field(data)
|
|
update_label_field(field_id, data)
|
|
flash("Campul a fost actualizat.", "success")
|
|
return redirect(url_for("fields.index"))
|
|
except ValidationError as exc:
|
|
flash(str(exc), "error")
|
|
field = {**field, **data}
|
|
return render_template("fields/form.html", **_form_context(field, is_new=False))
|
|
|
|
|
|
@bp.post("/<int:field_id>/stergere")
|
|
def remove(field_id: int):
|
|
field = get_label_field(field_id)
|
|
if field is None:
|
|
flash("Campul nu exista.", "error")
|
|
return redirect(url_for("fields.index"))
|
|
delete_label_field(field_id)
|
|
usage = count_label_field_usage(field["key"])
|
|
if usage:
|
|
flash(
|
|
f"Campul {field['label']} a fost sters. Atentie: {usage} sabloane il folosesc "
|
|
"si il vor afisa gol pana il inlocuiesti.",
|
|
"error",
|
|
)
|
|
else:
|
|
flash(f"Campul {field['label']} a fost sters.", "success")
|
|
return redirect(url_for("fields.index"))
|
|
|
|
|
|
@bp.get("/previzualizare")
|
|
def preview():
|
|
"""Valoarea rezultata pentru textul introdus, cu datele demo."""
|
|
text = (request.args.get("template") or "")[: designer.MAX_CUSTOM_TEMPLATE * 2]
|
|
errors = designer.custom_template_errors(text)
|
|
if errors:
|
|
return jsonify({"ok": False, "error": errors[0]})
|
|
demo = designer.demo_fields()
|
|
return jsonify({"ok": True, "value": designer.expand_custom(text, demo)})
|