Skip to content

Commit 42fa5b2

Browse files
committed
Show specific error for scanned downloadable items
1 parent 8377ed0 commit 42fa5b2

File tree

3 files changed

+34
-21
lines changed

3 files changed

+34
-21
lines changed

Modules/Sources/Storage/GRDB/Model/PersistedProduct.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@ public extension PersistedProduct {
9595
/// Returns a request for POS-supported products (simple and variable, non-downloadable) for a given site, ordered by name
9696
static func posProductsRequest(siteID: Int64) -> QueryInterfaceRequest<PersistedProduct> {
9797
return PersistedProduct
98-
.filter(Columns.siteID == siteID)
99-
.filter([ProductType.simple.rawValue, ProductType.variable.rawValue].contains(Columns.productTypeKey))
98+
.basePOSProductsRequest(siteID: siteID)
10099
.filter(Columns.downloadable == false)
101100
.order(Columns.name.collating(.localizedCaseInsensitiveCompare))
102101
}
@@ -108,11 +107,19 @@ public extension PersistedProduct {
108107
/// - Returns: A query request that matches products with the given global unique ID
109108
static func posProductByGlobalUniqueID(siteID: Int64, globalUniqueID: String) -> QueryInterfaceRequest<PersistedProduct> {
110109
return PersistedProduct
111-
.posProductsRequest(siteID: siteID)
110+
.basePOSProductsRequest(siteID: siteID)
112111
.filter(Columns.globalUniqueID == globalUniqueID)
113112
}
114113
}
115114

115+
private extension PersistedProduct {
116+
static func basePOSProductsRequest(siteID: Int64) -> QueryInterfaceRequest<PersistedProduct> {
117+
return PersistedProduct
118+
.filter(Columns.siteID == siteID)
119+
.filter([ProductType.simple.rawValue, ProductType.variable.rawValue].contains(Columns.productTypeKey))
120+
}
121+
}
122+
116123
// periphery:ignore - TODO: remove ignore when populating database
117124
private extension PersistedProduct {
118125
enum CodingKeys: String, CodingKey {

Modules/Sources/Storage/GRDB/Model/PersistedProductVariation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public extension PersistedProductVariation {
9292
return PersistedProductVariation
9393
.basePOSVariationsRequest(siteID: siteID)
9494
.filter(Columns.productID == parentProductID)
95+
.filter(Columns.downloadable == false)
9596
.order(Columns.id)
9697
}
9798

@@ -111,7 +112,6 @@ private extension PersistedProductVariation {
111112
static func basePOSVariationsRequest(siteID: Int64) -> QueryInterfaceRequest<PersistedProductVariation> {
112113
return PersistedProductVariation
113114
.filter(Columns.siteID == siteID)
114-
.filter(Columns.downloadable == false)
115115
}
116116
}
117117

Modules/Sources/Yosemite/PointOfSale/Items/PointOfSaleLocalBarcodeScanService.swift

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ public final class PointOfSaleLocalBarcodeScanService: PointOfSaleBarcodeScanSer
2121
/// - Parameter barcode: The barcode string from a scan (global unique identifier)
2222
/// - Returns: A POSItem if found, or throws an error
2323
public func getItem(barcode: String) async throws(PointOfSaleBarcodeScanError) -> POSItem {
24-
// Search for product or variation by global unique ID
2524
do {
2625
if let product = try searchProductByGlobalUniqueID(barcode) {
2726
return try convertProductToItem(product, scannedCode: barcode)
@@ -31,7 +30,6 @@ public final class PointOfSaleLocalBarcodeScanService: PointOfSaleBarcodeScanSer
3130
return try await convertVariationToItem(variationAndParent.variation, parentProduct: variationAndParent.parentProduct, scannedCode: barcode)
3231
}
3332

34-
// No match found
3533
throw PointOfSaleBarcodeScanError.notFound(scannedCode: barcode)
3634
} catch let error as PointOfSaleBarcodeScanError {
3735
throw error
@@ -69,7 +67,6 @@ public final class PointOfSaleLocalBarcodeScanService: PointOfSaleBarcodeScanSer
6967
do {
7068
let posProduct = try persistedProduct.toPOSProduct(db: grdbManager.databaseConnection)
7169

72-
// Validate product is not downloadable (should already be filtered by query, but double-check)
7370
guard !posProduct.downloadable else {
7471
throw PointOfSaleBarcodeScanError.downloadableProduct(scannedCode: scannedCode, productName: posProduct.name)
7572
}
@@ -102,27 +99,20 @@ public final class PointOfSaleLocalBarcodeScanService: PointOfSaleBarcodeScanSer
10299
parentProduct: PersistedProduct,
103100
scannedCode: String) async throws(PointOfSaleBarcodeScanError) -> POSItem {
104101
do {
105-
// Validate variation is not downloadable (should already be filtered by query, but double-check)
106-
guard !persistedVariation.downloadable else {
107-
// We don't have the product name for variations, so use a generic message
108-
throw PointOfSaleBarcodeScanError.downloadableProduct(scannedCode: scannedCode, productName: "Product variation")
109-
}
110-
111102
// Convert both variation and parent to POS models
112103
let posVariation = try persistedVariation.toPOSProductVariation(db: grdbManager.databaseConnection)
113104
let parentPOSProduct = try parentProduct.toPOSProduct(db: grdbManager.databaseConnection)
114105

115-
// Map parent to POSVariableParentProduct
116-
let mappedParents = itemMapper.mapProductsToPOSItems(products: [parentPOSProduct])
117-
guard let mappedParent = mappedParents.first,
118-
case .variableParentProduct(let variableParentProduct) = mappedParent else {
106+
// Map to POSItem
107+
guard let mappedParent = itemMapper.mapProductsToPOSItems(products: [parentPOSProduct]).first,
108+
case .variableParentProduct(let variableParentProduct) = mappedParent,
109+
let item = itemMapper.mapVariationsToPOSItems(variations: [posVariation], parentProduct: variableParentProduct).first else {
119110
throw PointOfSaleBarcodeScanError.variationCouldNotBeConverted(scannedCode: scannedCode)
120111
}
121112

122-
// Convert to POSItem
123-
let items = itemMapper.mapVariationsToPOSItems(variations: [posVariation], parentProduct: variableParentProduct)
124-
guard let item = items.first else {
125-
throw PointOfSaleBarcodeScanError.variationCouldNotBeConverted(scannedCode: scannedCode)
113+
guard !persistedVariation.downloadable else {
114+
throw PointOfSaleBarcodeScanError.downloadableProduct(scannedCode: scannedCode,
115+
productName: variationName(for: item))
126116
}
127117

128118
return item
@@ -132,4 +122,20 @@ public final class PointOfSaleLocalBarcodeScanService: PointOfSaleBarcodeScanSer
132122
throw PointOfSaleBarcodeScanError.mappingError(scannedCode: scannedCode, underlyingError: error)
133123
}
134124
}
125+
126+
private func variationName(for item: POSItem) -> String {
127+
guard case .variation(let posVariation) = item else {
128+
return Localization.unknownVariationName
129+
}
130+
return posVariation.name
131+
}
132+
}
133+
134+
private extension PointOfSaleLocalBarcodeScanService {
135+
enum Localization {
136+
static let unknownVariationName = NSLocalizedString(
137+
"pointOfSale.barcodeScanning.unresolved.variation.name",
138+
value: "Unknown",
139+
comment: "A placeholder name when we can't determine the name of a variation for an error message")
140+
}
135141
}

0 commit comments

Comments
 (0)