[32788f42] Update QR card generator: adjust Y-coordinates, add timezone support, and render checkboxes
This commit is contained in:
@@ -79,21 +79,25 @@ def get_calendly_events(api_token: str, start_time: str, end_time: str, event_ty
|
||||
"""
|
||||
Fetches events from Calendly API for the current user within a time range.
|
||||
"""
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
raw_data = get_calendly_events_raw(api_token, start_time, end_time, event_type_name)
|
||||
formatted_data = []
|
||||
|
||||
for item in raw_data:
|
||||
# Parse start time
|
||||
# Parse start time from UTC
|
||||
start_dt = datetime.datetime.fromisoformat(item['start_time'].replace('Z', '+00:00'))
|
||||
# Convert to Europe/Berlin (CET/CEST)
|
||||
start_dt = start_dt.astimezone(ZoneInfo("Europe/Berlin"))
|
||||
# Format as HH:MM
|
||||
time_str = start_dt.strftime('%H:%M')
|
||||
|
||||
name = item['invitee_name']
|
||||
|
||||
# Extract specific answers from the Calendly form
|
||||
# We look for the number of children and any additional notes
|
||||
num_children = ""
|
||||
additional_notes = ""
|
||||
has_consent = False
|
||||
questions_and_answers = item.get('questions_and_answers', [])
|
||||
|
||||
for q_a in questions_and_answers:
|
||||
@@ -103,12 +107,20 @@ def get_calendly_events(api_token: str, start_time: str, end_time: str, event_ty
|
||||
if "wie viele kinder" in q_text:
|
||||
num_children = a_text
|
||||
elif "nachricht" in q_text or "anmerkung" in q_text:
|
||||
# If there's a custom notes field in some events
|
||||
additional_notes = a_text
|
||||
elif "schöne bilder" in q_text and "website veröffentlichen" in q_text:
|
||||
if "ja, gerne" in a_text.lower():
|
||||
has_consent = True
|
||||
|
||||
# Construct the final string: "Name, X Kinder // HH:MM Uhr (Notes)"
|
||||
# Construct the final string: "[☑] Name, X Kinder // HH:MM Uhr (Notes)"
|
||||
# matching: Halime Türe, 1 Kind // 12:00 Uhr
|
||||
final_text = f"{name}"
|
||||
final_text = ""
|
||||
if has_consent:
|
||||
# We use a placeholder character or string that we will handle in overlay_text_on_pdf
|
||||
# because standard Helvetica doesn't support Unicode checkbox.
|
||||
final_text += "☑ "
|
||||
|
||||
final_text += f"{name}"
|
||||
if num_children:
|
||||
final_text += f", {num_children}"
|
||||
|
||||
@@ -124,13 +136,9 @@ def get_calendly_events(api_token: str, start_time: str, end_time: str, event_ty
|
||||
|
||||
|
||||
def overlay_text_on_pdf(base_pdf_path: str, output_pdf_path: str, texts: list):
|
||||
"""
|
||||
Overlays text from the `texts` list onto a base PDF.
|
||||
Expects two text entries per page (top and bottom element).
|
||||
Coordinates are in mm from bottom-left (ReportLab default).
|
||||
Target:
|
||||
Element 1: X: 72mm, Y: 22mm (from top-left in user spec, need to convert)
|
||||
Element 2: X: 72mm, Y: 171mm (from top-left in user spec, need to convert)
|
||||
# Target:
|
||||
# Element 1: X: 72mm, Y: 22mm + 9mm = 31mm
|
||||
# Element 2: X: 72mm, Y: 171mm + 9mm = 180mm
|
||||
"""
|
||||
|
||||
# Convert mm to points (1 mm = 2.83465 points)
|
||||
@@ -141,12 +149,12 @@ def overlay_text_on_pdf(base_pdf_path: str, output_pdf_path: str, texts: list):
|
||||
|
||||
# User coordinates are from top-left.
|
||||
# ReportLab uses bottom-left as (0,0).
|
||||
# Element 1 (Top): X = 72mm, Y = 22mm (from top) -> Y = page_height - 22mm
|
||||
# Element 2 (Bottom): X = 72mm, Y = 171mm (from top) -> Y = page_height - 171mm
|
||||
# Element 1 (Top): X = 72mm, Y = 31mm (from top) -> Y = page_height - 31mm
|
||||
# Element 2 (Bottom): X = 72mm, Y = 180mm (from top) -> Y = page_height - 180mm
|
||||
|
||||
x_pos = 72 * mm_to_pt
|
||||
y_pos_1 = page_height - (22 * mm_to_pt)
|
||||
y_pos_2 = page_height - (171 * mm_to_pt)
|
||||
y_pos_1 = page_height - (31 * mm_to_pt)
|
||||
y_pos_2 = page_height - (180 * mm_to_pt)
|
||||
|
||||
reader = PdfReader(base_pdf_path)
|
||||
writer = PdfWriter()
|
||||
@@ -163,19 +171,38 @@ def overlay_text_on_pdf(base_pdf_path: str, output_pdf_path: str, texts: list):
|
||||
|
||||
for page_idx, pair in enumerate(text_pairs):
|
||||
if page_idx >= total_pages:
|
||||
break # Should be caught by the truncation above, but safety first
|
||||
break # Safety first
|
||||
|
||||
# Create a new blank page in memory to draw the text
|
||||
packet = io.BytesIO()
|
||||
can = canvas.Canvas(packet, pagesize=A4)
|
||||
|
||||
# Draw the text.
|
||||
can.setFont("Helvetica", 12)
|
||||
|
||||
# We handle the "☑" character manually since Helvetica might not support it.
|
||||
def draw_text_with_checkbox(can, x, y, text):
|
||||
current_x = x
|
||||
if text.startswith("☑ "):
|
||||
# Draw a checkbox manually
|
||||
size = 10
|
||||
# Draw box (baseline adjustment to align with text)
|
||||
can.rect(x, y - 1, size, size)
|
||||
# Draw checkmark
|
||||
can.setLineWidth(1.5)
|
||||
can.line(x + 2, y + 3, x + 4.5, y + 0.5)
|
||||
can.line(x + 4.5, y + 0.5, x + 8.5, y + 7)
|
||||
can.setLineWidth(1)
|
||||
|
||||
# Move text X position to the right
|
||||
current_x += size + 5
|
||||
text = text[2:] # Remove the "☑ " from string
|
||||
|
||||
can.setFont("Helvetica", 12)
|
||||
can.drawString(current_x, y, text)
|
||||
|
||||
if len(pair) > 0:
|
||||
can.drawString(x_pos, y_pos_1, pair[0])
|
||||
draw_text_with_checkbox(can, x_pos, y_pos_1, pair[0])
|
||||
if len(pair) > 1:
|
||||
can.drawString(x_pos, y_pos_2, pair[1])
|
||||
draw_text_with_checkbox(can, x_pos, y_pos_2, pair[1])
|
||||
|
||||
can.save()
|
||||
packet.seek(0)
|
||||
|
||||
Reference in New Issue
Block a user