diff --git a/addon/models/maintenance-schedule.js b/addon/models/maintenance-schedule.js index 818abd8..a154b3b 100644 --- a/addon/models/maintenance-schedule.js +++ b/addon/models/maintenance-schedule.js @@ -7,10 +7,15 @@ export default class MaintenanceScheduleModel extends Model { @attr('string') uuid; @attr('string') public_id; @attr('string') company_uuid; + @attr('string') subject_uuid; + @attr('string') subject_type; + @attr('string') default_assignee_uuid; + @attr('string') default_assignee_type; /** @polymorphic relationships */ @belongsTo('maintenance-subject', { polymorphic: true, async: false }) subject; @belongsTo('facilitator', { polymorphic: true, async: false }) default_assignee; + /** @computed names — server-side convenience fields (read-only) */ @attr('string') subject_name; @attr('string') default_assignee_name; diff --git a/addon/models/order.js b/addon/models/order.js index 55b1d45..a33f1dd 100644 --- a/addon/models/order.js +++ b/addon/models/order.js @@ -22,6 +22,7 @@ export default class OrderModel extends Model { @attr('string') purchase_rate_uuid; @attr('string') tracking_number_uuid; @attr('string') driver_assigned_uuid; + @attr('string') vehicle_assigned_uuid; @attr('string') manifest_uuid; @attr('string') service_quote_uuid; @attr('string') order_config_uuid; @@ -58,6 +59,7 @@ export default class OrderModel extends Model { @alias('payload.entitiesByDestination') entitiesByDestination; @alias('payload.isMultiDrop') isMultiDrop; @alias('payload.isMultiDrop') isMultiDropOrder; + @alias('payload.hasIntermediateWaypoints') hasIntermediateWaypoints; /** @attributes */ @attr('string') tracking; @@ -76,10 +78,15 @@ export default class OrderModel extends Model { @attr('string') notes; @attr('string') type; @attr('string') status; + @attr('string') latest_status; + @attr('string') latest_status_code; @attr('number') adhoc_distance; + @attr('number') distance; + @attr('number') time; @attr('number') total_entities; @attr('number') transaction_amount; @attr('boolean') has_driver_assigned; + @attr('boolean') is_scheduled; @attr('boolean') pod_required; @attr('boolean') dispatched; @attr('boolean') started; @@ -466,10 +473,25 @@ export default class OrderModel extends Model { async loadPayload(options = {}) { const owner = getOwner(this); const store = owner.lookup('service:store'); - if (shouldNotLoadRelation(this, 'payload')) { + if (isBlank(this.payload_uuid)) { return; } + const existingPayload = this.payload; + const isLightweightIndexOrder = this.meta?._index_resource === true; + const hasLoadedWaypointCollection = typeof existingPayload?.waypoints?.toArray === 'function' || isArray(existingPayload?.waypoints); + const indexedWaypointCount = Number(existingPayload?.waypoints_count ?? 0); + const loadedWaypointCount = Number(existingPayload?.waypoints?.length ?? 0); + const needsWaypointUpgrade = indexedWaypointCount > 0 && loadedWaypointCount === 0; + + if (existingPayload && hasLoadedWaypointCollection && !needsWaypointUpgrade) { + return existingPayload; + } + + if (existingPayload && !hasLoadedWaypointCollection && !isLightweightIndexOrder) { + return existingPayload; + } + const payload = await store.queryRecord( 'payload', { diff --git a/addon/models/payload.js b/addon/models/payload.js index b446990..8768ecd 100644 --- a/addon/models/payload.js +++ b/addon/models/payload.js @@ -19,11 +19,14 @@ export default class PayloadModel extends Model { @hasMany('entity', { async: false }) entities; /** @attributes */ - @attr('string') meta; + @attr('raw') meta; @attr('string') cod_amount; @attr('string') cod_currency; @attr('string') cod_payment_method; + @attr('string') payment_method; @attr('string') type; + @attr('number') entities_count; + @attr('number') waypoints_count; @attr('date') deleted_at; @attr('date') created_at; @attr('date') updated_at; @@ -35,6 +38,14 @@ export default class PayloadModel extends Model { @notEmpty('dropoff_uuid') hasDropoff; @notEmpty('return_uuid') hasReturn; + @computed('waypoints.[]') get hasIntermediateWaypoints() { + return this.waypoints.length > 0; + } + + @computed('waypoints_count') get waypoint_count() { + return this.waypoints_count; + } + @computed('waypoints.[]', 'pickup_uuid', 'dropoff_uuid') get isMultiDrop() { return this.waypoints.length > 0 && !this.pickup_uuid && !this.dropoff_uuid; } @@ -109,12 +120,12 @@ export default class PayloadModel extends Model { // eslint-disable-next-line ember/use-brace-expansion @computed('{dropoff,pickup,waypoints}', 'waypoints.[]') get places() { - return [this.pickup, ...this.waypoints.toArray(), this.pickup].filter(Boolean); + return [this.pickup, ...this.waypoints.toArray(), this.dropoff].filter(Boolean); } // eslint-disable-next-line ember/use-brace-expansion @computed('waypoints.@each.place', 'waypoints.[]') get waypointPlaces() { - return this.waypoints.toArray().map((wp) => wp.place); + return this.waypoints.toArray().map((wp) => wp.place ?? wp); } @computed('{dropoff,pickup,waypoints}', 'waypoints.[]') get payloadCoordinates() { diff --git a/addon/models/recurring-order-schedule.js b/addon/models/recurring-order-schedule.js new file mode 100644 index 0000000..fce714c --- /dev/null +++ b/addon/models/recurring-order-schedule.js @@ -0,0 +1,50 @@ +import Model, { attr, belongsTo } from '@ember-data/model'; + +export default class RecurringOrderScheduleModel extends Model { + @attr('string') public_id; + @attr('string') uuid; + @attr('string') name; + @attr('string') description; + @attr('string') status; + @attr('string') timezone; + @attr('date') starts_at; + @attr('date') ends_at; + @attr('string') rrule; + @attr('date') last_materialized_at; + @attr('date') materialization_horizon; + @attr('string') customer_uuid; + @attr('string') customer_type; + @attr('string') facilitator_uuid; + @attr('string') facilitator_type; + @attr('string') order_config_uuid; + @attr('string') driver_assigned_uuid; + @attr('string') vehicle_assigned_uuid; + @attr('string') service_rate_uuid; + @attr('raw') template_order_meta; + @attr('raw') template_payload; + @attr('raw') template_entities; + @attr('raw') meta; + @attr('raw') upcoming_occurrences; + @attr('date') next_occurrence_at; + @attr('date') created_at; + @attr('date') updated_at; + + @belongsTo('customer', { polymorphic: true, async: false }) customer; + @belongsTo('facilitator', { polymorphic: true, async: false }) facilitator; + @belongsTo('order-config', { async: false }) order_config; + @belongsTo('driver', { async: false }) driver_assigned; + @belongsTo('vehicle', { async: false }) vehicle_assigned; + @belongsTo('service-rate', { async: false }) service_rate; + + get isActive() { + return this.status === 'active'; + } + + get isPaused() { + return this.status === 'paused'; + } + + get isCanceled() { + return this.status === 'canceled'; + } +} diff --git a/addon/models/waypoint.js b/addon/models/waypoint.js index 90d3f00..816f093 100644 --- a/addon/models/waypoint.js +++ b/addon/models/waypoint.js @@ -21,6 +21,7 @@ export default class WaypointModel extends PlaceModel { @attr('string') status_code; @attr('string') type; @attr('number') order; + @attr('boolean') complete; // Orchestrator time windows @attr('date') time_window_start; @attr('date') time_window_end; diff --git a/addon/serializers/entity.js b/addon/serializers/entity.js index 1cbcc63..61aaf06 100644 --- a/addon/serializers/entity.js +++ b/addon/serializers/entity.js @@ -41,10 +41,6 @@ export default class EntitySerializer extends ApplicationSerializer.extend(Embed if (isPolymorphicTypeBlank) { key = this.keyForAttribute ? this.keyForAttribute(key, 'serialize') : key; - if (!isBlank(belongsTo.attr(`${key}_type`))) { - type = belongsTo.attr(`${key}_type`); - } - if (!belongsTo) { json[key + '_type'] = null; } else { diff --git a/addon/serializers/maintenance-schedule.js b/addon/serializers/maintenance-schedule.js index badb35b..7832ab1 100644 --- a/addon/serializers/maintenance-schedule.js +++ b/addon/serializers/maintenance-schedule.js @@ -51,9 +51,6 @@ export default class MaintenanceScheduleSerializer extends ApplicationSerializer json[key + '_type'] = null; } else { let type = belongsTo.modelName; - if (!isBlank(belongsTo.attr(`${key}_type`))) { - type = belongsTo.attr(`${key}_type`); - } // Strip abstract subtype prefixes so the server receives the bare model type // e.g. 'facilitator-vendor' -> 'vendor', 'maintenance-subject-vehicle' -> 'vehicle' if (typeof type === 'string') { diff --git a/addon/serializers/maintenance.js b/addon/serializers/maintenance.js index e3f6306..8b2155d 100644 --- a/addon/serializers/maintenance.js +++ b/addon/serializers/maintenance.js @@ -53,9 +53,6 @@ export default class MaintenanceSerializer extends ApplicationSerializer.extend( json[key + '_type'] = null; } else { let type = belongsTo.modelName; - if (!isBlank(belongsTo.attr(`${key}_type`))) { - type = belongsTo.attr(`${key}_type`); - } // Strip abstract subtype prefixes so the server receives the bare model type // e.g. 'facilitator-vendor' -> 'vendor', 'maintenance-subject-vehicle' -> 'vehicle' if (typeof type === 'string') { diff --git a/addon/serializers/order.js b/addon/serializers/order.js index d74b467..a4cd5f1 100644 --- a/addon/serializers/order.js +++ b/addon/serializers/order.js @@ -85,9 +85,6 @@ export default class OrderSerializer extends ApplicationSerializer.extend(Embedd json[key + '_type'] = null; } else { let type = belongsTo.modelName; - if (!isBlank(belongsTo.attr(`${key}_type`))) { - type = belongsTo.attr(`${key}_type`); - } // Strip abstract subtype prefixes so the server receives the bare model type // e.g. 'facilitator-vendor' -> 'vendor', 'customer-contact' -> 'contact' if (typeof type === 'string') { diff --git a/addon/serializers/waypoint.js b/addon/serializers/waypoint.js index 81b5269..cac2a6d 100644 --- a/addon/serializers/waypoint.js +++ b/addon/serializers/waypoint.js @@ -68,10 +68,6 @@ export default class WaypointSerializer extends ApplicationSerializer.extend(Emb if (isPolymorphicTypeBlank) { key = this.keyForAttribute ? this.keyForAttribute(key, 'serialize') : key; - if (!isBlank(belongsTo.attr(`${key}_type`))) { - type = belongsTo.attr(`${key}_type`); - } - // hotfix polymprohpic model types that do not exists as models like `customer-contact` `customer-vendor` should be `contact` or `vendor` if (typeof type === 'string') { if (type.startsWith('customer-')) { diff --git a/addon/serializers/work-order.js b/addon/serializers/work-order.js index dfd8bce..292124c 100644 --- a/addon/serializers/work-order.js +++ b/addon/serializers/work-order.js @@ -52,9 +52,6 @@ export default class WorkOrderSerializer extends ApplicationSerializer.extend(Em json[key + '_type'] = null; } else { let type = belongsTo.modelName; - if (!isBlank(belongsTo.attr(`${key}_type`))) { - type = belongsTo.attr(`${key}_type`); - } // Strip abstract subtype prefixes so the server receives the bare model type // e.g. 'facilitator-vendor' -> 'vendor', 'maintenance-subject-vehicle' -> 'vehicle' if (typeof type === 'string') { diff --git a/app/models/recurring-order-schedule.js b/app/models/recurring-order-schedule.js new file mode 100644 index 0000000..b65eef6 --- /dev/null +++ b/app/models/recurring-order-schedule.js @@ -0,0 +1 @@ +export { default } from '@fleetbase/fleetops-data/models/recurring-order-schedule'; diff --git a/package.json b/package.json index 47bb20f..09eac8e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fleetbase/fleetops-data", - "version": "0.1.30", + "version": "0.1.31", "description": "Fleetbase Fleet-Ops based models, serializers, transforms, adapters and GeoJson utility functions.", "keywords": [ "fleetbase-data",