iOS: Kassenzettel scannen -> Lebensmittel erkennen & einlagern

Neuer Flow (Kachel im Listen-Tab): Foto aufnehmen/waehlen, Artikelbereich per
Rechteck markieren, on-device OCR (Vision, deutsch; Bild bleibt auf dem Geraet),
Zeilen an /products/match schicken. Pruefen-Liste je Zeile: Artikel-Picker
(Auto-Treffer ueber Schwellwert + eigene Lebensmittel-Suche), Menge (aus Zeile
geparst, korrigierbar), Lagerort-Dropdown + QR-Scan. Einlagern per checkInBatch,
unbekannte Zeilen werden uebersprungen; keine Neuanlage.

Backend: MatchCandidate traegt package_size/base_unit mit, damit die App die
Einheit ohne Extra-Abruf kennt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-30 18:40:10 +02:00
parent 9cc3e325bb
commit 648b8294b8
6 changed files with 488 additions and 1 deletions

View File

@@ -277,6 +277,38 @@ struct BatchCheckInRequest: Codable {
}
}
// MARK: - Kassenzettel-Abgleich
struct MatchRequest: Codable {
let lines: [String]
let threshold: Int?
}
struct MatchCandidate: Codable, Identifiable, Hashable {
let productId: Int
let name: String
let brand: String?
let score: Int
let packageSize: Double?
let baseUnit: String
var id: Int { productId }
/// Einheit fuers Einlagern: ganze Gebinde, sonst die Basiseinheit.
var checkInUnit: String { (packageSize ?? 0) > 0 ? "package" : baseUnit }
enum CodingKeys: String, CodingKey {
case name, brand, score
case productId = "product_id"
case packageSize = "package_size"
case baseUnit = "base_unit"
}
}
struct MatchLine: Codable {
let text: String
let candidates: [MatchCandidate]
}
struct CheckOutRequest: Codable {
let productId: Int
let quantity: Double