Files
vet-print-client/templates.py
2026-02-18 05:18:25 -05:00

300 lines
12 KiB
Python

# Template definitions for different label layouts
from PIL import Image, ImageDraw, ImageFont
from datetime import date
def vet_label_template(variables, width_pixels=991, height_pixels=306, filename=None):
"""Default vet label template"""
image = Image.new('RGB', (width_pixels, height_pixels), 'white')
draw = ImageDraw.Draw(image)
try:
font_bold = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', 36)
font_normal = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 32)
font_small = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 28)
font_footer = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Oblique.ttf', 22)
except:
font_bold = ImageFont.load_default()
font_normal = ImageFont.load_default()
font_small = ImageFont.load_default()
font_footer = ImageFont.load_default()
margin = 10
top = margin
left_col = margin
x1 = 200
x2 = 500
x3 = 750
line_height = 50
# Practice name (top left)
draw.text((left_col, top), variables.get('practice_name', ''), fill='black', font=font_bold)
# Date (top right)
today = date.today().strftime("%d %b %Y")
bbox = draw.textbbox((0, 0), today, font=font_small)
date_width = bbox[2] - bbox[0]
draw.text((width_pixels - margin - date_width, top), today, fill='black', font=font_small)
# Three columns of data
y = top + line_height + 10
# Column 1
draw.text((left_col, y), "Animal:", fill='black', font=font_normal)
draw.text((left_col, y + line_height), "Drug:", fill='black', font=font_normal)
draw.text((left_col, y + 2 * line_height), "Dose:", fill='black', font=font_normal)
# Column 2
draw.text((x1, y), variables.get('animal_name', ''), fill='black', font=font_normal)
draw.text((x1, y + line_height), variables.get('drug_name', ''), fill='black', font=font_normal)
draw.text((x1, y + 2 * line_height), variables.get('dosage', ''), fill='black', font=font_normal)
# Column 3
draw.text((x2, y), "Qty:", fill='black', font=font_normal)
draw.text((x2, y + line_height), "Vet:", fill='black', font=font_normal)
draw.text((x3, y), variables.get('quantity', ''), fill='black', font=font_normal)
draw.text((x3, y + line_height), variables.get('vet_initials', ''), fill='black', font=font_normal)
# Footer at bottom
footer_text = "For animal treatment only"
bbox = draw.textbbox((0, 0), footer_text, font=font_footer)
text_width = bbox[2] - bbox[0]
footer_x = (width_pixels - text_width) / 2
footer_y = height_pixels - margin - 20
draw.text((footer_x, footer_y), footer_text, fill='black', font=font_footer)
if filename:
image.save(filename)
return image
def new_label_template(variables, width_pixels=991, height_pixels=306, filename=None):
"""Simplified label template with centered drug and dose"""
image = Image.new('RGB', (width_pixels, height_pixels), 'white')
draw = ImageDraw.Draw(image)
try:
font_header = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', 36)
font_bold = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', 48)
font_normal = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 36)
font_small = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 28)
font_footer = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Oblique.ttf', 22)
except:
font_header = ImageFont.load_default()
font_bold = ImageFont.load_default()
font_normal = ImageFont.load_default()
font_small = ImageFont.load_default()
font_footer = ImageFont.load_default()
margin = 10
top = margin
left_col = margin
x1 = 200
x2 = 500
x3 = 580
line_height = 50
# Practice name (top left)
draw.text((left_col, top), variables.get('practice_name', ''), fill='black', font=font_header)
# Date (top right)
today = date.today().strftime("%d %b %Y")
bbox = draw.textbbox((0, 0), today, font=font_small)
date_width = bbox[2] - bbox[0]
draw.text((width_pixels - margin - date_width, top), today, fill='black', font=font_small)
# Centered drug name (bold)
y = top + line_height + 10
drug_name = variables.get('drug_name', '')
bbox = draw.textbbox((0, 0), drug_name, font=font_bold)
drug_width = bbox[2] - bbox[0]
drug_x = (width_pixels - drug_width) / 2
drug_y = y
draw.text((drug_x, drug_y), drug_name, fill='black', font=font_bold)
# Centered dose underneath
dosage = variables.get('dosage', '')
bbox = draw.textbbox((0, 0), dosage, font=font_normal)
dose_width = bbox[2] - bbox[0]
dose_x = (width_pixels - dose_width) / 2
dose_y = drug_y + 60
draw.text((dose_x, dose_y), dosage, fill='black', font=font_normal)
# Animal and Qty on same line below drug/dose
animal_qty_y = dose_y + 50
draw.text((left_col, animal_qty_y), "Animal:", fill='black', font=font_normal)
draw.text((x1, animal_qty_y), variables.get('animal_name', ''), fill='black', font=font_normal)
draw.text((x2, animal_qty_y), "Qty:", fill='black', font=font_normal)
draw.text((x3, animal_qty_y), variables.get('quantity', ''), fill='black', font=font_normal)
# Expiry and Vet on next line
expiry_vet_y = animal_qty_y + line_height
draw.text((left_col, expiry_vet_y), "Expiry:", fill='black', font=font_normal)
draw.text((x1, expiry_vet_y), variables.get('expiry_date', ''), fill='black', font=font_normal)
draw.text((x2, expiry_vet_y), "Vet:", fill='black', font=font_normal)
draw.text((x3, expiry_vet_y), "________________________", fill='black', font=font_normal)
# Footer at bottom
footer_text = "For animal treatment only"
bbox = draw.textbbox((0, 0), footer_text, font=font_footer)
text_width = bbox[2] - bbox[0]
footer_x = (width_pixels - text_width) / 2
footer_y = height_pixels - margin - 20
draw.text((footer_x, footer_y), footer_text, fill='black', font=font_footer)
if filename:
image.save(filename)
return image
def new_label_large_template(variables, width_pixels=991, height_pixels=413, filename=None):
"""Simplified label template with centered drug and dose - larger format"""
image = Image.new('RGB', (width_pixels, height_pixels), 'white')
draw = ImageDraw.Draw(image)
try:
font_header = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', 36)
font_bold = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', 48)
font_normal = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 36)
font_small = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 28)
font_footer = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Oblique.ttf', 22)
except:
font_header = ImageFont.load_default()
font_bold = ImageFont.load_default()
font_normal = ImageFont.load_default()
font_small = ImageFont.load_default()
font_footer = ImageFont.load_default()
margin = 10
top = margin
left_col = margin
x1 = 200
x2 = 500
x3 = 580
line_height = 60
# Practice name (top left)
draw.text((left_col, top), variables.get('practice_name', ''), fill='black', font=font_header)
# Date (top right)
today = date.today().strftime("%d %b %Y")
bbox = draw.textbbox((0, 0), today, font=font_small)
date_width = bbox[2] - bbox[0]
draw.text((width_pixels - margin - date_width, top), today, fill='black', font=font_small)
# Centered drug name (bold)
y = top + line_height + 20
drug_name = variables.get('drug_name', '')
bbox = draw.textbbox((0, 0), drug_name, font=font_bold)
drug_width = bbox[2] - bbox[0]
drug_x = (width_pixels - drug_width) / 2
drug_y = y
draw.text((drug_x, drug_y), drug_name, fill='black', font=font_bold)
# Centered dose underneath
dosage = variables.get('dosage', '')
bbox = draw.textbbox((0, 0), dosage, font=font_normal)
dose_width = bbox[2] - bbox[0]
dose_x = (width_pixels - dose_width) / 2
dose_y = drug_y + 70
draw.text((dose_x, dose_y), dosage, fill='black', font=font_normal)
# Animal and Qty on same line below drug/dose
animal_qty_y = dose_y + 70
draw.text((left_col, animal_qty_y), "Animal:", fill='black', font=font_normal)
draw.text((x1, animal_qty_y), variables.get('animal_name', ''), fill='black', font=font_normal)
draw.text((x2, animal_qty_y), "Qty:", fill='black', font=font_normal)
draw.text((x3, animal_qty_y), variables.get('quantity', ''), fill='black', font=font_normal)
# Expiry and Vet on next line
expiry_vet_y = animal_qty_y + line_height
draw.text((left_col, expiry_vet_y), "Expiry:", fill='black', font=font_normal)
draw.text((x1, expiry_vet_y), variables.get('expiry_date', ''), fill='black', font=font_normal)
draw.text((x2, expiry_vet_y), "Vet:", fill='black', font=font_normal)
draw.text((x3, expiry_vet_y), "________________________", fill='black', font=font_normal)
# Footer at bottom
footer_text = "For animal treatment only"
bbox = draw.textbbox((0, 0), footer_text, font=font_footer)
text_width = bbox[2] - bbox[0]
footer_x = (width_pixels - text_width) / 2
footer_y = height_pixels - margin - 20
draw.text((footer_x, footer_y), footer_text, fill='black', font=font_footer)
if filename:
image.save(filename)
return image
def notes_1_template(variables, width_pixels=991, height_pixels=413, filename=None):
"""Notes template with animal/date header and wrapped notes"""
image = Image.new('RGB', (width_pixels, height_pixels), 'white')
draw = ImageDraw.Draw(image)
try:
font_header = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', 36)
font_notes = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 32)
font_small = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 28)
except:
font_header = ImageFont.load_default()
font_notes = ImageFont.load_default()
font_small = ImageFont.load_default()
margin = 10
top = margin
left_col = margin
right_margin = margin
line_height = 46
animal = variables.get('animal', '')
note_date = variables.get('date', '')
notes = variables.get('notes', '')
# Animal (left) and date (right) on the same line
draw.text((left_col, top), animal, fill='black', font=font_header)
bbox = draw.textbbox((0, 0), note_date, font=font_small)
date_width = bbox[2] - bbox[0]
draw.text((width_pixels - right_margin - date_width, top + 4), note_date, fill='black', font=font_small)
# Wrapped notes below the header
notes_top = top + line_height + 10
max_width = width_pixels - (left_col + right_margin)
def wrap_text(text, font, max_px):
lines = []
for raw_line in text.splitlines():
words = raw_line.split()
if not words:
lines.append('')
continue
line = []
for word in words:
test_line = ' '.join(line + [word])
bbox = draw.textbbox((0, 0), test_line, font=font)
test_width = bbox[2] - bbox[0]
if test_width <= max_px or not line:
line.append(word)
else:
lines.append(' '.join(line))
line = [word]
if line:
lines.append(' '.join(line))
return lines
for i, line in enumerate(wrap_text(notes, font_notes, max_width)):
draw.text((left_col, notes_top + i * (line_height - 6)), line, fill='black', font=font_notes)
if filename:
image.save(filename)
return image
# Template registry
TEMPLATES = {
'vet_label': vet_label_template,
'new_label': new_label_template,
'new_label_large': new_label_large_template,
'notes_1': notes_1_template,
# Add more templates here, e.g., 'vet_label_small': vet_label_small_template
}