Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

800 строки
34 KiB

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