brewery-website/config/extras.py

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)