feat: lensIssues - Добавлена возможность получения lensIssue по lensId

This commit is contained in:
Андрей Дувакин 2025-07-04 07:35:20 +05:00
parent 1541aba89f
commit 551af24be9
6 changed files with 132 additions and 14 deletions

View File

@ -85,6 +85,15 @@ class LensIssuesRepository:
result = await self.db.execute(stmt) result = await self.db.execute(stmt)
return result.scalars().all() return result.scalars().all()
async def get_by_lens_id(self, lens_id: int) -> Optional[LensIssue]:
stmt = (
select(LensIssue)
.filter_by(lens_id=lens_id)
.options(joinedload(LensIssue.patient))
)
result = await self.db.execute(stmt)
return result.scalars().first()
async def get_by_id(self, lens_issue_id: int) -> Optional[LensIssue]: async def get_by_id(self, lens_issue_id: int) -> Optional[LensIssue]:
stmt = select(LensIssue).filter_by(id=lens_issue_id) stmt = select(LensIssue).filter_by(id=lens_issue_id)
result = await self.db.execute(stmt) result = await self.db.execute(stmt)

View File

@ -60,6 +60,21 @@ async def get_lens_issues_by_patient(
return await lens_issues_service.get_lens_issues_by_patient_id(patient_id) return await lens_issues_service.get_lens_issues_by_patient_id(patient_id)
@router.get(
'/by-lens/{lens_id}/',
response_model=Optional[LensIssueEntity],
summary="Get lens issues by lens id",
description="Returns a paginated list of lens issues by lens id",
)
async def get_lens_issues_by_lens_id(
lens_id: int,
db: AsyncSession = Depends(get_db),
user=Depends(get_current_user),
):
lens_issues_service = LensIssuesService(db)
return await lens_issues_service.get_lens_issue_by_lens_id(lens_id)
@router.post( @router.post(
"/", "/",
response_model=LensIssueEntity, response_model=LensIssueEntity,

View File

@ -1,5 +1,5 @@
from datetime import date from datetime import date
from typing import Optional, Literal, Tuple from typing import Optional, Literal, Tuple, Any, Coroutine
from fastapi import HTTPException from fastapi import HTTPException
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
@ -56,13 +56,24 @@ class LensIssuesService:
lens_issues = await self.lens_issues_repository.get_by_patient_id(patient.id) lens_issues = await self.lens_issues_repository.get_by_patient_id(patient.id)
print(lens_issues)
return [ return [
self.model_to_entity(lens_issue) self.model_to_entity(lens_issue)
for lens_issue in lens_issues for lens_issue in lens_issues
] ]
async def get_lens_issue_by_lens_id(self, lens_id: int) -> Optional[LensIssueEntity]:
lens = await self.lenses_repository.get_by_id(lens_id)
if not lens:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail='Линза с таким ID не найдена',
)
lens_issue = await self.lens_issues_repository.get_by_lens_id(lens_id)
return self.model_to_entity(lens_issue)
async def create_lens_issue(self, lens_issue: LensIssueEntity, user_id: int) -> Optional[LensIssueEntity]: async def create_lens_issue(self, lens_issue: LensIssueEntity, user_id: int) -> Optional[LensIssueEntity]:
patient = await self.patient_repository.get_by_id(lens_issue.patient_id) patient = await self.patient_repository.get_by_id(lens_issue.patient_id)

View File

@ -50,6 +50,10 @@ export const lensIssuesApi = createApi({
query: (patientId) => `/lens_issues/by-patient/${patientId}/`, query: (patientId) => `/lens_issues/by-patient/${patientId}/`,
providesTags: ['LensIssues'], providesTags: ['LensIssues'],
}), }),
getLensIssueByLens: builder.query({
query: (lensId) => `/lens_issues/by-lens/${lensId}/`,
providesTags: ['LensIssues'],
}),
}), }),
}); });
@ -57,4 +61,5 @@ export const {
useGetLensIssuesQuery, useGetLensIssuesQuery,
useAddLensIssuesMutation, useAddLensIssuesMutation,
useGetLensIssuesByPatientQuery, useGetLensIssuesByPatientQuery,
useGetLensIssueByLensQuery,
} = lensIssuesApi; } = lensIssuesApi;

