Skip to content

release: Fleet-Ops v0.6.70 - #343

Merged
roncodes merged 30 commits into
mainfrom
release/v0.6.70
Sep 28, 2026
Merged

roncodes merged 30 commits into
mainfrom
release/v0.6.70

Conversation

@roncodes

Copy link
Copy Markdown
Member

Summary

  • open the Fleet-Ops v0.6.70 release branch
  • synchronize the extension, frontend package, and API package versions
  • prepare release notes for order reporting and the default dashboard

Planned release work

  • Custom field persistence fixes and order reporting schema #342:
    • the order reporting schema: items, tracking, identifiers, summary columns and soft deletes, with 13 dead column references removed;
    • custom field values persisting on fuel reports and service areas;
    • declared default dashboard order and live-map cards in the Live Fleet widget.

Merging this closes #342.

Related

  • Release v1.6.64 core-api#271 (v1.6.64): expression columns, soft deletes and computed group keys used by the order schema. The schema also registers on older core-api.
  • Release v0.4.4 ember-ui#184 (v0.4.4): report builder changes and default dashboard ordering.
  • fleetbase/ledger v0.0.11: ledger's widgets on the default dashboard.

@fleetbase/ember-ui stays at ^0.4.3 here, because 0.4.4 isn't published yet. Without it the dashboard order is ignored rather than breaking anything. Bump the dependency once ember-ui v0.4.4 is published.

🤖 Generated with Claude Code

Telematics polling writes a device event, a position and a delivery envelope per
reporting device per poll, and nothing bounded device_events or positions. Add a
per-company retention policy (Fleet-Ops > Settings > Telematics Data, with admin
system defaults) enforced by fleetops:prune-telematics-data every fifteen minutes
in bounded hard-delete batches, with raw payload compaction, inbox tables resolved
through connections, an orphan sweep, dry-run/filter/lock options, supporting
indexes, a storage usage endpoint and an on-demand cleanup job.

Ingestion fixes: device_events.meta no longer duplicates the raw provider unit,
and telemetry-driven saves skip the activity log unless the company opts in. The
drain command now only recovers deliveries and finishes interrupted runs.
… values

Ember Data's REST serializer sends a record under a camelCase root
(`fuelReport`, `serviceArea`). The base controller's payload reader
accepts both spellings, so the ordinary attributes saved, but these two
afterSave hooks read `$request->array('fuel_report.custom_field_values')`
and `'service_area.custom_field_values'` from the raw request, which was
always empty. No custom field value was ever persisted for either
resource; single-word resources (driver, vehicle, ...) were unaffected.

Read the values from the payload the base controller already extracted,
which the after hook receives as its third argument, so the root key's
spelling no longer matters.

Found while testing the ember-ui signature pad custom field on a fuel
report: the upload landed, the report saved, and the value vanished.
…refront totals

The Orders report table was missing most of what an order report needs, and
several tables referenced columns that do not exist.

Orders
- Order ID / Internal ID now show (core-api hid every *_id column as a key).
- New columns: customer and facilitator kind, dispatched/started flags, time
  window, ad hoc distance, POD method, route optimized, priority, notes.
- Storefront totals from meta as expression columns: storefront, currency,
  subtotal, delivery fee, tip and total (in the currency's smallest unit).
- Summary columns: total/completed/canceled orders (distinct, so they stay right
  when items are joined), order total/average, delivery fees, tips; the
  transaction sums now read transaction.amount instead of a missing orders.amount.
- New relationships: tracking number (+ latest tracking status), order config,
  customer vendor, created by, purchase rate -> service quote, payload return.
- Payload now has its own columns and exposes its items (payload.entities, one
  row per item) with name, SKU, price, product ID, quantity and line total
  from meta, plus the item destination.
- Distance/duration are labelled in meters/seconds (what is stored); the
  km->miles transformer on a meters column is gone.

Other tables
- Drivers: name/email/phone and current_vehicle_uuid do not exist on drivers;
  use the user and vehicle relationships.
- Vehicles: the driver join used a non-existent current_driver_uuid.
- Fuel reports: cost/odometer_reading/report_date do not exist; use amount,
  odometer, metric unit and created_at.
- Every table and item join leaves soft-deleted rows out.

Requires fleetbase/core-api feature/report-framework-enhancements for expression
columns and soft-delete filtering; on older core-api releases the schema still
registers (the new columns fall back to plain computed columns).
meta has no fixed structure: users, integrations and extensions each put
their own keys there, so a column such as "Order Total" read from
meta.total is empty or wrong for most orders. Remove the columns built on
meta keys (storefront, order currency/subtotal/delivery fee/tip/total, the
order total/average/fee/tip summaries, and item product ID, quantity and
line total). meta stays selectable as raw JSON on orders and items, and a
key is read with a computed column, e.g.
CAST(JSON_UNQUOTE(JSON_EXTRACT(payload.entities.meta, '$.quantity')) AS DECIMAL(15,2)).
A table's own columns no longer repeat the table's name: Orders "Order ID"
and "Order Type" are "ID" and "Type", and every table's public ID is "ID".
Relationship labels are tuned for core-api's whole-name prefixes:
"Tracking Status" (not "Tracking Status Status"), "Service Quote Amount",
"Transaction Gateway ID", "Transaction Item Quantity", "Inspection Form Name",
"Target Vehicle ID".
…Fleet widget

Default dashboard
- Fleet-ops widgets declare an `order` so the shared default dashboard lays
  out cleanly beside other extensions' widgets: the KPI row (Radar, Active
  Orders, Drivers Online, with ledger's Revenue), ledger's KPI row, the Live
  Fleet Map at full width, then Revenue Trend, Top Drivers and Maintenance
  Overview a third of the width each.
- Earnings and Avg Order Value are no longer defaults (still addable).

Live Fleet widget
- Its marker popups and hover tooltips are now the live map's own cards: the
  driver and vehicle cards moved into shared Map::MarkerCard::Driver/Vehicle
  components (the live map rendered each twice, inline), and the widget uses
  them too.
- /fleet-ops/analytics/live-fleet adds each marker's `card`, the same index
  resource the live map's endpoints return (status, driver, trailers,
  devices, order, speed, heading, location labels).
