This commit is contained in:
2024-04-11 07:57:08 +03:00
parent 93eb6ae6b7
commit 7f302acdb5
8 changed files with 267 additions and 26 deletions

View File

@@ -6,7 +6,7 @@ import routers
origins = [ origins = [
'http://localhost:5173' 'http://localhost:5173'
] ]
app = FastAPI() app = FastAPI(separate_input_output_schemas=False)
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,

View File

@@ -33,7 +33,7 @@ class Deal(BaseModel):
is_completed = Column(Boolean, nullable=False, server_default='0', default=False, comment='Завершена') is_completed = Column(Boolean, nullable=False, server_default='0', default=False, comment='Завершена')
services = relationship('DealService', back_populates='deal') services = relationship('DealService', back_populates='deal')
products = relationship('DealProduct', back_populates='deal')
class DealStatusHistory(BaseModel): class DealStatusHistory(BaseModel):
__tablename__ = 'deals_status_history' __tablename__ = 'deals_status_history'

View File

@@ -13,3 +13,15 @@ class DealService(BaseModel):
service = relationship('Service') service = relationship('Service')
quantity = Column(Integer, nullable=False, comment='Кол-во услуги') quantity = Column(Integer, nullable=False, comment='Кол-во услуги')
class DealProduct(BaseModel):
__tablename__ = 'deal_products'
deal_id = Column(Integer, ForeignKey('deals.id'), nullable=False, comment='ID Сделки', primary_key=True)
deal = relationship('Deal', back_populates='products')
product_id = Column(Integer, ForeignKey('products.id'), nullable=False, comment='ID Продукта', primary_key=True)
product = relationship('Product')
quantity = Column(Integer, nullable=False, comment='Кол-во продукта')

View File

