diff --git a/crud.py b/crud.py index 1ed911b..82ba8dd 100644 --- a/crud.py +++ b/crud.py @@ -1,5 +1,5 @@ from sqlalchemy.orm import Session -from models import Car, EngineType, HybridType, PowerRatio +from models import Car, EngineType, HybridType, PowerRatio, Personal import schemas from typing import List, Optional @@ -72,3 +72,50 @@ def delete_car(db: Session, car_id: int) -> bool: db.delete(db_car) db.commit() return True + +# Персонал --------- + +def get_personal(db: Session, personal_id: int) -> Optional[Personal]: + return db.query(Personal).filter(Personal.id == personal_id).first() + +def get_all_personal(db: Session, skip: int = 0, limit: int = 100) -> List[Personal]: + return db.query(Personal).offset(skip).limit(limit).all() + +def get_personal_count(db: Session) -> int: + return db.query(Personal).count() + +def create_personal(db: Session, personal: schemas.PersonalCreate) -> Personal: + db_personal = Personal( + name=personal.name, + surname=personal.surname, + role=personal.role, + photo=personal.photo + ) + db.add(db_personal) + db.commit() + db.refresh(db_personal) + return db_personal + +def update_personal(db: Session, personal_id: int, personal_update: schemas.PersonalUpdate) -> Optional[Personal]: + db_personal = get_personal(db, personal_id) + if not db_personal: + return None + + update_data = personal_update.model_dump(exclude_unset=True) + + # Обновление полей + for key, value in update_data.items(): + setattr(db_personal, key, value) + + db.commit() + db.refresh(db_personal) + return db_personal + +def delete_personal(db: Session, personal_id: int) -> bool: + db_personal = get_personal(db, personal_id) + if not db_personal: + return False + + db.delete(db_personal) + db.commit() + return True \ No newline at end of file diff --git a/main.py b/main.py index 49f4820..2339c44 100644 --- a/main.py +++ b/main.py @@ -157,3 +157,129 @@ def delete_car( if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=3000) + +# Персонал --------- + +@app.get("/personal", response_model=schemas.PersonalListResponse) +def get_all_personal( + skip: int = Query(0, description="Количество пропускаемых записей"), + limit: int = Query(100, description="Максимальное количество записей"), + db: Session = Depends(get_db) +): + staff = crud.get_all_personal(db, skip=skip, limit=limit) + total = crud.get_personal_count(db) + return {"staff": staff, "total": total} + +@app.get("/personal/{personal_id}", response_model=schemas.PersonalResponse) +def get_personal( + personal_id: int = Path(..., description="ID сотрудника", gt=0), + db: Session = Depends(get_db) +): + personal = crud.get_personal(db, personal_id=personal_id) + if personal is None: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="Сотрудник не найден" + ) + return {"personal": personal} + +@app.post("/personal", response_model=schemas.PersonalResponse, status_code=status.HTTP_201_CREATED) +async def create_personal( + personal_data: str = Form(..., description="Данные сотрудника в JSON формате"), + photo: UploadFile = File(None, description="Фотография сотрудника"), + db: Session = Depends(get_db) +): + try: + # Преобразуем строку JSON в словарь + personal_dict = json.loads(personal_data) + + # Загружаем фото, если оно предоставлено + if photo: + photo_path = await save_image(photo) + personal_dict["photo"] = photo_path + + # Создаем объект Pydantic для валидации данных + personal = schemas.PersonalCreate(**personal_dict) + + # Создаем запись в БД + db_personal = crud.create_personal(db=db, personal=personal) + return {"personal": db_personal} + except ValueError as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=str(e) + ) + except json.JSONDecodeError: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Неверный формат JSON" + ) + +@app.put("/personal/{personal_id}", response_model=schemas.PersonalResponse) +async def update_personal( + personal_id: int = Path(..., description="ID сотрудника", gt=0), + personal_data: str = Form(None, description="Данные сотрудника в JSON формате"), + photo: UploadFile = File(None, description="Фотография сотрудника"), + db: Session = Depends(get_db) +): + # Проверяем существование сотрудника + existing_personal = crud.get_personal(db, personal_id=personal_id) + if existing_personal is None: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="Сотрудник не найден" + ) + + try: + # Преобразуем строку JSON в словарь, если она предоставлена + personal_dict = {} + if personal_data: + personal_dict = json.loads(personal_data) + + # Загружаем новую фотографию, если она предоставлена + if photo: + # Удаляем старую фотографию, если есть + if existing_personal.photo: + delete_image(existing_personal.photo) + + # Сохраняем новую фотографию + photo_path = await save_image(photo) + personal_dict["photo"] = photo_path + + # Создаем объект Pydantic для валидации данных + personal_update = schemas.PersonalUpdate(**personal_dict) + + # Обновляем запись в БД + updated_personal = crud.update_personal(db=db, personal_id=personal_id, personal_update=personal_update) + return {"personal": updated_personal} + except ValueError as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=str(e) + ) + except json.JSONDecodeError: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Неверный формат JSON" + ) + +@app.delete("/personal/{personal_id}", status_code=status.HTTP_204_NO_CONTENT) +def delete_personal( + personal_id: int = Path(..., description="ID сотрудника", gt=0), + db: Session = Depends(get_db) +): + # Получаем сотрудника перед удалением + personal = crud.get_personal(db, personal_id=personal_id) + if personal is None: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="Сотрудник не найден" + ) + + # Удаляем фотографию, если есть + if personal.photo: + delete_image(personal.photo) + + # Удаляем запись из БД + crud.delete_personal(db=db, personal_id=personal_id) + return None diff --git a/models.py b/models.py index bf2d032..406d9da 100644 --- a/models.py +++ b/models.py @@ -35,3 +35,12 @@ class Car(Base): electric_motor_power = Column(Integer, nullable=True) # мощность электродвигателя hybrid_type = Column(Enum(HybridType), default=HybridType.NONE) # тип гибрида power_ratio = Column(Enum(PowerRatio), default=PowerRatio.NA) # соотношение мощности + +class Personal(Base): + __tablename__ = "personal" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String, index=True) # ФИО сотрудника + surname = Column(String, index=True) # ФИО сотрудника + role = Column(String) # Должность (произвольная строка) + photo = Column(String, nullable=True) # путь к фотографии diff --git a/schemas.py b/schemas.py index 782cfc4..ee8f97b 100644 --- a/schemas.py +++ b/schemas.py @@ -65,3 +65,33 @@ class CarResponse(BaseModel): class CarsResponse(BaseModel): cars: List[Car] total: int + +# Персонал --------- + +class PersonalBase(BaseModel): + name: str + surname: str + role: str + photo: Optional[str] = None + +class PersonalCreate(PersonalBase): + pass + +class PersonalUpdate(BaseModel): + name: Optional[str] = None + surname: Optional[str] = None + role: Optional[str] = None + photo: Optional[str] = None + +class Personal(PersonalBase): + id: int + + class Config: + from_attributes = True + +class PersonalResponse(BaseModel): + personal: Personal + +class PersonalListResponse(BaseModel): + staff: List[Personal] + total: int \ No newline at end of file