Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Modules/Sources/Fakes/Networking.generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,8 @@ extension Networking.Booking {
startDate: .fake(),
statusKey: .fake(),
localTimezone: .fake(),
currency: .fake()
currency: .fake(),
orderInfo: .fake()
)
}
}
Expand Down
11 changes: 8 additions & 3 deletions Modules/Sources/Networking/Model/Bookings/Booking.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ public struct Booking: Codable, GeneratedCopiable, Hashable, GeneratedFakeable {
public let statusKey: String
public let localTimezone: String
public let currency: String

// periphery: ignore - to be used later
public let orderInfo: BookingOrderInfo?

public var bookingStatus: BookingStatus {
return BookingStatus(rawValue: statusKey) ?? .unknown
}
Expand All @@ -47,7 +48,8 @@ public struct Booking: Codable, GeneratedCopiable, Hashable, GeneratedFakeable {
startDate: Date,
statusKey: String,
localTimezone: String,
currency: String) {
currency: String,
orderInfo: BookingOrderInfo?) {
self.siteID = siteID
self.bookingID = bookingID
self.allDay = allDay
Expand All @@ -66,6 +68,7 @@ public struct Booking: Codable, GeneratedCopiable, Hashable, GeneratedFakeable {
self.statusKey = statusKey
self.localTimezone = localTimezone
self.currency = currency
self.orderInfo = orderInfo
}

/// The public initializer for Booking.
Expand Down Expand Up @@ -99,6 +102,7 @@ public struct Booking: Codable, GeneratedCopiable, Hashable, GeneratedFakeable {
let statusKey = try container.decode(String.self, forKey: .statusKey)
let localTimezone = try container.decode(String.self, forKey: .localTimezone)
let currency = try container.decode(String.self, forKey: .currency)
let orderInfo: BookingOrderInfo? = nil // to be prefilled when synced

self.init(siteID: siteID,
bookingID: bookingID,
Expand All @@ -117,7 +121,8 @@ public struct Booking: Codable, GeneratedCopiable, Hashable, GeneratedFakeable {
startDate: startDate,
statusKey: statusKey,
localTimezone: localTimezone,
currency: currency)
currency: currency,
orderInfo: orderInfo)
}

public func encode(to encoder: Encoder) throws {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Foundation

public struct BookingCustomerInfo: Hashable {
public let billingAddress: Address

public init(billingAddress: Address) {
self.billingAddress = billingAddress
}
}
19 changes: 19 additions & 0 deletions Modules/Sources/Networking/Model/Bookings/BookingOrderInfo.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// periphery:ignore:all
import Foundation

public struct BookingOrderInfo: Hashable {
public let statusKey: String
public let paymentInfo: BookingPaymentInfo?
public let customerInfo: BookingCustomerInfo?
public let productInfo: BookingProductInfo?

public init(statusKey: String,
paymentInfo: BookingPaymentInfo?,
customerInfo: BookingCustomerInfo?,
productInfo: BookingProductInfo?) {
self.statusKey = statusKey
self.paymentInfo = paymentInfo
self.customerInfo = customerInfo
self.productInfo = productInfo
}
}
24 changes: 24 additions & 0 deletions Modules/Sources/Networking/Model/Bookings/BookingPaymentInfo.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Foundation

public struct BookingPaymentInfo: Hashable {
public let paymentMethodID: String
public let paymentMethodTitle: String
public let subtotal: String
public let subtotalTax: String
public let total: String
public let totalTax: String

public init(paymentMethodID: String,
paymentMethodTitle: String,
subtotal: String,
subtotalTax: String,
total: String,
totalTax: String) {
self.paymentMethodID = paymentMethodID
self.paymentMethodTitle = paymentMethodTitle
self.subtotal = subtotal
self.subtotalTax = subtotalTax
self.total = total
self.totalTax = totalTax
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Foundation

public struct BookingProductInfo: Hashable {
public let name: String

public init(name: String) {
self.name = name
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,8 @@ extension Networking.Booking {
startDate: CopiableProp<Date> = .copy,
statusKey: CopiableProp<String> = .copy,
localTimezone: CopiableProp<String> = .copy,
currency: CopiableProp<String> = .copy
currency: CopiableProp<String> = .copy,
orderInfo: NullableCopiableProp<BookingOrderInfo> = .copy
) -> Networking.Booking {
let siteID = siteID ?? self.siteID
let bookingID = bookingID ?? self.bookingID
Expand All @@ -467,6 +468,7 @@ extension Networking.Booking {
let statusKey = statusKey ?? self.statusKey
let localTimezone = localTimezone ?? self.localTimezone
let currency = currency ?? self.currency
let orderInfo = orderInfo ?? self.orderInfo

return Networking.Booking(
siteID: siteID,
Expand All @@ -486,7 +488,8 @@ extension Networking.Booking {
startDate: startDate,
statusKey: statusKey,
localTimezone: localTimezone,
currency: currency
currency: currency,
orderInfo: orderInfo
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion Modules/Sources/NetworkingCore/Model/Address.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Codegen

/// Represents an Address Entity.
///
public struct Address: Codable, Sendable, GeneratedFakeable, GeneratedCopiable {
public struct Address: Codable, Sendable, GeneratedFakeable, GeneratedCopiable, Hashable {
public let firstName: String
public let lastName: String
public let company: String?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Foundation
import Storage


// MARK: - Storage.Booking: ReadOnlyConvertible
//
extension Storage.Booking: ReadOnlyConvertible {
Expand Down Expand Up @@ -49,6 +48,7 @@ extension Storage.Booking: ReadOnlyConvertible {
startDate: startDate ?? Date(),
statusKey: statusKey ?? "",
localTimezone: localTimezone ?? "",
currency: currency ?? "USD")
currency: currency ?? "USD",
orderInfo: orderInfo?.toReadOnly())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Foundation
import Storage

// MARK: - Storage.BookingCustomerInfo: ReadOnlyConvertible
//
extension Storage.BookingCustomerInfo: ReadOnlyConvertible {
public func update(with customerInfo: Yosemite.BookingCustomerInfo) {
billingAddress1 = customerInfo.billingAddress.address1
billingAddress2 = customerInfo.billingAddress.address2
billingCity = customerInfo.billingAddress.city
billingCompany = customerInfo.billingAddress.company
billingCountry = customerInfo.billingAddress.country
billingEmail = customerInfo.billingAddress.email
billingFirstName = customerInfo.billingAddress.firstName
billingLastName = customerInfo.billingAddress.lastName
billingPhone = customerInfo.billingAddress.phone
billingPostcode = customerInfo.billingAddress.postcode
billingState = customerInfo.billingAddress.state
}

public func toReadOnly() -> Yosemite.BookingCustomerInfo {
let address = Yosemite.Address(firstName: billingFirstName ?? "",
lastName: billingLastName ?? "",
company: billingCompany,
address1: billingAddress1 ?? "",
address2: billingAddress2,
city: billingCity ?? "",
state: billingState ?? "",
postcode: billingPostcode ?? "",
country: billingCountry ?? "",
phone: billingPhone,
email: billingEmail)
return .init(billingAddress: address)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Foundation
import Storage

// MARK: - Storage.BookingOrderInfo: ReadOnlyConvertible
//
extension Storage.BookingOrderInfo: ReadOnlyConvertible {
public func update(with orderInfo: Yosemite.BookingOrderInfo) {
statusKey = orderInfo.statusKey
// Relationships are handled in BookingStore
}

public func toReadOnly() -> Yosemite.BookingOrderInfo {
return .init(statusKey: statusKey ?? "",
paymentInfo: paymentInfo?.toReadOnly(),
customerInfo: customerInfo?.toReadOnly(),
productInfo: productInfo?.toReadOnly())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Foundation
import Storage

// MARK: - Storage.BookingPaymentInfo: ReadOnlyConvertible
//
extension Storage.BookingPaymentInfo: ReadOnlyConvertible {
public func update(with paymentInfo: Yosemite.BookingPaymentInfo) {
paymentMethodID = paymentInfo.paymentMethodID
paymentMethodTitle = paymentInfo.paymentMethodTitle
subtotal = paymentInfo.subtotal
subtotalTax = paymentInfo.subtotalTax
total = paymentInfo.total
totalTax = paymentInfo.totalTax
}

public func toReadOnly() -> Yosemite.BookingPaymentInfo {
return .init(paymentMethodID: paymentMethodID ?? "",
paymentMethodTitle: paymentMethodTitle ?? "",
subtotal: subtotal ?? "",
subtotalTax: subtotalTax ?? "",
total: total ?? "",
totalTax: totalTax ?? "")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Foundation
import Storage

// MARK: - Storage.BookingProductInfo: ReadOnlyConvertible
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just wondering what these MARK notations do at the extensions? Are they used for code generation or something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, just for clarity I believe.

//
extension Storage.BookingProductInfo: ReadOnlyConvertible {
public func update(with productInfo: Yosemite.BookingProductInfo) {
name = productInfo.name
}

public func toReadOnly() -> Yosemite.BookingProductInfo {
return .init(name: name ?? "")
}
}
4 changes: 4 additions & 0 deletions Modules/Sources/Yosemite/Model/Model.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ public typealias BlazeTargetOptions = Networking.BlazeTargetOptions
public typealias BlazeTargetLocation = Networking.BlazeTargetLocation
public typealias BlazeTargetTopic = Networking.BlazeTargetTopic
public typealias Booking = Networking.Booking
public typealias BookingOrderInfo = Networking.BookingOrderInfo
public typealias BookingCustomerInfo = Networking.BookingCustomerInfo
public typealias BookingPaymentInfo = Networking.BookingPaymentInfo
public typealias BookingProductInfo = Networking.BookingProductInfo
public typealias CreateBlazeCampaign = Networking.CreateBlazeCampaign
public typealias FallibleCancelable = Hardware.FallibleCancelable
public typealias CommentStatus = Networking.CommentStatus
Expand Down
36 changes: 30 additions & 6 deletions Modules/Sources/Yosemite/Stores/BookingStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ private extension BookingStore {
/// - readOnlyOrders: Remote Orders associated with bookings.
/// - storage: Where we should save all the things!
///
func upsertStoredBookings(readOnlyBookings: [Networking.Booking], readOnlyOrders: [Yosemite.Order], in storage: StorageType) {
func upsertStoredBookings(readOnlyBookings: [Yosemite.Booking], readOnlyOrders: [Yosemite.Order], in storage: StorageType) {
// Fetch all existing bookings for the site at once
let bookingIDs = readOnlyBookings.map { $0.bookingID }
let siteID = readOnlyBookings.first?.siteID ?? 0
Expand All @@ -268,12 +268,36 @@ private extension BookingStore {
let storageBooking = storedBookings.first { $0.bookingID == readOnlyBooking.bookingID } ??
storage.insertNewObject(ofType: StorageBooking.self)

// TODO: - Apply new Booking specific models
if let associatedOrder = readOnlyOrders.first(where: { $0.orderID == readOnlyBooking.orderID }) {
/// 1. Convert `Order` into `Booking` specific order, product and customer
/// 2. Obtain corresponding associated `Storage` models from `storageBooking` or create new ones.
/// 3. Update the above models with values from `associatedOrder`
print("The order for the booking \(readOnlyBooking.bookingID): \(associatedOrder)")
let orderInfo = storageBooking.orderInfo ?? storage.insertNewObject(ofType: Storage.BookingOrderInfo.self)

let productInfo = orderInfo.productInfo ?? storage.insertNewObject(ofType: Storage.BookingProductInfo.self)
let productName = associatedOrder.items.first(where: { $0.productID == readOnlyBooking.productID })?.name
productInfo.update(with: .init(name: productName ?? ""))
orderInfo.productInfo = productInfo

if let billingAddress = associatedOrder.billingAddress {
let customerInfo = orderInfo.customerInfo ?? storage.insertNewObject(ofType: Storage.BookingCustomerInfo.self)
customerInfo.update(with: .init(billingAddress: billingAddress))
orderInfo.customerInfo = customerInfo
}

let paymentInfo = orderInfo.paymentInfo ?? storage.insertNewObject(ofType: Storage.BookingPaymentInfo.self)
paymentInfo.update(with:
BookingPaymentInfo(
paymentMethodID: associatedOrder.paymentMethodID,
paymentMethodTitle: associatedOrder.paymentMethodTitle,
subtotal: associatedOrder.items.map({ Double($0.subtotal) ?? 0 }).reduce(0, +).description,
subtotalTax: associatedOrder.items.map({ Double($0.subtotalTax) ?? 0 }).reduce(0, +).description,
total: associatedOrder.total,
totalTax: associatedOrder.totalTax
)
)

orderInfo.paymentInfo = paymentInfo

orderInfo.statusKey = associatedOrder.status.rawValue
storageBooking.orderInfo = orderInfo
}

storageBooking.update(with: readOnlyBooking)
Expand Down
Loading