Files
Vorrania/ios/Sources/Models.swift
Scarriffle 4bb9a10366 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>
2026-07-22 14:59:04 +02:00

205 lines
4.9 KiB
Swift

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"
}
}