Files
vapor-po/Sources/DatabaseClientLive/VendorBranches.swift

173 lines
4.2 KiB
Swift

import DatabaseClient
import FluentKit
import Foundation
import SharedModels
public extension DatabaseClient.VendorBranches {
static func live(database db: any Database) -> Self {
.init { create in
let model = try create.toModel()
try await model.save(on: db)
return try model.toDTO()
} delete: { id in
guard let model = try await VendorBranchModel.find(id, on: db) else {
throw NotFoundError()
}
try await model.delete(on: db)
} fetchAll: { request in
let query = VendorBranchModel.query(on: db)
switch request {
case .all:
break
case let .for(vendorID: vendorID):
let branches = try await VendorModel.query(on: db)
.filter(\.$id == vendorID)
.with(\.$branches)
.first()?
.branches
.map { try $0.toDTO() }
guard let branches else { throw NotFoundError() }
return branches
}
return try await query.all().map { try $0.toDTO() }
} fetchAllWithDetail: {
try await VendorBranchModel.query(on: db)
.with(\.$vendor)
.all()
.map { try $0.toDetail() }
} get: { id in
try await VendorBranchModel.find(id, on: db).map { try $0.toDTO() }
} update: { id, updates in
guard let model = try await VendorBranchModel.find(id, on: db) else {
throw NotFoundError()
}
try model.applyUpdates(updates)
try await model.save(on: db)
return try model.toDTO()
}
}
}
extension VendorBranch {
struct Migrate: AsyncMigration {
let name = "CreateVendorBranch"
fileprivate typealias FieldKey = VendorBranch.Key.Field
func prepare(on database: any Database) async throws {
try await database.schema(VendorBranchModel.schema)
.id()
.field(.string(FieldKey.name), .string, .required)
.field(.string(FieldKey.vendorID), .uuid, .required)
.field(.string(FieldKey.createdAt), .datetime)
.field(.string(FieldKey.updatedAt), .datetime)
.foreignKey(.string(FieldKey.vendorID), references: VendorModel.schema, "id", onDelete: .cascade)
.create()
}
func revert(on database: any Database) async throws {
try await database.schema(VendorBranchModel.schema).delete()
}
}
}
extension VendorBranch.Create {
func toModel() throws -> VendorBranchModel {
try validate()
return .init(name: name, vendorId: vendorID)
}
func validate() throws {
guard !name.isEmpty else {
throw ValidationError(message: "Vendor branch name should not be empty.")
}
}
}
extension VendorBranch.Update {
func validate() throws {
if let name {
guard !name.isEmpty else {
throw ValidationError(message: "Vendor branch name should not be empty.")
}
}
}
}
private extension VendorBranch {
enum Key {
static let schema = "vendor_branch"
enum Field {
static let createdAt = "created_at"
static let name = "name"
static let updatedAt = "updated_at"
static let vendorID = "vendor_id"
}
}
}
final class VendorBranchModel: Model, @unchecked Sendable {
fileprivate typealias FieldKey = VendorBranch.Key.Field
static let schema = VendorBranch.Key.schema
@ID(key: .id)
var id: UUID?
@Field(key: .string(FieldKey.name))
var name: String
@Timestamp(key: .string(FieldKey.createdAt), on: .create)
var createdAt: Date?
@Timestamp(key: .string(FieldKey.updatedAt), on: .update)
var updatedAt: Date?
@Parent(key: .string(FieldKey.vendorID))
var vendor: VendorModel
init() {}
init(id: UUID? = nil, name: String, vendorId: Vendor.ID) {
self.id = id
self.name = name
$vendor.id = vendorId
}
func toDTO() throws -> VendorBranch {
try .init(
id: requireID(),
name: name,
vendorID: $vendor.id,
createdAt: createdAt,
updatedAt: updatedAt
)
}
func toDetail() throws -> VendorBranch.Detail {
try .init(
id: requireID(),
name: name,
vendor: vendor.toDTO(),
createdAt: createdAt,
updatedAt: updatedAt
)
}
func applyUpdates(_ updates: VendorBranch.Update) throws {
try updates.validate()
if let name = updates.name {
self.name = name
}
}
}