TM-SGNL-iOS/SignalServiceKit/Subscriptions/Donations/DonationReceipt.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

121 lines
4.1 KiB
Swift

//
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
public import GRDB
public final class DonationReceipt: NSObject, SDSCodableModel, Decodable {
public static var recordType: UInt { 0 }
public enum DonationReceiptType {
case boost
case subscription(subscriptionLevel: UInt)
case gift
}
public enum CodingKeys: String, CodingKey, ColumnExpression, CaseIterable {
case id
case uniqueId
case timestamp
case receiptType
case subscriptionLevel
case currencyCode
case amount
}
public var id: RowId?
public let uniqueId: String
public let receiptType: DonationReceiptType
public let timestamp: Date
public let amount: FiatMoney
public static let databaseTableName = "model_DonationReceipt"
public var localizedName: String {
switch receiptType {
case .boost:
return OWSLocalizedString(
"DONATION_RECEIPT_ONE_TIME",
comment: "Title for one-time donation receipts"
)
case .subscription:
return OWSLocalizedString(
"DONATION_RECEIPT_RECURRING",
comment: "Title for recurring donation receipts"
)
case .gift:
return OWSLocalizedString(
"DONATION_RECEIPT_FOR_DONATION_ON_BEHALF_OF_A_FRIEND",
comment: "Title for receipts for donations given on a friend's behalf"
)
}
}
public init(
receiptType: DonationReceiptType,
timestamp: Date,
amount: FiatMoney
) {
self.uniqueId = UUID().uuidString
self.receiptType = receiptType
self.timestamp = timestamp
self.amount = amount
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeIfPresent(RowId.self, forKey: .id)
uniqueId = try container.decode(String.self, forKey: .uniqueId)
timestamp = try container.decode(Date.self, forKey: .timestamp)
amount = FiatMoney(
currencyCode: try container.decode(Currency.Code.self, forKey: .currencyCode),
value: try container.decode(Decimal.self, forKey: .amount)
)
let subscriptionLevel = try container.decodeIfPresent(UInt.self, forKey: .subscriptionLevel)
let rawReceiptType = try container.decodeIfPresent(UInt.self, forKey: .receiptType)
switch rawReceiptType {
case nil:
Logger.info("Parsing an older donation receipt")
if let subscriptionLevel = subscriptionLevel {
receiptType = .subscription(subscriptionLevel: subscriptionLevel)
} else {
receiptType = .boost
}
case 0:
receiptType = .boost
case 1:
guard let subscriptionLevel = subscriptionLevel else {
owsFail("Found a donation receipt, marked as a subscription, with no subscription level")
}
receiptType = .subscription(subscriptionLevel: subscriptionLevel)
case 2:
receiptType = .gift
default:
owsFail("Found a donation receipt with an unknown receipt type")
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(id, forKey: .id)
try container.encode(uniqueId, forKey: .uniqueId)
try container.encode(timestamp, forKey: .timestamp)
try container.encode(amount.value, forKey: .amount)
try container.encode(amount.currencyCode, forKey: .currencyCode)
switch receiptType {
case .boost:
try container.encode(0, forKey: .receiptType)
case .subscription(let subscriptionLevel):
try container.encode(1, forKey: .receiptType)
try container.encode(subscriptionLevel, forKey: .subscriptionLevel)
case .gift:
try container.encode(2, forKey: .receiptType)
}
}
}