178 lines
4.2 KiB
Swift
178 lines
4.2 KiB
Swift
import DatabaseClient
|
|
import Fluent
|
|
import Foundation
|
|
import SharedModels
|
|
import Vapor
|
|
|
|
public extension DatabaseClient.Employees {
|
|
|
|
static func live(database: any Database) -> DatabaseClient.Employees {
|
|
.init { create in
|
|
let model = try create.toModel()
|
|
try await model.save(on: database)
|
|
return try model.toDTO()
|
|
} delete: { id in
|
|
guard let model = try await EmployeeModel.find(id, on: database) else {
|
|
throw NotFoundError()
|
|
}
|
|
try await model.delete(on: database)
|
|
} fetchAll: { request in
|
|
var query = EmployeeModel.query(on: database)
|
|
.sort(\.$lastName)
|
|
|
|
switch request {
|
|
case .active:
|
|
query = query.filter(\.$active == true)
|
|
case .inactive:
|
|
query = query.filter(\.$active == false)
|
|
case .all:
|
|
break
|
|
}
|
|
|
|
return try await query.all().map { try $0.toDTO() }
|
|
|
|
} get: { id in
|
|
try await EmployeeModel.find(id, on: database).map { try $0.toDTO() }
|
|
} update: { id, updates in
|
|
guard let model = try await EmployeeModel.find(id, on: database) else {
|
|
throw NotFoundError()
|
|
}
|
|
try model.applyUpdate(updates)
|
|
try await model.save(on: database)
|
|
return try model.toDTO()
|
|
}
|
|
}
|
|
}
|
|
|
|
private extension Employee.Create {
|
|
|
|
func toModel() throws -> EmployeeModel {
|
|
try validate()
|
|
return .init(firstName: firstName, lastName: lastName, active: active ?? true)
|
|
}
|
|
|
|
func validate() throws {
|
|
guard !firstName.isEmpty else {
|
|
throw ValidationError(message: "Employee first name should not be empty.")
|
|
}
|
|
guard !lastName.isEmpty else {
|
|
throw ValidationError(message: "Employee first name should not be empty.")
|
|
}
|
|
}
|
|
}
|
|
|
|
extension Employee.Update {
|
|
|
|
func validate() throws {
|
|
if let firstName {
|
|
guard !firstName.isEmpty else {
|
|
throw ValidationError(message: "Employee first name should not be empty.")
|
|
}
|
|
}
|
|
if let lastName {
|
|
guard !lastName.isEmpty else {
|
|
throw ValidationError(message: "Employee first name should not be empty.")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extension Employee {
|
|
|
|
struct Migrate: AsyncMigration {
|
|
|
|
let name = "CreateEmployee"
|
|
|
|
func prepare(on database: any Database) async throws {
|
|
try await database.schema(EmployeeModel.schema)
|
|
.id()
|
|
.field("first_name", .string, .required)
|
|
.field("last_name", .string, .required)
|
|
.field("is_active", .bool, .required)
|
|
.field("created_at", .datetime)
|
|
.field("updated_at", .datetime)
|
|
.unique(on: "first_name", "last_name")
|
|
.create()
|
|
}
|
|
|
|
func revert(on database: any Database) async throws {
|
|
try await database.schema(EmployeeModel.schema).delete()
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/// The employee database model.
|
|
///
|
|
/// An employee is someone that PO's can be generated for. They can be either a field
|
|
/// employee / technician, an office employee, or an administrator.
|
|
///
|
|
/// # NOTE: Only `User` types can login and generate po's for employees.
|
|
///
|
|
final class EmployeeModel: Model, @unchecked Sendable {
|
|
|
|
static let schema = "employee"
|
|
|
|
// @ID(key: ")
|
|
// var id: UUID?
|
|
@ID(key: .id)
|
|
var id: UUID?
|
|
|
|
@Field(key: "first_name")
|
|
var firstName: String
|
|
|
|
@Field(key: "last_name")
|
|
var lastName: String
|
|
|
|
@Field(key: "is_active")
|
|
var active: Bool
|
|
|
|
@Timestamp(key: "created_at", on: .create)
|
|
var createdAt: Date?
|
|
|
|
@Timestamp(key: "updated_at", on: .update)
|
|
var updatedAt: Date?
|
|
|
|
init() {}
|
|
|
|
init(
|
|
id: UUID? = nil,
|
|
firstName: String,
|
|
lastName: String,
|
|
active: Bool,
|
|
createdAt: Date? = nil,
|
|
updatedAt: Date? = nil
|
|
) {
|
|
self.id = id
|
|
self.firstName = firstName
|
|
self.lastName = lastName
|
|
self.active = active
|
|
self.createdAt = createdAt
|
|
self.updatedAt = updatedAt
|
|
}
|
|
|
|
func toDTO() throws -> Employee {
|
|
try .init(
|
|
id: requireID(),
|
|
active: active,
|
|
createdAt: createdAt!,
|
|
firstName: firstName,
|
|
lastName: lastName,
|
|
updatedAt: updatedAt!
|
|
)
|
|
}
|
|
|
|
func applyUpdate(_ updates: Employee.Update) throws {
|
|
try updates.validate()
|
|
if let firstName = updates.firstName {
|
|
self.firstName = firstName
|
|
}
|
|
if let lastName = updates.lastName {
|
|
self.lastName = lastName
|
|
}
|
|
if let active = updates.active {
|
|
self.active = active
|
|
}
|
|
}
|
|
}
|