214 lines
7.6 KiB
Python
214 lines
7.6 KiB
Python
import labels
|
|
import datetime
|
|
from random import randint
|
|
from django.db.models import BigIntegerField
|
|
|
|
|
|
from django.urls import reverse
|
|
|
|
from reportlab.graphics import shapes
|
|
from reportlab.graphics.barcode import createBarcodeDrawing
|
|
from reportlab.graphics.barcode.qr import QrCodeWidget
|
|
from reportlab.lib.pagesizes import LETTER
|
|
from config.settings import DEBUG
|
|
|
|
BREWFATHER_APP_ROOT = 'https://web.brewfather.app'
|
|
|
|
def random_with_N_digits(n):
|
|
range_start = 10**(n-1)
|
|
range_end = (10**n)-1
|
|
return randint(range_start, range_end)
|
|
|
|
|
|
class AveryLabel:
|
|
"""
|
|
test_labels = [
|
|
{'manufacturer':'SafAle', 'name':'S-04', 'date':'2024-05-01', 'id':'12345'},
|
|
{'manufacturer':'SafAle', 'name':'US-05', 'date':'2024-05-15', 'id':'23456'}
|
|
]
|
|
|
|
labelSheet = AveryLabel(18294, debug=True)
|
|
labelSheet.render(test_labels, 'filelabels.pdf', 5)
|
|
"""
|
|
|
|
AVERY = {
|
|
18294: ( 4, 15, LETTER, (44.45, 16.764), (7.62, 13.97)),
|
|
5263: ( 2, 5, LETTER, (101.6, 50.8), (3.95, 12.7)),
|
|
}
|
|
|
|
def __init__(self, label, **kwargs):
|
|
data = self.AVERY[label]
|
|
self.across = data[0]
|
|
self.down = data[1]
|
|
self.pagesize = data[2]
|
|
self.labelsize = data[3]
|
|
self.margins = data[4]
|
|
self.topDown = True
|
|
self.debug = False
|
|
self.position = 0
|
|
self.previous_used = 0
|
|
self.corner_radius = 2
|
|
self.__dict__.update(kwargs)
|
|
|
|
self.specs = labels.Specification(
|
|
self.pagesize[0]*0.352778, self.pagesize[1]*0.352778, # Convert from PostScript points to mm
|
|
self.across, self.down,
|
|
self.labelsize[0], self.labelsize[1],
|
|
corner_radius=self.corner_radius,
|
|
left_margin=self.margins[0], right_margin=self.margins[0], top_margin=self.margins[1],
|
|
left_padding=2, right_padding=1, top_padding=1, bottom_padding=0,
|
|
row_gap=0)
|
|
|
|
# def draw_sample(self, label, width, height, obj):
|
|
# if not obj['blank']:
|
|
# obj['path'] = reverse("yeast:sample", kwargs={"sample_id": obj['id']})
|
|
# # Barcode
|
|
# if DEBUG:
|
|
# qrw = QrCodeWidget('https://yeast.giacofei.org/{path}'.format(**obj))
|
|
# else:
|
|
# qrw = QrCodeWidget('https://{host}/{path}'.format(**obj))
|
|
|
|
# b = qrw.getBounds()
|
|
# w=b[2]-b[0]
|
|
# h=b[3]-b[1]
|
|
# psSize = (self.labelsize[1]/0.352778)
|
|
# d = shapes.Drawing(w,h, transform=[(4.5/6) * (psSize/w),0,0,(4.5/6) * (psSize/h),0,0])
|
|
# d.add(qrw)
|
|
# label.add(d)
|
|
|
|
# # Title
|
|
# label.add(shapes.String(
|
|
# 0, # Left Position
|
|
# 5 * height / 6, # Bottom Position
|
|
# '{manufacturer} {name}'.format(**obj), # Text
|
|
# fontName="Helvetica",
|
|
# fontSize=10
|
|
# ))
|
|
|
|
# # Line
|
|
# line_pos = 4.5 * height / 6
|
|
# label.add(shapes.Line(0, line_pos, width,line_pos))
|
|
|
|
# # Metadata
|
|
# label.add(shapes.String(
|
|
# height*.75, # Left Position
|
|
# 3 * height / 6, # Bottom Position
|
|
# 'ID: {id}'.format(**obj), # Text
|
|
# fontName="Helvetica",
|
|
# fontSize=6
|
|
# ))
|
|
# label.add(shapes.String(
|
|
# height*.75, # Left Position
|
|
# 2 * height / 6, # Bottom Position
|
|
# 'Packaging Date: {date}'.format(**obj), # Text
|
|
# fontName="Helvetica",
|
|
# fontSize=6
|
|
# ))
|
|
|
|
def draw(self, label, width, height, obj):
|
|
if not obj['blank']:
|
|
obj['path'] = reverse(
|
|
"{}:{}".format(obj['ns'],obj['template']),
|
|
kwargs={"{}_id".format(obj['template']): obj['id']}
|
|
)
|
|
|
|
# Barcode
|
|
if DEBUG:
|
|
qrw = QrCodeWidget('https://brewery.giacofei.org/{path}'.format(**obj))
|
|
else:
|
|
qrw = QrCodeWidget('https://{host}/{path}'.format(**obj))
|
|
|
|
num_lines = max(len(obj['data']) + 1, 6)
|
|
font = height/num_lines
|
|
|
|
b = qrw.getBounds()
|
|
w=b[2]-b[0]
|
|
h=b[3]-b[1]
|
|
psSize = (self.labelsize[1]/0.352778)
|
|
d = shapes.Drawing(w,h, transform=[(psSize/w),0,0,(psSize/h),0,0])
|
|
d.add(qrw)
|
|
label.add(d)
|
|
|
|
# Line
|
|
line_pos = (num_lines - 1) * height / num_lines
|
|
label.add(shapes.Line(height, line_pos, width,line_pos))
|
|
|
|
# Title
|
|
label.add(shapes.String(
|
|
height, # Left Position
|
|
line_pos * 1.05, # Bottom Position
|
|
'{title}'.format(**obj), # Text
|
|
fontName="Helvetica",
|
|
fontSize=font
|
|
))
|
|
|
|
for x, line in enumerate(obj['data']):
|
|
x=x+1
|
|
label.add(shapes.String(
|
|
height, # Left Position
|
|
line_pos - font * x, # Bottom Position
|
|
line, # Text
|
|
fontName="Helvetica",
|
|
fontSize=font
|
|
))
|
|
|
|
def render(self, objects, render_file, labels_used=0):
|
|
"""
|
|
|
|
# Create the HttpResponse object with the appropriate PDF headers.
|
|
response = HttpResponse(mimetype='application/pdf')
|
|
response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
|
|
"""
|
|
|
|
# Create the sheet.
|
|
# if render_type == 'sample':
|
|
# sheet = labels.Sheet(self.specs, self.draw_sample, border=self.debug)
|
|
|
|
sheet = labels.Sheet(self.specs, self.draw, border=self.debug)
|
|
|
|
# Add a couple of labels.
|
|
for i in range(int(labels_used)):
|
|
sheet.add_label({'blank':True})
|
|
|
|
for entry in objects:
|
|
sheet.add_label(entry)
|
|
|
|
# Save the file and we are done.
|
|
sheet.save(render_file)
|
|
|
|
class DateUUIDField(BigIntegerField):
|
|
"""
|
|
A field which stores a Short UUID value with prepended date. This may also have
|
|
the Boolean attribute 'auto' which will set the value on initial save to a
|
|
new UUID value (calculated using shortuuid's default (uuid4)). Note that while all
|
|
UUIDs are expected to be unique we enforce this with a DB constraint.
|
|
"""
|
|
|
|
def __init__(self, auto=True, *args, **kwargs):
|
|
self.auto = auto
|
|
if auto:
|
|
# Do not let the user edit UUIDs if they are auto-assigned.
|
|
kwargs['editable'] = False
|
|
kwargs['blank'] = True
|
|
kwargs['unique'] = True # if you want to be paranoid, set unique=True in your instantiation of the field.
|
|
|
|
super(DateUUIDField, self).__init__(*args, **kwargs)
|
|
|
|
def pre_save(self, model_instance, add):
|
|
"""
|
|
This is used to ensure that we auto-set values if required.
|
|
See CharField.pre_save
|
|
"""
|
|
value = super(DateUUIDField, self).pre_save(model_instance, add)
|
|
if self.auto and not value:
|
|
# Assign a new value for this attribute if required.
|
|
x = datetime.datetime.now()
|
|
front = x.strftime("%Y%m%d")
|
|
value = int('{}{}'.format(front,random_with_N_digits(6)))
|
|
setattr(model_instance, self.attname, value)
|
|
return value
|
|
|
|
def formfield(self, **kwargs):
|
|
if self.auto:
|
|
return None
|
|
return super(DateUUIDField, self).formfield(**kwargs) |