Files
Fulfillment-Backend/services/billing.py
2024-08-08 07:49:53 +03:00

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))