feat(backend): create improved tests

This commit is contained in:
2025-08-29 23:50:44 -04:00
parent 1dbfbb9ce6
commit b25191d99a
9 changed files with 3031 additions and 177 deletions

View File

@@ -48,12 +48,17 @@ class ScheduleRepository(BaseRepository[ScheduleModel]):
scheduled_at, expires_at : datetimecompatible | None
``scheduled_at`` defaults to SQLites ``CURRENT_TIMESTAMP``.
"""
# Handle timestamp - use actual datetime if not provided
import datetime
if scheduled_at is None:
scheduled_at = datetime.datetime.now(datetime.UTC).isoformat()
schedule = ScheduleModel(
ScheduleId=-1, # placeholder will be replaced
ServiceId=service_id,
MemberId=member_id,
Status=status.value,
ScheduledAt=scheduled_at or "CURRENT_TIMESTAMP",
ScheduledAt=scheduled_at,
AcceptedAt=None,
DeclinedAt=None,
ExpiresAt=expires_at,
@@ -110,8 +115,8 @@ class ScheduleRepository(BaseRepository[ScheduleModel]):
params: list[Any] = [new_status.value]
if new_status == ScheduleStatus.DECLINED:
set_clause = "Status = ?, DeclinedAt = ?, DeclineReason = ?"
params.extend(["CURRENT_TIMESTAMP", reason])
set_clause = "Status = ?, DeclinedAt = datetime('now'), DeclineReason = ?"
params.extend([reason])
params.append(schedule_id) # WHERE clause param
@@ -148,43 +153,6 @@ class ScheduleRepository(BaseRepository[ScheduleModel]):
row = self.db.fetchone(sql, params)
return row is not None
def is_available(self, member_id: int, service_id: int) -> bool:
"""
Cooldown rule: a member is unavailable if they have accepted a
schedule for the same service within the last ``COOLDOWN_DAYS``.
"""
# Latest acceptance timestamp (if any)
sql_latest = f"""
SELECT MAX(AcceptedAt) AS last_accept
FROM {self._TABLE}
WHERE MemberId = ?
AND ServiceId = ?
AND Status = ?
"""
row = self.db.fetchone(
sql_latest,
(member_id, service_id, ScheduleStatus.ACCEPTED.value),
)
last_accept: Optional[str] = row["last_accept"] if row else None
if not last_accept:
return True # never accepted → free to schedule
COOLDOWN_DAYS = 1
sql_cooldown = f"""
SELECT 1
FROM {self._TABLE}
WHERE MemberId = ?
AND ServiceId = ?
AND Status = ?
AND DATE(AcceptedAt) >= DATE('now', '-{COOLDOWN_DAYS} day')
LIMIT 1
"""
row = self.db.fetchone(
sql_cooldown,
(member_id, service_id, ScheduleStatus.ACCEPTED.value),
)
return row is None # None → outside the cooldown window
# ------------------------------------------------------------------
# Statustransition helpers (accept / decline) kept for completeness.
@@ -194,16 +162,26 @@ class ScheduleRepository(BaseRepository[ScheduleModel]):
schedule_id: int,
accepted_at: Optional[Any] = None,
) -> None:
sql = f"""
UPDATE {self._TABLE}
SET Status = ?,
AcceptedAt = ?,
DeclinedAt = NULL,
DeclineReason = NULL
WHERE {self._PK} = ?
"""
ts = accepted_at or "CURRENT_TIMESTAMP"
self.db.execute(sql, (ScheduleStatus.ACCEPTED.value, ts, schedule_id))
if accepted_at is None:
sql = f"""
UPDATE {self._TABLE}
SET Status = ?,
AcceptedAt = datetime('now'),
DeclinedAt = NULL,
DeclineReason = NULL
WHERE {self._PK} = ?
"""
self.db.execute(sql, (ScheduleStatus.ACCEPTED.value, schedule_id))
else:
sql = f"""
UPDATE {self._TABLE}
SET Status = ?,
AcceptedAt = ?,
DeclinedAt = NULL,
DeclineReason = NULL
WHERE {self._PK} = ?
"""
self.db.execute(sql, (ScheduleStatus.ACCEPTED.value, accepted_at, schedule_id))
def mark_declined(
self,
@@ -211,15 +189,24 @@ class ScheduleRepository(BaseRepository[ScheduleModel]):
declined_at: Optional[Any] = None,
decline_reason: Optional[str] = None,
) -> None:
sql = f"""
UPDATE {self._TABLE}
SET Status = ?,
DeclinedAt = ?,
DeclineReason = ?
WHERE {self._PK} = ?
"""
ts = declined_at or "CURRENT_TIMESTAMP"
self.db.execute(sql, (ScheduleStatus.DECLINED.value, ts, decline_reason, schedule_id))
if declined_at is None:
sql = f"""
UPDATE {self._TABLE}
SET Status = ?,
DeclinedAt = datetime('now'),
DeclineReason = ?
WHERE {self._PK} = ?
"""
self.db.execute(sql, (ScheduleStatus.DECLINED.value, decline_reason, schedule_id))
else:
sql = f"""
UPDATE {self._TABLE}
SET Status = ?,
DeclinedAt = ?,
DeclineReason = ?
WHERE {self._PK} = ?
"""
self.db.execute(sql, (ScheduleStatus.DECLINED.value, declined_at, decline_reason, schedule_id))
# ------------------------------------------------------------------
# Sameday helper used by the scheduling service