152 lines
4.4 KiB
Swift
152 lines
4.4 KiB
Swift
import Foundation
|
|
|
|
// MARK: - Unified bank data models
|
|
// These aggregate MIB, BML, and Fahipay responses into a common schema.
|
|
// All types are Codable for cache serialisation and Hashable for use in SwiftUI ForEach.
|
|
|
|
struct BankAccount: Identifiable, Codable, Hashable {
|
|
let id: String // Synthetic: "\(bank)_\(accountNumber)_\(loginTag)"
|
|
let bank: String // "MIB" | "BML" | "FAHIPAY"
|
|
let profileName: String
|
|
let profileType: String
|
|
let productCode: String
|
|
let accountNumber: String
|
|
let accountBriefName: String
|
|
let currencyName: String // "MVR" | "USD" | ...
|
|
let accountTypeName: String
|
|
let availableBalance: Double
|
|
let currentBalance: Double
|
|
let blockedAmount: Double
|
|
let mvrBalance: Double? // Converted balance when currency != MVR
|
|
let statusDesc: String
|
|
let profileImageHash: String?
|
|
let loginTag: String // loginId that owns this account
|
|
let profileId: String?
|
|
let internalId: String?
|
|
|
|
var isActive: Bool {
|
|
statusDesc.lowercased().contains("active")
|
|
}
|
|
|
|
var formattedAvailableBalance: String {
|
|
"\(currencyName) \(Self.balanceFormatter.string(from: NSNumber(value: availableBalance)) ?? "0.00")"
|
|
}
|
|
|
|
private static let balanceFormatter: NumberFormatter = {
|
|
let f = NumberFormatter()
|
|
f.numberStyle = .decimal
|
|
f.minimumFractionDigits = 2
|
|
f.maximumFractionDigits = 2
|
|
return f
|
|
}()
|
|
}
|
|
|
|
struct BankContact: Identifiable, Codable, Hashable {
|
|
let id: String // Unique composite across banks
|
|
let benefNo: String
|
|
let benefName: String
|
|
let benefNickName: String?
|
|
let benefAccount: String
|
|
let benefType: String // "MIB" | "LOCAL" | "SWIFT" | "BML" | "FAHIPAY"
|
|
let bankColor: String?
|
|
let benefBankName: String?
|
|
let bankCode: String?
|
|
let benefStatus: String
|
|
let transferCyDesc: String?
|
|
let customerImgHash: String?
|
|
let benefCategoryId: String?
|
|
let profileId: String?
|
|
let source: String // "MIB" | "BML" | "FAHIPAY"
|
|
|
|
var displayName: String {
|
|
if let nick = benefNickName, !nick.isEmpty { return nick }
|
|
return benefName
|
|
}
|
|
}
|
|
|
|
struct BankTransaction: Identifiable, Codable, Hashable {
|
|
let id: String
|
|
let date: Date
|
|
let description: String
|
|
let amount: Double // Positive = credit, negative = debit
|
|
let currency: String
|
|
let counterpartyName: String?
|
|
let reference: String?
|
|
let accountNumber: String
|
|
let accountDisplayName: String
|
|
let source: String // "MIB" | "BML" | "BML_CARD" | "FAHIPAY"
|
|
let iconUrl: String?
|
|
|
|
var isCredit: Bool { amount >= 0 }
|
|
|
|
var formattedAmount: String {
|
|
let sign = isCredit ? "+" : "-"
|
|
let abs = Self.amountFormatter.string(from: NSNumber(value: Swift.abs(amount))) ?? "0.00"
|
|
return "\(sign) \(currency) \(abs)"
|
|
}
|
|
|
|
private static let amountFormatter: NumberFormatter = {
|
|
let f = NumberFormatter()
|
|
f.numberStyle = .decimal
|
|
f.minimumFractionDigits = 2
|
|
f.maximumFractionDigits = 2
|
|
return f
|
|
}()
|
|
}
|
|
|
|
struct BankContactCategory: Identifiable, Codable, Hashable {
|
|
let id: String
|
|
let categoryName: String
|
|
let numBenef: Int
|
|
let source: String // "MIB" | "FAHIPAY"
|
|
}
|
|
|
|
struct BankNotification: Identifiable, Codable, Hashable {
|
|
let id: String
|
|
let title: String
|
|
let body: String
|
|
let date: Date
|
|
var isRead: Bool
|
|
let source: String
|
|
}
|
|
|
|
// MARK: - Transfer
|
|
|
|
struct TransferResult: Codable {
|
|
let success: Bool
|
|
let transactionId: String?
|
|
let reference: String?
|
|
let date: Date?
|
|
let errorMessage: String?
|
|
}
|
|
|
|
struct TransferReceiptData: Sendable, Equatable {
|
|
let fromAccountNumber: String
|
|
let fromBankName: String
|
|
let toAccountNumber: String
|
|
let toAccountName: String
|
|
let amount: Double
|
|
let currency: String
|
|
let reference: String
|
|
let date: String
|
|
let message: String
|
|
}
|
|
|
|
struct RecentPick: Identifiable, Codable, Hashable {
|
|
let id: String
|
|
let benefName: String
|
|
let benefAccount: String
|
|
let transferNetwork: String // TransferNetwork.rawValue
|
|
let bankName: String?
|
|
let lastUsed: Date
|
|
}
|
|
|
|
// MARK: - Connectivity
|
|
|
|
enum ConnectivityError: String, CaseIterable, Codable {
|
|
case noInternet = "NO_INTERNET"
|
|
case mib = "MIB"
|
|
case bml = "BML"
|
|
case fahipay = "FAHIPAY"
|
|
}
|