From f53d5bd9216c450d7e6bf9ba23cead1fc2cbb660 Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Wed, 29 Jul 2026 11:33:30 +0200 Subject: [PATCH] iOS: Verwaltungsart eines Gegenstands aendern (Menge/Einzelstueck/Verbrauch) Neue "Verwaltung"-Auswahl in der Detailansicht: Menge je Lagerort <-> Einzelstuecke <-> Verbrauchsgegenstand umstellbar. Wird beim Speichern per sendMode uebertragen (individual/bulk); vorhandener Bestand wird nicht automatisch umgerechnet (Hinweis im Footer). Co-Authored-By: Claude Opus 4.8 --- ios/Sources/ProductDetailView.swift | 66 ++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/ios/Sources/ProductDetailView.swift b/ios/Sources/ProductDetailView.swift index 1d861c0..5b96c69 100644 --- a/ios/Sources/ProductDetailView.swift +++ b/ios/Sources/ProductDetailView.swift @@ -22,6 +22,8 @@ struct ProductDetailView: View { @State private var datePrecision = "day" @State private var groupId: Int? @State private var categoryId: Int? + // Verwaltungsart eines Gegenstands: count | individual | bulk – umstellbar. + @State private var objMode = "count" @State private var groups: [GroupItem] = [] @State private var categories: [CategoryItem] = [] @@ -61,6 +63,7 @@ struct ProductDetailView: View { if minStock != minStockFeld { return true } } if current.isObject { + if objMode != currentObjMode { return true } if !current.isIndividual && !current.isBulk, shopId != current.shopId { return true } if !current.isBulk, productUrl != (current.productUrl ?? "") { return true } if fieldValues != Self.stringValues(current.fieldValues) { return true } @@ -129,6 +132,23 @@ struct ProductDetailView: View { : "Nur Lebensmittel-Kategorien.") } + // Verwaltungsart eines Gegenstands umstellen (z.B. Menge je Lagerort → + // Einzelstücke). Wirkt nach dem Speichern; der Bestand wird nicht + // automatisch umgerechnet. + if current.isObject { + Section { + Picker("Verwaltung", selection: $objMode) { + Text("Menge je Lagerort").tag("count") + Text("Einzelstücke").tag("individual") + Text("Verbrauchsgegenstand").tag("bulk") + } + } footer: { + Text(objMode == currentObjMode + ? "Wie der Bestand geführt wird." + : "Wird beim Speichern umgestellt – vorhandener Bestand wird nicht umgerechnet.") + } + } + // Bezugsquelle/Link nur für Menge je Lagerort und Einzelstücke – // Verbrauchsgegenstände laufen wie Lebensmittel und lassen das weg. if current.isObject && !current.isBulk { @@ -289,6 +309,11 @@ struct ProductDetailView: View { current.minStock.map { formatAmount($0 / max(current.unitFactor, 1)) } ?? "" } + /// Aktuelle Verwaltungsart des geladenen Artikels. + private var currentObjMode: String { + current.isIndividual ? "individual" : (current.isBulk ? "bulk" : "count") + } + private func fillForm() { name = current.name brand = current.brand ?? "" @@ -300,6 +325,7 @@ struct ProductDetailView: View { shopId = current.shopId productUrl = current.productUrl ?? "" minStock = minStockFeld + objMode = currentObjMode fieldValues = Self.stringValues(current.fieldValues) } @@ -331,6 +357,14 @@ struct ProductDetailView: View { } } + /// Verwaltungsart (individual/bulk) mitschicken, wenn sie umgestellt wurde. + private func applyModeChange(_ req: inout ProductUpdateRequest) { + guard current.isObject, objMode != currentObjMode else { return } + req.individual = objMode == "individual" + req.bulk = objMode == "bulk" + req.sendMode = true + } + private func save() async { error = nil status = nil @@ -363,6 +397,7 @@ struct ProductDetailView: View { for def in fieldDefs { fv[String(def.id)] = fieldValues[String(def.id)] ?? "" } req.fieldValues = fv } + applyModeChange(&req) current = try await APIClient.shared.updateProduct(id: current.id, req) if current.isObject { fieldValues = Self.stringValues(current.fieldValues) } } else { @@ -371,23 +406,22 @@ struct ProductDetailView: View { // dürfen weiter in eine Gruppe. var fv: [String: String?] = [:] for def in fieldDefs { fv[String(def.id)] = fieldValues[String(def.id)] ?? "" } - current = try await APIClient.shared.updateProduct( - id: current.id, - ProductUpdateRequest( - name: name, - brand: brand.isEmpty ? nil : brand, - packageSize: nil, packageLabel: nil, datePrecision: nil, - groupId: current.isIndividual ? nil : groupId, categoryId: categoryId, - // Einzelstücke tragen den Shop je Stück – nichts ans Modell. - shopId: current.isIndividual ? nil : shopId, - productUrl: productUrl.isEmpty ? nil : productUrl, - fieldValues: fv, - minStock: nil, - minStockInPackages: false, - minStockUnitId: nil, - sendMinStock: true - ) + var req = ProductUpdateRequest( + name: name, + brand: brand.isEmpty ? nil : brand, + packageSize: nil, packageLabel: nil, datePrecision: nil, + groupId: current.isIndividual ? nil : groupId, categoryId: categoryId, + // Einzelstücke tragen den Shop je Stück – nichts ans Modell. + shopId: current.isIndividual ? nil : shopId, + productUrl: productUrl.isEmpty ? nil : productUrl, + fieldValues: fv, + minStock: nil, + minStockInPackages: false, + minStockUnitId: nil, + sendMinStock: true ) + applyModeChange(&req) + current = try await APIClient.shared.updateProduct(id: current.id, req) fieldValues = Self.stringValues(current.fieldValues) } status = "Gespeichert."