Merge branch 'test' into AURORA-1043
This commit is contained in:
commit
ef335cf107
@ -363,24 +363,29 @@ async def add_form(
|
|||||||
form: FormCreateSchema,
|
form: FormCreateSchema,
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
current_user: AppUser = Depends(require_admin),
|
current_user: AppUser = Depends(require_admin),
|
||||||
) -> BaseSingleResponse[BudgetFormResponse]:
|
) -> BaseListResponse[BudgetFormResponse]:
|
||||||
t0 = time.perf_counter()
|
t0 = time.perf_counter()
|
||||||
bf_service = BudgetFormService(db)
|
bf_service = BudgetFormService(db)
|
||||||
org_service = OrgUnitService(db)
|
org_service = OrgUnitService(db)
|
||||||
|
|
||||||
org_unit = await org_service.get(org_unit_id=form.org_unit_id, user=current_user)
|
org_units = await org_service.get_list(user=current_user, org_unit_id=form.org_unit_ids)
|
||||||
if not org_unit:
|
org_unit_ids = [o.id for o in org_units]
|
||||||
raise HTTPException(404, f"ССП {form.org_unit_id} не найден")
|
if len(org_units) != len(form.org_unit_ids):
|
||||||
|
not_found_ids = ", ".join(
|
||||||
|
[str(oid) for oid in set(form.org_unit_ids) - set(org_unit_ids)],
|
||||||
|
)
|
||||||
|
raise HTTPException(404, f"ССП {not_found_ids} не найдены")
|
||||||
|
|
||||||
new_form = await bf_service.create(
|
new_forms = await bf_service.bulk_create(
|
||||||
form_type_code=form.form_type_code,
|
form_type_code=form.form_type_code,
|
||||||
year=form.year,
|
year=form.year,
|
||||||
org_unit_id=org_unit.id,
|
org_unit_ids=org_unit_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
db_ms = (time.perf_counter() - t0) * 1000
|
db_ms = (time.perf_counter() - t0) * 1000
|
||||||
response.headers["X-DB-Time-Ms"] = f"{db_ms:.2f}"
|
response.headers["X-DB-Time-Ms"] = f"{db_ms:.2f}"
|
||||||
|
|
||||||
return BaseSingleResponse(
|
return BaseListResponse(
|
||||||
result = BudgetFormResponse.model_validate(new_form),
|
result=[BudgetFormResponse.model_validate(new_form) for new_form in new_forms],
|
||||||
|
count=len(new_forms),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -223,7 +223,7 @@ class FormTypeSchemaEnum(str, enum.Enum):
|
|||||||
class FormCreateSchema(BaseModel):
|
class FormCreateSchema(BaseModel):
|
||||||
year: int
|
year: int
|
||||||
form_type_code: FormTypeSchemaEnum
|
form_type_code: FormTypeSchemaEnum
|
||||||
org_unit_id: int
|
org_unit_ids: list[int] = Field(..., min_length=1)
|
||||||
|
|
||||||
|
|
||||||
class OrgUnitBaseSchema(BaseModel):
|
class OrgUnitBaseSchema(BaseModel):
|
||||||
|
|||||||
@ -20,6 +20,7 @@ class OrgUnitRepository:
|
|||||||
limit: int | None = None,
|
limit: int | None = None,
|
||||||
is_ssp: bool | None = None,
|
is_ssp: bool | None = None,
|
||||||
is_active: bool | None = None,
|
is_active: bool | None = None,
|
||||||
|
org_unit_id: int | list[int] | None = None,
|
||||||
with_count: bool = False,
|
with_count: bool = False,
|
||||||
load_users: bool = False,
|
load_users: bool = False,
|
||||||
) -> list[OrgUnit] | tuple[int, list[OrgUnit]]:
|
) -> list[OrgUnit] | tuple[int, list[OrgUnit]]:
|
||||||
@ -32,7 +33,11 @@ class OrgUnitRepository:
|
|||||||
where.append(OrgUnit.is_ssp == is_ssp)
|
where.append(OrgUnit.is_ssp == is_ssp)
|
||||||
if is_active is not None:
|
if is_active is not None:
|
||||||
where.append(OrgUnit.is_active == is_active)
|
where.append(OrgUnit.is_active == is_active)
|
||||||
|
if org_unit_id is not None:
|
||||||
|
if isinstance(org_unit_id, int):
|
||||||
|
where.append(OrgUnit.id == org_unit_id)
|
||||||
|
else:
|
||||||
|
where.append(OrgUnit.id.in_(org_unit_id))
|
||||||
|
|
||||||
query = query.where(*where)
|
query = query.where(*where)
|
||||||
if load_users:
|
if load_users:
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
import asyncio
|
||||||
|
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from src.repository.user_repository import UserRepository
|
from src.repository.user_repository import UserRepository
|
||||||
@ -76,4 +78,21 @@ class BudgetFormService:
|
|||||||
form_type_code=form_type_code,
|
form_type_code=form_type_code,
|
||||||
year=year,
|
year=year,
|
||||||
org_unit_id=org_unit_id,
|
org_unit_id=org_unit_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def bulk_create(
|
||||||
|
self,
|
||||||
|
form_type_code: str,
|
||||||
|
year: int,
|
||||||
|
org_unit_ids: list[int],
|
||||||
|
) -> BudgetForm | None:
|
||||||
|
return await asyncio.gather(
|
||||||
|
*[
|
||||||
|
self.create(
|
||||||
|
form_type_code=form_type_code,
|
||||||
|
year=year,
|
||||||
|
org_unit_id=org_unit_id,
|
||||||
|
)
|
||||||
|
for org_unit_id in org_unit_ids
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|||||||
@ -20,6 +20,7 @@ class OrgUnitService:
|
|||||||
limit: int | None = None,
|
limit: int | None = None,
|
||||||
is_ssp: bool | None = None,
|
is_ssp: bool | None = None,
|
||||||
is_active: bool | None = None,
|
is_active: bool | None = None,
|
||||||
|
org_unit_id: int | list[int] | None = None,
|
||||||
with_count: bool = False,
|
with_count: bool = False,
|
||||||
load_users: bool = False,
|
load_users: bool = False,
|
||||||
) -> list[OrgUnit] | tuple[int, list[OrgUnit]]:
|
) -> list[OrgUnit] | tuple[int, list[OrgUnit]]:
|
||||||
@ -33,6 +34,7 @@ class OrgUnitService:
|
|||||||
is_ssp=is_ssp,
|
is_ssp=is_ssp,
|
||||||
is_active=is_active,
|
is_active=is_active,
|
||||||
load_users=load_users,
|
load_users=load_users,
|
||||||
|
org_unit_id=org_unit_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def get(
|
async def get(
|
||||||
|
|||||||
@ -140,17 +140,20 @@ def test_forms_delete_line_not_found_error_shape(client, admin_tokens, auth_head
|
|||||||
def test_forms_add_form_success(client, admin_tokens, auth_headers):
|
def test_forms_add_form_success(client, admin_tokens, auth_headers):
|
||||||
response = client.post(
|
response = client.post(
|
||||||
"/api/v1/form/",
|
"/api/v1/form/",
|
||||||
json={"year": 2025, "form_type_code": "FORM_1", "org_unit_id": 1},
|
json={"year": 2025, "form_type_code": "FORM_1", "org_unit_ids": [1]},
|
||||||
headers=auth_headers(admin_tokens),
|
headers=auth_headers(admin_tokens),
|
||||||
)
|
)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
payload = response.json()
|
payload = response.json()
|
||||||
assert "result" in payload
|
|
||||||
assert isinstance(payload["result"], dict)
|
|
||||||
assert payload["result"]["year"] == 2025
|
|
||||||
|
|
||||||
assert "id" in payload["result"]
|
assert "result" in payload
|
||||||
form_id = payload["result"]["id"]
|
assert isinstance(payload["result"], list)
|
||||||
|
assert len(payload["result"]) == 1
|
||||||
|
assert "year" in payload["result"][0]
|
||||||
|
assert payload["result"][0]["year"] == 2025
|
||||||
|
|
||||||
|
assert "id" in payload["result"][0]
|
||||||
|
form_id = payload["result"][0]["id"]
|
||||||
response = client.get(
|
response = client.get(
|
||||||
f"/api/v1/form/{form_id}",
|
f"/api/v1/form/{form_id}",
|
||||||
headers=auth_headers(admin_tokens),
|
headers=auth_headers(admin_tokens),
|
||||||
@ -161,7 +164,7 @@ def test_forms_add_form_success(client, admin_tokens, auth_headers):
|
|||||||
def test_forms_add_form_org_unit_not_found(client, admin_tokens, auth_headers):
|
def test_forms_add_form_org_unit_not_found(client, admin_tokens, auth_headers):
|
||||||
response = client.post(
|
response = client.post(
|
||||||
"/api/v1/form/",
|
"/api/v1/form/",
|
||||||
json={"year": 2025, "form_type_code": "FORM_1", "org_unit_id": 999},
|
json={"year": 2025, "form_type_code": "FORM_1", "org_unit_ids": [1, 999]},
|
||||||
headers=auth_headers(admin_tokens),
|
headers=auth_headers(admin_tokens),
|
||||||
)
|
)
|
||||||
assert response.status_code == 404
|
assert response.status_code == 404
|
||||||
@ -173,7 +176,7 @@ def test_forms_add_form_org_unit_not_found(client, admin_tokens, auth_headers):
|
|||||||
def test_forms_add_form_forbidden_not_admin(client, isp_tokens, auth_headers):
|
def test_forms_add_form_forbidden_not_admin(client, isp_tokens, auth_headers):
|
||||||
response = client.post(
|
response = client.post(
|
||||||
"/api/v1/form/",
|
"/api/v1/form/",
|
||||||
json={"year": 2025, "form_type_code": "FORM_1", "org_unit_id": 1},
|
json={"year": 2025, "form_type_code": "FORM_1", "org_unit_ids": [1]},
|
||||||
headers=auth_headers(isp_tokens),
|
headers=auth_headers(isp_tokens),
|
||||||
)
|
)
|
||||||
assert response.status_code == 403
|
assert response.status_code == 403
|
||||||
|
|||||||
@ -14,6 +14,7 @@ def _build_form(
|
|||||||
form_type_code: FormTypeEnum = FormTypeEnum.FORM_1,
|
form_type_code: FormTypeEnum = FormTypeEnum.FORM_1,
|
||||||
sheet_list: list[str] | None = None,
|
sheet_list: list[str] | None = None,
|
||||||
section_list: list[str] | None = None,
|
section_list: list[str] | None = None,
|
||||||
|
sheet_list_with_directions: list[dict] | None = None,
|
||||||
) -> SimpleNamespace:
|
) -> SimpleNamespace:
|
||||||
return SimpleNamespace(
|
return SimpleNamespace(
|
||||||
id=1,
|
id=1,
|
||||||
@ -25,6 +26,22 @@ def _build_form(
|
|||||||
code=form_type_code,
|
code=form_type_code,
|
||||||
sheet_list=sheet_list or ["AHR", "SMETA"],
|
sheet_list=sheet_list or ["AHR", "SMETA"],
|
||||||
section_list=section_list or ["plan", "q1"],
|
section_list=section_list or ["plan", "q1"],
|
||||||
|
sheet_list_with_directions=sheet_list_with_directions or [
|
||||||
|
{
|
||||||
|
"sheet_name": "AHR",
|
||||||
|
"direction": "Support",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sheet_name": "AHR",
|
||||||
|
"direction": "Development",
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sheet_name": "SMETA",
|
||||||
|
"direction": None,
|
||||||
|
|
||||||
|
},
|
||||||
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,7 +67,15 @@ async def test_export_sheet_rejects_direction_for_unsupported_sheet():
|
|||||||
async def test_export_sheet_rejects_sections_for_unsupported_sheet():
|
async def test_export_sheet_rejects_sections_for_unsupported_sheet():
|
||||||
service = ExportService(AsyncMock())
|
service = ExportService(AsyncMock())
|
||||||
service.budget_form_service.get = AsyncMock(
|
service.budget_form_service.get = AsyncMock(
|
||||||
return_value=_build_form(sheet_list=["SMETA"])
|
return_value=_build_form(
|
||||||
|
sheet_list=["SMETA"],
|
||||||
|
sheet_list_with_directions=[
|
||||||
|
{
|
||||||
|
"sheet_name": "SMETA",
|
||||||
|
"direction": None,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
)
|
||||||
)
|
)
|
||||||
service.sheet_service.get = AsyncMock(return_value=[])
|
service.sheet_service.get = AsyncMock(return_value=[])
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user