Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

753 rader
32 KiB

  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 data : [FuelEntry.Output] = []
  195. let meta = Meta(page: 0, per: 0, total: 0, lastpage: true, error: true, message: message, queryparameters: try await getParams(req) )
  196. return returnObj(data: data, meta: meta)
  197. }
  198. @Sendable
  199. func filterLoadDate(req: Request) async throws -> Response {
  200. let qstring = req.query
  201. var startdate : Date?
  202. if(try qstring.get(String?.self, at: "startdate") != nil) {
  203. startdate = try parseDate2(qstring.get(String?.self, at: "startdate") ?? "")
  204. if(startdate == nil) {
  205. return try await(getMaximError(req, "startdate is invalid format. YYYY-MM-DD")) .encodeResponse(for: req)
  206. }
  207. } else {
  208. //throw error
  209. return try await getMaximError(req, "startdate is required").encodeResponse(for: req)
  210. }
  211. var enddate : Date?//= try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  212. if(try qstring.get(String?.self, at: "enddate") != nil) {
  213. enddate = try parseDate2(qstring.get(String?.self, at: "enddate") ?? "", false)
  214. if(enddate == nil) {
  215. return try await getMaximError(req, "enddate is invalid format. YYYY-MM-DD").encodeResponse(for: req)
  216. }
  217. }
  218. let emptyData: Data? = Data()
  219. let page = try qstring.get(Int?.self, at: "page") ?? 1
  220. let per = try qstring.get(Int?.self, at: "per") ?? 10
  221. let records = try await getCount(req, generateSQLNoImage(startdate ?? nil, enddate ?? nil) )
  222. let paging = try await getPaging(page, per, records)
  223. let meta = Meta(page: page, per: per, total: records, lastpage: (paging["lastpage"] != nil) ? paging["lastpage"] as! Bool : false, error: false, message: "", queryparameters: try await getParams(req) )
  224. let query = try await FuelEntry.query(on: req.db)
  225. .field(\.$id)
  226. .field(\.$timestamp)
  227. .field(\.$userID)
  228. .field(\.$product)
  229. .field(\.$make)
  230. .field(\.$model)
  231. .field(\.$serialNumber)
  232. .field(\.$tankID)
  233. .field(\.$fuelAmount)
  234. .field(\.$fuelType)
  235. .field(\.$isOverride)
  236. .field(\.$latitude)
  237. .field(\.$longitude)
  238. .field(\.$downloaded)
  239. .field(\.$loaddate)
  240. .group(.and) {
  241. grp in
  242. grp.filter(\.$loaddate >= startdate)
  243. if( enddate != nil) {
  244. grp.filter(\.$loaddate <= enddate!)
  245. }
  246. }
  247. .sort(\.$loaddate, .ascending)
  248. .range(lower: (paging["offset"] as! Int), upper: (paging["offset"] as! Int) + (paging["per"] as! Int))
  249. .all().map{
  250. 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)
  251. }
  252. let response = returnObj(data: query, meta: meta)
  253. return try await response.encodeResponse(for: req)
  254. }
  255. @Sendable
  256. func filterImages(req: Request) async throws -> Response {
  257. let qstring = req.query
  258. var startdate : Date?
  259. if(try qstring.get(String?.self, at: "startdate") != nil) {
  260. startdate = try parseDate2(qstring.get(String?.self, at: "startdate") ?? "")
  261. if(startdate == nil) {
  262. return try await(getMaximError(req, "startdate is invalid format. YYYY-MM-DD")) .encodeResponse(for: req)
  263. }
  264. } else {
  265. //throw error
  266. return try await getMaximError(req, "startdate is required").encodeResponse(for: req)
  267. }
  268. var enddate : Date?//= try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  269. if(try qstring.get(String?.self, at: "enddate") != nil) {
  270. enddate = try parseDate2(qstring.get(String?.self, at: "enddate") ?? "", false)
  271. if(enddate == nil) {
  272. return try await getMaximError(req, "enddate is invalid format. YYYY-MM-DD").encodeResponse(for: req)
  273. }
  274. }
  275. let page = try qstring.get(Int?.self, at: "page") ?? 1
  276. let per = try qstring.get(Int?.self, at: "per") ?? 5
  277. var records : Int = 0
  278. if(enddate == nil) {
  279. records = try await FuelEntry.query(on: req.db)
  280. .field(\.$id)
  281. .group(.and) {
  282. grp in
  283. grp.filter(\.$loaddate >= startdate)
  284. .filter(\.$image != nil)
  285. }
  286. .all()
  287. .count
  288. } else {
  289. records = try await FuelEntry.query(on: req.db)
  290. .field(\.$id)
  291. .group(.and) {
  292. grp in
  293. grp.filter(\.$loaddate >= startdate)
  294. .filter(\.$image != nil)
  295. .filter(\.$loaddate <= enddate)
  296. }
  297. .all()
  298. .count
  299. }
  300. let paging = try await getPaging(page, per, records)
  301. let meta = Meta(page: page, per: per, total: records, lastpage: (paging["lastpage"] != nil) ? paging["lastpage"] as! Bool : false, error: false, message: "", queryparameters: try await getParams(req) )
  302. let query = try await FuelEntry.query(on: req.db)
  303. .field(\.$id)
  304. .field(\.$timestamp)
  305. .field(\.$userID)
  306. .field(\.$product)
  307. .field(\.$make)
  308. .field(\.$model)
  309. .field(\.$serialNumber)
  310. .field(\.$tankID)
  311. .field(\.$fuelAmount)
  312. .field(\.$fuelType)
  313. .field(\.$isOverride)
  314. .field(\.$latitude)
  315. .field(\.$longitude)
  316. .field(\.$downloaded)
  317. .field(\.$loaddate)
  318. .field(\.$image)
  319. .group(.and) {
  320. grp in if(enddate != nil) {
  321. grp.filter(\.$loaddate >= startdate)
  322. .filter(\.$image != nil)
  323. .filter(\.$loaddate <= enddate!)
  324. } else {
  325. grp.filter(\.$loaddate >= startdate)
  326. .filter(\.$image != nil)
  327. }
  328. }
  329. .sort(\.$loaddate, .ascending)
  330. .range(lower: (paging["offset"] as! Int), upper: (paging["offset"] as! Int) + (paging["per"] as! Int))
  331. .all().map{
  332. 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)
  333. }
  334. let response = returnObj(data: query, meta: meta)
  335. return try await response.encodeResponse(for: req)
  336. }
  337. @Sendable
  338. func filterTimeStamp(req: Request) async throws -> Response {
  339. let qstring = req.query
  340. var startdate : Date?
  341. if(try qstring.get(String?.self, at: "startdate") != nil) {
  342. startdate = try parseDate2(qstring.get(String?.self, at: "startdate") ?? "")
  343. if(startdate == nil) {
  344. return try await(getMaximError(req, "startdate is invalid format. YYYY-MM-DD")) .encodeResponse(for: req)
  345. }
  346. } else {
  347. //throw error
  348. return try await getMaximError(req, "startdate is required").encodeResponse(for: req)
  349. }
  350. var enddate : Date?//= try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  351. if(try qstring.get(String?.self, at: "enddate") != nil) {
  352. enddate = try parseDate2(qstring.get(String?.self, at: "enddate") ?? "", false)
  353. if(enddate == nil) {
  354. return try await getMaximError(req, "enddate is invalid format. YYYY-MM-DD").encodeResponse(for: req)
  355. }
  356. }
  357. let emptyData: Data? = Data()
  358. let page = try qstring.get(Int?.self, at: "page") ?? 1
  359. let per = try qstring.get(Int?.self, at: "per") ?? 10
  360. let records = try await getCount(req, generateSQLNoImage(startdate ?? nil, enddate ?? nil) )
  361. let paging = try await getPaging(page, per, records)
  362. let meta = Meta(page: page, per: per, total: records, lastpage: (paging["lastpage"] != nil) ? paging["lastpage"] as! Bool : false, error: false, message: "", queryparameters: try await getParams(req) )
  363. let query = try await FuelEntry.query(on: req.db)
  364. .field(\.$id)
  365. .field(\.$timestamp)
  366. .field(\.$userID)
  367. .field(\.$product)
  368. .field(\.$make)
  369. .field(\.$model)
  370. .field(\.$serialNumber)
  371. .field(\.$tankID)
  372. .field(\.$fuelAmount)
  373. .field(\.$fuelType)
  374. .field(\.$isOverride)
  375. .field(\.$latitude)
  376. .field(\.$longitude)
  377. .field(\.$downloaded)
  378. .field(\.$loaddate)
  379. .group(.and) {
  380. grp in
  381. grp.filter(\.$timestamp >= startdate ?? Calendar.current.startOfDay(for: Calendar.current.date(byAdding: .day, value: -2, to: Date())!))
  382. if( enddate != nil) {
  383. grp.filter(\.$timestamp <= enddate!)
  384. }
  385. }
  386. .sort(\.$loaddate, .ascending)
  387. .range(lower: (paging["offset"] as! Int), upper: (paging["offset"] as! Int) + (paging["per"] as! Int))
  388. .all().map{
  389. 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)
  390. }
  391. let response = returnObj(data: query, meta: meta)
  392. return try await response.encodeResponse(for: req)
  393. }
  394. @Sendable
  395. func filtered(req: Request) async throws -> Response {
  396. let qstring = req.query
  397. let startdate = try parseDate(qstring.get(String?.self, at: "startdate") ?? "")
  398. let enddate = try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  399. let image = try qstring.get(Bool?.self, at: "image") ?? false
  400. let serial = try qstring.get(String?.self, at: "serial") ?? nil
  401. let tank = try qstring.get(String?.self, at: "tank") ?? nil
  402. let previous = try qstring.get(Bool?.self, at: "previous") ?? false
  403. var query = FuelEntry.query(on: req.db)
  404. if(image){
  405. query = query
  406. .field(\.$id)
  407. .field(\.$timestamp)
  408. .field(\.$userID)
  409. .field(\.$product)
  410. .field(\.$make)
  411. .field(\.$model)
  412. .field(\.$serialNumber)
  413. .field(\.$tankID)
  414. .field(\.$fuelAmount)
  415. .field(\.$fuelType)
  416. .field(\.$isOverride)
  417. .field(\.$latitude)
  418. .field(\.$longitude)
  419. .field(\.$image)
  420. .field(\.$downloaded)
  421. .field(\.$loaddate)
  422. //.filter(\.$image != nil)
  423. } else {
  424. query = query
  425. .field(\.$id)
  426. .field(\.$timestamp)
  427. .field(\.$userID)
  428. .field(\.$product)
  429. .field(\.$make)
  430. .field(\.$model)
  431. .field(\.$serialNumber)
  432. .field(\.$tankID)
  433. .field(\.$fuelAmount)
  434. .field(\.$fuelType)
  435. .field(\.$isOverride)
  436. .field(\.$latitude)
  437. .field(\.$longitude)
  438. .field(\.$downloaded)
  439. .field(\.$loaddate)
  440. }
  441. query = query.group(.and){
  442. grp in
  443. if( startdate != nil) {
  444. grp.filter(\.$loaddate >= startdate)
  445. }
  446. if( enddate != nil) {
  447. grp.filter(\.$loaddate <= enddate!)
  448. }
  449. if( serial != nil) {
  450. grp.filter(\.$serialNumber == serial!)
  451. }
  452. if( tank != nil) {
  453. grp.filter(\.$tankID == tank!)
  454. }
  455. if(!previous){
  456. grp.filter(\.$pulldate == nil)
  457. }
  458. }
  459. query = query.sort(\.$loaddate, .ascending)
  460. if(image){
  461. //query = query.filter(\.$image)
  462. let wimage = try await query.paginate(for: req).map{
  463. 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())
  464. }
  465. if(!previous){
  466. wimage.items.forEach{
  467. _ = $0.toFuelEntry().save(on: req.db)
  468. }
  469. }
  470. return try await wimage.encodeResponse(for: req)
  471. } else {
  472. let woimage = try await query.paginate(for: req).map{
  473. 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())
  474. }
  475. if(!previous) {
  476. woimage.items.forEach {
  477. _ = $0.toFuelEntry().save(on: req.db)
  478. }
  479. }
  480. return try await woimage.encodeResponse(for: req)
  481. }
  482. }
  483. @Sendable
  484. func rpm(req: Request) async throws -> Response {
  485. let qstring = req.query
  486. let startdate = try parseDate(qstring.get(String?.self, at: "startdate") ?? "")
  487. let enddate = try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  488. let image = try qstring.get(Bool?.self, at: "image") ?? false
  489. let serial = try qstring.get(String?.self, at: "serial") ?? nil
  490. let tank = try qstring.get(String?.self, at: "tank") ?? nil
  491. let previous = try qstring.get(Bool?.self, at: "previous") ?? false
  492. var query = FuelEntry.query(on: req.db)
  493. if(image){
  494. query = query
  495. .field(\.$id)
  496. .field(\.$timestamp)
  497. .field(\.$userID)
  498. .field(\.$product)
  499. .field(\.$make)
  500. .field(\.$model)
  501. .field(\.$serialNumber)
  502. .field(\.$tankID)
  503. .field(\.$fuelAmount)
  504. .field(\.$fuelType)
  505. .field(\.$isOverride)
  506. .field(\.$latitude)
  507. .field(\.$longitude)
  508. .field(\.$image)
  509. .field(\.$downloaded)
  510. .field(\.$loaddate)
  511. } else {
  512. query = query
  513. .field(\.$id)
  514. .field(\.$timestamp)
  515. .field(\.$userID)
  516. .field(\.$product)
  517. .field(\.$make)
  518. .field(\.$model)
  519. .field(\.$serialNumber)
  520. .field(\.$tankID)
  521. .field(\.$fuelAmount)
  522. .field(\.$fuelType)
  523. .field(\.$isOverride)
  524. .field(\.$latitude)
  525. .field(\.$longitude)
  526. .field(\.$downloaded)
  527. .field(\.$loaddate)
  528. }
  529. query = query.group(.and){
  530. grp in
  531. if( startdate != nil) {
  532. grp.filter(\.$loaddate >= startdate!)
  533. }
  534. if( enddate != nil) {
  535. grp.filter(\.$loaddate <= enddate!)
  536. }
  537. if( serial != nil) {
  538. grp.filter(\.$serialNumber == serial!)
  539. }
  540. if( tank != nil) {
  541. grp.filter(\.$tankID == tank!)
  542. }
  543. if(!previous){
  544. grp.filter(\.$pulldate == nil)
  545. }
  546. }
  547. query = query.sort(\.$loaddate, .ascending).sort(\.$timestamp).sort(\.$serialNumber)
  548. if(image){
  549. //query = query.filter(\.$image)
  550. let wimage = try await query.paginate(for: req).map{
  551. 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())
  552. }
  553. return try await wimage.encodeResponse(for: req)
  554. } else {
  555. let woimage = try await query.paginate(for: req).map{
  556. 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())
  557. }
  558. return try await woimage.encodeResponse(for: req)
  559. }
  560. }
  561. func create(req: Request) async throws -> [FuelEntry] {
  562. let fuelEntry = try req.content.decode([FuelEntry].self)
  563. for entry in fuelEntry {
  564. let data = entry.image ?? nil
  565. let length = data?.count
  566. if(data == nil || length == 0){
  567. entry.image = nil
  568. }
  569. }
  570. try await fuelEntry.create(on: req.db)
  571. return fuelEntry
  572. }
  573. func delete(req: Request) async throws -> HTTPStatus {
  574. guard let fuelEntry = try await FuelEntry.find(req.parameters.get("fuelEntryID"), on: req.db) else {
  575. throw Abort(.notFound)
  576. }
  577. try await fuelEntry.delete(on: req.db)
  578. return .noContent
  579. }
  580. @Sendable
  581. func getrpm(req: Request) async throws -> Response {
  582. let qstring = req.query
  583. let startdate = try parseDate(qstring.get(String?.self, at: "startdate") ?? "")
  584. let enddate = try parseDate(qstring.get(String?.self, at: "enddate") ?? "", false)
  585. let image = try qstring.get(Bool?.self, at: "image") ?? false
  586. let serial = try qstring.get(String?.self, at: "serial") ?? nil
  587. let tank = try qstring.get(String?.self, at: "tank") ?? nil
  588. let previous = try qstring.get(Bool?.self, at: "previous") ?? false
  589. var query = FuelEntry.query(on: req.db)
  590. if(image){
  591. query = query
  592. .field(\.$id)
  593. .field(\.$timestamp)
  594. .field(\.$userID)
  595. .field(\.$product)
  596. .field(\.$make)
  597. .field(\.$model)
  598. .field(\.$serialNumber)
  599. .field(\.$tankID)
  600. .field(\.$fuelAmount)
  601. .field(\.$fuelType)
  602. .field(\.$isOverride)
  603. .field(\.$latitude)
  604. .field(\.$longitude)
  605. .field(\.$image)
  606. .field(\.$downloaded)
  607. .field(\.$loaddate)
  608. } else {
  609. query = query
  610. .field(\.$id)
  611. .field(\.$timestamp)
  612. .field(\.$userID)
  613. .field(\.$product)
  614. .field(\.$make)
  615. .field(\.$model)
  616. .field(\.$serialNumber)
  617. .field(\.$tankID)
  618. .field(\.$fuelAmount)
  619. .field(\.$fuelType)
  620. .field(\.$isOverride)
  621. .field(\.$latitude)
  622. .field(\.$longitude)
  623. .field(\.$downloaded)
  624. .field(\.$loaddate)
  625. }
  626. query = query.group(.and){
  627. grp in
  628. if( startdate != nil) {
  629. grp.filter(\.$loaddate >= startdate!)
  630. }
  631. if( enddate != nil) {
  632. grp.filter(\.$loaddate <= enddate!)
  633. }
  634. if( serial != nil) {
  635. grp.filter(\.$serialNumber == serial!)
  636. }
  637. if( tank != nil) {
  638. grp.filter(\.$tankID == tank!)
  639. }
  640. if(!previous){
  641. grp.filter(\.$pulldate == nil)
  642. }
  643. }
  644. query = query.sort(\.$loaddate, .ascending).sort(\.$timestamp).sort(\.$serialNumber)
  645. if(image){
  646. //query = query.filter(\.$image)
  647. let wimage = try await query.paginate(for: req).map{
  648. 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())
  649. }
  650. return try await wimage.encodeResponse(for: req)
  651. } else {
  652. let woimage = try await query.paginate(for: req).map{
  653. 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())
  654. }
  655. return try await woimage.encodeResponse(for: req)
  656. }
  657. }
  658. }
  659. struct custMeta: Content {
  660. let per: Int
  661. let page: Int
  662. let total: Int
  663. let status: String?
  664. }
  665. struct PageRequest: Content {
  666. var page: Int
  667. var size: Int
  668. var status: String?
  669. // Add any other properties needed for pagination
  670. init(page: Int, size: Int, status: String? = nil) {
  671. self.page = page
  672. self.size = size
  673. self.status = status
  674. }
  675. }