@fleetbase/fleetops-engine 0.6.51 → 0.6.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (360) hide show
  1. package/README.md +0 -2
  2. package/addon/components/cell/telematic-provider.hbs +16 -0
  3. package/addon/components/cell/telematic-provider.js +36 -0
  4. package/addon/components/cell/telematic-status.hbs +1 -0
  5. package/addon/components/cell/telematic-status.js +39 -0
  6. package/addon/components/device/manager.hbs +5 -6
  7. package/addon/components/device/manager.js +12 -15
  8. package/addon/components/driver/details.hbs +1 -1
  9. package/addon/components/fleet/vehicle-listing.js +1 -0
  10. package/addon/components/fuel-integration/form.hbs +200 -0
  11. package/addon/components/fuel-integration/form.js +242 -0
  12. package/addon/components/fuel-integration/hub.hbs +154 -0
  13. package/addon/components/fuel-integration/hub.js +165 -0
  14. package/addon/components/fuel-integration/matching-priority.hbs +76 -0
  15. package/addon/components/fuel-integration/matching-priority.js +145 -0
  16. package/addon/components/fuel-report/details.hbs +13 -1
  17. package/addon/components/issue/details.hbs +3 -57
  18. package/addon/components/issue/details.js +0 -96
  19. package/addon/components/layout/fleet-ops-sidebar.js +20 -2
  20. package/addon/components/map/drawer/device-event-listing.hbs +12 -2
  21. package/addon/components/map/drawer/driver-listing.hbs +14 -1
  22. package/addon/components/map/drawer/place-listing.hbs +14 -1
  23. package/addon/components/map/drawer/position-listing.hbs +12 -2
  24. package/addon/components/map/drawer/vehicle-listing.hbs +14 -1
  25. package/addon/components/modals/assigned-orders.hbs +40 -0
  26. package/addon/components/modals/attach-device.hbs +4 -3
  27. package/addon/components/modals/attach-telematic-device.hbs +25 -0
  28. package/addon/components/modals/attach-telematic-device.js +3 -0
  29. package/addon/components/modals/driver-assign-order.hbs +7 -58
  30. package/addon/components/modals/driver-assign-vehicle.hbs +10 -2
  31. package/addon/components/modals/fleet-assign-driver.hbs +18 -0
  32. package/addon/components/modals/fleet-assign-driver.js +3 -0
  33. package/addon/components/modals/fleet-assign-vehicle.hbs +18 -0
  34. package/addon/components/modals/fleet-assign-vehicle.js +3 -0
  35. package/addon/components/modals/telematic-connection-diagnostics.hbs +75 -0
  36. package/addon/components/modals/telematic-connection-diagnostics.js +287 -0
  37. package/addon/components/modals/vehicle-details.hbs +6 -1
  38. package/addon/components/modals/vehicle-form.hbs +8 -1
  39. package/addon/components/order/card.hbs +106 -0
  40. package/addon/components/order/card.js +257 -0
  41. package/addon/components/order/form/service-rate.hbs +2 -0
  42. package/addon/components/service-rate/form.hbs +3 -2
  43. package/addon/components/telematic/details.hbs +98 -87
  44. package/addon/components/telematic/details.js +230 -1
  45. package/addon/components/telematic/form.hbs +303 -72
  46. package/addon/components/telematic/form.js +519 -3
  47. package/addon/components/telematic/hub.hbs +149 -0
  48. package/addon/components/telematic/hub.js +142 -0
  49. package/addon/components/telematic/settings.hbs +152 -0
  50. package/addon/components/telematic/settings.js +45 -0
  51. package/addon/components/telematic/tab-empty-state.hbs +29 -0
  52. package/addon/components/telematic/tab-empty-state.js +33 -0
  53. package/addon/components/vehicle/details.hbs +6 -1
  54. package/addon/components/vehicle/form.hbs +2 -1
  55. package/addon/components/widget/fuel-providers.hbs +43 -0
  56. package/addon/components/widget/fuel-providers.js +27 -0
  57. package/addon/controllers/connectivity/devices/index/details.js +27 -1
  58. package/addon/controllers/connectivity/devices/index.js +14 -0
  59. package/addon/controllers/connectivity/fuel-providers/details/sync.js +18 -0
  60. package/addon/controllers/connectivity/fuel-providers/details/transactions.js +24 -0
  61. package/addon/controllers/connectivity/fuel-providers/details.js +69 -0
  62. package/addon/controllers/connectivity/fuel-providers/edit.js +24 -0
  63. package/addon/controllers/connectivity/fuel-providers/index.js +177 -0
  64. package/addon/controllers/connectivity/fuel-providers/new.js +37 -0
  65. package/addon/controllers/connectivity/telematics/details/attachments.js +247 -0
  66. package/addon/controllers/connectivity/telematics/details/devices.js +368 -0
  67. package/addon/controllers/connectivity/telematics/details/events.js +244 -0
  68. package/addon/controllers/connectivity/telematics/details/index.js +3 -0
  69. package/addon/controllers/connectivity/telematics/details/logs.js +43 -0
  70. package/addon/controllers/connectivity/telematics/details/sensors.js +270 -0
  71. package/addon/controllers/connectivity/telematics/details.js +149 -0
  72. package/addon/controllers/connectivity/telematics/{index/edit.js → edit.js} +15 -4
  73. package/addon/controllers/connectivity/telematics/index.js +25 -5
  74. package/addon/controllers/connectivity/telematics/{index/new.js → new.js} +8 -2
  75. package/addon/controllers/management/drivers/index/details.js +78 -1
  76. package/addon/controllers/management/drivers/index.js +39 -0
  77. package/addon/controllers/management/fleets/index/details.js +23 -1
  78. package/addon/controllers/management/fleets/index.js +6 -1
  79. package/addon/controllers/management/fuel-reports/index.js +37 -1
  80. package/addon/controllers/management/fuel-transactions/index/details.js +70 -0
  81. package/addon/controllers/management/fuel-transactions/index.js +240 -0
  82. package/addon/controllers/management/vehicles/index/details.js +32 -0
  83. package/addon/controllers/management/vehicles/index.js +26 -0
  84. package/addon/controllers/operations/orders/index.js +4 -0
  85. package/addon/controllers/settings/payments/index.js +5 -0
  86. package/addon/extension.js +10 -0
  87. package/addon/routes/connectivity/fuel-providers/details/index.js +7 -0
  88. package/addon/routes/connectivity/fuel-providers/details/matching.js +7 -0
  89. package/addon/routes/connectivity/fuel-providers/details/settings.js +7 -0
  90. package/addon/routes/connectivity/fuel-providers/details/sync.js +18 -0
  91. package/addon/routes/connectivity/fuel-providers/details/transactions.js +14 -0
  92. package/addon/routes/connectivity/fuel-providers/details.js +18 -0
  93. package/addon/routes/connectivity/fuel-providers/edit.js +18 -0
  94. package/addon/routes/connectivity/fuel-providers/index.js +20 -0
  95. package/addon/routes/connectivity/fuel-providers/new.js +3 -0
  96. package/addon/routes/connectivity/fuel-providers.js +3 -0
  97. package/addon/routes/connectivity/telematics/details/attachments.js +28 -0
  98. package/addon/routes/connectivity/telematics/details/devices.js +30 -0
  99. package/addon/routes/connectivity/telematics/details/events.js +33 -0
  100. package/addon/routes/connectivity/telematics/details/index.js +3 -0
  101. package/addon/routes/connectivity/telematics/details/logs.js +17 -0
  102. package/addon/routes/connectivity/telematics/details/sensors.js +29 -0
  103. package/addon/routes/connectivity/telematics/{index/details.js → details.js} +1 -1
  104. package/addon/routes/connectivity/telematics/{index/edit.js → edit.js} +1 -1
  105. package/addon/routes/connectivity/telematics/new.js +3 -0
  106. package/addon/routes/management/drivers/index/details/activity.js +3 -0
  107. package/addon/routes/management/fuel-reports/index.js +2 -0
  108. package/addon/routes/management/fuel-transactions/index/details.js +18 -0
  109. package/addon/routes/management/fuel-transactions/index.js +21 -0
  110. package/addon/routes/management/fuel-transactions.js +3 -0
  111. package/addon/routes.js +28 -9
  112. package/addon/services/device-actions.js +64 -1
  113. package/addon/services/device-event-actions.js +12 -1
  114. package/addon/services/driver-actions.js +147 -11
  115. package/addon/services/fleet-actions.js +66 -1
  116. package/addon/services/fuel-integration-actions.js +31 -0
  117. package/addon/services/issue-actions.js +1 -1
  118. package/addon/services/telematic-actions.js +9 -3
  119. package/addon/services/vehicle-actions.js +125 -0
  120. package/addon/styles/fleetops-engine.css +310 -34
  121. package/addon/templates/analytics/reports/index.hbs +19 -1
  122. package/addon/templates/connectivity/devices/index.hbs +19 -1
  123. package/addon/templates/connectivity/events/index.hbs +16 -1
  124. package/addon/templates/connectivity/fuel-providers/details/index.hbs +38 -0
  125. package/addon/templates/connectivity/fuel-providers/details/matching.hbs +13 -0
  126. package/addon/templates/connectivity/fuel-providers/details/settings.hbs +11 -0
  127. package/addon/templates/connectivity/fuel-providers/details/sync.hbs +48 -0
  128. package/addon/templates/connectivity/fuel-providers/details/transactions.hbs +21 -0
  129. package/addon/templates/connectivity/fuel-providers/details.hbs +51 -0
  130. package/addon/templates/connectivity/fuel-providers/edit.hbs +24 -0
  131. package/addon/templates/connectivity/fuel-providers/index.hbs +12 -0
  132. package/addon/templates/connectivity/fuel-providers/new.hbs +22 -0
  133. package/addon/templates/connectivity/fuel-providers.hbs +1 -0
  134. package/addon/templates/connectivity/sensors/index.hbs +19 -1
  135. package/addon/templates/connectivity/telematics/details/attachments.hbs +163 -0
  136. package/addon/templates/connectivity/telematics/details/devices.hbs +88 -0
  137. package/addon/templates/connectivity/telematics/details/events.hbs +101 -0
  138. package/addon/templates/connectivity/telematics/{index/details → details}/index.hbs +0 -1
  139. package/addon/templates/connectivity/telematics/details/logs.hbs +69 -0
  140. package/addon/templates/connectivity/telematics/details/sensors.hbs +88 -0
  141. package/addon/templates/connectivity/telematics/details.hbs +53 -0
  142. package/addon/templates/connectivity/telematics/edit.hbs +27 -0
  143. package/addon/templates/connectivity/telematics/index.hbs +6 -8
  144. package/addon/templates/connectivity/telematics/new.hbs +24 -0
  145. package/addon/templates/maintenance/equipment/index.hbs +19 -1
  146. package/addon/templates/maintenance/maintenances/index.hbs +15 -1
  147. package/addon/templates/maintenance/parts/index.hbs +19 -1
  148. package/addon/templates/maintenance/schedules/index.hbs +19 -1
  149. package/addon/templates/maintenance/work-orders/index.hbs +19 -1
  150. package/addon/templates/management/contacts/customers.hbs +15 -1
  151. package/addon/templates/management/contacts/index.hbs +19 -1
  152. package/addon/templates/management/drivers/index/details/activity.hbs +1 -0
  153. package/addon/templates/management/drivers/index.hbs +19 -1
  154. package/addon/templates/management/fleets/index.hbs +19 -1
  155. package/addon/templates/management/fuel-reports/index.hbs +19 -1
  156. package/addon/templates/management/fuel-transactions/index/details.hbs +73 -0
  157. package/addon/templates/management/fuel-transactions/index.hbs +58 -0
  158. package/addon/templates/management/fuel-transactions.hbs +1 -0
  159. package/addon/templates/management/issues/index.hbs +19 -1
  160. package/addon/templates/management/places/index.hbs +19 -1
  161. package/addon/templates/management/vehicles/index.hbs +19 -1
  162. package/addon/templates/management/vendors/index.hbs +19 -1
  163. package/addon/templates/management/vendors/integrated.hbs +13 -1
  164. package/addon/templates/operations/orders/index.hbs +19 -1
  165. package/addon/templates/operations/service-rates/index.hbs +19 -1
  166. package/addon/templates/settings/payments/index.hbs +15 -1
  167. package/addon/utils/fleet-ops-options.js +3 -0
  168. package/app/components/cell/telematic-provider.js +1 -0
  169. package/app/components/cell/telematic-status.js +1 -0
  170. package/app/components/fuel-integration/form.js +1 -0
  171. package/app/components/fuel-integration/hub.js +1 -0
  172. package/app/components/fuel-integration/matching-priority.js +1 -0
  173. package/app/components/modals/assigned-orders.js +1 -0
  174. package/app/components/modals/attach-telematic-device.js +1 -0
  175. package/app/components/modals/fleet-assign-driver.js +1 -0
  176. package/app/components/modals/fleet-assign-vehicle.js +1 -0
  177. package/app/components/modals/telematic-connection-diagnostics.js +1 -0
  178. package/app/components/order/card.js +1 -0
  179. package/app/components/telematic/hub.js +1 -0
  180. package/app/components/telematic/settings.js +1 -0
  181. package/app/components/telematic/tab-empty-state.js +1 -0
  182. package/app/components/widget/fuel-providers.js +1 -0
  183. package/app/controllers/connectivity/fuel-providers/details/sync.js +1 -0
  184. package/app/controllers/connectivity/{telematics/index/details/devices.js → fuel-providers/details/transactions.js} +1 -1
  185. package/app/controllers/connectivity/{telematics/index → fuel-providers}/details.js +1 -1
  186. package/app/controllers/connectivity/{telematics/index → fuel-providers}/edit.js +1 -1
  187. package/app/controllers/connectivity/{telematics/index/details → fuel-providers}/index.js +1 -1
  188. package/app/controllers/connectivity/{telematics/index → fuel-providers}/new.js +1 -1
  189. package/app/controllers/connectivity/telematics/details/attachments.js +1 -0
  190. package/app/controllers/connectivity/telematics/details/devices.js +1 -0
  191. package/app/controllers/connectivity/telematics/details/events.js +1 -0
  192. package/app/controllers/connectivity/telematics/details/index.js +1 -0
  193. package/app/controllers/connectivity/telematics/details/logs.js +1 -0
  194. package/app/controllers/connectivity/telematics/details/sensors.js +1 -0
  195. package/app/controllers/connectivity/telematics/details.js +1 -0
  196. package/app/controllers/connectivity/telematics/edit.js +1 -0
  197. package/app/controllers/connectivity/telematics/new.js +1 -0
  198. package/app/controllers/management/fuel-transactions/index/details.js +1 -0
  199. package/app/controllers/management/fuel-transactions/index.js +1 -0
  200. package/app/routes/connectivity/{telematics/index → fuel-providers}/details/index.js +1 -1
  201. package/app/routes/connectivity/{telematics/index/details/events.js → fuel-providers/details/matching.js} +1 -1
  202. package/app/routes/connectivity/fuel-providers/details/settings.js +1 -0
  203. package/app/routes/connectivity/fuel-providers/details/sync.js +1 -0
  204. package/app/routes/connectivity/{telematics/index/details/devices.js → fuel-providers/details/transactions.js} +1 -1
  205. package/app/routes/connectivity/{telematics/index → fuel-providers}/details.js +1 -1
  206. package/app/routes/connectivity/{telematics/index → fuel-providers}/edit.js +1 -1
  207. package/app/routes/connectivity/fuel-providers/index.js +1 -0
  208. package/app/routes/connectivity/{telematics/index → fuel-providers}/new.js +1 -1
  209. package/app/routes/connectivity/fuel-providers.js +1 -0
  210. package/app/routes/connectivity/telematics/details/attachments.js +1 -0
  211. package/app/routes/connectivity/telematics/details/devices.js +1 -0
  212. package/app/routes/connectivity/telematics/details/events.js +1 -0
  213. package/app/routes/connectivity/telematics/details/index.js +1 -0
  214. package/app/routes/connectivity/telematics/details/logs.js +1 -0
  215. package/app/routes/connectivity/telematics/details/sensors.js +1 -0
  216. package/app/routes/connectivity/telematics/details.js +1 -0
  217. package/app/routes/connectivity/telematics/edit.js +1 -0
  218. package/app/routes/connectivity/telematics/new.js +1 -0
  219. package/app/routes/management/drivers/index/details/activity.js +1 -0
  220. package/app/routes/management/fuel-transactions/index/details.js +1 -0
  221. package/app/routes/management/fuel-transactions/index.js +1 -0
  222. package/app/routes/management/fuel-transactions.js +1 -0
  223. package/app/services/fuel-integration-actions.js +1 -0
  224. package/app/templates/connectivity/{telematics/index → fuel-providers}/details/index.js +1 -1
  225. package/app/templates/connectivity/{telematics/index/details/events.js → fuel-providers/details/matching.js} +1 -1
  226. package/app/templates/connectivity/fuel-providers/details/settings.js +1 -0
  227. package/app/templates/connectivity/fuel-providers/details/sync.js +1 -0
  228. package/app/templates/connectivity/{telematics/index/details/devices.js → fuel-providers/details/transactions.js} +1 -1
  229. package/app/templates/connectivity/{telematics/index → fuel-providers}/details.js +1 -1
  230. package/app/templates/connectivity/{telematics/index → fuel-providers}/edit.js +1 -1
  231. package/app/templates/connectivity/fuel-providers/index.js +1 -0
  232. package/app/templates/connectivity/{telematics/index → fuel-providers}/new.js +1 -1
  233. package/app/templates/connectivity/fuel-providers.js +1 -0
  234. package/app/templates/connectivity/telematics/details/attachments.js +1 -0
  235. package/app/templates/connectivity/telematics/details/devices.js +1 -0
  236. package/app/templates/connectivity/telematics/details/events.js +1 -0
  237. package/app/templates/connectivity/telematics/details/index.js +1 -0
  238. package/app/templates/connectivity/telematics/details/logs.js +1 -0
  239. package/app/templates/connectivity/telematics/details/sensors.js +1 -0
  240. package/app/templates/connectivity/telematics/details.js +1 -0
  241. package/app/templates/connectivity/telematics/edit.js +1 -0
  242. package/app/templates/connectivity/telematics/new.js +1 -0
  243. package/app/templates/management/drivers/index/details/activity.js +1 -0
  244. package/app/templates/management/fuel-transactions/index/details.js +1 -0
  245. package/app/templates/management/fuel-transactions/index.js +1 -0
  246. package/app/templates/management/fuel-transactions.js +1 -0
  247. package/assets/images/telematics/providers/afaqy.webp +0 -0
  248. package/assets/images/telematics/providers/default.webp +0 -0
  249. package/assets/images/telematics/providers/flespi.webp +0 -0
  250. package/assets/images/telematics/providers/geotab.webp +0 -0
  251. package/assets/images/telematics/providers/safee.webp +0 -0
  252. package/assets/images/telematics/providers/samsara.webp +0 -0
  253. package/composer.json +1 -1
  254. package/extension.json +1 -1
  255. package/package.json +4 -4
  256. package/server/config/fuel-providers.php +42 -0
  257. package/server/config/telematics.php +139 -130
  258. package/server/migrations/2026_06_06_000001_harden_device_events_telematics_contract.php +59 -0
  259. package/server/migrations/2026_06_08_000001_create_fuel_provider_connections_table.php +37 -0
  260. package/server/migrations/2026_06_08_000002_create_fuel_provider_transactions_table.php +53 -0
  261. package/server/migrations/2026_06_08_000003_create_fuel_provider_sync_runs_table.php +40 -0
  262. package/server/migrations/2026_06_10_000001_add_fuel_card_number_to_vehicles_table.php +25 -0
  263. package/server/migrations/2026_06_10_000002_add_vehicle_identity_columns_to_fuel_provider_transactions_table.php +39 -0
  264. package/server/src/Contracts/FuelProvider.php +30 -0
  265. package/server/src/Contracts/TelematicProviderDescriptor.php +3 -1
  266. package/server/src/Events/FuelProviderTransactionImported.php +17 -0
  267. package/server/src/Events/FuelProviderTransactionMatched.php +17 -0
  268. package/server/src/Events/FuelProviderTransactionUnmatched.php +17 -0
  269. package/server/src/Events/FuelReportCreatedFromProvider.php +18 -0
  270. package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +6 -0
  271. package/server/src/Http/Controllers/Internal/v1/DeviceController.php +76 -2
  272. package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +44 -0
  273. package/server/src/Http/Controllers/Internal/v1/DriverController.php +158 -7
  274. package/server/src/Http/Controllers/Internal/v1/FuelProviderConnectionController.php +124 -0
  275. package/server/src/Http/Controllers/Internal/v1/FuelProviderSyncRunController.php +10 -0
  276. package/server/src/Http/Controllers/Internal/v1/FuelProviderTransactionController.php +76 -0
  277. package/server/src/Http/Controllers/Internal/v1/SensorController.php +1 -1
  278. package/server/src/Http/Controllers/Internal/v1/TelematicController.php +178 -15
  279. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +165 -0
  280. package/server/src/Http/Controllers/TelematicWebhookController.php +103 -19
  281. package/server/src/Http/Filter/FuelProviderConnectionFilter.php +33 -0
  282. package/server/src/Http/Filter/FuelProviderSyncRunFilter.php +28 -0
  283. package/server/src/Http/Filter/FuelProviderTransactionFilter.php +59 -0
  284. package/server/src/Http/Filter/FuelReportFilter.php +10 -0
  285. package/server/src/Http/Resources/v1/Driver.php +15 -0
  286. package/server/src/Http/Resources/v1/FuelProviderConnection.php +30 -0
  287. package/server/src/Http/Resources/v1/FuelProviderSyncRun.php +36 -0
  288. package/server/src/Http/Resources/v1/FuelProviderTransaction.php +54 -0
  289. package/server/src/Http/Resources/v1/FuelReport.php +28 -22
  290. package/server/src/Http/Resources/v1/Index/Driver.php +26 -20
  291. package/server/src/Http/Resources/v1/Index/Vehicle.php +29 -22
  292. package/server/src/Http/Resources/v1/Vehicle.php +17 -0
  293. package/server/src/Http/Resources/v1/VehicleWithoutDriver.php +2 -0
  294. package/server/src/Jobs/SyncFuelProviderTransactionsJob.php +57 -0
  295. package/server/src/Jobs/SyncTelematicDevicesJob.php +36 -6
  296. package/server/src/Jobs/TestTelematicConnectionJob.php +9 -22
  297. package/server/src/Models/Asset.php +2 -1
  298. package/server/src/Models/Contact.php +2 -1
  299. package/server/src/Models/Device.php +27 -4
  300. package/server/src/Models/DeviceEvent.php +40 -3
  301. package/server/src/Models/Driver.php +2 -1
  302. package/server/src/Models/Equipment.php +2 -1
  303. package/server/src/Models/Fleet.php +2 -1
  304. package/server/src/Models/FuelProviderConnection.php +60 -0
  305. package/server/src/Models/FuelProviderSyncRun.php +58 -0
  306. package/server/src/Models/FuelProviderTransaction.php +119 -0
  307. package/server/src/Models/FuelReport.php +16 -1
  308. package/server/src/Models/Part.php +2 -1
  309. package/server/src/Models/Sensor.php +21 -4
  310. package/server/src/Models/ServiceRate.php +39 -2
  311. package/server/src/Models/Vehicle.php +14 -2
  312. package/server/src/Models/Vendor.php +2 -1
  313. package/server/src/Providers/FleetOpsServiceProvider.php +10 -0
  314. package/server/src/Support/Analytics/FuelProviderSummary.php +42 -0
  315. package/server/src/Support/FuelProviders/FuelProviderDescriptor.php +55 -0
  316. package/server/src/Support/FuelProviders/FuelProviderRegistry.php +75 -0
  317. package/server/src/Support/FuelProviders/FuelProviderService.php +447 -0
  318. package/server/src/Support/FuelProviders/Providers/AbstractFuelProvider.php +98 -0
  319. package/server/src/Support/FuelProviders/Providers/PetroAppFuelProvider.php +167 -0
  320. package/server/src/Support/Telematics/Providers/AbstractProvider.php +27 -6
  321. package/server/src/Support/Telematics/Providers/AfaqyProvider.php +55 -26
  322. package/server/src/Support/Telematics/Providers/FlespiProvider.php +1 -0
  323. package/server/src/Support/Telematics/Providers/GeotabProvider.php +1 -0
  324. package/server/src/Support/Telematics/Providers/SafeeProvider.php +32 -22
  325. package/server/src/Support/Telematics/Providers/SamsaraProvider.php +3 -1
  326. package/server/src/Support/Telematics/TelematicService.php +340 -21
  327. package/server/src/routes.php +41 -4
  328. package/server/tests/FuelProviderRegistryTest.php +416 -0
  329. package/server/tests/ServiceRateAlgorithmWeightVariablesTest.php +44 -0
  330. package/server/tests/TelematicsHardeningTest.php +268 -0
  331. package/server/tests/VehicleDriverAssignmentTest.php +51 -0
  332. package/translations/ar-ae.yml +22 -0
  333. package/translations/bg-bg.yaml +72 -0
  334. package/translations/en-us.yaml +83 -0
  335. package/translations/es-pa.yaml +72 -0
  336. package/translations/fr-fr.yaml +72 -0
  337. package/translations/mn-mn.yaml +72 -0
  338. package/translations/pt-br.yaml +72 -0
  339. package/translations/ru-ru.yaml +72 -0
  340. package/translations/vi-vn.yaml +97 -0
  341. package/addon/controllers/connectivity/telematics/index/details/devices.js +0 -3
  342. package/addon/controllers/connectivity/telematics/index/details/events.js +0 -3
  343. package/addon/controllers/connectivity/telematics/index/details/index.js +0 -3
  344. package/addon/controllers/connectivity/telematics/index/details/sensors.js +0 -3
  345. package/addon/controllers/connectivity/telematics/index/details.js +0 -24
  346. package/addon/routes/connectivity/telematics/index/details/devices.js +0 -3
  347. package/addon/routes/connectivity/telematics/index/details/events.js +0 -3
  348. package/addon/routes/connectivity/telematics/index/details/index.js +0 -3
  349. package/addon/routes/connectivity/telematics/index/details/sensors.js +0 -3
  350. package/addon/routes/connectivity/telematics/index/new.js +0 -3
  351. package/addon/templates/connectivity/telematics/index/details/devices.hbs +0 -1
  352. package/addon/templates/connectivity/telematics/index/details/events.hbs +0 -1
  353. package/addon/templates/connectivity/telematics/index/details/sensors.hbs +0 -1
  354. package/addon/templates/connectivity/telematics/index/details.hbs +0 -14
  355. package/addon/templates/connectivity/telematics/index/edit.hbs +0 -12
  356. package/addon/templates/connectivity/telematics/index/new.hbs +0 -12
  357. package/app/controllers/connectivity/telematics/index/details/events.js +0 -1
  358. package/app/controllers/connectivity/telematics/index/details/sensors.js +0 -1
  359. package/app/routes/connectivity/telematics/index/details/sensors.js +0 -1
  360. package/app/templates/connectivity/telematics/index/details/sensors.js +0 -1
