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:
@@ -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."
|
||||||
|
|||||||
Reference in New Issue
Block a user