Implement bank transfer app flows
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
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"
|
||||
}
|
||||
Reference in New Issue
Block a user