Files
certain/ios/Modelle/Konto.swift
T
ScarriffleandClaude Opus 5 6b86a6bf91 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>
2026-10-20 16:20:03 +02:00

88 lines
3.1 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}
}