Backend-Arbeitsstand: ERP-Sync, Lieferlebenszyklus, Reports + config.toml
Bringt das Backend vom initialen Skeleton auf den aktuellen Arbeitsstand (Clean Architecture: domain → application → infrastructure → api). Wesentliche Bereiche: - ERP-Anbindung (MSSQL-Pull der Touren, Import-Scheduler, Rückschreiben) - Lieferlebenszyklus: Scan/Hold/Cancel/Complete, Gutschriften, Notizen, Bild-Anhänge, Unterschriften, PDF-Lieferreport → DOCUframe - Stammdaten: Kunden, Artikel, Lager, Zahlungsarten, Services - Keycloak-JWT-Gate + Fahrer-Provisionierung via Admin-API - Admin-API-Key-Gate (X-Admin-Api-Key) für Maschinen-Endpunkte Jüngste Änderungen dieser Session: - Belegspezifische Kontaktdaten: alle ERP-Adressen (Beleg-/Liefer-/ Rechnungsadresse, Ansprechpartner, Kundenstamm) mit Telefon/Mobil/ E-Mail werden gesynct (Migration 0029, MSSQL-Query, TourDetails) - Konfiguration von .env (envy/dotenvy) auf config.toml (toml/serde) umgestellt; Vorlage config.example.toml, Pfad via HOLZLEITNER_CONFIG Nicht im Repo (per .gitignore): config.toml (Secrets), data/ (Laufzeit-/ Kundendaten), demo.mp4, .claude/, variocontrol-ai/. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
97
tool/mark_all_scanned.sh
Executable file
97
tool/mark_all_scanned.sh
Executable file
@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Markiert ALLE scanbaren Items der Test-Touren als erfolgreich gescannt
|
||||
# (scan_status = 'done', scanned_quantity = required_quantity). Damit
|
||||
# erscheint jede Lieferung als „fertig beladen" und die Auslieferungs-Phase
|
||||
# lässt sich Ende-zu-Ende testen, ohne jedes Gerät am Gerät zu scannen.
|
||||
#
|
||||
# Im Gegensatz zur früheren Inline-Variante (nur Standardlager) erfasst
|
||||
# dieses Skript bewusst auch das Filiale — Ziel ist „nichts mehr offen".
|
||||
#
|
||||
# Regeln:
|
||||
# * nur scanbare Artikel (Dienstleistungen werden nicht gescannt)
|
||||
# * Standard- UND Filiale
|
||||
# * Items mit Status 'removed' bleiben unangetastet (bewusst entfernt)
|
||||
# * 'held' wird ebenfalls auf 'done' gehoben (sauberer Fertig-Zustand)
|
||||
#
|
||||
# Accounts:
|
||||
# * Default: 1001,1002 (die Demo-Test-Accounts)
|
||||
# * via Env überschreibbar: ACCOUNTS="1001,1002,1003" ./tool/mark_all_scanned.sh
|
||||
#
|
||||
# Aufruf:
|
||||
# ./tool/mark_all_scanned.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CONTAINER="${CONTAINER:-holzleitner-postgres}"
|
||||
DB_USER="${DB_USER:-holzleitner}"
|
||||
DB_NAME="${DB_NAME:-holzleitner}"
|
||||
ACCOUNTS="${ACCOUNTS:-1001,1002}"
|
||||
|
||||
# Nur Ziffern + Kommas — schützt die rohe psql-Variablen-Substitution unten
|
||||
# vor Injection.
|
||||
if ! [[ "$ACCOUNTS" =~ ^[0-9]+(,[0-9]+)*$ ]]; then
|
||||
echo "✗ Ungültige ACCOUNTS-Liste '$ACCOUNTS'. Erwartet: kommagetrennte Zahlen, z.B. 1001,1002." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker inspect "$CONTAINER" >/dev/null 2>&1; then
|
||||
echo "✗ Container '$CONTAINER' läuft nicht. Starte docker compose up -d." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "→ Alle scanbaren Items der Accounts ($ACCOUNTS) auf 'done' setzen …"
|
||||
|
||||
docker exec -i "$CONTAINER" psql -U "$DB_USER" -d "$DB_NAME" -v ON_ERROR_STOP=1 -q \
|
||||
-v accounts="$ACCOUNTS" <<'SQL'
|
||||
BEGIN;
|
||||
|
||||
-- Status VOR dem Update (Kontrolle).
|
||||
\echo
|
||||
\echo --- VORHER ---
|
||||
SELECT w.name AS lager, di.scan_status, COUNT(*) AS items
|
||||
FROM delivery_items di
|
||||
JOIN deliveries d ON d.id = di.delivery_id
|
||||
JOIN tours t ON t.id = d.tour_id
|
||||
JOIN warehouses w ON w.id = di.warehouse_id
|
||||
JOIN articles a ON a.id = di.article_id
|
||||
WHERE t.account_id IN (:accounts)
|
||||
AND a.scannable = TRUE
|
||||
GROUP BY w.name, di.scan_status
|
||||
ORDER BY w.name, di.scan_status;
|
||||
|
||||
-- Update über Subquery: Postgres erlaubt im UPDATE … FROM keinen
|
||||
-- Self-Join auf die Zieltabelle in der JOIN-Bedingung, daher die Id-Liste
|
||||
-- vorab per SELECT bestimmen.
|
||||
UPDATE delivery_items
|
||||
SET scanned_quantity = required_quantity,
|
||||
scan_status = 'done',
|
||||
scan_last_updated_at = now()
|
||||
WHERE id IN (
|
||||
SELECT di.id
|
||||
FROM delivery_items di
|
||||
JOIN deliveries d ON d.id = di.delivery_id
|
||||
JOIN tours t ON t.id = d.tour_id
|
||||
JOIN articles a ON a.id = di.article_id
|
||||
WHERE t.account_id IN (:accounts)
|
||||
AND a.scannable = TRUE
|
||||
AND di.scan_status <> 'removed'
|
||||
);
|
||||
|
||||
\echo
|
||||
\echo --- NACHHER ---
|
||||
SELECT w.name AS lager, di.scan_status, COUNT(*) AS items
|
||||
FROM delivery_items di
|
||||
JOIN deliveries d ON d.id = di.delivery_id
|
||||
JOIN tours t ON t.id = d.tour_id
|
||||
JOIN warehouses w ON w.id = di.warehouse_id
|
||||
JOIN articles a ON a.id = di.article_id
|
||||
WHERE t.account_id IN (:accounts)
|
||||
AND a.scannable = TRUE
|
||||
GROUP BY w.name, di.scan_status
|
||||
ORDER BY w.name, di.scan_status;
|
||||
|
||||
COMMIT;
|
||||
SQL
|
||||
|
||||
echo "✓ Alle scanbaren Items auf 'done' gesetzt — Auslieferung testbar."
|
||||
Reference in New Issue
Block a user