@fleetbase/fleetops-engine 0.4.3 → 0.4.4

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 (30) hide show
  1. package/addon/components/edit-order-route-panel.hbs +182 -0
  2. package/addon/components/edit-order-route-panel.js +265 -0
  3. package/addon/components/fleet-panel.js +3 -3
  4. package/addon/components/map-container/toolbar.hbs +2 -2
  5. package/addon/components/modals/order-route-form.hbs +1 -1
  6. package/addon/controllers/operations/orders/index/new.js +66 -22
  7. package/addon/controllers/operations/orders/index/view.js +131 -126
  8. package/addon/routes/operations/orders/index/view.js +1 -1
  9. package/addon/services/context-panel.js +6 -0
  10. package/addon/styles/fleetops-engine.css +5 -0
  11. package/addon/templates/operations/orders/index/new.hbs +390 -58
  12. package/addon/templates/operations/orders/index/view.hbs +135 -105
  13. package/addon/templates/operations/service-rates/index/new.hbs +3 -1
  14. package/composer.json +2 -2
  15. package/extension.json +1 -1
  16. package/package.json +3 -3
  17. package/server/src/Http/Controllers/Api/v1/DriverController.php +59 -20
  18. package/server/src/Http/Controllers/Api/v1/OrderController.php +2 -0
  19. package/server/src/Http/Controllers/Internal/v1/DriverController.php +16 -3
  20. package/server/src/Http/Controllers/Internal/v1/OrderController.php +11 -0
  21. package/server/src/Http/Resources/v1/Order.php +3 -0
  22. package/server/src/Http/Resources/v1/PurchaseRate.php +2 -1
  23. package/server/src/Http/Resources/v1/ServiceQuote.php +1 -0
  24. package/server/src/Http/Resources/v1/ServiceQuoteItem.php +29 -0
  25. package/server/src/Models/Driver.php +1 -1
  26. package/server/src/Models/Order.php +16 -0
  27. package/server/src/Models/Place.php +2 -2
  28. package/server/src/Observers/DriverObserver.php +6 -1
  29. package/server/src/routes.php +1 -0
  30. package/translations/en-us.yaml +9 -2
