135 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
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, \
 | 
						|
    DeleteBillRequestSchema
 | 
						|
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))
 | 
						|
 | 
						|
    async def cancel_deal_billing(self, user, request: CancelDealBillRequest) -> CancelDealBillResponse:
 | 
						|
        try:
 | 
						|
            deal_bill = await self._get_deal_bill_by_id(request.deal_id)
 | 
						|
            if not deal_bill:
 | 
						|
                return CancelDealBillResponse(ok=False, message='Заявка не найдена')
 | 
						|
            billing_client = BillingClient(backend.config.BILLING_API_KEY)
 | 
						|
            response = await billing_client.delete(DeleteBillRequestSchema(listener_transaction_id=request.deal_id))
 | 
						|
            if not response.ok:
 | 
						|
                return CancelDealBillResponse(ok=False, message='Ошибка')
 | 
						|
            await self.session.delete(deal_bill)
 | 
						|
            await self.session.commit()
 | 
						|
            return CancelDealBillResponse(ok=True, message='Заявка успешно отозвана')
 | 
						|
        except Exception as e:
 | 
						|
            return CancelDealBillResponse(ok=False, message=str(e))
 |