feat: add Django admin configuration, team services, and test planning for contracts

This commit is contained in:
Karl Determe 2026-09-24 11:33:53 +02:00
parent f19eae6067
commit 096886a194
3 changed files with 44 additions and 2 deletions

View file

@ -427,14 +427,14 @@ class CompanyMemberHistoryAdmin(admin.ModelAdmin):
list_display = ('member', 'team', 'join_date', 'leave_date', 'changed_by')
list_filter = ('team__company', 'team')
search_fields = ('member__name', 'team__name')
readonly_fields = ('member', 'team', 'join_date', 'leave_date', 'changed_by')
readonly_fields = ('member', 'team', 'join_date', 'changed_by')
date_hierarchy = 'join_date'
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
return True
@admin.register(CompanyMemberAbsence)

View file

@ -98,6 +98,8 @@ def set_member_team_schedule(
).filter(
Q(leave_date__isnull=True) | Q(leave_date__gte=target_date)
).update(leave_date=prev_leave)
if target_date <= today:
member.teams.remove(unassign_team_id)
else:
# Désassignation globale de toutes les équipes
if target_date > today:
@ -117,6 +119,8 @@ def set_member_team_schedule(
).filter(
Q(leave_date__isnull=True) | Q(leave_date__gte=target_date)
).update(leave_date=prev_leave)
if target_date <= today:
member.teams.clear()
_sync_teams_if_needed(member, target_date, today, sync_current)
return None

View file

@ -654,5 +654,43 @@ class TeamPlanningAjaxViewsTests(TestCase):
self.assertGreaterEqual(data['assigned_count'], 1)
self.assertEqual(get_member_team_for_date(self.member_alice, date(2026, 11, 1)), self.team_b)
def test_planning_unassign_member_for_today_removes_from_team_and_planning(self):
"""
Tester que la désassignation d'un membre pour aujourd'hui :
1. Le retire bien de member.teams.
2. Le retire bien de la composition d'équipe pour aujourd'hui (sans résurrection zombie).
"""
today = timezone.now().date()
member_test = CompanyMember.objects.create(name="Technicien Test", user=self.user)
member_test.teams.add(self.team_a)
# Vérifier qu'il est bien dans l'équipe A
self.assertIn(self.team_a, member_test.teams.all())
comp_before = get_teams_composition_for_period({self.team_a.id}, today, today)
self.assertIn(member_test.id, [m['id'] for m in comp_before.get((self.team_a.id, today), [])])
# Désassigner pour aujourd'hui via l'API AJAX
url = reverse('contracts:team_planning_assign_member_ajax')
payload = {
'member_id': member_test.id,
'team_id': None,
'date': today.isoformat(),
'unassign_team_id': self.team_a.id,
'scope': 'day',
}
response = self.client.post(url, data=json.dumps(payload), content_type='application/json')
self.assertEqual(response.status_code, 200)
self.assertTrue(response.json()['success'])
member_test.refresh_from_db()
# Le membre ne doit plus être dans l'équipe A aujourd'hui
self.assertNotIn(self.team_a, member_test.teams.all())
self.assertEqual(member_test.teams.count(), 0)
# Vérifier qu'il n'apparaît plus dans la composition d'aujourd'hui
comp_after = get_teams_composition_for_period({self.team_a.id}, today, today)
self.assertNotIn(member_test.id, [m['id'] for m in comp_after.get((self.team_a.id, today), [])])