Files
Fulfillment-Backend/services/client.py

174 lines
7.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)