diff --git a/backend/finance/payroll/scheduled_changes.py b/backend/finance/payroll/scheduled_changes.py index 121a0101..b753682e 100644 --- a/backend/finance/payroll/scheduled_changes.py +++ b/backend/finance/payroll/scheduled_changes.py @@ -52,7 +52,7 @@ def materialize_scheduled_changes( component.code: component for component in get_payroll_components(target_period) } source_lines = list( - PayrollInputLine.objects.select_for_update() + PayrollInputLine.objects.select_for_update(of=("self",)) .select_related("created_by", "approved_by") .filter( period=source_period, diff --git a/backend/tests/finance/test_payroll_scheduled_changes.py b/backend/tests/finance/test_payroll_scheduled_changes.py index 0dc625b2..ff1adc77 100644 --- a/backend/tests/finance/test_payroll_scheduled_changes.py +++ b/backend/tests/finance/test_payroll_scheduled_changes.py @@ -237,6 +237,40 @@ def test_marker_waits_until_the_next_period_is_created(scheduled_workspace): assert len(row["applied_scheduled_changes"]) == 1 +def test_materialization_locks_only_payroll_input_lines( + scheduled_workspace, + monkeypatch, +): + from django.db.models import QuerySet + + lock_targets = [] + original_select_for_update = QuerySet.select_for_update + + def track_select_for_update(queryset, *args, **kwargs): + if queryset.model is PayrollInputLine: + lock_targets.append(kwargs.get("of")) + return original_select_for_update(queryset, *args, **kwargs) + + monkeypatch.setattr(QuerySet, "select_for_update", track_select_for_update) + + workspace = scheduled_workspace + component = create_scheduled_component( + workspace["client"], + name="Маркер с безопасной блокировкой", + source_period=workspace["periods"][7], + ) + response = set_cell( + workspace["client"], + period=workspace["periods"][7], + employee=workspace["employee"], + component_code=component["code"], + amount="500.00", + ) + + assert response.status_code == 201, response.content + assert ("self",) in lock_targets + + def test_closed_next_period_rejects_marker_value(scheduled_workspace): workspace = scheduled_workspace target = workspace["periods"][8]