Skip to content

Commit 5efa028

Browse files
committed
Merge branch 'trunk' into WOOMOB-1236-booking-details-part-8
# Conflicts: # WooCommerce/Classes/ViewModels/Booking Details/AppointmentDetailsContent.swift # WooCommerce/Classes/ViewModels/Booking Details/BookingDetailsViewModel.swift # WooCommerce/Classes/ViewModels/Booking Details/CustomerContent.swift # WooCommerce/Classes/ViewModels/Booking Details/HeaderContent.swift # WooCommerce/Classes/ViewModels/Booking Details/PaymentContent.swift
2 parents fbe50e9 + c85bad1 commit 5efa028

File tree

78 files changed

+4698
-13790
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+4698
-13790
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<!--
22
Contains editorialized release notes. Raw release notes should go into `RELEASE-NOTES.txt`.
33
-->
4+
## 23.5
5+
This update brings smoother store management and better control. You can now filter orders by source, and manage all POS orders directly within the POS interface. Plus, we fixed a scrolling issue on the Create Coupon screen for a more seamless experience.
6+
47
## 23.4
58
This update delivers important fixes for a smoother store management experience. We've resolved navigation issues in order details and corrected store widget display on iOS 26. Update now for a more polished and reliable app experience.
69

Modules/Sources/Fakes/Networking.generated.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,24 @@ extension Networking.Booking {
344344
)
345345
}
346346
}
347+
extension Networking.BookingResource {
348+
/// Returns a "ready to use" type filled with fake values.
349+
///
350+
public static func fake() -> Networking.BookingResource {
351+
.init(
352+
siteID: .fake(),
353+
resourceID: .fake(),
354+
name: .fake(),
355+
quantity: .fake(),
356+
role: .fake(),
357+
email: .fake(),
358+
phoneNumber: .fake(),
359+
imageID: .fake(),
360+
imageURL: .fake(),
361+
description: .fake()
362+
)
363+
}
364+
}
347365
extension Networking.CompositeComponentOptionType {
348366
/// Returns a "ready to use" type filled with fake values.
349367
///
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import Foundation
2+
3+
/// Mapper: BookingResource
4+
///
5+
struct BookingResourceMapper: Mapper {
6+
let siteID: Int64
7+
8+
func map(response: Data) throws -> BookingResource {
9+
let decoder = JSONDecoder()
10+
decoder.userInfo = [
11+
.siteID: siteID
12+
]
13+
if hasDataEnvelope(in: response) {
14+
return try decoder.decode(BookingResourceEnvelope.self, from: response).bookingResource
15+
} else {
16+
return try decoder.decode(BookingResource.self, from: response)
17+
}
18+
}
19+
}
20+
21+
private struct BookingResourceEnvelope: Decodable {
22+
let bookingResource: BookingResource
23+
24+
private enum CodingKeys: String, CodingKey {
25+
case bookingResource = "data"
26+
}
27+
}

Modules/Sources/Networking/Model/Bookings/Booking.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ public struct Booking: Codable, GeneratedCopiable, Hashable, GeneratedFakeable {
2222
public let statusKey: String
2323
public let localTimezone: String
2424
public let currency: String
25-
// periphery: ignore - to be used later
2625
public let orderInfo: BookingOrderInfo?
2726

2827
public var bookingStatus: BookingStatus {

Modules/Sources/Networking/Model/Bookings/BookingOrderInfo.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,23 @@ public struct BookingOrderInfo: Hashable {
1616
self.customerInfo = customerInfo
1717
self.productInfo = productInfo
1818
}
19+
20+
public init(booking: Booking, order: Order) {
21+
self.customerInfo = {
22+
guard let billingAddress = order.billingAddress else {
23+
return nil
24+
}
25+
return BookingCustomerInfo(billingAddress: billingAddress)
26+
}()
27+
self.productInfo = BookingProductInfo(name: order.items.first(where: { $0.productID == booking.productID })?.name ?? "")
28+
self.paymentInfo = BookingPaymentInfo(
29+
paymentMethodID: order.paymentMethodID,
30+
paymentMethodTitle: order.paymentMethodTitle,
31+
subtotal: order.items.map({ Double($0.subtotal) ?? 0 }).reduce(0, +).description,
32+
subtotalTax: order.items.map({ Double($0.subtotalTax) ?? 0 }).reduce(0, +).description,
33+
total: order.total,
34+
totalTax: order.totalTax
35+
)
36+
self.statusKey = order.status.rawValue
37+
}
1938
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import Codegen
2+
import Foundation
3+
4+
public struct BookingResource: Hashable, Decodable, GeneratedFakeable, GeneratedCopiable {
5+
public let siteID: Int64
6+
public let resourceID: Int64
7+
public let name: String
8+
public let quantity: Int64
9+
public let role: String
10+
public let email: String?
11+
public let phoneNumber: String?
12+
public let imageID: Int64
13+
public let imageURL: String?
14+
public let description: String?
15+
16+
public init(siteID: Int64,
17+
resourceID: Int64,
18+
name: String,
19+
quantity: Int64,
20+
role: String,
21+
email: String?,
22+
phoneNumber: String?,
23+
imageID: Int64,
24+
imageURL: String?,
25+
description: String?) {
26+
self.siteID = siteID
27+
self.resourceID = resourceID
28+
self.name = name
29+
self.quantity = quantity
30+
self.role = role
31+
self.email = email
32+
self.phoneNumber = phoneNumber
33+
self.imageID = imageID
34+
self.imageURL = imageURL
35+
self.description = description
36+
}
37+
38+
public init(from decoder: Decoder) throws {
39+
guard let siteID = decoder.userInfo[.siteID] as? Int64 else {
40+
throw BookingResourceDecodingError.missingSiteID
41+
}
42+
43+
let container = try decoder.container(keyedBy: CodingKeys.self)
44+
45+
let resourceID = try container.decode(Int64.self, forKey: .resourceID)
46+
let name = try container.decode(String.self, forKey: .name)
47+
let quantity = try container.decode(Int64.self, forKey: .quantity)
48+
let role = try container.decode(String.self, forKey: .role)
49+
let email = try container.decodeIfPresent(String.self, forKey: .email)
50+
let phoneNumber = try container.decodeIfPresent(String.self, forKey: .phoneNumber)
51+
let imageID = try container.decode(Int64.self, forKey: .imageID)
52+
let imageURL = try container.decodeIfPresent(String.self, forKey: .imageURL)
53+
let description = try container.decodeIfPresent(String.self, forKey: .description)
54+
55+
self.init(siteID: siteID,
56+
resourceID: resourceID,
57+
name: name,
58+
quantity: quantity,
59+
role: role,
60+
email: email,
61+
phoneNumber: phoneNumber,
62+
imageID: imageID,
63+
imageURL: imageURL,
64+
description: description)
65+
}
66+
}
67+
68+
private extension BookingResource {
69+
enum CodingKeys: String, CodingKey {
70+
case resourceID = "id"
71+
case name
72+
case quantity = "qty"
73+
case role
74+
case email
75+
case phoneNumber = "phone_number"
76+
case imageID = "image_id"
77+
case imageURL = "image_url"
78+
case description
79+
}
80+
}
81+
82+
// MARK: - Decoding Errors
83+
//
84+
enum BookingResourceDecodingError: Error {
85+
case missingSiteID
86+
}

Modules/Sources/Networking/Model/Copiable/Models+Copiable.generated.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,45 @@ extension Networking.Booking {
494494
}
495495
}
496496

497+
extension Networking.BookingResource {
498+
public func copy(
499+
siteID: CopiableProp<Int64> = .copy,
500+
resourceID: CopiableProp<Int64> = .copy,
501+
name: CopiableProp<String> = .copy,
502+
quantity: CopiableProp<Int64> = .copy,
503+
role: CopiableProp<String> = .copy,
504+
email: NullableCopiableProp<String> = .copy,
505+
phoneNumber: NullableCopiableProp<String> = .copy,
506+
imageID: CopiableProp<Int64> = .copy,
507+
imageURL: NullableCopiableProp<String> = .copy,
508+
description: NullableCopiableProp<String> = .copy
509+
) -> Networking.BookingResource {
510+
let siteID = siteID ?? self.siteID
511+
let resourceID = resourceID ?? self.resourceID
512+
let name = name ?? self.name
513+
let quantity = quantity ?? self.quantity
514+
let role = role ?? self.role
515+
let email = email ?? self.email
516+
let phoneNumber = phoneNumber ?? self.phoneNumber
517+
let imageID = imageID ?? self.imageID
518+
let imageURL = imageURL ?? self.imageURL
519+
let description = description ?? self.description
520+
521+
return Networking.BookingResource(
522+
siteID: siteID,
523+
resourceID: resourceID,
524+
name: name,
525+
quantity: quantity,
526+
role: role,
527+
email: email,
528+
phoneNumber: phoneNumber,
529+
imageID: imageID,
530+
imageURL: imageURL,
531+
description: description
532+
)
533+
}
534+
}
535+
497536
extension Networking.Coupon {
498537
public func copy(
499538
siteID: CopiableProp<Int64> = .copy,

Modules/Sources/Networking/Remote/BookingsRemote.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public protocol BookingsRemoteProtocol {
1616

1717
func loadBooking(bookingID: Int64,
1818
siteID: Int64) async throws -> Booking?
19+
20+
func fetchResource(resourceID: Int64,
21+
siteID: Int64) async throws -> BookingResource?
1922
}
2023

2124
/// Booking: Remote Endpoints
@@ -84,6 +87,24 @@ public final class BookingsRemote: Remote, BookingsRemoteProtocol {
8487

8588
return try await enqueue(request, mapper: mapper)
8689
}
90+
91+
public func fetchResource(
92+
resourceID: Int64,
93+
siteID: Int64
94+
) async throws -> BookingResource? {
95+
let path = "\(Path.resources)/\(resourceID)"
96+
let request = JetpackRequest(
97+
wooApiVersion: .wcBookings,
98+
method: .get,
99+
siteID: siteID,
100+
path: path,
101+
availableAsRESTRequest: true
102+
)
103+
104+
let mapper = BookingResourceMapper(siteID: siteID)
105+
106+
return try await enqueue(request, mapper: mapper)
107+
}
87108
}
88109

89110
// MARK: - Constants
@@ -101,6 +122,7 @@ public extension BookingsRemote {
101122

102123
private enum Path {
103124
static let bookings = "bookings"
125+
static let resources = "resources/team-members"
104126
}
105127

106128
private enum ParameterKey {

Modules/Sources/NetworkingCore/Network/AlamofireNetworkErrorHandler.swift

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,23 @@ final class AlamofireNetworkErrorHandler {
8585
originalRequest: URLRequestConvertible,
8686
failure: Error?
8787
) {
88-
let retriedRequestIndex = retriedJetpackRequests.firstIndex { retriedRequest in
89-
let urlRequest = try? originalRequest.asURLRequest()
90-
let retriedRequest = try? retriedRequest.request.asURLRequest()
91-
return urlRequest == retriedRequest
92-
}
88+
let retriedRequest: RetriedJetpackRequest? = queue.sync(flags: .barrier) { [weak self] in
89+
guard let self else { return nil }
90+
guard let urlRequest = try? originalRequest.asURLRequest() else { return nil }
91+
let retriedRequestIndex = _retriedJetpackRequests.firstIndex { retriedRequest in
92+
guard let retriedURLRequest = try? retriedRequest.request.asURLRequest() else {
93+
return false
94+
}
95+
return urlRequest.url == retriedURLRequest.url &&
96+
urlRequest.httpMethod == retriedURLRequest.httpMethod
97+
}
9398

94-
guard let index = retriedRequestIndex else { return }
99+
guard let index = retriedRequestIndex else { return nil }
100+
101+
return _retriedJetpackRequests.remove(at: index)
102+
}
95103

96-
let retriedRequest = retriedJetpackRequests.remove(at: index)
104+
guard let retriedRequest else { return }
97105

98106
if failure == nil {
99107
let siteID = retriedRequest.request.siteID
@@ -141,10 +149,15 @@ final class AlamofireNetworkErrorHandler {
141149
}
142150

143151
func isRequestRetried(_ request: URLRequestConvertible) -> Bool {
144-
retriedJetpackRequests.contains { retriedRequest in
145-
let urlRequest = try? request.asURLRequest()
146-
let currentItem = try? retriedRequest.request.asURLRequest()
147-
return currentItem == urlRequest
152+
guard let urlRequest = try? request.asURLRequest() else {
153+
return false
154+
}
155+
return retriedJetpackRequests.contains { retriedRequest in
156+
guard let currentItem = try? retriedRequest.request.asURLRequest() else {
157+
return false
158+
}
159+
return currentItem.url == urlRequest.url &&
160+
currentItem.httpMethod == urlRequest.httpMethod
148161
}
149162
}
150163

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Foundation
2+
import CoreData
3+
4+
@objc(BookingResource)
5+
public class BookingResource: NSManagedObject {
6+
7+
}

0 commit comments

Comments
 (0)