v0.1
This commit is contained in:
125
services/deal.py
125
services/deal.py
@@ -21,38 +21,47 @@ class DealService(BaseService):
|
||||
async def _get_deal_by_id(self, deal_id) -> Union[Deal, None]:
|
||||
return await self.session.get(Deal, deal_id)
|
||||
|
||||
async def _get_rank(self):
|
||||
query = await self.session.execute(select(Deal.rank).order_by(Deal.rank.desc()))
|
||||
result = query.scalar_one_or_none()
|
||||
if not result:
|
||||
return str(lexorank.Bucket.BUCEKT_0.next())
|
||||
rank = lexorank.parse(result)
|
||||
return str(rank.next())
|
||||
async def _get_rank_for_deal(self, deal_status: DealStatus) -> int:
|
||||
deal_query = await self.session.execute(
|
||||
select(Deal).where(Deal.current_status == deal_status).order_by(Deal.lexorank.desc()).limit(1))
|
||||
deal = deal_query.scalar_one_or_none()
|
||||
if not deal:
|
||||
prev = lexorank.middle(lexorank.Bucket.BUCEKT_0)
|
||||
return str(prev.next())
|
||||
return str(lexorank.parse(deal.lexorank).next())
|
||||
|
||||
async def change_status(self, deal: Deal,
|
||||
status: DealStatus,
|
||||
user: User,
|
||||
deadline: datetime.datetime = None) -> DealStatusHistory:
|
||||
deadline = deadline
|
||||
status_change = DealStatusHistory(
|
||||
deal_id=deal.id,
|
||||
user_id=user.id,
|
||||
changed_at=datetime.datetime.now(),
|
||||
from_status=deal.current_status,
|
||||
to_status=status,
|
||||
next_status_deadline=deadline
|
||||
)
|
||||
self.session.add(status_change)
|
||||
deadline: datetime.datetime = None,
|
||||
rank=None,
|
||||
comment: str = '') -> DealStatusHistory:
|
||||
if not deal.current_status == status:
|
||||
deadline = deadline
|
||||
status_change = DealStatusHistory(
|
||||
deal_id=deal.id,
|
||||
user_id=user.id,
|
||||
changed_at=datetime.datetime.now(),
|
||||
from_status=deal.current_status,
|
||||
to_status=status,
|
||||
next_status_deadline=deadline,
|
||||
comment=comment
|
||||
)
|
||||
self.session.add(status_change)
|
||||
deal.current_status = status
|
||||
if not rank:
|
||||
rank = await self._get_rank_for_deal(status)
|
||||
if rank:
|
||||
deal.lexorank = rank
|
||||
await self.session.flush()
|
||||
return status_change
|
||||
|
||||
async def create(self, request: DealCreateRequest, user: User) -> DealCreateResponse:
|
||||
rank = await self._get_rank()
|
||||
rank = self._get_rank_for_deal(DealStatus.CREATED)
|
||||
deal = Deal(
|
||||
name=request.name,
|
||||
created_at=datetime.datetime.now(),
|
||||
current_status=DealStatus.CREATED,
|
||||
rank=rank
|
||||
lexorank=rank
|
||||
)
|
||||
self.session.add(deal)
|
||||
await self.session.flush()
|
||||
@@ -63,6 +72,14 @@ class DealService(BaseService):
|
||||
await self.session.commit()
|
||||
return DealCreateResponse(ok=True)
|
||||
|
||||
async def delete(self, request: DealDeleteRequest) -> DealDeleteResponse:
|
||||
deal = await self._get_deal_by_id(request.deal_id)
|
||||
if not deal:
|
||||
return DealDeleteResponse(ok=False, message="Сделка не найдена")
|
||||
deal.is_deleted = True
|
||||
await self.session.commit()
|
||||
return DealDeleteResponse(ok=True, message="Сделка успешно удалена")
|
||||
|
||||
async def quick_create(self, request: DealQuickCreateRequest, user: User) -> DealQuickCreateResponse:
|
||||
client_service = ClientService(self.session)
|
||||
client = await client_service.get_by_name(request.client_name)
|
||||
@@ -72,13 +89,13 @@ class DealService(BaseService):
|
||||
request.client_name,
|
||||
ClientDetailsSchema(address=request.client_address))
|
||||
await client_service.update_details(user, client, ClientDetailsSchema(address=request.client_address))
|
||||
rank = await self._get_rank()
|
||||
rank = await self._get_rank_for_deal(DealStatus.CREATED)
|
||||
deal = Deal(
|
||||
name=request.name,
|
||||
created_at=datetime.datetime.now(),
|
||||
client_id=client.id,
|
||||
current_status=DealStatus.CREATED,
|
||||
rank=rank
|
||||
lexorank=rank
|
||||
)
|
||||
self.session.add(deal)
|
||||
await self.session.flush()
|
||||
@@ -108,10 +125,11 @@ class DealService(BaseService):
|
||||
q = (
|
||||
select(
|
||||
Deal,
|
||||
func.coalesce(service_subquery.c.total_price, 0)
|
||||
)
|
||||
.order_by(
|
||||
Deal.rank.desc()
|
||||
func.coalesce(service_subquery.c.total_price, 0),
|
||||
func.row_number().over(
|
||||
partition_by=Deal.current_status,
|
||||
order_by=Deal.lexorank
|
||||
).label('rank')
|
||||
)
|
||||
.options(
|
||||
selectinload(Deal.status_history),
|
||||
@@ -126,18 +144,20 @@ class DealService(BaseService):
|
||||
)
|
||||
deals_query = await self.session.execute(q)
|
||||
summaries = []
|
||||
for deal, total_price in deals_query.all():
|
||||
for deal, total_price, rank in deals_query.all():
|
||||
deal: Deal
|
||||
last_status: DealStatusHistory = max(deal.status_history, key=lambda status: status.changed_at)
|
||||
deadline = last_status.next_status_deadline
|
||||
summaries.append(
|
||||
DealSummary(
|
||||
id=deal.id,
|
||||
client_name=deal.client.name,
|
||||
name=deal.name,
|
||||
changed_at=last_status.changed_at,
|
||||
deadline=deadline,
|
||||
status=last_status.to_status,
|
||||
total_price=total_price,
|
||||
rank=deal.rank
|
||||
rank=rank
|
||||
)
|
||||
)
|
||||
return DealSummaryResponse(summaries=summaries)
|
||||
@@ -190,8 +210,51 @@ class DealService(BaseService):
|
||||
await self.session.rollback()
|
||||
return DealUpdateGeneralInfoResponse(ok=False, message=str(e))
|
||||
|
||||
async def reorder(self, request: DealSummaryReorderRequest, user: User) -> DealSummaryReorderResponse:
|
||||
pass
|
||||
async def reorder(self, request: DealSummaryReorderRequest, user: User) -> DealSummaryResponse:
|
||||
deal: Deal = await self.session.scalar(select(Deal).where(Deal.id == request.deal_id))
|
||||
if request.index == 1:
|
||||
request.index = 0
|
||||
is_first = request.index == 0
|
||||
stmt = (
|
||||
select(Deal)
|
||||
.where(Deal.current_status == request.status,
|
||||
Deal.id != request.deal_id)
|
||||
.order_by(Deal.lexorank)
|
||||
.offset(max([request.index - 2, 0]))
|
||||
.limit(2 if not is_first else 1)
|
||||
|
||||
)
|
||||
query = await self.session.execute(stmt)
|
||||
boundaries = query.scalars().all()
|
||||
top_boundary: Union[Deal, None] = boundaries[0] if not is_first else None
|
||||
bottom_boundary: Union[Deal, None] = boundaries[1] if len(boundaries) == 2 else None
|
||||
if top_boundary:
|
||||
print(top_boundary.name)
|
||||
if bottom_boundary:
|
||||
print(bottom_boundary.name)
|
||||
# working when between two elements
|
||||
if top_boundary and bottom_boundary:
|
||||
top_lexorank = lexorank.parse(top_boundary.lexorank)
|
||||
bottom_lexorank = lexorank.parse(bottom_boundary.lexorank)
|
||||
new_rank = lexorank.between(top_lexorank, bottom_lexorank)
|
||||
|
||||
# working when at the bottom
|
||||
elif top_boundary and not bottom_boundary:
|
||||
new_rank = lexorank.parse(top_boundary.lexorank).next()
|
||||
# working when at the top
|
||||
elif bottom_boundary and not top_boundary:
|
||||
new_rank = lexorank.parse(bottom_boundary.lexorank).prev()
|
||||
elif not top_boundary and not bottom_boundary and len(boundaries) > 0:
|
||||
new_rank = lexorank.parse(boundaries[0].lexorank).prev()
|
||||
else:
|
||||
new_rank = lexorank.middle(lexorank.Bucket.BUCEKT_0)
|
||||
|
||||
await self.change_status(deal, request.status, user,
|
||||
deadline=request.deadline,
|
||||
comment=request.comment,
|
||||
rank=str(new_rank))
|
||||
await self.session.commit()
|
||||
return await self.get_summary()
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
Reference in New Issue
Block a user