View File

@ -0,0 +1,22 @@
import {useGetLensIssueByLensQuery} from "../../../../../../../Api/lensIssuesApi.js";
const useLensViewModal = (lens, visible) => {
const {
data: lensIssue = null,
isLoading: isLensIssueLoading,
isError: isLensIssueError,
} = useGetLensIssueByLensQuery(lens?.id, {
skip: !visible || !lens?.id,
pollingInterval: 60000,
refetchOnMountOrArgChange: true,
});
return {
lensIssue,
isLensIssueLoading,
isLensIssueError,
};
};
export default useLensViewModal;

View File

@ -1,10 +1,61 @@
import {Button, Col, Modal, Row, Typography, Divider} from "antd"; import {Button, Col, Modal, Row, Typography, Divider, Collapse, Result} from "antd";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import {PatientPropType} from "../../../../../Types/patientPropType.js"; import {PatientPropType} from "../../../../../Types/patientPropType.js";
import usePatientsViewModal from "./usePatientsViewModal.js";
import LoadingIndicator from "../../../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
const {Text, Title} = Typography; const {Text, Title} = Typography;
const PatientViewModal = ({visible, onCancel, patient}) => { const PatientViewModal = ({visible, onCancel, patient}) => {
const {lensIssues, isLensIssuesLoading, isLensIssuesError} = usePatientsViewModal(patient, visible);
if (isLensIssuesLoading) {
return (
<Modal title="Просмотр пациента" open={visible} onCancel={onCancel} footer={null}>
<LoadingIndicator/>
</Modal>
);
}
if (isLensIssuesError) {
return (
<Modal title="Просмотр пациента" open={visible} onCancel={onCancel} footer={null}>
<Result
status="error"
title="Ошибка"
subTitle="Не удалось загрузить данные о выданных линзах"
extra={<Button type="primary" onClick={onCancel}>Закрыть</Button>}
/>
</Modal>
);
}
const items = lensIssues.length ? lensIssues.map((issue) => {
return {
key: issue.id,
label: `${new Date(issue.issue_date).toLocaleDateString('ru-RU')}`,
children: issue.lens ? (
<div>
<p><b>id:</b> {issue.lens.id}</p>
<p><b>Линза:</b> {issue.lens.side}</p>
<p><b>Диаметр:</b> {issue.lens.diameter}</p>
<p><b>Тор:</b> {issue.lens.tor}</p>
<p><b>Пресетная рефракция:</b> {issue.lens.preset_refraction}</p>
<p><b>Периферийная торичность:</b> {issue.lens.periphery_toricity}</p>
<p><b>FVC:</b> {issue.lens.fvc}</p>
<p><b>ESP:</b> {issue.lens.esa}</p>
</div>
) : (
<p>Данные о линзе отсутствуют</p>
),
};
}) : [{
key: 'no-lenses',
label: 'Нет выданных линз',
children: <p>У пациента нет выданных линз</p>,
}];
return ( return (
<Modal <Modal
title="Просмотр пациента" title="Просмотр пациента"
@ -64,6 +115,11 @@ const PatientViewModal = ({ visible, onCancel, patient }) => {
<Title level={5}>👓 Коррекция</Title> <Title level={5}>👓 Коррекция</Title>
<Text>{patient.correction || 'Не указ'}</Text> <Text>{patient.correction || 'Не указ'}</Text>
</div> </div>
<Typography.Title level={5}>📦 Выданные линзы</Typography.Title>
<Collapse
items={items}
/>
</Modal> </Modal>
); );
}; };