fix(planning): scope Pronote removals to imported week
This commit is contained in:
parent
8248ca0df3
commit
90de40e227
3 changed files with 33 additions and 3 deletions
|
|
@ -79,7 +79,7 @@ def available_slots(room_id, day, window_start=time(8), window_end=time(17), dur
|
|||
return slots
|
||||
|
||||
|
||||
def sync_pronote_schedules(room_id, entries, *, synced_at=None):
|
||||
def sync_pronote_schedules(room_id, entries, *, synced_at=None, week_start=None):
|
||||
"""Applique un lot Pronote sans toucher aux créneaux manuels protégés.
|
||||
|
||||
``entries`` est une liste de dictionnaires normalisés par l'intégration
|
||||
|
|
@ -87,6 +87,9 @@ def sync_pronote_schedules(room_id, entries, *, synced_at=None):
|
|||
libellés optionnels). Cette fonction ne contacte jamais Pronote elle-même.
|
||||
"""
|
||||
synced_at = synced_at or datetime.utcnow()
|
||||
synced_weeks = {entry.get("week_start") for entry in entries if entry.get("week_start")}
|
||||
if week_start:
|
||||
synced_weeks.add(week_start)
|
||||
seen = set()
|
||||
for entry in entries:
|
||||
external_id = str(entry.get("external_id") or "").strip()
|
||||
|
|
@ -140,7 +143,10 @@ def sync_pronote_schedules(room_id, entries, *, synced_at=None):
|
|||
note = "Conflit avec un créneau manuel protégé"
|
||||
manual.conflict_note = note
|
||||
row.conflict_note = note
|
||||
existing = RoomSchedule.query.filter_by(room_id=room_id, source="pronote").all()
|
||||
existing_query = RoomSchedule.query.filter_by(room_id=room_id, source="pronote")
|
||||
if synced_weeks:
|
||||
existing_query = existing_query.filter(RoomSchedule.week_start.in_(synced_weeks))
|
||||
existing = existing_query.all()
|
||||
for row in existing:
|
||||
if row.external_id not in seen:
|
||||
row.resolution_status = "disabled"
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ def import_room_planning(room_id):
|
|||
try:
|
||||
lessons = get_lessons_for_room(client, room.name, monday, monday + timedelta(days=6), strict=True)
|
||||
entries = normalize_pronote_lessons(lessons, monday)
|
||||
sync_pronote_schedules(room.id, entries)
|
||||
sync_pronote_schedules(room.id, entries, week_start=monday)
|
||||
flash(f'{len(entries)} créneaux Pronote synchronisés. Les protections locales ont été conservées.', 'success')
|
||||
except Exception:
|
||||
db.session.rollback()
|
||||
|
|
|
|||
|
|
@ -172,6 +172,30 @@ def test_pronote_sync_change_removal_ambiguity_and_freshness(app):
|
|||
assert db.session.get(RoomSchedule, row.id) is not None
|
||||
|
||||
|
||||
def test_pronote_sync_removal_is_scoped_to_imported_week(app):
|
||||
with app.app_context():
|
||||
building = Building(name="Phase15 scope building")
|
||||
db.session.add(building)
|
||||
db.session.flush()
|
||||
room = Room(name="Phase15 scope room", building_id=building.id)
|
||||
db.session.add(room)
|
||||
db.session.flush()
|
||||
current_week, next_week = date(2026, 9, 7), date(2026, 9, 14)
|
||||
current = RoomSchedule(room_id=room.id, week_start=current_week, day_of_week=0,
|
||||
start_time=time(8), end_time=time(9), source="pronote",
|
||||
external_id="scope-current")
|
||||
future = RoomSchedule(room_id=room.id, week_start=next_week, day_of_week=0,
|
||||
start_time=time(8), end_time=time(9), source="pronote",
|
||||
external_id="scope-future")
|
||||
db.session.add_all([current, future])
|
||||
db.session.commit()
|
||||
sync_pronote_schedules(room.id, [], week_start=current_week)
|
||||
db.session.refresh(current)
|
||||
db.session.refresh(future)
|
||||
assert current.resolution_status == "disabled"
|
||||
assert future.resolution_status == "active"
|
||||
|
||||
|
||||
def test_normalize_pronote_lessons_is_stable_and_skips_invalid_entries():
|
||||
week = date(2026, 9, 7)
|
||||
lessons = [{
|
||||
|
|
|
|||
Loading…
Reference in a new issue