119 lines
5.2 KiB
Python
119 lines
5.2 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
|
|
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))
|