import datetime from typing import List from fastapi import HTTPException from sqlalchemy import select from starlette import status import backend.config from external.billing import BillingClient, CreateBillingRequestValue, CreateBillRequestSchema, CreateBillRequestItems, \ BillStatusUpdateRequest, NotificationChannel, NotifyReceivedBillRequestSchema, BillPaymentInfo from models import DealBillRequest, Deal from schemas.billing import * from services.base import BaseService from services.deal import DealService class BillingService(BaseService): async def _process_update_details( self, request: BillStatusUpdateRequest ): billing_client = BillingClient(backend.config.BILLING_API_KEY) notify_received_request = NotifyReceivedBillRequestSchema( listener_transaction_id=request.listener_transaction_id, channel=NotificationChannel.PAYMENT_DETAILS, received=True ) response = await billing_client.notify_received(notify_received_request) deal_bill_request = await self._get_deal_bill_by_id(request.listener_transaction_id) if not response.ok: return deal_bill_request.pdf_url = request.info.pdf_url deal_bill_request.invoice_number = request.info.invoice_number await self.session.commit() async def _process_update_verification( self, request: BillStatusUpdateRequest ): billing_client = BillingClient(backend.config.BILLING_API_KEY) notify_received_request = NotifyReceivedBillRequestSchema( listener_transaction_id=request.listener_transaction_id, channel=NotificationChannel.PAYMENT_VERIFICATION, received=True ) response = await billing_client.notify_received(notify_received_request) if not response.ok: return deal_bill_request = await self._get_deal_bill_by_id(request.listener_transaction_id) if not deal_bill_request: return deal_bill_request.paid = request.info.payed await self.session.commit() async def process_update( self, request: BillStatusUpdateRequest ): if request.channel == NotificationChannel.PAYMENT_DETAILS: await self._process_update_details(request) elif request.channel == NotificationChannel.PAYMENT_VERIFICATION: await self._process_update_verification(request) async def create_deal_billing(self, user, request: CreateDealBillRequest) -> CreateDealBillResponse: try: deal_service = DealService(self.session) billing_client = BillingClient(backend.config.BILLING_API_KEY) deal: Deal = await deal_service.get_by_id(user, request.deal_id) billing_request_values: List[CreateBillingRequestValue] = [] for product in deal.products: for service in product.services: billing_request_values.append( CreateBillingRequestValue( name=f'[{product.product.name}] - {service.service.name}', price=service.price, amount=product.quantity ) ) for service in deal.services: billing_request_values.append( CreateBillingRequestValue( name=f'{service.service.name}', price=service.price, amount=service.quantity ) ) create_bill_request = CreateBillRequestSchema( listener_transaction_id=deal.id, payer_name=deal.client.name, payer_inn=deal.client.details.inn, payer_phone=deal.client.details.phone_number, items=CreateBillRequestItems( values=billing_request_values ) ) create_bill_response = await billing_client.create(create_bill_request) if not create_bill_response.ok: return CreateDealBillResponse(ok=create_bill_response.ok, message='Ошибка!') deal_bill_request = DealBillRequest( deal_id=request.deal_id, created_at=datetime.datetime.now() ) self.session.add(deal_bill_request) deal.is_locked = True await self.session.commit() return CreateDealBillResponse(ok=create_bill_response.ok, message='Заявка успешно создана!') except Exception as e: return CreateDealBillResponse(ok=False, message=str(e)) async def _get_deal_bill_by_id(self, deal_id: int) -> Optional[DealBillRequest]: return await self.session.scalar(select(DealBillRequest).where(DealBillRequest.deal_id == deal_id)) async def get_deal_bill_by_id(self, deal_id: int) -> GetDealBillById: deal_bill = await self._get_deal_bill_by_id(deal_id) if not deal_bill: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='Deal bill was not found') return GetDealBillById(deal_bill=DealBillRequestSchema.model_validate(deal_bill))