feat: end-point for deal document generation

This commit is contained in:
2024-09-20 20:02:17 +04:00
parent 03aba9649a
commit 5316f7f9ce
9 changed files with 482 additions and 5 deletions

View File

@@ -1,12 +1,17 @@
from io import BytesIO
import lexorank
from fastapi import HTTPException
from sqlalchemy import select, func, update, delete, insert
from sqlalchemy.orm import joinedload, selectinload
from starlette import status
from weasyprint import HTML, CSS
import constants
import models.deal
import models.secondary
from models import User, Service, Client, DealProduct
from constants import ENV, DEAL_STATUS_STR
from models import User, Service, Client, DealProduct, DealService as DealServiceModel, Product
from models.deal import *
from schemas.client import ClientDetailsSchema
from schemas.deal import *
@@ -15,6 +20,7 @@ from services.base import BaseService
from services.client import ClientService
from services.service import ServiceService
from services.shipping_warehouse import ShippingWarehouseService
from utils.images_fetcher import fetch_images
class DealService(BaseService):
@@ -987,3 +993,56 @@ class DealService(BaseService):
except Exception as e:
await self.session.rollback()
return DealCompleteResponse(ok=False, message=str(e))
# region Deal documents
@staticmethod
async def _get_product_services_totals(deal: Deal) -> List[int]:
totals: List[int] = []
for product in deal.products:
total = sum((service.price * product.quantity for service in product.services))
totals.append(total)
return totals
async def _create_detailed_deal_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.products).selectinload(DealProduct.product).selectinload(Product.barcodes),
selectinload(Deal.services).selectinload(DealServiceModel.service),
selectinload(Deal.status_history),
joinedload(Deal.client),
joinedload(Deal.shipping_warehouse),
)
)
if not deal:
return ""
last_status: DealStatusHistory = max(deal.status_history, key=lambda status: status.changed_at)
general_services_total = sum((service.price * service.quantity for service in deal.services))
product_services_totals = await self._get_product_services_totals(deal)
template = ENV.get_template("deal.html")
product_images = await fetch_images([product.product.images[0].image_url for product in deal.products])
result = template.render({
"general_services_total": general_services_total,
"product_services_totals": product_services_totals,
"deal": deal,
"current_status_str": DEAL_STATUS_STR[deal.current_status],
"last_status": last_status,
"product_images": product_images,
})
return result
async def create_detailed_deal_document_pdf(self, deal_id) -> BytesIO:
doc = await self._create_detailed_deal_document_html(deal_id)
pdf_file = BytesIO()
HTML(string=doc).write_pdf(pdf_file, stylesheets=[CSS(constants.APP_PATH + '/static/css/deal.css')])
return pdf_file
# endregion