feat: Erste Stufe der iOS-App - Anmeldung und Kontenliste
Neuer Ordner ios/ mit dem Geruest: Netzwerkschicht, Modelle, Offline-Ablage, Texte in Deutsch und Englisch, Navigation, der komplette Anmeldeweg (Server waehlen, anmelden, zweiter Faktor, Pflicht-Passwortwechsel) und als erste Fachansicht die Kontenliste. Die Anmeldung laeuft einmal ueber das Sitzungs-Cookie, holt sich dabei eine App-Marke und legt sie in den Schluesselbund. Danach traegt nur noch der Header. Kein Passwort auf dem Geraet, kein Ablauf nach 30 Tagen. Der Code ist nie uebersetzt worden - hier gibt es kein Xcode. Geprueft ist dafuer jedes Modellfeld gegen echte Antworten des laufenden Backends; dabei kam heraus, dass created_at ohne Zeitzone und mit Mikrosekunden kommt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8a7545bf5b
commit
6b86a6bf91
@@ -0,0 +1,87 @@
|
||||
import Foundation
|
||||
|
||||
/// `AccountOut` aus `backend/app/schemas.py`.
|
||||
struct Konto: Codable, Sendable, Identifiable, Hashable {
|
||||
let id: Int
|
||||
let name: String
|
||||
let type: Kontoart
|
||||
let currency: String
|
||||
let icon: String
|
||||
let color: String
|
||||
let openingBalanceCents: Int
|
||||
let openingDate: Tagesdatum?
|
||||
let creditLimitCents: Int?
|
||||
let isLocked: Bool
|
||||
let isArchived: Bool
|
||||
let position: Int
|
||||
let savingsCategoryId: Int?
|
||||
let identifiers: [Kontokennung]
|
||||
/// Saldo in der Währung des Kontos.
|
||||
let balanceCents: Int
|
||||
/// Derselbe Saldo in der Hauptwährung – vom Server gerechnet.
|
||||
let balanceBaseCents: Int
|
||||
/// Was die Bank selbst meldet. Nur bei angebundenen Konten gesetzt.
|
||||
let bankBalanceCents: Int?
|
||||
let bankBalanceAt: Zeitpunkt?
|
||||
/// Nur ein gebuchter Banksaldo lässt sich mit unserer Rechnung
|
||||
/// vergleichen; ein verfügbarer enthält Vorgemerktes.
|
||||
let bankBalanceVergleichbar: Bool
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id, name, type, currency, icon, color, position, identifiers
|
||||
case openingBalanceCents = "opening_balance_cents"
|
||||
case openingDate = "opening_date"
|
||||
case creditLimitCents = "credit_limit_cents"
|
||||
case isLocked = "is_locked"
|
||||
case isArchived = "is_archived"
|
||||
case savingsCategoryId = "savings_category_id"
|
||||
case balanceCents = "balance_cents"
|
||||
case balanceBaseCents = "balance_base_cents"
|
||||
case bankBalanceCents = "bank_balance_cents"
|
||||
case bankBalanceAt = "bank_balance_at"
|
||||
case bankBalanceVergleichbar = "bank_balance_vergleichbar"
|
||||
}
|
||||
|
||||
var saldo: Geldbetrag { Geldbetrag(cents: balanceCents, waehrung: currency) }
|
||||
|
||||
/// Ob der gemeldete Banksaldo von unserer Rechnung abweicht – nur dann ist
|
||||
/// ein Hinweis angebracht.
|
||||
var weichtVonDerBankAb: Bool {
|
||||
guard bankBalanceVergleichbar, let bank = bankBalanceCents else { return false }
|
||||
return bank != balanceCents
|
||||
}
|
||||
}
|
||||
|
||||
/// `AccountType`
|
||||
enum Kontoart: String, Codable, Sendable, CaseIterable {
|
||||
case girokonto, sparkonto, bargeld, kreditkarte, depot, sonstiges
|
||||
|
||||
var name: String {
|
||||
switch self {
|
||||
case .girokonto: return String(localized: "kontoart.girokonto")
|
||||
case .sparkonto: return String(localized: "kontoart.sparkonto")
|
||||
case .bargeld: return String(localized: "kontoart.bargeld")
|
||||
case .kreditkarte: return String(localized: "kontoart.kreditkarte")
|
||||
case .depot: return String(localized: "kontoart.depot")
|
||||
case .sonstiges: return String(localized: "kontoart.sonstiges")
|
||||
}
|
||||
}
|
||||
|
||||
/// Ein Übertrag auf diese Konten zählt im Budget als Sparen, nicht als
|
||||
/// neutrale Umbuchung (`SAVINGS_ACCOUNT_TYPES` im Backend).
|
||||
var giltAlsSparen: Bool { self == .sparkonto || self == .depot }
|
||||
}
|
||||
|
||||
/// `AccountIdentifierOut`
|
||||
struct Kontokennung: Codable, Sendable, Identifiable, Hashable {
|
||||
let id: Int
|
||||
let kind: Art
|
||||
let value: String
|
||||
|
||||
enum Art: String, Codable, Sendable {
|
||||
case iban
|
||||
case accountNo = "account_no"
|
||||
case cardNo = "card_no"
|
||||
case text
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user