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 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-29 11:33:30 +02:00
parent 2c1efba83d
commit f53d5bd921

View File

@@ -22,6 +22,8 @@ struct ProductDetailView: View {
@State private var datePrecision = "day" @State private var datePrecision = "day"
@State private var groupId: Int? @State private var groupId: Int?
@State private var categoryId: 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 groups: [GroupItem] = []
@State private var categories: [CategoryItem] = [] @State private var categories: [CategoryItem] = []
@@ -61,6 +63,7 @@ struct ProductDetailView: View {
if minStock != minStockFeld { return true } if minStock != minStockFeld { return true }
} }
if current.isObject { if current.isObject {
if objMode != currentObjMode { return true }
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 fieldValues != Self.stringValues(current.fieldValues) { return true } if fieldValues != Self.stringValues(current.fieldValues) { return true }
@@ -129,6 +132,23 @@ struct ProductDetailView: View {
: "Nur Lebensmittel-Kategorien.") : "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 // Bezugsquelle/Link nur für Menge je Lagerort und Einzelstücke
// Verbrauchsgegenstände laufen wie Lebensmittel und lassen das weg. // Verbrauchsgegenstände laufen wie Lebensmittel und lassen das weg.
if current.isObject && !current.isBulk { if current.isObject && !current.isBulk {
@@ -289,6 +309,11 @@ struct ProductDetailView: View {
current.minStock.map { formatAmount($0 / max(current.unitFactor, 1)) } ?? "" 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() { private func fillForm() {
name = current.name name = current.name
brand = current.brand ?? "" brand = current.brand ?? ""
@@ -300,6 +325,7 @@ struct ProductDetailView: View {
shopId = current.shopId shopId = current.shopId
productUrl = current.productUrl ?? "" productUrl = current.productUrl ?? ""
minStock = minStockFeld minStock = minStockFeld
objMode = currentObjMode
fieldValues = Self.stringValues(current.fieldValues) 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 { private func save() async {
error = nil error = nil
status = nil status = nil
@@ -363,6 +397,7 @@ 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
} }
applyModeChange(&req)
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 {
@@ -371,23 +406,22 @@ struct ProductDetailView: View {
// dürfen weiter in eine Gruppe. // 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( var req = ProductUpdateRequest(
id: current.id, name: name,
ProductUpdateRequest( brand: brand.isEmpty ? nil : brand,
name: name, packageSize: nil, packageLabel: nil, datePrecision: nil,
brand: brand.isEmpty ? nil : brand, groupId: current.isIndividual ? nil : groupId, categoryId: categoryId,
packageSize: nil, packageLabel: nil, datePrecision: nil, // Einzelstücke tragen den Shop je Stück nichts ans Modell.
groupId: current.isIndividual ? nil : groupId, categoryId: categoryId, shopId: current.isIndividual ? nil : shopId,
// Einzelstücke tragen den Shop je Stück nichts ans Modell. productUrl: productUrl.isEmpty ? nil : productUrl,
shopId: current.isIndividual ? nil : shopId, fieldValues: fv,
productUrl: productUrl.isEmpty ? nil : productUrl, minStock: nil,
fieldValues: fv, minStockInPackages: false,
minStock: nil, minStockUnitId: nil,
minStockInPackages: false, sendMinStock: true
minStockUnitId: nil,
sendMinStock: true
)
) )
applyModeChange(&req)
current = try await APIClient.shared.updateProduct(id: current.id, req)
fieldValues = Self.stringValues(current.fieldValues) fieldValues = Self.stringValues(current.fieldValues)
} }
status = "Gespeichert." status = "Gespeichert."