25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

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