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.isObject {
if !current.isIndividual && !current.isBulk, shopId != current.shopId { return true } if !current.isIndividual && !current.isBulk, shopId != current.shopId { return true }
if !current.isBulk, productUrl != (current.productUrl ?? "") { 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 } if fieldValues != Self.stringValues(current.fieldValues) { return true }
} }
return false 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") { Section("Mindestbestand") {
QuantityField(label: "Gesamt (\(current.isBulk ? current.articleUnitLabel : "Stück"))", QuantityField(label: "Gesamt (\(current.unitName))", text: $minStock)
text: $minStock)
} }
} }
if current.foodLike {
Section { Section {
NavigationLink { NavigationLink {
ProductLocationMinView(product: current) { await reload() } ProductLocationMinView(product: current) { await reload() }
@@ -190,6 +194,7 @@ struct ProductDetailView: View {
} footer: { } footer: {
Text("Bedarf je Lagerort (z.B. Ferienhaus, Zuhause), zusätzlich zum Gesamt-Mindestbestand.") Text("Bedarf je Lagerort (z.B. Ferienhaus, Zuhause), zusätzlich zum Gesamt-Mindestbestand.")
} }
}
Section("Erkennung") { Section("Erkennung") {
LabeledContent("Barcode", value: current.barcode ?? "") LabeledContent("Barcode", value: current.barcode ?? "")
@@ -326,8 +331,9 @@ struct ProductDetailView: View {
busy = true busy = true
defer { busy = false } defer { busy = false }
do { do {
// Mindestbestand in der Anzeigeeinheit erfasst Basiseinheiten.
let minBase = Double(minStock.replacingOccurrences(of: ",", with: ".")) let minBase = Double(minStock.replacingOccurrences(of: ",", with: "."))
.map { $0 * current.articleUnitFactor } .map { $0 * current.unitFactor }
if current.foodLike { if current.foodLike {
// Lebensmittel ODER Verbrauchsgegenstand: als Charge mit Einheit/ // Lebensmittel ODER Verbrauchsgegenstand: als Charge mit Einheit/
// Packung/MHD/Gruppe. Verbrauchsgegenstände (isObject) tragen // 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)] ?? "" } for def in fieldDefs { fv[String(def.id)] = fieldValues[String(def.id)] ?? "" }
req.fieldValues = fv req.fieldValues = fv
req.minStock = minBase req.minStock = minBase
req.minStockInPackages = (current.packageSize ?? 0) > 0 req.minStockInPackages = false
req.minStockUnitId = nil req.minStockUnitId = nil
req.sendMinStock = true req.sendMinStock = true
} }
current = try await APIClient.shared.updateProduct(id: current.id, req) current = try await APIClient.shared.updateProduct(id: current.id, req)
if current.isObject { fieldValues = Self.stringValues(current.fieldValues) } if current.isObject { fieldValues = Self.stringValues(current.fieldValues) }
} else { } else {
// Gegenstand: Menge je Lagerort oder Einzelstücke. Menge- // Gegenstand: Menge je Lagerort oder Einzelstücke. Kein
// Gegenstände dürfen jetzt ebenfalls in eine Gruppe. // Mindestbestand (Alt-Werte werden geleert); Menge-Gegenstände
// dürfen weiter in eine Gruppe.
var fv: [String: String?] = [:] var fv: [String: String?] = [:]
for def in fieldDefs { fv[String(def.id)] = fieldValues[String(def.id)] ?? "" } for def in fieldDefs { fv[String(def.id)] = fieldValues[String(def.id)] ?? "" }
current = try await APIClient.shared.updateProduct( current = try await APIClient.shared.updateProduct(
@@ -368,8 +375,8 @@ struct ProductDetailView: View {
shopId: current.isIndividual ? nil : shopId, shopId: current.isIndividual ? nil : shopId,
productUrl: productUrl.isEmpty ? nil : productUrl, productUrl: productUrl.isEmpty ? nil : productUrl,
fieldValues: fv, fieldValues: fv,
minStock: minBase, minStock: nil,
minStockInPackages: (current.packageSize ?? 0) > 0, minStockInPackages: false,
minStockUnitId: nil, minStockUnitId: nil,
sendMinStock: true sendMinStock: true
) )
@@ -550,10 +557,16 @@ struct ProductLocationMinView: View {
@State private var busy = false @State private var busy = false
@State private var error: String? @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 { var body: some View {
Form { Form {
Section { 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) .font(.caption).foregroundStyle(.secondary)
} }
ForEach($rows) { $row in ForEach($rows) { $row in
@@ -597,7 +610,7 @@ struct ProductLocationMinView: View {
private func load() async { private func load() async {
locations = (try? await APIClient.shared.locations()) ?? [] locations = (try? await APIClient.shared.locations()) ?? []
rows = (product.locationMinStocks ?? []).map { 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 let wert = Double(row.amount.replacingOccurrences(of: ",", with: ".")) ?? 0
if wert > 0 { if wert > 0 {
gesehen.insert(loc) 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 { do {