@fleetbase/fleetops-engine 0.6.38 → 0.6.39
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.
- package/addon/components/activity/form.hbs +2 -12
- package/addon/components/activity/logic-builder.hbs +1 -1
- package/addon/components/custom-entity/form.hbs +4 -20
- package/addon/components/device/form.hbs +3 -15
- package/addon/components/device/panel-header.hbs +13 -2
- package/addon/components/driver/details.hbs +33 -2
- package/addon/components/driver/form.hbs +42 -0
- package/addon/components/driver/panel-header.hbs +8 -1
- package/addon/components/driver/schedule.hbs +115 -76
- package/addon/components/driver/schedule.js +349 -157
- package/addon/components/driver-onboard-settings.hbs +2 -8
- package/addon/components/entity-field-editing-settings.hbs +2 -5
- package/addon/components/equipment/card.hbs +49 -0
- package/addon/components/equipment/card.js +6 -0
- package/addon/components/equipment/details.hbs +83 -44
- package/addon/components/equipment/form.hbs +111 -41
- package/addon/components/equipment/form.js +78 -10
- package/addon/components/equipment/panel-header.hbs +36 -0
- package/addon/components/equipment/panel-header.js +2 -0
- package/addon/components/fleet/driver-listing.hbs +3 -1
- package/addon/components/fleet/vehicle-listing.hbs +4 -7
- package/addon/components/fleet-panel/vehicle-listing.hbs +1 -6
- package/addon/components/fuel-report/form.hbs +1 -5
- package/addon/components/layout/fleet-ops-sidebar.hbs +40 -36
- package/addon/components/layout/fleet-ops-sidebar.js +61 -10
- package/addon/components/maintenance/cost-panel.hbs +176 -0
- package/addon/components/maintenance/cost-panel.js +241 -0
- package/addon/components/maintenance/details.hbs +123 -60
- package/addon/components/maintenance/form.hbs +138 -78
- package/addon/components/maintenance/form.js +131 -6
- package/addon/components/maintenance/panel-header.hbs +31 -0
- package/addon/components/maintenance/panel-header.js +2 -0
- package/addon/components/maintenance-schedule/details.hbs +260 -0
- package/addon/components/maintenance-schedule/details.js +158 -0
- package/addon/components/maintenance-schedule/form.hbs +287 -0
- package/addon/components/maintenance-schedule/form.js +199 -0
- package/addon/components/map/container.hbs +1 -1
- package/addon/components/map/drawer/device-event-listing.hbs +1 -1
- package/addon/components/map/drawer/driver-listing.hbs +1 -6
- package/addon/components/map/drawer/place-listing.hbs +1 -6
- package/addon/components/map/drawer/vehicle-listing.hbs +1 -6
- package/addon/components/map/drawer.hbs +8 -1
- package/addon/components/map/leaflet-live-map.hbs +2 -1
- package/addon/components/map/toolbar/visibility-control-panel.hbs +1 -1
- package/addon/components/map/toolbar.hbs +4 -29
- package/addon/components/modals/add-driver-shift.hbs +155 -0
- package/addon/components/modals/add-driver-shift.js +210 -0
- package/addon/components/modals/bulk-assign-orders.hbs +67 -0
- package/addon/components/modals/driver-shift.hbs +43 -0
- package/addon/components/modals/driver-shift.js +56 -0
- package/addon/components/modals/entity-form.hbs +5 -28
- package/addon/components/modals/orchestrator-import.hbs +351 -0
- package/addon/components/modals/orchestrator-import.js +807 -0
- package/addon/components/modals/order-config-new-status.hbs +1 -5
- package/addon/components/modals/scheduling-conflict.hbs +47 -0
- package/addon/components/modals/scheduling-conflict.js +53 -0
- package/addon/components/modals/send-work-order.hbs +91 -0
- package/addon/components/modals/send-work-order.js +3 -0
- package/addon/components/modals/service-area-form.hbs +1 -6
- package/addon/components/modals/set-driver-availability.hbs +50 -0
- package/addon/components/modals/set-driver-availability.js +57 -0
- package/addon/components/modals/update-order-activity.hbs +13 -9
- package/addon/components/modals/user-form.hbs +1 -5
- package/addon/components/modals/vehicle-form.hbs +17 -102
- package/addon/components/modals/vendor-form.hbs +15 -82
- package/addon/components/orchestrator/card-fields-settings.hbs +76 -0
- package/addon/components/orchestrator/card-fields-settings.js +134 -0
- package/addon/components/orchestrator/order-pool.hbs +264 -0
- package/addon/components/orchestrator/order-pool.js +394 -0
- package/addon/components/orchestrator/phase-builder.hbs +162 -0
- package/addon/components/orchestrator/phase-builder.js +162 -0
- package/addon/components/orchestrator/plan-viewer.hbs +278 -0
- package/addon/components/orchestrator/plan-viewer.js +342 -0
- package/addon/components/orchestrator/resource-panel.hbs +301 -0
- package/addon/components/orchestrator/resource-panel.js +106 -0
- package/addon/components/orchestrator-workbench.hbs +318 -0
- package/addon/components/orchestrator-workbench.js +1087 -0
- package/addon/components/order/details/custom-fields.hbs +10 -1
- package/addon/components/order/details/detail.hbs +37 -2
- package/addon/components/order/details/detail.js +0 -1
- package/addon/components/order/details/integrated-vendor-details.hbs +4 -4
- package/addon/components/order/details/notes.hbs +1 -7
- package/addon/components/order/details/route.hbs +1 -5
- package/addon/components/order/form/details.hbs +44 -10
- package/addon/components/order/form/details.js +57 -0
- package/addon/components/order/form/notes.hbs +1 -7
- package/addon/components/order/form/payload.hbs +1 -7
- package/addon/components/order/form/route.hbs +3 -15
- package/addon/components/order/header.hbs +1 -7
- package/addon/components/order/route-editor.hbs +4 -25
- package/addon/components/order/schedule-card.hbs +102 -95
- package/addon/components/order/schedule-card.js +8 -3
- package/addon/components/order-config-manager/details.hbs +2 -10
- package/addon/components/order-config-manager/entities.hbs +1 -7
- package/addon/components/order-config-manager.hbs +1 -6
- package/addon/components/part/card.hbs +49 -0
- package/addon/components/part/card.js +6 -0
- package/addon/components/part/details.hbs +102 -56
- package/addon/components/part/form.hbs +131 -56
- package/addon/components/part/form.js +78 -11
- package/addon/components/part/panel-header.hbs +36 -0
- package/addon/components/part/panel-header.js +2 -0
- package/addon/components/place/form.hbs +1 -7
- package/addon/components/sensor/details.hbs +1 -1
- package/addon/components/sensor/form.hbs +5 -3
- package/addon/components/sensor/panel-header.hbs +8 -1
- package/addon/components/service-area/form.hbs +1 -6
- package/addon/components/service-rate/form.hbs +12 -60
- package/addon/components/telematic/form.hbs +6 -2
- package/addon/components/vehicle/details/maintenance-history.hbs +42 -0
- package/addon/components/vehicle/details/maintenance-history.js +32 -0
- package/addon/components/vehicle/details/schedules.hbs +40 -0
- package/addon/components/vehicle/details/schedules.js +32 -0
- package/addon/components/vehicle/details/work-orders.hbs +42 -0
- package/addon/components/vehicle/details/work-orders.js +32 -0
- package/addon/components/vehicle/details.hbs +30 -0
- package/addon/components/vehicle/form.hbs +39 -0
- package/addon/components/vehicle/panel-header.hbs +19 -49
- package/addon/components/warranty/details.hbs +3 -2
- package/addon/components/warranty/form.hbs +3 -17
- package/addon/components/work-order/details.hbs +135 -40
- package/addon/components/work-order/form.hbs +178 -45
- package/addon/components/work-order/form.js +197 -4
- package/addon/components/work-order/panel-header.hbs +31 -0
- package/addon/components/work-order/panel-header.js +2 -0
- package/addon/controllers/connectivity/devices/index/details.js +1 -1
- package/addon/controllers/maintenance/equipment/index/details/index.js +0 -1
- package/addon/controllers/maintenance/equipment/index/details.js +36 -1
- package/addon/controllers/maintenance/equipment/index/edit.js +56 -1
- package/addon/controllers/maintenance/equipment/index/new.js +32 -1
- package/addon/controllers/maintenance/equipment/index.js +127 -113
- package/addon/controllers/maintenance/maintenances/index/details/index.js +3 -0
- package/addon/controllers/maintenance/maintenances/index/details.js +54 -0
- package/addon/controllers/maintenance/maintenances/index/edit.js +68 -0
- package/addon/controllers/maintenance/maintenances/index/new.js +34 -0
- package/addon/controllers/maintenance/maintenances/index.js +191 -0
- package/addon/controllers/maintenance/parts/index/details/index.js +0 -1
- package/addon/controllers/maintenance/parts/index/details.js +36 -1
- package/addon/controllers/maintenance/parts/index/edit.js +56 -1
- package/addon/controllers/maintenance/parts/index/new.js +32 -1
- package/addon/controllers/maintenance/parts/index.js +135 -113
- package/addon/controllers/maintenance/schedules/index/details.js +115 -0
- package/addon/controllers/maintenance/schedules/index/edit.js +41 -0
- package/addon/controllers/maintenance/schedules/index/new.js +33 -0
- package/addon/controllers/maintenance/schedules/index.js +280 -0
- package/addon/controllers/maintenance/work-orders/index/details.js +41 -1
- package/addon/controllers/maintenance/work-orders/index/edit.js +67 -1
- package/addon/controllers/maintenance/work-orders/index/new.js +43 -1
- package/addon/controllers/maintenance/work-orders/index.js +105 -113
- package/addon/controllers/management/drivers/index/details.js +6 -1
- package/addon/controllers/management/vehicles/index/details.js +65 -0
- package/addon/controllers/management/vehicles/index.js +18 -0
- package/addon/controllers/operations/orchestrator.js +10 -0
- package/addon/controllers/operations/orders/index.js +6 -0
- package/addon/controllers/operations/scheduler/fleet-schedule.js +341 -0
- package/addon/controllers/operations/scheduler/index.js +799 -275
- package/addon/controllers/operations/scheduler.js +21 -0
- package/addon/controllers/settings/orchestrator.js +70 -0
- package/addon/controllers/settings/scheduling.js +155 -0
- package/addon/extension.js +19 -0
- package/addon/instance-initializers/register-vroom-allocation.js +27 -0
- package/addon/models/maintenance-schedule.js +61 -0
- package/addon/routes/maintenance/equipment/index/details.js +27 -1
- package/addon/routes/maintenance/equipment/index/edit.js +27 -1
- package/addon/routes/maintenance/maintenances/index/details/index.js +3 -0
- package/addon/routes/maintenance/maintenances/index/details.js +29 -0
- package/addon/routes/maintenance/maintenances/index/edit.js +29 -0
- package/addon/routes/maintenance/maintenances/index/new.js +3 -0
- package/addon/routes/maintenance/maintenances/index.js +23 -0
- package/addon/routes/maintenance/maintenances.js +3 -0
- package/addon/routes/maintenance/parts/index/details.js +27 -1
- package/addon/routes/maintenance/parts/index/edit.js +27 -1
- package/addon/routes/maintenance/schedules/index/details/index.js +2 -0
- package/addon/routes/maintenance/schedules/index/details/work-orders.js +11 -0
- package/addon/routes/maintenance/schedules/index/details.js +25 -0
- package/addon/routes/maintenance/schedules/index/edit.js +25 -0
- package/addon/routes/maintenance/schedules/index/new.js +2 -0
- package/addon/routes/maintenance/schedules/index.js +21 -0
- package/addon/routes/maintenance/schedules.js +2 -0
- package/addon/routes/maintenance/work-orders/index/details.js +27 -1
- package/addon/routes/maintenance/work-orders/index/edit.js +27 -1
- package/addon/routes/management/vehicles/index/details/maintenance-history.js +3 -0
- package/addon/routes/management/vehicles/index/details/schedules.js +3 -0
- package/addon/routes/management/vehicles/index/details/work-orders.js +3 -0
- package/addon/routes/operations/orchestrator.js +23 -0
- package/addon/routes/operations/scheduler/fleet-schedule.js +28 -0
- package/addon/routes/operations/scheduler/index.js +48 -26
- package/addon/routes/operations/scheduler.js +14 -1
- package/addon/routes/settings/orchestrator.js +27 -0
- package/addon/routes/settings/scheduling.js +3 -0
- package/addon/routes.js +31 -1
- package/addon/services/driver-actions.js +40 -7
- package/addon/services/driver-scheduling.js +4 -1
- package/addon/services/equipment-actions.js +15 -5
- package/addon/services/leaflet-map-manager.js +14 -6
- package/addon/services/maintenance-actions.js +17 -14
- package/addon/services/maintenance-schedule-actions.js +118 -0
- package/addon/services/orchestration-engine-interface.js +49 -0
- package/addon/services/orchestration-engine.js +74 -0
- package/addon/services/order-actions.js +15 -0
- package/addon/services/order-allocation.js +116 -0
- package/addon/services/part-actions.js +12 -2
- package/addon/services/scheduling.js +316 -0
- package/addon/services/vehicle-actions.js +70 -7
- package/addon/services/vroom-allocation-engine.js +45 -0
- package/addon/services/work-order-actions.js +80 -0
- package/addon/styles/fleetops-engine.css +1658 -0
- package/addon/templates/analytics/reports/index/edit.hbs +1 -1
- package/addon/templates/analytics/reports/index/new.hbs +1 -1
- package/addon/templates/application.hbs +6 -1
- package/addon/templates/connectivity/devices/index/details/events.hbs +0 -1
- package/addon/templates/connectivity/devices.hbs +0 -1
- package/addon/templates/connectivity/events/index/details.hbs +0 -1
- package/addon/templates/connectivity/events.hbs +0 -1
- package/addon/templates/connectivity/sensors.hbs +0 -1
- package/addon/templates/connectivity/telematics/index/details/devices.hbs +0 -1
- package/addon/templates/connectivity/telematics/index/details/events.hbs +0 -1
- package/addon/templates/connectivity/telematics/index/details/sensors.hbs +0 -1
- package/addon/templates/connectivity/telematics.hbs +0 -1
- package/addon/templates/connectivity/tracking.hbs +0 -1
- package/addon/templates/connectivity.hbs +0 -1
- package/addon/templates/maintenance/equipment/index/details/index.hbs +1 -2
- package/addon/templates/maintenance/equipment/index/details.hbs +15 -2
- package/addon/templates/maintenance/equipment/index/edit.hbs +12 -2
- package/addon/templates/maintenance/equipment/index/new.hbs +1 -2
- package/addon/templates/maintenance/equipment/index.hbs +48 -13
- package/addon/templates/maintenance/equipment.hbs +0 -1
- package/addon/templates/maintenance/maintenances/index/details/index.hbs +1 -0
- package/addon/templates/maintenance/maintenances/index/details.hbs +15 -0
- package/addon/templates/maintenance/maintenances/index/edit.hbs +12 -0
- package/addon/templates/maintenance/maintenances/index/new.hbs +11 -0
- package/addon/templates/maintenance/maintenances/index.hbs +14 -0
- package/addon/templates/maintenance/maintenances.hbs +1 -0
- package/addon/templates/maintenance/parts/index/details/index.hbs +1 -2
- package/addon/templates/maintenance/parts/index/details.hbs +15 -2
- package/addon/templates/maintenance/parts/index/edit.hbs +12 -2
- package/addon/templates/maintenance/parts/index/new.hbs +1 -2
- package/addon/templates/maintenance/parts/index.hbs +48 -13
- package/addon/templates/maintenance/parts.hbs +0 -1
- package/addon/templates/maintenance/schedules/index/details/index.hbs +1 -0
- package/addon/templates/maintenance/schedules/index/details/work-orders.hbs +39 -0
- package/addon/templates/maintenance/schedules/index/details.hbs +14 -0
- package/addon/templates/maintenance/schedules/index/edit.hbs +12 -0
- package/addon/templates/maintenance/schedules/index/new.hbs +11 -0
- package/addon/templates/maintenance/schedules/index.hbs +40 -0
- package/addon/templates/maintenance/schedules.hbs +1 -0
- package/addon/templates/maintenance/work-orders/index/details.hbs +2 -1
- package/addon/templates/maintenance/work-orders/index/edit.hbs +2 -4
- package/addon/templates/maintenance/work-orders/index/new.hbs +1 -2
- package/addon/templates/maintenance/work-orders.hbs +0 -1
- package/addon/templates/management/contacts/customers/edit.hbs +1 -2
- package/addon/templates/management/contacts/customers/new.hbs +1 -2
- package/addon/templates/management/contacts/customers.hbs +1 -1
- package/addon/templates/management/contacts/index/edit.hbs +1 -2
- package/addon/templates/management/contacts/index/new.hbs +1 -2
- package/addon/templates/management/drivers/index/details/orders.hbs +0 -1
- package/addon/templates/management/drivers/index/edit.hbs +1 -2
- package/addon/templates/management/drivers/index/new.hbs +1 -2
- package/addon/templates/management/fleets/index/edit.hbs +1 -2
- package/addon/templates/management/fleets/index/new.hbs +1 -2
- package/addon/templates/management/fleets/index.hbs +1 -2
- package/addon/templates/management/fuel-reports/index/edit.hbs +1 -2
- package/addon/templates/management/fuel-reports/index/new.hbs +1 -2
- package/addon/templates/management/fuel-reports/index.hbs +1 -2
- package/addon/templates/management/issues/index/edit.hbs +1 -2
- package/addon/templates/management/issues/index/new.hbs +1 -2
- package/addon/templates/management/issues/index.hbs +1 -2
- package/addon/templates/management/places/index/details/activity.hbs +0 -1
- package/addon/templates/management/places/index/details/comments.hbs +0 -1
- package/addon/templates/management/places/index/details/documents.hbs +0 -1
- package/addon/templates/management/places/index/details/map.hbs +0 -1
- package/addon/templates/management/places/index/details/operations.hbs +0 -1
- package/addon/templates/management/places/index/details/performance.hbs +0 -1
- package/addon/templates/management/places/index/details/rules.hbs +0 -1
- package/addon/templates/management/vehicles/index/details/equipment.hbs +0 -1
- package/addon/templates/management/vehicles/index/details/maintenance-history.hbs +2 -0
- package/addon/templates/management/vehicles/index/details/schedules.hbs +2 -0
- package/addon/templates/management/vehicles/index/details/work-orders.hbs +2 -0
- package/addon/templates/management/vehicles/index/details.hbs +1 -1
- package/addon/templates/management/vehicles/index/edit.hbs +1 -2
- package/addon/templates/management/vehicles/index/new.hbs +1 -2
- package/addon/templates/management/vendors/index/edit.hbs +1 -2
- package/addon/templates/management/vendors/index/new.hbs +1 -2
- package/addon/templates/management/vendors/index.hbs +1 -2
- package/addon/templates/management/vendors/integrated.hbs +1 -2
- package/addon/templates/operations/orchestrator.hbs +1 -0
- package/addon/templates/operations/orders/index.hbs +6 -1
- package/addon/templates/operations/scheduler/fleet-schedule.hbs +41 -0
- package/addon/templates/operations/scheduler/index.hbs +147 -88
- package/addon/templates/operations/scheduler.hbs +7 -1
- package/addon/templates/settings/avatars.hbs +1 -1
- package/addon/templates/settings/orchestrator.hbs +65 -0
- package/addon/templates/settings/payments/index.hbs +1 -5
- package/addon/templates/settings/scheduling.hbs +82 -0
- package/addon/utils/create-full-calendar-event-from-order.js +52 -14
- package/addon/utils/create-full-calendar-event-from-schedule-item.js +50 -0
- package/addon/utils/fleet-ops-options.js +254 -0
- package/addon/utils/route-colors.js +99 -0
- package/addon/utils/to-calendar-date.js +70 -0
- package/app/components/driver/schedule.js +1 -0
- package/app/components/maintenance/cost-panel.js +1 -0
- package/app/components/maintenance/panel-header.js +1 -0
- package/app/components/maintenance-schedule/details.js +1 -0
- package/app/components/maintenance-schedule/form.js +1 -0
- package/app/components/modals/add-driver-shift.js +1 -0
- package/app/components/modals/bulk-assign-orders.js +1 -0
- package/app/components/modals/driver-shift.js +1 -0
- package/app/components/modals/orchestrator-import.js +1 -0
- package/app/components/modals/scheduling-conflict.js +1 -0
- package/app/components/modals/send-work-order.js +1 -0
- package/app/components/modals/set-driver-availability.js +1 -0
- package/app/components/orchestrator/card-fields-settings.js +1 -0
- package/app/components/orchestrator/order-pool.js +1 -0
- package/app/components/orchestrator/phase-builder.js +1 -0
- package/app/components/orchestrator/plan-viewer.js +1 -0
- package/app/components/orchestrator/resource-panel.js +1 -0
- package/app/components/orchestrator-workbench.js +1 -0
- package/app/components/vehicle/details/maintenance-history.js +1 -0
- package/app/components/vehicle/details/schedules.js +1 -0
- package/app/components/vehicle/details/work-orders.js +1 -0
- package/app/controllers/operations/orchestrator.js +1 -0
- package/app/controllers/settings/orchestrator.js +1 -0
- package/app/controllers/settings/scheduling.js +1 -0
- package/app/routes/operations/orchestrator.js +1 -0
- package/app/routes/settings/orchestrator.js +1 -0
- package/app/routes/settings/scheduling.js +1 -0
- package/app/services/maintenance-schedule-actions.js +1 -0
- package/app/services/orchestration-engine-interface.js +1 -0
- package/app/services/orchestration-engine.js +1 -0
- package/app/services/order-allocation.js +1 -0
- package/app/services/scheduling.js +1 -0
- package/app/services/vroom-allocation-engine.js +1 -0
- package/app/templates/settings/scheduling.js +1 -0
- package/app/utils/create-full-calendar-event-from-schedule-item.js +1 -0
- package/app/utils/route-colors.js +1 -0
- package/composer.json +5 -3
- package/extension.json +1 -1
- package/package.json +6 -5
- package/server/config/fleetops.php +20 -1
- package/server/migrations/2025_08_28_054927_create_parts_table.php +2 -2
- package/server/migrations/2025_08_28_054932_add_public_id_to_maintenance_tables.php +45 -0
- package/server/migrations/2025_09_01_000001_create_maintenance_schedules_table.php +88 -0
- package/server/migrations/2026_04_01_000001_fix_monetary_columns_in_parts_table.php +48 -0
- package/server/migrations/2026_04_01_000003_add_photo_uuid_to_equipment_and_parts_tables.php +61 -0
- package/server/migrations/2026_04_01_000004_add_public_id_to_equipments_table.php +38 -0
- package/server/migrations/2026_04_01_000005_add_missing_columns_to_parts_table.php +67 -0
- package/server/migrations/2026_04_04_000001_add_reminder_offsets_to_maintenance_schedules.php +44 -0
- package/server/migrations/2026_04_08_000001_add_orchestrator_columns_to_vehicles_table.php +58 -0
- package/server/migrations/2026_04_08_000002_add_orchestrator_columns_to_drivers_table.php +41 -0
- package/server/migrations/2026_04_08_000003_add_orchestrator_columns_to_orders_table.php +38 -0
- package/server/migrations/2026_04_08_000004_add_orchestrator_columns_to_payloads_table.php +41 -0
- package/server/migrations/2026_04_08_000005_add_orchestrator_columns_to_waypoints_table.php +38 -0
- package/server/migrations/2026_04_09_000001_create_manifests_table.php +48 -0
- package/server/migrations/2026_04_09_000002_create_manifest_stops_table.php +48 -0
- package/server/migrations/2026_04_09_000003_add_manifest_uuid_to_orders_table.php +28 -0
- package/server/migrations/2026_04_13_000001_add_pod_notes_columns_to_waypoints_table.php +39 -0
- package/server/resources/views/mail/maintenance-schedule-reminder.blade.php +59 -0
- package/server/resources/views/mail/work-order-dispatched.blade.php +67 -0
- package/server/src/Auth/Schemas/FleetOps.php +44 -0
- package/server/src/Console/Commands/ProcessMaintenanceTriggers.php +150 -0
- package/server/src/Console/Commands/SendMaintenanceReminders.php +128 -0
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +1 -0
- package/server/src/Http/Controllers/Internal/v1/EquipmentController.php +27 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +9 -2
- package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +165 -0
- package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +304 -0
- package/server/src/Http/Controllers/Internal/v1/ManifestController.php +138 -0
- package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +975 -0
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +42 -0
- package/server/src/Http/Controllers/Internal/v1/PartController.php +27 -0
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +118 -0
- package/server/src/Http/Controllers/Internal/v1/Traits/DriverSchedulingTrait.php +214 -0
- package/server/src/Http/Controllers/Internal/v1/WorkOrderController.php +68 -0
- package/server/src/Http/Resources/v1/Driver.php +1 -0
- package/server/src/Http/Resources/v1/Maintenance.php +138 -0
- package/server/src/Http/Resources/v1/MaintenanceSchedule.php +137 -0
- package/server/src/Http/Resources/v1/Orchestrator/Order.php +116 -0
- package/server/src/Http/Resources/v1/Order.php +7 -4
- package/server/src/Http/Resources/v1/Waypoint.php +7 -0
- package/server/src/Http/Resources/v1/WorkOrder.php +136 -0
- package/server/src/Imports/EquipmentImport.php +32 -0
- package/server/src/Imports/MaintenanceImport.php +32 -0
- package/server/src/Imports/MaintenanceScheduleImport.php +32 -0
- package/server/src/Imports/PartImport.php +32 -0
- package/server/src/Imports/WorkOrderImport.php +32 -0
- package/server/src/Jobs/ProcessAllocationJob.php +119 -0
- package/server/src/Listeners/HandleDeliveryCompletion.php +47 -0
- package/server/src/Listeners/NotifyDriverOnShiftChange.php +63 -0
- package/server/src/Mail/MaintenanceScheduleReminder.php +68 -0
- package/server/src/Mail/WorkOrderDispatched.php +58 -0
- package/server/src/Models/Asset.php +2 -2
- package/server/src/Models/Device.php +1 -1
- package/server/src/Models/Driver.php +82 -4
- package/server/src/Models/Equipment.php +62 -2
- package/server/src/Models/Maintenance.php +127 -9
- package/server/src/Models/MaintenanceSchedule.php +353 -0
- package/server/src/Models/Manifest.php +214 -0
- package/server/src/Models/ManifestStop.php +162 -0
- package/server/src/Models/Order.php +70 -0
- package/server/src/Models/OrderConfig.php +5 -2
- package/server/src/Models/Part.php +69 -3
- package/server/src/Models/Payload.php +7 -2
- package/server/src/Models/Place.php +1 -1
- package/server/src/Models/Sensor.php +1 -1
- package/server/src/Models/ServiceQuote.php +1 -1
- package/server/src/Models/Vehicle.php +20 -1
- package/server/src/Models/Warranty.php +1 -1
- package/server/src/Models/Waypoint.php +7 -1
- package/server/src/Models/WorkOrder.php +122 -12
- package/server/src/Notifications/DriverShiftChanged.php +110 -0
- package/server/src/Observers/WorkOrderObserver.php +107 -0
- package/server/src/Orchestration/Contracts/OrchestrationEngineInterface.php +63 -0
- package/server/src/Orchestration/Engines/DriverAssignmentEngine.php +265 -0
- package/server/src/Orchestration/Engines/GreedyOrchestrationEngine.php +155 -0
- package/server/src/Orchestration/Engines/RouteSequencingEngine.php +272 -0
- package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +192 -0
- package/server/src/Orchestration/OrchestrationEngineRegistry.php +83 -0
- package/server/src/Orchestration/Support/OrchestrationPayloadBuilder.php +290 -0
- package/server/src/Providers/EventServiceProvider.php +7 -1
- package/server/src/Providers/FleetOpsServiceProvider.php +42 -15
- package/server/src/routes.php +65 -4
- package/translations/ar-ae.yml +44 -12
- package/translations/bg-bg.yaml +51 -10
- package/translations/en-us.yaml +444 -1
- package/translations/fr-fr.yaml +51 -10
- package/translations/mn-mn.yaml +51 -10
- package/translations/pt-br.yaml +51 -10
- package/translations/ru-ru.yaml +51 -10
- package/translations/vi-vn.yaml +48 -12
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Models;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Casts\Json;
|
|
6
|
+
use Fleetbase\Models\Model;
|
|
7
|
+
use Fleetbase\Traits\HasApiModelBehavior;
|
|
8
|
+
use Fleetbase\Traits\HasInternalId;
|
|
9
|
+
use Fleetbase\Traits\HasMetaAttributes;
|
|
10
|
+
use Fleetbase\Traits\HasPublicId;
|
|
11
|
+
use Fleetbase\Traits\HasUuid;
|
|
12
|
+
use Fleetbase\Traits\Searchable;
|
|
13
|
+
use Fleetbase\Traits\TracksApiCredential;
|
|
14
|
+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
15
|
+
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
16
|
+
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Manifest.
|
|
20
|
+
*
|
|
21
|
+
* Represents a committed delivery plan for a specific vehicle and (optionally)
|
|
22
|
+
* driver. Generated by the Orchestrator commit step. Each Manifest contains an
|
|
23
|
+
* ordered list of ManifestStops representing the physical locations to visit.
|
|
24
|
+
*
|
|
25
|
+
* Status lifecycle:
|
|
26
|
+
* draft → active → in_progress → completed
|
|
27
|
+
* ↘ cancelled
|
|
28
|
+
*/
|
|
29
|
+
class Manifest extends Model
|
|
30
|
+
{
|
|
31
|
+
use HasUuid;
|
|
32
|
+
use HasPublicId;
|
|
33
|
+
use HasInternalId;
|
|
34
|
+
use HasMetaAttributes;
|
|
35
|
+
use HasApiModelBehavior;
|
|
36
|
+
use TracksApiCredential;
|
|
37
|
+
use Searchable;
|
|
38
|
+
use SoftDeletes;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The database table used by the model.
|
|
42
|
+
*/
|
|
43
|
+
protected $table = 'manifests';
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The type of public ID to generate.
|
|
47
|
+
*/
|
|
48
|
+
protected $publicIdType = 'manifest';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Columns that can be searched.
|
|
52
|
+
*/
|
|
53
|
+
protected $searchableColumns = ['public_id', 'internal_id'];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Mass-assignable attributes.
|
|
57
|
+
*/
|
|
58
|
+
protected $fillable = [
|
|
59
|
+
'company_uuid',
|
|
60
|
+
'driver_uuid',
|
|
61
|
+
'vehicle_uuid',
|
|
62
|
+
'status',
|
|
63
|
+
'scheduled_date',
|
|
64
|
+
'started_at',
|
|
65
|
+
'completed_at',
|
|
66
|
+
'total_distance_m',
|
|
67
|
+
'total_duration_s',
|
|
68
|
+
'stop_count',
|
|
69
|
+
'notes',
|
|
70
|
+
'meta',
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Attribute casts.
|
|
75
|
+
*/
|
|
76
|
+
protected $casts = [
|
|
77
|
+
'meta' => Json::class,
|
|
78
|
+
'scheduled_date' => 'date',
|
|
79
|
+
'started_at' => 'datetime',
|
|
80
|
+
'completed_at' => 'datetime',
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Attributes appended to the model's JSON representation.
|
|
85
|
+
*/
|
|
86
|
+
protected $appends = [
|
|
87
|
+
'driver_name',
|
|
88
|
+
'vehicle_name',
|
|
89
|
+
'completed_stops',
|
|
90
|
+
'pending_stops',
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
// ── Relationships ─────────────────────────────────────────────────────────
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The driver assigned to this manifest.
|
|
97
|
+
*/
|
|
98
|
+
public function driver(): BelongsTo
|
|
99
|
+
{
|
|
100
|
+
return $this->belongsTo(Driver::class, 'driver_uuid', 'uuid');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The vehicle assigned to this manifest.
|
|
105
|
+
*/
|
|
106
|
+
public function vehicle(): BelongsTo
|
|
107
|
+
{
|
|
108
|
+
return $this->belongsTo(Vehicle::class, 'vehicle_uuid', 'uuid');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The ordered list of stops in this manifest.
|
|
113
|
+
*/
|
|
114
|
+
public function stops(): HasMany
|
|
115
|
+
{
|
|
116
|
+
return $this->hasMany(ManifestStop::class, 'manifest_uuid', 'uuid')
|
|
117
|
+
->orderBy('sequence');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The orders associated with this manifest (through stops).
|
|
122
|
+
*/
|
|
123
|
+
public function orders(): HasMany
|
|
124
|
+
{
|
|
125
|
+
return $this->hasMany(Order::class, 'manifest_uuid', 'uuid');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ── Computed Attributes ───────────────────────────────────────────────────
|
|
129
|
+
|
|
130
|
+
public function getDriverNameAttribute(): ?string
|
|
131
|
+
{
|
|
132
|
+
return $this->driver?->name;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public function getVehicleNameAttribute(): ?string
|
|
136
|
+
{
|
|
137
|
+
return $this->vehicle?->display_name;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public function getCompletedStopsAttribute(): int
|
|
141
|
+
{
|
|
142
|
+
return $this->stops()->where('status', 'completed')->count();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public function getPendingStopsAttribute(): int
|
|
146
|
+
{
|
|
147
|
+
return $this->stops()->whereIn('status', ['pending', 'arrived'])->count();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ── Scopes ────────────────────────────────────────────────────────────────
|
|
151
|
+
|
|
152
|
+
public function scopeForCompany($query, string $companyUuid)
|
|
153
|
+
{
|
|
154
|
+
return $query->where('company_uuid', $companyUuid);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
public function scopeActive($query)
|
|
158
|
+
{
|
|
159
|
+
return $query->whereIn('status', ['active', 'in_progress']);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public function scopeForDriver($query, string $driverUuid)
|
|
163
|
+
{
|
|
164
|
+
return $query->where('driver_uuid', $driverUuid);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public function scopeForVehicle($query, string $vehicleUuid)
|
|
168
|
+
{
|
|
169
|
+
return $query->where('vehicle_uuid', $vehicleUuid);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ── Business Logic ────────────────────────────────────────────────────────
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Mark the manifest as in_progress and record the start time.
|
|
176
|
+
*/
|
|
177
|
+
public function start(): self
|
|
178
|
+
{
|
|
179
|
+
$this->update(['status' => 'in_progress', 'started_at' => now()]);
|
|
180
|
+
|
|
181
|
+
return $this;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Mark the manifest as completed and record the completion time.
|
|
186
|
+
*/
|
|
187
|
+
public function complete(): self
|
|
188
|
+
{
|
|
189
|
+
$this->update(['status' => 'completed', 'completed_at' => now()]);
|
|
190
|
+
|
|
191
|
+
return $this;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Cancel the manifest.
|
|
196
|
+
*/
|
|
197
|
+
public function cancel(): self
|
|
198
|
+
{
|
|
199
|
+
$this->update(['status' => 'cancelled']);
|
|
200
|
+
|
|
201
|
+
return $this;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Check whether all stops are completed and auto-complete the manifest.
|
|
206
|
+
*/
|
|
207
|
+
public function checkAndAutoComplete(): void
|
|
208
|
+
{
|
|
209
|
+
$pendingCount = $this->stops()->whereIn('status', ['pending', 'arrived'])->count();
|
|
210
|
+
if ($pendingCount === 0 && $this->status === 'in_progress') {
|
|
211
|
+
$this->complete();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\FleetOps\Models;
|
|
4
|
+
|
|
5
|
+
use Fleetbase\Casts\Json;
|
|
6
|
+
use Fleetbase\Models\Model;
|
|
7
|
+
use Fleetbase\Traits\HasApiModelBehavior;
|
|
8
|
+
use Fleetbase\Traits\HasMetaAttributes;
|
|
9
|
+
use Fleetbase\Traits\HasPublicId;
|
|
10
|
+
use Fleetbase\Traits\HasUuid;
|
|
11
|
+
use Fleetbase\Traits\TracksApiCredential;
|
|
12
|
+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
13
|
+
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* ManifestStop.
|
|
17
|
+
*
|
|
18
|
+
* Represents a single physical stop within a Manifest. Each stop links to:
|
|
19
|
+
* - The parent Manifest
|
|
20
|
+
* - The Order being fulfilled at this stop
|
|
21
|
+
* - The Place (physical address) to visit
|
|
22
|
+
* - Optionally, the specific Waypoint within the order's Payload
|
|
23
|
+
*
|
|
24
|
+
* The sequence field holds the VROOM-optimised stop order (1-indexed).
|
|
25
|
+
*/
|
|
26
|
+
class ManifestStop extends Model
|
|
27
|
+
{
|
|
28
|
+
use HasUuid;
|
|
29
|
+
use HasPublicId;
|
|
30
|
+
use HasMetaAttributes;
|
|
31
|
+
use HasApiModelBehavior;
|
|
32
|
+
use TracksApiCredential;
|
|
33
|
+
use SoftDeletes;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The database table used by the model.
|
|
37
|
+
*/
|
|
38
|
+
protected $table = 'manifest_stops';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The type of public ID to generate.
|
|
42
|
+
*/
|
|
43
|
+
protected $publicIdType = 'mstop';
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Mass-assignable attributes.
|
|
47
|
+
*/
|
|
48
|
+
protected $fillable = [
|
|
49
|
+
'manifest_uuid',
|
|
50
|
+
'order_uuid',
|
|
51
|
+
'place_uuid',
|
|
52
|
+
'waypoint_uuid',
|
|
53
|
+
'status',
|
|
54
|
+
'sequence',
|
|
55
|
+
'estimated_arrival',
|
|
56
|
+
'actual_arrival',
|
|
57
|
+
'distance_from_prev_m',
|
|
58
|
+
'duration_from_prev_s',
|
|
59
|
+
'meta',
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Attribute casts.
|
|
64
|
+
*/
|
|
65
|
+
protected $casts = [
|
|
66
|
+
'meta' => Json::class,
|
|
67
|
+
'estimated_arrival' => 'datetime',
|
|
68
|
+
'actual_arrival' => 'datetime',
|
|
69
|
+
'sequence' => 'integer',
|
|
70
|
+
'distance_from_prev_m' => 'integer',
|
|
71
|
+
'duration_from_prev_s' => 'integer',
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Attributes appended to the model's JSON representation.
|
|
76
|
+
*/
|
|
77
|
+
protected $appends = [
|
|
78
|
+
'tracking_number',
|
|
79
|
+
'address',
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
// ── Relationships ─────────────────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The parent manifest.
|
|
86
|
+
*/
|
|
87
|
+
public function manifest(): BelongsTo
|
|
88
|
+
{
|
|
89
|
+
return $this->belongsTo(Manifest::class, 'manifest_uuid', 'uuid');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The order this stop fulfils.
|
|
94
|
+
*/
|
|
95
|
+
public function order(): BelongsTo
|
|
96
|
+
{
|
|
97
|
+
return $this->belongsTo(Order::class, 'order_uuid', 'uuid')
|
|
98
|
+
->with(['trackingNumber', 'payload.dropoff']);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The physical Place to visit.
|
|
103
|
+
*/
|
|
104
|
+
public function place(): BelongsTo
|
|
105
|
+
{
|
|
106
|
+
return $this->belongsTo(Place::class, 'place_uuid', 'uuid');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The specific Waypoint within the order payload (nullable).
|
|
111
|
+
*/
|
|
112
|
+
public function waypoint(): BelongsTo
|
|
113
|
+
{
|
|
114
|
+
return $this->belongsTo(Waypoint::class, 'waypoint_uuid', 'uuid');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ── Computed Attributes ───────────────────────────────────────────────────
|
|
118
|
+
|
|
119
|
+
public function getTrackingNumberAttribute(): ?string
|
|
120
|
+
{
|
|
121
|
+
return $this->order?->trackingNumber?->tracking_number;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public function getAddressAttribute(): ?string
|
|
125
|
+
{
|
|
126
|
+
return $this->place?->address ?? $this->order?->payload?->dropoff?->address;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ── Business Logic ────────────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Mark this stop as arrived and record the actual arrival time.
|
|
133
|
+
*/
|
|
134
|
+
public function markArrived(): self
|
|
135
|
+
{
|
|
136
|
+
$this->update(['status' => 'arrived', 'actual_arrival' => now()]);
|
|
137
|
+
|
|
138
|
+
return $this;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Mark this stop as completed and trigger manifest auto-completion check.
|
|
143
|
+
*/
|
|
144
|
+
public function markCompleted(): self
|
|
145
|
+
{
|
|
146
|
+
$this->update(['status' => 'completed']);
|
|
147
|
+
$this->manifest?->checkAndAutoComplete();
|
|
148
|
+
|
|
149
|
+
return $this;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Mark this stop as skipped.
|
|
154
|
+
*/
|
|
155
|
+
public function markSkipped(): self
|
|
156
|
+
{
|
|
157
|
+
$this->update(['status' => 'skipped']);
|
|
158
|
+
$this->manifest?->checkAndAutoComplete();
|
|
159
|
+
|
|
160
|
+
return $this;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
@@ -120,6 +120,13 @@ class Order extends Model
|
|
|
120
120
|
'notes',
|
|
121
121
|
'type',
|
|
122
122
|
'status',
|
|
123
|
+
// Orchestrator
|
|
124
|
+
'orchestrator_priority',
|
|
125
|
+
'required_skills',
|
|
126
|
+
'time_window_start',
|
|
127
|
+
'time_window_end',
|
|
128
|
+
// Manifest (set by orchestrator commit)
|
|
129
|
+
'manifest_uuid',
|
|
123
130
|
];
|
|
124
131
|
|
|
125
132
|
/**
|
|
@@ -205,6 +212,11 @@ class Order extends Model
|
|
|
205
212
|
'scheduled_at' => 'datetime',
|
|
206
213
|
'dispatched_at' => 'datetime',
|
|
207
214
|
'started_at' => 'datetime',
|
|
215
|
+
// Orchestrator
|
|
216
|
+
'required_skills' => Json::class,
|
|
217
|
+
'time_window_start' => 'datetime',
|
|
218
|
+
'time_window_end' => 'datetime',
|
|
219
|
+
'orchestrator_priority' => 'integer',
|
|
208
220
|
];
|
|
209
221
|
|
|
210
222
|
/**
|
|
@@ -623,6 +635,64 @@ class Order extends Model
|
|
|
623
635
|
$this->attributes['status'] = is_string($status) ? Str::snake($status) : 'created';
|
|
624
636
|
}
|
|
625
637
|
|
|
638
|
+
/**
|
|
639
|
+
* Normalise the date portion of time_window_start on write.
|
|
640
|
+
*
|
|
641
|
+
* If the incoming value has a Unix-epoch date (1970-01-01) — which happens
|
|
642
|
+
* when a caller supplies a time-only string such as "09:00:00" or when the
|
|
643
|
+
* client-side picker emits a time without a date — the date portion is
|
|
644
|
+
* replaced with the order's scheduled_at date, falling back to created_at,
|
|
645
|
+
* and finally to now(). If the value already carries a meaningful date it
|
|
646
|
+
* is stored as-is, so callers that supply a full datetime are never
|
|
647
|
+
* overridden.
|
|
648
|
+
*/
|
|
649
|
+
public function setTimeWindowStartAttribute($value): void
|
|
650
|
+
{
|
|
651
|
+
$this->attributes['time_window_start'] = $this->normaliseTimeWindowValue($value);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Normalise the date portion of time_window_end on write.
|
|
656
|
+
*
|
|
657
|
+
* @see setTimeWindowStartAttribute()
|
|
658
|
+
*/
|
|
659
|
+
public function setTimeWindowEndAttribute($value): void
|
|
660
|
+
{
|
|
661
|
+
$this->attributes['time_window_end'] = $this->normaliseTimeWindowValue($value);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Resolve a time-window value to a full datetime string, injecting the
|
|
666
|
+
* order's reference date (scheduled_at ?? created_at ?? now) when the
|
|
667
|
+
* supplied value has no meaningful date of its own.
|
|
668
|
+
*
|
|
669
|
+
* @param mixed $value Anything Carbon::parse() can accept, or null
|
|
670
|
+
*
|
|
671
|
+
* @return string|null MySQL-formatted datetime string, or null
|
|
672
|
+
*/
|
|
673
|
+
protected function normaliseTimeWindowValue($value): ?string
|
|
674
|
+
{
|
|
675
|
+
if ($value === null || $value === '') {
|
|
676
|
+
return null;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
$parsed = Carbon::parse($value);
|
|
680
|
+
|
|
681
|
+
// When the date portion is the Unix epoch the caller sent a time-only
|
|
682
|
+
// value (e.g. "09:00:00"). Inject the order's reference date.
|
|
683
|
+
if ($parsed->year === 1970 && $parsed->month === 1 && $parsed->day === 1) {
|
|
684
|
+
$ref = isset($this->attributes['scheduled_at']) && $this->attributes['scheduled_at']
|
|
685
|
+
? Carbon::parse($this->attributes['scheduled_at'])
|
|
686
|
+
: (isset($this->attributes['created_at']) && $this->attributes['created_at']
|
|
687
|
+
? Carbon::parse($this->attributes['created_at'])
|
|
688
|
+
: Carbon::now());
|
|
689
|
+
|
|
690
|
+
$parsed->setDate($ref->year, $ref->month, $ref->day);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return $parsed->toDateTimeString();
|
|
694
|
+
}
|
|
695
|
+
|
|
626
696
|
/**
|
|
627
697
|
* Checks if a driver is assigned to the order.
|
|
628
698
|
*
|
|
@@ -175,11 +175,14 @@ class OrderConfig extends Model
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
/**
|
|
178
|
-
*
|
|
178
|
+
* Get all custom fields defined for this order config.
|
|
179
|
+
* CustomField uses a polymorphic subject relationship (subject_uuid / subject_type).
|
|
180
|
+
*
|
|
181
|
+
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
|
|
179
182
|
*/
|
|
180
183
|
public function customFields()
|
|
181
184
|
{
|
|
182
|
-
return $this->
|
|
185
|
+
return $this->morphMany(\Fleetbase\Models\CustomField::class, 'subject', 'subject_type', 'subject_uuid');
|
|
183
186
|
}
|
|
184
187
|
|
|
185
188
|
/**
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
namespace Fleetbase\FleetOps\Models;
|
|
4
4
|
|
|
5
5
|
use Fleetbase\Casts\Json;
|
|
6
|
+
use Fleetbase\Casts\Money;
|
|
6
7
|
use Fleetbase\Casts\PolymorphicType;
|
|
8
|
+
use Fleetbase\FleetOps\Support\Utils;
|
|
7
9
|
use Fleetbase\FleetOps\Traits\Maintainable;
|
|
8
10
|
use Fleetbase\Models\Alert;
|
|
9
11
|
use Fleetbase\Models\File;
|
|
@@ -88,6 +90,7 @@ class Part extends Model
|
|
|
88
90
|
'quantity_on_hand',
|
|
89
91
|
'unit_cost',
|
|
90
92
|
'msrp',
|
|
93
|
+
'currency',
|
|
91
94
|
'asset_type',
|
|
92
95
|
'asset_uuid',
|
|
93
96
|
'type',
|
|
@@ -126,8 +129,9 @@ class Part extends Model
|
|
|
126
129
|
*/
|
|
127
130
|
protected $casts = [
|
|
128
131
|
'quantity_on_hand' => 'integer',
|
|
129
|
-
|
|
130
|
-
'
|
|
132
|
+
// Money values
|
|
133
|
+
'unit_cost' => Money::class,
|
|
134
|
+
'msrp' => Money::class,
|
|
131
135
|
'specs' => Json::class,
|
|
132
136
|
'meta' => Json::class,
|
|
133
137
|
'asset_type' => PolymorphicType::class,
|
|
@@ -199,7 +203,7 @@ class Part extends Model
|
|
|
199
203
|
|
|
200
204
|
public function asset(): MorphTo
|
|
201
205
|
{
|
|
202
|
-
return $this->morphTo();
|
|
206
|
+
return $this->morphTo(__FUNCTION__, 'asset_type', 'asset_uuid');
|
|
203
207
|
}
|
|
204
208
|
|
|
205
209
|
/**
|
|
@@ -501,4 +505,66 @@ class Part extends Model
|
|
|
501
505
|
|
|
502
506
|
return $quantity * ($price ?? 0);
|
|
503
507
|
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Create a Part instance from an import row.
|
|
511
|
+
*
|
|
512
|
+
* Monetary values (unit_cost, msrp) must be supplied in cents (integers).
|
|
513
|
+
* The Money cast will strip non-numeric characters before storage.
|
|
514
|
+
*
|
|
515
|
+
* @param array $row Associative array from the import spreadsheet
|
|
516
|
+
* @param bool $saveInstance Whether to persist the record immediately
|
|
517
|
+
*/
|
|
518
|
+
public static function createFromImport(array $row, bool $saveInstance = false): Part
|
|
519
|
+
{
|
|
520
|
+
$row = array_filter($row);
|
|
521
|
+
|
|
522
|
+
$sku = Utils::or($row, ['sku', 'part_number', 'internal_id']);
|
|
523
|
+
$name = Utils::or($row, ['name', 'part_name']);
|
|
524
|
+
$type = Utils::or($row, ['type', 'part_type'], 'consumable');
|
|
525
|
+
$status = Utils::or($row, ['status'], 'in_stock');
|
|
526
|
+
$manufacturer = Utils::or($row, ['manufacturer', 'make', 'brand']);
|
|
527
|
+
$model = Utils::or($row, ['model', 'part_model']);
|
|
528
|
+
$serialNumber = Utils::or($row, ['serial_number', 'serial']);
|
|
529
|
+
$barcode = Utils::or($row, ['barcode']);
|
|
530
|
+
$description = Utils::or($row, ['description']);
|
|
531
|
+
$quantityOnHand = Utils::or($row, ['quantity_on_hand', 'quantity', 'qty']);
|
|
532
|
+
$unitCost = Utils::or($row, ['unit_cost', 'cost']);
|
|
533
|
+
$msrp = Utils::or($row, ['msrp', 'retail_price']);
|
|
534
|
+
$currency = Utils::or($row, ['currency'], 'USD');
|
|
535
|
+
$vendorName = Utils::or($row, ['vendor_name', 'vendor', 'supplier']);
|
|
536
|
+
|
|
537
|
+
$part = new static([
|
|
538
|
+
'company_uuid' => session('company'),
|
|
539
|
+
'sku' => $sku,
|
|
540
|
+
'name' => $name,
|
|
541
|
+
'type' => $type,
|
|
542
|
+
'status' => $status,
|
|
543
|
+
'manufacturer' => $manufacturer,
|
|
544
|
+
'model' => $model,
|
|
545
|
+
'serial_number' => $serialNumber,
|
|
546
|
+
'barcode' => $barcode,
|
|
547
|
+
'description' => $description,
|
|
548
|
+
'quantity_on_hand' => $quantityOnHand ? (int) $quantityOnHand : 0,
|
|
549
|
+
'unit_cost' => $unitCost,
|
|
550
|
+
'msrp' => $msrp,
|
|
551
|
+
'currency' => strtoupper($currency ?? 'USD'),
|
|
552
|
+
]);
|
|
553
|
+
|
|
554
|
+
// Attempt to resolve vendor by name
|
|
555
|
+
if ($vendorName) {
|
|
556
|
+
$vendor = Vendor::where('company_uuid', session('company'))
|
|
557
|
+
->where('name', 'like', '%' . $vendorName . '%')
|
|
558
|
+
->first();
|
|
559
|
+
if ($vendor) {
|
|
560
|
+
$part->vendor_uuid = $vendor->uuid;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if ($saveInstance === true) {
|
|
565
|
+
$part->save();
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
return $part;
|
|
569
|
+
}
|
|
504
570
|
}
|
|
@@ -61,7 +61,7 @@ class Payload extends Model
|
|
|
61
61
|
*
|
|
62
62
|
* @var array
|
|
63
63
|
*/
|
|
64
|
-
protected $fillable = ['_key', 'company_uuid', 'pickup_uuid', 'dropoff_uuid', 'return_uuid', 'current_waypoint_uuid', 'meta', 'payment_method', 'cod_amount', 'cod_currency', 'cod_payment_method', 'type'];
|
|
64
|
+
protected $fillable = ['_key', 'company_uuid', 'pickup_uuid', 'dropoff_uuid', 'return_uuid', 'current_waypoint_uuid', 'meta', 'payment_method', 'cod_amount', 'cod_currency', 'cod_payment_method', 'type', 'capacity_weight_kg', 'capacity_volume_m3', 'capacity_pallets', 'capacity_parcels'];
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* The attributes that should be cast to native types.
|
|
@@ -69,7 +69,12 @@ class Payload extends Model
|
|
|
69
69
|
* @var array
|
|
70
70
|
*/
|
|
71
71
|
protected $casts = [
|
|
72
|
-
'meta'
|
|
72
|
+
'meta' => Json::class,
|
|
73
|
+
// Orchestrator
|
|
74
|
+
'capacity_weight_kg' => 'decimal:2',
|
|
75
|
+
'capacity_volume_m3' => 'decimal:3',
|
|
76
|
+
'capacity_pallets' => 'integer',
|
|
77
|
+
'capacity_parcels' => 'integer',
|
|
73
78
|
];
|
|
74
79
|
|
|
75
80
|
/**
|
|
@@ -235,7 +235,7 @@ class Place extends Model
|
|
|
235
235
|
function ($option) {
|
|
236
236
|
$key = str_replace(['.svg', '.png'], '', $option);
|
|
237
237
|
|
|
238
|
-
return [$key => Utils::
|
|
238
|
+
return [$key => Utils::assetFromFleetbase('static/place-icons/' . $option)];
|
|
239
239
|
}
|
|
240
240
|
);
|
|
241
241
|
|
|
@@ -121,7 +121,7 @@ class ServiceQuote extends Model
|
|
|
121
121
|
return $this->belongsTo(IntegratedVendor::class);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
public function getServiceRateNameAttribute(): string
|
|
124
|
+
public function getServiceRateNameAttribute(): ?string
|
|
125
125
|
{
|
|
126
126
|
return data_get($this, 'serviceRate.service_name');
|
|
127
127
|
}
|
|
@@ -139,6 +139,7 @@ class Vehicle extends Model
|
|
|
139
139
|
'type',
|
|
140
140
|
'class',
|
|
141
141
|
// Identifiers
|
|
142
|
+
'internal_id',
|
|
142
143
|
'plate_number',
|
|
143
144
|
'call_sign',
|
|
144
145
|
'serial_number',
|
|
@@ -204,6 +205,16 @@ class Vehicle extends Model
|
|
|
204
205
|
'slug',
|
|
205
206
|
'purchased_at',
|
|
206
207
|
'lease_expires_at',
|
|
208
|
+
// Orchestrator
|
|
209
|
+
'skills',
|
|
210
|
+
'capacity_weight_kg',
|
|
211
|
+
'capacity_volume_m3',
|
|
212
|
+
'capacity_pallets',
|
|
213
|
+
'capacity_parcels',
|
|
214
|
+
'max_tasks',
|
|
215
|
+
'time_window_start',
|
|
216
|
+
'time_window_end',
|
|
217
|
+
'return_to_depot',
|
|
207
218
|
];
|
|
208
219
|
|
|
209
220
|
/**
|
|
@@ -295,6 +306,14 @@ class Vehicle extends Model
|
|
|
295
306
|
'torque' => 'decimal:2',
|
|
296
307
|
'gvwr' => 'decimal:2',
|
|
297
308
|
'gcwr' => 'decimal:2',
|
|
309
|
+
// Orchestrator
|
|
310
|
+
'skills' => Json::class,
|
|
311
|
+
'capacity_weight_kg' => 'decimal:2',
|
|
312
|
+
'capacity_volume_m3' => 'decimal:3',
|
|
313
|
+
'capacity_pallets' => 'integer',
|
|
314
|
+
'capacity_parcels' => 'integer',
|
|
315
|
+
'max_tasks' => 'integer',
|
|
316
|
+
'return_to_depot' => 'boolean',
|
|
298
317
|
];
|
|
299
318
|
|
|
300
319
|
public function photo(): BelongsTo
|
|
@@ -561,7 +580,7 @@ class Vehicle extends Model
|
|
|
561
580
|
function ($option) {
|
|
562
581
|
$key = str_replace(['.svg', '.png'], '', $option);
|
|
563
582
|
|
|
564
|
-
return [$key => Utils::
|
|
583
|
+
return [$key => Utils::assetFromFleetbase('static/vehicle-icons/' . $option)];
|
|
565
584
|
}
|
|
566
585
|
);
|
|
567
586
|
|