…nd console paths

Setting::lookupCompany()/lookupFromCompany() return the default when
session('company') is missing, which is always the case on queue workers
and often in console commands. Switch the reachable call sites to
Setting::lookupForCompany() with the model's company:

- ProcessOperationalAlerts: tracking alert settings from the order company
- NotifyDriverOnShiftChange (ShouldQueue): scheduling settings from the
  schedule company
- VroomOrchestrationEngine: org VROOM settings from the allocated orders'
  company (ProcessAllocationJob is queued), session as fallback
- TrackingOptions/OrderTracker/TrackingIntelligenceService: tracking
  settings from the order company, session as fallback
- CustomerCredentialsMail: portal slug from the customer company

Requires fleetbase/core-api >=1.6.65 (fleetbase/core-api#262).
…mapped endpoints

Schema
- Declare resources the UI already checked but the schema never created, which
  left their API unguarded and their screens unreachable for non-admins:
  maintenance-schedule, device, sensor, device-event, telematic, warranty,
  purchase-rate, fuel-provider-connection/-transaction/-sync-run, analytics,
  scheduling-settings, tracking-settings. service-rate gains export.
- Fix the 'action' => 'actions' key on the settings resources, so
  `fleet-ops onboard payments` is actually created.
- Grant the new resources in the built-in policies (FleetManager,
  MaintenanceManager, ServiceRateManager, OperationsAdmin, DispatchManager).

Custom actions (Support\Authorization + #[SkipAuthorizationCheck])
- AuthorizationGuard maps unmatched method names by HTTP verb, so e.g.
  bulk-dispatch required `create order`, unassign-vehicle `create driver` and
  trailer attach `create trailer`. Map them to the schema actions: dispatch,
  cancel, schedule, import, assign-driver-for, update-route-for order;
  assign-order-for / assign-vehicle-for / update-user-for driver;
  attach-/detach-*-for trailer; and update on vehicle, vendor, device,
  telematic, maintenance-schedule, maintenance, work-order and
  fuel-provider-* sub-actions.

Controllers outside the guard
- Analytics and metrics require `view analytics`; live map feeds require list
  order/driver/vehicle/place; orchestrator, manifests, radar writes, customer
  portal logins and Stripe payments now require their permissions.
- Settings writes require the matching *-settings permission; the admin
  tracking/map settings require a system admin.
- Entity editing settings are one platform-wide map: a save now only writes
  the session company's order configs and keeps other companies' entries, and
  reads return only the company's own. Driver onboard settings are pinned to
  the session company instead of a request-supplied company id.
- Navigator link-app returned an API key to unauthenticated callers. The link
  is now a 30 minute signed URL issued only to system admins, and link-app
  rejects unsigned requests.
…ermission

- List guards on every index route that lacked one (orders, routes, trailers,
  fuel transactions, integrated vendors, all maintenance and connectivity
  routes, analytics, settings) and create/view/update guards on new, details
  and edit routes. Orders is the landing route, so it forwards users without
  `list order` to the first area they can open.
- Index New/Import/Export buttons, bulk actions and row actions pass their
  permission; the order details menu hides actions the user cannot perform.
- Sidebar hub items keep their permissions, branch defaults skip routes the
  user cannot open, and items use the schema's resource names (analytics,
  fuel-provider-*, list custom-field/avatar). Reports use the iam report
  permissions that the core reports API enforces.
- Header shortcuts carry their module permission; the virtual route honours
  menu item permissions.
- Live map layers check singular resource names (list vehicle, not vehicles),
  so non-admin users see their layers.
- Maintenance details/edit redirects used route names without the
  console.fleet-ops prefix and threw; fixed.
… controller middleware

- Move the explicit checks out of method bodies into a declarative map:
  FleetOpsController registers `$methodPermissions` (method => permission) as
  controller middleware via the AuthorizesMethods trait, and non-resource
  controllers call authorizeMethods() in their constructor. Behaviour through
  the router is unchanged; unit tests that call controller methods directly
  keep exercising the endpoint logic.
- Navigator links are signed with an HMAC over the expiry
  (NavigatorController::linkSignature) instead of Laravel's signed routes, so
  the link no longer depends on a named route or the URL generator.
- Tests: signed/unsigned/tampered/expired Navigator links; entity editing
  settings keep other companies' entries and ignore keys for foreign order
  configs; driver onboard settings ignore a request-supplied company id.
Telematics data retention settings and prune sweep
…ession

fix(settings): resolve company settings without a session in queued and console paths
fix(permissions): enforce Fleet-Ops permissions across the API and console
@codecov

codecov Bot commented Sep 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (a80f78d) to head (ec6ab05).

Additional details and impacted files
@@             Coverage Diff              @@
##                main      #343    +/-   ##
============================================
  Coverage     100.00%   100.00%            
- Complexity     12089     12329   +240     
============================================
  Files            591       600     +9     
  Lines          45427     46419   +992     
============================================
+ Hits           45427     46419   +992     
Flag Coverage Δ
backend 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@roncodes
roncodes merged commit 5f846a9 into main Sep 28, 2026
11 checks passed
@roncodes
roncodes deleted the release/v0.6.70 branch September 28, 2026 10:53
@roncodes roncodes mentioned this pull request Sep 28, 2026
6 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant