feat: end-point for bill of payment generation
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user