Eine Kategorie mit Artikeln zeigte "0 EANs", und der Versuch, den Code eines eigenen Artikels einzutragen, scheiterte mit "Dieser Code ist bereits vergeben". Beides war fachlich richtig, aber nirgends erklaert. Hintergrund: Die Code-Liste einer Kategorie ist eine Vorratsliste fuer Artikel, die es noch nicht gibt. Sie greift nur, wenn beim Einlagern ein unbekannter Code gescannt wird - dann landet der neu angelegte Artikel in dieser Kategorie (routers/products.lookup). Haengt ein Code bereits an einem Artikel, findet die Suche immer zuerst den Artikel; ein gleichlautender Kategorie-Eintrag koennte nie wirken. Die Spalte zaehlte bisher ausschliesslich diese Vorratscodes, nie die Codes der enthaltenen Artikel - daher die irritierende 0. Die Kategorie liefert jetzt zusaetzlich die Codes ihrer Artikel mit (product_barcodes, rein informativ). Beide Herkuenfte stehen in einer Liste: Artikel-Codes sind als solche gekennzeichnet, nennen den Artikel und lassen sich hier nicht loeschen, weil sie am Artikel haengen. Bewusst ohne Dublette in der Datenbank - ein zweiter Datensatz koennte nie greifen und beim Loeschen des Artikels verwaisen. Die Spalte zaehlt beide Herkuenfte. Die Fehlermeldung sagt jetzt, wem ein Code gehoert: beim Artikel mit Namen und dem Hinweis, dass Artikel-Codes hier nicht eingetragen werden muessen; bei einer anderen Kategorie mit deren Namen. Signal beim Einlagern: Wird ein Code erkannt, der einer Kategorie zugeordnet ist, steht jetzt deutlich sichtbar "Wird automatisch der Kategorie X zugeordnet" samt Begruendung - sowohl im Web als auch in der App, und in beiden Faellen (Open-Food-Facts-Treffer und voellig unbekannter Code). Nach dem Anlegen meldet die Web-Oberflaeche zurueck, welche Kategorie es geworden ist. Vorher stand die Zuordnung nur als Nebensatz in grauer Kleinschrift. Getestet: Gegen die laufende API geprueft, dass eine Kategorie die Codes ihrer Artikel meldet (Haupt-Barcode und zusaetzliche Alias-Codes), dass das Eintragen eines Artikel-Codes und eines fremden Kategorie-Codes mit der jeweils richtigen Begruendung abgewiesen wird und dass ein echter Vorratscode weiterhin angelegt werden kann. iOS-Geraetebuild und Web-Build fehlerfrei, 40 pytest-Tests gruen. Dabei zwei Uebersetzungsfehler durch deutsche Anfuehrungszeichen gefunden: Das schliessende Zeichen war ein gerades ", das den String vorzeitig beendete. Korrigiert und die uebrigen Vorkommen im Projekt gleich mit vereinheitlicht. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Project-Good – iOS-App
Native SwiftUI-App zum Ein- und Auslagern per Barcode-Scan. Sie spricht dieselbe REST-API wie die Web-Oberfläche.
Stand: Läuft auf dem Gerät. Login, Scanner, Einlagern mit mehreren Chargen/MHDs, MHD per Texterkennung, Auslagern mit Chargenauswahl, Artikel anlegen aus Open Food Facts, Einkaufsliste, Ablaufliste sowie Produkte ansehen und bearbeiten.
Projekt in Xcode öffnen
Variante A – mit XcodeGen (empfohlen)
brew install xcodegen
cd ios
xcodegen generate
open ProjectGood.xcodeproj
project.yml beschreibt das Projekt vollständig (Bundle-ID, Info.plist,
Shortcuts, URL-Schema).
Variante B – ohne XcodeGen
- Xcode → File ▸ New ▸ Project… → App, Interface SwiftUI, Sprache Swift
- Produktname
ProjectGood, Bundle-ID z. B.com.scarriffle.projectgood - Die von Xcode erzeugte
ContentView.swiftund…App.swiftlöschen - Den Ordner
Sources/per Drag & Drop ins Projekt ziehen („Copy items if needed") - In den Target-Einstellungen die mitgelieferte
Sources/Info.plistals Info.plist setzen (Build Settings ▸ Info.plist File) und Generate Info.plist File auf No stellen
Auf dem iPhone installieren
- iPhone per Kabel verbinden, in Xcode als Ziel auswählen
- Signing & Capabilities → dein Apple-Developer-Team wählen
- ▶︎ Run. Beim ersten Start auf dem iPhone unter Einstellungen ▸ Allgemein ▸ VPN & Geräteverwaltung dem Entwickler vertrauen
Erste Schritte in der App
Beim Start nach der Server-Adresse fragen lassen, z. B. http://192.168.1.50:8080
(dieselbe Adresse wie im Browser), dann mit deinem Benutzer anmelden. Adresse und
Token bleiben gespeichert – das Token liegt im Keychain.
Home-Screen-Shortcuts
Es gibt zwei Wege direkt in den Scan-Bildschirm:
Schnellaktionen – langer Druck auf das App-Symbol zeigt „Einlagern" und „Auslagern" (funktioniert ohne weitere Einrichtung).
Eigene Symbole auf dem Home-Bildschirm – über die Apple-App Kurzbefehle:
- Kurzbefehle ▸ + ▸ Aktion URL öffnen
- URL
projectgood://checkin(bzw.projectgood://checkout) eintragen - Kurzbefehl benennen, dann ▸ Zum Home-Bildschirm hinzufügen
Beide Wege öffnen die App direkt in der Kamera.
Aufbau der Quellen
| Datei | Inhalt |
|---|---|
ProjectGoodApp.swift |
App-Einstieg, Schnellaktionen, URL-Schema |
Session.swift |
Server-Adresse (UserDefaults) und Token (Keychain) |
APIClient.swift |
REST-Aufrufe gegen /api/... |
Models.swift |
Codable-Typen passend zu backend/app/schemas.py |
ScannerView.swift |
Kamera + Barcode-Erkennung (EAN-8/13, UPC-E, Code128, QR) |
RootView.swift |
Startbildschirm und Routing |
LoginView.swift |
Server + Anmeldung |
CheckInView.swift / CheckInFormView.swift |
Scan → Menge, mehrere Chargen mit MHD |
CheckOutView.swift |
Scan → Menge, Chargenauswahl oder FEFO |
ProductViews.swift |
Artikelsuche und Anlegen (mit OFF-Vorbefüllung) |
ProductDetailView.swift |
Produkt bearbeiten, Chargen korrigieren und löschen |
ListViews.swift |
Einkaufsliste, „bald ablaufend", Produktliste |
DateScanView.swift / BestBeforeText.swift |
MHD per Texterkennung ablesen |
DisplaySettings.swift |
Datumsformat und Einheiten-Beschriftungen vom Server |
Kategorien
Was in der Datenbank und in der Schnittstelle group heißt, trägt in der
Oberfläche den Namen Kategorie („Molkereiprodukte", „Brot", …). Der Name in
API und Tabelle blieb bewusst unverändert, damit bestehende Zugriffe – etwa aus
Home Assistant – weiterlaufen.
Noch offen
- Push-Benachrichtigungen bei ablaufenden Produkten
- Lagerort je Charge beim Einlagern wählbar