feat(backend): create improved tests
This commit is contained in:
@@ -48,12 +48,17 @@ class ScheduleRepository(BaseRepository[ScheduleModel]):
|
||||
scheduled_at, expires_at : datetime‑compatible | None
|
||||
``scheduled_at`` defaults to SQLite’s ``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:
|
||||
"""
|
||||
Cool‑down 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
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Status‑transition 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))
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Same‑day helper – used by the scheduling service
|
||||
|
||||
Reference in New Issue
Block a user