// // FuelEntryController.swift // // // Created by Bill Ryckman on 4/24/23. // import Vapor import FluentKit struct FuelEntryV2Controller: RouteCollection { func boot(routes: RoutesBuilder) throws { let fuelEntries = routes.grouped("fuel_entries") let tokenAuthMiddleware = Token.authenticator() let guardMiddleware = User.guardMiddleware() let tokenAuthGroup = fuelEntries.grouped(tokenAuthMiddleware, guardMiddleware) tokenAuthGroup.get(use: index) tokenAuthGroup.get("test", use: filtered) tokenAuthGroup.get("rpm", use: rpm) tokenAuthGroup.get("maxim", use: filtered) tokenAuthGroup.post(use: create) tokenAuthGroup.put( use: softdelete) tokenAuthGroup.group(":fuelEntryID") { fuelEntry in fuelEntry.delete(use: delete) } } func index(req: Request) async throws -> [FuelEntry] { return try await FuelEntry.query(on: req.db).all() } struct filteredreturn: Content{ var fuelentries: [FuelEntry] var pages: Int } struct dload: Content{ var id: UUID } @Sendable func softdelete(req: Request) async throws -> Response { let ids = try req.content.decode([dload].self) var msg: [String] = [] for id in ids { guard let fe = try await FuelEntry.find(id.id, on: req.db) else { msg.append("create error message for item") continue } fe.downloaded = true try await fe.save(on: req.db) } let response = Response(status: .ok, body: "good") return response } fileprivate func parseDate(_ dateString: String, _ start: Bool = true) -> Date? { if(dateString.count == 0){ return nil } else { let parts = dateString.split(separator: "-") let year = Int(parts[0])! let month = Int(parts[1])! let day = Int(parts[2])! var dateComponents = DateComponents() dateComponents.year = year dateComponents.month = month dateComponents.day = day if(start) { dateComponents.hour = 0 dateComponents.minute = 0 dateComponents.second = 0 } else { dateComponents.hour = 23 dateComponents.minute = 59 dateComponents.second = 59 } let calendar = Calendar(identifier: .gregorian) return calendar.date(from: dateComponents) } } @Sendable func filtered(req: Request) async throws -> Response { let qstring = req.query let startdate = try parseDate(qstring.get(String?.self, at: "startdate") ?? "") let enddate = try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false) let image = try qstring.get(Bool?.self, at: "image") ?? false let serial = try qstring.get(String?.self, at: "serial") ?? nil let tank = try qstring.get(String?.self, at: "tank") ?? nil let previous = try qstring.get(Bool?.self, at: "previous") ?? false var query = FuelEntry.query(on: req.db) if(image){ query = query .field(\.$id) .field(\.$timestamp) .field(\.$userID) .field(\.$product) .field(\.$make) .field(\.$model) .field(\.$serialNumber) .field(\.$tankID) .field(\.$fuelAmount) .field(\.$fuelType) .field(\.$isOverride) .field(\.$latitude) .field(\.$longitude) .field(\.$image) .field(\.$downloaded) .field(\.$loaddate) //.filter(\.$image != nil) } else { query = query .field(\.$id) .field(\.$timestamp) .field(\.$userID) .field(\.$product) .field(\.$make) .field(\.$model) .field(\.$serialNumber) .field(\.$tankID) .field(\.$fuelAmount) .field(\.$fuelType) .field(\.$isOverride) .field(\.$latitude) .field(\.$longitude) .field(\.$downloaded) .field(\.$loaddate) } query = query.group(.and){ grp in if( startdate != nil) { grp.filter(\.$loaddate >= startdate!) } if( enddate != nil) { grp.filter(\.$loaddate <= enddate!) } if( serial != nil) { grp.filter(\.$serialNumber == serial!) } if( tank != nil) { grp.filter(\.$tankID == tank!) } if(!previous){ grp.filter(\.$pulldate == nil) } } query = query.sort(\.$loaddate, .ascending) if(image){ //query = query.filter(\.$image) let wimage = try await query.paginate(for: req).map{ img in FuelEntry.wimage(id: img.id, timestamp: img.timestamp, userID: img.userID, latitude: img.latitude, longitutde: img.longitude, product: img.product, make: img.make, model: img.model, serialNumber: img.serialNumber, tankID: img.tankID, fuelAmount: img.fuelAmount, fuelType: img.fuelType, isOverride: img.isOverride, image: img.image == nil ? Data(): img.image, downloaded: img.downloaded == nil ? false : img.downloaded!, loaddate: img.loaddate == nil ? nil : img.loaddate, pulldate: Date()) } wimage.items.forEach{ _ = $0.toFuelEntry().save(on: req.db) } return try await wimage.encodeResponse(for: req) } else { let woimage = try await query.paginate(for: req).map{ img in FuelEntry.woimage(id: img.id, timestamp: img.timestamp, userID: img.userID, latitude: img.latitude, longitutde: img.longitude, product: img.product, make: img.make, model: img.model, serialNumber: img.serialNumber, tankID: img.tankID, fuelAmount: img.fuelAmount, fuelType: img.fuelType, isOverride: img.isOverride, downloaded: img.downloaded == nil ? false : img.downloaded!, loaddate: img.loaddate == nil ? nil : img.loaddate, pulldate: Date()) } woimage.items.forEach { _ = $0.toFuelEntry().save(on: req.db) } return try await woimage.encodeResponse(for: req) } } @Sendable func rpm(req: Request) async throws -> Response { let qstring = req.query let startdate = try parseDate(qstring.get(String?.self, at: "startdate") ?? "") let enddate = try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false) let image = try qstring.get(Bool?.self, at: "image") ?? false let serial = try qstring.get(String?.self, at: "serial") ?? nil let tank = try qstring.get(String?.self, at: "tank") ?? nil let previous = try qstring.get(Bool?.self, at: "previous") ?? false var query = FuelEntry.query(on: req.db) if(image){ query = query .field(\.$id) .field(\.$timestamp) .field(\.$userID) .field(\.$product) .field(\.$make) .field(\.$model) .field(\.$serialNumber) .field(\.$tankID) .field(\.$fuelAmount) .field(\.$fuelType) .field(\.$isOverride) .field(\.$latitude) .field(\.$longitude) .field(\.$image) .field(\.$downloaded) .field(\.$loaddate) //.filter(\.$image != nil) } else { query = query .field(\.$id) .field(\.$timestamp) .field(\.$userID) .field(\.$product) .field(\.$make) .field(\.$model) .field(\.$serialNumber) .field(\.$tankID) .field(\.$fuelAmount) .field(\.$fuelType) .field(\.$isOverride) .field(\.$latitude) .field(\.$longitude) .field(\.$downloaded) .field(\.$loaddate) } query = query.group(.and){ grp in if( startdate != nil) { grp.filter(\.$loaddate >= startdate!) } if( enddate != nil) { grp.filter(\.$loaddate <= enddate!) } if( serial != nil) { grp.filter(\.$serialNumber == serial!) } if( tank != nil) { grp.filter(\.$tankID == tank!) } if(!previous){ grp.filter(\.$pulldate == nil) } } query = query.sort(\.$loaddate, .ascending).sort(\.$timestamp).sort(\.$serialNumber) if(image){ //query = query.filter(\.$image) let wimage = try await query.paginate(for: req).map{ img in FuelEntry.wimage(id: img.id, timestamp: img.timestamp, userID: img.userID, latitude: img.latitude, longitutde: img.longitude, product: img.product, make: img.make, model: img.model, serialNumber: img.serialNumber, tankID: img.tankID, fuelAmount: img.fuelAmount, fuelType: img.fuelType, isOverride: img.isOverride, image: img.image == nil ? Data(): img.image, downloaded: img.downloaded == nil ? false : img.downloaded!, loaddate: img.loaddate == nil ? nil : img.loaddate, pulldate: Date()) } return try await wimage.encodeResponse(for: req) } else { let woimage = try await query.paginate(for: req).map{ img in FuelEntry.woimage(id: img.id, timestamp: img.timestamp, userID: img.userID, latitude: img.latitude, longitutde: img.longitude, product: img.product, make: img.make, model: img.model, serialNumber: img.serialNumber, tankID: img.tankID, fuelAmount: img.fuelAmount, fuelType: img.fuelType, isOverride: img.isOverride, downloaded: img.downloaded == nil ? false : img.downloaded!, loaddate: img.loaddate == nil ? nil : img.loaddate, pulldate: Date()) } return try await woimage.encodeResponse(for: req) } } func create(req: Request) async throws -> [FuelEntry] { let fuelEntry = try req.content.decode([FuelEntry].self) try await fuelEntry.create(on: req.db) return fuelEntry } func delete(req: Request) async throws -> HTTPStatus { guard let fuelEntry = try await FuelEntry.find(req.parameters.get("fuelEntryID"), on: req.db) else { throw Abort(.notFound) } try await fuelEntry.delete(on: req.db) return .noContent } } struct PageRequest: Content { var page: Int var size: Int // Add any other properties needed for pagination init(page: Int, size: Int) { self.page = page self.size = size } }