iOS-App angefangen; Import-Modi; MHD-Formatierung; Gebinde in Ablauf-Ansichten
iOS (neu, ios/):
- SwiftUI-App: Login (Server + Keychain-Token), Kamera-Scanner (EAN/UPC/Code128),
Einlagern mit mehreren Chargen und eigenem MHD, Auslagern mit Chargenauswahl
oder FEFO, Artikelsuche, Anlegen mit Open-Food-Facts-Vorbefuellung.
- Home-Screen-Shortcuts: Schnellaktionen (langer Druck) und URL-Schema
projectgood://checkin | ://checkout fuer eigene Symbole via Kurzbefehle.
- project.yml (XcodeGen) + README mit Build-Anleitung. NICHT kompiliert - auf
diesem Rechner ist kein Xcode vorhanden.
Import-Modi (wie besprochen sinnvoll):
- add (Standard, nichts loeschen), replace_listed (Bestaende der in der Datei
genannten Produkte ersetzen - fuer Inventur), replace_all (alles ersetzen).
Geleerte Bestaende werden als Korrektur-Bewegung protokolliert; die Oberflaeche
fragt bei den zerstoerenden Modi nach.
Anzeige:
- "Bald ablaufend"/"Abgelaufen" zeigen jetzt das Gebinde ("1 Glas") mit der
Basiseinheit klein darunter (ExpiringItem liefert die Einheiten mit).
- MHD als Zeitspanne mit korrektem Numerus: "in 3 Tagen", "in 1 Woche",
"vor 2 Wochen", dazu heute/morgen/gestern.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
204
ios/Sources/Models.swift
Normal file
204
ios/Sources/Models.swift
Normal file
@@ -0,0 +1,204 @@
|
||||
import Foundation
|
||||
|
||||
// Entspricht den Schemas des Backends (backend/app/schemas.py).
|
||||
|
||||
struct TokenResponse: Codable {
|
||||
let accessToken: String
|
||||
let role: String
|
||||
let username: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case accessToken = "access_token"
|
||||
case role, username
|
||||
}
|
||||
}
|
||||
|
||||
struct MeResponse: Codable {
|
||||
let id: Int
|
||||
let username: String
|
||||
let role: String
|
||||
|
||||
var isAdmin: Bool { role == "admin" }
|
||||
}
|
||||
|
||||
struct Unit: Codable, Identifiable, Hashable {
|
||||
let id: Int
|
||||
let name: String
|
||||
let kind: String
|
||||
let factor: Double
|
||||
}
|
||||
|
||||
struct BarcodeEntry: Codable, Identifiable, Hashable {
|
||||
let id: Int
|
||||
let code: String
|
||||
let note: String?
|
||||
}
|
||||
|
||||
struct Product: Codable, Identifiable, Hashable {
|
||||
let id: Int
|
||||
let barcode: String?
|
||||
let name: String
|
||||
let brand: String?
|
||||
let imageUrl: String?
|
||||
let baseUnit: String
|
||||
let packageSize: Double?
|
||||
let packageLabel: String?
|
||||
let groupId: Int?
|
||||
let minStock: Double?
|
||||
let stock: Double
|
||||
let expiredCount: Int
|
||||
let kind: String
|
||||
let unitName: String
|
||||
let unitFactor: Double
|
||||
let barcodes: [BarcodeEntry]
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, barcode, name, brand, stock, kind, barcodes
|
||||
case imageUrl = "image_url"
|
||||
case baseUnit = "base_unit"
|
||||
case packageSize = "package_size"
|
||||
case packageLabel = "package_label"
|
||||
case groupId = "group_id"
|
||||
case minStock = "min_stock"
|
||||
case expiredCount = "expired_count"
|
||||
case unitName = "unit_name"
|
||||
case unitFactor = "unit_factor"
|
||||
}
|
||||
|
||||
/// Bezeichnung der Artikeleinheit (Gebinde, sonst Produkteinheit).
|
||||
var articleUnitLabel: String {
|
||||
if let size = packageSize, size > 0 { return packageLabel ?? "Packung" }
|
||||
return unitName
|
||||
}
|
||||
|
||||
/// Faktor, um Basiseinheiten in Artikeleinheiten umzurechnen.
|
||||
var articleUnitFactor: Double {
|
||||
if let size = packageSize, size > 0 { return size }
|
||||
return unitFactor == 0 ? 1 : unitFactor
|
||||
}
|
||||
|
||||
var stockInArticleUnits: Double { stock / articleUnitFactor }
|
||||
}
|
||||
|
||||
struct LookupResult: Codable {
|
||||
let found: Bool
|
||||
let existingProduct: Product?
|
||||
let suggestion: Suggestion?
|
||||
let groupId: Int?
|
||||
let groupName: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case found, suggestion
|
||||
case existingProduct = "existing_product"
|
||||
case groupId = "group_id"
|
||||
case groupName = "group_name"
|
||||
}
|
||||
|
||||
struct Suggestion: Codable {
|
||||
let barcode: String?
|
||||
let name: String
|
||||
let brand: String?
|
||||
let imageUrl: String?
|
||||
let baseUnit: String?
|
||||
let packageSize: Double?
|
||||
let quantityText: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case barcode, name, brand
|
||||
case imageUrl = "image_url"
|
||||
case baseUnit = "base_unit"
|
||||
case packageSize = "package_size"
|
||||
case quantityText = "quantity_text"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Lot: Codable, Identifiable, Hashable {
|
||||
let id: Int
|
||||
let productId: Int
|
||||
let quantity: Double
|
||||
let bestBefore: String?
|
||||
let locationId: Int?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, quantity
|
||||
case productId = "product_id"
|
||||
case bestBefore = "best_before"
|
||||
case locationId = "location_id"
|
||||
}
|
||||
}
|
||||
|
||||
struct StorageLocation: Codable, Identifiable, Hashable {
|
||||
let id: Int
|
||||
let name: String
|
||||
let parentId: Int?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, name
|
||||
case parentId = "parent_id"
|
||||
}
|
||||
}
|
||||
|
||||
struct CheckInLine: Codable {
|
||||
let quantity: Double
|
||||
let bestBefore: String?
|
||||
let locationId: Int?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case quantity
|
||||
case bestBefore = "best_before"
|
||||
case locationId = "location_id"
|
||||
}
|
||||
}
|
||||
|
||||
struct BatchCheckInRequest: Codable {
|
||||
let productId: Int
|
||||
let unit: String
|
||||
let lines: [CheckInLine]
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case unit, lines
|
||||
case productId = "product_id"
|
||||
}
|
||||
}
|
||||
|
||||
struct CheckOutRequest: Codable {
|
||||
let productId: Int
|
||||
let quantity: Double
|
||||
let unit: String
|
||||
let lotId: Int?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case quantity, unit
|
||||
case productId = "product_id"
|
||||
case lotId = "lot_id"
|
||||
}
|
||||
}
|
||||
|
||||
struct StockResponse: Codable {
|
||||
let productStock: Double
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case productStock = "product_stock"
|
||||
}
|
||||
}
|
||||
|
||||
struct NewProductRequest: Codable {
|
||||
let barcode: String?
|
||||
let name: String
|
||||
let brand: String?
|
||||
let imageUrl: String?
|
||||
let baseUnit: String
|
||||
let packageSize: Double?
|
||||
let packageLabel: String?
|
||||
let groupId: Int?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case barcode, name, brand
|
||||
case imageUrl = "image_url"
|
||||
case baseUnit = "base_unit"
|
||||
case packageSize = "package_size"
|
||||
case packageLabel = "package_label"
|
||||
case groupId = "group_id"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user