Add support for requesting shifts

This commit is contained in:
Ross
2020-05-28 18:16:46 +01:00
parent 469674546d
commit 74484db6c6
6 changed files with 171 additions and 26 deletions
+59 -10
View File
@@ -21,6 +21,14 @@ days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
# weeks_days_product = list(itertools.product(weeks, days))
from govuk_bank_holidays.bank_holidays import BankHolidays
bank_holidays = BankHolidays()
bank_holiday_map = {}
for bank_holiday in bank_holidays.get_holidays():
bank_holiday_map[bank_holiday['date']] = bank_holiday['title']
# see BankHolidays source file for more methods and arguments…
class SingleShift(object):
"""Class to hold all details for a shift"""
@@ -89,6 +97,11 @@ class RotaBuilder(object):
self.weeks_days_product = list(itertools.product(self.weeks, days))
if start_date.weekday() != 0:
raise ValueError(
"Start date {} must be a Mon (not a {})".format(
start_date.isoformat(), days[start_date.weekday()]))
self.start_date = start_date
self.rota_days_length = len(self.weeks) * 7
self.rota_end_date = self.start_date + datetime.timedelta(
@@ -96,6 +109,8 @@ class RotaBuilder(object):
self.unavailable_to_work = set()
self.pref_not_to_work = {}
self.work_requests = set()
self.work_requests_map = {}
self.workers = []
@@ -338,14 +353,25 @@ class RotaBuilder(object):
return 0
return 1
#print(self.unavailable_to_work)
self.model.available = Param(
((worker.id, week, day) for worker in self.workers
for week, day in self.get_week_day_combinations()),
initialize=availability_init,
)
def work_request_init(model, wid, week, day, shift):
if (wid, week, day, shift) in self.work_requests:
self.work_requests_map[(wid, week, day)] = shift
print((wid, week, day))
return 1
return 0
self.model.work_requests = Param(
((worker.id, week, day, shift) for worker in self.workers
for week, day, shift in self.get_all_shiftname_combinations()),
initialize=work_request_init,
)
def pref_init(model, wid, week, day):
if (wid, week, day) in self.pref_not_to_work:
return self.pref_not_to_work[(wid, week, day)]
@@ -943,13 +969,21 @@ class RotaBuilder(object):
weekend_shift_balancing = 0
preference_constant = 10
# Preferences
# Preferences (not to work)
preferences = sum(
self.model.pref_not_to_work[worker.id, week, day] *
self.model.works[worker.id, week, day, shift] *
preference_constant for worker in self.workers
for week, day, shift in self.get_all_shiftname_combinations())
# Work requsets
work_request_constant = 1000
work_requests = sum(
self.model.work_requests[worker.id, week, day, shift] *
self.model.works[worker.id, week, day, shift] *
work_request_constant for worker in self.workers
for week, day, shift in self.get_all_shiftname_combinations())
# # Spread nights
if self.constraint_options["balance_nights_across_sites"]:
@@ -974,7 +1008,7 @@ class RotaBuilder(object):
#return weekend_shift_balancing + blocks_balancing
#return shift_balancing + preferences + blocks_balancing
#return shift_balancing + preferences + nights_site_balancing + blocks_balancing
return shift_balancing + night_shift_balancing + preferences + nights_site_balancing + blocks_balancing
return shift_balancing + night_shift_balancing + preferences + nights_site_balancing + blocks_balancing - work_requests
# add objective function to the model. rule (pass function) or expr (pass expression directly)
self.model.obj = Objective(rule=obj_rule, sense=minimize)
@@ -1406,27 +1440,42 @@ class RotaResults(object):
n = 0
for week, day in self.rota.get_week_day_combinations():
d = self.rota.start_date + datetime.timedelta(n)
n = n + 1
a = "-"
shift_name = ""
title = "{} ({})".format(shift_name, d)
for shift in self.rota.get_shift_names_by_day(day):
if model.works[worker.id, week, day, shift].value == 1:
shifts.append(shift)
a = shift[0]
shift_name = shift
break
css_class = ""
css_class = day
if model.available[worker.id, week, day] > 0:
available = True
else:
available = False
css_class = "unavailable"
if worker.name == "Delilah Trimmer":
pass
bank_holiday = ""
if d in bank_holiday_map:
css_class = " ".join((css_class, "bank-holiday"))
bank_holiday = " data-bank-holiday='{}'".format(
bank_holiday_map[d])
requests = ""
if (worker.id, week, day) in self.rota.work_requests_map:
css_class = " ".join((css_class, "shift-requested"))
title = " ".join((title, "[REQUESTED]"))
requests = " data-shift-request='{}'".format(
self.rota.work_requests_map[(worker.id, week, day)])
w.append(
"<td title='{} ({})' class='rota-day {}' data-shift='{}' data-available='{}' data-date='{}' data-week='{}' data-day='{}'>{}</td>"
.format(shift_name, d, css_class, shift_name, available, d,
week, day, a))
"<td title='{}' class='rota-day {}' data-shift='{}' data-available='{}' data-date='{}' data-week='{}' data-day='{}'{}{}>{}</td>"
.format(title, css_class, shift_name, available, d, week,
day, requests, bank_holiday, a))
shift_count = ""
for s in set(shifts):