You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FuelEntryV2Controller.swift 34 KiB

преди 2 години
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 2 години
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 1 година
преди 2 години
преди 1 година
преди 2 години
преди 1 година
преди 2 години
преди 1 година
преди 2 години
преди 1 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. //
  2. // FuelEntryController.swift
  3. //
  4. //
  5. // Created by Bill Ryckman on 4/24/23.
  6. //
  7. import Vapor
  8. import FluentKit
  9. import FluentSQL
  10. struct FuelEntryV2Controller: RouteCollection {
  11. func boot(routes: RoutesBuilder) throws {
  12. let fuelEntries = routes.grouped("fuel_entries")
  13. let tokenAuthMiddleware = Token.authenticator()
  14. let guardMiddleware = User.guardMiddleware()
  15. let tokenAuthGroup = fuelEntries.grouped(tokenAuthMiddleware, guardMiddleware)
  16. tokenAuthGroup.get(use: filterLoadDate)
  17. tokenAuthGroup.get("main", use: filterLoadDate)
  18. tokenAuthGroup.get("timestamp", use: filterTimeStamp)
  19. tokenAuthGroup.get("images", use: filterImages)
  20. tokenAuthGroup.get("test", use: filtered)
  21. tokenAuthGroup.get("rpm", use: rpm)
  22. tokenAuthGroup.get("maxim", use: filtered)
  23. tokenAuthGroup.post(use: create)
  24. tokenAuthGroup.put( use: softdelete)
  25. tokenAuthGroup.group(":fuelEntryID") { fuelEntry in
  26. fuelEntry.delete(use: delete)
  27. }
  28. }
  29. func index(req: Request) async throws -> [FuelEntry] {
  30. return try await FuelEntry.query(on: req.db).all()
  31. }
  32. struct filteredreturn: Content{
  33. var fuelentries: [FuelEntry]
  34. var pages: Int
  35. }
  36. struct dload: Content{
  37. var id: UUID
  38. }
  39. @Sendable
  40. func softdelete(req: Request) async throws -> Response {
  41. let ids = try req.content.decode([dload].self)
  42. var msg: [String] = []
  43. for id in ids {
  44. guard let fe = try await FuelEntry.find(id.id, on: req.db) else {
  45. msg.append("create error message for item")
  46. continue
  47. }
  48. fe.downloaded = true
  49. try await fe.save(on: req.db)
  50. }
  51. let response = Response(status: .ok, body: "good")
  52. return response
  53. }
  54. fileprivate func queryParamExists(_ req: Request, _ param: String) async throws -> Bool {
  55. let x = try req.query.get(Bool.self, at: param) ? true : false
  56. print ("x: \(x)")
  57. return x
  58. }
  59. fileprivate func parseDate2(_ dateString: String, _ start: Bool = true) throws -> Date? {
  60. let currentDate = Calendar.current.startOfDay(for: Date())
  61. if(dateString.count == 0 && start){
  62. if(start) {
  63. return Calendar.current.date(byAdding: .day, value: -2, to: currentDate)
  64. } else {
  65. return currentDate
  66. }
  67. } else {
  68. let parts = dateString.split(separator: "-")
  69. if(parts.count != 3) {
  70. return nil
  71. }
  72. let year = Int(parts[0]) ?? nil
  73. if(year == nil) {
  74. return nil
  75. }
  76. let month = Int(parts[1]) ?? nil
  77. if(month == nil) {
  78. return nil
  79. }
  80. let day = Int(parts[2]) ?? nil
  81. if( day == nil ) {
  82. return nil
  83. }
  84. var dateComponents = DateComponents()
  85. dateComponents.year = year
  86. dateComponents.month = month
  87. dateComponents.day = day
  88. if(start) {
  89. dateComponents.hour = 0
  90. dateComponents.minute = 0
  91. dateComponents.second = 0
  92. } else {
  93. dateComponents.hour = 23
  94. dateComponents.minute = 59
  95. dateComponents.second = 59
  96. }
  97. let calendar = Calendar(identifier: .gregorian)
  98. return calendar.date(from: dateComponents)
  99. }
  100. }
  101. fileprivate func parseDate(_ dateString: String, _ start: Bool = true) throws -> Date? {
  102. if(dateString.count == 0){
  103. return nil
  104. } else {
  105. let parts = dateString.split(separator: "-")
  106. if(parts.count != 3) {
  107. 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."))
  108. }
  109. let year = Int(parts[0]) ?? nil
  110. if(year == nil) {
  111. 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"))
  112. }
  113. let month = Int(parts[1]) ?? nil
  114. if(month == nil) {
  115. 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"))
  116. }
  117. let day = Int(parts[2]) ?? nil
  118. if( day == nil ) {
  119. 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"))
  120. }
  121. var dateComponents = DateComponents()
  122. dateComponents.year = year
  123. dateComponents.month = month
  124. dateComponents.day = day
  125. if(start) {
  126. dateComponents.hour = 0
  127. dateComponents.minute = 0
  128. dateComponents.second = 0
  129. } else {
  130. dateComponents.hour = 23
  131. dateComponents.minute = 59
  132. dateComponents.second = 59
  133. }
  134. let calendar = Calendar(identifier: .gregorian)
  135. return calendar.date(from: dateComponents)
  136. }
  137. }
  138. fileprivate func generateSQLNoImage(_ startdate: Date? = nil, _ enddate: Date? = nil) -> SQLQueryString {
  139. if(startdate == nil) {
  140. return SQLQueryString("select count(*) as total from \"fuel_entries\";")
  141. }
  142. if(enddate != nil) {
  143. return SQLQueryString("select count(*) as total from \"fuel_entries\" where \"loadDate\" >= \(bind: startdate) and \"loadDate\" <= \(bind: enddate) ;")
  144. } else {
  145. return SQLQueryString("select count(*) as total from \"fuel_entries\" where \"loadDate\" >= \(bind: startdate);")
  146. }
  147. }
  148. fileprivate func generateSQLImage(_ startdate: Date? = nil, _ enddate: Date? = nil) -> SQLQueryString {
  149. var sql: String = ""
  150. if(startdate == nil) {
  151. return SQLQueryString("select count(*) as total from \"fuel_entries\" where \"image\" is not null;")
  152. }
  153. if(enddate != nil) {
  154. sql = "select count(*) as total from \"fuel_entries\" where \"loadDate\" >= \(String(describing: startdate)) and \"loadDate\" <= \(String(describing: enddate)) and \"image\" is not null;"
  155. return SQLQueryString("select count(*) as total from \"fuel_entries\" where \"loadDate\" >= \(bind: startdate) and \"loadDate\" <= \(bind: enddate) and \"image\" is not null;")
  156. } else {
  157. sql = "select count(*) as total from \"fuel_entries\" where \"image\" is not null and \"loadDate\" >= '\(startdate ?? Date())';"
  158. return SQLQueryString(sql)
  159. }
  160. }
  161. struct CountRecords: Content {
  162. let total: Int
  163. }
  164. fileprivate func getCount(_ req: Request, _ sql: SQLQueryString) async throws -> Int {
  165. print(sql)
  166. if let db = req.db as? SQLDatabase {
  167. let answer = try await db
  168. .raw(sql)
  169. .first(decoding: CountRecords.self)
  170. return answer?.total ?? 0
  171. } else {
  172. return 0
  173. }
  174. }
  175. fileprivate func getPaging(_ page: Int, _ per: Int, _ records: Int) async throws -> [String: Any] {
  176. var vals: [String: Any] = [:]
  177. vals["page"] = page
  178. vals["per"] = per
  179. vals["records"] = records
  180. let lastpage = Int(ceil(Double(records) / Double(per)))
  181. vals["lastpage"] = (page == lastpage) ? true : false
  182. vals["offset"] = ( page * per) - per
  183. return vals
  184. }
  185. fileprivate func getParams(_ req: Request) async throws -> [qparam] {
  186. let urlComponents = URLComponents(string: req.url.description)!
  187. var params: [qparam] = []
  188. for queryItem in urlComponents.queryItems ?? [] {
  189. params.append(qparam(name: queryItem.name, value: queryItem.value ?? ""))
  190. }
  191. return params
  192. }
  193. fileprivate func getMaximError(_ req: Request, _ message: String) async throws -> returnObj {
  194. let rt = req.route!.description.replacingOccurrences(of: "GET ", with: "").replacingOccurrences(of: "PUT ", with: "").replacingOccurrences(of: "POST ", with: "").replacingOccurrences(of: "DELETE ", with: "")
  195. let method = req.method.rawValue
  196. let baseurl = "https://fueling.prelub.com"
  197. let data : [FuelEntry.Output] = []
  198. let meta = Meta(page: 0, per: 0, total: 0, lastpage: true, error: true, message: message, method: method, baseurl: baseurl, route: rt, querystring: "" )
  199. return returnObj(data: data, meta: meta)
  200. }
  201. @Sendable
  202. func filterLoadDate(req: Request) async throws -> Response {
  203. let rt = req.route!.description.replacingOccurrences(of: "GET ", with: "").replacingOccurrences(of: "PUT ", with: "").replacingOccurrences(of: "POST ", with: "").replacingOccurrences(of: "DELETE ", with: "")
  204. let method = req.method.rawValue
  205. let baseurl = "https://fueling.prelub.com"
  206. let qstring = req.query
  207. let components: Dictionary<String, String?> = try req.query.decode(Dictionary<String, String?>.self)
  208. var startdate : Date?
  209. var qs: [String] = []
  210. for component in components {
  211. qs.append( "\(component.key)=\(component.value ?? "nil")")
  212. }
  213. if(try qstring.get(String?.self, at: "startdate") != nil) {
  214. startdate = try parseDate2(qstring.get(String?.self, at: "startdate") ?? "")
  215. if(startdate == nil) {
  216. return try await(getMaximError(req, "startdate is invalid format. YYYY-MM-DD")) .encodeResponse(for: req)
  217. }
  218. } else {
  219. //throw error
  220. return try await getMaximError(req, "startdate is required").encodeResponse(for: req)
  221. }
  222. var enddate : Date?//= try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  223. if(try qstring.get(String?.self, at: "enddate") != nil) {
  224. enddate = try parseDate2(qstring.get(String?.self, at: "enddate") ?? "", false)
  225. if(enddate == nil) {
  226. return try await getMaximError(req, "enddate is invalid format. YYYY-MM-DD").encodeResponse(for: req)
  227. }
  228. }
  229. let emptyData: Data? = Data()
  230. let page = try qstring.get(Int?.self, at: "page") ?? 1
  231. let per = try qstring.get(Int?.self, at: "per") ?? 10
  232. let qsStr = qs.joined(separator: "&")
  233. let records = try await getCount(req, generateSQLNoImage(startdate ?? nil, enddate ?? nil) )
  234. let paging = try await getPaging(page, per, records)
  235. 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)")
  236. let query = try await FuelEntry.query(on: req.db)
  237. .field(\.$id)
  238. .field(\.$timestamp)
  239. .field(\.$userID)
  240. .field(\.$product)
  241. .field(\.$make)
  242. .field(\.$model)
  243. .field(\.$serialNumber)
  244. .field(\.$tankID)
  245. .field(\.$fuelAmount)
  246. .field(\.$fuelType)
  247. .field(\.$isOverride)
  248. .field(\.$latitude)
  249. .field(\.$longitude)
  250. .field(\.$downloaded)
  251. .field(\.$loaddate)
  252. .group(.and) {
  253. grp in
  254. grp.filter(\.$loaddate >= startdate)
  255. if( enddate != nil) {
  256. grp.filter(\.$loaddate <= enddate!)
  257. }
  258. }
  259. .sort(\.$loaddate, .ascending)
  260. .range(lower: (paging["offset"] as! Int), upper: (paging["offset"] as! Int) + (paging["per"] as! Int))
  261. .all().map{
  262. FuelEntry.Output(id: $0.id, timestamp: $0.timestamp, ssid: $0.userID, latitude: $0.latitude, longitude: $0.longitude, product: $0.product, make: $0.make, model: $0.model, serialNumber: $0.serialNumber, tankID: $0.tankID, fuelAmount: $0.fuelAmount, fuelType: $0.fuelType, isOverride: $0.isOverride, image: emptyData, loaddate: $0.loaddate)
  263. }
  264. let response = returnObj(data: query, meta: meta)
  265. return try await response.encodeResponse(for: req)
  266. }
  267. @Sendable
  268. func filterImages(req: Request) async throws -> Response {
  269. let rt = req.route!.description.replacingOccurrences(of: "GET ", with: "").replacingOccurrences(of: "PUT ", with: "").replacingOccurrences(of: "POST ", with: "").replacingOccurrences(of: "DELETE ", with: "")
  270. let method = req.method.rawValue
  271. let baseurl = "https://fueling.prelub.com"
  272. let qstring = req.query
  273. let components: Dictionary<String, String?> = try req.query.decode(Dictionary<String, String?>.self)
  274. var startdate : Date?
  275. var qs: [String] = []
  276. for component in components {
  277. qs.append( "\(component.key)=\(component.value ?? "nil")")
  278. }
  279. if(try qstring.get(String?.self, at: "startdate") != nil) {
  280. startdate = try parseDate2(qstring.get(String?.self, at: "startdate") ?? "")
  281. if(startdate == nil) {
  282. return try await(getMaximError(req, "startdate is invalid format. YYYY-MM-DD")) .encodeResponse(for: req)
  283. }
  284. } else {
  285. //throw error
  286. return try await getMaximError(req, "startdate is required").encodeResponse(for: req)
  287. }
  288. var enddate : Date?//= try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  289. if(try qstring.get(String?.self, at: "enddate") != nil) {
  290. enddate = try parseDate2(qstring.get(String?.self, at: "enddate") ?? "", false)
  291. if(enddate == nil) {
  292. return try await getMaximError(req, "enddate is invalid format. YYYY-MM-DD").encodeResponse(for: req)
  293. }
  294. }
  295. let page = try qstring.get(Int?.self, at: "page") ?? 1
  296. let per = try qstring.get(Int?.self, at: "per") ?? 5
  297. var records : Int = 0
  298. if(enddate == nil) {
  299. records = try await FuelEntry.query(on: req.db)
  300. .field(\.$id)
  301. .group(.and) {
  302. grp in
  303. grp.filter(\.$loaddate >= startdate)
  304. .filter(\.$image != nil)
  305. }
  306. .all()
  307. .count
  308. } else {
  309. records = try await FuelEntry.query(on: req.db)
  310. .field(\.$id)
  311. .group(.and) {
  312. grp in
  313. grp.filter(\.$loaddate >= startdate)
  314. .filter(\.$image != nil)
  315. .filter(\.$loaddate <= enddate)
  316. }
  317. .all()
  318. .count
  319. }
  320. let qsStr = qs.joined(separator: "&")
  321. let paging = try await getPaging(page, per, records)
  322. 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)")
  323. let query = try await FuelEntry.query(on: req.db)
  324. .field(\.$id)
  325. .field(\.$timestamp)
  326. .field(\.$userID)
  327. .field(\.$product)
  328. .field(\.$make)
  329. .field(\.$model)
  330. .field(\.$serialNumber)
  331. .field(\.$tankID)
  332. .field(\.$fuelAmount)
  333. .field(\.$fuelType)
  334. .field(\.$isOverride)
  335. .field(\.$latitude)
  336. .field(\.$longitude)
  337. .field(\.$downloaded)
  338. .field(\.$loaddate)
  339. .field(\.$image)
  340. .group(.and) {
  341. grp in if(enddate != nil) {
  342. grp.filter(\.$loaddate >= startdate)
  343. .filter(\.$image != nil)
  344. .filter(\.$loaddate <= enddate!)
  345. } else {
  346. grp.filter(\.$loaddate >= startdate)
  347. .filter(\.$image != nil)
  348. }
  349. }
  350. .sort(\.$loaddate, .ascending)
  351. .range(lower: (paging["offset"] as! Int), upper: (paging["offset"] as! Int) + (paging["per"] as! Int))
  352. .all().map{
  353. FuelEntry.Output(id: $0.id, timestamp: $0.timestamp, ssid: $0.userID, latitude: $0.latitude, longitude: $0.longitude, product: $0.product, make: $0.make, model: $0.model, serialNumber: $0.serialNumber, tankID: $0.tankID, fuelAmount: $0.fuelAmount, fuelType: $0.fuelType, isOverride: $0.isOverride, image: $0.image, loaddate: $0.loaddate)
  354. }
  355. let response = returnObj(data: query, meta: meta)
  356. return try await response.encodeResponse(for: req)
  357. }
  358. @Sendable
  359. func filterTimeStamp(req: Request) async throws -> Response {
  360. let rt = req.route!.description.replacingOccurrences(of: "GET ", with: "").replacingOccurrences(of: "PUT ", with: "").replacingOccurrences(of: "POST ", with: "").replacingOccurrences(of: "DELETE ", with: "")
  361. let method = req.method.rawValue
  362. let baseurl = "https://fueling.prelub.com"
  363. let qstring = req.query
  364. let components: Dictionary<String, String?> = try req.query.decode(Dictionary<String, String?>.self)
  365. var startdate : Date?
  366. var qs: [String] = []
  367. for component in components {
  368. qs.append( "\(component.key)=\(component.value ?? "nil")")
  369. }
  370. if(try qstring.get(String?.self, at: "startdate") != nil) {
  371. startdate = try parseDate2(qstring.get(String?.self, at: "startdate") ?? "")
  372. if(startdate == nil) {
  373. return try await(getMaximError(req, "startdate is invalid format. YYYY-MM-DD")) .encodeResponse(for: req)
  374. }
  375. } else {
  376. //throw error
  377. return try await getMaximError(req, "startdate is required").encodeResponse(for: req)
  378. }
  379. var enddate : Date?//= try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  380. if(try qstring.get(String?.self, at: "enddate") != nil) {
  381. enddate = try parseDate2(qstring.get(String?.self, at: "enddate") ?? "", false)
  382. if(enddate == nil) {
  383. return try await getMaximError(req, "enddate is invalid format. YYYY-MM-DD").encodeResponse(for: req)
  384. }
  385. }
  386. let emptyData: Data? = Data()
  387. let page = try qstring.get(Int?.self, at: "page") ?? 1
  388. let per = try qstring.get(Int?.self, at: "per") ?? 10
  389. let records = try await getCount(req, generateSQLNoImage(startdate ?? nil, enddate ?? nil) )
  390. let paging = try await getPaging(page, per, records)
  391. 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: "&"))")
  392. let query = try await FuelEntry.query(on: req.db)
  393. .field(\.$id)
  394. .field(\.$timestamp)
  395. .field(\.$userID)
  396. .field(\.$product)
  397. .field(\.$make)
  398. .field(\.$model)
  399. .field(\.$serialNumber)
  400. .field(\.$tankID)
  401. .field(\.$fuelAmount)
  402. .field(\.$fuelType)
  403. .field(\.$isOverride)
  404. .field(\.$latitude)
  405. .field(\.$longitude)
  406. .field(\.$downloaded)
  407. .field(\.$loaddate)
  408. .group(.and) {
  409. grp in
  410. grp.filter(\.$timestamp >= startdate ?? Calendar.current.startOfDay(for: Calendar.current.date(byAdding: .day, value: -2, to: Date())!))
  411. if( enddate != nil) {
  412. grp.filter(\.$timestamp <= enddate!)
  413. }
  414. }
  415. .sort(\.$loaddate, .ascending)
  416. .range(lower: (paging["offset"] as! Int), upper: (paging["offset"] as! Int) + (paging["per"] as! Int))
  417. .all().map{
  418. FuelEntry.Output(id: $0.id, timestamp: $0.timestamp, ssid: $0.userID, latitude: $0.latitude, longitude: $0.longitude, product: $0.product, make: $0.make, model: $0.model, serialNumber: $0.serialNumber, tankID: $0.tankID, fuelAmount: $0.fuelAmount, fuelType: $0.fuelType, isOverride: $0.isOverride, image: emptyData, loaddate: $0.loaddate)
  419. }
  420. let response = returnObj(data: query, meta: meta)
  421. return try await response.encodeResponse(for: req)
  422. }
  423. @Sendable
  424. func filtered(req: Request) async throws -> Response {
  425. let qstring = req.query
  426. let startdate = try parseDate(qstring.get(String?.self, at: "startdate") ?? "")
  427. let enddate = try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  428. let image = try qstring.get(Bool?.self, at: "image") ?? false
  429. let serial = try qstring.get(String?.self, at: "serial") ?? nil
  430. let tank = try qstring.get(String?.self, at: "tank") ?? nil
  431. let previous = try qstring.get(Bool?.self, at: "previous") ?? false
  432. var query = FuelEntry.query(on: req.db)
  433. if(image){
  434. query = query
  435. .field(\.$id)
  436. .field(\.$timestamp)
  437. .field(\.$userID)
  438. .field(\.$product)
  439. .field(\.$make)
  440. .field(\.$model)
  441. .field(\.$serialNumber)
  442. .field(\.$tankID)
  443. .field(\.$fuelAmount)
  444. .field(\.$fuelType)
  445. .field(\.$isOverride)
  446. .field(\.$latitude)
  447. .field(\.$longitude)
  448. .field(\.$image)
  449. .field(\.$downloaded)
  450. .field(\.$loaddate)
  451. //.filter(\.$image != nil)
  452. } else {
  453. query = query
  454. .field(\.$id)
  455. .field(\.$timestamp)
  456. .field(\.$userID)
  457. .field(\.$product)
  458. .field(\.$make)
  459. .field(\.$model)
  460. .field(\.$serialNumber)
  461. .field(\.$tankID)
  462. .field(\.$fuelAmount)
  463. .field(\.$fuelType)
  464. .field(\.$isOverride)
  465. .field(\.$latitude)
  466. .field(\.$longitude)
  467. .field(\.$downloaded)
  468. .field(\.$loaddate)
  469. }
  470. query = query.group(.and){
  471. grp in
  472. if( startdate != nil) {
  473. grp.filter(\.$loaddate >= startdate)
  474. }
  475. if( enddate != nil) {
  476. grp.filter(\.$loaddate <= enddate!)
  477. }
  478. if( serial != nil) {
  479. grp.filter(\.$serialNumber == serial!)
  480. }
  481. if( tank != nil) {
  482. grp.filter(\.$tankID == tank!)
  483. }
  484. if(!previous){
  485. grp.filter(\.$pulldate == nil)
  486. }
  487. }
  488. query = query.sort(\.$loaddate, .ascending)
  489. if(image){
  490. //query = query.filter(\.$image)
  491. let wimage = try await query.paginate(for: req).map{
  492. 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())
  493. }
  494. if(!previous){
  495. wimage.items.forEach{
  496. _ = $0.toFuelEntry().save(on: req.db)
  497. }
  498. }
  499. return try await wimage.encodeResponse(for: req)
  500. } else {
  501. let woimage = try await query.paginate(for: req).map{
  502. 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())
  503. }
  504. if(!previous) {
  505. woimage.items.forEach {
  506. _ = $0.toFuelEntry().save(on: req.db)
  507. }
  508. }
  509. return try await woimage.encodeResponse(for: req)
  510. }
  511. }
  512. @Sendable
  513. func rpm(req: Request) async throws -> Response {
  514. let qstring = req.query
  515. let startdate = try parseDate(qstring.get(String?.self, at: "startdate") ?? "")
  516. let enddate = try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  517. let image = try qstring.get(Bool?.self, at: "image") ?? false
  518. let serial = try qstring.get(String?.self, at: "serial") ?? nil
  519. let tank = try qstring.get(String?.self, at: "tank") ?? nil
  520. let previous = try qstring.get(Bool?.self, at: "previous") ?? false
  521. var query = FuelEntry.query(on: req.db)
  522. if(image){
  523. query = query
  524. .field(\.$id)
  525. .field(\.$timestamp)
  526. .field(\.$userID)
  527. .field(\.$product)
  528. .field(\.$make)
  529. .field(\.$model)
  530. .field(\.$serialNumber)
  531. .field(\.$tankID)
  532. .field(\.$fuelAmount)
  533. .field(\.$fuelType)
  534. .field(\.$isOverride)
  535. .field(\.$latitude)
  536. .field(\.$longitude)
  537. .field(\.$image)
  538. .field(\.$downloaded)
  539. .field(\.$loaddate)
  540. } else {
  541. query = query
  542. .field(\.$id)
  543. .field(\.$timestamp)
  544. .field(\.$userID)
  545. .field(\.$product)
  546. .field(\.$make)
  547. .field(\.$model)
  548. .field(\.$serialNumber)
  549. .field(\.$tankID)
  550. .field(\.$fuelAmount)
  551. .field(\.$fuelType)
  552. .field(\.$isOverride)
  553. .field(\.$latitude)
  554. .field(\.$longitude)
  555. .field(\.$downloaded)
  556. .field(\.$loaddate)
  557. }
  558. query = query.group(.and){
  559. grp in
  560. if( startdate != nil) {
  561. grp.filter(\.$loaddate >= startdate!)
  562. }
  563. if( enddate != nil) {
  564. grp.filter(\.$loaddate <= enddate!)
  565. }
  566. if( serial != nil) {
  567. grp.filter(\.$serialNumber == serial!)
  568. }
  569. if( tank != nil) {
  570. grp.filter(\.$tankID == tank!)
  571. }
  572. if(!previous){
  573. grp.filter(\.$pulldate == nil)
  574. }
  575. }
  576. query = query.sort(\.$loaddate, .ascending).sort(\.$timestamp).sort(\.$serialNumber)
  577. if(image){
  578. //query = query.filter(\.$image)
  579. let wimage = try await query.paginate(for: req).map{
  580. 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())
  581. }
  582. return try await wimage.encodeResponse(for: req)
  583. } else {
  584. let woimage = try await query.paginate(for: req).map{
  585. 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())
  586. }
  587. return try await woimage.encodeResponse(for: req)
  588. }
  589. }
  590. func create(req: Request) async throws -> [FuelEntry] {
  591. let fuelEntry = try req.content.decode([FuelEntry].self)
  592. for entry in fuelEntry {
  593. let data = entry.image ?? nil
  594. let length = data?.count
  595. if(data == nil || length == 0){
  596. entry.image = nil
  597. }
  598. }
  599. try await fuelEntry.create(on: req.db)
  600. return fuelEntry
  601. }
  602. func delete(req: Request) async throws -> HTTPStatus {
  603. guard let fuelEntry = try await FuelEntry.find(req.parameters.get("fuelEntryID"), on: req.db) else {
  604. throw Abort(.notFound)
  605. }
  606. try await fuelEntry.delete(on: req.db)
  607. return .noContent
  608. }
  609. @Sendable
  610. func getrpm(req: Request) async throws -> Response {
  611. let qstring = req.query
  612. let startdate = try parseDate(qstring.get(String?.self, at: "startdate") ?? "")
  613. let enddate = try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  614. let image = try qstring.get(Bool?.self, at: "image") ?? false
  615. let serial = try qstring.get(String?.self, at: "serial") ?? nil
  616. let tank = try qstring.get(String?.self, at: "tank") ?? nil
  617. let previous = try qstring.get(Bool?.self, at: "previous") ?? false
  618. var query = FuelEntry.query(on: req.db)
  619. if(image){
  620. query = query
  621. .field(\.$id)
  622. .field(\.$timestamp)
  623. .field(\.$userID)
  624. .field(\.$product)
  625. .field(\.$make)
  626. .field(\.$model)
  627. .field(\.$serialNumber)
  628. .field(\.$tankID)
  629. .field(\.$fuelAmount)
  630. .field(\.$fuelType)
  631. .field(\.$isOverride)
  632. .field(\.$latitude)
  633. .field(\.$longitude)
  634. .field(\.$image)
  635. .field(\.$downloaded)
  636. .field(\.$loaddate)
  637. } else {
  638. query = query
  639. .field(\.$id)
  640. .field(\.$timestamp)
  641. .field(\.$userID)
  642. .field(\.$product)
  643. .field(\.$make)
  644. .field(\.$model)
  645. .field(\.$serialNumber)
  646. .field(\.$tankID)
  647. .field(\.$fuelAmount)
  648. .field(\.$fuelType)
  649. .field(\.$isOverride)
  650. .field(\.$latitude)
  651. .field(\.$longitude)
  652. .field(\.$downloaded)
  653. .field(\.$loaddate)
  654. }
  655. query = query.group(.and){
  656. grp in
  657. if( startdate != nil) {
  658. grp.filter(\.$loaddate >= startdate!)
  659. }
  660. if( enddate != nil) {
  661. grp.filter(\.$loaddate <= enddate!)
  662. }
  663. if( serial != nil) {
  664. grp.filter(\.$serialNumber == serial!)
  665. }
  666. if( tank != nil) {
  667. grp.filter(\.$tankID == tank!)
  668. }
  669. if(!previous){
  670. grp.filter(\.$pulldate == nil)
  671. }
  672. }
  673. query = query.sort(\.$loaddate, .ascending).sort(\.$timestamp).sort(\.$serialNumber)
  674. if(image){
  675. //query = query.filter(\.$image)
  676. let wimage = try await query.paginate(for: req).map{
  677. 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())
  678. }
  679. return try await wimage.encodeResponse(for: req)
  680. } else {
  681. let woimage = try await query.paginate(for: req).map{
  682. 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())
  683. }
  684. return try await woimage.encodeResponse(for: req)
  685. }
  686. }
  687. }
  688. struct custMeta: Content {
  689. let per: Int
  690. let page: Int
  691. let total: Int
  692. let status: String?
  693. }
  694. struct PageRequest: Content {
  695. var page: Int
  696. var size: Int
  697. var status: String?
  698. // Add any other properties needed for pagination
  699. init(page: Int, size: Int, status: String? = nil) {
  700. self.page = page
  701. self.size = size
  702. self.status = status
  703. }
  704. }