From ff033581198ad9b21c379a7210c85ef1d803a603 Mon Sep 17 00:00:00 2001 From: Ross Date: Fri, 25 Feb 2022 17:59:48 +0000 Subject: [PATCH] update timetable dispaly of remote sites --- output/timetable.css | 7 +++---- output/timetable.js | 16 +++++++++++----- rota/shifts.py | 42 ++++++++++++++++-------------------------- rota/workers.py | 7 +------ test/test_rota.py | 8 +++----- 5 files changed, 34 insertions(+), 46 deletions(-) diff --git a/output/timetable.css b/output/timetable.css index 555bece..05676a1 100644 --- a/output/timetable.css +++ b/output/timetable.css @@ -198,10 +198,9 @@ td.worker { } -[data-night-at-derriford="0"] { +/* [data-night-at-derriford="0"] { border: 1px dotted orange; - /* Attribute has this exact value */ -} +} */ th.site-title { transform: unset; @@ -227,7 +226,7 @@ summary h2 { display: inline; } -.derriford-night.shift-highlight { +.remote-site-match.shift-highlight { background-color: yellow; } diff --git a/output/timetable.js b/output/timetable.js index c17a6c0..ec74399 100644 --- a/output/timetable.js +++ b/output/timetable.js @@ -320,7 +320,8 @@ $(".table-div + pre").each((n, pre) => { $("td").hover((e) => { //start hover - pair = $(e.target).closest('tr').find('td:first')[0].dataset.pair; + worker_td = $(e.target).closest('tr').find('td:first')[0] + pair = worker_td.dataset.pair; index = $(e.target).index() - 1; if (pair > 0) { $(`td[data-pair=${pair}]`).each((n, el) => { @@ -330,9 +331,14 @@ $("td").hover((e) => { if (e.target.dataset.shift != undefined && e.target.dataset.shift.length > 0) { $(`td[data-shift=${e.target.dataset.shift}]`).addClass("shift-highlight") - if (e.target.dataset.shift.includes("night")) { - $(`td[data-night-at-derriford=1]`).siblings().addClass("derriford-night") - } + console.log(`td[data-remote-site='${e.target.dataset.shiftRemoteSite}']`) + console.log($(e.target).closest('tr').find(`td[data-remote-site='${e.target.dataset.shiftRemoteSite}']`)) + + $(`td[data-remote-site='${e.target.dataset.shiftRemoteSite}']`).closest('tr').find(`td[data-shift=${e.target.dataset.shift}]`).addClass("remote-site-match") + // console.log(e.target.dataset.shiftRemoteSite , worker_td.dataset.remoteSite) + // if (e.target.dataset.shiftRemoteSite == worker_td.dataset.remoteSite) { + // $(`td[data-shift-remote-site=${e.target.dataset.shiftRemoteSite}]`).addClass("remote-site-match") + // } } }, (e) => { @@ -340,7 +346,7 @@ $("td").hover((e) => { //end hover $("td.pair-match").removeClass("pair-match") $("td.shift-highlight").removeClass("shift-highlight") - $("td.derriford-night").removeClass("derriford-night") + $("td.remote-site-match").removeClass("remote-site-match") }) diff --git a/rota/shifts.py b/rota/shifts.py index 7108a98..d291115 100644 --- a/rota/shifts.py +++ b/rota/shifts.py @@ -55,6 +55,9 @@ class SingleShift(object): postclear(2) / preclear(2) + require_remote_site_presence: + options: (site, required_number) + night limit_grade_number: @@ -123,7 +126,7 @@ class SingleShift(object): # self.total_shifts = length * len(days) * len(shift_days) def __str__(self): - return f"name: {self.name}, site: {self.site}, length: {self.length}, balance weighting: {self.balance_weighting}, balance offset: {self.balance_offset}, hard_constrain: {self.hard_constrain_shift}, workers required : {self.workers_required}, rota on nwds {self.rota_on_nwds}, assign as block: {self.assign_as_block}, force as block: {self.force_as_block}, constraints: {self.constraints}" # , total shifts: {self.total_shifts}" + return f"name: {self.name}, site: {self.site}, length: {self.length}, balance weighting: {self.balance_weighting}, balance offset: {self.balance_offset}, hard_constrain: {self.hard_constrain_shift}, workers required : {self.workers_required}, rota on nwds {self.rota_on_nwds}, assign as block: {self.assign_as_block}, force as block: {self.force_as_block}, constraints: {self.constraints}, constraint_options: {self.constraint_options}" # , total shifts: {self.total_shifts}" def get_shift_summary(self): """ @@ -181,7 +184,7 @@ class RotaBuilder(object): self.work_requests = set() self.work_requests_map = {} - self.workers = [] + self.workers: list[Worker] = [] self.worker_pairs = [] # self.night_blocks = ["weekday", "weekend", "none"] @@ -197,7 +200,6 @@ class RotaBuilder(object): self.constraint_options = { "ensure_1_st4_plus_on_nights": True, - "ensure_derriford_reg_for_nights": True, "balance_nights": True, "constrain_time_off_after_nights": False, "balance_nights_across_sites": True, @@ -791,25 +793,6 @@ class RotaBuilder(object): ), ) - # def nightShiftDerrifordRule(model, week, shift): - # derriford_workers = [w for w in self.workers if w.night_at_derriford >= 1] - # # if not derriford_workers: - # # return Constraint.Skip - # return ( - # sum( - # model.shift_week_worker_assigned[shift, week, w.id] - # for w in derriford_workers - # ) - # >= 1 - # ) - - # if self.constraint_options["ensure_derriford_reg_for_nights"]: - # self.model.night_shifts_derriford_rule = Constraint( - # [week for week in self.weeks], - # [shift.name for shift in self.get_shifts_with_constraint("night")], - # rule=nightShiftDerrifordRule, - # ) - def presenceAtRemoteSite(model, week, shift, required_site, required_number): required_site_workers = [ w for w in self.workers if required_site == w.remote_site @@ -2465,13 +2448,14 @@ class RotaBuilder(object): a = "-" shift_name = "" + # Loop through all the days possible shifts and see + # if the worker has been assigned for shift in self.get_shift_names_by_week_day(week, day): if model.works[worker.id, week, day, shift].value > 0: shifts.append(shift) a = shift[0] shift_name = shift break - # If we haven't run just add the shift title = f"{shift_name} ({d})" css_class = day unavailable_reason = "" @@ -2503,8 +2487,14 @@ class RotaBuilder(object): title = " ".join((title, "[REQUESTED]")) requests = f" data-shift-request='{self.work_requests_map[worker.id, week, day]}'" + remote_site = "" + if shift_name: + shift = self.get_shift_by_name(shift_name) + if "require_remote_site_presence" in shift.constraints: + remote_site = f" data-shift-remote-site='{shift.constraint_options['require_remote_site_presence'][0]}'" + shift_tds.append( - f"{a}" + f"{a}" ) shift_count = "" @@ -2524,7 +2514,7 @@ class RotaBuilder(object): data-fte='{fte}' data-fte_adj='{fte_adj}' data-end_date='{end_date}' data-worker-targets='{targets}' data-shift-counts='{worker_shift_counts}' data-weekend-target='{weekend_target}' - data-night-at-derriford='{nights_at_derriford}' + data-remote-site='{remote_site}' data-pair='{pair}' data-shift-balance-extra='{shift_balance_extra}' data-bank-holiday-extra='{bank_holiday_extra}' @@ -2541,7 +2531,7 @@ class RotaBuilder(object): targets=worker_targets, worker_shift_counts=json.dumps(shift_count_dict), weekend_target=worker.weekend_shift_target_number, - nights_at_derriford=worker.night_at_derriford, + remote_site=worker.remote_site, grade=worker.grade, pair=worker.pair, shift_balance_extra=json.dumps(worker.shift_balance_extra), diff --git a/rota/workers.py b/rota/workers.py index 7d4c46e..e19770f 100644 --- a/rota/workers.py +++ b/rota/workers.py @@ -52,10 +52,6 @@ class Worker: self.bank_holiday_extra = bank_holiday_extra self.remote_site = remote_site - if remote_site == "plymouth" or remote_site == "": - self.night_at_derriford = 1 - else: - self.night_at_derriford = 0 self.previous_shifts = previous_shifts @@ -181,12 +177,11 @@ class Worker: def __str__(self) -> str: nwd = ", ".join([str(i) for i in self.nwd]) if self.nwd is not None else "" - return "{} {} [{}] PROC SITE:{} ({})".format( + return "{} {} [{}] REMOTE SITE:{}".format( self.name, (self.site, self.grade, self.fte_adj), nwd, self.remote_site, - self.night_at_derriford, ) def get_details(self) -> str: diff --git a/test/test_rota.py b/test/test_rota.py index 1ce7c81..0ee9583 100644 --- a/test/test_rota.py +++ b/test/test_rota.py @@ -22,7 +22,6 @@ class TestDemoRota: Rota.constraint_options["max_shifts_per_week"] = 5 Rota.constraint_options["max_shifts_per_month"] = 31 - Rota.constraint_options["ensure_derriford_reg_for_nights"] = False Rota.constraint_options["constrain_time_off_after_nights"] = False Rota.constraint_options["balance_nights_across_site"] = False Rota.constraint_options["balance_shifts"] = True @@ -159,7 +158,7 @@ class TestDemoRota: case _: assert 1 == 0 - def test_worker_shift_targets(self): + def test_worker_shift_targets2(self): shift_number = self.Rota.get_shift_summary_dict() for worker in self.Rota.workers: @@ -197,7 +196,6 @@ class TestDemoRotaNights: Rota.constraint_options["max_shifts_per_week"] = 5 Rota.constraint_options["max_shifts_per_month"] = 31 - Rota.constraint_options["ensure_derriford_reg_for_nights"] = False Rota.constraint_options["limit_to_1_st2_on_nights"] = False Rota.constraint_options["constrain_time_off_after_nights"] = False Rota.constraint_options["balance_nights_across_site"] = False @@ -868,7 +866,7 @@ class TestLimitConstraints: ), ) self.Rota.build_and_solve(options={"ratio": 0.00}) - self.Rota.export_rota_to_html("test9") + self.Rota.export_rota_to_html("remote1") group_workers = self.Rota.get_workers_by_group() for group in group_workers: @@ -902,7 +900,7 @@ class TestLimitConstraints: ), ) self.Rota.build_and_solve(options={"ratio": 0.00}) - self.Rota.export_rota_to_html("test9") + self.Rota.export_rota_to_html("remote2") group_workers = self.Rota.get_workers_by_group() for group in group_workers: