Add support for avoiding shifts on specific dates with reasons
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import csv
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
import re
|
||||
import sys
|
||||
from requests import Session
|
||||
@@ -264,4 +264,92 @@ def load_academy(Rota):
|
||||
"""
|
||||
Some trainees spend month blocks in the academy. This function loads that information from a google sheet that published it as a csv file.
|
||||
"""
|
||||
url = "https://docs.google.com/spreadsheets/d/e/2PACX-1vQtNrp9F1fjtAh8vFX-W_R3RlD9H-2P_vCLMoHrVKR0e24yabbsdrD65VjwxoHlV1Qnatmw1NeghQHG/pub?gid=1113837782&single=true&output=csv"
|
||||
url = "https://docs.google.com/spreadsheets/d/e/2PACX-1vQtNrp9F1fjtAh8vFX-W_R3RlD9H-2P_vCLMoHrVKR0e24yabbsdrD65VjwxoHlV1Qnatmw1NeghQHG/pub?gid=1113837782&single=true&output=csv"
|
||||
|
||||
with Session() as s:
|
||||
headers = {"Cache-Control": "no-cache", "Pragma": "no-cache"}
|
||||
download = s.get(url, headers=headers)
|
||||
decoded = download.content.decode("utf-8")
|
||||
|
||||
reader = csv.reader(decoded.splitlines(), delimiter=',')
|
||||
|
||||
n = 0
|
||||
names = []
|
||||
# collect date rows (these are the month start boundaries) and their cells
|
||||
date_rows: list[datetime.date] = []
|
||||
date_row_cells: list[list[str]] = []
|
||||
|
||||
for row in reader:
|
||||
n += 1
|
||||
if n == 1:
|
||||
# header row: first cell is column title, remaining are worker names
|
||||
names = [c.strip() for c in row[1:]]
|
||||
continue
|
||||
|
||||
if not row:
|
||||
continue
|
||||
|
||||
row_title = row[0].strip()
|
||||
cells = row[1:]
|
||||
|
||||
# If this row is a date row like '02/03/2026' then treat it as a month-start boundary
|
||||
if re.match(date_re, row_title):
|
||||
try:
|
||||
try:
|
||||
d = datetime.strptime(row_title, "%d/%m/%Y").date()
|
||||
except ValueError:
|
||||
d = datetime.strptime(row_title, "%d/%m/%y").date()
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
date_rows.append(d)
|
||||
# normalize cells length to match names
|
||||
row_cells = [ (cells[i] if i < len(cells) else "").strip() for i in range(len(names)) ]
|
||||
date_row_cells.append(row_cells)
|
||||
|
||||
# If no date rows found, nothing to do
|
||||
if not date_rows:
|
||||
return
|
||||
|
||||
# Identify twilight shift names available in the rota
|
||||
twilight_shift_names = [s.name for s in Rota.get_shifts() if "twilight" in s.name]
|
||||
|
||||
# For each date boundary, compute its end (next boundary - 1 day) and register avoids where cell=='academy'
|
||||
for idx, start_date in enumerate(date_rows):
|
||||
if idx + 1 < len(date_rows):
|
||||
end_date = date_rows[idx + 1] - timedelta(days=1)
|
||||
else:
|
||||
end_date = Rota.rota_end_date
|
||||
|
||||
cells = date_row_cells[idx]
|
||||
for i, cell in enumerate(cells):
|
||||
if i >= len(names):
|
||||
break
|
||||
v = (cell or "").lower()
|
||||
if "academy" in v:
|
||||
worker_name = names[i]
|
||||
matching_workers = [w for w in Rota.workers if w.name.strip() == worker_name.strip()]
|
||||
if not matching_workers:
|
||||
logger.warning(f"Academy data: worker '{worker_name}' not found in rota, skipping")
|
||||
continue
|
||||
worker = matching_workers[0]
|
||||
|
||||
# choose twilight shifts relevant to the worker's site
|
||||
candidate_shifts = []
|
||||
for sh_name in twilight_shift_names:
|
||||
try:
|
||||
sh = Rota.get_shift_by_name(sh_name)
|
||||
except Exception:
|
||||
continue
|
||||
if hasattr(worker, "site") and worker.site in sh.sites:
|
||||
candidate_shifts.append(sh_name)
|
||||
elif sh_name.startswith(f"{worker.site}_"):
|
||||
candidate_shifts.append(sh_name)
|
||||
|
||||
if not candidate_shifts:
|
||||
candidate_shifts = twilight_shift_names.copy()
|
||||
|
||||
# register as a date range with a reason 'academy'
|
||||
Rota.add_avoid_shifts_for_workers_on_dates(
|
||||
names=[worker.name], shifts=candidate_shifts, start_date=start_date, end_date=end_date, reason="academy"
|
||||
)
|
||||
Reference in New Issue
Block a user