mirror of
https://github.com/Sea-Haven-Industries/afterhours-shift-manager.git
synced 2026-09-30 06:43:12 +00:00
Fix weekend day shift commands and admin 3CX routing
- Add _find_employee_shift() to check both day/night on weekends - Drop/swap now correctly find and operate on weekend day shifts - Pick finds first available shift type on weekends - Admin override/open/clear update 3CX for same-day active shifts
This commit is contained in:
parent
eb8f397b9e
commit
69220afb9a
1 changed files with 72 additions and 13 deletions
|
|
@ -100,6 +100,24 @@ def _is_active_shift_type(shift_type: str) -> bool:
|
|||
return shift_type == "night"
|
||||
|
||||
|
||||
def _find_employee_shift(schedule, date_str, day_name, employee_ext):
|
||||
"""Find which shift type an employee is assigned to on a given date.
|
||||
|
||||
On weekends, checks both day and night shifts. Returns (ext, name, source, shift_type)
|
||||
or None if not found on any shift.
|
||||
"""
|
||||
if day_name in WEEKEND_DAYS:
|
||||
for st in ("day", "night"):
|
||||
ext, name, source = schedule.resolve_shift(date_str, day_name, st)
|
||||
if ext == employee_ext:
|
||||
return ext, name, source, st
|
||||
return None
|
||||
ext, name, source = schedule.resolve_shift(date_str, day_name, "night")
|
||||
if ext == employee_ext:
|
||||
return ext, name, source, "night"
|
||||
return None
|
||||
|
||||
|
||||
def create_app(
|
||||
bot_token: str, signing_secret: str, schedule_channel: str | None = None
|
||||
) -> App:
|
||||
|
|
@ -380,7 +398,19 @@ def create_app(
|
|||
return
|
||||
|
||||
day_name = date.strftime("%A")
|
||||
ext, name, source = schedule.resolve_shift(date_str, day_name)
|
||||
|
||||
# On weekends, find the first available shift (day then night)
|
||||
shift_type = "night"
|
||||
if day_name in WEEKEND_DAYS:
|
||||
for st in ("day", "night"):
|
||||
ext, name, source = schedule.resolve_shift(date_str, day_name, st)
|
||||
if source == "available":
|
||||
shift_type = st
|
||||
break
|
||||
else:
|
||||
ext, name, source = schedule.resolve_shift(date_str, day_name)
|
||||
else:
|
||||
ext, name, source = schedule.resolve_shift(date_str, day_name)
|
||||
|
||||
# Already assigned to someone else (not open)
|
||||
if source in ("weekly", "override") and ext != FALLBACK_EXTENSION:
|
||||
|
|
@ -389,15 +419,22 @@ def create_app(
|
|||
)
|
||||
return
|
||||
|
||||
schedule.set_override(date_str, employee["extension"], employee["name"])
|
||||
schedule.set_override(
|
||||
date_str, employee["extension"], employee["name"], shift_type
|
||||
)
|
||||
|
||||
if is_today(date_str) and _is_active_shift_type("night"):
|
||||
if is_today(date_str) and _is_active_shift_type(shift_type):
|
||||
_update_3cx_routing(employee["extension"])
|
||||
|
||||
respond(text=f"You picked up the shift for *{date.strftime('%A, %b %-d')}*.")
|
||||
|
||||
blocks = build_shift_change_message(
|
||||
user_id, date_str, "picked_up", employee["extension"], employee["name"]
|
||||
user_id,
|
||||
date_str,
|
||||
"picked_up",
|
||||
employee["extension"],
|
||||
employee["name"],
|
||||
shift_type=shift_type,
|
||||
)
|
||||
try:
|
||||
client.chat_postMessage(
|
||||
|
|
@ -435,22 +472,28 @@ def create_app(
|
|||
return
|
||||
|
||||
day_name = date.strftime("%A")
|
||||
ext, name, source = schedule.resolve_shift(date_str, day_name)
|
||||
found = _find_employee_shift(
|
||||
schedule, date_str, day_name, employee["extension"]
|
||||
)
|
||||
|
||||
if ext != employee["extension"]:
|
||||
if not found:
|
||||
ext, name, _source = schedule.resolve_shift(date_str, day_name)
|
||||
respond(text=f"That's not your shift — it belongs to {name} (Ext {ext}).")
|
||||
return
|
||||
|
||||
schedule.mark_open(date_str)
|
||||
ext, name, source, shift_type = found
|
||||
schedule.mark_open(date_str, shift_type)
|
||||
|
||||
if is_today(date_str) and _is_active_shift_type("night"):
|
||||
if is_today(date_str) and _is_active_shift_type(shift_type):
|
||||
_update_3cx_routing(FALLBACK_EXTENSION)
|
||||
|
||||
respond(
|
||||
text=f"You dropped the shift for *{date.strftime('%A, %b %-d')}*. It's now open for pickup."
|
||||
)
|
||||
|
||||
blocks = build_shift_change_message(user_id, date_str, "dropped", ext, name)
|
||||
blocks = build_shift_change_message(
|
||||
user_id, date_str, "dropped", ext, name, shift_type=shift_type
|
||||
)
|
||||
try:
|
||||
client.chat_postMessage(
|
||||
channel=channel_id, blocks=blocks, text=f"Shift dropped for {date_str}"
|
||||
|
|
@ -486,14 +529,19 @@ def create_app(
|
|||
return
|
||||
|
||||
day_name = date.strftime("%A")
|
||||
ext, name, source = schedule.resolve_shift(date_str, day_name)
|
||||
found = _find_employee_shift(
|
||||
schedule, date_str, day_name, employee["extension"]
|
||||
)
|
||||
|
||||
if ext != employee["extension"]:
|
||||
if not found:
|
||||
ext, name, _source = schedule.resolve_shift(date_str, day_name)
|
||||
respond(
|
||||
text=f"That's not your shift — it belongs to {name} (Ext {ext}). You can only swap your own shifts."
|
||||
)
|
||||
return
|
||||
|
||||
_ext, _name, _source, shift_type = found
|
||||
|
||||
# Resolve target user — could be <@U12345> or an extension number
|
||||
target_text = parts[2].strip()
|
||||
slack_id_match = re.match(r"<@(\w+)(?:\|[^>]*)?>", target_text)
|
||||
|
|
@ -511,9 +559,9 @@ def create_app(
|
|||
respond(text=f"Extension `{target_text}` not found in the roster.")
|
||||
return
|
||||
|
||||
schedule.set_override(date_str, target["extension"], target["name"])
|
||||
schedule.set_override(date_str, target["extension"], target["name"], shift_type)
|
||||
|
||||
if is_today(date_str) and _is_active_shift_type("night"):
|
||||
if is_today(date_str) and _is_active_shift_type(shift_type):
|
||||
_update_3cx_routing(target["extension"])
|
||||
|
||||
blocks = build_shift_change_message(
|
||||
|
|
@ -522,6 +570,7 @@ def create_app(
|
|||
"swapped",
|
||||
target["extension"],
|
||||
target["name"],
|
||||
shift_type=shift_type,
|
||||
)
|
||||
respond(
|
||||
text=f"Swapped *{date.strftime('%A, %b %-d')}* to {target['name']} (Ext {target['extension']})."
|
||||
|
|
@ -572,6 +621,8 @@ def create_app(
|
|||
return
|
||||
date_str = date.strftime("%Y-%m-%d")
|
||||
schedule.set_override(date_str, employee["extension"], employee["name"])
|
||||
if is_today(date_str) and _is_active_shift_type("night"):
|
||||
_update_3cx_routing(employee["extension"])
|
||||
respond(
|
||||
text=f"Override set: *{date.strftime('%A, %b %-d')}* → {employee['name']} (Ext {ext})"
|
||||
)
|
||||
|
|
@ -587,6 +638,8 @@ def create_app(
|
|||
return
|
||||
date_str = date.strftime("%Y-%m-%d")
|
||||
schedule.mark_open(date_str)
|
||||
if is_today(date_str) and _is_active_shift_type("night"):
|
||||
_update_3cx_routing(FALLBACK_EXTENSION)
|
||||
respond(text=f"*{date.strftime('%A, %b %-d')}* marked as open.")
|
||||
_refresh_schedule_post(client)
|
||||
|
||||
|
|
@ -600,6 +653,12 @@ def create_app(
|
|||
return
|
||||
date_str = date.strftime("%Y-%m-%d")
|
||||
schedule.remove_override(date_str)
|
||||
if is_today(date_str) and _is_active_shift_type("night"):
|
||||
day_name = date.strftime("%A")
|
||||
ext, _name, _source = schedule.resolve_shift(
|
||||
date_str, day_name, "night"
|
||||
)
|
||||
_update_3cx_routing(ext)
|
||||
respond(
|
||||
text=f"Override cleared for *{date.strftime('%A, %b %-d')}* — reverted to weekly schedule."
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue