Fix planche generation issues

This commit is contained in:
2025-08-05 20:58:05 +02:00
parent 6a05e46946
commit d706ae1645
25 changed files with 85 additions and 68 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -23,7 +23,7 @@
"model": "tikette.tisub",
"pk": 4,
"fields": {
"name": "qty",
"name": "q",
"descritpion": "Poids net (g)",
"default": "370",
"type": "ST"
@@ -43,7 +43,7 @@
"model": "tikette.tisub",
"pk": 6,
"fields": {
"name": "fruit",
"name": "f",
"descritpion": "Quantité de fruits pour 100g (g)",
"default": "60",
"type": "ST"

View File

@@ -50,7 +50,7 @@ class Tikette(models.Model):
description = models.TextField()
color = models.CharField(max_length=6)
ab = models.CharField(max_length=7, choices=AbVisibility)
# designation_fontsize is hardcoded to 42.6667
# designation_fontsize is hardcoded to 42.6667 in planche/generate.py
def __str__(self):
return self.title

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 210 297"
height="297mm"
width="210mm">
<g transform="translate(3, 4.5)">
<g transform="translate(-42,144) rotate(-90,144,0)">
<g transform="translate( 0,0)">$right0</g>
<g transform="translate( 48,0)">$right1</g>
<g transform="translate( 96,0)">$right2</g>
<g transform="translate(144,0)">$right3</g>
<g transform="translate(192,0)">$right4</g>
<g transform="translate(240,0)">$right5</g>
</g>
<g transform="translate(-42,144) rotate(90,144,0)">
<g transform="translate( 0,0)">$left0</g>
<g transform="translate( 48,0)">$left1</g>
<g transform="translate( 96,0)">$left2</g>
<g transform="translate(144,0)">$left3</g>
<g transform="translate(192,0)">$left4</g>
<g transform="translate(240,0)">$left5</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 896 B

View File

@@ -7,6 +7,8 @@ from .makeplanche import makeplanche
OUT_DIR = tempfile.gettempdir()
DEFAULT_DPI = 300
DESIGNATION_FONTSIZE = 42.6667
def inkscapize(svg_in, pdf_out):
png_out = tempfile.mktemp(suffix='.png')
@@ -22,31 +24,31 @@ def inkscapize(svg_in, pdf_out):
os.unlink(png_out)
def generate(request, out_dir):
def generate(template, subs, out_dir, landscape=False):
""" Generate a sticker sheet.
request: dict-like with the following fields:
sticker: mandatory. filename for the sticker
subs: mandatory. dict-like with key-value template subtitution fields
landscape: optional. defaults to False
template: file name for the sticker template
subs: dict-like with key-value template subtitution fields
out_dir: you get it
landscape: optional. defaults to False
"""
# default designation font size
subs['designation_fontsize'] = subs.get('designation_fontsize',
DESIGNATION_FONTSIZE)
# fill in sticker details
sticker_out = tempfile.mktemp(suffix='.svg')
try:
with open(sticker_out, 'w') as stickout:
landscape = request.get('landscape', False)
makesticker(os.path.join(out_dir, request['sticker']), stickout,
request['subs'], landscape=landscape)
makesticker(os.path.join(out_dir, template), stickout, subs)
# make sticker sheet
planche_out = tempfile.mktemp(suffix='.svg')
with open(sticker_out, 'r') as stickin:
with open(planche_out, 'w') as planchout:
makeplanche(stickin, planchout)
makeplanche(stickin, planchout, landscape=landscape)
# process to printable pdf
pdf_out = tempfile.mktemp(dir=out_dir, suffix='.pdf')

View File

@@ -20,6 +20,9 @@ def parse_args():
default=sys.stdout,
type=argparse.FileType('w'),
help='output path (default: stdout)')
parser.add_argument('--landscape',
action='store_true',
help='input sticker is in landscape orientation')
parser.add_argument('sticker',
type=argparse.FileType('r'),
default=sys.stdin,
@@ -29,7 +32,7 @@ def parse_args():
return parser.parse_args()
def makeplanche(sticker, out, template=DEFAULT_SHEET_TEMPLATE):
def makeplanche(sticker, out, template=DEFAULT_SHEET_TEMPLATE ,landscape=False):
with open(template) as tpl:
tpl_data = tpl.read()
@@ -38,19 +41,11 @@ def makeplanche(sticker, out, template=DEFAULT_SHEET_TEMPLATE):
lines = lines[1:]
sticker_data = ''.join(lines)
rotate = "translate(102, 0) rotate(90)" if not landscape else ""
subs = {
'left0': sticker_data,
'left1': sticker_data,
'left2': sticker_data,
'left3': sticker_data,
'left4': sticker_data,
'left5': sticker_data,
'right0': sticker_data,
'right1': sticker_data,
'right2': sticker_data,
'right3': sticker_data,
'right4': sticker_data,
'right5': sticker_data,
'sticker': sticker_data,
'rotate': rotate,
}
out.write(Template(tpl_data).substitute(subs))

View File

@@ -22,25 +22,18 @@ def parse_args():
parser.add_argument('--teneur', '-t', required=False, help='Teneur en sucre')
parser.add_argument('--fruit', '-f', required=False, help='Quantité de fruits')
parser.add_argument('--size', '-s', required=False, help='Masse de produit')
parser.add_argument('--landscape',
action='store_true',
help='input sticker is in landscape orientation')
parser.add_argument('sticker', help='path to the sticker template')
return parser.parse_args()
def makesticker(sticker: str, out: typing.IO, subs: dict, landscape=False):
def makesticker(sticker: str, out: typing.IO, subs: dict):
with open(sticker) as fin:
lines = fin.readlines()
if lines[0].startswith('<?xml'):
lines = lines[1:]
sticker_data = ''.join(lines)
if landscape:
# Rotate the sticker 90 degrees
sticker_data = "<g transform=\"rotate(-90,0,0) translate(-102,0)\">{}</g>".format(sticker_data)
out.write(Template(sticker_data).substitute(subs))
@@ -50,8 +43,8 @@ if __name__ == "__main__":
'dluo': args.pop('dluo'),
'lot': args.pop('lot'),
'teneur': args.pop('teneur'),
'fruit': args.pop('fruit'),
'qty': args.pop('quantite'),
'f': args.pop('fruit'),
'q': args.pop('quantite'),
'size': args.pop('size'),
}
args['subs'] = subs

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 210 297"
height="297mm"
width="210mm">
<g transform="translate(3, 4.5)">
<g transform="translate(0, 0) ${rotate} scale(0.26458)">${sticker}</g>
<g transform="translate(0, 48) ${rotate} scale(0.26458)">${sticker}</g>
<g transform="translate(0, 96) ${rotate} scale(0.26458)">${sticker}</g>
<g transform="translate(0, 144) ${rotate} scale(0.26458)">${sticker}</g>
<g transform="translate(0, 192) ${rotate} scale(0.26458)">${sticker}</g>
<g transform="translate(0, 240) ${rotate} scale(0.26458)">${sticker}</g>
<g transform="rotate(180, 102, 144)">
<g transform="translate(0, 0) ${rotate} scale(0.26458)">${sticker}</g>
<g transform="translate(0, 48) ${rotate} scale(0.26458)">${sticker}</g>
<g transform="translate(0, 96) ${rotate} scale(0.26458)">${sticker}</g>
<g transform="translate(0, 144) ${rotate} scale(0.26458)">${sticker}</g>
<g transform="translate(0, 192) ${rotate} scale(0.26458)">${sticker}</g>
<g transform="translate(0, 240) ${rotate} scale(0.26458)">${sticker}</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -5,18 +5,34 @@ from django.http import JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from . import generate as stickersheet
from .planche import generate as stickersheet
from .models import Tikette, Tikategory
CORS={'access-control-allow-origin': '*'}
def quirk_bold_allergens(ingredients):
out = []
for ing in (x.strip() for x in ingredients.split(',')):
if ing.startswith('*'):
out.append(f'<tspan style="font-weight:bold">{ing[1:]}</tspan>')
else:
out.append(ing)
return ", ".join(out)
def get_list(request):
tikettes = [{
'id': x.id,
'title': x.title,
'category': x.category.name,
'prototempalte': x.category.prototempalte.name,
'landscape': x.category.landscape,
'designation': x.designation,
'ingredients': quirk_bold_allergens(x.ingredients),
'description': x.description,
'ab': x.ab,
'color': x.color,
'subs': {x.name: x.default for x in x.category.subs.all()},
} for x in Tikette.objects.all()]
return JsonResponse({'status': 'ok', 'tikettes': tikettes}, headers=CORS)
@@ -36,7 +52,14 @@ def generate(request):
return JsonResponse({'status': 'notok', 'message': 'this isn\'t the way'})
payload = json.loads(request.body)
pdfpath = stickersheet.generate(payload, out_dir=settings.TIKETTE_OUT_DIR)
subs = dict(payload['subs'])
for key in ('designation', 'ingredients', 'description', 'color', 'AB'):
subs[key] = payload[key]
pdfpath = stickersheet.generate(template=payload['template'], subs=subs,
out_dir=settings.TIKETTE_OUT_DIR,
landscape=payload['landscape'])
return JsonResponse({'status': 'ok', 'file': pdfpath}, headers=CORS)