Skip to content

Phase 1 + 2: multi-tenant scoping + carrier/location/contact/service-area settings UI#226

Open
TLemmAI wants to merge 15 commits intofleetbase:mainfrom
TLemmAI:feat/multi-tenant-hierarchy
Open

Phase 1 + 2: multi-tenant scoping + carrier/location/contact/service-area settings UI#226
TLemmAI wants to merge 15 commits intofleetbase:mainfrom
TLemmAI:feat/multi-tenant-hierarchy

Conversation

@TLemmAI
Copy link
Copy Markdown

@TLemmAI TLemmAI commented Apr 15, 2026

Summary

Part of the upstream fleetbase Phase 1 + 2 TMS productization consolidation.

Phase 1

  • Order model: ScopedToCompanyContext trait applied (local scope; existing queries unaffected)
  • rate_contracts.is_shared migration (additive flag for cross-client sharing)

Phase 2 — data model

  • Vendor: 9 additive freight fields (SCAC, MC#, DOT#, insurance_expiry, insurance_amount, payment_terms_days, default_payment_method, carrier_type, is_preferred) + fillable + casts (date/decimal:2/integer/boolean)
  • Place: 5 operational columns (location_type, appointment_required, contact_name, contact_phone, contact_email) + meta helpers for operating_hours, dock_info, special_instructions
  • Contact: TYPE_* enum constants + isValidType() + scopeOfType() (schema unchanged — existing type column)
  • ServiceArea: states_list + zip_ranges JSON columns (augments existing polygon scoping — no replacement)

Phase 2 — UI

  • Vendor form: new "Freight / Carrier Info" section + insurance-expiry color coding in list (red/yellow/green/neutral)
  • Place form: "Contact / Operational" panel + meta-backed JSON editors for operating_hours, dock_info, special_instructions (meta-preservation guaranteed)
  • Contact directory: type filter + badge column + type select on form
  • ServiceArea form: PowerSelectMultiple for states + zip-range row editor

Merged from upstream/main

origin/main had drifted by 3 commits (dep upgrades, orchestrator styling, v0.6.39). Merge commit 9e65a7e4 reconciles both trunks. One manual conflict resolution in addon/utils/fleet-ops-options.js — both sides added new export const blocks; resolution is additive concatenation (preserves upstream's orchestrator options AND Phase 2's carrierTypes / contactPersonTypes / vendorPaymentMethods / usStates).

Dependencies

  • core-api PR (CompanySettingsResolver + CompanyContextResolver middleware + ScopedToCompanyContext trait)
  • fleetops-data PR v0.4.1 #48 (@attr declarations for Vendor/Place/ServiceArea — blocks Ember Data round-trip)

Test plan

  • core-api Pest suite: 116 passed (no regression on multi-tenant / settings tests)
  • Manual: Vendor create/edit → all 9 new fields persist + reload; list color coding verified for expired / near-expiry / valid insurance
  • Manual: Place create/edit → all 5 new fields + 3 meta editors round-trip; unrelated meta keys preserved across edits
  • Manual: Contact filter + badge rendering with 4 canonical types + legacy values
  • Manual: ServiceArea save/reload states + zip ranges; polygon editing untouched
  • Smoke test API/SDK 14/14

local and others added 15 commits April 6, 2026 13:15
…y coloring to list

Extends Carrier Management UI (Phase 2 Task 11) to surface the 9 freight
columns added to vendors in Tasks 4 + 5.

Form (addon/components/vendor/form.hbs, details.hbs):
- New 'Freight / Carrier Info' ContentPanel with 9 inputs: scac_code,
  mc_number, dot_number, carrier_type (select: asset/broker/both),
  insurance_expiry (DatePicker), insurance_amount (number step=0.01),
  payment_terms_days (number, help text hints null inherits company
  default), default_payment_method (select: ach/check/wire/card),
  is_preferred (checkbox).
- View-mode details mirror the new panel for read-only display.

List (addon/controllers/management/vendors/index.js):
- 3 new columns wired: carrier_type (badge cell), is_preferred (star
  cell), insurance_expiry (color-coded date cell).
- Added query params + @Tracked props for filtering.

Color coding (addon/helpers/insurance-expiry-class.js):
- Pure helper: past -> text-danger, <=30 days -> text-warning,
  >30 days -> text-success, null -> neutral. No Moment/date-fns added.
- Consumed by new cell/vendor-insurance-expiry and view-mode details.

Options (addon/utils/fleet-ops-options.js):
- Added carrierTypes + vendorPaymentMethods lists and registered
  them in the fleetOpsOptions() lookup map.

Translations: Added vendor.fields.* keys for the 9 freight fields plus
column.carrier-type / column.is-preferred / column.insurance-expiry.

Manual verification plan (fleetops has no cheap test harness; Pest on
core-api passes 116 — no backend touched):
- /fleet-ops/management/vendors/new: open the form, scroll to
  'Freight / Carrier Info'; all 9 inputs render.
- Fill fields; save; inspect Network panel — payload carries all 9
  attrs under vendor.
- Reopen vendor: values reload correctly in both form and details view.
- Create a 2nd vendor with insurance_expiry in the past: list cell
  renders in text-danger (red).
- Create a 3rd with expiry 15 days out: list cell renders text-warning
  (yellow). One with expiry 60 days out: text-success (green).
- Toggle is_preferred: list cell shows yellow star + 'Preferred'.

Known dependency gap: the Ember Data Vendor model
(@fleetbase/fleetops-data npm package, separate submodule under
fleetbase/packages/) does not yet declare @attr entries for these 9
fields. The backend columns are live (Task 4 + 5) and fleetbase's API
serializer returns them, but full save/load round-tripping through
Ember Data may require adding @attr declarations in the fleetops-data
package (out of scope for this task per the no-backend / no-console
guardrails). Fields still bind presentationally; explicit Ember
attrs are a follow-up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extends Location Management UI (Phase 2 Task 12) to surface the 5
operational columns added in Task 6 plus editors for 3 meta-backed
fields wired in Task 7 + Task 11.5.

Form (addon/components/place/form.hbs, form.js):
- New 'Contact / Operational' ContentPanel with 5 inputs: location_type
  (PowerSelect reusing existing placeTypes option source), contact_name
  (text), contact_phone (PhoneInput), contact_email (email), and
  appointment_required (Checkbox). No new taxonomy invented.
- New 'Operational Details' ContentPanel with 3 meta editors:
  operating_hours (JSON textarea), dock_info (JSON textarea) and
  special_instructions (plain textarea). JSON textareas validate on
  input; invalid JSON shows inline error and leaves previous meta value
  intact. Chose JSON-textarea pattern per spec: repo has no existing
  widget for structured meta fields on place and "keep it simple;
  don't invent" was the directive.

Meta preservation: form.js writes back via spread-update —
  this.args.resource.meta = { ...(meta ?? {}), <sub_key>: value }
This preserves every other meta key on the place. Empty / null values
omit the sub-key (matches Task 7 PHP helper null-removal semantics).

Details view (addon/components/place/details.hbs):
- Two new ContentPanels mirror the form in read-only mode: 5 dedicated
  fields + JSON pretty-print for operating_hours / dock_info + wrapped
  text for special_instructions. Uses json-stringify helper from
  ember-ui (already present; no new dependency).

List (addon/controllers/management/places/index.js):
- 2 new columns: location_type (badge cell, multi-option filter against
  placeTypes) and appointment_required (icon/label cell, checkbox
  filter). New cell components under addon/components/cell/
  (place-location-type.hbs, place-appointment-required.hbs), template-
  only — same pattern as vendor-preferred.hbs / vendor-carrier-type.hbs
  added in Task 11. Query params + @Tracked props registered.

Translations: added place.fields.* keys for the 5 dedicated fields, the
3 meta editors (with JSON format hints in help text) and the two new
column labels.

Backend round-trip verified via tinker:
- All 5 dedicated columns + 3 meta sub-keys persist + reload correctly.
- Spread-update on meta preserves unrelated keys (preexisting_key +
  dock_info + special_instructions all survive operating_hours edit).

Regression: core-api Pest 116 passed / 279 assertions.

No backend, migration, service, controller, routing, or console
changes. fleetops-data Ember attrs already declared in Task 11.5.

Manual verification plan (fleetops has no cheap test harness):
- /fleet-ops/management/places/new: open form; 5 fields under
  'Contact / Operational' + 3 textareas under 'Operational Details'.
- Enter valid JSON for operating_hours, save; reload form — values
  persist. Enter invalid JSON — inline 'Invalid JSON' message shows;
  save is still allowed (previous valid value is retained server-side).
- Pre-populate meta with an unrelated key via API or tinker; edit
  operating_hours via UI; reload — the unrelated key is still present.
- Places list: location_type column shows info Badge per value;
  appointment_required shows yellow calendar-check icon when true.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rarchy

# Conflicts:
#	addon/utils/fleet-ops-options.js
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