Skip to content

Commit fd096d4

Browse files
committed
Add DocC for data models
1 parent 1027991 commit fd096d4

File tree

4 files changed

+212
-28
lines changed

4 files changed

+212
-28
lines changed

Snippets/OrderData.swift

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import FluentKit
2+
import FluentWalletOrders
3+
import Foundation
4+
import WalletOrders
5+
6+
// snippet.ORDER_DATA
7+
final class OrderData: OrderDataModel, @unchecked Sendable {
8+
static let schema = "Order_data"
9+
10+
static let typeIdentifier = "order.com.example.FluentWallet"
11+
12+
@ID
13+
var id: UUID?
14+
15+
@Parent(key: "order_id")
16+
var order: Order
17+
18+
// Example of other extra fields:
19+
@Field(key: "merchant_name")
20+
var merchantName: String
21+
22+
// Add any other field relative to your app, such as an identifier, the order status, etc.
23+
24+
init() {}
25+
}
26+
27+
// snippet.CREATE_ORDER_DATA
28+
struct CreateOrderData: AsyncMigration {
29+
public func prepare(on database: Database) async throws {
30+
try await database.schema(OrderData.schema)
31+
.id()
32+
.field("order_id", .uuid, .required, .references(Order.schema, .id, onDelete: .cascade))
33+
.field("merchant_name", .string, .required)
34+
.create()
35+
}
36+
37+
public func revert(on database: Database) async throws {
38+
try await database.schema(OrderData.schema).delete()
39+
}
40+
}
41+
42+
// snippet.ORDER_JSON
43+
extension OrderData {
44+
func orderJSON(on db: any Database) async throws -> any OrderJSON.Properties {
45+
try await OrderJSONData(data: self, order: self.$order.get(on: db))
46+
}
47+
48+
func sourceFilesDirectoryPath(on db: any Database) async throws -> String {
49+
// The location might vary depending on the type of order.
50+
"SourceFiles/Orders/"
51+
}
52+
}
53+
54+
// snippet.ORDER_JSON_DATA
55+
struct OrderJSONData: OrderJSON.Properties {
56+
var schemaVersion = OrderJSON.SchemaVersion.v1
57+
var orderType = OrderJSON.OrderType.ecommerce
58+
var orderNumber = "HM090772020864"
59+
var webServiceURL = "https://example.com/api/orders/"
60+
var status = OrderJSON.OrderStatus.open
61+
var orderManagementURL = "https://www.example.com/"
62+
63+
var createdAt: String
64+
var updatedAt: String
65+
var merchant: MerchantData
66+
var authenticationToken: String
67+
var orderIdentifier: String
68+
69+
var orderTypeIdentifier = OrderData.typeIdentifier
70+
71+
struct MerchantData: OrderJSON.Merchant {
72+
var merchantIdentifier = "com.example.pet-store"
73+
var displayName: String
74+
var url = "https://www.example.com/"
75+
var logo = "pet_store_logo.png"
76+
}
77+
78+
init(data: OrderData, order: Order) {
79+
self.orderIdentifier = order.id!.uuidString
80+
self.authenticationToken = order.authenticationToken
81+
self.merchant = MerchantData(displayName: "Pet Store")
82+
83+
let dateFormatter = ISO8601DateFormatter()
84+
dateFormatter.formatOptions = .withInternetDateTime
85+
self.createdAt = dateFormatter.string(from: order.createdAt!)
86+
self.updatedAt = dateFormatter.string(from: order.updatedAt!)
87+
}
88+
}

