Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f4cf155
Add mapping for persisted models
joshheald Aug 29, 2025
b37d574
Add attribute and image associations
joshheald Aug 29, 2025
ff03881
Test persisted to networking model conversion
joshheald Aug 29, 2025
f416265
Save product/variation entities with relationships
joshheald Aug 29, 2025
627787d
Fix whitespace
joshheald Aug 29, 2025
e831e89
Test saving POS models and regroup mapping tests
joshheald Aug 29, 2025
e9fc1ce
Tests for saving POS models to GRDB
joshheald Aug 29, 2025
9f46de1
Fix test expectation
joshheald Aug 29, 2025
f822a09
Match attribute handling for product and variation
joshheald Sep 1, 2025
218d704
Test updates from code revier
joshheald Sep 1, 2025
cdc2e9d
Test fix
joshheald Sep 1, 2025
e3d7b85
Use a single transaction for reading relationships
joshheald Sep 1, 2025
435502f
Merge branch 'woomob-1210-basic-mapping-from-POS-entities-to-persiste…
joshheald Sep 1, 2025
b9c3b19
Merge branch 'woomob-1210-relationship-based-mapping-and-saving-for-P…
joshheald Sep 1, 2025
5c8d942
Remove test prefixes
joshheald Sep 1, 2025
a9048a2
Demonstrate joined records in variation tests
joshheald Sep 1, 2025
991e405
Given/When/Then for all tests
joshheald Sep 1, 2025
c523e48
Fix lint
joshheald Sep 1, 2025
2477ef4
Ignore periphery
joshheald Sep 1, 2025
604a3df
More periphery
joshheald Sep 1, 2025
d0c1b2d
[Woo POS][Local Catalog] Tests for saving pos models (#16064)
joshheald Sep 1, 2025
2159f0d
[Woo POS][Local catalog] Add relationship mapping and saving for POS …
joshheald Sep 1, 2025
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
6 changes: 6 additions & 0 deletions Modules/Sources/Storage/GRDB/Model/PersistedProduct.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation
import GRDB

// periphery:ignore - TODO: remove ignore when populating database
public struct PersistedProduct: Codable {
public let id: Int64
public let siteID: Int64
Expand Down Expand Up @@ -48,6 +49,7 @@ public struct PersistedProduct: Codable {
}
}

// periphery:ignore - TODO: remove ignore when populating database
extension PersistedProduct: FetchableRecord, PersistableRecord {
public static var databaseTableName: String { "product" }

Expand All @@ -67,8 +69,12 @@ extension PersistedProduct: FetchableRecord, PersistableRecord {
static let stockQuantity = Column(CodingKeys.stockQuantity)
static let stockStatusKey = Column(CodingKeys.stockStatusKey)
}

public static let images = hasMany(PersistedProductImage.self)
public static let attributes = hasMany(PersistedProductAttribute.self)
}

// periphery:ignore - TODO: remove ignore when populating database
private extension PersistedProduct {
enum CodingKeys: String, CodingKey {
case id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation
import GRDB

// periphery:ignore - TODO: remove ignore when populating database
public struct PersistedProductAttribute: Codable {
public private(set) var id: Int64?
public let productID: Int64
Expand All @@ -27,6 +28,7 @@ public struct PersistedProductAttribute: Codable {
}
}

// periphery:ignore - TODO: remove ignore when populating database
extension PersistedProductAttribute: FetchableRecord, MutablePersistableRecord {
public static var databaseTableName: String { "productAttribute" }

Expand All @@ -46,6 +48,7 @@ extension PersistedProductAttribute: FetchableRecord, MutablePersistableRecord {
}


// periphery:ignore - TODO: remove ignore when populating database
private extension PersistedProductAttribute {
enum CodingKeys: String, CodingKey {
case id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation
import GRDB

// periphery:ignore - TODO: remove ignore when populating database
public struct PersistedProductImage: Codable {
public let id: Int64
public let productID: Int64
Expand All @@ -27,6 +28,7 @@ public struct PersistedProductImage: Codable {
}
}

// periphery:ignore - TODO: remove ignore when populating database
extension PersistedProductImage: FetchableRecord, PersistableRecord {
public static var databaseTableName: String { "productImage" }

Expand All @@ -42,6 +44,7 @@ extension PersistedProductImage: FetchableRecord, PersistableRecord {
}


// periphery:ignore - TODO: remove ignore when populating database
private extension PersistedProductImage {
enum CodingKeys: String, CodingKey {
case id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation
import GRDB

// periphery:ignore - TODO: remove ignore when populating database
public struct PersistedProductVariation: Codable {
public let id: Int64
public let siteID: Int64
Expand Down Expand Up @@ -39,6 +40,7 @@ public struct PersistedProductVariation: Codable {
}
}

// periphery:ignore - TODO: remove ignore when populating database
extension PersistedProductVariation: FetchableRecord, PersistableRecord {
public static var databaseTableName: String { "productVariation" }

Expand All @@ -55,9 +57,13 @@ extension PersistedProductVariation: FetchableRecord, PersistableRecord {
static let stockQuantity = Column(CodingKeys.stockQuantity)
static let stockStatusKey = Column(CodingKeys.stockStatusKey)
}

public static let attributes = hasMany(PersistedProductVariationAttribute.self).forKey("attributes")
public static let image = hasOne(PersistedProductVariationImage.self).forKey("image")
}


// periphery:ignore - TODO: remove ignore when populating database
private extension PersistedProductVariation {
enum CodingKeys: String, CodingKey {
case id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation
import GRDB

// periphery:ignore - TODO: remove ignore when populating database
public struct PersistedProductVariationAttribute: Codable {
public private(set) var id: Int64?
public let productVariationID: Int64
Expand All @@ -18,6 +19,8 @@ public struct PersistedProductVariationAttribute: Codable {
}
}

// periphery:ignore - TODO: remove ignore when populating database
// periphery:ignore - TODO: remove ignore when populating database
extension PersistedProductVariationAttribute: FetchableRecord, MutablePersistableRecord {
public static var databaseTableName: String { "productVariationAttribute" }

Expand All @@ -34,6 +37,7 @@ extension PersistedProductVariationAttribute: FetchableRecord, MutablePersistabl
}


// periphery:ignore - TODO: remove ignore when populating database
private extension PersistedProductVariationAttribute {
enum CodingKeys: String, CodingKey {
case id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation
import GRDB

// periphery:ignore - TODO: remove ignore when populating database
public struct PersistedProductVariationImage: Codable {
public let id: Int64
public let productVariationID: Int64
Expand All @@ -27,6 +28,7 @@ public struct PersistedProductVariationImage: Codable {
}
}

// periphery:ignore - TODO: remove ignore when populating database
extension PersistedProductVariationImage: FetchableRecord, PersistableRecord {
public static var databaseTableName: String { "productVariationImage" }

Expand All @@ -42,6 +44,7 @@ extension PersistedProductVariationImage: FetchableRecord, PersistableRecord {
}


// periphery:ignore - TODO: remove ignore when populating database
private extension PersistedProductVariationImage {
enum CodingKeys: String, CodingKey {
case id
Expand Down
6 changes: 6 additions & 0 deletions Modules/Sources/Storage/GRDB/Model/PersistedSite.swift
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
import Foundation
import GRDB

// periphery:ignore - TODO: remove ignore when populating database
public struct PersistedSite: Codable {
// periphery:ignore - TODO: remove ignore when populating database
public let id: Int64

// periphery:ignore - TODO: remove ignore when populating database
public init(id: Int64) {
self.id = id
}
}

// periphery:ignore - TODO: remove ignore when populating database
extension PersistedSite: FetchableRecord, PersistableRecord {
public static var databaseTableName: String { "site" }

public enum Columns {
// periphery:ignore - TODO: remove ignore when populating database
static let id = Column(CodingKeys.id)
}
}

// periphery:ignore - TODO: remove ignore when populating database
private extension PersistedSite {
enum CodingKeys: String, CodingKey {
case id
Expand Down
1 change: 1 addition & 0 deletions Modules/Sources/Storage/Protocols/Object.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public protocol Object: AnyObject {

/// Returns an instance of ObjectID: expected to identify the current instance, unequivocally.
///
// periphery:ignore - Used in tests, no changes but mysteriously stopped being ignored.
var objectID: ObjectID { get }

/// Returns the receiver's Entity Name.
Expand Down
7 changes: 7 additions & 0 deletions Modules/Sources/Yosemite/Model/Model.swift
Original file line number Diff line number Diff line change
Expand Up @@ -350,12 +350,19 @@ public typealias StorageWooShippingShipment = Storage.WooShippingShipment
public typealias StorageWooShippingOriginAddress = Storage.WooShippingOriginAddress

// MARK: - GRDB Persisted Models
// periphery:ignore - TODO: remove ignore when populating database
public typealias PersistedSite = Storage.PersistedSite
// periphery:ignore - TODO: remove ignore when populating database
public typealias PersistedProduct = Storage.PersistedProduct
// periphery:ignore - TODO: remove ignore when populating database
public typealias PersistedProductAttribute = Storage.PersistedProductAttribute
// periphery:ignore - TODO: remove ignore when populating database
public typealias PersistedProductImage = Storage.PersistedProductImage
// periphery:ignore - TODO: remove ignore when populating database
public typealias PersistedProductVariation = Storage.PersistedProductVariation
// periphery:ignore - TODO: remove ignore when populating database
public typealias PersistedProductVariationAttribute = Storage.PersistedProductVariationAttribute
// periphery:ignore - TODO: remove ignore when populating database
public typealias PersistedProductVariationImage = Storage.PersistedProductVariationImage

// MARK: - Internal ReadOnly Models
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import Foundation
import Storage

// MARK: - PersistedProduct Conversions
// periphery:ignore - TODO: remove ignore when populating database
extension PersistedProduct {
init(from posProduct: POSProduct) {
self.init(
id: posProduct.productID,
siteID: posProduct.siteID,
name: posProduct.name,
productTypeKey: posProduct.productTypeKey,
fullDescription: posProduct.fullDescription,
shortDescription: posProduct.shortDescription,
sku: posProduct.sku,
globalUniqueID: posProduct.globalUniqueID,
price: posProduct.price,
downloadable: posProduct.downloadable,
parentID: posProduct.parentID,
manageStock: posProduct.manageStock,
stockQuantity: posProduct.stockQuantity,
stockStatusKey: posProduct.stockStatusKey
)
}

func toPOSProduct(images: [ProductImage] = [], attributes: [ProductAttribute] = []) -> POSProduct {
return POSProduct(
siteID: siteID,
productID: id,
name: name,
productTypeKey: productTypeKey,
fullDescription: fullDescription,
shortDescription: shortDescription,
sku: sku,
globalUniqueID: globalUniqueID,
price: price,
downloadable: downloadable,
parentID: parentID,
images: images,
attributes: attributes,
manageStock: manageStock,
stockQuantity: stockQuantity,
stockStatusKey: stockStatusKey
)
}

func toPOSProduct(db: GRDBDatabaseConnection) throws -> POSProduct {
let (images, attributes) = try db.read { db in
let images = try request(for: PersistedProduct.images).fetchAll(db)
let attributes = try request(for: PersistedProduct.attributes).fetchAll(db)
return (images, attributes)
}

return toPOSProduct(
images: images.map { $0.toProductImage() },
attributes: attributes.map { $0.toProductAttribute(siteID: siteID) }
)
}

}

// MARK: - POSProduct Storage Extensions
// periphery:ignore - TODO: remove ignore when populating database
extension POSProduct {
public func save(to db: GRDBDatabaseConnection) throws {
try db.write { db in
let product = PersistedProduct(from: self)
try product.insert(db)

// Save related images
for image in self.images {
let persistedImage = PersistedProductImage(from: image, productID: self.productID)
try persistedImage.insert(db)
}

// Save related attributes
for attribute in self.attributes {
var persistedAttribute = PersistedProductAttribute(from: attribute, productID: self.productID)
try persistedAttribute.insert(db)
}
}
}
}

// MARK: - PersistedProductAttribute Conversions
// periphery:ignore - TODO: remove ignore when populating database
extension PersistedProductAttribute {
init(from productAttribute: ProductAttribute, productID: Int64) {
self.init(
productID: productID,
name: productAttribute.name,
position: Int64(productAttribute.position),
visible: productAttribute.visible,
variation: productAttribute.variation,
options: productAttribute.options
)
}

func toProductAttribute(siteID: Int64) -> ProductAttribute {
return ProductAttribute(
siteID: siteID,
attributeID: id ?? 0,
name: name,
position: Int(position),
visible: visible,
variation: variation,
options: options
)
}
}

// MARK: - PersistedProductImage Conversions
// periphery:ignore - TODO: remove ignore when populating database
extension PersistedProductImage {
init(from productImage: ProductImage, productID: Int64) {
self.init(
id: productImage.imageID,
productID: productID,
dateCreated: productImage.dateCreated,
dateModified: productImage.dateModified,
src: productImage.src,
name: productImage.name,
alt: productImage.alt
)
}

func toProductImage() -> ProductImage {
return ProductImage(
imageID: id,
dateCreated: dateCreated,
dateModified: dateModified,
src: src,
name: name,
alt: alt
)
}
}
Loading