@@ -53,11 +53,82 @@ async def get_summary(
@deal_router.post( @deal_router.post(
'/services/add', '/services/add/multiple',
response_model=DealAddServicesResponse, response_model=DealAddServicesResponse,
operation_id='addMultipleDealServices'
) )
async def services_add( async def services_add(
request: DealAddServicesRequest, request: DealAddServicesRequest,
session: Annotated[AsyncSession, Depends(get_session)] session: Annotated[AsyncSession, Depends(get_session)]
): ):
return await DealService(session).add_services(request) return await DealService(session).add_services(request)
@deal_router.post(
'/services/add',
response_model=DealAddServiceResponse,
operation_id='addDealService'
)
async def services_add(
request: DealAddServiceRequest,
session: Annotated[AsyncSession, Depends(get_session)]
):
return await DealService(session).add_service(request)
@deal_router.post(
'/services/update-quantity',
response_model=DealUpdateServiceQuantityResponse,
operation_id='updateDealServiceQuantity'
)
async def services_update(
request: DealUpdateServiceQuantityRequest,
session: Annotated[AsyncSession, Depends(get_session)]
):
return await DealService(session).update_service_quantity(request)
@deal_router.post(
'/services/delete',
response_model=DealDeleteServiceResponse,
operation_id='deleteDealService'
)
async def services_delete(
request: DealDeleteServiceRequest,
session: Annotated[AsyncSession, Depends(get_session)]
):
return await DealService(session).delete_service(request)
@deal_router.post(
'/services/delete/multiple',
response_model=DealDeleteServicesResponse,
operation_id='deleteMultipleDealServices'
)
async def services_delete(
request: DealDeleteServicesRequest,
session: Annotated[AsyncSession, Depends(get_session)]
):
return await DealService(session).delete_services(request)
@deal_router.get(
'/get-all',
response_model=DealGetAllResponse,
operation_id='getAllDeals'
)
async def get_all(
session: Annotated[AsyncSession, Depends(get_session)]
):
return await DealService(session).get_all()
# endpoint to get deal by id
@deal_router.get(
'/get/{deal_id}',
response_model=DealSchema,
operation_id='getDealById'
)
async def get_deal_by_id(
deal_id: int,
session: Annotated[AsyncSession, Depends(get_session)]
):
return await DealService(session).get_by_id(deal_id)

View File

@@ -3,6 +3,7 @@ from typing import List
from schemas.base import CustomModelCamel, OkMessageSchema from schemas.base import CustomModelCamel, OkMessageSchema
# region Entities
class ClientDetailsSchema(CustomModelCamel): class ClientDetailsSchema(CustomModelCamel):
address: str | None = None address: str | None = None
phone_number: str | None = None phone_number: str | None = None
@@ -16,19 +17,37 @@ class ClientSchema(CustomModelCamel):
details: ClientDetailsSchema | None = None details: ClientDetailsSchema | None = None
# endregion
# region Requests
class ClientSearchRequest(CustomModelCamel): class ClientSearchRequest(CustomModelCamel):
name: str name: str
class ClientSearchResponse(CustomModelCamel):
clients: List[ClientSchema]
class ClientUpdateDetailsRequest(CustomModelCamel): class ClientUpdateDetailsRequest(CustomModelCamel):
client_id: int client_id: int
details: ClientDetailsSchema details: ClientDetailsSchema
class ClientCreateRequest(CustomModelCamel):
data: ClientSchema
class ClientUpdateRequest(CustomModelCamel):
data: ClientSchema
class ClientDeleteRequest(CustomModelCamel):
client_id: int
# endregion
# region Responses
class ClientSearchResponse(CustomModelCamel):
clients: List[ClientSchema]
class ClientUpdateDetailsResponse(CustomModelCamel): class ClientUpdateDetailsResponse(CustomModelCamel):
ok: bool ok: bool
@@ -41,21 +60,10 @@ class ClientCreateResponse(OkMessageSchema):
pass pass
class ClientCreateRequest(CustomModelCamel):
data: ClientSchema
class ClientUpdateRequest(CustomModelCamel):
data: ClientSchema
class ClientUpdateResponse(OkMessageSchema): class ClientUpdateResponse(OkMessageSchema):
pass pass
class ClientDeleteRequest(CustomModelCamel):
client_id: int
class ClientDeleteResponse(OkMessageSchema): class ClientDeleteResponse(OkMessageSchema):
pass pass
# endregion

View File

@@ -1,8 +1,9 @@
import datetime import datetime
from typing import List from typing import List
from schemas.base import CustomModelCamel from schemas.base import CustomModelCamel, OkMessageSchema
from schemas.client import ClientSchema from schemas.client import ClientSchema
from schemas.service import ServiceSchema
# region Entities # region Entities
@@ -23,10 +24,20 @@ class DealSummary(CustomModelCamel):
class DealServiceSchema(CustomModelCamel): class DealServiceSchema(CustomModelCamel):
id: int service: ServiceSchema
quantity: int quantity: int
class DealSchema(CustomModelCamel):
id: int
name: str
client_id: int
created_at: datetime.datetime
current_status: int
services: List[DealServiceSchema]
# total_price: int
# endregion Entities # endregion Entities
# region Requests # region Requests
@@ -56,6 +67,36 @@ class DealAddServicesRequest(CustomModelCamel):
services: list[DealServiceSchema] services: list[DealServiceSchema]
class DealGetAllResponse(CustomModelCamel):
deals: List[DealSchema]
class DealUpdateServiceQuantityRequest(CustomModelCamel):
deal_id: int
service_id: int
quantity: int
class DealAddServiceRequest(CustomModelCamel):
deal_id: int
service_id: int
quantity: int
class DealDeleteServiceRequest(CustomModelCamel):
deal_id: int
service_id: int
class DealDeleteServicesResponse(OkMessageSchema):
pass
class DealDeleteServicesRequest(CustomModelCamel):
deal_id: int
service_ids: List[int]
# endregion Requests # endregion Requests
# region Responses # region Responses
@@ -79,4 +120,17 @@ class DealSummaryResponse(CustomModelCamel):
class DealAddServicesResponse(CustomModelCamel): class DealAddServicesResponse(CustomModelCamel):
ok: bool ok: bool
message: str message: str
class DealUpdateServiceQuantityResponse(CustomModelCamel):
ok: bool
message: str
class DealAddServiceResponse(OkMessageSchema):
pass
class DealDeleteServiceResponse(OkMessageSchema):
pass
# endregion Responses # endregion Responses

View File

@@ -1,14 +1,12 @@
import datetime import datetime
from typing import Union, Annotated from typing import Union
from fastapi import Depends
from sqlalchemy import select, update from sqlalchemy import select, update
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from models import Client, ClientDetails, User from models import Client, ClientDetails, User
from services.auth import get_current_user
from services.base import BaseService
from schemas.client import * from schemas.client import *
from services.base import BaseService
class ClientService(BaseService): class ClientService(BaseService):

View File

@@ -1,6 +1,6 @@
import models.secondary import models.secondary
from typing import Union from typing import Union
import models.deal
from fastapi import HTTPException from fastapi import HTTPException
from sqlalchemy import select, func from sqlalchemy import select, func
from sqlalchemy.orm import joinedload, selectinload from sqlalchemy.orm import joinedload, selectinload
@@ -156,3 +156,101 @@ class DealService(BaseService):
) )
await self.session.commit() await self.session.commit()
return DealAddServicesResponse(ok=True, message='Услуги успешно добавлены') return DealAddServicesResponse(ok=True, message='Услуги успешно добавлены')
async def get_all(self) -> DealGetAllResponse:
deals_query = await self.session.scalars(select(Deal).options(joinedload(Deal.client)))
deals = deals_query.all()
result = []
for deal in deals:
result.append(DealSchema.model_validate(deal))
return DealGetAllResponse(deals=result)
async def get_by_id(self, deal_id: int) -> DealSchema:
deal = await self.session.scalar(
select(Deal)
.options(
joinedload(Deal.client),
selectinload(Deal.services)
.joinedload(models.secondary.DealService.service)
.joinedload(Service.category))
.where(Deal.id == deal_id)
)
if not deal:
raise HTTPException(status_code=404, detail="Сделка не найдена")
return DealSchema.model_validate(deal)
async def update_service_quantity(self,
request: DealUpdateServiceQuantityRequest) -> DealUpdateServiceQuantityResponse:
try:
deal_service = await self.session.scalar(
select(models.secondary.DealService)
.where(models.secondary.DealService.deal_id == request.deal_id,
models.secondary.DealService.service_id == request.service_id)
)
if not deal_service:
raise HTTPException(status_code=404, detail="Сделка не найдена")
deal_service.quantity = request.quantity
await self.session.commit()
return DealUpdateServiceQuantityResponse(ok=True, message='Количество успешно обновлено')
except Exception as e:
await self.session.rollback()
return DealUpdateServiceQuantityResponse(ok=False, message=str(e))
async def add_service(self, request: DealAddServiceRequest) -> DealAddServiceResponse:
try:
deal = await self.session.scalar(select(Deal).where(Deal.id == request.deal_id))
if not deal:
raise HTTPException(status_code=404, detail="Сделка не найдена")
service = await self.session.scalar(select(Service).where(Service.id == request.service_id))
if not service:
raise HTTPException(status_code=404, detail="Услуга не найдена")
# Preventing duplicates
deal_service = await self.session.scalar(
select(models.secondary.DealService)
.where(models.secondary.DealService.deal_id == request.deal_id,
models.secondary.DealService.service_id == request.service_id)
)
if deal_service:
raise HTTPException(status_code=400, detail="Услуга уже добавлена")
deal_service = models.secondary.DealService(
deal_id=request.deal_id,
service_id=request.service_id,
quantity=request.quantity
)
self.session.add(deal_service)
await self.session.commit()
return DealAddServiceResponse(ok=True, message='Услуга успешно добавлена')
except Exception as e:
await self.session.rollback()
return DealAddServiceResponse(ok=False, message=str(e))
async def delete_service(self, request: DealDeleteServiceRequest) -> DealDeleteServiceResponse:
try:
deal_service = await self.session.scalar(
select(models.secondary.DealService)
.where(models.secondary.DealService.deal_id == request.deal_id,
models.secondary.DealService.service_id == request.service_id)
)
if not deal_service:
raise HTTPException(status_code=404, detail="Сделка не найдена")
await self.session.delete(deal_service)
await self.session.commit()
return DealDeleteServiceResponse(ok=True, message='Услуга успешно удалена')
except Exception as e:
await self.session.rollback()
return DealDeleteServiceResponse(ok=False, message=str(e))
async def delete_services(self, request: DealDeleteServicesRequest) -> DealDeleteServicesResponse:
try:
deal_services = await self.session.scalars(
select(models.secondary.DealService)
.where(models.secondary.DealService.deal_id == request.deal_id,
models.secondary.DealService.service_id.in_(request.service_ids))
)
for deal_service in deal_services:
await self.session.delete(deal_service)
await self.session.commit()
return DealDeleteServicesResponse(ok=True, message='Услуги успешно удалены')
except Exception as e:
await self.session.rollback()
return DealDeleteServicesResponse(ok=False, message=str(e))