import datetime from typing import Type, Union from sqlalchemy import select from sqlalchemy.orm import joinedload, selectinload from models import User, Deal from models.deal import * from schemas.client import ClientDetailsSchema from schemas.deal import * from services.base import BaseService from services.client import ClientService 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 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) await self.session.flush() return status_change async def create(self, request: DealCreateRequest, user: User) -> DealCreateResponse: deal = Deal( name=request.name, created_at=datetime.datetime.now(), current_status=DealStatus.CREATED ) self.session.add(deal) await self.session.flush() # Append status history await self.change_status(deal, DealStatus.AWAITING_ACCEPTANCE, user) await self.session.commit() return DealCreateResponse(ok=True) 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) if not client: client = await client_service.create_client_raw( user, request.client_name, ClientDetailsSchema(address=request.client_address)) await client_service.update_details(user, client, ClientDetailsSchema(address=request.client_address)) deal = Deal( name=request.name, created_at=datetime.datetime.now(), client_id=client.id, current_status=DealStatus.CREATED ) self.session.add(deal) await self.session.flush() await self.change_status(deal, DealStatus.AWAITING_ACCEPTANCE, user, deadline=request.acceptance_date) await self.session.commit() return DealQuickCreateResponse(deal_id=deal.id) async def change_status_manual(self, request: DealChangeStatusRequest, user: User) -> DealChangeStatusResponse: # Changing current status deal = await self._get_deal_by_id(request.deal_id) if not deal: return DealChangeStatusResponse(ok=False) await self.change_status(deal, DealStatus(request.new_status), user) await self.session.commit() return DealChangeStatusResponse(ok=True) async def get_summary(self) -> DealSummaryResponse: deals_query = await self.session.scalars(select(Deal) .options(selectinload(Deal.status_history), joinedload(Deal.client)) .where(Deal.is_deleted == False, Deal.is_completed == False)) summaries = [] for deal in deals_query.all(): deal: Deal last_status: DealStatusHistory = max(deal.status_history, key=lambda status: status.changed_at) summaries.append( DealSummary( id=deal.id, client_name=deal.client.name, name=deal.name, changed_at=last_status.changed_at, status=last_status.to_status ) ) return DealSummaryResponse(summaries=summaries)