174 lines
7.6 KiB
Python
174 lines
7.6 KiB
Python
import datetime
|
||
from typing import Union
|
||
|
||
from fastapi import HTTPException
|
||
from sqlalchemy import select, update
|
||
from sqlalchemy.orm import joinedload, selectinload, noload
|
||
|
||
from models import Client, ClientDetails, User, ResidualPallet, ResidualBox, ResidualProduct, Product
|
||
from schemas.client import *
|
||
from services.auth import AuthService
|
||
from services.base import BaseService
|
||
|
||
|
||
class ClientService(BaseService):
|
||
|
||
async def get_by_name(self, name: str) -> Union[Client, None]:
|
||
client = await self.session.scalar(select(Client).where(Client.name == name))
|
||
return client
|
||
|
||
async def _get_by_id(self, client_id: int) -> Union[Client, None]:
|
||
return await self.session.get(Client, client_id)
|
||
|
||
async def get_by_id(self, client_id: int) -> ClientGetResponse:
|
||
stmt = (
|
||
select(Client)
|
||
.options(
|
||
selectinload(Client.pallets)
|
||
.selectinload(ResidualPallet.residual_products)
|
||
.selectinload(ResidualProduct.product)
|
||
.noload(Product.barcodes),
|
||
selectinload(Client.pallets)
|
||
.selectinload(ResidualPallet.boxes)
|
||
.selectinload(ResidualBox.residual_products)
|
||
.selectinload(ResidualProduct.product)
|
||
.noload(Product.barcodes),
|
||
selectinload(Client.boxes)
|
||
.selectinload(ResidualBox.residual_products)
|
||
.selectinload(ResidualProduct.product)
|
||
.noload(Product.barcodes),
|
||
)
|
||
.where(Client.id == client_id)
|
||
)
|
||
client = (await self.session.execute(stmt)).one_or_none()
|
||
client = client[0] if client else None
|
||
if not client:
|
||
raise HTTPException(status_code=404, detail="Клиент не найден")
|
||
return ClientGetResponse(client=client)
|
||
|
||
async def get_details_by_client_id(self, client_id: int) -> Union[ClientDetails, None]:
|
||
details = await self.session.scalar(select(ClientDetails).where(ClientDetails.client_id == client_id))
|
||
return details
|
||
|
||
async def get_all(self) -> ClientGetAllResponse:
|
||
clients_query = await self.session.scalars(
|
||
select(Client)
|
||
.options(
|
||
joinedload(Client.details),
|
||
noload(Client.products),
|
||
noload(Client.pallets),
|
||
noload(Client.boxes),
|
||
noload(Client.chat)
|
||
)
|
||
)
|
||
clients = clients_query.all()
|
||
result = []
|
||
for client in clients:
|
||
result.append(ClientSchema.model_validate(client))
|
||
return ClientGetAllResponse(clients=result)
|
||
|
||
async def create_details(self, user, client: Client, request: ClientDetailsSchema):
|
||
dict_data = request.dict()
|
||
dict_data['client_id'] = client.id
|
||
dict_data['last_modified_at'] = datetime.datetime.now()
|
||
dict_data['modified_by_user_id'] = user.id
|
||
details = ClientDetails(**dict_data)
|
||
self.session.add(details)
|
||
await self.session.flush()
|
||
return details
|
||
|
||
async def update_details(self, user: User, client: Client, request: ClientDetailsSchema) -> ClientDetails:
|
||
details = await self.get_details_by_client_id(client_id=client.id)
|
||
if not details:
|
||
details = await self.create_details(user, client, request)
|
||
dict_data = request.dict()
|
||
dict_data['last_modified_at'] = datetime.datetime.now()
|
||
dict_data['modified_by_user_id'] = user.id
|
||
await self.session.execute(update(ClientDetails).where(ClientDetails.id == details.id).values(**dict_data))
|
||
await self.session.flush()
|
||
|
||
async def create_client_raw(self,
|
||
user: User,
|
||
client_name: str,
|
||
details_schema: ClientDetailsSchema) -> Client:
|
||
client = Client(name=client_name, created_at=datetime.datetime.now())
|
||
self.session.add(client)
|
||
await self.session.flush()
|
||
|
||
await self.update_details(user, client, details_schema)
|
||
|
||
return client
|
||
|
||
async def search_clients(self, request: ClientSearchRequest) -> ClientSearchResponse:
|
||
query = await self.session.scalars(select(Client)
|
||
.where(Client.name.ilike(f'%{request.name}%'))
|
||
.options(joinedload(Client.details)))
|
||
clients = []
|
||
for client in query.all():
|
||
clients.append(ClientSchema.model_validate(client))
|
||
return ClientSearchResponse(clients=clients)
|
||
|
||
async def create(self, request: ClientCreateRequest, user: User) -> ClientCreateResponse:
|
||
try:
|
||
client = await self.get_by_name(request.data.name)
|
||
if client:
|
||
return ClientCreateResponse(ok=False, message='Клиент с таким именем уже существует')
|
||
client_dict = request.data.dict()
|
||
del client_dict['id']
|
||
del client_dict['details']
|
||
del client_dict['barcode_template']
|
||
if request.data.barcode_template:
|
||
client_dict['barcode_template_id'] = request.data.barcode_template.id
|
||
client_dict['created_at'] = datetime.datetime.now()
|
||
|
||
client = Client(**client_dict)
|
||
self.session.add(client)
|
||
await self.session.flush()
|
||
await self.create_details(user, client, request.data.details)
|
||
|
||
# await self.create_client_raw(user, request.data.name, request.data.details)
|
||
await self.session.commit()
|
||
return ClientCreateResponse(ok=True, message='Client created')
|
||
except Exception as e:
|
||
return ClientCreateResponse(ok=False, message=str(e))
|
||
|
||
async def update(self, request: ClientUpdateRequest, user: User) -> ClientUpdateResponse:
|
||
try:
|
||
client = await self._get_by_id(request.data.id)
|
||
if not client:
|
||
return ClientUpdateResponse(ok=False, message='Клиент не найден')
|
||
request_dict = request.data.dict()
|
||
del request_dict['id']
|
||
del request_dict['details']
|
||
del request_dict['barcode_template']
|
||
del request_dict['chat']
|
||
if request.data.barcode_template:
|
||
request_dict['barcode_template_id'] = request.data.barcode_template.id
|
||
stmt = (
|
||
update(Client)
|
||
.where(Client.id == client.id)
|
||
.values(**request_dict)
|
||
)
|
||
await self.session.execute(stmt)
|
||
await self.update_details(user, client, request.data.details)
|
||
await self.session.commit()
|
||
return ClientUpdateResponse(ok=True, message='Клиент обновлен')
|
||
except Exception as e:
|
||
return ClientUpdateResponse(ok=False, message=str(e))
|
||
|
||
async def delete(self, request: ClientDeleteRequest) -> ClientDeleteResponse:
|
||
try:
|
||
client = await self._get_by_id(request.client_id)
|
||
if not client:
|
||
return ClientDeleteResponse(ok=False, message='Клиент не найден')
|
||
await self.session.delete(client)
|
||
await self.session.commit()
|
||
return ClientDeleteResponse(ok=True, message='Клиент удален')
|
||
except Exception as e:
|
||
return ClientDeleteResponse(ok=False, message=str(e))
|
||
|
||
async def create_guest_url(self, client_id: int) -> CreateGuestUrlResponse:
|
||
access_token = AuthService(self.session).create_client_guest_token(client_id)
|
||
url = f"leads?accessToken={access_token}"
|
||
return CreateGuestUrlResponse(ok=True, message='Ссылка успешно создана!', url=url)
|