Files
ccn/Packages/Persistence/Sources/Public/Models/Offer.swift
T

87 lines
2.3 KiB
Swift
Raw Normal View History

import Foundation
/// A `Sendable` snapshot of a buyer's offer on a listing.
public struct Offer: Sendable, Equatable {
// MARK: Constants
/// The share of the asking price under which an offer is declined outright.
public static let floorShare = 0.8
/// How long an offer binds its buyer: 48 hours.
public static let lifetime: TimeInterval = 172_800
// MARK: Properties
/// The offer's identifier.
public let id: UUID
/// The identifier of the conversation the offer was made in.
public let conversationID: UUID
/// The listing offered on.
public let listing: Listing
/// The account offering.
public let buyer: User
/// The amount offered, in euro cents.
public let amountCents: Int
/// Where the offer stands; an open offer past its expiry reads as expired.
public let status: Status
/// When the offer was made.
public let createdAt: Date
/// When the offer stops binding its buyer.
public let expiresAt: Date
// MARK: Initializers
public init(
id: UUID,
conversationID: UUID,
listing: Listing,
buyer: User,
amountCents: Int,
status: Status,
createdAt: Date,
expiresAt: Date
) {
self.id = id
self.conversationID = conversationID
self.listing = listing
self.buyer = buyer
self.amountCents = amountCents
self.status = status
self.createdAt = createdAt
self.expiresAt = expiresAt
}
}
// MARK: - Enumerations
public extension Offer {
/// Where an offer stands.
enum Status: String, Sendable {
/// Waiting for the seller's answer.
case open
/// Accepted: a sale record was opened.
case accepted
/// Declined by the seller.
case declined
/// Left unanswered past its expiry, or overtaken by a sale of the listing.
case expired
}
}
// MARK: - Extensions
public extension Offer {
// MARK: Methods
/// The lowest offer a listing's seller hears, in euro cents: ``floorShare`` of the asking price, rounded up to a whole euro.
/// - Parameter askingCents: the listing's asking price, in euro cents.
static func floor(
forAsking askingCents: Int
) -> Int {
Int((Double(askingCents) * floorShare / 100).rounded(.up)) * 100
}
}