@@ -0,0 +1,33 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class ConnectivityTelematicsDetailsEventsRoute extends Route {
5
+ @service store;
6
+
7
+ queryParams = {
8
+ page: { refreshModel: true },
9
+ limit: { refreshModel: true },
10
+ sort: { refreshModel: true },
11
+ query: { refreshModel: true },
12
+ event_type: { refreshModel: true },
13
+ severity: { refreshModel: true },
14
+ device_uuid: { refreshModel: true },
15
+ provider: { refreshModel: true },
16
+ processed: { refreshModel: true },
17
+ occurred_at: { refreshModel: true },
18
+ created_at: { refreshModel: true },
19
+ };
20
+
21
+ model(params) {
22
+ const telematic = this.modelFor('connectivity.telematics.details');
23
+ return this.store.query('device-event', {
24
+ ...params,
25
+ telematic: telematic.id,
26
+ });
27
+ }
28
+
29
+ setupController(controller, model) {
30
+ super.setupController(controller, model);
31
+ controller.telematic = this.modelFor('connectivity.telematics.details');
32
+ }
33
+ }
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class ConnectivityTelematicsDetailsIndexRoute extends Route {}
@@ -0,0 +1,17 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class ConnectivityTelematicsDetailsLogsRoute extends Route {
5
+ @service fetch;
6
+
7
+ model() {
8
+ const telematic = this.modelFor('connectivity.telematics.details');
9
+
10
+ return this.fetch.get(`telematics/${telematic.id}/logs`);
11
+ }
12
+
13
+ setupController(controller, model) {
14
+ super.setupController(controller, model);
15
+ controller.telematic = this.modelFor('connectivity.telematics.details');
16
+ }
17
+ }
@@ -0,0 +1,29 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class ConnectivityTelematicsDetailsSensorsRoute extends Route {
5
+ @service store;
6
+
7
+ queryParams = {
8
+ page: { refreshModel: true },
9
+ limit: { refreshModel: true },
10
+ sort: { refreshModel: true },
11
+ query: { refreshModel: true },
12
+ status: { refreshModel: true },
13
+ type: { refreshModel: true },
14
+ device_uuid: { refreshModel: true },
15
+ };
16
+
17
+ model(params) {
18
+ const telematic = this.modelFor('connectivity.telematics.details');
19
+ return this.store.query('sensor', {
20
+ ...params,
21
+ telematic_uuid: telematic.id,
22
+ });
23
+ }
24
+
25
+ setupController(controller, model) {
26
+ super.setupController(controller, model);
27
+ controller.telematic = this.modelFor('connectivity.telematics.details');
28
+ }
29
+ }
@@ -2,7 +2,7 @@ import Route from '@ember/routing/route';
2
2
  import { inject as service } from '@ember/service';
