Skip to content

Commit

Permalink
Rename Personalization to PersonalizationInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
fpseverino committed Jan 12, 2025
1 parent 6e8fc58 commit fbfe7eb
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 39 deletions.
2 changes: 1 addition & 1 deletion Snippets/PassData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ extension PassData {
func personalizationJSON(on db: any Database) async throws -> PersonalizationJSON? {
let pass = try await self.$pass.get(on: db)

let personalization = try await Personalization.query(on: db)
let personalization = try await PersonalizationInfo.query(on: db)
.filter(\.$pass.$id == pass.requireID())
.first()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ For information on Apple Wallet passes, see the [Apple Developer Documentation](
### Personalized Passes

- <doc:PersonalizedPasses>
- ``PersonalizationModel``
- ``Personalization``
- ``CreatePersonalization``
- ``PersonalizationInfoModel``
- ``PersonalizationInfo``
- ``CreatePersonalizationInfo``
- ``PersonalizationDictionaryDTO``
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ If the pass requires personalization, and if it was not already personalized, cr

In the ``PassDataModel/sourceFilesDirectoryPath(on:)`` method, you have to return two different directory paths, depending on whether the pass has to be personalized or not. If it does, the directory must contain the `[email protected]` file.

Finally, you have to implement the ``PassDataModel/passJSON(on:)`` method as usual, but remember to use in the `PassJSON.Properties` initializer the user info that will be saved inside ``Personalization`` after the pass has been personalized.
Each ``Personalization`` instance has a reference to the pass it belongs to, so you can easily retrieve the user info for the pass.
Finally, you have to implement the ``PassDataModel/passJSON(on:)`` method as usual, but remember to use in the `PassJSON.Properties` initializer the user info that will be saved inside ``PersonalizationInfo`` after the pass has been personalized.
Each ``PersonalizationInfo`` instance has a reference to the pass it belongs to, so you can easily retrieve the user info for the pass.

### Implement the Web Service

Expand All @@ -39,12 +39,12 @@ Build the pass bundle with a `PassBuilder` as usual and distribute it.

The user will be prompted to provide the required personal information when they add the pass.

Wallet will then send the user personal information to your server, which should be saved in the ``Personalization`` table, along with a personalization token that you have to sign and return to Wallet in the response.
Wallet will then send the user personal information to your server, which should be saved in the ``PersonalizationInfo`` table, along with a personalization token that you have to sign and return to Wallet in the response.
You can use the `PassBuilder.signature(for:)` method to sign the personalization token.

Immediately after that, Wallet will request the updated pass.
This updated pass will contain the user personalization data that was previously saved inside the ``Personalization`` table.
You can access the pass linked to the personalization data by using the ``Personalization/pass`` field.
This updated pass will contain the user personalization data that was previously saved inside the ``PersonalizationInfo`` table.
You can access the pass linked to the personalization data by using the ``PersonalizationInfo/pass`` field.

> Important: This updated and personalized pass **must not** contain the `personalization.json` file, so make sure that the ``PassDataModel/personalizationJSON(on:)`` method returns `nil` when the pass has already been personalized.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,83 +1,83 @@
import FluentKit

/// The `Model` that stores user personalization info.
final public class Personalization: PersonalizationModel, @unchecked Sendable {
final public class PersonalizationInfo: PersonalizationInfoModel, @unchecked Sendable {
/// The schema name of the user personalization model.
public static let schema = Personalization.FieldKeys.schemaName
public static let schema = PersonalizationInfo.FieldKeys.schemaName

@ID(custom: .id)
public var id: Int?

/// The pass this personalization info is associated with.
@Parent(key: Personalization.FieldKeys.passID)
@Parent(key: PersonalizationInfo.FieldKeys.passID)
public var pass: Pass

/// The user’s full name, as entered by the user.
@OptionalField(key: Personalization.FieldKeys.fullName)
@OptionalField(key: PersonalizationInfo.FieldKeys.fullName)
public var fullName: String?

/// The user’s given name, parsed from the full name.
///
/// This is the name bestowed upon an individual to differentiate them from other members of a group that share a family name (for example, “John”).
/// In some locales, this is also known as a first name or forename.
@OptionalField(key: Personalization.FieldKeys.givenName)
@OptionalField(key: PersonalizationInfo.FieldKeys.givenName)
public var givenName: String?

/// The user’s family name, parsed from the full name.
///
/// This is the name bestowed upon an individual to denote membership in a group or family (for example, “Appleseed”).
@OptionalField(key: Personalization.FieldKeys.familyName)
@OptionalField(key: PersonalizationInfo.FieldKeys.familyName)
public var familyName: String?

/// The email address, as entered by the user.
@OptionalField(key: Personalization.FieldKeys.emailAddress)
@OptionalField(key: PersonalizationInfo.FieldKeys.emailAddress)
public var emailAddress: String?

/// The postal code, as entered by the user.
@OptionalField(key: Personalization.FieldKeys.postalCode)
@OptionalField(key: PersonalizationInfo.FieldKeys.postalCode)
public var postalCode: String?

/// The user’s ISO country code.
///
/// This key is only included when the system can deduce the country code.
@OptionalField(key: Personalization.FieldKeys.isoCountryCode)
@OptionalField(key: PersonalizationInfo.FieldKeys.isoCountryCode)
public var isoCountryCode: String?

/// The phone number, as entered by the user.
@OptionalField(key: Personalization.FieldKeys.phoneNumber)
@OptionalField(key: PersonalizationInfo.FieldKeys.phoneNumber)
public var phoneNumber: String?

public init() {}
}

/// The migration that creates the ``Personalization`` table.
public struct CreatePersonalization: AsyncMigration {
/// The migration that creates the ``PersonalizationInfo`` table.
public struct CreatePersonalizationInfo: AsyncMigration {
public func prepare(on database: any Database) async throws {
try await database.schema(Personalization.FieldKeys.schemaName)
try await database.schema(PersonalizationInfo.FieldKeys.schemaName)
.field(.id, .int, .identifier(auto: true))
.field(
Personalization.FieldKeys.passID, .uuid, .required,
PersonalizationInfo.FieldKeys.passID, .uuid, .required,
.references(Pass.FieldKeys.schemaName, .id, onDelete: .cascade)
)
.unique(on: Personalization.FieldKeys.passID)
.field(Personalization.FieldKeys.fullName, .string)
.field(Personalization.FieldKeys.givenName, .string)
.field(Personalization.FieldKeys.familyName, .string)
.field(Personalization.FieldKeys.emailAddress, .string)
.field(Personalization.FieldKeys.postalCode, .string)
.field(Personalization.FieldKeys.isoCountryCode, .string)
.field(Personalization.FieldKeys.phoneNumber, .string)
.unique(on: PersonalizationInfo.FieldKeys.passID)
.field(PersonalizationInfo.FieldKeys.fullName, .string)
.field(PersonalizationInfo.FieldKeys.givenName, .string)
.field(PersonalizationInfo.FieldKeys.familyName, .string)
.field(PersonalizationInfo.FieldKeys.emailAddress, .string)
.field(PersonalizationInfo.FieldKeys.postalCode, .string)
.field(PersonalizationInfo.FieldKeys.isoCountryCode, .string)
.field(PersonalizationInfo.FieldKeys.phoneNumber, .string)
.create()
}

public func revert(on database: any Database) async throws {
try await database.schema(Personalization.FieldKeys.schemaName).delete()
try await database.schema(PersonalizationInfo.FieldKeys.schemaName).delete()
}

public init() {}
}

extension Personalization {
extension PersonalizationInfo {
enum FieldKeys {
static let schemaName = "personalization_info"
static let passID = FieldKey(stringLiteral: "pass_id")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import FluentKit

/// Represents the `Model` that stores user personalization info.
public protocol PersonalizationModel: Model where IDValue == Int {
public protocol PersonalizationInfoModel: Model where IDValue == Int {
associatedtype PassType: PassModel

/// The pass this personalization info is associated with.
Expand Down Expand Up @@ -36,7 +36,7 @@ public protocol PersonalizationModel: Model where IDValue == Int {
var phoneNumber: String? { get set }
}

extension PersonalizationModel {
extension PersonalizationInfoModel {
public var _$id: ID<Int> {
guard let mirror = Mirror(reflecting: self).descendant("_id"),
let id = mirror as? ID<Int>
Expand Down
8 changes: 4 additions & 4 deletions Tests/FluentWalletPassesTests/FluentWalletPassesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ struct FluentWalletPassesTests {
try await migration.revert(on: test.db)
}

@Test("Personalization Concrete Model")
@Test("PersonalizationInfo Concrete Model")
func personalization() async throws {
let migration = CreatePersonalization()
let migration = CreatePersonalizationInfo()
try await migration.prepare(on: test.db)

let typeIdentifier = "Test Type Identifier"
Expand All @@ -91,7 +91,7 @@ struct FluentWalletPassesTests {
let isoCountryCode = "Test ISO Country Code"
let phoneNumber = "Test Phone Number"

let personalization = Personalization()
let personalization = PersonalizationInfo()
personalization.$pass.id = pass.id!
personalization.fullName = fullName
personalization.givenName = givenName
Expand All @@ -104,7 +104,7 @@ struct FluentWalletPassesTests {
TestOutput(personalization)
])

let fetchedPersonalization = try #require(await Personalization.query(on: test.db).first())
let fetchedPersonalization = try #require(await PersonalizationInfo.query(on: test.db).first())
#expect(fetchedPersonalization._$pass.id == pass.id)
#expect(fetchedPersonalization._$fullName.value == fullName)
#expect(fetchedPersonalization._$givenName.value == givenName)
Expand Down

0 comments on commit fbfe7eb

Please sign in to comment.