Mike Carman 2 недель назад
Родитель
Сommit
eb2ba91a21
8 измененных файлов: 1010 добавлений и 182 удалений
  1. Двоичные данные
      .swiftpm/xcode/package.xcworkspace/xcuserdata/mcarman.xcuserdatad/UserInterfaceState.xcuserstate
  2. +19
    -127
      .swiftpm/xcode/xcuserdata/mcarman.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  3. +18
    -14
      Sources/App/Controllers/V2.1/FuelEntryControllerV2_1.swift
  4. +819
    -0
      Sources/App/Controllers/V2.2/FuelEntryControllerV2_2.swift
  5. +71
    -0
      Sources/App/DTO/V2.2/v2.2.swift
  6. +14
    -0
      Sources/App/Migrations/CreateFuelEntry.swift
  7. +68
    -41
      Sources/App/Models/FuelEntry.swift
  8. +1
    -0
      Sources/App/configure.swift

Двоичные данные
.swiftpm/xcode/package.xcworkspace/xcuserdata/mcarman.xcuserdatad/UserInterfaceState.xcuserstate Просмотреть файл


+ 19
- 127
.swiftpm/xcode/xcuserdata/mcarman.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist Просмотреть файл

@@ -8,15 +8,15 @@
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "1165C094-7F83-4580-9E1E-36ACC4A42F04"
shouldBeEnabled = "Yes"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Sources/App/Models/FuelEntry.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "240"
endingLineNumber = "240"
landmarkName = "init(id:timestamp:userID:latitude:longitude:product:make:model:serialNumber:tankID:fuelAmount:fuelType:isOverride:tabletserial:)"
startingLineNumber = "245"
endingLineNumber = "245"
landmarkName = "init(id:timestamp:userID:latitude:longitude:product:make:model:serialNumber:tankID:fuelAmount:fuelType:isOverride:tabletserial:uniqueID:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@@ -24,15 +24,15 @@
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "F812306B-8399-447C-84BE-4AC7A776D420"
shouldBeEnabled = "Yes"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Sources/App/Models/FuelEntry.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "220"
endingLineNumber = "220"
landmarkName = "init(id:timestamp:userID:latitude:longitude:image:product:make:model:serialNumber:tankID:fuelAmount:fuelType:isOverride:tabletserial:)"
startingLineNumber = "224"
endingLineNumber = "224"
landmarkName = "init(id:timestamp:userID:latitude:longitude:image:product:make:model:serialNumber:tankID:fuelAmount:fuelType:isOverride:tabletserial:uniqueID:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@@ -46,9 +46,9 @@
filePath = "Sources/App/Models/FuelEntry.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "200"
endingLineNumber = "200"
landmarkName = "init(id:timestamp:userID:latitude:longitude:image:product:make:model:serialNumber:tankID:fuelAmount:fuelType:isOverride:downloaded:tabletserial:)"
startingLineNumber = "203"
endingLineNumber = "203"
landmarkName = "init(id:timestamp:userID:latitude:longitude:image:product:make:model:serialNumber:tankID:fuelAmount:fuelType:isOverride:downloaded:tabletserial:uniqueID:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@@ -174,8 +174,8 @@
filePath = "Sources/App/Models/FuelEntry.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "285"
endingLineNumber = "285"
startingLineNumber = "291"
endingLineNumber = "291"
landmarkName = "init(from:)"
landmarkType = "7">
</BreakpointContent>
@@ -222,76 +222,12 @@
filePath = "Sources/App/Models/FuelEntry.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "291"
endingLineNumber = "291"
startingLineNumber = "297"
endingLineNumber = "297"
landmarkName = "init(from:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "F4FFD2D4-D060-42E1-A190-F9069A311629"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Sources/App/Controllers/V2.1/FuelEntryControllerV2_1.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "666"
endingLineNumber = "666"
landmarkName = "create(req:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "638255FC-C3CE-4BDA-9A17-20B3673C7544"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Sources/App/Controllers/V2.1/FuelEntryControllerV2_1.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "665"
endingLineNumber = "665"
landmarkName = "create(req:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "CDCEBD6E-46BC-4235-8E96-E63E8486B0B2"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Sources/App/Controllers/V2.1/FuelEntryControllerV2_1.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "661"
endingLineNumber = "661"
landmarkName = "create(req:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "B5F6C965-701B-4342-A558-033C96744411"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Sources/App/Controllers/V2.1/FuelEntryControllerV2_1.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "659"
endingLineNumber = "659"
landmarkName = "create(req:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
@@ -302,8 +238,8 @@
filePath = "Sources/App/Controllers/V2.1/FuelEntryControllerV2_1.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "673"
endingLineNumber = "673"
startingLineNumber = "677"
endingLineNumber = "677"
landmarkName = "create(req:)"
landmarkType = "7">
</BreakpointContent>
@@ -318,54 +254,10 @@
filePath = "Sources/App/Controllers/V2.1/FuelEntryControllerV2_1.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "670"
endingLineNumber = "670"
startingLineNumber = "674"
endingLineNumber = "674"
landmarkName = "create(req:)"
landmarkType = "7">
<Locations>
<Location
uuid = "96C20337-81C9-49B5-9456-AE00B5B367EA - d762ab0350a06ee2"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "(1) suspend resume partial function for App.FuelEntryV2ControllerV2_1.create(req: Vapor.Request) async throws -&gt; Vapor.Response"
moduleName = "App"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/mcarman/Projects/Vapor/fueling_v1/Sources/App/Controllers/V2.1/FuelEntryControllerV2_1.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "670"
endingLineNumber = "670">
</Location>
<Location
uuid = "96C20337-81C9-49B5-9456-AE00B5B367EA - 8039ff4beb6fe6e6"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "(5) suspend resume partial function for App.FuelEntryV2ControllerV2_1.create(req: Vapor.Request) async throws -&gt; Vapor.Response"
moduleName = "App"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/mcarman/Projects/Vapor/fueling_v1/Sources/App/Controllers/V2.1/FuelEntryControllerV2_1.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "670"
endingLineNumber = "670">
</Location>
<Location
uuid = "96C20337-81C9-49B5-9456-AE00B5B367EA - 59be19ac25be1c89"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "closure #1 (App.FuelEntry) throws -&gt; App.FuelEntry.V2_1_Output in App.FuelEntryV2ControllerV2_1.create(req: Vapor.Request) async throws -&gt; Vapor.Response"
moduleName = "App"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/mcarman/Projects/Vapor/fueling_v1/Sources/App/Controllers/V2.1/FuelEntryControllerV2_1.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "670"
endingLineNumber = "670">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>


