feat: exclude fixed-salary managers from absence pickers
This commit is contained in:
parent
0f45d64eea
commit
5fa3efcf64
@ -660,7 +660,7 @@ class AbsenceLogForm(forms.ModelForm):
|
|||||||
help_text='Optional — narrows the worker list below.',
|
help_text='Optional — narrows the worker list below.',
|
||||||
)
|
)
|
||||||
workers = forms.ModelMultipleChoiceField(
|
workers = forms.ModelMultipleChoiceField(
|
||||||
queryset=Worker.objects.filter(active=True),
|
queryset=Worker.objects.filter(active=True).exclude(pay_type='fixed'),
|
||||||
widget=forms.CheckboxSelectMultiple,
|
widget=forms.CheckboxSelectMultiple,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -699,7 +699,7 @@ class AbsenceLogForm(forms.ModelForm):
|
|||||||
active=True,
|
active=True,
|
||||||
teams__supervisor=user,
|
teams__supervisor=user,
|
||||||
teams__active=True,
|
teams__active=True,
|
||||||
).distinct()
|
).exclude(pay_type='fixed').distinct()
|
||||||
)
|
)
|
||||||
# Project dropdown — only projects this supervisor is assigned to.
|
# Project dropdown — only projects this supervisor is assigned to.
|
||||||
# Mirrors the AttendanceLogForm supervisor scoping pattern.
|
# Mirrors the AttendanceLogForm supervisor scoping pattern.
|
||||||
@ -840,7 +840,7 @@ class AbsenceEditForm(forms.ModelForm):
|
|||||||
def __init__(self, *args, user=None, **kwargs):
|
def __init__(self, *args, user=None, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
# Default: every active worker. Admins (staff/superuser) keep this list.
|
# Default: every active worker. Admins (staff/superuser) keep this list.
|
||||||
self.fields['worker'].queryset = Worker.objects.filter(active=True)
|
self.fields['worker'].queryset = Worker.objects.filter(active=True).exclude(pay_type='fixed')
|
||||||
# Project is optional — leave blank for non-project absences.
|
# Project is optional — leave blank for non-project absences.
|
||||||
self.fields['project'].required = False
|
self.fields['project'].required = False
|
||||||
# Supervisor scope: when a non-admin opens the edit form, the worker
|
# Supervisor scope: when a non-admin opens the edit form, the worker
|
||||||
@ -853,7 +853,7 @@ class AbsenceEditForm(forms.ModelForm):
|
|||||||
active=True,
|
active=True,
|
||||||
teams__supervisor=user,
|
teams__supervisor=user,
|
||||||
teams__active=True,
|
teams__active=True,
|
||||||
).distinct()
|
).exclude(pay_type='fixed').distinct()
|
||||||
self.fields['project'].queryset = Project.objects.filter(
|
self.fields['project'].queryset = Project.objects.filter(
|
||||||
active=True, supervisors=user,
|
active=True, supervisors=user,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -3500,3 +3500,46 @@ class ManagerSalariedAttendanceExclusionTests(TestCase):
|
|||||||
ids = tw_map.get(str(self.team.id)) or tw_map.get(self.team.id) or []
|
ids = tw_map.get(str(self.team.id)) or tw_map.get(self.team.id) or []
|
||||||
self.assertIn(self.daily.id, ids)
|
self.assertIn(self.daily.id, ids)
|
||||||
self.assertNotIn(self.mgr.id, ids)
|
self.assertNotIn(self.mgr.id, ids)
|
||||||
|
|
||||||
|
|
||||||
|
# === MANAGER / SALARIED ABSENCE-PICKER EXCLUSION TESTS (Task 4) ===
|
||||||
|
# A pay_type='fixed' manager must be impossible to mark absent — the
|
||||||
|
# AbsenceLogForm worker picker (admin default + supervisor branch) and
|
||||||
|
# the AbsenceEditForm worker picker (admin + supervisor branch) must
|
||||||
|
# exclude fixed-salary workers. (Managers stay selectable in payroll
|
||||||
|
# modals / team-edit — those are NOT touched by this task.)
|
||||||
|
|
||||||
|
class ManagerSalariedAbsenceExclusionTests(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.admin = User.objects.create_user('msab_admin', password='x', is_staff=True)
|
||||||
|
self.sup = User.objects.create_user('msab_sup', password='x')
|
||||||
|
self.daily = Worker.objects.create(
|
||||||
|
name='Abs Daily', id_number='MSAB-D', monthly_salary=Decimal('6000'))
|
||||||
|
self.mgr = Worker.objects.create(
|
||||||
|
name='Abs Mgr', id_number='MSAB-M', monthly_salary=Decimal('40000'),
|
||||||
|
pay_type='fixed')
|
||||||
|
self.team = Team.objects.create(name='MSAB Team', supervisor=self.sup, active=True)
|
||||||
|
self.team.workers.add(self.daily, self.mgr)
|
||||||
|
|
||||||
|
def test_absencelog_admin_excludes_fixed(self):
|
||||||
|
from core.forms import AbsenceLogForm
|
||||||
|
qs = AbsenceLogForm(user=self.admin).fields['workers'].queryset
|
||||||
|
self.assertIn(self.daily, qs)
|
||||||
|
self.assertNotIn(self.mgr, qs)
|
||||||
|
|
||||||
|
def test_absencelog_supervisor_excludes_fixed(self):
|
||||||
|
from core.forms import AbsenceLogForm
|
||||||
|
qs = AbsenceLogForm(user=self.sup).fields['workers'].queryset
|
||||||
|
self.assertIn(self.daily, qs)
|
||||||
|
self.assertNotIn(self.mgr, qs)
|
||||||
|
|
||||||
|
def test_absenceedit_admin_excludes_fixed(self):
|
||||||
|
from core.forms import AbsenceEditForm
|
||||||
|
qs = AbsenceEditForm(user=self.admin).fields['worker'].queryset
|
||||||
|
self.assertIn(self.daily, qs)
|
||||||
|
self.assertNotIn(self.mgr, qs)
|
||||||
|
|
||||||
|
def test_absenceedit_supervisor_excludes_fixed(self):
|
||||||
|
from core.forms import AbsenceEditForm
|
||||||
|
qs = AbsenceEditForm(user=self.sup).fields['worker'].queryset
|
||||||
|
self.assertNotIn(self.mgr, qs)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user