Snippets/PassData.swift

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -79,41 +79,41 @@ extension PassData {
7979

8080
// snippet.PASS_JSON_DATA
8181
struct PassJSONData: PassJSON.Properties {
82-
let formatVersion = PassJSON.FormatVersion.v1
83-
let organizationName = "example"
84-
let teamIdentifier = "DEF123GHIJ" // You should keep this value secret
85-
let webServiceURL = "https://example.com/api/passes/"
86-
let logoText = "Example"
87-
let sharingProhibited = true
88-
let backgroundColor = "rgb(207, 77, 243)"
89-
let foregroundColor = "rgb(255, 255, 255)"
90-
91-
let passTypeIdentifier = PassData.typeIdentifier
92-
93-
let description: String
94-
let serialNumber: String
95-
let authenticationToken: String
96-
97-
let barcodes = Barcode(message: "message")
82+
var formatVersion = PassJSON.FormatVersion.v1
83+
var organizationName = "example"
84+
var teamIdentifier = "DEF123GHIJ" // You should keep this value secret
85+
var webServiceURL = "https://example.com/api/passes/"
86+
var logoText = "Example"
87+
var sharingProhibited = true
88+
var backgroundColor = "rgb(207, 77, 243)"
89+
var foregroundColor = "rgb(255, 255, 255)"
90+
91+
var passTypeIdentifier = PassData.typeIdentifier
92+
93+
var description: String
94+
var serialNumber: String
95+
var authenticationToken: String
96+
97+
var barcodes = Barcode(message: "message")
9898
struct Barcode: PassJSON.Barcodes {
99-
let format = PassJSON.BarcodeFormat.qr
100-
let message: String
101-
let messageEncoding = "iso-8859-1"
99+
var format = PassJSON.BarcodeFormat.qr
100+
var message: String
101+
var messageEncoding = "iso-8859-1"
102102
}
103103

104104
let boardingPass = Boarding(transitType: .air)
105105
struct Boarding: PassJSON.BoardingPass {
106-
let transitType: PassJSON.TransitType
107-
let headerFields: [PassField]
108-
let primaryFields: [PassField]
109-
let secondaryFields: [PassField]
110-
let auxiliaryFields: [PassField]
111-
let backFields: [PassField]
106+
var transitType: PassJSON.TransitType
107+
var headerFields: [PassField]
108+
var primaryFields: [PassField]
109+
var secondaryFields: [PassField]
110+
var auxiliaryFields: [PassField]
111+
var backFields: [PassField]
112112

113113
struct PassField: PassJSON.PassFieldContent {
114-
let key: String
115-
let label: String
116-
let value: String
114+
var key: String
115+
var label: String
116+
var value: String
117117
}
118118

119119
init(transitType: PassJSON.TransitType) {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# ``FluentWalletOrders/OrderDataModel``
2+
3+
## Overview
4+
5+
The `FluentWalletOrders` framework provides models to save all the basic information for orders, user devices and their registration to each order.
6+
For all the other custom data needed to generate the order, such as the barcodes, merchant info, etc., you have to create your own model and its model middleware to handle the creation and update of order.
7+
The order data model will be used to generate the `order.json` file contents.
8+
9+
### Implement the Order Data Model
10+
11+
Your data model should contain all the fields that you store for your order, as well as a foreign key to ``Order`` and a order type identifier that's registered with Apple.
12+
13+
@Snippet(path: "fluent-wallet/Snippets/OrderData", slice: ORDER_DATA)
14+
15+
Don't forget to create the migration for the ``OrderDataModel``.
16+
17+
@Snippet(path: "fluent-wallet/Snippets/OrderData", slice: CREATE_ORDER_DATA)
18+
19+
You also have to define two methods in the ``OrderDataModel``:
20+
- ``OrderDataModel/orderJSON(on:)``, where you'll have to return a `struct` that conforms to `OrderJSON.Properties`.
21+
- ``OrderDataModel/sourceFilesDirectoryPath(on:)``, where you'll have to return the path to a folder containing the order files.
22+
23+
@Snippet(path: "fluent-wallet/Snippets/OrderData", slice: ORDER_JSON)
24+
25+
### Handle Cleanup
26+
27+
Depending on your implementation details, you may want to automatically clean out the orders and devices table when a registration is deleted.
28+
The implementation will be based on your type of SQL database, as there's not yet a Fluent way to implement something like SQL's `NOT EXISTS` call with a `DELETE` statement.
29+
30+
> Warning: Be careful with SQL triggers, as they can have unintended consequences if not properly implemented.
31+
32+
### Model the order.json contents
33+
34+
Create a `struct` that implements `OrderJSON.Properties`, which will contain all the fields for the generated `order.json` file, to return in the ``OrderDataModel/orderJSON(on:)`` method.
35+
Create an initializer that takes your custom order data, the ``Order`` and everything else you may need.
36+
37+
> Tip: For information on the various keys available see the [documentation](https://developer.apple.com/documentation/walletorders/order).
38+
39+
@Snippet(path: "fluent-wallet/Snippets/OrderData", slice: ORDER_JSON_DATA)
40+
41+
### Implement the Web Service
42+
43+
After implementing the data models, you have to implement the web service that will handle the order creation and update.
44+
45+
You can use the concrete models provided by `FluentWalletOrders` or create your own models that conform to the protocols defined in the package.
46+
For the provided models, there are corresponding migrations that you can use to create the tables in your database.
47+
48+
It's highly recommended to create a model middleware for your custom ``OrderDataModel`` to handle the creation and update of orders, because whenever your order data changes, you must update the ``Order/updatedAt`` time so that Wallet knows to retrieve a new order.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# ``FluentWalletPasses/PassDataModel``
2+
3+
## Overview
4+
5+
The `FluentWalletPasses` framework provides models to save all the basic information for passes, user devices and their registration to each pass.
6+
For all the other custom data needed to generate the pass, such as the barcodes, locations, etc., you have to create your own model and its model middleware to handle the creation and update of passes.
7+
The pass data model will be used to generate the `pass.json` file contents.
8+
9+
### Implement the Pass Data Model
10+
11+
Your data model should contain all the fields that you store for your pass, as well as a foreign key to ``Pass`` and a pass type identifier that's registered with Apple.
12+
13+
@Snippet(path: "fluent-wallet/Snippets/PassData", slice: PASS_DATA)
14+
15+
Don't forget to create the migration for the ``PassDataModel``.
16+
17+
@Snippet(path: "fluent-wallet/Snippets/PassData", slice: CREATE_PASS_DATA)
18+
19+
You also have to define two methods in the ``PassDataModel``:
20+
- ``PassDataModel/passJSON(on:)``, where you'll have to return a `struct` that conforms to `PassJSON.Properties`.
21+
- ``PassDataModel/sourceFilesDirectoryPath(on:)``, where you'll have to return the path to a folder containing the pass files.
22+
23+
@Snippet(path: "fluent-wallet/Snippets/PassData", slice: PASS_JSON)
24+
25+
### Handle Cleanup
26+
27+
Depending on your implementation details, you may want to automatically clean out the passes and devices table when a registration is deleted.
28+
The implementation will be based on your type of SQL database, as there's not yet a Fluent way to implement something like SQL's `NOT EXISTS` call with a `DELETE` statement.
29+
30+
> Warning: Be careful with SQL triggers, as they can have unintended consequences if not properly implemented.
31+
32+
### Model the pass.json contents
33+
34+
You have to create a `struct` that implements `PassJSON.Properties`, which will contain all the fields for the generated `pass.json` file, to return in the ``PassDataModel/passJSON(on:)`` method.
35+
Create an initializer that takes your custom pass data, the ``Pass`` and everything else you may need.
36+
37+
> Tip: For information on the various keys available see the [documentation](https://developer.apple.com/documentation/walletpasses/pass). See also [this guide](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/PassKit_PG/index.html#//apple_ref/doc/uid/TP40012195-CH1-SW1) for some help.
38+
39+
@Snippet(path: "fluent-wallet/Snippets/PassData", slice: PASS_JSON_DATA)
40+
41+
### Implement the Web Service
42+
43+
After implementing the data models, you have to implement the web service that will handle the pass creation and update.
44+
45+
You can use the concrete models provided by `FluentWalletPasses` or create your own models that conform to the protocols defined in the package.
46+
For the provided models, there are corresponding migrations that you can use to create the tables in your database.
47+
48+
It's highly recommended to create a model middleware for your custom ``PassDataModel`` to handle the creation and update of passes, because whenever your pass data changes, you must update the ``Pass/updatedAt`` time so that Wallet knows to retrieve a new pass.

0 commit comments

Comments
 (0)