Skip to content

Commit b357920

Browse files
committed
Prevent duplicated attributes in variation names
1 parent 1857228 commit b357920

File tree

2 files changed

+37
-9
lines changed

2 files changed

+37
-9
lines changed

Modules/Sources/Yosemite/Tools/POS/POSCatalogPersistenceService.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ final class POSCatalogPersistenceService: POSCatalogPersistenceServiceProtocol {
9595

9696
try await grdbManager.databaseConnection.write { db in
9797
for product in catalog.products {
98+
// Delete attributes for updated products, the remaining set will be recreated later in the save
99+
try PersistedProductAttribute
100+
.filter(PersistedProductAttribute.Columns.productID == product.productID)
101+
.deleteAll(db)
102+
98103
try PersistedProduct(from: product).save(db)
99104

100105
// Delete variations that are no longer associated with this product
@@ -129,7 +134,7 @@ final class POSCatalogPersistenceService: POSCatalogPersistenceServiceProtocol {
129134
}
130135

131136
for var attribute in catalog.productAttributesToPersist {
132-
try attribute.save(db)
137+
try attribute.insert(db)
133138
}
134139

135140
for var attribute in catalog.variationAttributesToPersist {

Modules/Tests/YosemiteTests/Tools/POS/POSCatalogPersistenceServiceTests.swift

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ struct POSCatalogPersistenceServiceTests {
275275
}
276276
}
277277

278-
@Test func persistIncrementalCatalogData_upserts_attributes_for_updated_product() async throws {
278+
@Test func persistIncrementalCatalogData_replaces_attributes_for_updated_product() async throws {
279279
// Given
280280
let attribute1 = Yosemite.ProductAttribute.fake().copy(name: "Color", options: ["Indigo", "Blue"])
281281
let attribute2 = Yosemite.ProductAttribute.fake().copy(name: "Size")
@@ -291,17 +291,40 @@ struct POSCatalogPersistenceServiceTests {
291291

292292
// Then
293293
try await grdbManager.databaseConnection.read { db in
294-
// Should have 4 attributes: original 2 + updated 2 (upsert adds new ones, keeps old ones)
294+
// Should have 2 attributes - old ones deleted, new ones added (no duplicates)
295295
let attributeCount = try PersistedProductAttribute.fetchCount(db)
296-
#expect(attributeCount == 4)
296+
#expect(attributeCount == 2)
297+
298+
let attributes = try PersistedProductAttribute.fetchAll(db).sorted(by: { $0.name < $1.name })
299+
#expect(attributes[0].name == "Color")
300+
#expect(attributes[0].options == ["Cardinal", "Blue"]) // Updated version
301+
#expect(attributes[1].name == "Material") // New attribute
302+
}
303+
}
304+
305+
@Test func persistIncrementalCatalogData_prevents_duplicate_attributes_on_multiple_syncs() async throws {
306+
// Given - product with attributes
307+
let attribute1 = Yosemite.ProductAttribute.fake().copy(name: "Color", options: ["Red", "Blue"])
308+
let attribute2 = Yosemite.ProductAttribute.fake().copy(name: "Size", options: ["S", "M", "L"])
309+
let product = POSProduct.fake().copy(siteID: sampleSiteID, productID: 1, attributes: [attribute1, attribute2])
310+
try await insertProduct(product)
311+
312+
// When - perform multiple incremental syncs with the same product/attributes
313+
let catalog = POSCatalog(products: [product], variations: [], syncDate: .now)
314+
try await sut.persistIncrementalCatalogData(catalog, siteID: sampleSiteID)
315+
try await sut.persistIncrementalCatalogData(catalog, siteID: sampleSiteID)
316+
try await sut.persistIncrementalCatalogData(catalog, siteID: sampleSiteID)
317+
318+
// Then - should have exactly 2 attributes, not duplicates
319+
try await grdbManager.databaseConnection.read { db in
320+
let attributeCount = try PersistedProductAttribute.fetchCount(db)
321+
#expect(attributeCount == 2)
297322

298323
let attributes = try PersistedProductAttribute.fetchAll(db).sorted(by: { $0.name < $1.name })
299324
#expect(attributes[0].name == "Color")
300-
#expect(attributes[0].options == ["Indigo", "Blue"]) // Original unchanged
301-
#expect(attributes[1].name == "Color")
302-
#expect(attributes[1].options == ["Cardinal", "Blue"]) // Updated version
303-
#expect(attributes[2].name == "Material") // New attribute
304-
#expect(attributes[3].name == "Size") // Original unchanged
325+
#expect(attributes[0].options == ["Red", "Blue"])
326+
#expect(attributes[1].name == "Size")
327+
#expect(attributes[1].options == ["S", "M", "L"])
305328
}
306329
}
307330

0 commit comments

Comments
 (0)