+ 18
- 14
Sources/App/Controllers/V2.1/FuelEntryControllerV2_1.swift Просмотреть файл

@@ -649,21 +649,25 @@ struct FuelEntryV2ControllerV2_1: RouteCollection {
var results: [FuelEntry] = []
for entry in fuelEntry {
let input = try FuelEntry.init(from: entry)
let data = entry.image ?? nil
let length = data?.count
if(data == nil || length == 0){
input.image = nil
}
if(entry.id != nil){
if (try await FuelEntry.find(entry.id!, on: req.db)) != nil {
input._$id.exists = true
} else {
input._$idExists = false
let data = entry.image ?? nil
let length = data?.count
if(data == nil || length == 0){
input.image = nil
}
}
try await input.save(on: req.db)
results.append(input)
if(entry.id != nil){
if (try await FuelEntry.find(entry.id!, on: req.db)) != nil {
input._$id.exists = true
} else {
input._$idExists = false
}
}
try await input.save(on: req.db)
results.append(input)
}
// try await fuelEntry.create(on: req.db)


+ 819
- 0
Sources/App/Controllers/V2.2/FuelEntryControllerV2_2.swift Просмотреть файл

@@ -0,0 +1,819 @@
//
// FuelEntryControllerV2_2.swift
// Fueling
//
// Created by Michiel Carman on 10/26/26.
//

//
// FuelEntryControllerV2_1.swift
// Fueling
//
// Created by Michiel Carman on 9/15/26.
//

import Vapor
import FluentKit
import FluentSQL

struct FuelEntryV2ControllerV2_2: 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 -> Response {
let fuelEntry = try req.content.decode([FuelEntry.V2_2_Input].self)
var results: [FuelEntry] = []
for entry in fuelEntry {
let input = FuelEntry.init(from: entry)
let exists = try await FuelEntry.query(on: req.db).filter(\.$uniqueID, .equal, input.uniqueID).first()
if(exists == nil) {
let data = entry.image ?? nil
let length = data?.count
if(data == nil || length == 0){
input.image = nil
}
if(entry.id != nil){
if (try await FuelEntry.find(entry.id!, on: req.db)) != nil {
input._$id.exists = true
} else {
input._$idExists = false
}
}
try await input.save(on: req.db)
results.append(input)
} else {
results.append(exists!)
}
}
// try await fuelEntry.create(on: req.db)
let response = try await results.map{
try FuelEntry.V2_1_Output.init(from: $0)
}.encodeResponse(for: req)
return response
}

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
// }
//}











+ 71
- 0
Sources/App/DTO/V2.2/v2.2.swift Просмотреть файл

@@ -0,0 +1,71 @@
//
// v2.2.swift
// Fueling
//
// Created by Michiel Carman on 10/26/26.
//

import Vapor

extension FuelEntry {
struct V2_2_Input: Content {
var id: UUID?
var tabletSerial: String?
var fuelAmount: Double?
var fuelType: String?
var timeStamp: Date?
var appVersion: String?
var longitude: Double?
var product: String?
var latitude: Double?
var serialNumber: String?
var isOverride: Bool?
var make: String?
var model: String?
var tankId: String?
var image: Data?
var userId: String?
var uniqueID: String?
}
struct V2_2_Output: Content {
var id: UUID?
var tabletSerial: String?
var fuelAmount: Double?
var fuelType: String?
var timeStamp: Date?
var appVersion: String?
var longitude: Double?
var product: String?
var latitude: Double?
var serialNumber: String?
var isOverride: Bool?
var make: String?
var model: String?
var tankId: String?
var image: Data?
var uniqueID: String?
init(from decoder: FuelEntry, img: Bool = false) throws {
self.id = decoder.id
self.tabletSerial = decoder.tabletserial
self.fuelAmount = decoder.fuelAmount
self.fuelType = decoder.fuelType
self.timeStamp = decoder.timestamp
self.appVersion = decoder.appVersion
self.longitude = decoder.longitude
self.product = decoder.product
self.latitude = decoder.latitude
self.serialNumber = decoder.serialNumber
self.isOverride = decoder.isOverride
self.make = decoder.make
self.model = decoder.model
self.tankId = decoder.tankID
if img {
self.image = decoder.image
}
self.uniqueID = decoder.uniqueID?.uuidString
}
}
}


+ 14
- 0
Sources/App/Migrations/CreateFuelEntry.swift Просмотреть файл

@@ -96,6 +96,20 @@ struct AddDownloadedBool: AsyncMigration {
}
}

struct AddUniqueIDFiled: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("fuel_entries")
.field("unique_id", .uuid)
.update()
}
func revert(on database: Database) async throws {
try await database.schema("fuel_entries")
.deleteField("unique_id")
.update()
}
}

