сделал слои для содержимого наборов линз в апи
This commit is contained in:
parent
a7e6bb3f59
commit
24405f1e06
42
api/app/application/set_content_repository.py
Normal file
42
api/app/application/set_content_repository.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
from typing import Sequence, Optional
|
||||||
|
|
||||||
|
from sqlalchemy import select
|
||||||
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
|
from app.domain.models import SetContent
|
||||||
|
|
||||||
|
|
||||||
|
class SetContentRepository:
|
||||||
|
def __init__(self, db: AsyncSession):
|
||||||
|
self.db = db
|
||||||
|
|
||||||
|
async def get_all(self) -> Sequence[SetContent]:
|
||||||
|
stmt = select(SetContent)
|
||||||
|
result = await self.db.execute(stmt)
|
||||||
|
return result.scalars().all()
|
||||||
|
|
||||||
|
async def get_by_id(self, set_content_id: int) -> Optional[SetContent]:
|
||||||
|
stmt = select(SetContent).filter(SetContent.id == set_content_id)
|
||||||
|
result = await self.db.execute(stmt)
|
||||||
|
return result.scalars().first()
|
||||||
|
|
||||||
|
async def get_by_set_id(self, set_id: int) -> Sequence[SetContent]:
|
||||||
|
stmt = select(SetContent).filter(SetContent.set_id == set_id)
|
||||||
|
result = await self.db.execute(stmt)
|
||||||
|
return result.scalars().all()
|
||||||
|
|
||||||
|
async def create(self, set_content: SetContent) -> SetContent:
|
||||||
|
self.db.add(set_content)
|
||||||
|
await self.db.commit()
|
||||||
|
await self.db.refresh(set_content)
|
||||||
|
return set_content
|
||||||
|
|
||||||
|
async def update(self, set_content: SetContent) -> SetContent:
|
||||||
|
await self.db.merge(set_content)
|
||||||
|
await self.db.commit()
|
||||||
|
return set_content
|
||||||
|
|
||||||
|
async def delete(self, set_content: SetContent) -> SetContent:
|
||||||
|
await self.db.delete(set_content)
|
||||||
|
await self.db.commit()
|
||||||
|
return set_content
|
||||||
70
api/app/controllers/set_content_router.py
Normal file
70
api/app/controllers/set_content_router.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
from fastapi import APIRouter, Depends
|
||||||
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
|
from app.database.session import get_db
|
||||||
|
from app.domain.entities.set_content import SetContentEntity
|
||||||
|
from app.infrastructure.dependencies import get_current_user
|
||||||
|
from app.infrastructure.set_content_service import SetContentService
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get(
|
||||||
|
'/set_content/{set_id}/',
|
||||||
|
response_model=list[SetContentEntity],
|
||||||
|
summary='Get all set content by set ID',
|
||||||
|
description='Returns a list of set content by set ID',
|
||||||
|
)
|
||||||
|
async def get_set_content_by_set_id(
|
||||||
|
set_id: int,
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
user=Depends(get_current_user),
|
||||||
|
):
|
||||||
|
set_content_service = SetContentService(db)
|
||||||
|
return await set_content_service.get_content_by_set_id(set_id)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post(
|
||||||
|
'/set_content/',
|
||||||
|
response_model=SetContentEntity,
|
||||||
|
summary='Create a new set content',
|
||||||
|
description='Create a new set content',
|
||||||
|
)
|
||||||
|
async def create_set_content(
|
||||||
|
set_content: SetContentEntity,
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
user=Depends(get_current_user),
|
||||||
|
):
|
||||||
|
set_content_service = SetContentService(db)
|
||||||
|
return await set_content_service.create_set_content(set_content)
|
||||||
|
|
||||||
|
|
||||||
|
@router.put(
|
||||||
|
'/set_content/{set_content_id}/',
|
||||||
|
response_model=SetContentEntity,
|
||||||
|
summary='Update a set content',
|
||||||
|
description='Update a set content',
|
||||||
|
)
|
||||||
|
async def update_set_content(
|
||||||
|
set_content_id: int,
|
||||||
|
set_content: SetContentEntity,
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
user=Depends(get_current_user),
|
||||||
|
):
|
||||||
|
set_content_service = SetContentService(db)
|
||||||
|
return await set_content_service.update_set_content(set_content_id, set_content)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete(
|
||||||
|
'/set_content/{set_content_id}/',
|
||||||
|
response_model=SetContentEntity,
|
||||||
|
summary='Delete set content',
|
||||||
|
description='Delete an existing set content',
|
||||||
|
)
|
||||||
|
async def delete_set_content(
|
||||||
|
set_content_id: int,
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
user=Depends(get_current_user),
|
||||||
|
):
|
||||||
|
set_content_service = SetContentService(db)
|
||||||
|
return await set_content_service.delete_set_content(set_content_id)
|
||||||
@ -51,7 +51,7 @@ async def update_set(
|
|||||||
user=Depends(get_current_user),
|
user=Depends(get_current_user),
|
||||||
):
|
):
|
||||||
sets_service = SetsService(db)
|
sets_service = SetsService(db)
|
||||||
return sets_service.update_set(set_id, _set)
|
return await sets_service.update_set(set_id, _set)
|
||||||
|
|
||||||
|
|
||||||
@router.delete(
|
@router.delete(
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
"""добавил тип линзы у содержимого отчета
|
||||||
|
|
||||||
|
Revision ID: 15df0d2bfad5
|
||||||
|
Revises: a5c09be17888
|
||||||
|
Create Date: 2025-02-20 19:51:20.196094
|
||||||
|
|
||||||
|
"""
|
||||||
|
from typing import Sequence, Union
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision: str = '15df0d2bfad5'
|
||||||
|
down_revision: Union[str, None] = 'a5c09be17888'
|
||||||
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('set_contents', sa.Column('type_id', sa.Integer(), nullable=False))
|
||||||
|
op.create_foreign_key(None, 'set_contents', 'lens_types', ['type_id'], ['id'])
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_constraint(None, 'set_contents', type_='foreignkey')
|
||||||
|
op.drop_column('set_contents', 'type_id')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
"""сделал у содержания набора тип стороны enum
|
||||||
|
|
||||||
|
Revision ID: a5c09be17888
|
||||||
|
Revises: 0249759985c3
|
||||||
|
Create Date: 2025-02-20 19:39:57.756998
|
||||||
|
|
||||||
|
"""
|
||||||
|
from typing import Sequence, Union
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision: str = 'a5c09be17888'
|
||||||
|
down_revision: Union[str, None] = '0249759985c3'
|
||||||
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
op.execute("ALTER TABLE set_contents ALTER COLUMN side TYPE sideenum USING CASE "
|
||||||
|
"WHEN side = 0 THEN 'LEFT'::sideenum "
|
||||||
|
"WHEN side = 1 THEN 'RIGHT'::sideenum END")
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
op.execute("ALTER TABLE set_contents ALTER COLUMN side TYPE INTEGER USING CASE "
|
||||||
|
"WHEN side = 'LEFT' THEN 0 "
|
||||||
|
"WHEN side = 'RIGHT' THEN 1 END")
|
||||||
@ -15,4 +15,5 @@ class SetContentEntity(BaseModel):
|
|||||||
side: str
|
side: str
|
||||||
count: int
|
count: int
|
||||||
|
|
||||||
|
type_id: int
|
||||||
set_id: int
|
set_id: int
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
from sqlalchemy import Column, Integer, ForeignKey
|
from sqlalchemy import Column, Integer, ForeignKey, Enum
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
from app.domain.models.base import BaseModel
|
from app.domain.models.base import BaseModel
|
||||||
|
from app.domain.models.lens import SideEnum
|
||||||
|
|
||||||
|
|
||||||
class SetContent(BaseModel):
|
class SetContent(BaseModel):
|
||||||
@ -14,9 +15,11 @@ class SetContent(BaseModel):
|
|||||||
preset_refraction = Column(Integer, nullable=False)
|
preset_refraction = Column(Integer, nullable=False)
|
||||||
diameter = Column(Integer, nullable=False)
|
diameter = Column(Integer, nullable=False)
|
||||||
periphery_toricity = Column(Integer, nullable=False)
|
periphery_toricity = Column(Integer, nullable=False)
|
||||||
side = Column(Integer, nullable=False)
|
side = Column(Enum(SideEnum), nullable=False)
|
||||||
count = Column(Integer, nullable=False)
|
count = Column(Integer, nullable=False)
|
||||||
|
|
||||||
|
type_id = Column(Integer, ForeignKey('lens_types.id'), nullable=False)
|
||||||
set_id = Column(Integer, ForeignKey('sets.id'), nullable=False)
|
set_id = Column(Integer, ForeignKey('sets.id'), nullable=False)
|
||||||
|
|
||||||
|
type = relationship('LensType', back_populates='lenses')
|
||||||
set = relationship('Set', back_populates='contents')
|
set = relationship('Set', back_populates='contents')
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from typing import Optional, Any, Coroutine
|
from typing import Optional
|
||||||
|
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
@ -41,7 +41,7 @@ class LensesService:
|
|||||||
if not lens_type:
|
if not lens_type:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
detail='The lens type with this ID was not found'
|
detail='The lens type with this ID was not found',
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
198
api/app/infrastructure/set_content_service.py
Normal file
198
api/app/infrastructure/set_content_service.py
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from fastapi import HTTPException
|
||||||
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
from starlette import status
|
||||||
|
|
||||||
|
from app.application.lens_types_repository import LensTypesRepository
|
||||||
|
from app.application.set_content_repository import SetContentRepository
|
||||||
|
from app.application.sets_repository import SetsRepository
|
||||||
|
from app.domain.entities.set_content import SetContentEntity
|
||||||
|
from app.domain.models import SetContent
|
||||||
|
from app.domain.models.lens import SideEnum
|
||||||
|
|
||||||
|
|
||||||
|
class SetContentService:
|
||||||
|
def __init__(self, db: AsyncSession):
|
||||||
|
self.set_content_repository = SetContentRepository(db)
|
||||||
|
self.set_repository = SetsRepository(db)
|
||||||
|
self.lens_types_repository = LensTypesRepository(db)
|
||||||
|
|
||||||
|
async def get_all_set_content(self) -> list[SetContentEntity]:
|
||||||
|
set_content = await self.set_content_repository.get_all()
|
||||||
|
return [
|
||||||
|
SetContentEntity(
|
||||||
|
id=content.id,
|
||||||
|
tor=content.tor,
|
||||||
|
trial=content.trial,
|
||||||
|
esa=content.esa,
|
||||||
|
fvc=content.fvc,
|
||||||
|
preset_refraction=content.preset_refraction,
|
||||||
|
diameter=content.diameter,
|
||||||
|
periphery_toricity=content.periphery_toricity,
|
||||||
|
side=content.side,
|
||||||
|
count=content.count,
|
||||||
|
type_id=content.type_id,
|
||||||
|
set_id=content.set_id,
|
||||||
|
)
|
||||||
|
for content in set_content
|
||||||
|
]
|
||||||
|
|
||||||
|
async def get_content_by_set_id(self, set_id: int) -> Optional[list[SetContentEntity]]:
|
||||||
|
_set = self.set_repository.get_by_id(set_id)
|
||||||
|
|
||||||
|
if not _set:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail='The set with this ID was not found',
|
||||||
|
)
|
||||||
|
|
||||||
|
set_content = await self.set_content_repository.get_by_set_id(set_id)
|
||||||
|
|
||||||
|
return [
|
||||||
|
SetContentEntity(
|
||||||
|
id=content.id,
|
||||||
|
tor=content.tor,
|
||||||
|
trial=content.trial,
|
||||||
|
esa=content.esa,
|
||||||
|
fvc=content.fvc,
|
||||||
|
preset_refraction=content.preset_refraction,
|
||||||
|
diameter=content.diameter,
|
||||||
|
periphery_toricity=content.periphery_toricity,
|
||||||
|
side=content.side,
|
||||||
|
count=content.count,
|
||||||
|
type_id=content.type_id,
|
||||||
|
set_id=content.set_id,
|
||||||
|
)
|
||||||
|
for content in set_content
|
||||||
|
]
|
||||||
|
|
||||||
|
async def create_set_content(self, set_content: SetContentEntity) -> SetContentEntity:
|
||||||
|
lens_type = await self.lens_types_repository.get_by_id(set_content.type_id)
|
||||||
|
|
||||||
|
if not lens_type:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail='The lens type with this ID was not found',
|
||||||
|
)
|
||||||
|
|
||||||
|
_set = self.set_repository.get_by_id(set_content.set_id)
|
||||||
|
|
||||||
|
if not _set:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail='The set with this ID was not found',
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
side_enum = SideEnum(set_content.side)
|
||||||
|
except ValueError:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=f"Invalid side value: {set_content.side}. Must be 'левая' or 'правая'."
|
||||||
|
)
|
||||||
|
|
||||||
|
set_content_model = SetContent(
|
||||||
|
tor=set_content.tor,
|
||||||
|
trial=set_content.trial,
|
||||||
|
esa=set_content.esa,
|
||||||
|
fvc=set_content.fvc,
|
||||||
|
preset_refraction=set_content.preset_refraction,
|
||||||
|
diameter=set_content.diameter,
|
||||||
|
periphery_toricity=set_content.periphery_toricity,
|
||||||
|
side=side_enum,
|
||||||
|
count=set_content.count,
|
||||||
|
type_id=set_content.type_id,
|
||||||
|
set_id=set_content.set_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
await self.set_content_repository.create(set_content_model)
|
||||||
|
|
||||||
|
return SetContentEntity(
|
||||||
|
id=set_content_model.id,
|
||||||
|
tor=set_content_model.tor,
|
||||||
|
trial=set_content_model.trial,
|
||||||
|
esa=set_content_model.esa,
|
||||||
|
fvc=set_content_model.fvc,
|
||||||
|
preset_refraction=set_content_model.preset_refraction,
|
||||||
|
diameter=set_content_model.diameter,
|
||||||
|
periphery_toricity=set_content_model.periphery_toricity,
|
||||||
|
side=set_content_model.side.value,
|
||||||
|
count=set_content_model.count,
|
||||||
|
type_id=set_content_model.type_id,
|
||||||
|
set_id=set_content_model.set_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def update_set_content(self, set_content_id: int, set_content: SetContentEntity):
|
||||||
|
set_content_model = await self.set_content_repository.get_by_id(set_content_id)
|
||||||
|
|
||||||
|
if not set_content_model:
|
||||||
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Set content not found")
|
||||||
|
|
||||||
|
_set = await self.set_repository.get_by_id(set_content.set_id)
|
||||||
|
|
||||||
|
if not _set:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail='The set with this ID was not found',
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
side_enum = SideEnum(set_content_model.side)
|
||||||
|
except ValueError:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=f"Invalid side value: {set_content_model.side}. Must be 'левая' or 'правая'."
|
||||||
|
)
|
||||||
|
|
||||||
|
set_content_model.tor = set_content.tor
|
||||||
|
set_content_model.trial = set_content.trial
|
||||||
|
set_content_model.esa = set_content.esa
|
||||||
|
set_content_model.fvc = set_content.fvc
|
||||||
|
set_content_model.preset_refraction = set_content.preset_refraction
|
||||||
|
set_content_model.diameter = set_content.diameter
|
||||||
|
set_content_model.periphery_toricity = set_content.periphery_toricity
|
||||||
|
set_content_model.side = side_enum
|
||||||
|
set_content_model.count = set_content.count
|
||||||
|
set_content_model.type_id = set_content.type_id
|
||||||
|
set_content_model.set_id = set_content.set_id
|
||||||
|
|
||||||
|
await self.set_content_repository.update(set_content_model)
|
||||||
|
|
||||||
|
return SetContentEntity(
|
||||||
|
id=set_content_model.id,
|
||||||
|
tor=set_content_model.tor,
|
||||||
|
trial=set_content_model.trial,
|
||||||
|
esa=set_content_model.esa,
|
||||||
|
fvc=set_content_model.fvc,
|
||||||
|
preset_refraction=set_content_model.preset_refraction,
|
||||||
|
diameter=set_content_model.diameter,
|
||||||
|
periphery_toricity=set_content_model.periphery_toricity,
|
||||||
|
side=set_content_model.side.value,
|
||||||
|
count=set_content_model.count,
|
||||||
|
type_id=set_content_model.type_id,
|
||||||
|
set_id=set_content_model.set_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def delete_set_content(self, set_content_id: int) -> Optional[SetContentEntity]:
|
||||||
|
set_content = await self.set_content_repository.get_by_id(set_content_id)
|
||||||
|
|
||||||
|
if not set_content:
|
||||||
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Set content not found")
|
||||||
|
|
||||||
|
result = await self.set_content_repository.delete(set_content)
|
||||||
|
|
||||||
|
return SetContentEntity(
|
||||||
|
id=result.id,
|
||||||
|
tor=result.tor,
|
||||||
|
trial=result.trial,
|
||||||
|
esa=result.esa,
|
||||||
|
fvc=result.fvc,
|
||||||
|
preset_refraction=result.preset_refraction,
|
||||||
|
diameter=result.diameter,
|
||||||
|
periphery_toricity=result.periphery_toricity,
|
||||||
|
side=result.side.value,
|
||||||
|
count=result.count,
|
||||||
|
type_id=result.type_id,
|
||||||
|
set_id=result.set_id,
|
||||||
|
)
|
||||||
@ -6,6 +6,7 @@ from app.controllers.lens_types_router import router as lens_types_router
|
|||||||
from app.controllers.lenses_router import router as lenses_router
|
from app.controllers.lenses_router import router as lenses_router
|
||||||
from app.controllers.patients_router import router as patients_router
|
from app.controllers.patients_router import router as patients_router
|
||||||
from app.controllers.register_routes import router as register_router
|
from app.controllers.register_routes import router as register_router
|
||||||
|
from app.controllers.set_content_router import router as set_content_router
|
||||||
from app.controllers.sets_router import router as sets_router
|
from app.controllers.sets_router import router as sets_router
|
||||||
from app.settings import settings
|
from app.settings import settings
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ def start_app():
|
|||||||
api_app.include_router(lenses_router, prefix=settings.APP_PREFIX, tags=['lenses'])
|
api_app.include_router(lenses_router, prefix=settings.APP_PREFIX, tags=['lenses'])
|
||||||
api_app.include_router(lens_types_router, prefix=settings.APP_PREFIX, tags=['lens_types'])
|
api_app.include_router(lens_types_router, prefix=settings.APP_PREFIX, tags=['lens_types'])
|
||||||
api_app.include_router(sets_router, prefix=settings.APP_PREFIX, tags=['sets'])
|
api_app.include_router(sets_router, prefix=settings.APP_PREFIX, tags=['sets'])
|
||||||
|
api_app.include_router(set_content_router, prefix=settings.APP_PREFIX, tags=['set_content'])
|
||||||
|
|
||||||
return api_app
|
return api_app
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user