From 0bbe267498c324c89a027ab6aad1606e5ad98d45 Mon Sep 17 00:00:00 2001 From: kdeterme Date: Mon, 28 Sep 2026 14:17:44 +0200 Subject: [PATCH] feat(contracts): auto-sync team schedule daily and on mobile access - Register sync_teams_schedule in init_scheduled_tasks (daily at 04:00 local) - Trigger sync_member_current_teams on mobile intervention list load - Trigger sync_member_current_teams on user login signal --- .../commands/init_scheduled_tasks.py | 41 ++++++++++++++++++- loko/contracts/signals.py | 18 ++++++++ loko/interventions/views/mobile.py | 6 +++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/loko/common/management/commands/init_scheduled_tasks.py b/loko/common/management/commands/init_scheduled_tasks.py index 42c41df..eebc4d5 100644 --- a/loko/common/management/commands/init_scheduled_tasks.py +++ b/loko/common/management/commands/init_scheduled_tasks.py @@ -325,7 +325,46 @@ Chaque utilisateur configure son délai et ses préférences dans la page /notif if task7.next_run: self.stdout.write(f' - Prochaine exécution: {task7.next_run.strftime("%Y-%m-%d %H:%M")}') - self.stdout.write(self.style.SUCCESS('\n=== Initialisation terminée ===')) + # 8. Synchronisation quotidienne des équipes du planning + task_name_sync_teams = "Synchronisation quotidienne des équipes" + + task8, created8 = ScheduledCommand.objects.get_or_create( + name=task_name_sync_teams, + defaults={ + 'command_name': 'sync_teams_schedule', + 'command_args': {}, + 'frequency': 'daily', + 'hour': 2, + 'minute': 0, + 'is_active': True, + 'send_email': False, + 'description': ''' +Synchronise quotidiennement la composition des équipes (member.teams) avec l'historique planifié pour la journée (CompanyMemberHistory). + +La tâche s'exécute tous les jours à 2h00 UTC (4h00 locale). +Elle garantit que les techniciens et membres d'équipes disposent de leurs assignations d'équipes dès le début de leur journée de travail. + '''.strip() + } + ) + + if created8: + task8.next_run = task8.calculate_next_run() + task8.save() + + self.stdout.write(self.style.SUCCESS(f' +[OK] Tâche créée: {task_name_sync_teams}')) + self.stdout.write(f' - Fréquence: {task8.get_frequency_display()}') + self.stdout.write(f' - Planning: Tous les jours à {task8.hour:02d}:{task8.minute:02d} UTC') + self.stdout.write(f' - Prochaine exécution: {task8.next_run.strftime("%Y-%m-%d %H:%M")}') + else: + self.stdout.write(self.style.WARNING(f' +! Tâche déjà existante: {task_name_sync_teams}')) + self.stdout.write(f' - Statut: {"Active" if task8.is_active else "Inactive"}') + if task8.next_run: + self.stdout.write(f' - Prochaine exécution: {task8.next_run.strftime("%Y-%m-%d %H:%M")}') + + self.stdout.write(self.style.SUCCESS(' +=== Initialisation terminée ===')) self.stdout.write('\nPour gérer les tâches planifiées:') self.stdout.write(' 1. Accédez à l\'admin Django: /admin/') self.stdout.write(' 2. Section: Common > Commandes planifiées') diff --git a/loko/contracts/signals.py b/loko/contracts/signals.py index ffdfb78..d48a27b 100644 --- a/loko/contracts/signals.py +++ b/loko/contracts/signals.py @@ -120,3 +120,21 @@ def update_member_team_history(sender, instance, action, reverse, pk_set, **kwar ).update(leave_date=today) +from django.contrib.auth.signals import user_logged_in + + +@receiver(user_logged_in) +def sync_user_current_teams_on_login(sender, request, user, **kwargs): + """ + Synchronise les équipes du membre connecté avec l'historique planifié pour aujourd'hui. + """ + try: + from contracts.services_teams import sync_member_current_teams + member = CompanyMember.objects.filter(user=user).first() + if member: + sync_member_current_teams(member) + except Exception: + pass + + + diff --git a/loko/interventions/views/mobile.py b/loko/interventions/views/mobile.py index 1a364d0..a69fe35 100644 --- a/loko/interventions/views/mobile.py +++ b/loko/interventions/views/mobile.py @@ -167,6 +167,12 @@ def interventions_index_mobile(request): return HttpResponseRedirect(f"{request.path}?{query_params.urlencode()}") + # Synchroniser les équipes du jour du membre avec l'historique planifié + company_member_current = CompanyMember.objects.filter(user=request.user).first() + if company_member_current: + from contracts.services_teams import sync_member_current_teams + sync_member_current_teams(company_member_current) + # permissions interventions = filter_viewable_interventions_for_user(request.user, limit_to_default_thematic=True)