fix(finance): scope workbook import row lock
This commit is contained in:
parent
d3d2bb4462
commit
e936bc869e
@ -486,6 +486,15 @@ def _ensure_import_allowed(period: PayrollPeriod):
|
||||
_error("PERIOD_INPUTS_LOCKED", "Сначала верните текущий расчёт на исправление.")
|
||||
|
||||
|
||||
def _period_import_lock_queryset():
|
||||
# current_run is nullable, so PostgreSQL must lock only the period table.
|
||||
# Locking every joined table raises an error for the outer join when a
|
||||
# period has no current run.
|
||||
return PayrollPeriod.objects.select_for_update(of=("self",)).select_related(
|
||||
"current_run"
|
||||
)
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def apply_workbook_import(
|
||||
period_id: int,
|
||||
@ -515,11 +524,7 @@ def apply_workbook_import(
|
||||
"WORKBOOK_CHANGED",
|
||||
"После предпросмотра выбран другой файл. Повторите проверку.",
|
||||
)
|
||||
period = (
|
||||
PayrollPeriod.objects.select_for_update()
|
||||
.select_related("current_run")
|
||||
.get(pk=period_id)
|
||||
)
|
||||
period = _period_import_lock_queryset().get(pk=period_id)
|
||||
_ensure_import_allowed(period)
|
||||
if period.lock_version != expected_period_lock_version:
|
||||
_error("STALE_PERIOD", "Период уже изменён; повторите предпросмотр.")
|
||||
|
||||
@ -10,7 +10,11 @@ from django.urls import reverse
|
||||
from openpyxl import Workbook
|
||||
|
||||
from finance.models import PayrollDailyWorkEntry, PayrollPeriod, PayrollWorkRecord
|
||||
from finance.payroll.workbook_import import _sanitize_styles, parse_workbook
|
||||
from finance.payroll.workbook_import import (
|
||||
_period_import_lock_queryset,
|
||||
_sanitize_styles,
|
||||
parse_workbook,
|
||||
)
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
@ -64,6 +68,13 @@ def make_period(creator):
|
||||
)
|
||||
|
||||
|
||||
def test_import_period_lock_targets_only_the_period_table():
|
||||
query = _period_import_lock_queryset().query
|
||||
|
||||
assert query.select_for_update is True
|
||||
assert query.select_for_update_of == ("self",)
|
||||
|
||||
|
||||
def test_invalid_legacy_colour_can_be_repaired_before_parsing():
|
||||
payload = workbook_bytes()
|
||||
source = zipfile.ZipFile(io.BytesIO(payload))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user