iOS: Mindestbestand je Lagerort (Produkte) + Einkaufsliste je Ort

- Produkt-Detail: neuer Editor „Mindestbestand je Lagerort" (Zeilen: Lagerort +
  Menge in Artikeleinheiten), zusaetzlich zum Gesamt-Mindestbestand.
- Einkaufsliste: Abschnitte „Bedarf: <Lagerort>" mit Produkten und Gruppen, die
  am Ort unter dem dort hinterlegten Mindestbestand liegen.
- Models/Client: LocationMinStock(+In), LocationNeeds*, setProductLocationMinStock,
  shoppingByLocation; Product um location_min_stocks erweitert.
(Gruppen-Bedarf je Ort ist vorerst nur im Web pflegbar, wird aber in der iOS-
 Einkaufsliste mit angezeigt.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-27 07:23:12 +02:00
parent dff7677e50
commit 5d3ae185ce
6 changed files with 247 additions and 1 deletions

View File

@@ -76,9 +76,12 @@ struct Product: Codable, Identifiable, Hashable {
let fieldValues: [String: String?]?
/// Gegenstand als Einzelstücke (Items mit UID/QR) statt als Menge geführt.
let individual: Bool?
/// Mindestbestand je Lagerort (zusaetzlich zum globalen Mindestbestand).
let locationMinStocks: [LocationMinStock]?
enum CodingKeys: String, CodingKey {
case id, barcode, name, brand, stock, kind, barcodes, tracking, individual
case locationMinStocks = "location_min_stocks"
case datePrecision = "date_precision"
case categoryId = "category_id"
case categoryName = "category_name"
@@ -129,6 +132,31 @@ struct Product: Codable, Identifiable, Hashable {
}
}
/// Mindestbestand eines Produkts/einer Gruppe an einem Lagerort (Anzeige).
struct LocationMinStock: Codable, Hashable, Identifiable {
let locationId: Int
let locationName: String?
let minStock: Double
var id: Int { locationId }
enum CodingKeys: String, CodingKey {
case minStock = "min_stock"
case locationId = "location_id"
case locationName = "location_name"
}
}
/// Ein Mindestbestand-Eintrag zum Speichern (Menge in Artikeleinheiten).
struct LocationMinStockIn: Codable {
let locationId: Int
let minStock: Double
enum CodingKeys: String, CodingKey {
case minStock = "min_stock"
case locationId = "location_id"
}
}
/// Auswahleintrag fuer Einheiten.
///
/// Anzeige und uebertragener Wert sind bewusst getrennt: Das Backend kennt
@@ -324,6 +352,59 @@ struct GroupShoppingItem: Codable, Identifiable {
}
}
// MARK: - Bedarfe je Lagerort
struct LocationNeedProduct: Codable, Identifiable {
let productId: Int
let name: String
let unitLabel: String
let stock: Double
let minStock: Double
let deficit: Double
var id: Int { productId }
enum CodingKeys: String, CodingKey {
case name, stock, deficit
case productId = "product_id"
case unitLabel = "unit_label"
case minStock = "min_stock"
}
}
struct LocationNeedGroup: Codable, Identifiable {
let groupId: Int
let name: String
let unitName: String
let stock: Double
let minStock: Double
let deficit: Double
var id: Int { groupId }
enum CodingKeys: String, CodingKey {
case name, stock, deficit
case groupId = "group_id"
case unitName = "unit_name"
case minStock = "min_stock"
}
}
struct LocationNeeds: Codable, Identifiable {
let locationId: Int
let locationName: String
let products: [LocationNeedProduct]
let groups: [LocationNeedGroup]
var id: Int { locationId }
enum CodingKeys: String, CodingKey {
case products, groups
case locationId = "location_id"
case locationName = "location_name"
}
}
struct ExpiringItem: Codable, Identifiable {
let lotId: Int
let productId: Int