create-form: создание задачи
This commit is contained in:
parent
e7e8bc0df2
commit
2073569765
@ -5,13 +5,14 @@ from fastapi import APIRouter, Depends, HTTPException, Response
|
||||
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.services.org_unit_service import OrgUnitService
|
||||
from src.services.budget_line_service import BudgetLineService
|
||||
from src.db.models.form_type import FormTypeEnum
|
||||
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.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
|
||||
|
||||
router = APIRouter(prefix="/form", tags=["forms"])
|
||||
@ -353,4 +354,33 @@ async def delete_line(
|
||||
return BaseListResponse(
|
||||
count=len(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"
|
||||
|
||||
|
||||
class FormCreateSchema(BaseModel):
|
||||
year: int
|
||||
form_type_code: FormTypeSchemaEnum
|
||||
org_unit_id: int
|
||||
|
||||
|
||||
class OrgUnitBaseSchema(BaseModel):
|
||||
title: str
|
||||
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 src.db.models.budget_form import BudgetForm
|
||||
@ -82,4 +82,34 @@ class BudgetFormRepository:
|
||||
joinedload(BudgetForm.form_type)
|
||||
)
|
||||
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_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()
|
||||
assert isinstance(payload, dict)
|
||||
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