Skip to content

Commit ee4814f

Browse files
authored
[Woo POS][Local catalog] Create local database when POS tab is shown (#16054)
2 parents 5620f79 + 9790bd8 commit ee4814f

File tree

6 files changed

+105
-43
lines changed

6 files changed

+105
-43
lines changed
Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,34 @@
11
import Foundation
22
import GRDB
33

4-
// TODO: remove ignore when we start using this
5-
// periphery: ignore
6-
public final class GRDBManager {
4+
public protocol GRDBManagerProtocol {
5+
var databaseConnection: GRDBDatabaseConnection { get }
6+
}
77

8-
let databaseQueue: DatabaseQueue
9-
private let databasePath: String
8+
public protocol GRDBDatabaseConnection: DatabaseReader & DatabaseWriter {}
109

11-
public init(databasePath: String) throws {
12-
self.databasePath = databasePath
10+
public final class GRDBManager: GRDBManagerProtocol {
11+
12+
public let databaseConnection: GRDBDatabaseConnection
1313

14+
public init(databasePath: String) throws {
1415
let databaseURL = URL(fileURLWithPath: databasePath)
1516
let directoryURL = databaseURL.deletingLastPathComponent()
1617

1718
try FileManager.default.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
1819

19-
self.databaseQueue = try DatabaseQueue(path: databasePath)
20+
self.databaseConnection = try DatabaseQueue(path: databasePath)
2021

2122
try migrateIfNeeded()
2223
}
2324

25+
// Creates an in-memory database, intended for use in tests.
2426
init() throws {
25-
self.databasePath = "in-memory"
26-
self.databaseQueue = try DatabaseQueue()
27+
self.databaseConnection = try DatabaseQueue()
2728
try migrateIfNeeded()
2829
}
2930
}
3031

31-
// TODO: remove ignore when we start using this
32-
// periphery: ignore
3332
private extension GRDBManager {
3433
func migrateIfNeeded() throws {
3534
var migrator = DatabaseMigrator()
@@ -43,6 +42,8 @@ private extension GRDBManager {
4342
try V001InitialSchema.migrate(db)
4443
}
4544

46-
try migrator.migrate(databaseQueue)
45+
try migrator.migrate(databaseConnection)
4746
}
4847
}
48+
49+
extension DatabaseQueue: GRDBDatabaseConnection {}

Modules/Sources/Storage/GRDB/Migrations/V001InitialSchema.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import Foundation
22
import GRDB
33

4-
// TODO: remove ignore when we start using this
5-
// periphery: ignore
64
struct V001InitialSchema {
75
// This migration is under development and not released yet.
86
// It's still open for modification, until we ship.

Modules/Tests/StorageTests/GRDB/GRDBManagerTests.swift

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct GRDBManagerTests {
1818
let manager = try GRDBManager()
1919

2020
// When
21-
let tableExists = try manager.databaseQueue.read { db in
21+
let tableExists = try manager.databaseConnection.read { db in
2222
return (
2323
try db.tableExists("site"),
2424
try db.tableExists("product"),
@@ -49,7 +49,7 @@ struct GRDBManagerTests {
4949

5050
init() throws {
5151
self.manager = try GRDBManager()
52-
try manager.databaseQueue.write { db in
52+
try manager.databaseConnection.write { db in
5353
let record = TestSite(id: sampleSiteID)
5454
try record.insert(db)
5555
}
@@ -60,7 +60,7 @@ struct GRDBManagerTests {
6060
// Given
6161

6262
// When
63-
try manager.databaseQueue.write { db in
63+
try manager.databaseConnection.write { db in
6464
let record = TestProduct(
6565
siteID: 1,
6666
id: 100,
@@ -74,7 +74,7 @@ struct GRDBManagerTests {
7474
}
7575

7676
// Then
77-
let productCount = try manager.databaseQueue.read { db in
77+
let productCount = try manager.databaseConnection.read { db in
7878
try TestProduct.fetchCount(db)
7979
}
8080

@@ -84,7 +84,7 @@ struct GRDBManagerTests {
8484
@Test("Insert product variation with a relationship to a product")
8585
func test_after_init_can_insert_productVariation_with_foreign_key() throws {
8686
// Given – parent product
87-
try manager.databaseQueue.write { db in
87+
try manager.databaseConnection.write { db in
8888
let product = TestProduct(
8989
siteID: 1,
9090
id: 100,
@@ -98,7 +98,7 @@ struct GRDBManagerTests {
9898
}
9999

100100
// When - Insert variation
101-
try manager.databaseQueue.write { db in
101+
try manager.databaseConnection.write { db in
102102
let variation = TestProductVariation(
103103
siteID: 1,
104104
id: 200,
@@ -110,7 +110,7 @@ struct GRDBManagerTests {
110110
}
111111

112112
// Then
113-
let variations = try manager.databaseQueue.read { db in
113+
let variations = try manager.databaseConnection.read { db in
114114
try TestProductVariation.fetchAll(db)
115115
}
116116

@@ -121,7 +121,7 @@ struct GRDBManagerTests {
121121
@Test("Fetch variations by product ID")
122122
func test_after_init_and_insert_can_query_productVariation_using_foreign_key() throws {
123123
// Given parent product and some variations
124-
try manager.databaseQueue.write { db in
124+
try manager.databaseConnection.write { db in
125125
// Insert product
126126
let product = TestProduct(
127127
siteID: 1,
@@ -148,7 +148,7 @@ struct GRDBManagerTests {
148148
}
149149

150150
// When
151-
let variations = try manager.databaseQueue.read { db in
151+
let variations = try manager.databaseConnection.read { db in
152152
try TestProductVariation
153153
.filter(Column("productID") == 100)
154154
.fetchAll(db)
@@ -162,7 +162,7 @@ struct GRDBManagerTests {
162162
@Test("Insert product attribute with options array (JSON)")
163163
func test_after_init_can_insert_productAttribute_with_options_as_JSON_array() throws {
164164
// Given parent product
165-
try manager.databaseQueue.write { db in
165+
try manager.databaseConnection.write { db in
166166
// Insert product first
167167
let product = TestProduct(
168168
siteID: 1,
@@ -177,7 +177,7 @@ struct GRDBManagerTests {
177177
}
178178

179179
// When
180-
try manager.databaseQueue.write { db in
180+
try manager.databaseConnection.write { db in
181181
let attribute = TestProductAttribute(
182182
productID: 100,
183183
name: "Color",
@@ -190,7 +190,7 @@ struct GRDBManagerTests {
190190
}
191191

192192
// Then
193-
let attribute = try manager.databaseQueue.read { db in
193+
let attribute = try manager.databaseConnection.read { db in
194194
try TestProductAttribute.fetchOne(db)
195195
}
196196

@@ -201,7 +201,7 @@ struct GRDBManagerTests {
201201
@Test("Insert variation attributes")
202202
func test_after_init_can_insert_variation_attributes() throws {
203203
// Given parent product and variation
204-
try manager.databaseQueue.write { db in
204+
try manager.databaseConnection.write { db in
205205
// Insert product
206206
let product = TestProduct(
207207
siteID: 1,
@@ -226,7 +226,7 @@ struct GRDBManagerTests {
226226
}
227227

228228
// When
229-
try manager.databaseQueue.write { db in
229+
try manager.databaseConnection.write { db in
230230
let variationAttribute = TestProductVariationAttribute(
231231
productVariationID: 200,
232232
name: "Color",
@@ -236,7 +236,7 @@ struct GRDBManagerTests {
236236
}
237237

238238
// Then
239-
let attributes = try manager.databaseQueue.read { db in
239+
let attributes = try manager.databaseConnection.read { db in
240240
try TestProductVariationAttribute.fetchAll(db)
241241
}
242242

@@ -247,14 +247,14 @@ struct GRDBManagerTests {
247247
@Test("Deleting site cascades to all related entities")
248248
func test_deleting_site_cascades_to_all_related_entities() throws {
249249
// Given - Create a separate site for this test to avoid interfering with other tests
250-
let testSiteId = try manager.databaseQueue.write { db -> Int64 in
250+
let testSiteId = try manager.databaseConnection.write { db -> Int64 in
251251
let site = TestSite(id: 999)
252252
try site.insert(db)
253253
return 999
254254
}
255255

256256
// Insert full entity hierarchy
257-
try manager.databaseQueue.write { db in
257+
try manager.databaseConnection.write { db in
258258
let product = TestProduct(
259259
siteID: testSiteId,
260260
id: 100,
@@ -294,7 +294,7 @@ struct GRDBManagerTests {
294294
}
295295

296296
// Verify entities exist for test site
297-
let countsBefore = try manager.databaseQueue.read { db in
297+
let countsBefore = try manager.databaseConnection.read { db in
298298
return (
299299
products: try TestProduct.filter(Column("siteID") == testSiteId).fetchCount(db),
300300
variations: try TestProductVariation.filter(Column("siteID") == testSiteId).fetchCount(db),
@@ -309,12 +309,12 @@ struct GRDBManagerTests {
309309
#expect(countsBefore.variationAttributes == 1)
310310

311311
// When - Delete the site
312-
_ = try manager.databaseQueue.write { db in
312+
_ = try manager.databaseConnection.write { db in
313313
try TestSite.filter(Column("id") == testSiteId).deleteAll(db)
314314
}
315315

316316
// Then - All related entities should be deleted
317-
let countsAfter = try manager.databaseQueue.read { db in
317+
let countsAfter = try manager.databaseConnection.read { db in
318318
return (
319319
sites: try TestSite.filter(Column("id") == testSiteId).fetchCount(db),
320320
products: try TestProduct.filter(Column("siteID") == testSiteId).fetchCount(db),
@@ -334,13 +334,13 @@ struct GRDBManagerTests {
334334
@Test("Fetch products by site")
335335
func test_can_fetch_products_by_site() throws {
336336
// Given - Create second site and products for both sites
337-
let site2Id = try manager.databaseQueue.write { db -> Int64 in
337+
let site2Id = try manager.databaseConnection.write { db -> Int64 in
338338
let site = TestSite(id: 2)
339339
try site.insert(db)
340340
return 2
341341
}
342342

343-
try manager.databaseQueue.write { db in
343+
try manager.databaseConnection.write { db in
344344
// Site 1 products
345345
for i in 1...3 {
346346
let product = TestProduct(
@@ -371,13 +371,13 @@ struct GRDBManagerTests {
371371
}
372372

373373
// When
374-
let site1Products = try manager.databaseQueue.read { db in
374+
let site1Products = try manager.databaseConnection.read { db in
375375
try TestProduct
376376
.filter(Column("siteID") == sampleSiteID)
377377
.fetchAll(db)
378378
}
379379

380-
let site2Products = try manager.databaseQueue.read { db in
380+
let site2Products = try manager.databaseConnection.read { db in
381381
try TestProduct
382382
.filter(Column("siteID") == site2Id)
383383
.fetchAll(db)
@@ -397,7 +397,7 @@ struct GRDBManagerTests {
397397
@Test("Fetch variations by site")
398398
func test_can_fetch_variations_by_site() throws {
399399
// Given - Product and variations
400-
try manager.databaseQueue.write { db in
400+
try manager.databaseConnection.write { db in
401401
let product = TestProduct(
402402
siteID: sampleSiteID,
403403
id: 100,
@@ -422,7 +422,7 @@ struct GRDBManagerTests {
422422
}
423423

424424
// When
425-
let variations = try manager.databaseQueue.read { db in
425+
let variations = try manager.databaseConnection.read { db in
426426
try TestProductVariation
427427
.filter(Column("siteID") == sampleSiteID)
428428
.fetchAll(db)
@@ -438,7 +438,7 @@ struct GRDBManagerTests {
438438
func test_cannot_insert_product_without_valid_site() throws {
439439
// When/Then
440440
#expect(throws: DatabaseError.self) {
441-
try manager.databaseQueue.write { db in
441+
try manager.databaseConnection.write { db in
442442
let product = TestProduct(
443443
siteID: 999, // Non-existent site
444444
id: 100,
@@ -457,7 +457,7 @@ struct GRDBManagerTests {
457457
func test_cannot_insert_variation_without_valid_product() throws {
458458
// When/Then
459459
#expect(throws: DatabaseError.self) {
460-
try manager.databaseQueue.write { db in
460+
try manager.databaseConnection.write { db in
461461
let variation = TestProductVariation(
462462
siteID: sampleSiteID,
463463
id: 200,

WooCommerce/Classes/POS/TabBar/POSTabCoordinator.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import SwiftUI
44
import Yosemite
55
import class WooFoundation.CurrencySettings
66
import protocol Storage.StorageManagerType
7+
import protocol Storage.GRDBManagerProtocol
78

89
/// View controller that provides the tab bar item for the Point of Sale tab.
910
/// It is never visible on the screen, only used to provide the tab bar item as all POS UI is full-screen.
@@ -26,6 +27,7 @@ final class POSTabCoordinator {
2627
private let storesManager: StoresManager
2728
private let credentials: Credentials?
2829
private let storageManager: StorageManagerType
30+
private let grdbManager: GRDBManagerProtocol?
2931
private let currencySettings: CurrencySettings
3032
private let pushNotesManager: PushNotesManager
3133
private let eligibilityChecker: POSEntryPointEligibilityCheckerProtocol
@@ -77,6 +79,13 @@ final class POSTabCoordinator {
7779
self.eligibilityChecker = eligibilityChecker
7880

7981
tabContainerController.wrappedController = POSTabViewController()
82+
83+
if ServiceLocator.featureFlagService.isFeatureFlagEnabled(.pointOfSaleLocalCatalogi1) {
84+
self.grdbManager = ServiceLocator.grdbManager
85+
logDatabaseSchema()
86+
} else {
87+
self.grdbManager = nil
88+
}
8089
}
8190

8291
func onTabSelected() {
@@ -165,3 +174,11 @@ private extension POSTabCoordinator {
165174
TracksProvider.setPOSMode(isPointOfSaleActive)
166175
}
167176
}
177+
178+
private extension POSTabCoordinator {
179+
func logDatabaseSchema() {
180+
try? grdbManager?.databaseConnection.read { db in
181+
return try db.dumpSchema()
182+
}
183+
}
184+
}

0 commit comments

Comments
 (0)