iOS: Mindestbestand nur fuer Verbrauchsgegenstand, in echter Einheit

Mindestbestand (global + je Lagerort) nur noch bei Charge-Artikeln: das Feld
verschwindet bei Menge je Lagerort und Einzelstuecken, Alt-Werte werden beim
Speichern geleert. Angezeigt/gespeichert wird in der Anzeigeeinheit
(Milliliter/Gramm/Stueck) statt in Packungen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-28 09:02:10 +02:00
parent 3ff7d2a35a
commit 27f84003f3

View File

@@ -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,13 +173,16 @@ 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)
}
}
if current.foodLike {
Section {
NavigationLink {
ProductLocationMinView(product: current) { await reload() }
@@ -190,6 +194,7 @@ struct ProductDetailView: View {
} footer: {
Text("Bedarf je Lagerort (z.B. Ferienhaus, Zuhause), zusätzlich zum Gesamt-Mindestbestand.")
}
}
Section("Erkennung") {
LabeledContent("Barcode", value: current.barcode ?? "")
@@ -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 {