diff --git a/ios/Sources/ProductDetailView.swift b/ios/Sources/ProductDetailView.swift index b3d0b1b..fd7b9d7 100644 --- a/ios/Sources/ProductDetailView.swift +++ b/ios/Sources/ProductDetailView.swift @@ -61,7 +61,8 @@ struct ProductDetailView: View { if current.isObject { if !current.isIndividual && !current.isBulk, shopId != current.shopId { return true } if !current.isBulk, productUrl != (current.productUrl ?? "") { return true } - if minStock != (current.minStockDisplay.map { formatAmount($0) } ?? "") { return true } + // Mindestbestand gibt es nur beim Verbrauchsgegenstand. + if current.isBulk, minStock != (current.minStockDisplay.map { formatAmount($0) } ?? "") { return true } if fieldValues != Self.stringValues(current.fieldValues) { return true } } return false @@ -172,23 +173,27 @@ struct ProductDetailView: View { } } - if current.isObject { + // Mindestbestand nur bei Verbrauchsgegenständen (Charge) – in der + // Anzeigeeinheit (z.B. Milliliter), nicht in Packungen. Menge je + // Lagerort und Einzelstücke haben keinen Mindestbestand. + if current.isBulk { Section("Mindestbestand") { - QuantityField(label: "Gesamt (\(current.isBulk ? current.articleUnitLabel : "Stück"))", - text: $minStock) + QuantityField(label: "Gesamt (\(current.unitName))", text: $minStock) } } - Section { - NavigationLink { - ProductLocationMinView(product: current) { await reload() } - } label: { - let n = (current.locationMinStocks ?? []).count - Label(n > 0 ? "Mindestbestand je Lagerort (\(n))" : "Mindestbestand je Lagerort", - systemImage: "mappin.and.ellipse") + if current.foodLike { + Section { + NavigationLink { + ProductLocationMinView(product: current) { await reload() } + } label: { + let n = (current.locationMinStocks ?? []).count + Label(n > 0 ? "Mindestbestand je Lagerort (\(n))" : "Mindestbestand je Lagerort", + systemImage: "mappin.and.ellipse") + } + } footer: { + Text("Bedarf je Lagerort (z.B. Ferienhaus, Zuhause), zusätzlich zum Gesamt-Mindestbestand.") } - } footer: { - Text("Bedarf je Lagerort (z.B. Ferienhaus, Zuhause), zusätzlich zum Gesamt-Mindestbestand.") } Section("Erkennung") { @@ -326,8 +331,9 @@ struct ProductDetailView: View { busy = true defer { busy = false } do { + // Mindestbestand in der Anzeigeeinheit erfasst → Basiseinheiten. let minBase = Double(minStock.replacingOccurrences(of: ",", with: ".")) - .map { $0 * current.articleUnitFactor } + .map { $0 * current.unitFactor } if current.foodLike { // Lebensmittel ODER Verbrauchsgegenstand: als Charge mit Einheit/ // Packung/MHD/Gruppe. Verbrauchsgegenstände (isObject) tragen @@ -346,15 +352,16 @@ struct ProductDetailView: View { for def in fieldDefs { fv[String(def.id)] = fieldValues[String(def.id)] ?? "" } req.fieldValues = fv req.minStock = minBase - req.minStockInPackages = (current.packageSize ?? 0) > 0 + req.minStockInPackages = false req.minStockUnitId = nil req.sendMinStock = true } current = try await APIClient.shared.updateProduct(id: current.id, req) if current.isObject { fieldValues = Self.stringValues(current.fieldValues) } } else { - // Gegenstand: Menge je Lagerort oder Einzelstücke. Menge- - // Gegenstände dürfen jetzt ebenfalls in eine Gruppe. + // Gegenstand: Menge je Lagerort oder Einzelstücke. Kein + // Mindestbestand (Alt-Werte werden geleert); Menge-Gegenstände + // 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( @@ -368,8 +375,8 @@ struct ProductDetailView: View { shopId: current.isIndividual ? nil : shopId, productUrl: productUrl.isEmpty ? nil : productUrl, fieldValues: fv, - minStock: minBase, - minStockInPackages: (current.packageSize ?? 0) > 0, + minStock: nil, + minStockInPackages: false, minStockUnitId: nil, sendMinStock: true ) @@ -550,10 +557,16 @@ struct ProductLocationMinView: View { @State private var busy = false @State private var error: String? + // Speicherung in Artikeleinheiten, Anzeige in der Anzeigeeinheit (Gramm/ml/Stück). + private var artToDisp: Double { + let disp = product.unitFactor == 0 ? 1 : product.unitFactor + return product.articleUnitFactor / disp + } + var body: some View { Form { Section { - Text("Bedarf je Lagerort (z.B. Ferienhaus, Zuhause). Menge in \(product.articleUnitLabel).") + Text("Bedarf je Lagerort (z.B. Ferienhaus, Zuhause). Menge in \(product.unitName).") .font(.caption).foregroundStyle(.secondary) } ForEach($rows) { $row in @@ -597,7 +610,7 @@ struct ProductLocationMinView: View { private func load() async { locations = (try? await APIClient.shared.locations()) ?? [] rows = (product.locationMinStocks ?? []).map { - MinRow(locationId: $0.locationId, amount: formatAmount($0.minStock)) + MinRow(locationId: $0.locationId, amount: formatAmount($0.minStock * artToDisp)) } } @@ -611,7 +624,8 @@ struct ProductLocationMinView: View { let wert = Double(row.amount.replacingOccurrences(of: ",", with: ".")) ?? 0 if wert > 0 { gesehen.insert(loc) - list.append(LocationMinStockIn(locationId: loc, minStock: wert)) + // Eingabe in Anzeigeeinheit → Artikeleinheiten (so gespeichert). + list.append(LocationMinStockIn(locationId: loc, minStock: wert / artToDisp)) } } do {