add proverka func
This commit is contained in:
28
backend/create_inspection_tables.py
Normal file
28
backend/create_inspection_tables.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
"""
|
||||||
|
Скрипт для создания таблиц системы проверок оборудования.
|
||||||
|
Создаёт только новые таблицы, не затрагивая существующие.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from backend.database import engine
|
||||||
|
from backend.models import Base, InspectionSession, InspectionRecord, UnknownBarcode
|
||||||
|
|
||||||
|
|
||||||
|
def create_inspection_tables():
|
||||||
|
"""Создать таблицы для системы проверок"""
|
||||||
|
print("Creating inspection tables...")
|
||||||
|
|
||||||
|
# Создать только новые таблицы
|
||||||
|
Base.metadata.create_all(bind=engine, tables=[
|
||||||
|
InspectionSession.__table__,
|
||||||
|
InspectionRecord.__table__,
|
||||||
|
UnknownBarcode.__table__
|
||||||
|
])
|
||||||
|
|
||||||
|
print("Inspection tables created successfully!")
|
||||||
|
print("- inspection_sessions")
|
||||||
|
print("- inspection_records")
|
||||||
|
print("- unknown_barcodes")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
create_inspection_tables()
|
||||||
214
backend/routers/inspections.py
Normal file
214
backend/routers/inspections.py
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
from datetime import datetime, timezone
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Depends, HTTPException, status
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from sqlalchemy import func
|
||||||
|
|
||||||
|
from .. import schemas, database, models
|
||||||
|
from ..security import get_current_user
|
||||||
|
|
||||||
|
|
||||||
|
inspections = APIRouter(prefix="/inspections", tags=["inspections"])
|
||||||
|
|
||||||
|
|
||||||
|
@inspections.post("/sessions", response_model=schemas.InspectionSessionRead)
|
||||||
|
async def create_inspection_session(
|
||||||
|
payload: schemas.InspectionSessionCreate,
|
||||||
|
db: Session = Depends(database.get_db),
|
||||||
|
current_user: models.User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""Начать новую сессию проверки"""
|
||||||
|
session = models.InspectionSession(
|
||||||
|
user_id=current_user.id,
|
||||||
|
started_at=datetime.now(timezone.utc),
|
||||||
|
aud_id=payload.aud_id
|
||||||
|
)
|
||||||
|
db.add(session)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(session)
|
||||||
|
return session
|
||||||
|
|
||||||
|
|
||||||
|
class CheckBarcodeRequest(schemas.BaseModel):
|
||||||
|
inv_number: str
|
||||||
|
|
||||||
|
|
||||||
|
@inspections.post("/sessions/{session_id}/check", response_model=schemas.CheckBarcodeResponse)
|
||||||
|
async def check_barcode(
|
||||||
|
session_id: int,
|
||||||
|
payload: CheckBarcodeRequest,
|
||||||
|
db: Session = Depends(database.get_db),
|
||||||
|
current_user: models.User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""Отсканировать штрихкод"""
|
||||||
|
inv_number = payload.inv_number
|
||||||
|
# Проверка существования сессии
|
||||||
|
session = db.query(models.InspectionSession).filter(models.InspectionSession.id == session_id).first()
|
||||||
|
if not session:
|
||||||
|
raise HTTPException(status_code=404, detail="Session not found")
|
||||||
|
|
||||||
|
# Проверка, что сессия не завершена
|
||||||
|
if session.completed_at is not None:
|
||||||
|
raise HTTPException(status_code=400, detail="Session already completed")
|
||||||
|
|
||||||
|
# Поиск оборудования по invNumber (точное совпадение)
|
||||||
|
# invNumber может быть строкой или числом, преобразуем для поиска
|
||||||
|
try:
|
||||||
|
inv_num_int = int(inv_number)
|
||||||
|
oborud = db.query(models.Oboruds).filter(models.Oboruds.invNumber == inv_num_int).first()
|
||||||
|
except ValueError:
|
||||||
|
oborud = None
|
||||||
|
|
||||||
|
if oborud:
|
||||||
|
# Оборудование найдено - создаём/обновляем запись (UPSERT)
|
||||||
|
record = db.query(models.InspectionRecord).filter_by(
|
||||||
|
session_id=session_id,
|
||||||
|
oborud_id=oborud.id
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if record:
|
||||||
|
# Обновить время проверки
|
||||||
|
record.checked_at = datetime.now(timezone.utc)
|
||||||
|
else:
|
||||||
|
# Создать новую запись
|
||||||
|
record = models.InspectionRecord(
|
||||||
|
session_id=session_id,
|
||||||
|
oborud_id=oborud.id,
|
||||||
|
checked_at=datetime.now(timezone.utc)
|
||||||
|
)
|
||||||
|
db.add(record)
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
db.refresh(oborud)
|
||||||
|
|
||||||
|
return schemas.CheckBarcodeResponse(
|
||||||
|
status="found",
|
||||||
|
equipment=schemas.OborudRead.model_validate(oborud),
|
||||||
|
message=f"Оборудование найдено: {oborud.nazvanie}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Оборудование не найдено - сохранить в неизвестные штрихкоды
|
||||||
|
unknown = models.UnknownBarcode(
|
||||||
|
session_id=session_id,
|
||||||
|
barcode=inv_number,
|
||||||
|
scanned_at=datetime.now(timezone.utc)
|
||||||
|
)
|
||||||
|
db.add(unknown)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
return schemas.CheckBarcodeResponse(
|
||||||
|
status="not_found",
|
||||||
|
equipment=None,
|
||||||
|
message=f"Оборудование с номером {inv_number} не найдено"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@inspections.get("/sessions/{session_id}", response_model=schemas.InspectionSessionStats)
|
||||||
|
async def get_inspection_session_stats(
|
||||||
|
session_id: int,
|
||||||
|
db: Session = Depends(database.get_db),
|
||||||
|
current_user: models.User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""Получить статистику сессии проверки"""
|
||||||
|
session = db.query(models.InspectionSession).filter(models.InspectionSession.id == session_id).first()
|
||||||
|
if not session:
|
||||||
|
raise HTTPException(status_code=404, detail="Session not found")
|
||||||
|
|
||||||
|
# Подсчёт статистики
|
||||||
|
total_checked = db.query(models.InspectionRecord).filter(
|
||||||
|
models.InspectionRecord.session_id == session_id
|
||||||
|
).count()
|
||||||
|
|
||||||
|
total_unknown = db.query(models.UnknownBarcode).filter(
|
||||||
|
models.UnknownBarcode.session_id == session_id
|
||||||
|
).count()
|
||||||
|
|
||||||
|
# Подсчёт ожидаемого количества оборудования
|
||||||
|
if session.aud_id:
|
||||||
|
# Проверка по аудитории
|
||||||
|
total_expected = db.query(models.Oboruds).filter(
|
||||||
|
models.Oboruds.aud_id == session.aud_id
|
||||||
|
).count()
|
||||||
|
else:
|
||||||
|
# Проверка всего оборудования
|
||||||
|
total_expected = db.query(models.Oboruds).count()
|
||||||
|
|
||||||
|
# Расчёт прогресса
|
||||||
|
progress_percent = round((total_checked / total_expected * 100), 2) if total_expected > 0 else 0.0
|
||||||
|
|
||||||
|
return schemas.InspectionSessionStats(
|
||||||
|
session=schemas.InspectionSessionRead.model_validate(session),
|
||||||
|
total_expected=total_expected,
|
||||||
|
total_checked=total_checked,
|
||||||
|
total_unknown=total_unknown,
|
||||||
|
progress_percent=progress_percent
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@inspections.post("/sessions/{session_id}/complete", response_model=schemas.InspectionSessionRead)
|
||||||
|
async def complete_inspection_session(
|
||||||
|
session_id: int,
|
||||||
|
db: Session = Depends(database.get_db),
|
||||||
|
current_user: models.User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""Завершить сессию проверки"""
|
||||||
|
session = db.query(models.InspectionSession).filter(models.InspectionSession.id == session_id).first()
|
||||||
|
if not session:
|
||||||
|
raise HTTPException(status_code=404, detail="Session not found")
|
||||||
|
|
||||||
|
if session.completed_at is not None:
|
||||||
|
raise HTTPException(status_code=400, detail="Session already completed")
|
||||||
|
|
||||||
|
session.completed_at = datetime.now(timezone.utc)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(session)
|
||||||
|
return session
|
||||||
|
|
||||||
|
|
||||||
|
@inspections.get("/sessions", response_model=list[schemas.InspectionSessionRead])
|
||||||
|
async def list_inspection_sessions(
|
||||||
|
user_id: Optional[int] = None,
|
||||||
|
aud_id: Optional[int] = None,
|
||||||
|
db: Session = Depends(database.get_db),
|
||||||
|
current_user: models.User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""Получить список всех сессий проверок (история)"""
|
||||||
|
query = db.query(models.InspectionSession)
|
||||||
|
|
||||||
|
if user_id is not None:
|
||||||
|
query = query.filter(models.InspectionSession.user_id == user_id)
|
||||||
|
|
||||||
|
if aud_id is not None:
|
||||||
|
query = query.filter(models.InspectionSession.aud_id == aud_id)
|
||||||
|
|
||||||
|
# Сортировка по дате (новые сверху)
|
||||||
|
sessions = query.order_by(models.InspectionSession.started_at.desc()).all()
|
||||||
|
return sessions
|
||||||
|
|
||||||
|
|
||||||
|
@inspections.get("/sessions/{session_id}/records", response_model=schemas.InspectionDetailReport)
|
||||||
|
async def get_inspection_session_records(
|
||||||
|
session_id: int,
|
||||||
|
db: Session = Depends(database.get_db),
|
||||||
|
current_user: models.User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""Получить детальный отчёт по сессии проверки"""
|
||||||
|
session = db.query(models.InspectionSession).filter(models.InspectionSession.id == session_id).first()
|
||||||
|
if not session:
|
||||||
|
raise HTTPException(status_code=404, detail="Session not found")
|
||||||
|
|
||||||
|
# Получить все записи проверок с информацией об оборудовании
|
||||||
|
records = db.query(models.InspectionRecord).filter(
|
||||||
|
models.InspectionRecord.session_id == session_id
|
||||||
|
).order_by(models.InspectionRecord.checked_at.desc()).all()
|
||||||
|
|
||||||
|
# Получить неизвестные штрихкоды
|
||||||
|
unknown_barcodes = db.query(models.UnknownBarcode).filter(
|
||||||
|
models.UnknownBarcode.session_id == session_id
|
||||||
|
).order_by(models.UnknownBarcode.scanned_at.desc()).all()
|
||||||
|
|
||||||
|
return schemas.InspectionDetailReport(
|
||||||
|
records=[schemas.InspectionRecordRead.model_validate(r) for r in records],
|
||||||
|
unknown_barcodes=[schemas.UnknownBarcodeRead.model_validate(ub) for ub in unknown_barcodes]
|
||||||
|
)
|
||||||
7
frontend/bootstrap.min.css
vendored
Normal file
7
frontend/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user