您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

FuelEntryControllerV2_2.swift 34 KiB

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