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 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 var query = VendorBranchModel.query(on: db) switch request { case .all: break case .withVendor: query = query.with(\.$vendor) case let .for(vendorID: vendorID): let branches = try await VendorModel.query(on: db) .filter(\.$id == vendorID) .with(\.$branches) .first()? .branches .map { $0.toDTO() } guard let branches else { throw NotFoundError() } return branches } return try await query.all().map { $0.toDTO() } } get: { id in try await VendorBranchModel.find(id, on: db).map { $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 model.toDTO() } } } extension VendorBranch { struct Migrate: AsyncMigration { let name = "CreateVendorBranch" func prepare(on database: Database) async throws { try await database.schema(VendorBranchModel.schema) .id() .field("name", .string, .required) .field("vendor_id", .uuid, .required) .field("created_at", .datetime) .field("updated_at", .datetime) .foreignKey("vendor_id", references: VendorModel.schema, "id", onDelete: .cascade) .create() } func revert(on database: 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.") } } } } final class VendorBranchModel: Model, @unchecked Sendable { static let schema = "vendor_branch" @ID(key: .id) var id: UUID? @Field(key: "name") var name: String @Timestamp(key: "created_at", on: .create) var createdAt: Date? @Timestamp(key: "updated_at", on: .update) var updatedAt: Date? @Parent(key: "vendor_id") var vendor: VendorModel init() {} init(id: UUID? = nil, name: String, vendorId: Vendor.ID) { self.id = id self.name = name $vendor.id = vendorId } func toDTO() -> VendorBranch { .init( id: id, name: name, vendorID: $vendor.id, createdAt: createdAt, updatedAt: updatedAt ) } func applyUpdates(_ updates: VendorBranch.Update) throws { try updates.validate() if let name = updates.name { self.name = name } } }