refactor: update default parameters and improve CSV download links in gen_proc and leave modules

This commit is contained in:
Ross
2026-07-08 21:34:13 +01:00
parent 09c8124cdd
commit 02598cb665
2 changed files with 79 additions and 56 deletions
+64 -40
View File
@@ -33,7 +33,7 @@ def load_leave(Rota):
if live_rota:
download = s.get(
"https://docs.google.com/spreadsheets/d/e/2PACX-1vQtNrp9F1fjtAh8vFX-W_R3RlD9H-2P_vCLMoHrVKR0e24yabbsdrD65VjwxoHlV1Qnatmw1NeghQHG/pub?gid=1199196967&single=true&output=csv",
"https://docs.google.com/spreadsheets/d/e/2PACX-1vSh64r9uUbPsCdhcV7zmZz10gVqIy6rhXFUvDgJxRD5W45IYEaZpKMxAqDsD1ph6dob4AiRzJXVVtOu/pub?gid=580824586&single=true&output=csv",
headers=headers,
)
# download = s.get("https://docs.google.com/spreadsheets/d/e/2PACX-1vSRx9VWXSlRubPyA0RhiI-Oqf5eHNYYEc6rFzlraDbR5_8qqr5g13-4uV-gn4u-TjZxiSMv1fBUaESq/pub?gid=814517272&single=true&output=csv", headers=headers)
@@ -55,10 +55,12 @@ def load_leave(Rota):
n = 1
for row in reader:
if n < 10:
print(row)
pass
#print(row)
row_title = row[0]
print(row_title)
#print(row_title)
row_date = row[0]
row_extra = row[1]
r = row[2:]
# header, extract names
if n == 1:
@@ -210,6 +212,14 @@ def load_leave(Rota):
if lower_item:
worker["bank_holiday_extra"] = int(lower_item)
elif row_title == "Weekends/Twilights":
if lower_item:
worker["site"] = lower_item
#elif row_title == "Academy":
# pass
elif re.match(date_re, row_date) is not None:
if lower_item != "":
try:
@@ -258,70 +268,79 @@ def load_leave(Rota):
return workers
# load_leave()
def load_academy(Rota):
"""Load academy month blocks from the main published CSV and register avoids.
Spreadsheet layout expected:
- Column A: row title (should be 'Academy' for relevant rows)
- Column B: start date for the month (e.g. '07/09/2026')
- Columns C...: worker columns matching the header row (first CSV row's columns C...)
Cells containing the word 'academy' (case-insensitive) mark that worker as being in academy
for that month.
"""
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"
# Use the same published CSV as load_leave (main sheet)
url = (
"https://docs.google.com/spreadsheets/d/e/2PACX-1vSh64r9uUbPsCdhcV7zmZz10gVqIy6rhXFUvDgJxRD5W45IYEaZpKMxAqDsD1ph6dob4AiRzJXVVtOu/pub?gid=580824586&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=',')
reader = csv.reader(decoded.splitlines(), delimiter=",")
names = []
month_starts: list[datetime.date] = []
month_cells: list[list[str]] = []
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:]
# header row: collect worker names from column C onwards
if n == 1:
# some files may have two leading columns (like 'Email Address' and blank/extra), so take from index 2
names = [c.strip() for c in (row[2:] if len(row) > 2 else row[1:])]
continue
# 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):
row_title = row[0].strip() if len(row) > 0 else ""
start_cell = row[1].strip() if len(row) > 1 else ""
cells = row[2:] if len(row) > 2 else []
# Only treat rows where the first column mentions 'Academy' (some sheets may include other rows)
if row_title and "academy" in row_title.lower():
# parse start date
try:
try:
d = datetime.strptime(row_title, "%d/%m/%Y").date()
start_date = datetime.strptime(start_cell, "%d/%m/%Y").date()
except ValueError:
d = datetime.strptime(row_title, "%d/%m/%y").date()
start_date = datetime.strptime(start_cell, "%d/%m/%y").date()
except Exception:
# skip rows without a valid date
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)
month_starts.append(start_date)
# normalize cell list to names length
row_cells = [(cells[i] if i < len(cells) else "").strip() for i in range(len(names))]
month_cells.append(row_cells)
# If no date rows found, nothing to do
if not date_rows:
if not month_starts:
return
# Identify twilight shift names available in the rota
# determine twilight shifts available
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)
# for each month start, compute end date and register avoids
for idx, start_date in enumerate(month_starts):
if idx + 1 < len(month_starts):
end_date = month_starts[idx + 1] - timedelta(days=1)
else:
end_date = Rota.rota_end_date
cells = date_row_cells[idx]
cells = month_cells[idx]
for i, cell in enumerate(cells):
if i >= len(names):
break
@@ -341,7 +360,7 @@ def load_academy(Rota):
sh = Rota.get_shift_by_name(sh_name)
except Exception:
continue
if hasattr(worker, "site") and worker.site in sh.sites:
if hasattr(worker, "site") and worker.site in getattr(sh, "sites", []):
candidate_shifts.append(sh_name)
elif sh_name.startswith(f"{worker.site}_"):
candidate_shifts.append(sh_name)
@@ -349,7 +368,12 @@ def load_academy(Rota):
if not candidate_shifts:
candidate_shifts = twilight_shift_names.copy()
# register as a date range with a reason 'academy'
#print(f"Academy: {worker.name} on academy from {start_date} to {end_date}, avoiding shifts: {candidate_shifts}")
Rota.add_avoid_shifts_for_workers_on_dates(
names=[worker.name], shifts=candidate_shifts, start_date=start_date, end_date=end_date, reason="academy"
names=[worker.name],
shifts=candidate_shifts,
start_date=start_date,
end_date=end_date,
reason="academy",
)