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