Files
Touchh/bot/utils/pdf_report.py
2024-12-25 11:28:50 +09:00

120 lines
4.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from fpdf import FPDF
import os
from datetime import datetime, timedelta
from asgiref.sync import sync_to_async
from django.utils.timezone import make_aware, is_aware, localtime
import pytz
from bot.utils.date_utils import ensure_datetime
from touchh.utils.log import CustomLogger
logger = CustomLogger(name="CustomPDF Report", log_level="DEBUG").get_logger()
# Определение абсолютного пути к папке "reports"
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
REPORTS_DIR = os.path.join(BASE_DIR, "reports")
os.makedirs(REPORTS_DIR, exist_ok=True)
@sync_to_async
def get_reservation_data(res):
check_in = ensure_datetime(res.check_in)
check_out = ensure_datetime(res.check_out)
if not check_in or not check_out:
raise ValueError(f"Некорректные даты бронирования: check_in={res.check_in}, check_out={res.check_out}")
return {
"hotel_name": res.hotel.name,
"pms": getattr(res.hotel, 'pms', 'N/A'),
"reservation_id": res.reservation_id,
"room_number": res.room_number if res.room_number else "Не указан",
"room_type": res.room_type,
"check_in": check_in,
"check_out": check_out,
"status": res.status,
}
def sanitize_text(text):
return text.replace("\n", " ").strip() if isinstance(text, str) else text
class CustomPDF(FPDF):
def __init__(self, hotel_name, start_date, end_date, *args, **kwargs):
super().__init__(*args, **kwargs)
self.font_folder = "bot/fonts/"
self.add_font("DejaVuSans-Bold", "", os.path.join(self.font_folder, "DejaVuSans-Bold.ttf"), uni=True)
self.add_font("DejaVuSans", "", os.path.join(self.font_folder, "DejaVuSans.ttf"), uni=True)
self.creation_date = ensure_datetime(datetime.now(pytz.UTC))
self.hotel_name = hotel_name
self.start_date = start_date
self.end_date = end_date
def header(self):
if self.page == 1:
self.set_font("DejaVuSans-Bold", size=14)
self.cell(0, 10, f"Отчет о бронированиях отеля {self.hotel_name}", ln=1, align="C")
self.ln(5)
self.set_font("DejaVuSans", size=10)
self.cell(
0,
10,
f"за период {self.start_date.strftime('%Y-%m-%d %H:%M:%S')} - {self.end_date.strftime('%Y-%m-%d %H:%M:%S')}",
ln=1,
align="C"
)
self.ln(10)
def footer(self):
self.set_y(-15)
self.set_font("DejaVuSans", size=8)
self.cell(60, 10, f"Copyright (C) 2024 by Touchh", align="L")
self.cell(0, 10, f"Лист {self.page_no()} из {{nb}} / Дата генерации отчета: {self.creation_date}", align="C")
async def generate_pdf_report(hotel_name, reservations, start_date, end_date):
start_date = ensure_datetime(start_date)
end_date = ensure_datetime(end_date)
logger.debug(f"Start_DATE: {start_date} / TYPE: {type(start_date)}")
logger.debug(f"END_DATE: {end_date} / TYPE: {type(end_date)}")
if not start_date or not end_date:
raise ValueError("Некорректные даты для генерации отчета.")
pdf = CustomPDF(hotel_name=hotel_name, start_date=start_date, end_date=end_date, orientation="L", unit="mm", format="A4")
pdf.alias_nb_pages()
pdf.add_page()
pdf.set_font("DejaVuSans", size=8)
col_widths = [30, 30, 30, 60, 35, 35, 30]
row_height = 10
for res in reservations:
try:
res_data = await get_reservation_data(res)
res_data["check_in"] = ensure_datetime(res_data["check_in"])
res_data["check_out"] = ensure_datetime(res_data["check_out"])
row_data = [
sanitize_text(res_data["hotel_name"]),
sanitize_text(str(res_data["reservation_id"])),
sanitize_text(str(res_data["room_number"])),
sanitize_text(str(res_data["room_type"])),
res_data["check_in"].strftime('%Y-%m-%d %H:%M:%S'),
res_data["check_out"].strftime('%Y-%m-%d %H:%M:%S'),
sanitize_text(res_data["status"]),
]
for col_width, data in zip(col_widths, row_data):
pdf.cell(col_width, row_height, data, border=1, align="C")
pdf.ln()
except Exception as e:
logger.error(f"[ERROR] Error processing reservation {res.id}: {e}")
pdf_output_path = os.path.join(REPORTS_DIR, f"{hotel_name.replace(' ', '_')}_report_{start_date.strftime('%Y-%m-%d')}-{end_date.strftime('%Y-%m-%d')}.pdf")
logger.debug(f"PDF output path: {pdf_output_path}")
pdf.output(pdf_output_path)
if not os.path.exists(pdf_output_path):
raise RuntimeError(f"PDF file was not created at: {pdf_output_path}")
return pdf_output_path