App: Einzelstuecke verleihen - alle Scan-Wege enden schon dort
Verleih-Abschnitt im Einzelstueck: an wen, seit wann, bis wann, dazu Herausgeben bzw. Zuruecknehmen und der Verleih-Verlauf. Pflicht ist nur der Name; Grund und Rueckgabedatum sind abschaltbar, weil "kurz mal mitgenommen" nicht an einem Datum scheitern soll. Der Abschnitt sitzt bewusst oben in ItemEditView, und zwar nicht nur der Wichtigkeit wegen: QR ueber Nachschlagen, eingenaehtes NFC-Tag und ein angetipptes Tag (vorrania://i/<UID>) landen alle in genau dieser Ansicht. Damit ist "scannen und verleihen" ueberall moeglich, ohne einen eigenen Weg dafuer zu bauen. In der Einzelstueck-Liste steht der Verleih unter dem Stueck - ueberfaellig in Rot - und das Filter-Menue kann auf Verliehen, Ueberfaellig oder Im Haus eingrenzen. Wo etwas ist, war bisher immer der Lagerort; ist es verliehen, ist der Entleiher die Antwort, und der Lagerort steht daneben. days_overdue rechnet der Server (GET /loans, ItemOut.loan), damit App und Web nicht getrennt rechnen und nicht auseinanderlaufen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1332dd86fa
commit
aa72d8342a
@@ -1046,6 +1046,68 @@ struct ItemDocument: Codable, Identifiable, Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
/// Ein Verleih-Vorgang eines Einzelstuecks. `returnedOn == nil` heisst „noch
|
||||
/// draussen"; je Stueck gibt es hoechstens einen solchen offenen Verleih.
|
||||
///
|
||||
/// `daysOverdue` rechnet der Server, damit App und Web nicht getrennt rechnen -
|
||||
/// nil heisst: ohne Frist, zurueck, oder noch nicht faellig.
|
||||
struct Loan: Codable, Identifiable, Hashable {
|
||||
let id: Int
|
||||
let itemId: Int
|
||||
let borrower: String
|
||||
let reason: String?
|
||||
let lentOn: String // "yyyy-MM-dd"
|
||||
let dueOn: String?
|
||||
let returnedOn: String?
|
||||
let createdAt: String
|
||||
let username: String?
|
||||
let daysOverdue: Int?
|
||||
let itemUid: String?
|
||||
let productId: Int?
|
||||
let productName: String?
|
||||
let productBrand: String?
|
||||
let locationId: String?
|
||||
let locationName: String?
|
||||
|
||||
var istOffen: Bool { returnedOn == nil }
|
||||
var istUeberfaellig: Bool { (daysOverdue ?? 0) > 0 }
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, borrower, reason, username
|
||||
case itemId = "item_id"
|
||||
case lentOn = "lent_on"
|
||||
case dueOn = "due_on"
|
||||
case returnedOn = "returned_on"
|
||||
case createdAt = "created_at"
|
||||
case daysOverdue = "days_overdue"
|
||||
case itemUid = "item_uid"
|
||||
case productId = "product_id"
|
||||
case productName = "product_name"
|
||||
case productBrand = "product_brand"
|
||||
case locationId = "location_id"
|
||||
case locationName = "location_name"
|
||||
}
|
||||
}
|
||||
|
||||
struct LoanCreateRequest: Encodable {
|
||||
let borrower: String
|
||||
var reason: String? = nil
|
||||
var lentOn: String? = nil
|
||||
var dueOn: String? = nil
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case borrower, reason
|
||||
case lentOn = "lent_on"
|
||||
case dueOn = "due_on"
|
||||
}
|
||||
}
|
||||
|
||||
struct LoanReturnRequest: Encodable {
|
||||
var returnedOn: String? = nil
|
||||
|
||||
enum CodingKeys: String, CodingKey { case returnedOn = "returned_on" }
|
||||
}
|
||||
|
||||
struct Item: Codable, Identifiable, Hashable {
|
||||
let id: Int
|
||||
let uid: String
|
||||
@@ -1065,9 +1127,14 @@ struct Item: Codable, Identifiable, Hashable {
|
||||
let categoryId: Int?
|
||||
let categoryName: String?
|
||||
let documents: [ItemDocument]
|
||||
/// Der offene Verleih, falls das Stueck gerade draussen ist - sonst nil.
|
||||
/// Der Lagerort steht daneben unveraendert: dorthin gehoert es zurueck.
|
||||
let loan: Loan?
|
||||
|
||||
var istVerliehen: Bool { loan != nil }
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, uid, note, currency, documents
|
||||
case id, uid, note, currency, documents, loan
|
||||
case productId = "product_id"
|
||||
case locationId = "location_id"
|
||||
case locationName = "location_name"
|
||||
|
||||
Reference in New Issue
Block a user