feat: add Django admin configuration, team services, and test planning for contracts
This commit is contained in:
parent
f19eae6067
commit
096886a194
3 changed files with 44 additions and 2 deletions
|
|
@ -427,14 +427,14 @@ class CompanyMemberHistoryAdmin(admin.ModelAdmin):
|
||||||
list_display = ('member', 'team', 'join_date', 'leave_date', 'changed_by')
|
list_display = ('member', 'team', 'join_date', 'leave_date', 'changed_by')
|
||||||
list_filter = ('team__company', 'team')
|
list_filter = ('team__company', 'team')
|
||||||
search_fields = ('member__name', 'team__name')
|
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'
|
date_hierarchy = 'join_date'
|
||||||
|
|
||||||
def has_add_permission(self, request):
|
def has_add_permission(self, request):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def has_delete_permission(self, request, obj=None):
|
def has_delete_permission(self, request, obj=None):
|
||||||
return False
|
return True
|
||||||
|
|
||||||
|
|
||||||
@admin.register(CompanyMemberAbsence)
|
@admin.register(CompanyMemberAbsence)
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,8 @@ def set_member_team_schedule(
|
||||||
).filter(
|
).filter(
|
||||||
Q(leave_date__isnull=True) | Q(leave_date__gte=target_date)
|
Q(leave_date__isnull=True) | Q(leave_date__gte=target_date)
|
||||||
).update(leave_date=prev_leave)
|
).update(leave_date=prev_leave)
|
||||||
|
if target_date <= today:
|
||||||
|
member.teams.remove(unassign_team_id)
|
||||||
else:
|
else:
|
||||||
# Désassignation globale de toutes les équipes
|
# Désassignation globale de toutes les équipes
|
||||||
if target_date > today:
|
if target_date > today:
|
||||||
|
|
@ -117,6 +119,8 @@ def set_member_team_schedule(
|
||||||
).filter(
|
).filter(
|
||||||
Q(leave_date__isnull=True) | Q(leave_date__gte=target_date)
|
Q(leave_date__isnull=True) | Q(leave_date__gte=target_date)
|
||||||
).update(leave_date=prev_leave)
|
).update(leave_date=prev_leave)
|
||||||
|
if target_date <= today:
|
||||||
|
member.teams.clear()
|
||||||
|
|
||||||
_sync_teams_if_needed(member, target_date, today, sync_current)
|
_sync_teams_if_needed(member, target_date, today, sync_current)
|
||||||
return None
|
return None
|
||||||
|
|
|
||||||
|
|
@ -654,5 +654,43 @@ class TeamPlanningAjaxViewsTests(TestCase):
|
||||||
self.assertGreaterEqual(data['assigned_count'], 1)
|
self.assertGreaterEqual(data['assigned_count'], 1)
|
||||||
self.assertEqual(get_member_team_for_date(self.member_alice, date(2026, 11, 1)), self.team_b)
|
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), [])])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue