fix: treat remote work as employment activation
This commit is contained in:
parent
5c896ad589
commit
d36996b4e3
@ -19,6 +19,7 @@ from employees.constants import (
|
||||
ACTION_ON_SICK_LEAVE,
|
||||
ACTION_REHIRED,
|
||||
ACTION_REMOTE,
|
||||
ACTION_WORKING,
|
||||
)
|
||||
from employees.models import Employee, EmployeeAction, EmployeeSkillProgress, Skill
|
||||
from employees.services.skill_progress import SKILL_RANKS, rarity_payload
|
||||
@ -466,27 +467,33 @@ def _employment_period(
|
||||
actions: list[EmployeeAction],
|
||||
reference_date: date,
|
||||
) -> tuple[date, date] | None:
|
||||
activation_dates = [
|
||||
action_date
|
||||
for action in actions
|
||||
if action.action in {ACTION_HIRED, ACTION_REHIRED}
|
||||
and (action_date := _action_date(action)) is not None
|
||||
and action_date <= reference_date
|
||||
]
|
||||
created_date = timezone.localtime(employee.created_at).date()
|
||||
start_date = max(activation_dates) if activation_dates else created_date
|
||||
if start_date > reference_date:
|
||||
return None
|
||||
segment_start = created_date
|
||||
segment_end: date | None = None
|
||||
is_employed = True
|
||||
for action in actions:
|
||||
action_date = _action_date(action)
|
||||
if action_date is None or action_date > reference_date:
|
||||
continue
|
||||
if action.action in {ACTION_HIRED, ACTION_REHIRED}:
|
||||
segment_start = action_date
|
||||
segment_end = None
|
||||
is_employed = True
|
||||
elif action.action in {ACTION_REMOTE, ACTION_WORKING}:
|
||||
if not is_employed:
|
||||
segment_start = action_date
|
||||
segment_end = None
|
||||
is_employed = True
|
||||
elif action.action == ACTION_DISMISSED and is_employed:
|
||||
segment_end = action_date
|
||||
is_employed = False
|
||||
|
||||
dismissal_dates = [
|
||||
action_date
|
||||
for action in actions
|
||||
if action.action == ACTION_DISMISSED
|
||||
and (action_date := _action_date(action)) is not None
|
||||
and start_date <= action_date <= reference_date
|
||||
]
|
||||
end_date = min(dismissal_dates) if dismissal_dates else reference_date
|
||||
return start_date, end_date
|
||||
if segment_start > reference_date:
|
||||
return None
|
||||
return (
|
||||
segment_start,
|
||||
reference_date if is_employed else segment_end or reference_date,
|
||||
)
|
||||
|
||||
|
||||
def _action_period(
|
||||
|
||||
@ -6,6 +6,7 @@ from django.utils import timezone
|
||||
|
||||
from attendance.models import AttendanceAnalysisRun, AttendanceRecord
|
||||
from employees.constants import (
|
||||
ACTION_DISMISSED,
|
||||
ACTION_HIRED,
|
||||
ACTION_ON_DAY_OFF,
|
||||
ACTION_ON_SICK_LEAVE,
|
||||
@ -327,6 +328,40 @@ def test_reliability_uses_only_personnel_events_and_recovers_rank(user_factory):
|
||||
assert progress.progress_data["penalty_levels"] == 0
|
||||
|
||||
|
||||
def test_remote_reactivates_employment_without_resetting_active_period(user_factory):
|
||||
employee = user_factory()
|
||||
start = date(2025, 1, 1)
|
||||
_action(employee, ACTION_HIRED, start)
|
||||
_action(employee, ACTION_REMOTE, start + timedelta(days=30))
|
||||
|
||||
with patch(
|
||||
"employees.services.secret_skills.timezone.localdate",
|
||||
return_value=start + timedelta(days=59),
|
||||
):
|
||||
recalculate_attendance_secret_skills(employee.id)
|
||||
|
||||
skill = Skill.objects.get(system_code="attendance_reliability")
|
||||
progress = EmployeeSkillProgress.objects.get(employee=employee, skill=skill)
|
||||
assert progress.special_rank == "bronze"
|
||||
assert progress.progress_data["worked_days"] == 60
|
||||
|
||||
_action(employee, ACTION_DISMISSED, start + timedelta(days=60))
|
||||
_action(employee, ACTION_REMOTE, start + timedelta(days=70))
|
||||
with patch(
|
||||
"employees.services.secret_skills.timezone.localdate",
|
||||
return_value=start + timedelta(days=129),
|
||||
):
|
||||
recalculate_attendance_secret_skills(employee.id)
|
||||
|
||||
progress.refresh_from_db()
|
||||
assert progress.special_rank == "bronze"
|
||||
assert progress.progress_data["worked_days"] == 60
|
||||
assert (
|
||||
progress.progress_data["last_evaluated_date"]
|
||||
== (start + timedelta(days=129)).isoformat()
|
||||
)
|
||||
|
||||
|
||||
def test_resilience_counts_sick_episodes_and_recovers_rank(user_factory):
|
||||
employee = user_factory()
|
||||
start = date(2024, 1, 1)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user