fix(finance): calculate personnel points through yesterday
This commit is contained in:
parent
bc965c412e
commit
54171f9dad
@ -3,6 +3,8 @@ from __future__ import annotations
|
||||
from datetime import date, timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
from attendance.services import (
|
||||
get_employee_work_schedule_payload,
|
||||
get_standard_work_schedule,
|
||||
@ -102,18 +104,20 @@ def calculate_period_personnel_points(
|
||||
) -> tuple[Decimal, int]:
|
||||
"""Project points from the work calendar and official personnel events.
|
||||
|
||||
A scheduled day is treated as attended unless the personnel state explicitly
|
||||
says that attendance is not expected (leave, sick leave, day off, maternity
|
||||
leave or dismissal). The result is a read-only projection and is not stored
|
||||
in payroll models.
|
||||
Only completed scheduled days before today participate in the projection.
|
||||
Such a day is treated as attended unless the personnel state explicitly says
|
||||
that attendance is not expected (leave, sick leave, day off, maternity leave
|
||||
or dismissal). The result is read-only and is not stored in payroll models.
|
||||
"""
|
||||
|
||||
if schedule is None:
|
||||
schedule, _ = resolve_employee_schedule(employee)
|
||||
workdates = period_workdates(period, schedule)
|
||||
today = timezone.localdate()
|
||||
completed_workdates = [workdate for workdate in workdates if workdate < today]
|
||||
attended_dates = [
|
||||
workdate
|
||||
for workdate in workdates
|
||||
for workdate in completed_workdates
|
||||
if resolve_employee_personnel_state(
|
||||
employee,
|
||||
workdate,
|
||||
|
||||
@ -274,6 +274,7 @@ def test_period_table_lists_all_employees_and_requires_view_all(
|
||||
def test_period_table_projects_attendance_and_official_personnel_points(
|
||||
user_factory,
|
||||
auth_client_factory,
|
||||
monkeypatch,
|
||||
):
|
||||
manager = user_factory(email="table.projections.manager@example.test")
|
||||
employee = user_factory(
|
||||
@ -335,6 +336,10 @@ def test_period_table_projects_attendance_and_official_personnel_points(
|
||||
|
||||
action = EmployeeAction.objects.get(source_request=vacation)
|
||||
assert action.date.date() == date(2026, 6, 3)
|
||||
monkeypatch.setattr(
|
||||
"finance.payroll.work_norm.timezone.localdate",
|
||||
lambda: date(2026, 6, 4),
|
||||
)
|
||||
|
||||
response = auth_client_factory(manager).get(
|
||||
api_url("admin-period-table", pk=period.pk),
|
||||
@ -348,7 +353,7 @@ def test_period_table_projects_attendance_and_official_personnel_points(
|
||||
)
|
||||
assert row["target_points"] == "220.0000"
|
||||
assert row["attendance_points"] == "15.0000"
|
||||
assert row["personnel_points"] == "210.0000"
|
||||
assert row["personnel_points"] == "20.0000"
|
||||
|
||||
|
||||
def test_component_cell_can_be_cleared_and_voids_all_active_lines(
|
||||
|
||||
@ -293,8 +293,8 @@ function calculationHelps(pointPolicy: PayrollPeriodTable["calculation_rules"]["
|
||||
},
|
||||
personnelPoints: {
|
||||
title: "Баллы по кадровым событиям",
|
||||
logic: "Вычисляются на ходу от нормы баллов сотрудника, рабочего графика и официальных кадровых событий. Каждый плановый рабочий день считается отработанным полностью, пока одобренное заявление или кадровое событие не подтверждает отсутствие. Отпуск, больничный, отгул, декрет и увольнение дают 0 баллов за затронутые рабочие дни; удалённая работа считается присутствием.",
|
||||
formula: "Баллы по кадровым событиям = Норма баллов × Рабочие дни без подтверждённого отсутствия ÷ Плановые рабочие дни",
|
||||
logic: "Это накопительный показатель на начало текущего дня. Он вычисляется на ходу от нормы баллов сотрудника, рабочего графика и официальных кадровых событий. Текущий и будущие дни не учитываются. Каждый завершённый плановый рабочий день считается отработанным полностью, пока одобренное заявление или кадровое событие не подтверждает отсутствие. Отпуск, больничный, отгул, декрет и увольнение дают 0 баллов; удалённая работа считается присутствием.",
|
||||
formula: "Баллы по кадровым событиям = Норма баллов × Завершённые рабочие дни без подтверждённого отсутствия ÷ Все плановые рабочие дни периода",
|
||||
manual: "Нет. Значение меняется через норму баллов, заявление, кадровое событие или рабочий график.",
|
||||
},
|
||||
pointDelta: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user