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
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ final class POSCatalogPersistenceService: POSCatalogPersistenceServiceProtocol {

try await grdbManager.databaseConnection.write { db in
for product in catalog.products {
// Delete attributes for updated products, the remaining set will be recreated later in the save
try PersistedProductAttribute
.filter(PersistedProductAttribute.Columns.productID == product.productID)
.deleteAll(db)

try PersistedProduct(from: product).save(db)

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

for var attribute in catalog.productAttributesToPersist {
try attribute.save(db)
try attribute.insert(db)
}

for var attribute in catalog.variationAttributesToPersist {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ struct POSCatalogPersistenceServiceTests {
}
}

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

// Then
try await grdbManager.databaseConnection.read { db in
// Should have 4 attributes: original 2 + updated 2 (upsert adds new ones, keeps old ones)
// Should have 2 attributes - old ones deleted, new ones added (no duplicates)
let attributeCount = try PersistedProductAttribute.fetchCount(db)
#expect(attributeCount == 4)
#expect(attributeCount == 2)

let attributes = try PersistedProductAttribute.fetchAll(db).sorted(by: { $0.name < $1.name })
#expect(attributes[0].name == "Color")
#expect(attributes[0].options == ["Cardinal", "Blue"]) // Updated version
#expect(attributes[1].name == "Material") // New attribute
}
}

@Test func persistIncrementalCatalogData_prevents_duplicate_attributes_on_multiple_syncs() async throws {
// Given - product with attributes
let attribute1 = Yosemite.ProductAttribute.fake().copy(name: "Color", options: ["Red", "Blue"])
let attribute2 = Yosemite.ProductAttribute.fake().copy(name: "Size", options: ["S", "M", "L"])
let product = POSProduct.fake().copy(siteID: sampleSiteID, productID: 1, attributes: [attribute1, attribute2])
try await insertProduct(product)

// When - perform multiple incremental syncs with the same product/attributes
let catalog = POSCatalog(products: [product], variations: [], syncDate: .now)
try await sut.persistIncrementalCatalogData(catalog, siteID: sampleSiteID)
try await sut.persistIncrementalCatalogData(catalog, siteID: sampleSiteID)
try await sut.persistIncrementalCatalogData(catalog, siteID: sampleSiteID)

// Then - should have exactly 2 attributes, not duplicates
try await grdbManager.databaseConnection.read { db in
let attributeCount = try PersistedProductAttribute.fetchCount(db)
#expect(attributeCount == 2)

let attributes = try PersistedProductAttribute.fetchAll(db).sorted(by: { $0.name < $1.name })
#expect(attributes[0].name == "Color")
#expect(attributes[0].options == ["Indigo", "Blue"]) // Original unchanged
#expect(attributes[1].name == "Color")
#expect(attributes[1].options == ["Cardinal", "Blue"]) // Updated version
#expect(attributes[2].name == "Material") // New attribute
#expect(attributes[3].name == "Size") // Original unchanged
#expect(attributes[0].options == ["Red", "Blue"])
#expect(attributes[1].name == "Size")
#expect(attributes[1].options == ["S", "M", "L"])
}
}

Expand Down
Loading