Files
goodtimes/manage_events/report.py
2024-06-20 15:05:54 +05:30

379 lines
13 KiB
Python

from django.db.models import Count, Q
from django.utils import timezone
from datetime import timedelta
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import mm
from reportlab.graphics.shapes import Drawing, Rect
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.graphics.charts.piecharts import Pie
from reportlab.platypus import (
SimpleDocTemplate,
Table,
TableStyle,
Paragraph,
Spacer,
PageBreak,
Image,
)
from io import BytesIO
from django.conf import settings
from collections import defaultdict
from reportlab.graphics import renderPDF
from django.contrib.auth import get_user_model
from accounts.models import IAmPrincipalType
from manage_events.models import Event, EventInteractionType, EventShare, EventView
import os
User = get_user_model()
def generate_filename(email, date):
# Extract the username from the email address
username = email.split("@")[0]
# Get the full month name from the date
month_name = date.strftime("%B")
# Create the filename
filename = f"{username}_{month_name}_report.pdf"
return filename
def event_managers():
principal_type = IAmPrincipalType.objects.filter(name="event_manager").first()
return User.objects.filter(principal_type=principal_type, is_active=True)
def get_previous_month_date_range():
today = timezone.now()
first_day_of_current_month = today.replace(day=1)
last_day_of_previous_month = first_day_of_current_month - timedelta(days=1)
first_day_of_previous_month = last_day_of_previous_month.replace(day=1)
return first_day_of_previous_month, last_day_of_previous_month
def generate_event_report(user_id):
start_date, end_date = get_previous_month_date_range()
user = User.objects.get(id=user_id)
# events = Event.objects.filter(
# created_by=user, start_date__gte=start_date, start_date__lte=end_date
# ).annotate(
# favorites_count=Count("favorites"),
# interested_count=Count(
# "interaction_event",
# filter=Q(interaction_event__status=EventInteractionType.INTERESTED),
# ),
# going_count=Count(
# "interaction_event",
# filter=Q(interaction_event__status=EventInteractionType.GOING),
# ),
# reviews_count=Count(
# "reviews", filter=Q(reviews__active=True, reviews__deleted=False)
# ),
# views_count=Count("views"),
# )
# # print("events: ", events)
# report_data = []
# for event in events:
# views = EventView.objects.filter(event=event)
# locations = defaultdict(int)
# for view in views:
# locations[view.location] += 1
# shares = (
# EventShare.objects.filter(event=event)
# .values("principal")
# .annotate(share_count=Count("principal"))
# )
# shares_data = {
# User.objects.get(id=share["principal"]).get_full_name(): share[
# "share_count"
# ]
# for share in shares
# }
# report_data.append(
# {
# "event_name": event.title,
# "event_type": event.category.title,
# "event_date": str(event.start_date),
# "favorites_count": event.favorites_count,
# "interested_count": event.interested_count,
# "going_count": event.going_count,
# "reviews_count": event.reviews_count,
# "views_count": event.views_count,
# "locations": dict(locations),
# "social_media_shares": event.social_media_shares_count,
# "shares_data": shares_data,
# }
# )
# # print("report_data: ", report_data)
# return report_data
events = Event.objects.filter(
created_by=user, start_date__gte=start_date, start_date__lte=end_date
)
report_data = []
for event in events:
# Collecting individual counts for each event
favorites_count = event.favorites.count()
interested_count = event.interaction_event.filter(
status=EventInteractionType.INTERESTED
).count()
going_count = event.interaction_event.filter(
status=EventInteractionType.GOING
).count()
reviews_count = event.reviews.filter(active=True, deleted=False).count()
views_count = event.views.count()
# Collecting views and locations
views = EventView.objects.filter(event=event)
locations = defaultdict(int)
for view in views:
locations[view.location] += 1
# Collecting shares data
shares = (
EventShare.objects.filter(event=event)
.values("principal")
.annotate(share_count=Count("principal"))
)
shares_data = {
User.objects.get(id=share["principal"]).get_full_name(): share[
"share_count"
]
for share in shares
}
# Appending event data to report
report_data.append(
{
"event_name": event.title,
"event_type": event.category.title,
"event_date": str(event.start_date),
"favorites_count": favorites_count,
"interested_count": interested_count,
"going_count": going_count,
"reviews_count": reviews_count,
"views_count": views_count,
"locations": dict(locations),
"social_media_shares": event.social_media_shares_count,
"shares_data": shares_data,
}
)
return report_data
def generate_event_report_pdf_three(user, report_data):
start_date, _ = get_previous_month_date_range()
filename = generate_filename(user.email, start_date)
buffer = BytesIO()
# pdf = canvas.Canvas(buffer, pagesize=letter)
pdf = SimpleDocTemplate(buffer, pagesize=letter)
width, height = letter
elements = []
styles = getSampleStyleSheet()
custom_style = ParagraphStyle(
name="Custom",
parent=styles["Normal"],
fontName="Helvetica",
fontSize=14,
leading=18,
spaceAfter=12,
)
def add_page_number(canvas, doc):
page_num_text = f"Page {doc.page}"
canvas.drawRightString(200 * mm, 10 * mm, page_num_text)
# Header Section
title = Paragraph("Good Times Ltd. Monthly Report", styles["Title"])
report_for_month = Paragraph(
f"Report for the month of - {start_date.strftime('%B %Y')}", styles["Title"]
)
organiser_name = Paragraph(
f"Name of the Organiser - {user.get_full_name()}", styles["Title"]
)
contact_email = Paragraph(f"Contact Email - {user.email}", styles["Title"])
elements.extend(
[
title,
Spacer(1, 12),
report_for_month,
Spacer(1, 12),
organiser_name,
Spacer(1, 12),
contact_email,
Spacer(1, 72), # Add space before the logo
]
)
# Insert company logo
logo_path = settings.LOGO_PATH
print("logo_path: ", logo_path)
logo_path = os.path.join(str(logo_path), "images/icon.png") # Path to the logo
logo = Image(logo_path)
logo.drawWidth = 200 # Adjust the width as needed
logo.drawHeight = 300 # Adjust the height as needed
logo.hAlign = "CENTER" # Center the logo
elements.append(logo)
elements.append(Spacer(1, 12)) # Add space after the logo
# Page break after header and logo
elements.append(PageBreak())
# Summary Section
summary_text = (
f"Number of Events added in {start_date.strftime('%B %Y')} - {len(report_data)}"
)
elements.append(Paragraph(summary_text, styles["Title"]))
elements.append(Spacer(1, 24))
data = [["Sr No.", "Name of the Event", "Event Type", "Date"]]
for idx, event in enumerate(report_data, start=1):
data.append(
[
idx,
event["event_name"],
event["event_type"],
event["event_date"],
]
)
table = Table(data, colWidths=[50, 250, 150, 100])
style = TableStyle(
[
("BACKGROUND", (0, 0), (-1, 0), colors.grey),
("TEXTCOLOR", (0, 0), (-1, 0), colors.whitesmoke),
("ALIGN", (0, 0), (-1, -1), "CENTER"),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("BOTTOMPADDING", (0, 0), (-1, 0), 12),
("BACKGROUND", (0, 1), (-1, -1), colors.beige),
("GRID", (0, 0), (-1, -1), 1, colors.black),
]
)
table.setStyle(style)
elements.append(table)
elements.append(PageBreak())
# Traffic Details Section
traffic_header = "Traffic Details for profile - Event Organisers London Ltd."
elements.append(Paragraph(traffic_header, styles["Title"]))
elements.append(Spacer(1, 12))
views_count = sum(event["views_count"] for event in report_data)
favorites_count = sum(event["favorites_count"] for event in report_data)
social_media_shares = sum(event["social_media_shares"] for event in report_data)
elements.append(Paragraph(f"Number of Event Views - {views_count}", custom_style))
elements.append(Spacer(1, 12))
elements.append(
Paragraph(f"Number of Event Favorites - {favorites_count}", custom_style)
)
elements.append(Spacer(1, 12))
elements.append(
Paragraph(f"Social Media Shares - {social_media_shares}", custom_style)
)
# elements.append(PageBreak())
elements.append(Spacer(1, 60))
# Top 5 Locations and Top 5 Viewed Events
all_locations = defaultdict(int)
for event in report_data:
for location, count in event["locations"].items():
all_locations[location] += count
# top 5 events by location
top_locations = sorted(all_locations.items(), key=lambda x: x[1], reverse=True)[:5]
# top 5 events overall by views
top_events_by_views = sorted(
report_data, key=lambda x: x["views_count"], reverse=True
)[:5]
data = [
["Top 5 Locations Viewed From", "Top 5 Viewed Events"],
]
for i in range(5):
location = top_locations[i][0] if i < len(top_locations) else ""
event = (
top_events_by_views[i]["event_name"] if i < len(top_events_by_views) else ""
)
data.append([location, event])
table = Table(data, colWidths=[200, 200])
style = TableStyle(
[
("BACKGROUND", (0, 0), (-1, 0), colors.grey),
("TEXTCOLOR", (0, 0), (-1, 0), colors.whitesmoke),
("ALIGN", (0, 0), (-1, -1), "CENTER"),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("BOTTOMPADDING", (0, 0), (-1, 0), 12),
("BACKGROUND", (0, 1), (-1, -1), colors.beige),
("GRID", (0, 0), (-1, -1), 1, colors.black),
]
)
table.setStyle(style)
elements.append(table)
elements.append(PageBreak())
# Detailed Review of Each Event
for event in report_data:
elements.append(
Paragraph(f"Event Name - {event['event_name']}", styles["Heading1"])
)
elements.append(Spacer(1, 12))
elements.append(Paragraph(f"Event Type - {event['event_type']}", custom_style))
elements.append(Paragraph(f"Event Date - {event['event_date']}", custom_style))
views = f"Number of Views - {event['views_count']}"
favorites = f"Favorites Count - {event['favorites_count']}"
interested = f"Interested in Going - {event['interested_count']}"
going = f"Going - {event['going_count']}"
reviews = f"Reviews - {event['reviews_count']}"
shares = f"Social Media Shares - {event['social_media_shares']}"
elements.append(Paragraph(views, custom_style))
elements.append(Paragraph(shares, custom_style))
elements.append(Paragraph(favorites, custom_style))
elements.append(Paragraph(interested, custom_style))
elements.append(Paragraph(going, custom_style))
elements.append(Paragraph(reviews, custom_style))
elements.append(Spacer(1, 48))
pie_data = [
event["views_count"],
event["social_media_shares"],
event["favorites_count"],
event["interested_count"],
event["going_count"],
]
pie_labels = ["Views", "Shares", "Favorites", "Interested", "Going"]
drawing = Drawing(300, 200)
pie = Pie()
pie.data = pie_data
pie.labels = pie_labels
pie.width = 150
pie.height = 150
pie.x = 75
pie.y = 25
drawing.add(pie)
elements.append(drawing)
elements.append(PageBreak())
pdf.build(elements, onFirstPage=add_page_number, onLaterPages=add_page_number)
buffer.seek(0)
pdf_data = buffer.read()
buffer.close()
return pdf_data, filename