3
3
  import { action } from '@ember/object';
4
4
 
5
- export default class ConnectivityTelematicsIndexDetailsRoute extends Route {
5
+ export default class ConnectivityTelematicsDetailsRoute extends Route {
6
6
  @service store;
7
7
  @service notifications;
8
8
  @service hostRouter;
@@ -2,7 +2,7 @@ import Route from '@ember/routing/route';
2
2
  import { inject as service } from '@ember/service';
3
3
  import { action } from '@ember/object';
4
4
 
5
- export default class ConnectivityTelematicsIndexEditRoute extends Route {
5
+ export default class ConnectivityTelematicsEditRoute extends Route {
6
6
  @service store;
7
7
  @service notifications;
8
8
  @service hostRouter;
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class ConnectivityTelematicsNewRoute extends Route {}
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class ManagementDriversIndexDetailsActivityRoute extends Route {}
@@ -13,6 +13,8 @@ export default class ManagementFuelReportsIndexRoute extends Route {
13
13
  reporter: { refreshModel: true },
14
14
  driver: { refreshModel: true },
15
15
  status: { refreshModel: true },
16
+ source: { refreshModel: true },
17
+ provider: { refreshModel: true },
16
18
  createdAt: { refreshModel: true },
17
19
  updatedAt: { refreshModel: true },
18
20
  public_id: { refreshModel: true },
@@ -0,0 +1,18 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+ import { action } from '@ember/object';
4
+
5
+ export default class ManagementFuelTransactionsIndexDetailsRoute extends Route {
6
+ @service store;
7
+ @service notifications;
8
+ @service hostRouter;
9
+
10
+ @action error(error) {
11
+ this.notifications.serverError(error);
12
+ return this.hostRouter.transitionTo('console.fleet-ops.management.fuel-transactions.index');
13
+ }
14
+
15
+ model({ public_id }) {
16
+ return this.store.findRecord('fuel-provider-transaction', public_id);
17
+ }
18
+ }
@@ -0,0 +1,21 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class ManagementFuelTransactionsIndexRoute extends Route {
5
+ @service store;
6
+
7
+ queryParams = {
8
+ page: { refreshModel: true },
9
+ limit: { refreshModel: true },
10
+ sort: { refreshModel: true },
11
+ query: { refreshModel: true },
12
+ provider: { refreshModel: true },
13
+ sync_status: { refreshModel: true },
14
+ vehicle: { refreshModel: true },
15
+ transaction_at: { refreshModel: true },
16
+ };
17
+
18
+ model(params) {
19
+ return this.store.query('fuel-provider-transaction', { sort: '-transaction_at', ...params });
20
+ }
21
+ }
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class ManagementFuelTransactionsRoute extends Route {}
package/addon/routes.js CHANGED
@@ -71,6 +71,7 @@ export default buildRoutes(function () {
71
71
  this.route('details', { path: '/:public_id' }, function () {
72
72
  this.route('index', { path: '/' });
73
73
  this.route('positions');
74
+ this.route('activity');
74
75
  this.route('schedule');
75
76
  this.route('virtual', { path: '/:slug' });
76
77
  });
@@ -135,6 +136,11 @@ export default buildRoutes(function () {
135
136
  this.route('edit', { path: '/edit/:public_id' });
136
137
  });
137
138
  });
139
+ this.route('fuel-transactions', function () {
140
+ this.route('index', { path: '/' }, function () {
141
+ this.route('details', { path: '/:public_id' });
142
+ });
143
+ });
138
144
  this.route('issues', function () {
139
145
  this.route('index', { path: '/' }, function () {
140
146
  this.route('new');
@@ -146,16 +152,29 @@ export default buildRoutes(function () {
146
152
  });
147
153
  });
148
154
  this.route('connectivity', function () {
155
+ this.route('fuel-providers', { path: '/fuel-integrations' }, function () {
156
+ this.route('index', { path: '/' });
157
+ this.route('new');
158
+ this.route('edit', { path: '/edit/:public_id' });
159
+ this.route('details', { path: '/:public_id' }, function () {
160
+ this.route('index', { path: '/' });
161
+ this.route('sync');
162
+ this.route('matching');
163
+ this.route('transactions');
164
+ this.route('settings');
165
+ });
166
+ });
149
167
  this.route('telematics', function () {
150
- this.route('index', { path: '/' }, function () {
151
- this.route('new');
152
- this.route('edit', { path: '/edit/:public_id' });
153
- this.route('details', { path: '/:public_id' }, function () {
154
- this.route('index', { path: '/' });
155
- this.route('devices');
156
- this.route('sensors');
157
- this.route('events');
158
- });
168
+ this.route('index', { path: '/' });
169
+ this.route('new');
170
+ this.route('edit', { path: '/edit/:public_id' });
171
+ this.route('details', { path: '/:public_id' }, function () {
172
+ this.route('index', { path: '/' });
173
+ this.route('devices');
174
+ this.route('attachments');
175
+ this.route('sensors');
176
+ this.route('events');
177
+ this.route('logs');
159
178
  });
160
179
  });
161
180
 
@@ -1,6 +1,9 @@
1
- import ResourceActionService from '@fleetbase/ember-core/services/resource-action';
1
+ import ResourceActionService, { inject as service } from '@fleetbase/ember-core/services/resource-action';
2
+ import { action } from '@ember/object';
2
3
 
3
4
  export default class DeviceActionsService extends ResourceActionService {
5
+ @service fetch;
6
+
4
7
  constructor() {
5
8
  super(...arguments);
6
9
  this.initialize('device');
@@ -78,4 +81,64 @@ export default class DeviceActionsService extends ResourceActionService {
78
81
  });
79
82
  },
80
83
  };
84
+
85
+ @action attachToVehicle(device, options = {}) {
86
+ this.modalsManager.show('modals/attach-telematic-device', {
87
+ title: this.intl.t('device.prompts.attach-to-vehicle-title'),
88
+ acceptButtonText: this.intl.t('device.actions.attach-to-vehicle'),
89
+ acceptButtonIcon: 'link',
90
+ device,
91
+ selectedVehicle: null,
92
+ confirm: async (modal) => {
93
+ const selectedVehicle = modal.getOption('selectedVehicle');
94
+
95
+ if (!selectedVehicle) {
96
+ return this.notifications.warning(this.intl.t('device.prompts.select-vehicle-warning'));
97
+ }
98
+
99
+ modal.startLoading();
100
+
101
+ try {
102
+ await this.fetch.post(`devices/${device.id}/attach`, { vehicle: selectedVehicle.id });
103
+ await device.reload?.();
104
+ this.notifications.success(this.intl.t('device.prompts.attach-to-vehicle-success'));
105
+ modal.done();
106
+ this.refresh();
107
+ } catch (error) {
108
+ this.notifications.serverError(error);
109
+ modal.stopLoading();
110
+ }
111
+ },
112
+ ...options,
113
+ });
114
+ }
115
+
116
+ @action detachFromVehicle(device, options = {}) {
117
+ const deviceName = device.displayName ?? device.name ?? this.intl.t('resource.device');
118
+ const vehicleName = device.attached_to_name ?? device.attachable?.display_name ?? device.attachable?.name;
119
+
120
+ if (!device.attachable_uuid && !vehicleName) {
121
+ return this.notifications.warning(this.intl.t('device.prompts.not-attached-warning', { deviceName }));
122
+ }
123
+
124
+ this.modalsManager.confirm({
125
+ title: this.intl.t('device.prompts.detach-from-vehicle-title', { deviceName }),
126
+ body: this.intl.t('device.prompts.detach-from-vehicle-body', { deviceName, vehicleName: vehicleName ?? this.intl.t('resource.vehicle') }),
127
+ confirm: async (modal) => {
128
+ modal.startLoading();
129
+
130
+ try {
131
+ await this.fetch.post(`devices/${device.id}/detach`);
132
+ await device.reload?.();
133
+ this.notifications.success(this.intl.t('device.prompts.detach-from-vehicle-success'));
134
+ modal.done();
135
+ this.refresh();
136
+ } catch (error) {
137
+ this.notifications.serverError(error);
138
+ modal.stopLoading();
139
+ }
140
+ },
141
+ ...options,
142
+ });
143
+ }
81
144
  }
@@ -1,9 +1,13 @@
1
+ import { inject as service } from '@ember/service';
1
2
  import ResourceActionService from '@fleetbase/ember-core/services/resource-action';
2
3
 
3
4
  export default class DeviceEventActionsService extends ResourceActionService {
5
+ @service fetch;
6
+ @service notifications;
7
+
4
8
  constructor() {
5
9
  super(...arguments);
6
- this.initialize('device');
10
+ this.initialize('device-event');
7
11
  }
8
12
 
9
13
  transition = {
@@ -34,4 +38,11 @@ export default class DeviceEventActionsService extends ResourceActionService {
34
38
  });
35
39
  },
36
40
  };
41
+
42
+ async markProcessed(deviceEvent) {
43
+ const response = await this.fetch.post(`device-events/${deviceEvent.id}/mark-processed`);
44
+ this.notifications.success(response?.message ?? 'Event marked processed.');
45
+
46
+ return response;
47
+ }
37
48
  }
@@ -7,6 +7,7 @@ import { dasherize } from '@ember/string';
7
7
 
8
8
  export default class DriverActionsService extends ResourceActionService {
9
9
  @service('universe/menu-service') menuService;
10
+ @service fetch;
10
11
 
11
12
  get registeredTabs() {
12
13
  const registeredTabs = this.menuService.getMenuItems('fleet-ops:component:driver:details');
@@ -176,8 +177,8 @@ export default class DriverActionsService extends ResourceActionService {
176
177
 
177
178
  @action assignOrder(driver, options = {}) {
178
179
  this.modalsManager.show('modals/driver-assign-order', {
179
- title: this.intl.t('fleet-ops.management.drivers.index.order-driver'),
180
- acceptButtonText: this.intl.t('fleet-ops.management.drivers.index.assign-order'),
180
+ title: this.intl.t('driver.prompts.assign-order-title', { driverName: driver.name }),
181
+ acceptButtonText: this.intl.t('driver.actions.assign-order'),
181
182
  acceptButtonIcon: 'check',
182
183
  acceptButtonIconPrefix: 'fas',
183
184
  acceptButtonDisabled: true,
@@ -191,18 +192,20 @@ export default class DriverActionsService extends ResourceActionService {
191
192
  confirm: async (modal) => {
192
193
  const selectedOrder = modal.getOption('selectedOrder');
193
194
  if (!selectedOrder) {
194
- return this.notifications.warning(this.intl.t('fleet-ops.management.drivers.index.no-order-warning'));
195
+ return this.notifications.warning(this.intl.t('driver.prompts.select-order-warning'));
195
196
  }
196
197
 
197
198
  modal.startLoading();
198
199
 
199
200
  try {
200
- driver.set('current_job_uuid', selectedOrder.id);
201
- await driver.save();
201
+ await this.fetch.post(`drivers/${driver.id}/assign-order`, { order: selectedOrder.id });
202
+ await driver.reload?.();
203
+ this.notifications.success(this.intl.t('driver.prompts.assign-order-success', { driverName: driver.name }));
204
+ modal.done();
205
+ this.refresh();
202
206
  } catch (err) {
203
207
  this.notifications.serverError(err);
204
208
  driver.rollbackAttributes();
205
- } finally {
206
209
  modal.stopLoading();
207
210
  }
208
211
  },
@@ -212,8 +215,8 @@ export default class DriverActionsService extends ResourceActionService {
212
215
 
213
216
  @action assignVehicle(driver, options = {}) {
214
217
  this.modalsManager.show('modals/driver-assign-vehicle', {
215
- title: this.intl.t('fleet-ops.management.drivers.index.title-vehicle'),
216
- acceptButtonText: this.intl.t('fleet-ops.management.drivers.index.confirm-button'),
218
+ title: this.intl.t('driver.prompts.assign-vehicle-title', { driverName: driver.name }),
219
+ acceptButtonText: this.intl.t('driver.actions.assign-vehicle'),
217
220
  acceptButtonIcon: 'check',
218
221
  hideDeclineButton: true,
219
222
  driver,
@@ -221,16 +224,149 @@ export default class DriverActionsService extends ResourceActionService {
221
224
  modal.startLoading();
222
225
 
223
226
  try {
224
- await driver.save();
225
- this.notifications.success(this.intl.t('fleet-ops.management.drivers.index.assign-vehicle', { driverName: driver.name }));
227
+ const vehicleId = driver.vehicle_uuid ?? driver.vehicle?.id;
228
+ if (!vehicleId) {
229
+ modal.stopLoading();
230
+ return this.notifications.warning(this.intl.t('driver.prompts.select-vehicle-warning'));
231
+ }
232
+
233
+ await this.fetch.post(`drivers/${driver.id}/assign-vehicle`, { vehicle: vehicleId });
234
+ await driver.reload?.();
235
+ this.notifications.success(this.intl.t('driver.prompts.assign-vehicle-success', { driverName: driver.name }));
236
+ modal.done();
237
+ this.refresh();
226
238
  } catch (err) {
227
239
  this.notifications.serverError(err);
228
240
  driver.rollbackAttributes();
229
- } finally {
230
241
  modal.stopLoading();
231
242
  }
232
243
  },
233
244
  ...options,
234
245
  });
235
246
  }
247
+
248
+ @action unassignOrder(driver, options = {}) {
249
+ return this.unassignOrders(driver, options);
250
+ }
251
+
252
+ @action async unassignOrders(driver, options = {}) {
253
+ let response;
254
+
255
+ try {
256
+ response = await this.fetch.get(`drivers/${driver.id}/assigned-orders`);
257
+ } catch (error) {
258
+ return this.notifications.serverError(error);
259
+ }
260
+
261
+ const currentOrderId = response.current;
262
+ const orders = (response.orders ?? response.data ?? []).map((order) => ({
263
+ ...order,
264
+ is_current_job: [order.id, order.uuid, order.public_id].includes(currentOrderId),
265
+ }));
266
+
267
+ if (orders.length === 0) {
268
+ return this.notifications.warning(this.intl.t('driver.prompts.no-assigned-orders-warning', { driverName: driver.name }));
269
+ }
270
+
271
+ this.modalsManager.show('modals/assigned-orders', {
272
+ title: this.intl.t('driver.prompts.unassign-orders-title', { driverName: driver.name }),
273
+ acceptButtonText: this.intl.t('driver.actions.unassign-orders'),
274
+ acceptButtonIcon: 'user-minus',
275
+ acceptButtonDisabled: true,
276
+ subjectLabel: this.intl.t('resource.driver'),
277
+ subjectName: driver.name,
278
+ orders,
279
+ selectedOrderIds: [],
280
+ toggleOrder: (order) => {
281
+ const orderId = order.id;
282
+ const selected = this.modalsManager.getOption('selectedOrderIds') ?? [];
283
+ const selectedOrderIds = selected.includes(orderId) ? selected.filter((id) => id !== orderId) : [...selected, orderId];
284
+ this.modalsManager.setOption('selectedOrderIds', selectedOrderIds);
285
+ this.modalsManager.setOption('acceptButtonDisabled', selectedOrderIds.length === 0);
286
+ },
287
+ confirm: async (modal) => {
288
+ const selectedOrderIds = modal.getOption('selectedOrderIds') ?? [];
289
+ const selectedOrders = orders.filter((order) => selectedOrderIds.includes(order.id));
290
+
291
+ if (selectedOrders.length === 0) {
292
+ return this.notifications.warning(this.intl.t('driver.prompts.select-orders-warning'));
293
+ }
294
+
295
+ const orderList = this.orderReferenceList(selectedOrders);
296
+ const confirmed = await this.confirmUnassignOrders({
297
+ title: this.intl.t('driver.prompts.confirm-unassign-orders-title', { count: selectedOrders.length, driverName: driver.name }),
298
+ body: this.intl.t('driver.prompts.confirm-unassign-orders-body', { driverName: driver.name, orders: orderList }),
299
+ });
300
+
301
+ if (!confirmed) {
302
+ return;
303
+ }
304
+
305
+ modal.startLoading();
306
+
307
+ try {
308
+ await this.fetch.post(`drivers/${driver.id}/unassign-orders`, { orders: selectedOrderIds });
309
+ await driver.reload?.();
310
+ this.notifications.success(this.intl.t('driver.prompts.unassign-orders-success', { count: selectedOrders.length, driverName: driver.name }));
311
+ modal.done();
312
+ this.refresh();
313
+ } catch (error) {
314
+ this.notifications.serverError(error);
315
+ modal.stopLoading();
316
+ }
317
+ },
318
+ ...options,
319
+ });
320
+ }
321
+
322
+ @action unassignVehicle(driver, options = {}) {
323
+ const vehicleName = driver.vehicle?.get?.('display_name') ?? driver.vehicle?.get?.('name') ?? driver.get?.('vehicle_name') ?? driver.vehicle_name;
324
+
325
+ if (!driver.vehicle_uuid && !driver.vehicle?.id && !vehicleName) {
326
+ return this.notifications.warning(this.intl.t('driver.prompts.no-vehicle-assigned-warning', { driverName: driver.name }));
327
+ }
328
+
329
+ this.modalsManager.confirm({
330
+ title: this.intl.t('driver.prompts.unassign-vehicle-title', { driverName: driver.name, vehicleName }),
331
+ body: this.intl.t('driver.prompts.unassign-vehicle-body', { driverName: driver.name, vehicleName }),
332
+ confirm: async (modal) => {
333
+ modal.startLoading();
334
+
335
+ try {
336
+ await this.fetch.post(`drivers/${driver.id}/unassign-vehicle`);
337
+ await driver.reload?.();
338
+ this.notifications.success(this.intl.t('driver.prompts.unassign-vehicle-success', { driverName: driver.name, vehicleName }));
339
+ modal.done();
340
+ this.refresh();
341
+ } catch (error) {
342
+ this.notifications.serverError(error);
343
+ modal.stopLoading();
344
+ }
345
+ },
346
+ ...options,
347
+ });
348
+ }
349
+
350
+ orderReferenceList(orders) {
351
+ const references = orders.map((order) => order.tracking ?? order.public_id ?? order.id).filter(Boolean);
352
+
353
+ return references.length > 5 ? `${references.slice(0, 5).join(', ')} +${references.length - 5}` : references.join(', ');
354
+ }
355
+
356
+ async confirmUnassignOrders({ title, body }) {
357
+ return new Promise((resolve) => {
358
+ this.modalsManager.confirm({
359
+ title,
360
+ body,
361
+ confirm: (_modal, done) => {
362
+ done();
363
+ resolve(true);
364
+ },
365
+ decline: (_modal, done) => {
366
+ done();
367
+ resolve(false);
368
+ },
369
+ });
370
+ });
371
+ }
236
372
  }
@@ -1,6 +1,9 @@
1
- import ResourceActionService from '@fleetbase/ember-core/services/resource-action';
1
+ import ResourceActionService, { inject as service } from '@fleetbase/ember-core/services/resource-action';
2
+ import { action } from '@ember/object';
2
3
 
3
4
  export default class FleetActionsService extends ResourceActionService {
5
+ @service fetch;
6
+
4
7
  constructor() {
5
8
  super(...arguments);
6
9
  this.initialize('fleet', { defaultAttributes: { status: 'active' } });
@@ -81,4 +84,66 @@ export default class FleetActionsService extends ResourceActionService {
81
84
  });
82
85
  },
83
86
  };
87
+
88
+ @action assignDriver(fleet, options = {}) {
89
+ this.modalsManager.show('modals/fleet-assign-driver', {
90
+ title: this.intl.t('fleet.prompts.assign-driver-title', { fleetName: fleet.name }),
91
+ acceptButtonText: this.intl.t('fleet.actions.assign-driver'),
92
+ acceptButtonIcon: 'user-plus',
93
+ selectedDriver: null,
94
+ fleet,
95
+ confirm: async (modal) => {
96
+ const selectedDriver = modal.getOption('selectedDriver');
97
+
98
+ if (!selectedDriver) {
99
+ return this.notifications.warning(this.intl.t('fleet.prompts.select-driver-warning'));
100
+ }
101
+
102
+ modal.startLoading();
103
+
104
+ try {
105
+ await this.fetch.post('fleets/assign-driver', { driver: selectedDriver.id, fleet: fleet.id });
106
+ await fleet.reload?.();
107
+ this.notifications.success(this.intl.t('fleet.prompts.assign-driver-success', { fleetName: fleet.name }));
108
+ modal.done();
109
+ this.refresh();
110
+ } catch (error) {
111
+ this.notifications.serverError(error);
112
+ modal.stopLoading();
113
+ }
114
+ },
115
+ ...options,
116
+ });
117
+ }
118
+
119
+ @action assignVehicle(fleet, options = {}) {
120
+ this.modalsManager.show('modals/fleet-assign-vehicle', {
121
+ title: this.intl.t('fleet.prompts.assign-vehicle-title', { fleetName: fleet.name }),
122
+ acceptButtonText: this.intl.t('fleet.actions.assign-vehicle'),
123
+ acceptButtonIcon: 'car',
124
+ selectedVehicle: null,
125
+ fleet,
126
+ confirm: async (modal) => {
127
+ const selectedVehicle = modal.getOption('selectedVehicle');
128
+
129
+ if (!selectedVehicle) {
130
+ return this.notifications.warning(this.intl.t('fleet.prompts.select-vehicle-warning'));
131
+ }
132
+
133
+ modal.startLoading();
134
+
135
+ try {
136
+ await this.fetch.post('fleets/assign-vehicle', { vehicle: selectedVehicle.id, fleet: fleet.id });
137
+ await fleet.reload?.();
138
+ this.notifications.success(this.intl.t('fleet.prompts.assign-vehicle-success', { fleetName: fleet.name }));
139
+ modal.done();
140
+ this.refresh();
141
+ } catch (error) {
142
+ this.notifications.serverError(error);
143
+ modal.stopLoading();
144
+ }
145
+ },
146
+ ...options,
147
+ });
148
+ }
84
149
  }
@@ -0,0 +1,31 @@
1
+ import ResourceActionService from '@fleetbase/ember-core/services/resource-action';
2
+
3
+ export default class FuelIntegrationActionsService extends ResourceActionService {
4
+ constructor() {
5
+ super(...arguments);
6
+ this.initialize('fuel-provider-connection', {
7
+ defaultAttributes: {
8
+ status: 'draft',
9
+ environment: 'production',
10
+ credentials: {},
11
+ sync_settings: {
12
+ window_days: 7,
13
+ matching_order: ['plate_number', 'internal_id', 'vin', 'serial_number', 'call_sign', 'fuel_card_number', 'trip_number'],
14
+ auto_create_fuel_reports: true,
15
+ },
16
+ },
17
+ });
18
+ }
19
+
20
+ transition = {
21
+ view: (connection) => this.transitionTo('connectivity.fuel-providers.details', connection),
22
+ edit: (connection) => this.transitionTo('connectivity.fuel-providers.edit', connection),
23
+ create: (provider) => {
24
+ if (provider) {
25
+ return this.transitionTo('connectivity.fuel-providers.new', { queryParams: { setupProvider: provider } });
26
+ }
27
+
28
+ return this.transitionTo('connectivity.fuel-providers.new');
29
+ },
30
+ };
31
+ }
@@ -66,7 +66,7 @@ export default class IssueActionsService extends ResourceActionService {
66
66
  return this.modalsManager.show('modals/resource', {
67
67
  resource: issue,
68
68
  title: this.intl.t('common.create-a-new-resource', { resource: this.intl.t('resource.issue')?.toLowerCase() }),
69
- acceptButtonText: this.intl.t('common.create-resource', { resource: this.intl.t('resource.Issue') }),
69
+ acceptButtonText: this.intl.t('common.create-resource', { resource: this.intl.t('resource.issue') }),
70
70
  component: 'issue/form',
71
71
  confirm: (modal) => this.modalTask.perform(modal, 'saveTask', issue, { refresh: true, ...saveOptions }),
72
72
  ...options,