Merge pull request 'create-form: создание задачи' (#39) from create-form-back into test
Reviewed-on: #39 Reviewed-by: Raykov-MS <RaykovMS@avt.rshb.ru>
This commit is contained in:
commit
4308e11bc9
@ -5,13 +5,14 @@ from fastapi import APIRouter, Depends, HTTPException, Response
|
|||||||
|
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
|
from src.services.org_unit_service import OrgUnitService
|
||||||
from src.services.budget_line_service import BudgetLineService
|
from src.services.budget_line_service import BudgetLineService
|
||||||
from src.db.models.form_type import FormTypeEnum
|
from src.db.models.form_type import FormTypeEnum
|
||||||
from src.services.sheet_service import SheetService
|
from src.services.sheet_service import SheetService
|
||||||
from src.domain.schemas import AddLineSchema, BaseListResponse, BaseSingleResponse, BudgetFormResponse, CellPatch, CellsPatch, DirectionSchemaEnum, SheetFormTypeResponse, SheetResponse
|
from src.domain.schemas import AddLineSchema, BaseListResponse, BaseSingleResponse, BudgetFormResponse, CellPatch, CellsPatch, DirectionSchemaEnum, FormCreateSchema, SheetFormTypeResponse, SheetResponse
|
||||||
from src.db.models.app_user import AppUser
|
from src.db.models.app_user import AppUser
|
||||||
from src.services.budget_form_service import BudgetFormService
|
from src.services.budget_form_service import BudgetFormService
|
||||||
from src.api.v1.deps import get_current_active_user_with_set_db
|
from src.api.v1.deps import get_current_active_user_with_set_db, require_admin
|
||||||
from src.db.session import get_db
|
from src.db.session import get_db
|
||||||
|
|
||||||
router = APIRouter(prefix="/form", tags=["forms"])
|
router = APIRouter(prefix="/form", tags=["forms"])
|
||||||
@ -354,3 +355,32 @@ async def delete_line(
|
|||||||
count=len(result),
|
count=len(result),
|
||||||
result=_rows_to_sheet_response(result),
|
result=_rows_to_sheet_response(result),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/")
|
||||||
|
async def add_form(
|
||||||
|
response: Response,
|
||||||
|
form: FormCreateSchema,
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
current_user: AppUser = Depends(require_admin),
|
||||||
|
) -> BaseSingleResponse[BudgetFormResponse]:
|
||||||
|
t0 = time.perf_counter()
|
||||||
|
bf_service = BudgetFormService(db)
|
||||||
|
org_service = OrgUnitService(db)
|
||||||
|
|
||||||
|
org_unit = await org_service.get(org_unit_id=form.org_unit_id, user=current_user)
|
||||||
|
if not org_unit:
|
||||||
|
raise HTTPException(404, f"ССП {form.org_unit_id} не найден")
|
||||||
|
|
||||||
|
new_form = await bf_service.create(
|
||||||
|
form_type_code=form.form_type_code,
|
||||||
|
year=form.year,
|
||||||
|
org_unit_id=org_unit.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
db_ms = (time.perf_counter() - t0) * 1000
|
||||||
|
response.headers["X-DB-Time-Ms"] = f"{db_ms:.2f}"
|
||||||
|
|
||||||
|
return BaseSingleResponse(
|
||||||
|
result = BudgetFormResponse.model_validate(new_form),
|
||||||
|
)
|
||||||
|
|||||||
@ -220,6 +220,12 @@ class FormTypeSchemaEnum(str, enum.Enum):
|
|||||||
FORM_4 = "FORM_4"
|
FORM_4 = "FORM_4"
|
||||||
|
|
||||||
|
|
||||||
|
class FormCreateSchema(BaseModel):
|
||||||
|
year: int
|
||||||
|
form_type_code: FormTypeSchemaEnum
|
||||||
|
org_unit_id: int
|
||||||
|
|
||||||
|
|
||||||
class OrgUnitBaseSchema(BaseModel):
|
class OrgUnitBaseSchema(BaseModel):
|
||||||
title: str
|
title: str
|
||||||
is_ssp: bool
|
is_ssp: bool
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from sqlalchemy import func, select
|
from sqlalchemy import func, select, text
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from src.db.models.budget_form import BudgetForm
|
from src.db.models.budget_form import BudgetForm
|
||||||
@ -83,3 +83,33 @@ class BudgetFormRepository:
|
|||||||
)
|
)
|
||||||
return (await self.db.execute(query)).scalars().first()
|
return (await self.db.execute(query)).scalars().first()
|
||||||
|
|
||||||
|
async def create(
|
||||||
|
self,
|
||||||
|
form_type_code: str,
|
||||||
|
year: int,
|
||||||
|
org_unit_id: int,
|
||||||
|
) -> BudgetForm | None:
|
||||||
|
form_id = (
|
||||||
|
await self.db.execute(
|
||||||
|
text(
|
||||||
|
"""
|
||||||
|
SELECT *
|
||||||
|
FROM v3.add_budget_form(
|
||||||
|
:form_type,
|
||||||
|
:year,
|
||||||
|
:org_unit_id
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
),
|
||||||
|
{
|
||||||
|
"form_type": form_type_code,
|
||||||
|
"year": year,
|
||||||
|
"org_unit_id": org_unit_id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
).scalar_one_or_none()
|
||||||
|
if form_id is None:
|
||||||
|
return None
|
||||||
|
return await self.get(
|
||||||
|
budget_form_id=form_id,
|
||||||
|
)
|
||||||
@ -65,3 +65,15 @@ class BudgetFormService:
|
|||||||
load_form_type=load_form_type,
|
load_form_type=load_form_type,
|
||||||
load_org=load_org,
|
load_org=load_org,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def create(
|
||||||
|
self,
|
||||||
|
form_type_code: str,
|
||||||
|
year: int,
|
||||||
|
org_unit_id: int,
|
||||||
|
) -> BudgetForm | None:
|
||||||
|
return await self.bf_repo.create(
|
||||||
|
form_type_code=form_type_code,
|
||||||
|
year=year,
|
||||||
|
org_unit_id=org_unit_id,
|
||||||
|
)
|
||||||
@ -135,3 +135,48 @@ def test_forms_delete_line_not_found_error_shape(client, admin_tokens, auth_head
|
|||||||
payload = response.json()
|
payload = response.json()
|
||||||
assert isinstance(payload, dict)
|
assert isinstance(payload, dict)
|
||||||
assert "message" in payload
|
assert "message" in payload
|
||||||
|
|
||||||
|
|
||||||
|
def test_forms_add_form_success(client, admin_tokens, auth_headers):
|
||||||
|
response = client.post(
|
||||||
|
"/api/v1/form/",
|
||||||
|
json={"year": 2025, "form_type_code": "FORM_1", "org_unit_id": 1},
|
||||||
|
headers=auth_headers(admin_tokens),
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
payload = response.json()
|
||||||
|
assert "result" in payload
|
||||||
|
assert isinstance(payload["result"], dict)
|
||||||
|
assert payload["result"]["year"] == 2025
|
||||||
|
|
||||||
|
assert "id" in payload["result"]
|
||||||
|
form_id = payload["result"]["id"]
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1/form/{form_id}",
|
||||||
|
headers=auth_headers(admin_tokens),
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
def test_forms_add_form_org_unit_not_found(client, admin_tokens, auth_headers):
|
||||||
|
response = client.post(
|
||||||
|
"/api/v1/form/",
|
||||||
|
json={"year": 2025, "form_type_code": "FORM_1", "org_unit_id": 999},
|
||||||
|
headers=auth_headers(admin_tokens),
|
||||||
|
)
|
||||||
|
assert response.status_code == 404
|
||||||
|
payload = response.json()
|
||||||
|
assert isinstance(payload, dict)
|
||||||
|
assert "message" in payload
|
||||||
|
|
||||||
|
|
||||||
|
def test_forms_add_form_forbidden_not_admin(client, isp_tokens, auth_headers):
|
||||||
|
response = client.post(
|
||||||
|
"/api/v1/form/",
|
||||||
|
json={"year": 2025, "form_type_code": "FORM_1", "org_unit_id": 1},
|
||||||
|
headers=auth_headers(isp_tokens),
|
||||||
|
)
|
||||||
|
assert response.status_code == 403
|
||||||
|
payload = response.json()
|
||||||
|
assert isinstance(payload, dict)
|
||||||
|
assert "message" in payload
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user