@@ -1,12 +1,5 @@
1
- <Overlay @position="right" @noBackdrop={{true}} @width="570px" @fullHeight={{true}} @isResizable={{true}} @onLoad={{this.setupInterface}} as |overlay|>
2
- <Overlay::Header
3
- @overlay={{overlay}}
4
- @title={{@model.public_id}}
5
- @status={{@model.status}}
6
- @dispatched={{@model.dispatched}}
7
- @createdAt={{@model.createdAt}}
8
- @onPressCancel={{this.transitionBack}}
9
- >
1
+ <Overlay @position="right" @noBackdrop={{true}} @width="550px" @fullHeight={{true}} @isResizable={{true}} @onLoad={{this.setupInterface}} as |overlay|>
2
+ <Overlay::Header @overlay={{overlay}} @title={{@model.public_id}} @status={{@model.status}} @dispatched={{@model.dispatched}} @createdAt={{@model.createdAt}} @onPressCancel={{this.transitionBack}}>
10
3
  {{#if @model.canBeDispatched}}
11
4
  <Button @type="primary" @icon="paper-plane" @text={{t "fleet-ops.operations.orders.index.view.dispatch"}} class="mr-2" @onClick={{fn this.dispatchOrder @model}} />
12
5
  {{/if}}
@@ -87,15 +80,8 @@
87
80
  </DropdownButton>
88
81
  </Overlay::Header>
89
82
 
90
- <Overlay::Body @wrapperClass="new-order-overlay-body" @increaseInnerBodyHeightBy={{1000}}>
91
- <ContentPanel
92
- @title={{t "fleet-ops.operations.orders.index.view.activity"}}
93
- @open={{true}}
94
- @pad={{false}}
95
- @isLoading={{not this.loadOrderRelations.isIdle}}
96
- @panelBodyWrapperClass="px-0 py-4"
97
- @panelBodyClass="bg-white dark:bg-gray-800"
98
- >
83
+ <Overlay::Body @wrapperClass="new-order-overlay-body">
84
+ <ContentPanel @title={{t "fleet-ops.operations.orders.index.view.activity"}} @open={{true}} @pad={{false}} @isLoading={{not this.loadOrderRelations.isIdle}} @panelBodyWrapperClass="px-0 py-4" @panelBodyClass="bg-white dark:bg-gray-800">
99
85
  {{#if @model.tracking_statuses}}
100
86
  <Timeline @activity={{@model.tracking_statuses}} @arrowClass="bg-gray-600 border border-gray-900 shadow-md" as |TimelineItem|>
101
87
  <TimelineItem @activeStatus={{@model.status}} as |trackingStatus|>
@@ -135,12 +121,7 @@
135
121
  <div class="field-name">{{t "fleet-ops.operations.orders.index.view.customer"}}</div>
136
122
  <div class="flex flex-row">
137
123
  <div>
138
- <Image
139
- src={{avatar-url @model.customer.photo_url}}
140
- @fallbackSrc={{config "defaultValues.contactImage"}}
141
- class="w-8 h-8 rounded-md shadow-sm mr-2"
142
- alt={{@model.customer.name}}
143
- />
124
+ <Image src={{avatar-url @model.customer.photo_url}} @fallbackSrc={{config "defaultValues.contactImage"}} class="w-8 h-8 rounded-md shadow-sm mr-2" alt={{@model.customer.name}} />
144
125
  </div>
145
126
  <div>
146
127
  <div class="field-value">{{n-a @model.customer.name "No Customer"}}</div>
@@ -155,12 +136,7 @@
155
136
  {{#if @model.facilitator.isIntegratedVendor}}
156
137
  <div class="flex flex-row">
157
138
  <div>
158
- <Image
159
- src={{avatar-url @model.facilitator.photo_url}}
160
- @fallbackSrc={{config "defaultValues.contactImage"}}
161
- class="w-8 h-8 rounded-md border border-gray-200 dark:border-gray-900 shadow-sm mr-2"
162
- alt={{@model.facilitator.name}}
163
- />
139
+ <Image src={{avatar-url @model.facilitator.photo_url}} @fallbackSrc={{config "defaultValues.contactImage"}} class="w-8 h-8 rounded-md border border-gray-200 dark:border-gray-900 shadow-sm mr-2" alt={{@model.facilitator.name}} />
164
140
  </div>
165
141
  <div>
166
142
  <div class="field-value">{{n-a @model.facilitator.name}}</div>
@@ -177,14 +153,7 @@
177
153
  <div>
178
154
  <a href="javascript:;" class="flex flex-row" {{on "click" (fn this.focusOrderAssignedDriver @model)}}>
179
155
  <div>
180
- <Image
181
- src={{avatar-url @model.driver_assigned.photo_url}}
182
- @fallbackSrc={{config "defaultValues.driverImage"}}
183
- width="32"
184
- height="32"
185
- class="w-8 h-8 rounded-md shadow-sm mr-3 lg:mr-2"
186
- alt={{@model.driver_assigned.name}}
187
- />
156
+ <Image src={{avatar-url @model.driver_assigned.photo_url}} @fallbackSrc={{config "defaultValues.driverImage"}} width="32" height="32" class="w-8 h-8 rounded-md shadow-sm mr-3 lg:mr-2" alt={{@model.driver_assigned.name}} />
188
157
  </div>
189
158
  <div class="field-value">
190
159
  <div>{{n-a @model.driver_assigned.name "No Driver"}}</div>
@@ -194,13 +163,7 @@
194
163
  </div>
195
164
  </a>
196
165
  <div class="mt-1">
197
- <Button
198
- @size="xs"
199
- @type="default"
200
- @icon="edit"
201
- @text={{if @model.has_driver_assigned (t "fleet-ops.operations.orders.index.view.change-driver") (t "fleet-ops.operations.orders.index.view.assign-driver")}}
202
- @onClick={{fn this.assignDriver @model}}
203
- />
166
+ <Button @size="xs" @type="default" @icon="edit" @text={{if @model.has_driver_assigned (t "fleet-ops.operations.orders.index.view.change-driver") (t "fleet-ops.operations.orders.index.view.assign-driver")}} @onClick={{fn this.assignDriver @model}} />
204
167
  </div>
205
168
  </div>
206
169
  </div>
@@ -239,25 +202,56 @@
239
202
  </div>
240
203
  </ContentPanel>
241
204
 
205
+ {{#if @model.purchase_rate}}
206
+ <ContentPanel @title={{t "fleet-ops.operations.orders.index.view.purchase-rate-panel-title"}} @open={{true}} @pad={{false}} @panelBodyClass="bg-white dark:bg-gray-800">
207
+ <div class="order-view-purchase-rate-table-wrapper next-table-wrapper h-auto table-fluid rounded-b-md">
208
+ <table id="order-view-purchase-rate-table" class="table table-fixed flex-1">
209
+ <thead>
210
+ <tr>
211
+ <th class="text-left">{{t "fleet-ops.operations.orders.index.new.breakdown"}}</th>
212
+ <th>
213
+ <div class="flex flex-row items-center justify-end">{{@model.purchase_rate.service_quote.currency}}</div>
214
+ </th>
215
+ </tr>
216
+ </thead>
217
+ <tbody>
218
+ {{#each @model.purchase_rate.service_quote.items as |item|}}
219
+ <tr>
220
+ <td>
221
+ <span class="font-semibold">{{smart-humanize item.details}}</span>
222
+ </td>
223
+ <td>
224
+ <div class="flex flex-row items-center justify-end">{{format-currency item.amount @model.purchase_rate.service_quote.currency}}</div>
225
+ </td>
226
+ </tr>
227
+ {{/each}}
228
+ <tr class="border-b-0">
229
+ <td class="border-b-0">
230
+ <span class="font-semibold">{{t "fleet-ops.common.total"}}</span>
231
+ </td>
232
+ <td class="border-b-0">
233
+ <div class="flex flex-row items-center justify-end">{{format-currency @model.purchase_rate.service_quote.amount @model.purchase_rate.service_quote.currency}}</div>
234
+ </td>
235
+ </tr>
236
+ </tbody>
237
+ </table>
238
+ </div>
239
+ </ContentPanel>
240
+ {{/if}}
241
+
242
+ <ContentPanel @title={{t "fleet-ops.operations.orders.index.view.notes-title"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
243
+ <p class="text-gray-700 dark:text-gray-300 leading-5 text-sm">{{n-a @model.notes}}</p>
244
+ </ContentPanel>
245
+
242
246
  {{#if @model.isIntegratedVendorOrder}}
243
- <ContentPanel
244
- @title={{concat @model.facilitator.name (t "fleet-ops.operations.orders.index.view.order-details-title")}}
245
- @open={{true}}
246
- @pad={{true}}
247
- @panelBodyClass="bg-white dark:bg-gray-800"
248
- >
247
+ <ContentPanel @title={{concat @model.facilitator.name (t "fleet-ops.operations.orders.index.view.order-details-title")}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
249
248
  <IntegratedOrderDetails @integratedVendor={{@model.facilitator}} @details={{@model.meta.integrated_vendor_order}} />
250
249
  </ContentPanel>
251
250
  {{/if}}
252
251
 
253
252
  {{#if @model.order_config}}
254
253
  {{#each @model.groupedMetaFields as |group|}}
255
- <ContentPanel
256
- @title={{if group.value (humanize group.value) (t "fleet-ops.operations.orders.index.view.additional-details-title")}}
257
- @open={{true}}
258
- @pad={{true}}
259
- @panelBodyClass="bg-white dark:bg-gray-800"
260
- >
254
+ <ContentPanel @title={{if group.value (humanize group.value) (t "fleet-ops.operations.orders.index.view.additional-details-title")}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
261
255
  <div class="grid grid-cols-1 lg:grid-cols-2 gap-4 lg:gap-2">
262
256
  {{#each group.items as |metaField|}}
263
257
  <div class="field-info-container space-y-2">
@@ -273,14 +267,7 @@
273
267
  {{/if}}
274
268
 
275
269
  {{#if @model.tracking_number}}
276
- <ContentPanel
277
- @title={{t "fleet-ops.operations.orders.index.view.tracking"}}
278
- @prefixTitleRight={{@model.tracking}}
279
- @isLoading={{not this.loadOrderRelations.isIdle}}
280
- @open={{true}}
281
- @pad={{true}}
282
- @panelBodyClass="bg-white dark:bg-gray-800"
283
- >
270
+ <ContentPanel @title={{t "fleet-ops.operations.orders.index.view.tracking"}} @prefixTitleRight={{@model.tracking}} @isLoading={{not this.loadOrderRelations.isIdle}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
284
271
  <div class="mb-4 flex justify-end">
285
272
  <Button @size="xs" @type="default" @icon="barcode" @text="Get Order Label" @onClick={{fn this.viewOrderLabel @model}} />
286
273
  </div>
@@ -295,7 +282,7 @@
295
282
  </ContentPanel>
296
283
  {{/if}}
297
284
 
298
- <ContentPanel @title="Route" @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800" @actionButtons={{this.routePanelButtons}}>
285
+ <ContentPanel @title={{t "fleet-ops.operations.orders.index.view.route-panel-title"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800" @actionButtons={{this.routePanelButtons}}>
299
286
  {{#if @model.payload.isMultiDrop}}
300
287
  <div>
301
288
  <RouteList @order={{@model}} />
@@ -319,14 +306,7 @@
319
306
  </ContentPanel>
320
307
 
321
308
  {{#if @model.isStorefrontOrder}}
322
- <ContentPanel
323
- @title={{t "fleet-ops.operations.orders.index.view.order-summary"}}
324
- @prefixTitleRight={{if @model.payload.cod_amount "Cash" ""}}
325
- @prefixTitleRightClass="text-green-400"
326
- @open={{true}}
327
- @pad={{true}}
328
- @panelBodyClass="bg-white dark:bg-gray-800"
329
- >
309
+ <ContentPanel @title={{t "fleet-ops.operations.orders.index.view.order-summary"}} @prefixTitleRight={{if @model.payload.cod_amount "Cash" ""}} @prefixTitleRightClass="text-green-400" @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
330
310
  <div class="flex flex-col space-y-4 p-2 overflow-hidden">
331
311
  {{#each @model.payload.entities as |entity|}}
332
312
  <div class="flex flex-1">
@@ -399,7 +379,7 @@
399
379
  </ContentPanel>
400
380
  {{/if}}
401
381
 
402
- <ContentPanel @title={{t "fleet-ops.operations.orders.index.view.payload"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
382
+ <ContentPanel @title={{t "fleet-ops.operations.orders.index.view.payload"}} @open={{gt @model.payload.entities.length 0}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
403
383
  {{#if this.isMultiDropOrder}}
404
384
  <div class="space-y-2">
405
385
  {{#each this.entitiesByDestination as |group|}}
@@ -419,15 +399,7 @@
419
399
  <Badge @status={{group.waypoint.status_code}} />
420
400
  </div>
421
401
  <div class="flex items-start">
422
- <DropdownButton
423
- @triggerClass="mr-2"
424
- @iconClass="icon-text-height"
425
- @buttonSize="sm"
426
- @icon="ellipsis-h"
427
- @iconPrefix="fas"
428
- @contentClass="dropdown-menu"
429
- as |dd|
430
- >
402
+ <DropdownButton @triggerClass="mr-2" @iconClass="icon-text-height" @buttonSize="sm" @icon="ellipsis-h" @iconPrefix="fas" @contentClass="dropdown-menu" as |dd|>
431
403
  <div class="next-dd-menu mt-1 mx-0" aria-labelledby="user-menu">
432
404
  <div class="px-1">
433
405
  <div class="text-sm flex flex-row items-center px-3 py-1 rounded-md my-1 text-gray-300">
@@ -445,13 +417,7 @@
445
417
  </div>
446
418
  </div>
447
419
  </DropdownButton>
448
- <Button
449
- @icon="plus"
450
- @iconPrefix="fas"
451
- @text={{t "fleet-ops.operations.orders.index.view.add-item-button"}}
452
- @size="sm"
453
- @onClick={{fn this.addEntity group.waypoint}}
454
- />
420
+ <Button @icon="plus" @iconPrefix="fas" @text={{t "fleet-ops.operations.orders.index.view.add-item-button"}} @size="sm" @onClick={{fn this.addEntity group.waypoint}} />
455
421
  </div>
456
422
  </div>
457
423
  </div>
@@ -469,12 +435,7 @@
469
435
  <div class="dark:text-gray-100 truncate mb-2">
470
436
  {{entity.tracking}}
471
437
  </div>
472
- <Button
473
- @icon="pencil"
474
- @text={{t "fleet-ops.operations.orders.index.view.edit-item-button"}}
475
- @size="xs"
476
- @onClick={{fn this.editEntity entity}}
477
- />
438
+ <Button @icon="pencil" @text={{t "fleet-ops.operations.orders.index.view.edit-item-button"}} @size="xs" @onClick={{fn this.editEntity entity}} />
478
439
  </div>
479
440
  <div class="absolute top-0 right-0 p-2">
480
441
  <Button @icon="times" @iconPrefix="fas" @type="danger" @size="xs" @onClick={{fn this.removeEntity entity}} />
@@ -504,14 +465,7 @@
504
465
  <Button @icon="pencil" @text={{t "fleet-ops.operations.orders.index.view.edit-item-button"}} @size="sm" @onClick={{fn this.editEntity entity}} />
505
466
  </div>
506
467
  <div class="absolute top-0 right-0 p-2">
507
- <Button
508
- @icon="times"
509
- @iconPrefix="fas"
510
- @type="danger"
511
- @size="xs"
512
- @onClick={{fn this.removeEntity entity}}
513
- @wrapperClass={{if (eq index 0) "invisible"}}
514
- />
468
+ <Button @icon="times" @iconPrefix="fas" @type="danger" @size="xs" @onClick={{fn this.removeEntity entity}} @wrapperClass={{if (eq index 0) "invisible"}} />
515
469
  </div>
516
470
  </div>
517
471
  </div>
@@ -519,5 +473,81 @@
519
473
  </div>
520
474
  {{/if}}
521
475
  </ContentPanel>
476
+
477
+ <ContentPanel @title={{t "fleet-ops.operations.orders.index.view.documents-panel-title"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
478
+ <div class="space-y-4">
479
+ {{#if this.isUploading}}
480
+ <div
481
+ class="dropzone w-full rounded-lg px-4 py-8 bg-gray-50 dark:bg-gray-900 bg-opacity-25 text-gray-900 dark:text-white text-center flex flex-col items-center justify-center border-2 border-dashed border-gray-200 dark:border-indigo-500"
482
+ >
483
+ <div class="flex items-center justify-center py-5">
484
+ <Spinner class="text-sm dar:text-gray-100" @loadingMessage={{t "fleet-ops.common.uploading"}} />
485
+ </div>
486
+ </div>
487
+ {{else}}
488
+ {{#let (file-queue name="files" onFileAdded=this.queueFile accept=(join "," this.acceptedFileTypes)) as |queue|}}
489
+ <FileDropzone @queue={{queue}} class="dropzone file-dropzone" as |dropzone|>
490
+ {{#if dropzone.active}}
491
+ {{#if dropzone.valid}}
492
+ {{t "component.dropzone.drop-to-upload"}}
493
+ {{else}}
494
+ {{t "component.dropzone.invalid"}}
495
+ {{/if}}
496
+ {{else if queue.files.length}}
497
+ <div class="my-2">
498
+ <FaIcon @icon="folder-open" class="text-indigo-500 mr-2" />
499
+ {{t "component.dropzone.files-ready-for-upload" numOfFiles=(pluralize queue.files.length (t "component.dropzone.file"))}}
500
+ </div>
501
+ <div class="my-2">({{queue.progress}}%)</div>
502
+ {{else}}
503
+ <h4 class="font-semibold">
504
+ <FaIcon @icon="folder-open" @size="lg" class="text-indigo-500 mr-2" />
505
+ {{t "component.dropzone.upload-documents-files"}}
506
+ </h4>
507
+ <div>
508
+ {{#if dropzone.supported}}
509
+ <p class="text-sm my-5">{{t "component.dropzone.dropzone-supported-files"}}</p>
510
+ {{/if}}
511
+ <FileUpload @name="files" @for="files" @accept={{join "," this.acceptedFileTypes}} @multiple={{true}} @onFileAdded={{this.queueFile}}>
512
+ <a tabindex={{0}} class="btn btn-magic cursor-pointer ml-1">{{t "component.dropzone.or-select-button-text"}}</a>
513
+ </FileUpload>
514
+ </div>
515
+ {{/if}}
516
+ </FileDropzone>
517
+ {{/let}}
518
+ {{#if this.uploadQueue}}
519
+ <div class="mx-4">
520
+ <div class="flex items-center justify-between mb-4">
521
+ <span class="leading-6 dark:text-gray-100">{{t "component.dropzone.upload-queue"}}</span>
522
+ </div>
523
+ <div class="space-y-2 mb-4">
524
+ {{#each this.uploadQueue as |file|}}
525
+ <div class="flex items-center justify-between bg-blue-100 border border-blue-800 dark:border-blue-800 py-1.5 shadow-sm rounded-lg px-4">
526
+ <div class="text-xs text-blue-900 truncate">{{truncate-filename file.name 50}}</div>
527
+ <div class="flex items-center text-sm">
528
+ <Spinner class="text-blue-900 mr-2" />
529
+ <span class="font-bold text-blue-900">{{round file.progress}}%</span>
530
+ </div>
531
+ </div>
532
+ {{/each}}
533
+ </div>
534
+ </div>
535
+ {{/if}}
536
+ <div>
537
+ <div class="grid grid-cols-2 md:grid-cols-4 gap-2 md:gap-4">
538
+ {{#each @model.files as |file|}}
539
+ <File @file={{file}} @onDelete={{this.removeFile}} />
540
+ {{/each}}
541
+ </div>
542
+ </div>
543
+ {{/if}}
544
+ </div>
545
+ </ContentPanel>
546
+
547
+ <ContentPanel @title={{t "fleet-ops.operations.orders.index.view.comments-title"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800" @wrapperClass="mb-20">
548
+ <CommentThread @subject={{@model}} @subjectType="fleet-ops:order" />
549
+ </ContentPanel>
550
+
551
+ <Spacer @height="300px" />
522
552
  </Overlay::Body>
523
553
  </Overlay>
@@ -7,7 +7,7 @@
7
7
  {{/if}}
8
8
  </Overlay::Header>
9
9
 
10
- <Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4" @increaseInnerBodyHeightBy={{1000}}>
10
+ <Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4">
11
11
  <div>
12
12
  <div class="grid grid-cols-2 gap-2">
13
13
  <div class="input-group">
@@ -302,5 +302,7 @@
302
302
  </div>
303
303
  {{/if}}
304
304
  </ContentPanel>
305
+
306
+ <Spacer @height="300px" />
305
307
  </Overlay::Body>
306
308
  </Overlay>
package/composer.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbase/fleetops-api",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "keywords": [
6
6
  "fleetbase-extension",
@@ -22,7 +22,7 @@
22
22
  ],
23
23
  "require": {
24
24
  "php": "^7.4|^8.0",
25
- "fleetbase/core-api": "^1.3.12",
25
+ "fleetbase/core-api": "^1.3.13",
26
26
  "barryvdh/laravel-dompdf": "^2.0",
27
27
  "brick/geo": "0.7.2",
28
28
  "cknow/laravel-money": "^7.1",
package/extension.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Fleet-Ops",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "repository": "https://github.com/fleetbase/fleetops",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fleetbase/fleetops-engine",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "fleetbase": {
6
6
  "route": "fleet-ops",
@@ -44,8 +44,8 @@
44
44
  "dependencies": {
45
45
  "@babel/core": "^7.23.2",
46
46
  "@fleetbase/ember-core": "^0.2.1",
47
- "@fleetbase/ember-ui": "^0.2.9",
48
- "@fleetbase/fleetops-data": "^0.1.7",
47
+ "@fleetbase/ember-ui": "^0.2.10",
48
+ "@fleetbase/fleetops-data": "^0.1.8",
49
49
  "@fleetbase/leaflet-routing-machine": "^3.2.16",
50
50
  "@fortawesome/ember-fontawesome": "^0.4.1",
51
51
  "@fortawesome/fontawesome-svg-core": "^6.4.0",
@@ -376,7 +376,7 @@ class DriverController extends Controller
376
376
  }
377
377
 
378
378
  // Get the user's company for this driver profile
379
- $company = $this->_getDriverCompanyFromUser($user);
379
+ $company = static::getDriverCompanyFromUser($user);
380
380
 
381
381
  // Get driver record
382
382
  $driver = Driver::where(
@@ -414,7 +414,7 @@ class DriverController extends Controller
414
414
  }
415
415
 
416
416
  // Get the user's company for this driver profile
417
- $company = $this->_getDriverCompanyFromUser($user);
417
+ $company = static::getDriverCompanyFromUser($user);
418
418
 
419
419
  // generate verification token
420
420
  try {
@@ -464,7 +464,7 @@ class DriverController extends Controller
464
464
  }
465
465
 
466
466
  // Get the user's company for this driver profile
467
- $company = $this->_getDriverCompanyFromUser($user);
467
+ $company = static::getDriverCompanyFromUser($user);
468
468
 
469
469
  // get driver record
470
470
  $driver = Driver::where(
@@ -488,19 +488,33 @@ class DriverController extends Controller
488
488
  }
489
489
 
490
490
  /**
491
- * Patches phone number with international code.
491
+ * Gets the current organization/company for the driver
492
+ *
493
+ * @param string $id
494
+ * @param \Illuminate\Http\Request $request
495
+ * @return \Fleetbase\Http\Resources\Organization
492
496
  */
493
- public static function phone(string $phone = null): string
497
+ public function currentOrganization(string $id, Request $request)
494
498
  {
495
- if ($phone === null) {
496
- $phone = request()->input('phone');
499
+ try {
500
+ $driver = Driver::findRecordOrFail($id);
501
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
502
+ return response()->apiError('Driver resource not found.', 404);
497
503
  }
498
504
 
499
- if (!Str::startsWith($phone, '+')) {
500
- $phone = '+' . $phone;
505
+ // Get the driver user account
506
+ $user = $driver->getUser();
507
+ if (!$user) {
508
+ return response()->apiError('Driver has not user account.');
501
509
  }
502
510
 
503
- return $phone;
511
+ // Get the user account company
512
+ $company = Flow::getCompanySessionForUser($user);
513
+ if (!$company) {
514
+ return response()->apiError('No company found for this driver.');
515
+ }
516
+
517
+ return new Organization($company);
504
518
  }
505
519
 
506
520
  /**
@@ -548,23 +562,26 @@ class DriverController extends Controller
548
562
  );
549
563
  }
550
564
 
551
- // get the next organization
565
+ // Get the next organization
552
566
  $company = Company::where('public_id', $nextOrganization)->first();
553
567
 
554
568
  if ($company->uuid === $driver->user->company_uuid) {
555
- return response()->json([
556
- 'error' => 'Driver is already on this organizations session',
557
- ]);
569
+ return response()->apiError('Driver is already on this organizations session.');
558
570
  }
559
571
 
560
572
  if (!CompanyUser::where(['user_uuid' => $driver->user_uuid, 'company_uuid' => $company->uuid])->exists()) {
561
- return response()->json([
562
- 'errors' => ['You do not belong to this organization'],
563
- ]);
573
+ return response()->apiError('You do not belong to this organization');
574
+ }
575
+
576
+ // Get the driver user account
577
+ $user = $driver->getUser();
578
+ if (!$user) {
579
+ return response()->apiError('Driver has not user account.');
564
580
  }
565
581
 
566
- $driver->user->assignCompany($company);
567
- Auth::setSession($driver->user);
582
+ // Assign user to company and update their session
583
+ $user->assignCompany($company);
584
+ Auth::setSession($user);
568
585
 
569
586
  return new Organization($company);
570
587
  }
@@ -700,7 +717,13 @@ class DriverController extends Controller
700
717
  return response()->json($route);
701
718
  }
702
719
 
703
- private function _getDriverCompanyFromUser(User $user): ?Company
720
+ /**
721
+ * Get the drivers current company using their user account.
722
+ *
723
+ * @param \Fleetbase\Models\User $user
724
+ * @return \Fleetbase\Models\Company|null
725
+ */
726
+ private static function getDriverCompanyFromUser(User $user): ?Company
704
727
  {
705
728
  // company defaults to null
706
729
  $company = null;
@@ -719,4 +742,20 @@ class DriverController extends Controller
719
742
 
720
743
  return $company;
721
744
  }
745
+
746
+ /**
747
+ * Patches phone number with international code.
748
+ */
749
+ private static function phone(string $phone = null): string
750
+ {
751
+ if ($phone === null) {
752
+ $phone = request()->input('phone');
753
+ }
754
+
755
+ if (!Str::startsWith($phone, '+')) {
756
+ $phone = '+' . $phone;
757
+ }
758
+
759
+ return $phone;
760
+ }
722
761
  }
@@ -422,6 +422,8 @@ class OrderController extends Controller
422
422
  public function query(Request $request)
423
423
  {
424
424
  $results = Order::queryWithRequest($request, function (&$query, $request) {
425
+ $query->where('company_uuid', session('company'));
426
+
425
427
  if ($request->has('payload')) {
426
428
  $query->whereHas('payload', function ($q) use ($request) {
427
429
  $q->where('public_id', $request->input('payload'));
@@ -94,8 +94,9 @@ class DriverController extends FleetOpsController
94
94
  ->filter()
95
95
  ->toArray();
96
96
 
97
- // set the user
98
- $input['company_uuid'] = session('company');
97
+ // Get current session company
98
+ $company = Auth::getCompany();
99
+ $input['company_uuid'] = session('company', $company->uuid);
99
100
  $input['user_uuid'] = $existingUser->uuid;
100
101
  $input['slug'] = $existingUser->slug;
101
102
 
@@ -107,6 +108,18 @@ class DriverController extends FleetOpsController
107
108
  // create the profile
108
109
  $driverProfile = Driver::create($input);
109
110
 
111
+ // Assign user to company
112
+ if ($company) {
113
+ $existingUser->assignCompany($company);
114
+
115
+ // create company user
116
+ CompanyUser::create([
117
+ 'user_uuid' => $existingUser->uuid,
118
+ 'company_uuid' => $company->uuid,
119
+ 'status' => $isOrganizationMember ? 'active' : 'pending'
120
+ ]);
121
+ }
122
+
110
123
  if (!$isOrganizationMember) {
111
124
  // send invitation to user
112
125
  $invitation = Invite::create([
@@ -159,7 +172,7 @@ class DriverController extends FleetOpsController
159
172
 
160
173
  // Get current session company
161
174
  $company = Auth::getCompany();
162
- $userInput['company_uuid'] = $company ? $company->uuid : session('company');
175
+ $userInput['company_uuid'] = session('company', $company->uuid);
163
176
 
164
177
  // Create user account
165
178
  $user = User::create($userInput);
@@ -82,6 +82,7 @@ class OrderController extends FleetOpsController
82
82
  $payload = Utils::get($input, 'payload');
83
83
  $waypoints = Utils::get($input, 'payload.waypoints');
84
84
  $entities = Utils::get($input, 'payload.entities');
85
+ $uploads = Utils::get($input, 'files', []);
85
86
 
86
87
  // save order route & payload with request input
87
88
  $order
@@ -91,6 +92,16 @@ class OrderController extends FleetOpsController
91
92
  ->insertWaypoints($waypoints)
92
93
  ->insertEntities($entities);
93
94
 
95
+ // If order creation includes files assosciate each to this order
96
+ if ($uploads) {
97
+ $ids = collect($uploads)->pluck('uuid');
98
+ $files = File::whereIn('uuid', $ids)->get();
99
+
100
+ foreach ($files as $file) {
101
+ $file->setKey($order);
102
+ }
103
+ }
104
+
94
105
  // if it's integrated vendor order apply to meta
95
106
  if ($isIntegratedVendorOrder) {
96
107
  $order->updateMeta(
@@ -4,6 +4,7 @@ namespace Fleetbase\FleetOps\Http\Resources\v1;
4
4
 
5
5
  use Fleetbase\FleetOps\Support\Utils;
6
6
  use Fleetbase\Http\Resources\FleetbaseResource;
7
+ use Fleetbase\Http\Resources\Comment;
7
8
  use Fleetbase\Support\Http;
8
9
  use Fleetbase\Support\Resolve;
9
10
 
@@ -43,6 +44,8 @@ class Order extends FleetbaseResource
43
44
  'driver_assigned' => new Driver($this->driverAssigned()->without(['jobs', 'currentJob'])->first()),
44
45
  'tracking_number' => new TrackingNumber($this->trackingNumber),
45
46
  'tracking_statuses' => $this->whenLoaded('trackingStatuses', TrackingStatus::collection($this->trackingStatuses)),
47
+ 'comments' => $this->when(Http::isInternalRequest(), Comment::collection($this->comments)),
48
+ 'files' => $this->when(Http::isInternalRequest(), $this->files),
46
49
  'purchase_rate' => new PurchaseRate($this->purchaseRate),
47
50
  'notes' => $this->notes,
48
51
  'type' => $this->type,