Skip to content
Snippets Groups Projects
Commit a693fe43 authored by Stefan Beck's avatar Stefan Beck
Browse files

Bestellschein Retrokarte

Erzeugt einen Bestellschein für eine Retrokarte.
parent 2b166d0b
No related branches found
No related tags found
No related merge requests found
Pipeline #3418 passed
...@@ -7,6 +7,7 @@ from flask import request ...@@ -7,6 +7,7 @@ from flask import request
from .pdf import reservation_order_a4 from .pdf import reservation_order_a4
from .pdf import reservation_bon from .pdf import reservation_bon
from .pdf import retro_a4
# Wir arbeiten hier mit Handlern und filtern um ein einigermaßen gutes Logging für den Container zu bekommen. # Wir arbeiten hier mit Handlern und filtern um ein einigermaßen gutes Logging für den Container zu bekommen.
# Die ist einfach: Für das Loglevel INFO gehen wir nach stdout, höheres nach stderr. Daher filtern wir beim Handler für Level INFO. # Die ist einfach: Für das Loglevel INFO gehen wir nach stdout, höheres nach stderr. Daher filtern wir beim Handler für Level INFO.
...@@ -43,6 +44,8 @@ def make_pdf(): ...@@ -43,6 +44,8 @@ def make_pdf():
logger.info(print_request) logger.info(print_request)
if print_group_name == "Phil II Vormerkungen": if print_group_name == "Phil II Vormerkungen":
func = reservation_bon func = reservation_bon
elif print_group_name == "retro":
func = retro_a4
# Die restlichen Zettel sehen alle gleich aus, daher diese "unsaubere" Lösung. # Die restlichen Zettel sehen alle gleich aus, daher diese "unsaubere" Lösung.
else: else:
func = reservation_order_a4 func = reservation_order_a4
......
from base64 import b64decode
import barcode import barcode
import os import os
import unicodedata import unicodedata
from datetime import timedelta, datetime, date from datetime import timedelta, datetime, date, timezone
from io import BytesIO from io import BytesIO
from reportlab.lib.enums import TA_CENTER from reportlab.lib.enums import TA_CENTER
...@@ -47,15 +49,16 @@ def bestelldatum(data: dict) -> str: ...@@ -47,15 +49,16 @@ def bestelldatum(data: dict) -> str:
""" """
Formatiert das Bestelldatum mit Uhrzeit sinnvoll menschenlesbar. Formatiert das Bestelldatum mit Uhrzeit sinnvoll menschenlesbar.
Bei einem Datum ohne Zeitzone nehmen wir UTC an.
Als Bonus wird auch die Zeitzone korrekt berechnet. Als Bonus wird auch die Zeitzone korrekt berechnet.
:param data: :param data:
:return: bestelldatum (str) :return: bestelldatum (str)
""" """
value = ( request_date = datetime.fromisoformat(data["requestDate"])
datetime.fromisoformat(f"{data['requestDate']}+00:00") # Datum ohne Zeitzone ist wahrscheinlich UTC.
.astimezone() if not request_date.tzinfo:
.strftime("%Y-%m-%d %H:%M:%S %Z") request_date = request_date.replace(tzinfo=timezone.utc)
) value = request_date.astimezone().strftime("%Y-%m-%d %H:%M %Z")
return value return value
...@@ -70,6 +73,47 @@ def print_ppa_group(data: dict) -> str: ...@@ -70,6 +73,47 @@ def print_ppa_group(data: dict) -> str:
return "" return ""
def pre_story_to_story(pre_story: list, style: ParagraphStyle) -> list:
"""
Erstellt aus Sting-Elementen einen Paragraph mit Stil.
Nicht-Strings werden übernommen, wie sie sind.
Möchte man einen anderen ParagraphStyle für den Paragraphen, muss man diesen so abliefern.
:param pre_story:
:param style:
:return:
"""
story = [
(
Paragraph(unicodedata.normalize("NFC", line), style=style)
if isinstance(line, str)
else line
)
for line in pre_story
]
return story
def watermark(canvas, page_width, page_height, font_size):
"""
Fügt einem canvas ein Wasserzeichen in der vorgegebenen Schriftgröße hinzu.
Für die Platzierung wird Seitenbreite- und höhe genutzt. Das Wasserzeichen erscheint in der oberen Hälfte.
:param canvas:
:param page_width:
:param page_height:
:param font_size:
:return:
"""
canvas.setFillColor(colors.grey, alpha=0.4)
canvas.setFont("dejavu-mono", font_size)
# Startkoordinaten verschieben (oberes Viertel), anschließend dort drehen
canvas.translate(page_width / 2, 3 * page_height / 4)
canvas.rotate(45)
canvas.drawCentredString(0 * mm, 0 * mm, "Testsystem")
canvas.rotate(-45)
# Definition der Schrift # Definition der Schrift
registerFont(TTFont("dejavu-mono", "DejaVuSansMono.ttf")) registerFont(TTFont("dejavu-mono", "DejaVuSansMono.ttf"))
registerFont(TTFont("dejavu-mono-bold", "DejaVuSansMono-Bold.ttf")) registerFont(TTFont("dejavu-mono-bold", "DejaVuSansMono-Bold.ttf"))
...@@ -80,6 +124,15 @@ registerFontFamily( ...@@ -80,6 +124,15 @@ registerFontFamily(
italic="", italic="",
boldItalic="", boldItalic="",
) )
registerFont(TTFont("dejavu-sans", "DejaVuSans.ttf"))
registerFont(TTFont("dejavu-sans-bold", "DejaVuSans-Bold.ttf"))
registerFontFamily(
"dejavu-sans",
normal="dejavu-sans",
bold="dejavu-sans-bold",
italic="",
boldItalic="",
)
def reservation_order_a4(data: dict) -> BytesIO: def reservation_order_a4(data: dict) -> BytesIO:
...@@ -189,25 +242,11 @@ def reservation_order_a4(data: dict) -> BytesIO: ...@@ -189,25 +242,11 @@ def reservation_order_a4(data: dict) -> BytesIO:
), ),
f"Auslage bis: <b>{auslage_bis(data)}</b>", f"Auslage bis: <b>{auslage_bis(data)}</b>",
] ]
story = [ frame.addFromList(pre_story_to_story(pre_story, default_style), canvas)
(
Paragraph(unicodedata.normalize("NFC", line), style=default_style)
if isinstance(line, str)
else line
)
for line in pre_story
]
frame.addFromList(story, canvas)
# Handelt es sich um das Testsystem, fügen wir ein Wasserzeichen ein # Handelt es sich um das Testsystem, fügen wir ein Wasserzeichen ein
if os.environ.get("TESTSYSTEM"): if os.environ.get("TESTSYSTEM"):
canvas.setFillColor(colors.grey, alpha=0.4) watermark(canvas, *A4, 70)
canvas.setFont("dejavu-mono", 70)
# Startkoordinaten verschieben (oberes Viertel), anschließend dort drehen
canvas.translate(A4[0] / 2, 3 * A4[1] / 4)
canvas.rotate(45)
canvas.drawCentredString(0 * mm, 0 * mm, "Testsystem")
canvas.save() canvas.save()
...@@ -257,53 +296,174 @@ def reservation_bon(data: dict) -> BytesIO: ...@@ -257,53 +296,174 @@ def reservation_bon(data: dict) -> BytesIO:
data["itemBarcode"], writer=barcode.writer.ImageWriter(), add_checksum=False data["itemBarcode"], writer=barcode.writer.ImageWriter(), add_checksum=False
).write(volume_barcode, text="") ).write(volume_barcode, text="")
story = [ pre_story = [
Paragraph("Bibliothekssystem", style=center_style), Paragraph("Bibliothekssystem", style=center_style),
Paragraph("JLU Gießen", style=center_style), Paragraph("JLU Gießen", style=center_style),
Spacer(0, 3 * spacer_size), Spacer(0, 3 * spacer_size),
Paragraph("Zweigbibliothek Philosophikum II", style=default_style), "Zweigbibliothek Philosophikum II",
Paragraph("Karl-Glöckner-Straße 21 F", style=default_style), "Karl-Glöckner-Straße 21 F" "35394 Gießen",
Paragraph("35394 Gießen", style=default_style),
Spacer(0, 3 * spacer_size), Spacer(0, 3 * spacer_size),
# Paragraph("Signatur", style=default_style), f'<b><font size="12">{data["itemCallNumber"]}</font></b>',
Paragraph(
f'<b><font size="12">{data["itemCallNumber"]}</font></b>',
style=default_style,
),
Spacer(0, 4 * spacer_size), Spacer(0, 4 * spacer_size),
Paragraph( escape(data.get("instanceContributorName", "-")[:32]),
unicodedata.normalize("NFC", escape(data.get("instanceContributorName", "-")))[:32], escape(data.get("instanceTitle", "-")[: 2 * 32]),
style=default_style,
),
Paragraph(
unicodedata.normalize("NFC", escape(data.get("instanceTitle", "-")))[: 2 * 32],
style=default_style,
),
Spacer(0, 3 * spacer_size), Spacer(0, 3 * spacer_size),
Image(volume_barcode, width=72 * mm, height=25 * mm, kind="proportional"), Image(volume_barcode, width=72 * mm, height=25 * mm, kind="proportional"),
Paragraph(data["itemBarcode"], style=center_style), Paragraph(data["itemBarcode"], style=center_style),
Spacer(0, 3 * spacer_size), Spacer(0, 3 * spacer_size),
Paragraph( f'Auslage bis: <b><font size="12">{auslage_bis(data)}</font></b>',
f'Auslage bis: <b><font size="12">{auslage_bis(data)}</font></b>',
style=default_style,
),
Spacer(0, 3 * spacer_size), Spacer(0, 3 * spacer_size),
Paragraph( f'Benutzernummer: xxxx<b><font size="12">{data.get("requesterBarcode", "")[-4:]}</font></b> {print_ppa_group(data)}',
f'Benutzernummer: xxxx<b><font size="12">{data.get("requesterBarcode", "")[-4:]}</font></b> {print_ppa_group(data)}',
style=default_style,
),
] ]
frame.addFromList(story, canvas) frame.addFromList(pre_story_to_story(pre_story, default_style), canvas)
# Handelt es sich um das Testsystem, fügen wir ein Wasserzeichen ein # Handelt es sich um das Testsystem, fügen wir ein Wasserzeichen ein
if os.environ.get("TESTSYSTEM"): if os.environ.get("TESTSYSTEM"):
canvas.setFillColor(colors.grey, alpha=0.4) watermark(canvas, *pagesize, 30)
canvas.setFont("dejavu-mono", 30)
# Startkoordinaten verschieben (oberes Viertel), anschließend dort drehen
canvas.translate(72 * mm / 2, 3 * 150 * mm / 4)
canvas.rotate(45)
canvas.drawCentredString(0 * mm, 0 * mm, "Testsystem")
canvas.save() canvas.save()
return buffer return buffer
def retro_a4(data: dict) -> BytesIO:
"""
Erzeugt einen Retro-Bestellzettel.
:param data:
:return:
"""
buffer = BytesIO()
canvas = Canvas(buffer)
canvas.line(0, A4[1] / 2, A4[0], A4[1] / 2)
font_name = "dejavu-sans"
font_size = 10
spacer_size = 0.75 * font_size
default_style = ParagraphStyle(
"default",
fontName=font_name,
fontSize=font_size,
bulletFontName=font_name,
spaceBefore=1,
justifyLastLine=1,
justifyBreak=1,
)
center_style = ParagraphStyle(
"default",
fontName=font_name,
fontSize=font_size,
spaceBefore=1,
justifyLastLine=1,
justifyBreak=1,
alignment=TA_CENTER,
)
frame_left = Frame(
0,
A4[1] / 2,
50 * mm,
A4[1] / 2 - 20 * mm,
leftPadding=5 * mm,
topPadding=5 * mm,
bottomPadding=5 * mm,
rightPadding=0 * mm,
showBoundary=1,
)
frame_middle = Frame(
50 * mm,
A4[1] / 2,
A4[0] - 100 * mm,
A4[1] / 2 - 5 * mm,
leftPadding=5 * mm,
topPadding=5 * mm,
bottomPadding=5 * mm,
rightPadding=5 * mm,
showBoundary=1,
)
frame_right = Frame(
A4[0] - 50 * mm,
A4[1] / 2,
50 * mm,
A4[1] / 2 - 20 * mm,
leftPadding=0 * mm,
topPadding=5 * mm,
bottomPadding=5 * mm,
rightPadding=5 * mm,
showBoundary=1,
)
story_left = [
"Besteller/in",
f"<b>{data['requesterLastName']},</b>",
f"<b>{data.get('requesterFirstName', '-')}</b>",
f"<font size=\"8\">{escape(data.get('requesterAddressLine1', ''))}</font>",
f"<font size=\"8\">{escape(data.get('requesterAddressLine2', '-'))}</font>",
Spacer(0, spacer_size),
"Lieferung an",
f"{data.get('customFieldLieferungAn', '-')}",
Spacer(0, spacer_size),
"Nutzergruppe",
f"{data.get('requesterPatronGroupName')}",
Spacer(0, spacer_size),
"Nutzernummer",
f"<b>{data.get('requesterBarcode', '-')}</b>",
Spacer(0, spacer_size),
"Theke",
f"<b>{data['pickupServicePointName']}</b>",
Spacer(0, spacer_size),
"Bestelldatum",
f"{bestelldatum(data)}",
Spacer(0, spacer_size),
"Auslage bis",
f"<b>{auslage_bis(data)}</b>",
]
story_middle = [
Paragraph('<font size="16"><b>Bestellschein</b></font>', style=center_style),
Spacer(0, 2 * spacer_size),
Image(
BytesIO(b64decode(data.get("itemRetroCard"))),
width=A4[0] - 100 * mm,
height=500 * mm,
kind="proportional",
),
Spacer(0, 2 * spacer_size),
Paragraph(f"hebis Retro ID: <b>{data['itemRetroId']}</b>", style=center_style),
]
standorte = [
"Freihandbereich / Lesesaal",
"Zweigbibliothek ZNL",
"Zweigbibliothek Re/Wi",
"Zweigbibliothek Zeughaus",
"Zweigbibliothek Phil II",
"dezentrale Fachbibliothek",
]
def vorhanden_in():
for item in standorte:
yield Spacer(0, spacer_size)
yield Paragraph(
f'<font size="8"><bullet>\u25cb</bullet> {item}</font>',
style=default_style,
)
story_right = [
"<b>Universitätsbibliothek</b>",
"<b>Otto-Behagel-Str. 8</b>",
"<b>34394 Gießen</b>",
Spacer(0, spacer_size),
"Vorhanden",
*vorhanden_in(),
]
frame_middle.addFromList(pre_story_to_story(story_middle, default_style), canvas)
frame_left.addFromList(pre_story_to_story(story_left, default_style), canvas)
frame_right.addFromList(pre_story_to_story(story_right, default_style), canvas)
canvas.save()
return buffer
[
{
"id": "16061ec0-7bb0-4dd9-a8d8-477e907e1e5b",
"successfully_printed": false,
"external_id": "e19a6738-3740-4f23-af30-e417772708d7",
"origin": "retro",
"print_group_name": "retro",
"data": {
"requestId": "b84a1e01-7e5b-4de5-95ef-d13288e42aa8",
"requestDate": "2024-11-12 11:55:10.457197+00:00",
"itemIssue": "",
"itemRetroId": "g6580146",
"itemRetroCard": "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",
"itemMaterialTypeName": "Retro",
"pickupServicePointName": "Ausleihe/UB",
"requesterBarcode": "00099997",
"requesterPatronGroupId": "9e7a5f7d-bf8a-408f-a02e-f0f5576a8214",
"requesterPatronGroupName": "UB-Mitarbeiter",
"requesterFirstName": "Testnutzer",
"requesterLastName": "HRZ-Administrator",
"requesterAddressLine1": "zH Stefan",
"requesterAddressLine2": "Heinrich-Buff-Ring 44",
"requesterAddressPostalCode": "35392",
"requesterAddressCity": "Gießen",
"customFieldsLieferungAn": "ZSK000"
}
}
]
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment