MHD per Texterkennung einlesen
In der Chargenzeile beim Einlagern gibt es einen Knopf "MHD scannen". Er oeffnet die Texterkennung von VisionKit; erkannte Daten erscheinen als Vorschlag und werden erst uebernommen, wenn man sie antippt. Bewusst kein automatisches Uebernehmen: Eine Fehllesung beim MHD faellt sonst erst auf, wenn die Ware bereits falsch einsortiert ist. Der Parser deckt die Schreibweisen ab, die auf Verpackungen vorkommen - Tagesdaten (12.09.2026, 2026-09-12, 12/09/2026, 12.09.26) und Monatsangaben (09/2026, 09.2026, 2026-09, 09/26). Erkennt der Aufdruck nur Monat und Jahr, stellt sich die Eingabe sichtbar auf Monat/Jahr um. Damit aus Chargennummern und EAN-Codes keine Phantasiedaten werden, greifen mehrere Einschraenkungen: Muster mit Tag werden zuerst geprueft, ein bereits erkannter Textabschnitt wird nicht erneut ausgewertet, Monate ausserhalb 1-12 entfallen und das Jahr muss im Fenster von fuenf Jahren rueckwaerts bis dreissig vorwaerts liegen. Der Knopf erscheint nur, wenn das Geraet Texterkennung unterstuetzt (Neural Engine); sonst bleibt die Eingabe von Hand. Getestet: Der Parser wurde eigenstaendig uebersetzt und gegen 14 Faelle geprueft, alle korrekt - darunter, dass "12.09.2026" nicht als Monatsangabe gelesen wird, dass eine EAN keine Treffer erzeugt und dass unplausible Jahre und Monate verworfen werden. Der iOS-Geraetebuild laeuft fehlerfrei durch. Die Erkennung an einer echten Verpackung habe ich nicht selbst ausprobiert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -107,6 +107,27 @@ actor APIClient {
|
||||
return try await send(request, as: Product.self)
|
||||
}
|
||||
|
||||
func updateProduct(id: Int, _ payload: ProductUpdateRequest) async throws -> Product {
|
||||
var request = try makeRequest("/products/\(id)", method: "PATCH")
|
||||
try jsonBody(&request, payload)
|
||||
return try await send(request, as: Product.self)
|
||||
}
|
||||
|
||||
// MARK: - Listen
|
||||
|
||||
func shoppingList() async throws -> [ShoppingItem] {
|
||||
try await send(try makeRequest("/shopping-list"), as: [ShoppingItem].self)
|
||||
}
|
||||
|
||||
func shoppingGroups() async throws -> [GroupShoppingItem] {
|
||||
try await send(try makeRequest("/shopping-list/groups"), as: [GroupShoppingItem].self)
|
||||
}
|
||||
|
||||
func expiring(days: Int? = nil) async throws -> [ExpiringItem] {
|
||||
let path = days.map { "/expiring?days=\($0)" } ?? "/expiring"
|
||||
return try await send(try makeRequest(path), as: [ExpiringItem].self)
|
||||
}
|
||||
|
||||
// MARK: - Bestand
|
||||
|
||||
func lots(productId: Int) async throws -> [Lot] {
|
||||
@@ -124,4 +145,16 @@ actor APIClient {
|
||||
try jsonBody(&request, payload)
|
||||
return try await send(request, as: StockResponse.self)
|
||||
}
|
||||
|
||||
func updateLot(id: Int, _ payload: LotUpdateRequest) async throws -> Lot {
|
||||
var request = try makeRequest("/lots/\(id)", method: "PATCH")
|
||||
try jsonBody(&request, payload)
|
||||
return try await send(request, as: Lot.self)
|
||||
}
|
||||
|
||||
func deleteLot(id: Int) async throws {
|
||||
let request = try makeRequest("/lots/\(id)", method: "DELETE")
|
||||
let (data, response) = try await URLSession.shared.data(for: request)
|
||||
try check(response, data: data) // 204: kein Rumpf zum Auswerten
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user