mirror of
https://github.com/fleetbase/fleetbase.git
synced 2026-04-06 16:22:33 +00:00
Compare commits
3 Commits
main
...
feat/sched
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4715d137f | ||
|
|
a83f1f7079 | ||
|
|
7f5242fff4 |
69
console/app/models/schedule-exception.js
Normal file
69
console/app/models/schedule-exception.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import Model, { attr, belongsTo } from '@ember-data/model';
|
||||
|
||||
/**
|
||||
* ScheduleException
|
||||
*
|
||||
* Represents a deviation from a driver's recurring schedule — time off requests,
|
||||
* sick leave, holidays, shift swaps, training days, or other exceptions.
|
||||
*
|
||||
* An exception is submitted by a driver or dispatcher, then approved or rejected
|
||||
* by a manager. When approved, all ScheduleItem records that fall within the
|
||||
* exception's date range are automatically cancelled.
|
||||
*
|
||||
* @see core-api ScheduleException model
|
||||
*/
|
||||
export default class ScheduleExceptionModel extends Model {
|
||||
/** @ids */
|
||||
@attr('string') public_id;
|
||||
@attr('string') schedule_uuid;
|
||||
@attr('string') subject_uuid;
|
||||
@attr('string') subject_type;
|
||||
@attr('string') requested_by_uuid;
|
||||
|
||||
/** @attributes */
|
||||
@attr('string', { defaultValue: 'time_off' }) type;
|
||||
@attr('string', { defaultValue: 'pending' }) status;
|
||||
@attr('date') start_at;
|
||||
@attr('date') end_at;
|
||||
@attr('string') reason;
|
||||
@attr('string') notes;
|
||||
@attr('string') rejection_reason;
|
||||
@attr('date') reviewed_at;
|
||||
@attr('string') reviewed_by_uuid;
|
||||
|
||||
/** @meta */
|
||||
@attr('object') meta;
|
||||
|
||||
/** @relationships */
|
||||
@belongsTo('schedule', { async: true }) schedule;
|
||||
|
||||
/** @dates */
|
||||
@attr('date') created_at;
|
||||
@attr('date') updated_at;
|
||||
@attr('date') deleted_at;
|
||||
|
||||
/** @computed */
|
||||
get isPending() {
|
||||
return this.status === 'pending';
|
||||
}
|
||||
|
||||
get isApproved() {
|
||||
return this.status === 'approved';
|
||||
}
|
||||
|
||||
get isRejected() {
|
||||
return this.status === 'rejected';
|
||||
}
|
||||
|
||||
get typeLabel() {
|
||||
const labels = {
|
||||
time_off: 'Time Off',
|
||||
sick_leave: 'Sick Leave',
|
||||
holiday: 'Holiday',
|
||||
swap: 'Shift Swap',
|
||||
training: 'Training',
|
||||
other: 'Other',
|
||||
};
|
||||
return labels[this.type] || this.type;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
import Model, { attr, belongsTo } from '@ember-data/model';
|
||||
|
||||
export default class ScheduleItemModel extends Model {
|
||||
/** @ids */
|
||||
@attr('string') public_id;
|
||||
@attr('string') schedule_uuid;
|
||||
@attr('string') schedule_template_uuid;
|
||||
@attr('string') assignee_uuid;
|
||||
@attr('string') assignee_type;
|
||||
@attr('string') resource_uuid;
|
||||
@@ -12,10 +14,20 @@ export default class ScheduleItemModel extends Model {
|
||||
@attr('number') duration;
|
||||
@attr('date') break_start_at;
|
||||
@attr('date') break_end_at;
|
||||
@attr('string', { defaultValue: 'pending' }) status;
|
||||
@attr('string') title;
|
||||
@attr('string', { defaultValue: 'scheduled' }) status;
|
||||
@attr('string') notes;
|
||||
|
||||
/** @exception fields */
|
||||
@attr('boolean', { defaultValue: false }) is_exception;
|
||||
@attr('date') exception_for_date;
|
||||
|
||||
/** @meta */
|
||||
@attr('object') meta;
|
||||
|
||||
@belongsTo('schedule') schedule;
|
||||
/** @relationships */
|
||||
@belongsTo('schedule', { async: true }) schedule;
|
||||
@belongsTo('schedule-template', { async: true }) scheduleTemplate;
|
||||
|
||||
@attr('date') created_at;
|
||||
@attr('date') updated_at;
|
||||
|
||||
@@ -1,22 +1,51 @@
|
||||
import Model, { attr, belongsTo } from '@ember-data/model';
|
||||
|
||||
/**
|
||||
* ScheduleTemplate
|
||||
*
|
||||
* A reusable recurring shift pattern that a manager can apply to one or many
|
||||
* drivers. Stores the RRULE (e.g. FREQ=WEEKLY;BYDAY=MO,TU,TH) plus the
|
||||
* daily start/end times. When applied to a driver's Schedule, the
|
||||
* ScheduleService materialises ScheduleItem records for the rolling horizon.
|
||||
*/
|
||||
export default class ScheduleTemplateModel extends Model {
|
||||
/** @ids */
|
||||
@attr('string') public_id;
|
||||
@attr('string') company_uuid;
|
||||
@attr('string') subject_uuid;
|
||||
@attr('string') subject_type;
|
||||
|
||||
/** @attributes */
|
||||
@attr('string') name;
|
||||
@attr('string') description;
|
||||
@attr('string') start_time;
|
||||
@attr('string') end_time;
|
||||
@attr('number') duration;
|
||||
@attr('number') break_duration;
|
||||
@attr('string') rrule;
|
||||
@attr('string') start_time; // HH:mm — e.g. "08:00"
|
||||
@attr('string') end_time; // HH:mm — e.g. "16:00"
|
||||
@attr('string') break_start_time; // HH:mm — e.g. "12:00" (optional)
|
||||
@attr('string') break_end_time; // HH:mm — e.g. "13:00" (optional)
|
||||
@attr('number') duration; // computed minutes (end - start)
|
||||
@attr('number') break_duration; // minutes
|
||||
@attr('string') rrule; // RFC 5545 RRULE string
|
||||
@attr('string') color; // hex color for calendar display
|
||||
@attr('object') meta;
|
||||
|
||||
@belongsTo('company') company;
|
||||
/** @relationships */
|
||||
@belongsTo('company', { async: true }) company;
|
||||
|
||||
/** @dates */
|
||||
@attr('date') created_at;
|
||||
@attr('date') updated_at;
|
||||
@attr('date') deleted_at;
|
||||
|
||||
/**
|
||||
* Parse the RRULE string and return a human-readable summary.
|
||||
* e.g. "Weekly on Mon, Tue, Thu · 08:00–16:00"
|
||||
*/
|
||||
get recurrenceSummary() {
|
||||
if (!this.rrule) return null;
|
||||
const dayMap = { MO: 'Mon', TU: 'Tue', WE: 'Wed', TH: 'Thu', FR: 'Fri', SA: 'Sat', SU: 'Sun' };
|
||||
const byday = this.rrule.match(/BYDAY=([^;]+)/);
|
||||
const days = byday ? byday[1].split(',').map((d) => dayMap[d] || d).join(', ') : '';
|
||||
const freq = this.rrule.match(/FREQ=(\w+)/);
|
||||
const freqLabel = freq ? freq[1].charAt(0) + freq[1].slice(1).toLowerCase() : '';
|
||||
const times = this.start_time && this.end_time ? ` · ${this.start_time}–${this.end_time}` : '';
|
||||
return `${freqLabel} on ${days}${times}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,14 @@ export default class ScheduleModel extends Model {
|
||||
@attr('string', { defaultValue: 'draft' }) status;
|
||||
@attr('object') meta;
|
||||
|
||||
/** @materialization tracking */
|
||||
@attr('date') last_materialized_at;
|
||||
@attr('number', { defaultValue: 60 }) materialization_horizon_days;
|
||||
|
||||
/** @relationships */
|
||||
@hasMany('schedule-item') items;
|
||||
@belongsTo('company') company;
|
||||
@hasMany('schedule-item', { async: true }) items;
|
||||
@hasMany('schedule-exception', { async: true }) exceptions;
|
||||
@belongsTo('company', { async: true }) company;
|
||||
|
||||
/** @dates */
|
||||
@attr('date') created_at;
|
||||
|
||||
Reference in New Issue
Block a user