feat: billing for groups of deals

This commit is contained in:
2024-11-15 20:27:16 +04:00
parent bbe9832923
commit e2d35fb7c4
6 changed files with 145 additions and 31 deletions

View File

@@ -1,4 +1,4 @@
from collections import defaultdict
import logging
from io import BytesIO
from typing import List
from uuid import uuid4
@@ -12,12 +12,12 @@ from weasyprint import HTML, CSS
import backend.config
import constants
import models
from constants import MONTHS, ENV
from external.billing import BillingClient, CreateBillingRequestValue, CreateBillRequestSchema, CreateBillRequestItems, \
BillStatusUpdateRequest, NotificationChannel, NotifyReceivedBillRequestSchema, DeleteBillRequestSchema, \
ProductBillingDocumentPdf, ServiceBillingDocumentPdf
from models import DealBillRequest, Deal, DealProduct, DealService as DealServiceModel, DealProductService, DealGroup
from models import DealBillRequest, Deal, DealProduct, DealService as DealServiceModel, DealProductService, DealGroup, \
GroupBillRequest
from schemas.billing import *
from services.base import BaseService
from services.deal import DealService
@@ -25,6 +25,30 @@ from utils.list_utils import to_locale_number
class BillingService(BaseService):
async def _process_deal_update_details(
self,
request: BillStatusUpdateRequest,
):
deal_bill_request = await self._get_deal_bill_by_id(request.listener_transaction_id)
if not deal_bill_request:
return
deal_bill_request.pdf_url = request.info.pdf_url
deal_bill_request.invoice_number = request.info.invoice_number
async def _process_group_update_details(
self,
request: BillStatusUpdateRequest,
):
prefix = "group-"
if not request.listener_transaction_id.startswith(prefix):
return
group_id = int(request.listener_transaction_id.removeprefix(prefix))
group_bill_request = await self._get_group_bill_by_id(group_id)
if not group_bill_request:
return
group_bill_request.pdf_url = request.info.pdf_url
group_bill_request.invoice_number = request.info.invoice_number
async def _process_update_details(
self,
request: BillStatusUpdateRequest
@@ -36,13 +60,36 @@ class BillingService(BaseService):
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
if type(request.listener_transaction_id) is int:
await self._process_deal_update_details(request)
else:
await self._process_group_update_details(request)
await self.session.commit()
async def _process_deal_update_verification(
self,
request: BillStatusUpdateRequest
):
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
async def _process_group_update_verification(
self,
request: BillStatusUpdateRequest
):
prefix = "group-"
if not request.listener_transaction_id.startswith(prefix):
return
group_id = int(request.listener_transaction_id.removeprefix(prefix))
group_bill_request = await self._get_group_bill_by_id(group_id)
if not group_bill_request:
return
group_bill_request.paid = request.info.payed
async def _process_update_verification(
self,
request: BillStatusUpdateRequest
@@ -56,10 +103,10 @@ class BillingService(BaseService):
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
if type(request.listener_transaction_id) is int:
await self._process_deal_update_verification(request)
else:
await self._process_group_update_verification(request)
await self.session.commit()
async def process_update(
@@ -71,6 +118,25 @@ class BillingService(BaseService):
elif request.channel == NotificationChannel.PAYMENT_VERIFICATION:
await self._process_update_verification(request)
async def create_deal_bill_request(self, deal: Deal):
deal_bill_request = DealBillRequest(
deal_id=deal.id,
created_at=datetime.datetime.now()
)
self.session.add(deal_bill_request)
deal.is_locked = True
await self.session.commit()
async def create_group_bill_request(self, group: DealGroup):
group_bill_request = GroupBillRequest(
group_id=group.id,
created_at=datetime.datetime.now()
)
self.session.add(group_bill_request)
for deal in group.deals:
deal.is_locked = True
await self.session.commit()
async def create_deal_billing(self, user, request: CreateDealBillRequest) -> CreateDealBillResponse:
try:
deal_service = DealService(self.session)
@@ -88,7 +154,6 @@ class BillingService(BaseService):
is_size_needed: bool
billing_request_values: List[CreateBillingRequestValue] = []
for service in services.values():
billing_request_values.append(
CreateBillingRequestValue(
@@ -99,8 +164,11 @@ class BillingService(BaseService):
)
deal = basic_deal
listener_transaction_id = deal.id
if deal.group:
listener_transaction_id = f"group-{basic_deal.group.id}"
create_bill_request = CreateBillRequestSchema(
listener_transaction_id=deal.id,
listener_transaction_id=listener_transaction_id,
payer_name=deal.client.name,
payer_inn=deal.client.details.inn,
payer_phone=deal.client.details.phone_number,
@@ -111,13 +179,12 @@ class BillingService(BaseService):
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()
if basic_deal.group:
await self.create_group_bill_request(basic_deal.group)
else:
await self.create_deal_bill_request(basic_deal)
return CreateDealBillResponse(ok=create_bill_response.ok, message='Заявка успешно создана!')
except Exception as e:
return CreateDealBillResponse(ok=False, message=str(e))
@@ -125,6 +192,9 @@ class BillingService(BaseService):
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_group_bill_by_id(self, group_id: int) -> Optional[GroupBillRequest]:
return await self.session.scalar(select(GroupBillRequest).where(GroupBillRequest.group_id == group_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:
@@ -133,14 +203,27 @@ class BillingService(BaseService):
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))
deal = await self._get_deal_by_id(request.deal_id)
if not deal:
return CancelDealBillResponse(ok=False, message='Сделка не найдена')
if deal.group:
bill = await self._get_group_bill_by_id(deal.group.id)
if not bill:
return CancelDealBillResponse(ok=False, message='Заявка не найдена')
billing_client = BillingClient(backend.config.BILLING_API_KEY)
response = await billing_client.delete(DeleteBillRequestSchema(listener_transaction_id=deal.group.id))
else:
bill = await self._get_deal_bill_by_id(request.deal_id)
if not 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.delete(bill)
await self.session.commit()
return CancelDealBillResponse(ok=True, message='Заявка успешно отозвана')
except Exception as e: