-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a0dbb52
commit 436520c
Showing
7 changed files
with
402 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import Fluent | ||
import struct Foundation.UUID | ||
import Orders | ||
import Vapor | ||
|
||
final class OrderData: OrderDataModel, @unchecked Sendable { | ||
static let schema = OrderData.vddMMyyyy.schemaName | ||
|
||
@ID(key: .id) | ||
var id: UUID? | ||
|
||
@Field(key: OrderData.vddMMyyyy.title) | ||
var title: String | ||
|
||
@Parent(key: OrderData.vddMMyyyy.orderID) | ||
var order: Order | ||
|
||
init() { } | ||
|
||
init(id: UUID? = nil, title: String) { | ||
self.id = id | ||
self.title = title | ||
} | ||
|
||
func toDTO() -> OrderDataDTO { | ||
.init( | ||
id: self.id, | ||
title: self.$title.value | ||
) | ||
} | ||
} | ||
|
||
struct OrderDataDTO: Content { | ||
var id: UUID? | ||
var title: String? | ||
|
||
func toModel() -> OrderData { | ||
let model = OrderData() | ||
|
||
model.id = self.id | ||
if let title = self.title { | ||
model.title = title | ||
} | ||
return model | ||
} | ||
} | ||
|
||
struct CreateOrderData: AsyncMigration { | ||
func prepare(on database: any Database) async throws { | ||
try await database.schema(OrderData.vddMMyyyy.schemaName) | ||
.id() | ||
.field(OrderData.vddMMyyyy.title, .string, .required) | ||
.field(OrderData.vddMMyyyy.orderID, .uuid, .required, .references(Order.schema, .id, onDelete: .cascade)) | ||
.create() | ||
} | ||
|
||
func revert(on database: any Database) async throws { | ||
try await database.schema(OrderData.vddMMyyyy.schemaName).delete() | ||
} | ||
} | ||
|
||
extension OrderData { | ||
enum vddMMyyyy { | ||
static let schemaName = "order_data" | ||
static let title = FieldKey(stringLiteral: "title") | ||
static let orderID = FieldKey(stringLiteral: "order_id") | ||
} | ||
} | ||
|
||
struct OrderJSONData: OrderJSON.Properties { | ||
let schemaVersion = OrderJSON.SchemaVersion.v1 | ||
let orderTypeIdentifier = "order.com.example.pet-store" | ||
let orderIdentifier: String | ||
let orderType = OrderJSON.OrderType.ecommerce | ||
let orderNumber = "HM090772020864" | ||
let createdAt: String | ||
let updatedAt: String | ||
let status = OrderJSON.OrderStatus.open | ||
let merchant: MerchantData | ||
let orderManagementURL = "https://www.example.com/" | ||
let authenticationToken: String | ||
|
||
private let webServiceURL = "https://www.example.com/api/orders/" | ||
|
||
struct MerchantData: OrderJSON.Merchant { | ||
let merchantIdentifier = "com.example.pet-store" | ||
let displayName: String | ||
let url = "https://www.example.com/" | ||
let logo = "pet_store_logo.png" | ||
} | ||
|
||
init(data: OrderData, order: Order) { | ||
self.orderIdentifier = order.id!.uuidString | ||
self.authenticationToken = order.authenticationToken | ||
self.merchant = MerchantData(displayName: data.title) | ||
let dateFormatter = ISO8601DateFormatter() | ||
dateFormatter.formatOptions = .withInternetDateTime | ||
self.createdAt = dateFormatter.string(from: order.createdAt!) | ||
self.updatedAt = dateFormatter.string(from: order.updatedAt!) | ||
} | ||
} | ||
|
||
struct OrderDataMiddleware: AsyncModelMiddleware { | ||
private unowned let service: OrdersService | ||
|
||
init(service: OrdersService) { | ||
self.service = service | ||
} | ||
|
||
func create(model: OrderData, on db: any Database, next: any AnyAsyncModelResponder) async throws { | ||
let order = Order( | ||
orderTypeIdentifier: "order.com.example.pet-store", | ||
authenticationToken: Data([UInt8].random(count: 12)).base64EncodedString()) | ||
try await order.save(on: db) | ||
model.$order.id = try order.requireID() | ||
try await next.create(model, on: db) | ||
} | ||
|
||
func update(model: OrderData, on db: any Database, next: any AnyAsyncModelResponder) async throws { | ||
let order = try await model.$order.get(on: db) | ||
order.updatedAt = Date() | ||
try await order.save(on: db) | ||
try await next.update(model, on: db) | ||
try await service.sendPushNotifications(for: order, on: db) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import Vapor | ||
import Fluent | ||
import Orders | ||
|
||
final class OrderDelegate: OrdersDelegate { | ||
let sslSigningFilesDirectory = URL(fileURLWithPath: "Certificates/Orders/", isDirectory: true) | ||
|
||
let pemPrivateKeyPassword: String? = "password" | ||
|
||
func encode<O: OrderModel>(order: O, db: any Database, encoder: JSONEncoder) async throws -> Data { | ||
guard let orderData = try await OrderData.query(on: db) | ||
.filter(\.$order.$id == order.requireID()) | ||
.with(\.$order) | ||
.first() | ||
else { | ||
throw Abort(.internalServerError) | ||
} | ||
guard let data = try? encoder.encode(OrderJSONData(data: orderData, order: orderData.order)) else { | ||
throw Abort(.internalServerError) | ||
} | ||
return data | ||
} | ||
|
||
func template<O: OrderModel>(for: O, db: any Database) async throws -> URL { | ||
return URL(fileURLWithPath: "Templates/Orders/", isDirectory: true) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,27 @@ | ||
import XCTVapor | ||
import Fluent | ||
import FluentSQLiteDriver | ||
@testable import Orders | ||
|
||
final class OrdersTests: XCTestCase { | ||
func testExample() { | ||
// This is an example of a functional test case. | ||
// Use XCTAssert and related functions to verify your tests produce the correct | ||
// results. | ||
//XCTAssertEqual(OrdersService().text, "Hello, World!") | ||
var app: Application! | ||
let orderDelegate = OrderDelegate() | ||
|
||
override func setUp() async throws { | ||
self.app = try await Application.make(.testing) | ||
|
||
app.databases.use(.sqlite(.memory), as: .sqlite) | ||
OrdersService.register(migrations: app.migrations) | ||
app.migrations.add(CreateOrderData()) | ||
let ordersService = try OrdersService(app: app, delegate: orderDelegate) | ||
app.databases.middleware.use(OrderDataMiddleware(service: ordersService), on: .sqlite) | ||
|
||
try await app.autoMigrate() | ||
} | ||
|
||
override func tearDown() async throws { | ||
try await app.autoRevert() | ||
try await self.app.asyncShutdown() | ||
self.app = nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
import Fluent | ||
import struct Foundation.UUID | ||
import Passes | ||
import Vapor | ||
|
||
final class PassData: PassDataModel, @unchecked Sendable { | ||
static let schema = PassData.vddMMyyyy.schemaName | ||
|
||
@ID(key: .id) | ||
var id: UUID? | ||
|
||
@Field(key: PassData.vddMMyyyy.title) | ||
var title: String | ||
|
||
@Parent(key: PassData.vddMMyyyy.passID) | ||
var pass: PKPass | ||
|
||
init() { } | ||
|
||
init(id: UUID? = nil, title: String) { | ||
self.id = id | ||
self.title = title | ||
} | ||
|
||
func toDTO() -> PassDataDTO { | ||
.init( | ||
id: self.id, | ||
title: self.$title.value | ||
) | ||
} | ||
} | ||
|
||
struct PassDataDTO: Content { | ||
var id: UUID? | ||
var title: String? | ||
|
||
func toModel() -> PassData { | ||
let model = PassData() | ||
|
||
model.id = self.id | ||
if let title = self.title { | ||
model.title = title | ||
} | ||
return model | ||
} | ||
} | ||
|
||
struct CreatePassData: AsyncMigration { | ||
func prepare(on database: any Database) async throws { | ||
try await database.schema(PassData.vddMMyyyy.schemaName) | ||
.id() | ||
.field(PassData.vddMMyyyy.title, .string, .required) | ||
.field(PassData.vddMMyyyy.passID, .uuid, .required, .references(PKPass.schema, .id, onDelete: .cascade)) | ||
.create() | ||
} | ||
|
||
func revert(on database: any Database) async throws { | ||
try await database.schema(PassData.vddMMyyyy.schemaName).delete() | ||
} | ||
} | ||
|
||
extension PassData { | ||
enum vddMMyyyy { | ||
static let schemaName = "pass_data" | ||
static let title = FieldKey(stringLiteral: "title") | ||
static let passID = FieldKey(stringLiteral: "pass_id") | ||
} | ||
} | ||
|
||
struct PassJSONData: PassJSON.Properties { | ||
let description: String | ||
let formatVersion = PassJSON.FormatVersion.v1 | ||
let organizationName = "vapor-community" | ||
let passTypeIdentifier = "pass.com.vapor-community.pass" | ||
let serialNumber: String | ||
let teamIdentifier = "ABCD1234" | ||
|
||
private let webServiceURL = "https://www.example.com/api/passes/" | ||
private let authenticationToken: String | ||
private let logoText = "Vapor" | ||
private let sharingProhibited = true | ||
let backgroundColor = "rgb(207, 77, 243)" | ||
let foregroundColor = "rgb(255, 255, 255)" | ||
|
||
let barcodes = Barcode(message: "test") | ||
struct Barcode: PassJSON.Barcodes { | ||
let format = PassJSON.BarcodeFormat.qr | ||
let message: String | ||
let messageEncoding = "iso-8859-1" | ||
} | ||
|
||
let boardingPass = Boarding(transitType: .air) | ||
struct Boarding: PassJSON.BoardingPass { | ||
let transitType: PassJSON.TransitType | ||
let headerFields: [PassField] | ||
let primaryFields: [PassField] | ||
let secondaryFields: [PassField] | ||
let auxiliaryFields: [PassField] | ||
let backFields: [PassField] | ||
|
||
struct PassField: PassJSON.PassFieldContent { | ||
let key: String | ||
let label: String | ||
let value: String | ||
} | ||
|
||
init(transitType: PassJSON.TransitType) { | ||
self.headerFields = [.init(key: "header", label: "Header", value: "Header")] | ||
self.primaryFields = [.init(key: "primary", label: "Primary", value: "Primary")] | ||
self.secondaryFields = [.init(key: "secondary", label: "Secondary", value: "Secondary")] | ||
self.auxiliaryFields = [.init(key: "auxiliary", label: "Auxiliary", value: "Auxiliary")] | ||
self.backFields = [.init(key: "back", label: "Back", value: "Back")] | ||
self.transitType = transitType | ||
} | ||
} | ||
|
||
init(data: PassData, pass: PKPass) { | ||
self.description = data.title | ||
self.serialNumber = pass.id!.uuidString | ||
self.authenticationToken = pass.authenticationToken | ||
} | ||
} | ||
|
||
struct PersonalizationJSONData: PersonalizationJSON.Properties { | ||
var requiredPersonalizationFields = [ | ||
PersonalizationJSON.PersonalizationField.name, | ||
PersonalizationJSON.PersonalizationField.postalCode, | ||
PersonalizationJSON.PersonalizationField.emailAddress, | ||
PersonalizationJSON.PersonalizationField.phoneNumber | ||
] | ||
var description = "Hello, World!" | ||
} | ||
|
||
struct PassDataMiddleware: AsyncModelMiddleware { | ||
private unowned let service: PassesService | ||
|
||
init(service: PassesService) { | ||
self.service = service | ||
} | ||
|
||
func create(model: PassData, on db: any Database, next: any AnyAsyncModelResponder) async throws { | ||
let pkPass = PKPass( | ||
passTypeIdentifier: "pass.com.vapor-community.pass", | ||
authenticationToken: Data([UInt8].random(count: 12)).base64EncodedString()) | ||
try await pkPass.save(on: db) | ||
model.$pass.id = try pkPass.requireID() | ||
try await next.create(model, on: db) | ||
} | ||
|
||
func update(model: PassData, on db: any Database, next: any AnyAsyncModelResponder) async throws { | ||
let pkPass = try await model.$pass.get(on: db) | ||
pkPass.updatedAt = Date() | ||
try await pkPass.save(on: db) | ||
try await next.update(model, on: db) | ||
try await service.sendPushNotifications(for: pkPass, on: db) | ||
} | ||
} |
Oops, something went wrong.