struct AddAppVersion: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("fuel_entries")


+ 68
- 41
Sources/App/Models/FuelEntry.swift Просмотреть файл

@@ -115,46 +115,46 @@ final class FuelEntry: Model, Content {
return entry
}
}
@ID(key: .id)
var id: UUID?
@Field(key: "timestamp")
var timestamp: Date
@Field(key: "user_id")
var userID: String
@Field(key: "latitude")
var latitude: Double
@Field(key: "longitude")
var longitude: Double
@Field(key: "image")
var image: Data?
@Field(key: "product")
var product: String
@Field(key: "make")
var make: String
@Field(key: "model")
var model: String
@Field(key: "serial_number")
var serialNumber: String
@Field(key: "tank_id")
var tankID: String
@Field(key: "fuel_amount")
var fuelAmount: Double
@Field(key: "fuel_type")
var fuelType: String
@Field(key: "is_override")
var isOverride: Bool
@@ -170,11 +170,13 @@ final class FuelEntry: Model, Content {
@Timestamp(key: "loadDate", on: .create) var loaddate: Date?
@Timestamp(key: "pullDate", on: .none) var pulldate: Date?
// var imageData: Data?

@Field(key: "unique_id") var uniqueID: UUID?
// var imageData: Data?
init() {}
init(id: UUID? = nil, timestamp: Date, userID: String, latitude: Double, longitude: Double, image: Data?, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool, downloaded: Bool? = nil, tabletserial: String? = nil, appversion: String? = nil) { //imageData: Data?
init(id: UUID? = nil, timestamp: Date, userID: String, latitude: Double, longitude: Double, image: Data?, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool, downloaded: Bool? = nil, tabletserial: String? = nil, appversion: String? = nil, uniqueID: UUID? = nil) { //imageData: Data?
self.id = id
self.timestamp = timestamp
self.userID = userID
@@ -193,10 +195,11 @@ final class FuelEntry: Model, Content {
self.image = image ?? nil
self.tabletserial = tabletserial ?? nil
self.appVersion = appversion ?? nil
// self.imageData = imageData
self.uniqueID = uniqueID
// self.imageData = imageData
}
init(id: UUID? = nil, timestamp: Date, userID: String, latitude: Double, longitude: Double, image: Data?, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool, downloaded: Bool? = nil, tabletserial: String? = nil) { //imageData: Data?
init(id: UUID? = nil, timestamp: Date, userID: String, latitude: Double, longitude: Double, image: Data?, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool, downloaded: Bool? = nil, tabletserial: String? = nil, uniqueID: UUID? = nil) { //imageData: Data?
self.id = id
self.timestamp = timestamp
self.userID = userID
@@ -214,9 +217,10 @@ final class FuelEntry: Model, Content {
self.downloaded = downloaded ?? nil
self.image = image ?? nil
self.tabletserial = tabletserial ?? nil
// self.imageData = imageData
self.uniqueID = uniqueID
// self.imageData = imageData
}
init(id: UUID? = nil, timestamp: Date, userID: String, latitude: Double, longitude: Double, image: Data?, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool, tabletserial: String? = nil) { //imageData: Data?
init(id: UUID? = nil, timestamp: Date, userID: String, latitude: Double, longitude: Double, image: Data?, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool, tabletserial: String? = nil, uniqueID: UUID? = nil) { //imageData: Data?
self.id = id
self.timestamp = timestamp
self.userID = userID
@@ -234,9 +238,10 @@ final class FuelEntry: Model, Content {
self.downloaded = downloaded ?? nil
self.image = image ?? nil
self.tabletserial = tabletserial ?? nil
// self.imageData = imageData
self.uniqueID = uniqueID
// self.imageData = imageData
}
init(id: UUID? = nil, timestamp: Date, userID: String, latitude: Double, longitude: Double, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool, tabletserial: String? = nil) { //imageData: Data?
init(id: UUID? = nil, timestamp: Date, userID: String, latitude: Double, longitude: Double, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool, tabletserial: String? = nil, uniqueID: UUID? = nil) { //imageData: Data?
self.id = id
self.timestamp = timestamp
self.userID = userID
@@ -252,26 +257,27 @@ final class FuelEntry: Model, Content {
self.fuelType = fuelType
self.isOverride = isOverride
self.tabletserial = tabletserial ?? nil
// self.imageData = imageData
self.uniqueID = uniqueID
// self.imageData = imageData
}
// struct V2_1_Input: Content {
// var id: UUID?
// var tabletSerial: Date?
// var fuelAmount: Double?
// var fuelType: String?
// var timeStamp: Date?
// var appVersion: String?
// var longitude: String?
// var product: String?
// var latitude: String?
// var serialNumber: String?
// var isOverride: Bool?
// var make: String?
// var model: String?
// var tankId: String?
// var image: Data?
// }
// struct V2_1_Input: Content {
// var id: UUID?
// var tabletSerial: Date?
// var fuelAmount: Double?
// var fuelType: String?
// var timeStamp: Date?
// var appVersion: String?
// var longitude: String?
// var product: String?
// var latitude: String?
// var serialNumber: String?
// var isOverride: Bool?
// var make: String?
// var model: String?
// var tankId: String?
// var image: Data?
// }
init(from decoder: FuelEntry.V2_1_Input) throws {
self.id = decoder.id
@@ -292,4 +298,25 @@ final class FuelEntry: Model, Content {
self.tabletserial = decoder.tabletSerial ?? ""
self.downloaded = false
}
init(from decoder: FuelEntry.V2_2_Input) {
self.id = decoder.id
self.timestamp = decoder.timeStamp ?? Date()
self.fuelAmount = decoder.fuelAmount ?? 0
self.fuelType = decoder.fuelType ?? ""
self.appVersion = decoder.appVersion ?? ""
self.longitude = decoder.longitude ?? 0
self.product = decoder.product ?? ""
self.latitude = decoder.latitude ?? 0
self.serialNumber = decoder.serialNumber ?? ""
self.isOverride = decoder.isOverride ?? false
self.make = decoder.make ?? ""
self.model = decoder.model ?? ""
self.tankID = decoder.tankId ?? ""
self.userID = decoder.userId ?? ""
self.image = decoder.image
self.tabletserial = decoder.tabletSerial ?? ""
self.downloaded = false
self.uniqueID = decoder.uniqueID == nil ? nil : UUID(uuidString: decoder.uniqueID!)
}
}

+ 1
- 0
Sources/App/configure.swift Просмотреть файл

@@ -52,6 +52,7 @@ public func configure(_ app: Application) async throws {
app.migrations.add(AddLoadDateAndPullDate())
app.migrations.add(AddDeviceSerial())
app.migrations.add(AddAppVersion())
app.migrations.add(AddUniqueIDFiled())
try await app.autoMigrate().get()

// register routes


Загрузка…
Отмена
Сохранить