This commit is contained in:
@@ -151,16 +151,20 @@ location /app/wdm-performance/ {
|
|||||||
(.xlsx) oder CSV-Datei per Drag & Drop oder Dateiauswahl bulk-anlegen,
|
(.xlsx) oder CSV-Datei per Drag & Drop oder Dateiauswahl bulk-anlegen,
|
||||||
siehe eigener Abschnitt unten
|
siehe eigener Abschnitt unten
|
||||||
- **Auftragsübersicht**: alle Aufträge (inkl. Artikel, Maschinenname),
|
- **Auftragsübersicht**: alle Aufträge (inkl. Artikel, Maschinenname),
|
||||||
standardmäßig nur offen/pausiert (umschaltbar auf "Alle"), optional nach
|
standardmäßig offen/pausiert **und aktiv** (umschaltbar auf "Alle", zeigt
|
||||||
Maschine gefiltert, löschbar und (mit Einschränkungen) bearbeitbar:
|
dann zusätzlich auch abgeschlossene Aufträge), optional nach Maschine
|
||||||
- **Status und Priorität sind hier nicht editierbar** (nur informativ
|
gefiltert, löschbar und (mit Einschränkungen) bearbeitbar:
|
||||||
angezeigt) – Status ändert sich ausschließlich über die eigentlichen
|
- **Status ist hier manuell änderbar** (z.B. um einen versehentlich
|
||||||
Maschinen-Aktionen (Start/Pause/Beenden), Priorität ausschließlich über
|
abgeschlossenen Auftrag wieder auf "Offen" zu setzen) – **"Aktiv" ist als
|
||||||
die Drag & Drop-Seite "Auftragspriorität".
|
Zielwert bewusst ausgeschlossen**, das passiert ausschließlich über die
|
||||||
- **Aktive Aufträge werden angezeigt, können aber nicht bearbeitet
|
eigentlichen Maschinen-Aktionen (Start/Pause/Beenden). **Priorität bleibt
|
||||||
werden** – ein Bearbeitungsversuch (auch ein direkter POST) wird mit
|
weiterhin nicht editierbar**, dafür gibt es die Drag & Drop-Seite
|
||||||
einer Fehlermeldung abgelehnt, solange der Auftrag gerade an der
|
"Auftragspriorität".
|
||||||
Maschine läuft.
|
- **Aktive Aufträge werden angezeigt, können aber weder bearbeitet noch
|
||||||
|
gelöscht werden** – Bearbeiten- und Löschen-Button werden für sie in der
|
||||||
|
Liste durch einen Hinweistext ersetzt; ein direkter POST-Versuch (am UI
|
||||||
|
vorbei) wird serverseitig ebenfalls abgelehnt, solange der Auftrag gerade
|
||||||
|
an der Maschine läuft.
|
||||||
- Editierbar bleiben Maschine (inkl. automatischem Umhängen der kompletten
|
- Editierbar bleiben Maschine (inkl. automatischem Umhängen der kompletten
|
||||||
MDE-Buchungshistorie auf die neue Maschine), Auftragsnummer, Artikel,
|
MDE-Buchungshistorie auf die neue Maschine), Auftragsnummer, Artikel,
|
||||||
Produktionsmenge und Stück/Stunde.
|
Produktionsmenge und Stück/Stunde.
|
||||||
|
|||||||
+42
-11
@@ -58,6 +58,11 @@ STATUS_LABEL = {
|
|||||||
"abgeschlossen": "Abgeschlossen",
|
"abgeschlossen": "Abgeschlossen",
|
||||||
}
|
}
|
||||||
STATUS_OPTIONEN = [("offen", "Offen"), ("aktiv", "Aktiv"), ("pause", "Pausiert"), ("abgeschlossen", "Abgeschlossen")]
|
STATUS_OPTIONEN = [("offen", "Offen"), ("aktiv", "Aktiv"), ("pause", "Pausiert"), ("abgeschlossen", "Abgeschlossen")]
|
||||||
|
# In der Auftragsübersicht darf der Status manuell gesetzt werden (z.B. um einen
|
||||||
|
# Auftrag versehentlich abgeschlossenen wieder zu öffnen) - "aktiv" ist hier
|
||||||
|
# aber bewusst ausgeschlossen, das passiert ausschließlich über die
|
||||||
|
# Start-Aktion an der Maschine selbst.
|
||||||
|
STATUS_OPTIONEN_BEARBEITBAR = [(wert, label) for wert, label in STATUS_OPTIONEN if wert != "aktiv"]
|
||||||
|
|
||||||
# Anzahl Zeilen, auf die MDE-/Auftragslisten ausgelegt sind (kein hartes Limit,
|
# Anzahl Zeilen, auf die MDE-/Auftragslisten ausgelegt sind (kein hartes Limit,
|
||||||
# aber Referenzgröße für Layout/Performance-Überlegungen).
|
# aber Referenzgröße für Layout/Performance-Überlegungen).
|
||||||
@@ -705,7 +710,11 @@ def leitstand_uebersicht():
|
|||||||
bedingungen.append('maschine_id = %s')
|
bedingungen.append('maschine_id = %s')
|
||||||
params.append(filter_maschine_id)
|
params.append(filter_maschine_id)
|
||||||
if filter_status == "offen_pause":
|
if filter_status == "offen_pause":
|
||||||
bedingungen.append("status IN ('offen', 'pause')")
|
# "aktiv" wird hier bewusst mit angezeigt (nur informativ, nicht
|
||||||
|
# bearbeitbar/löschbar - siehe leitstand_uebersicht_bearbeiten
|
||||||
|
# bzw. leitstand_uebersicht_loeschen), damit laufende Aufträge in
|
||||||
|
# der Übersicht nicht verschwinden.
|
||||||
|
bedingungen.append("status IN ('offen', 'pause', 'aktiv')")
|
||||||
|
|
||||||
where_sql = (" WHERE " + " AND ".join(bedingungen)) if bedingungen else ""
|
where_sql = (" WHERE " + " AND ".join(bedingungen)) if bedingungen else ""
|
||||||
cur.execute(
|
cur.execute(
|
||||||
@@ -735,12 +744,14 @@ def leitstand_uebersicht():
|
|||||||
|
|
||||||
@app.route("/start_uebersicht/<int:auftrag_id>/bearbeiten", methods=["GET", "POST"])
|
@app.route("/start_uebersicht/<int:auftrag_id>/bearbeiten", methods=["GET", "POST"])
|
||||||
def leitstand_uebersicht_bearbeiten(auftrag_id):
|
def leitstand_uebersicht_bearbeiten(auftrag_id):
|
||||||
"""Auftrag bearbeiten. Status und Priorität (sid) sind hier bewusst NICHT
|
"""Auftrag bearbeiten. Der Status ist hier manuell änderbar (z.B. um einen
|
||||||
editierbar - Status ändert sich nur über die eigentlichen Maschinen-
|
versehentlich abgeschlossenen Auftrag wieder auf "offen" zu setzen) -
|
||||||
Aktionen (Start/Pause/Beenden), Priorität nur über die Drag&Drop-Seite
|
"aktiv" ist als Zielwert bewusst ausgeschlossen, das passiert
|
||||||
"Auftragspriorität". Aktive Aufträge werden nur angezeigt, eine
|
ausschließlich über die eigentlichen Maschinen-Aktionen (Start/Pause/
|
||||||
Bearbeitung wird komplett verweigert (Fehlermeldung), da sie gerade an
|
Beenden). Priorität (sid) ist weiterhin NICHT editierbar, dafür gibt es
|
||||||
der Maschine läuft."""
|
die Drag&Drop-Seite "Auftragspriorität". Aktive Aufträge werden nur
|
||||||
|
angezeigt, eine Bearbeitung wird komplett verweigert (Fehlermeldung), da
|
||||||
|
sie gerade an der Maschine läuft."""
|
||||||
filter_maschine_id = request.args.get("maschine_id") or request.form.get("maschine_id_filter") or ""
|
filter_maschine_id = request.args.get("maschine_id") or request.form.get("maschine_id_filter") or ""
|
||||||
filter_status = request.args.get("status") or request.form.get("status_filter") or "offen_pause"
|
filter_status = request.args.get("status") or request.form.get("status_filter") or "offen_pause"
|
||||||
with db.get_cursor() as cur:
|
with db.get_cursor() as cur:
|
||||||
@@ -759,6 +770,7 @@ def leitstand_uebersicht_bearbeiten(auftrag_id):
|
|||||||
"leitstand_uebersicht_bearbeiten.html", title="Auftrag bearbeiten",
|
"leitstand_uebersicht_bearbeiten.html", title="Auftrag bearbeiten",
|
||||||
auftrag=alt, maschinen=maschinen, gesperrt=True,
|
auftrag=alt, maschinen=maschinen, gesperrt=True,
|
||||||
status_anzeige=STATUS_LABEL.get(alt["status"], alt["status"]),
|
status_anzeige=STATUS_LABEL.get(alt["status"], alt["status"]),
|
||||||
|
status_optionen=STATUS_OPTIONEN_BEARBEITBAR,
|
||||||
filter_maschine_id=filter_maschine_id, filter_status=filter_status,
|
filter_maschine_id=filter_maschine_id, filter_status=filter_status,
|
||||||
error="Dieser Auftrag ist aktuell aktiv und kann deshalb nicht bearbeitet werden. "
|
error="Dieser Auftrag ist aktuell aktiv und kann deshalb nicht bearbeitet werden. "
|
||||||
"Bitte an der Maschine erst pausieren oder beenden.",
|
"Bitte an der Maschine erst pausieren oder beenden.",
|
||||||
@@ -770,6 +782,7 @@ def leitstand_uebersicht_bearbeiten(auftrag_id):
|
|||||||
soll_h = request.form.get("soll_h")
|
soll_h = request.form.get("soll_h")
|
||||||
artikel = (request.form.get("artikel") or "").strip() or None
|
artikel = (request.form.get("artikel") or "").strip() or None
|
||||||
neue_maschine_id = request.form.get("maschine_id")
|
neue_maschine_id = request.form.get("maschine_id")
|
||||||
|
neuer_status = request.form.get("status")
|
||||||
|
|
||||||
error = None
|
error = None
|
||||||
einheiten_f = soll_h_f = None
|
einheiten_f = soll_h_f = None
|
||||||
@@ -782,6 +795,10 @@ def leitstand_uebersicht_bearbeiten(auftrag_id):
|
|||||||
if not error and not auftragsnummer:
|
if not error and not auftragsnummer:
|
||||||
error = "Auftragsnummer darf nicht leer sein."
|
error = "Auftragsnummer darf nicht leer sein."
|
||||||
|
|
||||||
|
gueltige_status = {wert for wert, _ in STATUS_OPTIONEN_BEARBEITBAR}
|
||||||
|
if not error and neuer_status not in gueltige_status:
|
||||||
|
error = "Ungültiger Status."
|
||||||
|
|
||||||
if not error:
|
if not error:
|
||||||
if not neue_maschine_id:
|
if not neue_maschine_id:
|
||||||
error = "Maschine muss ausgewählt werden."
|
error = "Maschine muss ausgewählt werden."
|
||||||
@@ -806,17 +823,27 @@ def leitstand_uebersicht_bearbeiten(auftrag_id):
|
|||||||
auftrag["sid_fmt"] = fmt_num(alt["sid"])
|
auftrag["sid_fmt"] = fmt_num(alt["sid"])
|
||||||
auftrag["artikel"] = artikel
|
auftrag["artikel"] = artikel
|
||||||
auftrag["maschine_id"] = neue_maschine_id or alt["maschine_id"]
|
auftrag["maschine_id"] = neue_maschine_id or alt["maschine_id"]
|
||||||
|
auftrag["status"] = neuer_status if neuer_status in gueltige_status else alt["status"]
|
||||||
return render_template(
|
return render_template(
|
||||||
"leitstand_uebersicht_bearbeiten.html", title="Auftrag bearbeiten",
|
"leitstand_uebersicht_bearbeiten.html", title="Auftrag bearbeiten",
|
||||||
auftrag=auftrag, maschinen=maschinen,
|
auftrag=auftrag, maschinen=maschinen,
|
||||||
status_anzeige=STATUS_LABEL.get(alt["status"], alt["status"]),
|
status_anzeige=STATUS_LABEL.get(alt["status"], alt["status"]),
|
||||||
|
status_optionen=STATUS_OPTIONEN_BEARBEITBAR,
|
||||||
filter_maschine_id=filter_maschine_id, filter_status=filter_status, error=error,
|
filter_maschine_id=filter_maschine_id, filter_status=filter_status, error=error,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Wurde der Status auf "abgeschlossen" geändert (oder war er das
|
||||||
|
# schon und bleibt es), Endzeitpunkt entsprechend setzen bzw.
|
||||||
|
# beibehalten - beim (Wieder-)Öffnen wird er zurückgesetzt.
|
||||||
|
if neuer_status == "abgeschlossen":
|
||||||
|
ende_wert = alt["ende"] if alt["status"] == "abgeschlossen" else now_ts()
|
||||||
|
else:
|
||||||
|
ende_wert = None
|
||||||
|
|
||||||
cur.execute(
|
cur.execute(
|
||||||
'UPDATE "Auftraege" SET auftragsnummer = %s, einheiten = %s, soll_h = %s, '
|
'UPDATE "Auftraege" SET auftragsnummer = %s, einheiten = %s, soll_h = %s, '
|
||||||
'artikel = %s, maschine_id = %s WHERE id = %s',
|
'artikel = %s, maschine_id = %s, status = %s, aktiv = false, ende = %s WHERE id = %s',
|
||||||
(auftragsnummer, einheiten_f, soll_h_f, artikel, neue_maschine_id, auftrag_id),
|
(auftragsnummer, einheiten_f, soll_h_f, artikel, neue_maschine_id, neuer_status, ende_wert, auftrag_id),
|
||||||
)
|
)
|
||||||
# Maschine und/oder Auftragsnummer geändert? Dann muss die MDE-Historie
|
# Maschine und/oder Auftragsnummer geändert? Dann muss die MDE-Historie
|
||||||
# (dort per maschine_id + Auftragsnummer verknüpft) mitgezogen werden.
|
# (dort per maschine_id + Auftragsnummer verknüpft) mitgezogen werden.
|
||||||
@@ -835,6 +862,7 @@ def leitstand_uebersicht_bearbeiten(auftrag_id):
|
|||||||
"leitstand_uebersicht_bearbeiten.html", title="Auftrag bearbeiten",
|
"leitstand_uebersicht_bearbeiten.html", title="Auftrag bearbeiten",
|
||||||
auftrag=alt, maschinen=maschinen,
|
auftrag=alt, maschinen=maschinen,
|
||||||
status_anzeige=STATUS_LABEL.get(alt["status"], alt["status"]),
|
status_anzeige=STATUS_LABEL.get(alt["status"], alt["status"]),
|
||||||
|
status_optionen=STATUS_OPTIONEN_BEARBEITBAR,
|
||||||
filter_maschine_id=filter_maschine_id, filter_status=filter_status,
|
filter_maschine_id=filter_maschine_id, filter_status=filter_status,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -844,7 +872,10 @@ def leitstand_uebersicht_loeschen(auftrag_id):
|
|||||||
filter_maschine_id = request.form.get("maschine_id") or ""
|
filter_maschine_id = request.form.get("maschine_id") or ""
|
||||||
filter_status = request.form.get("status") or "offen_pause"
|
filter_status = request.form.get("status") or "offen_pause"
|
||||||
with db.get_cursor() as cur:
|
with db.get_cursor() as cur:
|
||||||
cur.execute('DELETE FROM "Auftraege" WHERE id = %s', (auftrag_id,))
|
# Aktive Aufträge (gerade an der Maschine laufend) dürfen hier nicht
|
||||||
|
# gelöscht werden können, unabhängig davon, was im UI angeboten wird
|
||||||
|
# (analog zur Bearbeiten-Sperre für aktive Aufträge).
|
||||||
|
cur.execute('DELETE FROM "Auftraege" WHERE id = %s AND status <> \'aktiv\'', (auftrag_id,))
|
||||||
return redirect(url_for("leitstand_uebersicht", maschine_id=filter_maschine_id, status=filter_status))
|
return redirect(url_for("leitstand_uebersicht", maschine_id=filter_maschine_id, status=filter_status))
|
||||||
|
|
||||||
|
|
||||||
@@ -1123,4 +1154,4 @@ def health():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(host="0.0.0.0", port=5000, debug=False)
|
app.run(host="0.0.0.0", port=5000, debug=False)
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
</select>
|
</select>
|
||||||
<span>Status:</span>
|
<span>Status:</span>
|
||||||
<select name="status" onchange="this.form.submit()">
|
<select name="status" onchange="this.form.submit()">
|
||||||
<option value="offen_pause" {% if filter_status == "offen_pause" %}selected{% endif %}>Offen/Pausiert</option>
|
<option value="offen_pause" {% if filter_status == "offen_pause" %}selected{% endif %}>Offen/Pausiert/Aktiv</option>
|
||||||
<option value="alle" {% if filter_status == "alle" %}selected{% endif %}>Alle</option>
|
<option value="alle" {% if filter_status == "alle" %}selected{% endif %}>Alle</option>
|
||||||
</select>
|
</select>
|
||||||
<button type="submit">Filtern</button>
|
<button type="submit">Filtern</button>
|
||||||
@@ -42,6 +42,9 @@
|
|||||||
<td>{{ "Ja" if a.aktiv else "Nein" }}</td>
|
<td>{{ "Ja" if a.aktiv else "Nein" }}</td>
|
||||||
<td>{{ a.sid_fmt }}</td>
|
<td>{{ a.sid_fmt }}</td>
|
||||||
<td class="col-actions">
|
<td class="col-actions">
|
||||||
|
{% if a.status == "aktiv" %}
|
||||||
|
<span style="color:var(--text-dim); font-size:0.85em;">gesperrt (aktiv an Maschine)</span>
|
||||||
|
{% else %}
|
||||||
<div class="row-actions">
|
<div class="row-actions">
|
||||||
<a class="icon-btn" href="{{ url_for('leitstand_uebersicht_bearbeiten', auftrag_id=a.id, maschine_id=filter_maschine_id, status=filter_status) }}">Bearbeiten</a>
|
<a class="icon-btn" href="{{ url_for('leitstand_uebersicht_bearbeiten', auftrag_id=a.id, maschine_id=filter_maschine_id, status=filter_status) }}">Bearbeiten</a>
|
||||||
<form method="post" action="{{ url_for('leitstand_uebersicht_loeschen', auftrag_id=a.id) }}" class="order-form">
|
<form method="post" action="{{ url_for('leitstand_uebersicht_loeschen', auftrag_id=a.id) }}" class="order-form">
|
||||||
@@ -50,6 +53,7 @@
|
|||||||
<button type="submit" class="icon-btn danger">Löschen</button>
|
<button type="submit" class="icon-btn danger">Löschen</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -57,4 +61,4 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -31,7 +31,18 @@
|
|||||||
<label for="soll_h">Stück pro Stunde</label>
|
<label for="soll_h">Stück pro Stunde</label>
|
||||||
<input type="number" step="any" id="soll_h" name="soll_h" value="{{ auftrag.soll_h_fmt }}" {{ 'readonly' if gesperrt }} required>
|
<input type="number" step="any" id="soll_h" name="soll_h" value="{{ auftrag.soll_h_fmt }}" {{ 'readonly' if gesperrt }} required>
|
||||||
</div>
|
</div>
|
||||||
|
{% if gesperrt %}
|
||||||
<div class="status-line"><span class="label">Status</span><span>{{ status_anzeige }}</span></div>
|
<div class="status-line"><span class="label">Status</span><span>{{ status_anzeige }}</span></div>
|
||||||
|
{% else %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="status">Status</label>
|
||||||
|
<select id="status" name="status" required>
|
||||||
|
{% for wert, label in status_optionen %}
|
||||||
|
<option value="{{ wert }}" {% if auftrag.status == wert %}selected{% endif %}>{{ label }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div class="status-line">
|
<div class="status-line">
|
||||||
<span class="label">Priorität</span>
|
<span class="label">Priorität</span>
|
||||||
<span>{{ auftrag.sid_fmt }} <span style="color:var(--text-dim); font-size:0.85em;">(änderbar unter "Auftragspriorität")</span></span>
|
<span>{{ auftrag.sid_fmt }} <span style="color:var(--text-dim); font-size:0.85em;">(änderbar unter "Auftragspriorität")</span></span>
|
||||||
|
|||||||
Reference in New Issue
Block a user