feat: end-point for bill of payment generation

This commit is contained in:
2024-09-11 19:08:06 +04:00
parent 49037125c2
commit 50a315ca18
7 changed files with 260 additions and 51 deletions

View File

@@ -1,19 +1,30 @@
import datetime
import locale
from ast import Bytes
from io import BytesIO
from pathlib import Path
from typing import List
from fastapi import HTTPException
from jinja2 import Environment, FileSystemLoader
from number_to_string import get_string_by_number
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from starlette import status
from weasyprint import HTML
import backend.config
from external.billing import BillingClient, CreateBillingRequestValue, CreateBillRequestSchema, CreateBillRequestItems, \
BillStatusUpdateRequest, NotificationChannel, NotifyReceivedBillRequestSchema, BillPaymentInfo, \
DeleteBillRequestSchema
from models import DealBillRequest, Deal
BillStatusUpdateRequest, NotificationChannel, NotifyReceivedBillRequestSchema, DeleteBillRequestSchema
from models import DealBillRequest, Deal, DealProduct, DealService as DealServiceModel
from schemas.billing import *
from services.base import BaseService
from services.deal import DealService
locale.setlocale(locale.LC_TIME, "ru_RU.UTF-8")
env = Environment(loader=FileSystemLoader(Path("templates") / Path("documents")))
class BillingService(BaseService):
async def _process_update_details(
@@ -132,3 +143,60 @@ class BillingService(BaseService):
return CancelDealBillResponse(ok=True, message='Заявка успешно отозвана')
except Exception as e:
return CancelDealBillResponse(ok=False, message=str(e))
async def _get_services_for_deal(self, deal: Deal) -> List[CreateBillingRequestValue]:
services: List[CreateBillingRequestValue] = []
for product in deal.products:
for service in product.services:
services.append(
CreateBillingRequestValue(
name=f'[{product.product.name}] - {service.service.name}',
price=service.price,
amount=product.quantity
)
)
for service in deal.services:
services.append(
CreateBillingRequestValue(
name=f'{service.service.name}',
price=service.price,
amount=service.quantity
)
)
return services
async def _create_billing_document_html(self, deal_id: int):
deal: Deal | None = await self.session.scalar(
select(Deal)
.where(Deal.id == deal_id)
.options(
selectinload(Deal.products).selectinload(DealProduct.services),
selectinload(Deal.services).selectinload(DealServiceModel.service),
)
)
if not deal:
return ""
services = await self._get_services_for_deal(deal)
deal_price = sum((service.price for service in services))
deal_price_words = get_string_by_number(deal_price)[0:-10]
template = env.get_template("bill-of-payment.html")
return template.render({
"services": services,
"deal_price": deal_price,
"deal_price_words": deal_price_words,
"deal": deal,
"curr_date": datetime.datetime.now().strftime("%d %B %Y г.")
})
async def create_billing_document_pdf(self, deal_id) -> BytesIO:
doc = await self._create_billing_document_html(deal_id)
pdf_file = BytesIO()
HTML(string=doc).write_pdf(pdf_file)
return pdf_file