@fleetbase/fleetops-engine 0.6.38 → 0.6.40
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 +43 -38
- package/addon/components/layout/fleet-ops-sidebar.js +103 -24
- 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 +1088 -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 +52 -0
- package/addon/components/vehicle/form.hbs +51 -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 +79 -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 +4 -2
- 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 +53 -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 +38 -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/migrations/2026_04_14_000001_drop_redundant_capacity_columns_from_payloads_table.php +42 -0
- package/server/migrations/2026_04_14_000002_rename_capacity_columns_on_vehicles_table.php +48 -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/Api/v1/OrderController.php +15 -2
- package/server/src/Http/Controllers/Api/v1/VehicleController.php +18 -2
- 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/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 +18 -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 +380 -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,241 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { action } from '@ember/object';
|
|
4
|
+
import { inject as service } from '@ember/service';
|
|
5
|
+
import { isArray } from '@ember/array';
|
|
6
|
+
import numbersOnly from '@fleetbase/ember-core/utils/numbers-only';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `Maintenance::CostPanel`
|
|
10
|
+
*
|
|
11
|
+
* Renders an invoice-style line items editor for a maintenance record.
|
|
12
|
+
*
|
|
13
|
+
* Line items are stored in the `line_items` JSON column on the maintenance
|
|
14
|
+
* record (`@attr('raw')`). Mutations are purely in-memory — the array is
|
|
15
|
+
* written back onto `@resource.line_items` and the parent form's normal
|
|
16
|
+
* save flow persists everything together in a single request. This means
|
|
17
|
+
* the component works correctly for both new (unsaved) and existing records.
|
|
18
|
+
*
|
|
19
|
+
* All monetary values (unit_cost, labor_cost, tax, parts_cost, total_cost)
|
|
20
|
+
* are stored as **cents** (integers) on the backend via the Money::class cast
|
|
21
|
+
* and surfaced as strings by `@attr('string')` on the Ember model. The
|
|
22
|
+
* `numbersOnly()` utility strips any non-digit characters and `parseInt`
|
|
23
|
+
* converts to a safe integer before arithmetic.
|
|
24
|
+
*
|
|
25
|
+
* The `MoneyInput` component handles the cents ↔ display conversion:
|
|
26
|
+
* - `@value` receives cents (e.g. 1000 = $10.00)
|
|
27
|
+
* - `@onChange` emits cents (e.g. 1000 = $10.00)
|
|
28
|
+
*
|
|
29
|
+
* Usage:
|
|
30
|
+
* <Maintenance::CostPanel @resource={{this.maintenance}} @disabled={{cannot-write this.maintenance}} />
|
|
31
|
+
*/
|
|
32
|
+
export default class MaintenanceCostPanelComponent extends Component {
|
|
33
|
+
@service notifications;
|
|
34
|
+
@service intl;
|
|
35
|
+
|
|
36
|
+
/** Whether the "Add line item" row is currently visible */
|
|
37
|
+
@tracked isAddingItem = false;
|
|
38
|
+
|
|
39
|
+
/** Tracks which line item index is currently being edited (null = none) */
|
|
40
|
+
@tracked editingIndex = null;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Draft values for the add/edit form row.
|
|
44
|
+
* `draftUnitCost` is stored in **cents** (integer) to match the backend
|
|
45
|
+
* Money::class cast and the MoneyInput component's expected input/output format.
|
|
46
|
+
*/
|
|
47
|
+
@tracked draftDescription = '';
|
|
48
|
+
@tracked draftQuantity = 1;
|
|
49
|
+
@tracked draftUnitCost = 0;
|
|
50
|
+
|
|
51
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Safely parse a monetary string attribute (cents stored as string) to int.
|
|
55
|
+
*/
|
|
56
|
+
@action _toCents(value) {
|
|
57
|
+
if (value === null || value === undefined || value === '') return 0;
|
|
58
|
+
const parsed = parseInt(numbersOnly(String(value)), 10);
|
|
59
|
+
return isNaN(parsed) ? 0 : parsed;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ─── Computed getters ─────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
get lineItems() {
|
|
65
|
+
return isArray(this.args.resource?.line_items) ? this.args.resource.line_items : [];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get currency() {
|
|
69
|
+
return this.args.resource?.currency ?? 'USD';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get laborCost() {
|
|
73
|
+
return this._toCents(this.args.resource?.labor_cost);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get tax() {
|
|
77
|
+
return this._toCents(this.args.resource?.tax);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get partsCost() {
|
|
81
|
+
return this.lineItems.reduce((sum, item) => {
|
|
82
|
+
const qty = parseInt(item.quantity, 10) || 0;
|
|
83
|
+
const cost = this._toCents(item.unit_cost);
|
|
84
|
+
return sum + qty * cost;
|
|
85
|
+
}, 0);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
get totalCost() {
|
|
89
|
+
return this.laborCost + this.partsCost + this.tax;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Live preview of the draft line total (in cents).
|
|
94
|
+
* Displayed via `format-currency` which also expects cents.
|
|
95
|
+
*/
|
|
96
|
+
get draftLineTotal() {
|
|
97
|
+
return (parseInt(this.draftQuantity, 10) || 0) * this._toCents(this.draftUnitCost);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get isDisabled() {
|
|
101
|
+
return this.args.disabled ?? false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ─── Draft unit cost setter ───────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Called by MoneyInput's `@onChange`. The value is already in cents.
|
|
108
|
+
*/
|
|
109
|
+
@action
|
|
110
|
+
setDraftUnitCost(cents) {
|
|
111
|
+
this.draftUnitCost = cents ?? 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ─── Line item helpers ────────────────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Returns the line total for a single item (quantity × unit_cost).
|
|
118
|
+
* Both values are in cents, so the result is also in cents.
|
|
119
|
+
* Used in the template as (this.lineTotal item).
|
|
120
|
+
*/
|
|
121
|
+
@action
|
|
122
|
+
lineTotal(item) {
|
|
123
|
+
const qty = parseInt(item?.quantity, 10) || 0;
|
|
124
|
+
const cost = this._toCents(item?.unit_cost);
|
|
125
|
+
return qty * cost;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Write a new copy of the line items array back onto the resource so
|
|
130
|
+
* Ember Data tracks the change and includes it in the next save().
|
|
131
|
+
*/
|
|
132
|
+
_commitItems(items) {
|
|
133
|
+
this.args.resource.set('line_items', [...items]);
|
|
134
|
+
// Recompute parts_cost and total_cost locally so the summary updates
|
|
135
|
+
// immediately without waiting for a server round-trip.
|
|
136
|
+
const partsCost = items.reduce((sum, item) => {
|
|
137
|
+
return sum + (parseInt(item.quantity, 10) || 0) * this._toCents(item.unit_cost);
|
|
138
|
+
}, 0);
|
|
139
|
+
this.args.resource.set('parts_cost', String(partsCost));
|
|
140
|
+
this.args.resource.set('total_cost', String(this.laborCost + partsCost + this.tax));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ─── Add item ────────────────────────────────────────────────────────────
|
|
144
|
+
|
|
145
|
+
@action
|
|
146
|
+
showAddRow() {
|
|
147
|
+
this.isAddingItem = true;
|
|
148
|
+
this.editingIndex = null;
|
|
149
|
+
this._resetDraft();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@action
|
|
153
|
+
cancelAdd() {
|
|
154
|
+
this.isAddingItem = false;
|
|
155
|
+
this._resetDraft();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@action
|
|
159
|
+
addLineItem() {
|
|
160
|
+
if (!this.draftDescription?.trim()) {
|
|
161
|
+
this.notifications.warning('Please enter a description for the line item.');
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const newItem = {
|
|
166
|
+
description: this.draftDescription.trim(),
|
|
167
|
+
quantity: parseInt(this.draftQuantity, 10) || 1,
|
|
168
|
+
unit_cost: this.draftUnitCost,
|
|
169
|
+
currency: this.currency,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
this._commitItems([...this.lineItems, newItem]);
|
|
173
|
+
this.isAddingItem = false;
|
|
174
|
+
this._resetDraft();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ─── Edit item ───────────────────────────────────────────────────────────
|
|
178
|
+
|
|
179
|
+
@action
|
|
180
|
+
startEdit(index) {
|
|
181
|
+
const item = this.lineItems[index];
|
|
182
|
+
if (!item) return;
|
|
183
|
+
this.editingIndex = index;
|
|
184
|
+
this.isAddingItem = false;
|
|
185
|
+
this.draftDescription = item.description ?? '';
|
|
186
|
+
this.draftQuantity = item.quantity ?? 1;
|
|
187
|
+
// unit_cost from the record is already in cents
|
|
188
|
+
this.draftUnitCost = this._toCents(item.unit_cost);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@action
|
|
192
|
+
cancelEdit() {
|
|
193
|
+
this.editingIndex = null;
|
|
194
|
+
this._resetDraft();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@action
|
|
198
|
+
saveEdit() {
|
|
199
|
+
if (!this.draftDescription?.trim()) {
|
|
200
|
+
this.notifications.warning('Please enter a description for the line item.');
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const index = this.editingIndex;
|
|
205
|
+
const updatedItems = this.lineItems.map((item, i) => {
|
|
206
|
+
if (i !== index) return item;
|
|
207
|
+
return {
|
|
208
|
+
...item,
|
|
209
|
+
description: this.draftDescription.trim(),
|
|
210
|
+
quantity: parseInt(this.draftQuantity, 10) || 1,
|
|
211
|
+
unit_cost: this.draftUnitCost,
|
|
212
|
+
currency: this.currency,
|
|
213
|
+
};
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
this._commitItems(updatedItems);
|
|
217
|
+
this.editingIndex = null;
|
|
218
|
+
this._resetDraft();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ─── Remove item ─────────────────────────────────────────────────────────
|
|
222
|
+
|
|
223
|
+
@action
|
|
224
|
+
removeLineItem(index) {
|
|
225
|
+
const updatedItems = this.lineItems.filter((_, i) => i !== index);
|
|
226
|
+
this._commitItems(updatedItems);
|
|
227
|
+
// If we were editing this item, close the edit row
|
|
228
|
+
if (this.editingIndex === index) {
|
|
229
|
+
this.editingIndex = null;
|
|
230
|
+
this._resetDraft();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// ─── Private helpers ─────────────────────────────────────────────────────
|
|
235
|
+
|
|
236
|
+
_resetDraft() {
|
|
237
|
+
this.draftDescription = '';
|
|
238
|
+
this.draftQuantity = 1;
|
|
239
|
+
this.draftUnitCost = 0;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -1,23 +1,27 @@
|
|
|
1
|
-
<div class="
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<div class="field-value">{{n-a @resource.summary}}</div>
|
|
7
|
-
</div>
|
|
1
|
+
<div class="next-content-panel-wrapper" ...attributes>
|
|
2
|
+
|
|
3
|
+
{{! ===== OVERVIEW ===== }}
|
|
4
|
+
<ContentPanel @title="Overview" @open={{true}} @wrapperClass="bordered-top">
|
|
5
|
+
<div class="grid grid-cols-1 lg:grid-cols-2 gap-2 text-xs dark:text-gray-100">
|
|
8
6
|
|
|
7
|
+
{{! — Identity & Classification — }}
|
|
8
|
+
<div class="col-span-2 text-[11px] uppercase tracking-wide text-gray-500 font-semibold mt-1">
|
|
9
|
+
Identity & Classification
|
|
10
|
+
</div>
|
|
11
|
+
<div class="field-info-container">
|
|
12
|
+
<div class="field-name">ID</div>
|
|
13
|
+
<div class="field-value">{{n-a @resource.public_id}}</div>
|
|
14
|
+
</div>
|
|
9
15
|
<div class="field-info-container">
|
|
10
16
|
<div class="field-name">Type</div>
|
|
11
|
-
<div class="field-value">{{smart-humanize @resource.type}}</div>
|
|
17
|
+
<div class="field-value">{{n-a (smart-humanize @resource.type)}}</div>
|
|
12
18
|
</div>
|
|
13
|
-
|
|
14
19
|
<div class="field-info-container">
|
|
15
20
|
<div class="field-name">Status</div>
|
|
16
21
|
<div class="field-value">
|
|
17
22
|
<Badge @status={{@resource.status}}>{{smart-humanize @resource.status}}</Badge>
|
|
18
23
|
</div>
|
|
19
24
|
</div>
|
|
20
|
-
|
|
21
25
|
<div class="field-info-container">
|
|
22
26
|
<div class="field-name">Priority</div>
|
|
23
27
|
<div class="field-value">
|
|
@@ -33,91 +37,150 @@
|
|
|
33
37
|
</div>
|
|
34
38
|
</div>
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
{{! — Asset & Assignment — }}
|
|
41
|
+
<div class="col-span-2 text-[11px] uppercase tracking-wide text-gray-500 font-semibold mt-3">
|
|
42
|
+
Asset & Assignment
|
|
39
43
|
</div>
|
|
40
|
-
|
|
41
44
|
<div class="field-info-container">
|
|
42
|
-
<div class="field-name">Maintainable</div>
|
|
43
|
-
<div class="field-value">{{n-a @resource.maintainable_name}}</div>
|
|
45
|
+
<div class="field-name">Maintainable Asset</div>
|
|
46
|
+
<div class="field-value">{{n-a (or @resource.maintainable.displayName @resource.maintainable.name @resource.maintainable_name)}}</div>
|
|
44
47
|
</div>
|
|
45
|
-
|
|
46
48
|
<div class="field-info-container">
|
|
47
49
|
<div class="field-name">Performed By</div>
|
|
48
|
-
<div class="field-value">{{n-a @resource.performed_by_name}}</div>
|
|
50
|
+
<div class="field-value">{{n-a (or @resource.performed_by.displayName @resource.performed_by.name @resource.performed_by_name)}}</div>
|
|
49
51
|
</div>
|
|
52
|
+
{{#if (or @resource.work_order_uuid @resource.work_order_subject)}}
|
|
53
|
+
<div class="field-info-container">
|
|
54
|
+
<div class="field-name">Linked Work Order</div>
|
|
55
|
+
<div class="field-value">{{n-a @resource.work_order_subject}}</div>
|
|
56
|
+
</div>
|
|
57
|
+
{{/if}}
|
|
50
58
|
|
|
59
|
+
{{! — Timeline — }}
|
|
60
|
+
<div class="col-span-2 text-[11px] uppercase tracking-wide text-gray-500 font-semibold mt-3">
|
|
61
|
+
Timeline
|
|
62
|
+
</div>
|
|
51
63
|
<div class="field-info-container">
|
|
52
64
|
<div class="field-name">Scheduled At</div>
|
|
53
|
-
<div class="field-value">{{format-date @resource.scheduled_at}}</div>
|
|
65
|
+
<div class="field-value">{{n-a (format-date-fns @resource.scheduled_at "dd MMM yyyy, HH:mm")}}</div>
|
|
54
66
|
</div>
|
|
55
|
-
|
|
56
67
|
<div class="field-info-container">
|
|
57
68
|
<div class="field-name">Started At</div>
|
|
58
|
-
<div class="field-value">{{format-date @resource.started_at}}</div>
|
|
69
|
+
<div class="field-value">{{n-a (format-date-fns @resource.started_at "dd MMM yyyy, HH:mm")}}</div>
|
|
59
70
|
</div>
|
|
60
|
-
|
|
61
71
|
<div class="field-info-container">
|
|
62
72
|
<div class="field-name">Completed At</div>
|
|
63
|
-
<div class="field-value">{{format-date @resource.completed_at}}</div>
|
|
73
|
+
<div class="field-value">{{n-a (format-date-fns @resource.completed_at "dd MMM yyyy, HH:mm")}}</div>
|
|
64
74
|
</div>
|
|
75
|
+
{{#if @resource.is_overdue}}
|
|
76
|
+
<div class="field-info-container">
|
|
77
|
+
<div class="field-name">Overdue</div>
|
|
78
|
+
<div class="field-value"><Badge @status="danger">Overdue</Badge></div>
|
|
79
|
+
</div>
|
|
80
|
+
{{else if @resource.days_until_due}}
|
|
81
|
+
<div class="field-info-container">
|
|
82
|
+
<div class="field-name">Days Until Due</div>
|
|
83
|
+
<div class="field-value">{{@resource.days_until_due}} days</div>
|
|
84
|
+
</div>
|
|
85
|
+
{{/if}}
|
|
65
86
|
|
|
87
|
+
{{! — Readings — }}
|
|
88
|
+
<div class="col-span-2 text-[11px] uppercase tracking-wide text-gray-500 font-semibold mt-3">
|
|
89
|
+
Readings
|
|
90
|
+
</div>
|
|
66
91
|
<div class="field-info-container">
|
|
67
92
|
<div class="field-name">Odometer</div>
|
|
68
93
|
<div class="field-value">{{n-a @resource.odometer}}</div>
|
|
69
94
|
</div>
|
|
70
|
-
|
|
71
95
|
<div class="field-info-container">
|
|
72
96
|
<div class="field-name">Engine Hours</div>
|
|
73
97
|
<div class="field-value">{{n-a @resource.engine_hours}}</div>
|
|
74
98
|
</div>
|
|
75
|
-
|
|
76
99
|
<div class="field-info-container">
|
|
77
100
|
<div class="field-name">Duration</div>
|
|
78
|
-
<div class="field-value">{{n-a @resource.duration_hours}}
|
|
79
|
-
</div>
|
|
80
|
-
|
|
81
|
-
<div class="field-info-container">
|
|
82
|
-
<div class="field-name">Labor Cost</div>
|
|
83
|
-
<div class="field-value">{{format-currency @resource.labor_cost}}</div>
|
|
84
|
-
</div>
|
|
85
|
-
|
|
86
|
-
<div class="field-info-container">
|
|
87
|
-
<div class="field-name">Parts Cost</div>
|
|
88
|
-
<div class="field-value">{{format-currency @resource.parts_cost}}</div>
|
|
89
|
-
</div>
|
|
90
|
-
|
|
91
|
-
<div class="field-info-container">
|
|
92
|
-
<div class="field-name">Tax</div>
|
|
93
|
-
<div class="field-value">{{format-currency @resource.tax}}</div>
|
|
94
|
-
</div>
|
|
95
|
-
|
|
96
|
-
<div class="field-info-container">
|
|
97
|
-
<div class="field-name">Total Cost</div>
|
|
98
|
-
<div class="field-value"><strong>{{format-currency @resource.total_cost}}</strong></div>
|
|
101
|
+
<div class="field-value">{{n-a @resource.duration_hours}} hrs</div>
|
|
99
102
|
</div>
|
|
100
103
|
|
|
101
|
-
{{
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
<Badge @status="danger">Overdue</Badge>
|
|
106
|
-
</div>
|
|
104
|
+
{{! — Summary & Notes — }}
|
|
105
|
+
{{#if @resource.summary}}
|
|
106
|
+
<div class="col-span-2 text-[11px] uppercase tracking-wide text-gray-500 font-semibold mt-3">
|
|
107
|
+
Summary
|
|
107
108
|
</div>
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
<div class="field-name">Days Until Due</div>
|
|
111
|
-
<div class="field-value">{{@resource.days_until_due}} days</div>
|
|
109
|
+
<div class="field-info-container col-span-2">
|
|
110
|
+
<div class="field-value whitespace-pre-wrap">{{@resource.summary}}</div>
|
|
112
111
|
</div>
|
|
113
112
|
{{/if}}
|
|
113
|
+
{{#if @resource.notes}}
|
|
114
|
+
<div class="col-span-2 text-[11px] uppercase tracking-wide text-gray-500 font-semibold mt-3">
|
|
115
|
+
Notes
|
|
116
|
+
</div>
|
|
117
|
+
<div class="field-info-container col-span-2">
|
|
118
|
+
<div class="field-value whitespace-pre-wrap">{{@resource.notes}}</div>
|
|
119
|
+
</div>
|
|
120
|
+
{{/if}}
|
|
121
|
+
</div>
|
|
122
|
+
</ContentPanel>
|
|
114
123
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
124
|
+
{{! ===== PARTS & SERVICES (invoice-style line items + totals) ===== }}
|
|
125
|
+
<ContentPanel @title="Parts & Services" @open={{true}} @wrapperClass="bordered-top" @panelBodyWrapperClass="px-0i">
|
|
126
|
+
{{#if @resource.line_items.length}}
|
|
127
|
+
<table class="w-full text-xs">
|
|
128
|
+
<colgroup>
|
|
129
|
+
<col class="w-[45%]" />
|
|
130
|
+
<col class="w-[10%]" />
|
|
131
|
+
<col class="w-[20%]" />
|
|
132
|
+
<col class="w-[25%]" />
|
|
133
|
+
</colgroup>
|
|
134
|
+
<thead>
|
|
135
|
+
<tr class="border-b border-gray-200 dark:border-gray-700">
|
|
136
|
+
<th class="text-left text-[10px] uppercase tracking-wide text-gray-400 dark:text-gray-500 font-semibold pb-1 px-4">Description</th>
|
|
137
|
+
<th class="text-right text-[10px] uppercase tracking-wide text-gray-400 dark:text-gray-500 font-semibold pb-1 px-2">Qty</th>
|
|
138
|
+
<th class="text-right text-[10px] uppercase tracking-wide text-gray-400 dark:text-gray-500 font-semibold pb-1 px-2">Unit Cost</th>
|
|
139
|
+
<th class="text-right text-[10px] uppercase tracking-wide text-gray-400 dark:text-gray-500 font-semibold pb-1 px-4">Total</th>
|
|
140
|
+
</tr>
|
|
141
|
+
</thead>
|
|
142
|
+
<tbody>
|
|
143
|
+
{{#each @resource.line_items as |item|}}
|
|
144
|
+
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
145
|
+
<td class="py-1.5 px-4 text-gray-700 dark:text-gray-200">{{n-a item.description}}</td>
|
|
146
|
+
<td class="py-1.5 px-2 text-right text-gray-500 dark:text-gray-400">{{n-a item.quantity}}</td>
|
|
147
|
+
<td class="py-1.5 px-2 text-right text-gray-500 dark:text-gray-400">
|
|
148
|
+
{{format-currency item.unit_cost (or item.currency @resource.currency)}}
|
|
149
|
+
</td>
|
|
150
|
+
<td class="py-1.5 px-4 text-right text-gray-700 dark:text-gray-200 font-medium">
|
|
151
|
+
{{format-currency (mult item.quantity item.unit_cost) (or item.currency @resource.currency)}}
|
|
152
|
+
</td>
|
|
153
|
+
</tr>
|
|
154
|
+
{{/each}}
|
|
155
|
+
</tbody>
|
|
156
|
+
</table>
|
|
157
|
+
{{else}}
|
|
158
|
+
<div class="px-4 py-3 text-xs text-gray-400 dark:text-gray-500 italic">No line items recorded.</div>
|
|
159
|
+
{{/if}}
|
|
160
|
+
|
|
161
|
+
{{! Totals }}
|
|
162
|
+
<div class="border-t border-gray-200 dark:border-gray-700 pt-2 mt-1 space-y-1 text-xs px-4 pb-3">
|
|
163
|
+
<div class="flex justify-between text-gray-500 dark:text-gray-400">
|
|
164
|
+
<span>Labour</span>
|
|
165
|
+
<span>{{format-currency @resource.labor_cost @resource.currency}}</span>
|
|
166
|
+
</div>
|
|
167
|
+
<div class="flex justify-between text-gray-500 dark:text-gray-400">
|
|
168
|
+
<span>Parts</span>
|
|
169
|
+
<span>{{format-currency @resource.parts_cost @resource.currency}}</span>
|
|
170
|
+
</div>
|
|
171
|
+
<div class="flex justify-between text-gray-500 dark:text-gray-400">
|
|
172
|
+
<span>Tax</span>
|
|
173
|
+
<span>{{format-currency @resource.tax @resource.currency}}</span>
|
|
174
|
+
</div>
|
|
175
|
+
<div class="flex justify-between font-semibold text-gray-800 dark:text-gray-100 border-t border-gray-200 dark:border-gray-700 pt-1 mt-1">
|
|
176
|
+
<span>Total</span>
|
|
177
|
+
<span>{{format-currency @resource.total_cost @resource.currency}}</span>
|
|
118
178
|
</div>
|
|
119
179
|
</div>
|
|
120
180
|
</ContentPanel>
|
|
121
181
|
|
|
182
|
+
{{! ===== CUSTOM FIELDS ===== }}
|
|
122
183
|
<CustomField::Yield @subject={{@resource}} @viewMode={{true}} @wrapperClass="bordered-top" />
|
|
123
|
-
|
|
184
|
+
|
|
185
|
+
<Spacer @height="200px" />
|
|
186
|
+
</div>
|