feat: add schedule, schedule-item and availability relationships to Driver model#45
Open
feat: add schedule, schedule-item and availability relationships to Driver model#45
Conversation
…river model Connects the Driver Ember Data model to the core-api scheduling system by adding three hasMany relationships: - schedules: polymorphic Schedule records where the driver is the subject - schedule_items: individual shift records (ScheduleItem) where the driver is the assignee (assignee_type='driver', assignee_uuid=driver.id) - availabilities: ScheduleAvailability records for time-off and preferred working hours These relationships are required by: 1. The new driver/schedule panel component which renders a per-driver FullCalendar shift management view 2. The Intelligent Order Allocation Engine AllocationPayloadBuilder which queries active schedule_items to inject shift time_window constraints into the VROOM optimization payload Refs: fleetbase/fleetops#214
…rializer
The backend stores STI discriminator values (e.g. `fliit_contact`) in the
contacts.type column and passes them straight through in the Contact HTTP
Resource. Ember Data's VendorModel declares `@hasMany('contact') personnels`
and tries to resolve each embedded record by its `type` field as a model
registry name — finding `fliit_contact` instead of `contact` and throwing:
Assertion Failed: Encountered a relationship identifier with type
'fliit_contact' for the hasMany relationship 'personnels' on <vendor:…>,
Expected an identifier with type 'contact'.
Fix:
- Add `personnels: { embedded: 'always' }` to VendorSerializer attrs so the
inline objects are processed through the normalize pipeline.
- Override `normalize()` in VendorSerializer to strip known package prefixes
(fliit_, fleet_ops_, fleetops_) from each personnel's `type` field,
converting it to the bare Ember model name (e.g. `contact`).
- Preserve the original discriminator value under `subtype` so application
code that depends on it (role checks, routing, conditional rendering) is
completely unaffected.
- Add `@attr('string') subtype` to ContactModel to expose the preserved value.
No backend changes required.
The VendorModel declares `@hasMany('contact') personnels` but the
VendorSerializer did not declare personnels as embedded. Without the
embedded declaration, Ember Data attempts to resolve each inline personnel
object by reading its `type` field as a model registry name. The backend
stores an STI discriminator in that field (e.g. `fliit_contact`) which does
not exist in the Ember Data registry, causing:
Assertion Failed: Encountered a relationship identifier with type
'fliit_contact' for the hasMany relationship 'personnels' on <vendor:…>
Fix: add `personnels: { embedded: 'always' }` to VendorSerializer attrs.
The EmbeddedRecordsMixin then resolves each record using the declared
relationship model type (`contact`) and the `type` attribute on each
payload object is treated as a plain domain attribute — untouched.
Also reverts the unnecessary `subtype` attr added to ContactModel in the
previous commit.
Adds the maintenance-schedule model to the fleetops-data package so the Ember Data store can resolve 'maintenance-schedule' queries from the maintenance module. Files added: - addon/models/maintenance-schedule.js: full model with all interval fields (time/distance/engine-hours), next-due thresholds, default assignee attrs, status, subject polymorphic fields, and computed date helpers (updatedAt, createdAt, nextDueAt, isActive, isPaused) - app/models/maintenance-schedule.js: re-export shim following the same pattern as all other models in this package
…e module
- Add abstract MaintenanceSubject base model with common attributes (name, status, photo_url, dates)
- Add MaintenanceSubjectVehicle concrete model extending base (vehicle-specific attrs: make, model, year, plate_number, vin, odometer, engine_hours)
- Add MaintenanceSubjectEquipment concrete model extending base (equipment-specific attrs: serial_number, manufacturer, purchase_price)
- Add app re-export shims for all three maintenance-subject models
- Update MaintenanceSchedule model: replace subject_type/subject_uuid attrs with @belongsTo('maintenance-subject', {polymorphic: true}) and @belongsTo('facilitator', {polymorphic: true}) for default_assignee
- Update WorkOrder model: replace target_type/target_uuid with @belongsTo('maintenance-subject', {polymorphic: true}) and assignee_type/assignee_uuid with @belongsTo('facilitator', {polymorphic: true})
- Update Maintenance model: replace maintainable_type/maintainable_uuid with @belongsTo('maintenance-subject', {polymorphic: true}) and performed_by_type/performed_by_uuid with @belongsTo('facilitator', {polymorphic: true})
- Add MaintenanceScheduleSerializer with normalizePolymorphicType/serializePolymorphicType for subject and default_assignee
- Update WorkOrderSerializer with type mapping: fleet-ops:vehicle -> maintenance-subject-vehicle, fleet-ops:equipment -> maintenance-subject-equipment
- Update MaintenanceSerializer with type mapping for maintainable and performed_by relationships
- All serializers use EmbeddedRecordsMixin with embedded: always for polymorphic relationships
Follows the existing facilitator pattern (abstract base + concrete subtypes) used throughout the fleetops-data package.
… transformers exist - maintenance-schedule: subject + default_assignee now embedded: always - work-order: target + assignee + custom_field_values now embedded: always - maintenance: maintainable + performed_by now embedded: always (work_order and custom_field_values were already embedded) The backend PHP resource transformers (MaintenanceSchedule, WorkOrder, Maintenance) eager-load these relationships via $with and embed them in every response, so the frontend serializers can safely declare them as embedded: always.
…hicType The previous commit incorrectly changed the normalizePolymorphicType maps from PHP class names to shorthand strings. This would break any model that does not go through the new resource transformers. The maps must stay as PHP class names since that is what the backend returns for *_type fields on the parent record. The backend resource transformers already handle the Ember Data type resolution problem correctly by injecting a 'type' field into the embedded object — the serializer maps do not need to change.
…e models MoneyInput component emits cents as integers, and the backend Money cast stores/retrieves integer cent values. Using @attr('number') caused JS number coercion issues with large cent values. Using @attr('string') passes the raw integer string through Ember Data without any transformation, which is correct for MoneyInput's @value binding. Affected models and attributes: - equipment: purchase_price - part: unit_cost, msrp - maintenance: labor_cost, parts_cost, tax, total_cost - work-order: estimated_cost, approved_budget, actual_cost
… Data models Audited every maintenance-related server-side resource (fillable + appends) against the corresponding fleetops-data Ember Data model and added all fields that were present in the API response but absent from the model definition. Equipment: + uuid + equipped_to_name (server appended) + is_equipped (server appended) + age_in_days (server appended — computed from purchased_at) + depreciated_value (server appended — straight-line depreciation) Part: + uuid + total_value (server appended — quantity_on_hand × unit_cost) + is_in_stock (server appended) + is_low_stock (server appended) + asset_name (server appended) WorkOrder: + is_overdue (server appended) + days_until_due (server appended) + completion_percentage (server appended) + estimated_duration (server appended) (estimated_cost, approved_budget, actual_cost, currency, cost_breakdown, cost_center, budget_code were already present from a prior commit) Maintenance: + work_order_subject (server convenience field) + duration_hours (server appended — diff of started_at/completed_at) + is_overdue (server appended) + days_until_due (server appended) + cost_breakdown (server appended) Asset: + uuid + current_location (server appended) + is_online (server appended) + last_maintenance (server appended) + next_maintenance_due (server appended) Warranty: + uuid + subject_name (server appended) + is_active (server appended) + is_expired (server appended) + days_remaining (server appended) + coverage_summary (server appended) + status (server appended) Device: + uuid + warranty_name (server appended) + telematic_name (server appended) + is_online (server appended) + attached_to_name (server appended) + connection_status (server appended) Sensor: + uuid Reorganised: moved photo_url, is_active, threshold_status under a clear "server-computed" section (they were already declared but mixed into attributes) MaintenanceSchedule: no changes needed — subject_name and default_assignee_name were already present.
…acilitator_type All three maintenance serializers (work-order, maintenance, maintenance-schedule) previously only mapped full PHP class names in MAINTENANCE_SUBJECT_TYPE_MAP and FACILITATOR_TYPE_MAP. The fixed backend resources now inject bare slug strings (e.g. 'facilitator-vendor', 'maintenance-subject-vehicle') via subject_type and facilitator_type fields on the embedded object, so the old maps never matched. Changes: - Expand all type maps to cover: bare slug, fleet-ops: short-form, bare model name, and full PHP class name - so any variant the backend ever sends is handled. - normalizePolymorphicType now reads the injected subject_type / facilitator_type field first (set by the fixed PHP resource), falling back to the raw _type field. - serializePolymorphicType EMBER_TO_SHORTHAND maps extended to cover raw model names (vehicle, equipment, vendor, contact, driver) so saving works even when the record was set directly from a non-subtyped model (e.g. target=@vehicle). Affected serializers: work-order, maintenance, maintenance-schedule.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Connects the
DriverEmber Data model to thefleetbase/core-apischeduling system by adding threehasManyrelationships.Changes
addon/models/driver.jsAdded the following relationships under a new
@scheduling-relationshipssection:scheduleshasMany(async)scheduleSchedulerecords where the driver is thesubjectschedule_itemshasMany(async)schedule-itemScheduleItem) whereassignee_type='driver'availabilitieshasMany(async)schedule-availabilityWhy
The
core-apialready contains a complete scheduling system (Schedule,ScheduleItem,ScheduleAvailability,ScheduleConstraint,ScheduleTemplate) with all routes registered. These Ember Data relationships are the missing link that allows the FleetOps frontend to:driver/schedulecomponent (in the companionfleetbase/fleetopsPR) renders a per-driver FullCalendar shift management view using these relationships.AllocationPayloadBuilderqueriesschedule_itemsto retrieve a driver's active shiftstart_at/end_atand injects them astime_windowhard constraints into the VROOM optimization payload, ensuring no driver is assigned a route that exceeds their scheduled shift.Related
fleetbase/fleetops: driver scheduling UI + backend relationships