|
|
@@ -1,7 +1,799 @@ |
|
|
// |
|
|
// |
|
|
// FuelEntryControllerV2.1.swift |
|
|
|
|
|
|
|
|
// FuelEntryControllerV2_1.swift |
|
|
// Fueling |
|
|
// Fueling |
|
|
// |
|
|
// |
|
|
// Created by Michiel Carman on 9/15/26. |
|
|
// Created by Michiel Carman on 9/15/26. |
|
|
// |
|
|
// |
|
|
|
|
|
|
|
|
|
|
|
import Vapor |
|
|
|
|
|
import FluentKit |
|
|
|
|
|
import FluentSQL |
|
|
|
|
|
|
|
|
|
|
|
struct FuelEntryV2ControllerV2_1: 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: filterLoadDate) |
|
|
|
|
|
tokenAuthGroup.get("main", use: filterLoadDate) |
|
|
|
|
|
tokenAuthGroup.get("timestamp", use: filterTimeStamp) |
|
|
|
|
|
tokenAuthGroup.get("images", use: filterImages) |
|
|
|
|
|
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) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
@Sendable |
|
|
|
|
|
func index(req: Request) async throws -> Response { |
|
|
|
|
|
return try await FuelEntry.query(on: req.db).all().map{ |
|
|
|
|
|
try FuelEntry.V2_1_Output.init(from: $0) |
|
|
|
|
|
}.encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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 queryParamExists(_ req: Request, _ param: String) async throws -> Bool { |
|
|
|
|
|
let x = try req.query.get(Bool.self, at: param) ? true : false |
|
|
|
|
|
|
|
|
|
|
|
print ("x: \(x)") |
|
|
|
|
|
return x |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fileprivate func parseDate2(_ dateString: String, _ start: Bool = true) throws -> Date? { |
|
|
|
|
|
let currentDate = Calendar.current.startOfDay(for: Date()) |
|
|
|
|
|
if(dateString.count == 0 && start){ |
|
|
|
|
|
if(start) { |
|
|
|
|
|
return Calendar.current.date(byAdding: .day, value: -2, to: currentDate) |
|
|
|
|
|
} else { |
|
|
|
|
|
return currentDate |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
let parts = dateString.split(separator: "-") |
|
|
|
|
|
if(parts.count != 3) { |
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
let year = Int(parts[0]) ?? nil |
|
|
|
|
|
if(year == nil) { |
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
let month = Int(parts[1]) ?? nil |
|
|
|
|
|
if(month == nil) { |
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
let day = Int(parts[2]) ?? nil |
|
|
|
|
|
if( day == nil ) { |
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
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) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fileprivate func parseDate(_ dateString: String, _ start: Bool = true) throws -> Date? { |
|
|
|
|
|
|
|
|
|
|
|
if(dateString.count == 0){ |
|
|
|
|
|
return nil |
|
|
|
|
|
} else { |
|
|
|
|
|
let parts = dateString.split(separator: "-") |
|
|
|
|
|
if(parts.count != 3) { |
|
|
|
|
|
throw Abort(.custom(code: 400,reasonPhrase: "Value at path '\(start ? "startdate" : "enddate")' was not of format 'yyyy-MM-dd'. Data found at '\(start ? "startdate" : "enddate")' was not properly formatted.")) |
|
|
|
|
|
} |
|
|
|
|
|
let year = Int(parts[0]) ?? nil |
|
|
|
|
|
if(year == nil) { |
|
|
|
|
|
throw Abort(.custom(code: 400,reasonPhrase: "Value at path '\(start ? "startdate" : "enddate")' was not of format 'yyyy-MM-dd'. Data found at '\(start ? "startdate" : "enddate")' was not properly formatted. Year component must be in the format yyyy and must be an integer")) |
|
|
|
|
|
} |
|
|
|
|
|
let month = Int(parts[1]) ?? nil |
|
|
|
|
|
if(month == nil) { |
|
|
|
|
|
throw Abort(.custom(code: 400,reasonPhrase: "Value at path '\(start ? "startdate" : "enddate")' was not of format 'yyyy-MM-dd'. Data found at '\(start ? "startdate" : "enddate")' was not properly formatted. Month component must be in the format MM and must be an integer")) |
|
|
|
|
|
} |
|
|
|
|
|
let day = Int(parts[2]) ?? nil |
|
|
|
|
|
if( day == nil ) { |
|
|
|
|
|
throw Abort(.custom(code: 400,reasonPhrase: "Value at path '\(start ? "startdate" : "enddate")' was not of format 'yyyy-MM-dd'. Data found at '\(start ? "startdate" : "enddate")' was not properly formatted. Day component must be in the format dd and must be an integer")) |
|
|
|
|
|
} |
|
|
|
|
|
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) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fileprivate func generateSQLNoImage(_ startdate: Date? = nil, _ enddate: Date? = nil) -> SQLQueryString { |
|
|
|
|
|
if(startdate == nil) { |
|
|
|
|
|
return SQLQueryString("select count(*) as total from \"fuel_entries\";") |
|
|
|
|
|
} |
|
|
|
|
|
if(enddate != nil) { |
|
|
|
|
|
return SQLQueryString("select count(*) as total from \"fuel_entries\" where \"loadDate\" >= \(bind: startdate) and \"loadDate\" <= \(bind: enddate) ;") |
|
|
|
|
|
} else { |
|
|
|
|
|
return SQLQueryString("select count(*) as total from \"fuel_entries\" where \"loadDate\" >= \(bind: startdate);") |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fileprivate func generateSQLImage(_ startdate: Date? = nil, _ enddate: Date? = nil) -> SQLQueryString { |
|
|
|
|
|
var sql: String = "" |
|
|
|
|
|
if(startdate == nil) { |
|
|
|
|
|
return SQLQueryString("select count(*) as total from \"fuel_entries\" where \"image\" is not null;") |
|
|
|
|
|
} |
|
|
|
|
|
if(enddate != nil) { |
|
|
|
|
|
sql = "select count(*) as total from \"fuel_entries\" where \"loadDate\" >= \(String(describing: startdate)) and \"loadDate\" <= \(String(describing: enddate)) and \"image\" is not null;" |
|
|
|
|
|
return SQLQueryString("select count(*) as total from \"fuel_entries\" where \"loadDate\" >= \(bind: startdate) and \"loadDate\" <= \(bind: enddate) and \"image\" is not null;") |
|
|
|
|
|
} else { |
|
|
|
|
|
sql = "select count(*) as total from \"fuel_entries\" where \"image\" is not null and \"loadDate\" >= '\(startdate ?? Date())';" |
|
|
|
|
|
return SQLQueryString(sql) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct CountRecords: Content { |
|
|
|
|
|
let total: Int |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fileprivate func getCount(_ req: Request, _ sql: SQLQueryString) async throws -> Int { |
|
|
|
|
|
print(sql) |
|
|
|
|
|
if let db = req.db as? SQLDatabase { |
|
|
|
|
|
let answer = try await db |
|
|
|
|
|
.raw(sql) |
|
|
|
|
|
.first(decoding: CountRecords.self) |
|
|
|
|
|
return answer?.total ?? 0 |
|
|
|
|
|
} else { |
|
|
|
|
|
return 0 |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fileprivate func getPaging(_ page: Int, _ per: Int, _ records: Int) async throws -> [String: Any] { |
|
|
|
|
|
var vals: [String: Any] = [:] |
|
|
|
|
|
vals["page"] = page |
|
|
|
|
|
vals["per"] = per |
|
|
|
|
|
vals["records"] = records |
|
|
|
|
|
let lastpage = Int(ceil(Double(records) / Double(per))) |
|
|
|
|
|
vals["lastpage"] = (page == lastpage) ? true : false |
|
|
|
|
|
vals["offset"] = ( page * per) - per |
|
|
|
|
|
return vals |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fileprivate func getParams(_ req: Request) async throws -> [qparam] { |
|
|
|
|
|
let urlComponents = URLComponents(string: req.url.description)! |
|
|
|
|
|
var params: [qparam] = [] |
|
|
|
|
|
for queryItem in urlComponents.queryItems ?? [] { |
|
|
|
|
|
params.append(qparam(name: queryItem.name, value: queryItem.value ?? "")) |
|
|
|
|
|
} |
|
|
|
|
|
return params |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fileprivate func getMaximError(_ req: Request, _ message: String) async throws -> returnObjV2_1 { |
|
|
|
|
|
let rt = req.route!.description.replacingOccurrences(of: "GET ", with: "").replacingOccurrences(of: "PUT ", with: "").replacingOccurrences(of: "POST ", with: "").replacingOccurrences(of: "DELETE ", with: "") |
|
|
|
|
|
let method = req.method.rawValue |
|
|
|
|
|
let baseurl = "https://fueling.prelub.com" |
|
|
|
|
|
let data : [FuelEntry.V2_1_Output] = [] |
|
|
|
|
|
let meta = Meta(page: 0, per: 0, total: 0, lastpage: true, error: true, message: message, method: method, baseurl: baseurl, route: rt, querystring: "" ) |
|
|
|
|
|
return returnObjV2_1(data: data, meta: meta) |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Sendable |
|
|
|
|
|
func filterLoadDate(req: Request) async throws -> Response { |
|
|
|
|
|
let rt = req.route!.description.replacingOccurrences(of: "GET ", with: "").replacingOccurrences(of: "PUT ", with: "").replacingOccurrences(of: "POST ", with: "").replacingOccurrences(of: "DELETE ", with: "") |
|
|
|
|
|
let method = req.method.rawValue |
|
|
|
|
|
let baseurl = "https://fueling.prelub.com" |
|
|
|
|
|
|
|
|
|
|
|
let qstring = req.query |
|
|
|
|
|
let components: Dictionary<String, String?> = try req.query.decode(Dictionary<String, String?>.self) |
|
|
|
|
|
|
|
|
|
|
|
var startdate : Date? |
|
|
|
|
|
var qs: [String] = [] |
|
|
|
|
|
for component in components { |
|
|
|
|
|
qs.append( "\(component.key)=\(component.value ?? "nil")") |
|
|
|
|
|
} |
|
|
|
|
|
if(try qstring.get(String?.self, at: "startdate") != nil) { |
|
|
|
|
|
startdate = try parseDate2(qstring.get(String?.self, at: "startdate") ?? "") |
|
|
|
|
|
if(startdate == nil) { |
|
|
|
|
|
return try await(getMaximError(req, "startdate is invalid format. YYYY-MM-DD")) .encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
//throw error |
|
|
|
|
|
return try await getMaximError(req, "startdate is required").encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
var enddate : Date?//= try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false) |
|
|
|
|
|
if(try qstring.get(String?.self, at: "enddate") != nil) { |
|
|
|
|
|
enddate = try parseDate2(qstring.get(String?.self, at: "enddate") ?? "", false) |
|
|
|
|
|
if(enddate == nil) { |
|
|
|
|
|
return try await getMaximError(req, "enddate is invalid format. YYYY-MM-DD").encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
let emptyData: Data? = Data() |
|
|
|
|
|
let page = try qstring.get(Int?.self, at: "page") ?? 1 |
|
|
|
|
|
let per = try qstring.get(Int?.self, at: "per") ?? 10 |
|
|
|
|
|
let qsStr = qs.joined(separator: "&") |
|
|
|
|
|
|
|
|
|
|
|
let records = try await getCount(req, generateSQLNoImage(startdate ?? nil, enddate ?? nil) ) |
|
|
|
|
|
|
|
|
|
|
|
let paging = try await getPaging(page, per, records) |
|
|
|
|
|
let meta = Meta(page: page, per: per, total: records, lastpage: (paging["lastpage"] != nil) ? paging["lastpage"] as! Bool : false, error: false, message: "", method: method, baseurl: baseurl, route: rt, querystring: "?\(qsStr)") |
|
|
|
|
|
let query = try await FuelEntry.query(on: req.db) |
|
|
|
|
|
.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) |
|
|
|
|
|
.field(\.$tabletserial) |
|
|
|
|
|
.group(.and) { |
|
|
|
|
|
grp in |
|
|
|
|
|
grp.filter(\.$loaddate >= startdate) |
|
|
|
|
|
if( enddate != nil) { |
|
|
|
|
|
grp.filter(\.$loaddate <= enddate!) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
.sort(\.$loaddate, .ascending) |
|
|
|
|
|
.range(lower: (paging["offset"] as! Int), upper: (paging["offset"] as! Int) + (paging["per"] as! Int)) |
|
|
|
|
|
.all().map{ |
|
|
|
|
|
try FuelEntry.V2_1_Output.init(from: $0) |
|
|
|
|
|
} |
|
|
|
|
|
let response = returnObjV2_1(data: query, meta: meta) |
|
|
|
|
|
return try await response.encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Sendable |
|
|
|
|
|
func filterImages(req: Request) async throws -> Response { |
|
|
|
|
|
let rt = req.route!.description.replacingOccurrences(of: "GET ", with: "").replacingOccurrences(of: "PUT ", with: "").replacingOccurrences(of: "POST ", with: "").replacingOccurrences(of: "DELETE ", with: "") |
|
|
|
|
|
let method = req.method.rawValue |
|
|
|
|
|
let baseurl = "https://fueling.prelub.com" |
|
|
|
|
|
let qstring = req.query |
|
|
|
|
|
let components: Dictionary<String, String?> = try req.query.decode(Dictionary<String, String?>.self) |
|
|
|
|
|
var startdate : Date? |
|
|
|
|
|
var qs: [String] = [] |
|
|
|
|
|
for component in components { |
|
|
|
|
|
qs.append( "\(component.key)=\(component.value ?? "nil")") |
|
|
|
|
|
} |
|
|
|
|
|
if(try qstring.get(String?.self, at: "startdate") != nil) { |
|
|
|
|
|
startdate = try parseDate2(qstring.get(String?.self, at: "startdate") ?? "") |
|
|
|
|
|
if(startdate == nil) { |
|
|
|
|
|
return try await(getMaximError(req, "startdate is invalid format. YYYY-MM-DD")) .encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
//throw error |
|
|
|
|
|
return try await getMaximError(req, "startdate is required").encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
var enddate : Date?//= try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false) |
|
|
|
|
|
if(try qstring.get(String?.self, at: "enddate") != nil) { |
|
|
|
|
|
enddate = try parseDate2(qstring.get(String?.self, at: "enddate") ?? "", false) |
|
|
|
|
|
if(enddate == nil) { |
|
|
|
|
|
return try await getMaximError(req, "enddate is invalid format. YYYY-MM-DD").encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
let page = try qstring.get(Int?.self, at: "page") ?? 1 |
|
|
|
|
|
let per = try qstring.get(Int?.self, at: "per") ?? 5 |
|
|
|
|
|
var records : Int = 0 |
|
|
|
|
|
if(enddate == nil) { |
|
|
|
|
|
records = try await FuelEntry.query(on: req.db) |
|
|
|
|
|
.field(\.$id) |
|
|
|
|
|
.group(.and) { |
|
|
|
|
|
grp in |
|
|
|
|
|
grp.filter(\.$loaddate >= startdate) |
|
|
|
|
|
.filter(\.$image != nil) |
|
|
|
|
|
} |
|
|
|
|
|
.all() |
|
|
|
|
|
.count |
|
|
|
|
|
} else { |
|
|
|
|
|
records = try await FuelEntry.query(on: req.db) |
|
|
|
|
|
.field(\.$id) |
|
|
|
|
|
.group(.and) { |
|
|
|
|
|
grp in |
|
|
|
|
|
grp.filter(\.$loaddate >= startdate) |
|
|
|
|
|
.filter(\.$image != nil) |
|
|
|
|
|
.filter(\.$loaddate <= enddate) |
|
|
|
|
|
} |
|
|
|
|
|
.all() |
|
|
|
|
|
.count |
|
|
|
|
|
} |
|
|
|
|
|
let qsStr = qs.joined(separator: "&") |
|
|
|
|
|
|
|
|
|
|
|
let paging = try await getPaging(page, per, records) |
|
|
|
|
|
let meta = Meta(page: page, per: per, total: records, lastpage: (paging["lastpage"] != nil) ? paging["lastpage"] as! Bool : false, error: false, message: "", method: method, baseurl: baseurl, route: rt, querystring: "?\(qsStr)") |
|
|
|
|
|
let query = try await FuelEntry.query(on: req.db) |
|
|
|
|
|
.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) |
|
|
|
|
|
.field(\.$image) |
|
|
|
|
|
.field(\.$tabletserial) |
|
|
|
|
|
.group(.and) { |
|
|
|
|
|
grp in if(enddate != nil) { |
|
|
|
|
|
grp.filter(\.$loaddate >= startdate) |
|
|
|
|
|
.filter(\.$image != nil) |
|
|
|
|
|
.filter(\.$loaddate <= enddate!) |
|
|
|
|
|
} else { |
|
|
|
|
|
grp.filter(\.$loaddate >= startdate) |
|
|
|
|
|
.filter(\.$image != nil) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
.sort(\.$loaddate, .ascending) |
|
|
|
|
|
.range(lower: (paging["offset"] as! Int), upper: (paging["offset"] as! Int) + (paging["per"] as! Int)) |
|
|
|
|
|
.all().map{ |
|
|
|
|
|
try FuelEntry.V2_1_Output.init(from: $0) |
|
|
|
|
|
} |
|
|
|
|
|
let response = returnObjV2_1(data: query, meta: meta) |
|
|
|
|
|
return try await response.encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Sendable |
|
|
|
|
|
func filterTimeStamp(req: Request) async throws -> Response { |
|
|
|
|
|
let rt = req.route!.description.replacingOccurrences(of: "GET ", with: "").replacingOccurrences(of: "PUT ", with: "").replacingOccurrences(of: "POST ", with: "").replacingOccurrences(of: "DELETE ", with: "") |
|
|
|
|
|
let method = req.method.rawValue |
|
|
|
|
|
let baseurl = "https://fueling.prelub.com" |
|
|
|
|
|
let qstring = req.query |
|
|
|
|
|
let components: Dictionary<String, String?> = try req.query.decode(Dictionary<String, String?>.self) |
|
|
|
|
|
var startdate : Date? |
|
|
|
|
|
var qs: [String] = [] |
|
|
|
|
|
for component in components { |
|
|
|
|
|
qs.append( "\(component.key)=\(component.value ?? "nil")") |
|
|
|
|
|
} |
|
|
|
|
|
if(try qstring.get(String?.self, at: "startdate") != nil) { |
|
|
|
|
|
startdate = try parseDate2(qstring.get(String?.self, at: "startdate") ?? "") |
|
|
|
|
|
if(startdate == nil) { |
|
|
|
|
|
return try await(getMaximError(req, "startdate is invalid format. YYYY-MM-DD")) .encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
//throw error |
|
|
|
|
|
return try await getMaximError(req, "startdate is required").encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
var enddate : Date?//= try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false) |
|
|
|
|
|
if(try qstring.get(String?.self, at: "enddate") != nil) { |
|
|
|
|
|
enddate = try parseDate2(qstring.get(String?.self, at: "enddate") ?? "", false) |
|
|
|
|
|
if(enddate == nil) { |
|
|
|
|
|
return try await getMaximError(req, "enddate is invalid format. YYYY-MM-DD").encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
let emptyData: Data? = Data() |
|
|
|
|
|
let page = try qstring.get(Int?.self, at: "page") ?? 1 |
|
|
|
|
|
let per = try qstring.get(Int?.self, at: "per") ?? 10 |
|
|
|
|
|
let records = try await getCount(req, generateSQLNoImage(startdate ?? nil, enddate ?? nil) ) |
|
|
|
|
|
let paging = try await getPaging(page, per, records) |
|
|
|
|
|
let meta = Meta(page: page, per: per, total: records, lastpage: (paging["lastpage"] != nil) ? paging["lastpage"] as! Bool : false, error: false, message: "", method: method, baseurl: baseurl, route: rt, querystring: "?\(qs.joined(separator: "&"))") |
|
|
|
|
|
let query = try await FuelEntry.query(on: req.db) |
|
|
|
|
|
.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) |
|
|
|
|
|
.field(\.$tabletserial) |
|
|
|
|
|
.group(.and) { |
|
|
|
|
|
grp in |
|
|
|
|
|
grp.filter(\.$timestamp >= startdate ?? Calendar.current.startOfDay(for: Calendar.current.date(byAdding: .day, value: -2, to: Date())!)) |
|
|
|
|
|
if( enddate != nil) { |
|
|
|
|
|
grp.filter(\.$timestamp <= enddate!) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
.sort(\.$loaddate, .ascending) |
|
|
|
|
|
.range(lower: (paging["offset"] as! Int), upper: (paging["offset"] as! Int) + (paging["per"] as! Int)) |
|
|
|
|
|
.all().map{ |
|
|
|
|
|
try FuelEntry.V2_1_Output.init(from: $0) |
|
|
|
|
|
} |
|
|
|
|
|
let response = returnObjV2_1(data: query, meta: meta) |
|
|
|
|
|
return try await response.encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@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) |
|
|
|
|
|
.field(\.$tabletserial) |
|
|
|
|
|
//.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(\.$tabletserial) |
|
|
|
|
|
.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, longitude: 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: previous == true ? img.pulldate : Date()) |
|
|
|
|
|
} |
|
|
|
|
|
if(!previous){ |
|
|
|
|
|
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, longitude: img.longitude, product: img.product, make: img.make, model: img.model, serialNumber: img.serialNumber, tankID: img.tankID, fuelAmount: img.fuelAmount, fuelType: img.fuelType, image: nil, isOverride: img.isOverride, downloaded: img.downloaded == nil ? false : img.downloaded!, loaddate: img.loaddate == nil ? nil : img.loaddate, pulldate: previous == true ? img.pulldate : Date(), useremail: img.tabletserial) |
|
|
|
|
|
} |
|
|
|
|
|
if(!previous) { |
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} 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, longitude: 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, longitude: img.longitude, product: img.product, make: img.make, model: img.model, serialNumber: img.serialNumber, tankID: img.tankID, fuelAmount: img.fuelAmount, fuelType: img.fuelType, image: nil, isOverride: img.isOverride, downloaded: img.downloaded == nil ? false : img.downloaded!, loaddate: img.loaddate == nil ? nil : img.loaddate, pulldate: Date(), useremail: img.tabletserial) |
|
|
|
|
|
} |
|
|
|
|
|
return try await woimage.encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func create(req: Request) async throws -> [FuelEntry] { |
|
|
|
|
|
let fuelEntry = try req.content.decode([FuelEntry].self) |
|
|
|
|
|
for entry in fuelEntry { |
|
|
|
|
|
let data = entry.image ?? nil |
|
|
|
|
|
let length = data?.count |
|
|
|
|
|
if(data == nil || length == 0){ |
|
|
|
|
|
entry.image = nil |
|
|
|
|
|
} |
|
|
|
|
|
if(entry.id != nil){ |
|
|
|
|
|
let dbentry = try await FuelEntry.find(entry.id!, on: req.db) |
|
|
|
|
|
if(dbentry != nil){ |
|
|
|
|
|
entry._$idExists = true |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
entry.save(on: req.db).whenFailure({ error in |
|
|
|
|
|
|
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 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 |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Sendable |
|
|
|
|
|
func getrpm(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) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} 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, longitude: 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, longitude: img.longitude, product: img.product, make: img.make, model: img.model, serialNumber: img.serialNumber, tankID: img.tankID, fuelAmount: img.fuelAmount, fuelType: img.fuelType, image: nil, isOverride: img.isOverride, downloaded: img.downloaded == nil ? false : img.downloaded!, loaddate: img.loaddate == nil ? nil : img.loaddate, pulldate: Date(), useremail: img.tabletserial) |
|
|
|
|
|
} |
|
|
|
|
|
return try await woimage.encodeResponse(for: req) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//struct custMeta: Content { |
|
|
|
|
|
// let per: Int |
|
|
|
|
|
// let page: Int |
|
|
|
|
|
// let total: Int |
|
|
|
|
|
// let status: String? |
|
|
|
|
|
//} |
|
|
|
|
|
// |
|
|
|
|
|
//struct PageRequest: Content { |
|
|
|
|
|
// var page: Int |
|
|
|
|
|
// var size: Int |
|
|
|
|
|
// var status: String? |
|
|
|
|
|
// // Add any other properties needed for pagination |
|
|
|
|
|
// |
|
|
|
|
|
// init(page: Int, size: Int, status: String? = nil) { |
|
|
|
|
|
// self.page = page |
|
|
|
|
|
// self.size = size |
|
|
|
|
|
// self.status = status |
|
|
|
|
|
// } |
|
|
|
|
|
//} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|