Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion addon/components/customer/orders.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default class CustomerOrdersComponent extends Component {

get modalsManager() {
const owner = getOwner(this);
const application = typeof this.universe.getApplicationInstance === 'function' ? this.universe.getApplicationInstance() : window.Fleetbase;
const application = this.universe.getApplicationInstance();
const modalsManager = application ? application.lookup('service:modals-manager') : owner.lookup('service:modals-manager');
return modalsManager;
}
Expand Down
2 changes: 1 addition & 1 deletion addon/services/leaflet-routing-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default class LeafletRoutingControlService extends Service {

#initializeRegistry() {
const registry = 'registry:routing-controls';
const application = typeof this.universe?.getApplicationInstance === 'function' ? this.universe.getApplicationInstance() : window.Fleetbase;
const application = this.universe.getApplicationInstance();
if (!application.hasRegistration(registry)) {
application.register(registry, new RoutingControlRegistry(), { instantiate: false });
}
Expand Down
3 changes: 2 additions & 1 deletion addon/services/movement-tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export class EventBuffer {

export default class MovementTrackerService extends Service {
@service socket;
@service universe;
@tracked channels = [];
@tracked buffers = new Map();

Expand All @@ -131,7 +132,7 @@ export default class MovementTrackerService extends Service {
}

#getOwner(owner = null) {
return owner ?? window.Fleetbase ?? getOwner(this);
return owner ?? this.universe.getApplicationInstance() ?? getOwner(this);
}

#getBuffer(key, model, opts = {}) {
Expand Down
2 changes: 1 addition & 1 deletion addon/services/route-optimization.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default class RouteOptimizationService extends Service {

#initializeRegistry() {
const registry = 'registry:route-optimization-engines';
const application = typeof this.universe?.getApplicationInstance === 'function' ? this.universe.getApplicationInstance() : window.Fleetbase;
const application = this.universe.getApplicationInstance();
if (!application.hasRegistration(registry)) {
application.register(registry, new RouteOptimizationRegistry(), { instantiate: false });
}
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fleetbase/fleetops-api",
"version": "0.6.31",
"version": "0.6.32",
"description": "Fleet & Transport Management Extension for Fleetbase",
"keywords": [
"fleetbase-extension",
Expand Down
2 changes: 1 addition & 1 deletion extension.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Fleet-Ops",
"version": "0.6.31",
"version": "0.6.32",
"description": "Fleet & Transport Management Extension for Fleetbase",
"repository": "https://github.com/fleetbase/fleetops",
"license": "AGPL-3.0-or-later",
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fleetbase/fleetops-engine",
"version": "0.6.31",
"version": "0.6.32",
"description": "Fleet & Transport Management Extension for Fleetbase",
"fleetbase": {
"route": "fleet-ops"
Expand Down Expand Up @@ -42,8 +42,8 @@
},
"dependencies": {
"@babel/core": "^7.23.2",
"@fleetbase/ember-core": "^0.3.9",
"@fleetbase/ember-ui": "^0.3.15",
"@fleetbase/ember-core": "^0.3.10",
"@fleetbase/ember-ui": "^0.3.17",
"@fleetbase/fleetops-data": "^0.1.24",
"@fleetbase/leaflet-routing-machine": "^3.2.17",
"@fortawesome/ember-fontawesome": "^2.0.0",
Expand Down
618 changes: 73 additions & 545 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion server/src/Http/Controllers/Internal/v1/LiveController.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ function ($q) {

if ($active) {
$query->whereHas('driverAssigned');
$query->whereNotIn('status', ['created', 'completed', 'expired', 'order_canceled', 'canceled', 'pending']);
}

if ($unassigned) {
Expand Down Expand Up @@ -166,7 +167,7 @@ public function drivers(Request $request)

return LiveCacheService::remember('drivers', $cacheParams, function () use ($bounds) {
$query = Driver::where(['company_uuid' => session('company')])
->with(['user', 'vehicle', 'currentJob'])
->with(['user', 'vehicle'])
->applyDirectivesForPermissions('fleet-ops list driver');

// Filter out drivers with invalid coordinates
Expand Down
2 changes: 1 addition & 1 deletion server/src/Http/Filter/OrderFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public function active(bool $active = false)
$this->builder->where(
function ($q) {
$q->whereHas('driverAssigned');
$q->whereNotIn('status', ['created', 'canceled', 'order_canceled', 'completed']);
$q->whereNotIn('status', ['created', 'completed', 'expired', 'order_canceled', 'canceled', 'pending']);
}
);
}
Expand Down
1 change: 1 addition & 0 deletions server/src/Http/Resources/v1/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public function toArray($request): array
'pod_method' => $this->pod_method,
'pod_required' => (bool) data_get($this, 'pod_required', false),
'dispatched' => (bool) data_get($this, 'dispatched', false),
'started' => (bool) data_get($this, 'started', false),
'adhoc' => (bool) data_get($this, 'adhoc', false),
'adhoc_distance' => (int) $this->getAdhocDistance(),
'distance' => (int) $this->distance,
Expand Down
4 changes: 2 additions & 2 deletions server/src/Models/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,12 @@ public function vendor(): BelongsTo|Builder

public function currentJob(): BelongsTo|Builder
{
return $this->belongsTo(Order::class)->select(['id', 'uuid', 'public_id', 'payload_uuid', 'driver_assigned_uuid'])->without(['driver']);
return $this->belongsTo(Order::class)->without(['driver']);
}

public function currentOrder(): BelongsTo|Builder
{
return $this->belongsTo(Order::class, 'current_job_uuid')->select(['id', 'uuid', 'public_id', 'payload_uuid', 'driver_assigned_uuid'])->without(['driver']);
return $this->belongsTo(Order::class, 'current_job_uuid')->without(['driver']);
}

public function jobs(): HasMany|Builder
Expand Down
50 changes: 50 additions & 0 deletions server/src/Observers/OrderObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ public function created(Order $order)
$this->invalidateCache($order);
}

/**
* Handle the Order "updating" event.
*
* This event is fired before the order is persisted to the database.
* It is used to mutate attributes as part of the same update operation
* without triggering additional save cycles.
*
* @param Order $order The order being updated
*/
public function updating(Order $order): void
{
$this->ensureOrderStarted($order);
}

/**
* Handle the Order "updated" event.
*
Expand Down Expand Up @@ -62,4 +76,40 @@ protected function invalidateCache(?Order $order = null): void
Cache::forget("order:{$order->uuid}:tracker");
}
}

/**
* Detects when an order has just transitioned to the "started" status
* and initializes start-related fields.
*
* This method should be called during the "updating" lifecycle event
* to ensure that the changes are persisted as part of the same database
* update and do not trigger additional observer events.
*
* An order is considered "started" when:
* - The "status" attribute is being changed in the current update
* - The previous status was not "started"
* - The new status is "started"
*
* When these conditions are met, the order's start timestamp and
* started flag are set if they have not already been initialized.
*
* @param Order $order The order being evaluated for a start transition
*/
protected function ensureOrderStarted(Order $order): void
{
if (
$order->isDirty('status')
&& $order->getOriginal('status') === 'dispatched'
&& $order->status === 'started'
) {
// Only set defaults if not explicitly provided
if (is_null($order->started_at)) {
$order->started_at = now();
}

if (!$order->started) {
$order->started = true;
}
}
}
}
Loading