185 lines
4.4 KiB
Python
185 lines
4.4 KiB
Python
from pathlib import Path
|
|
import argparse
|
|
import csv
|
|
|
|
from jinja2 import Environment, FileSystemLoader
|
|
from weasyprint import HTML
|
|
|
|
|
|
def load_csv(csv_path):
|
|
categories = {}
|
|
|
|
with open(csv_path, newline="", encoding="utf-8-sig") as f:
|
|
sample = f.read(4096)
|
|
f.seek(0)
|
|
|
|
dialect = csv.Sniffer().sniff(sample, delimiters=",;")
|
|
reader = csv.DictReader(f, dialect=dialect)
|
|
|
|
for row in reader:
|
|
normalized = {
|
|
(key or "").strip().lower().replace(" ", "_"): (value or "").strip()
|
|
for key, value in row.items()
|
|
}
|
|
|
|
category = (
|
|
normalized.get("category")
|
|
or normalized.get("catagory")
|
|
or normalized.get("kategorie")
|
|
or "Ostatní"
|
|
)
|
|
|
|
name = (
|
|
normalized.get("name")
|
|
or normalized.get("nazev")
|
|
or normalized.get("název")
|
|
or ""
|
|
)
|
|
|
|
price = (
|
|
normalized.get("price")
|
|
or normalized.get("cena")
|
|
or ""
|
|
)
|
|
|
|
image = (
|
|
normalized.get("image")
|
|
or normalized.get("foto")
|
|
or normalized.get("fotka")
|
|
or normalized.get("obrazek")
|
|
or normalized.get("obrázek")
|
|
or ""
|
|
)
|
|
|
|
show_allergen_icon = (
|
|
normalized.get("show_alergen_icon")
|
|
or normalized.get("show_allergen_icon")
|
|
or normalized.get("alergen_icon")
|
|
or normalized.get("allergen_icon")
|
|
or ""
|
|
).lower() in ("1", "true", "yes", "ano", "y")
|
|
|
|
note = (
|
|
normalized.get("note")
|
|
or normalized.get("description")
|
|
or normalized.get("poznamka")
|
|
or normalized.get("poznámka")
|
|
or ""
|
|
)
|
|
|
|
if category not in categories:
|
|
categories[category] = []
|
|
|
|
categories[category].append({
|
|
"name": name,
|
|
"price": price,
|
|
"image": image,
|
|
"show_allergen_icon": show_allergen_icon,
|
|
"description": note,
|
|
})
|
|
|
|
return categories
|
|
|
|
|
|
def build_catalog_data(title, subtitle, categories):
|
|
return {
|
|
"title": title,
|
|
"subtitle": subtitle,
|
|
"categories": [
|
|
{
|
|
"name": name,
|
|
"products": products,
|
|
}
|
|
for name, products in categories.items()
|
|
],
|
|
}
|
|
|
|
|
|
def render_html(data, template_dir, images_dir):
|
|
env = Environment(
|
|
loader=FileSystemLoader(template_dir)
|
|
)
|
|
|
|
template = env.get_template("catalog.html.j2")
|
|
return template.render(
|
|
catalog=data,
|
|
brand=data,
|
|
settings={
|
|
"columns": 4,
|
|
"page_size": "1024px 768px",
|
|
"margin": "0",
|
|
},
|
|
images_dir=images_dir.as_posix(),
|
|
assets_dir=(Path(__file__).resolve().parent / "assets").as_posix(),
|
|
logo_exists=(Path(__file__).resolve().parent / "assets" / "logo.png").exists(),
|
|
)
|
|
|
|
|
|
def generate_pdf(html_content, output_path):
|
|
HTML(string=html_content).write_pdf(output_path)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument(
|
|
"-i",
|
|
"--input",
|
|
required=True,
|
|
help="CSV input file"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--output",
|
|
default="output/catalog.pdf",
|
|
help="Output PDF path"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--images-dir",
|
|
default="images",
|
|
help="Directory with product images"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--title",
|
|
default="Bistro Ušky",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--subtitle",
|
|
default="Cake & Patisserie",
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
base_dir = Path(__file__).resolve().parent
|
|
|
|
csv_path = Path(args.input)
|
|
output_path = Path(args.output)
|
|
images_dir = Path(args.images_dir)
|
|
|
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
categories = load_csv(csv_path)
|
|
|
|
catalog_data = build_catalog_data(
|
|
args.title,
|
|
args.subtitle,
|
|
categories,
|
|
)
|
|
|
|
html = render_html(
|
|
catalog_data,
|
|
base_dir / "templates",
|
|
images_dir,
|
|
)
|
|
|
|
generate_pdf(html, output_path)
|
|
|
|
print(f"PDF generated: {output_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|