5d60d33db1
Volledige Foodlinkk Command Center uitbreiding met social automatisering, reclamefolder filters, Proxmox monitoring en documentatie.
81 lines
2.8 KiB
Python
81 lines
2.8 KiB
Python
"""Packaging generation API routes."""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import Any, Literal
|
|
from uuid import uuid4
|
|
|
|
from fastapi import APIRouter, HTTPException, Query
|
|
from fastapi.responses import Response
|
|
from pydantic import BaseModel, Field
|
|
|
|
from app.packaging.export import svg_to_pdf_bytes, svg_to_png_bytes
|
|
from app.packaging.generator import FOODLINKK_BRAND, generate_packaging
|
|
|
|
router = APIRouter(prefix="/packaging", tags=["packaging"])
|
|
|
|
_PROJECTS: dict[str, dict[str, Any]] = {}
|
|
|
|
|
|
class PackagingSpec(BaseModel):
|
|
type: Literal["folding_box", "wrap", "round_label"]
|
|
width_mm: float = Field(default=120, gt=0, le=4000)
|
|
height_mm: float = Field(default=80, gt=0, le=4000)
|
|
depth_mm: float = Field(default=40, ge=0, le=4000)
|
|
elements: dict[str, bool] = Field(default_factory=dict)
|
|
brand: dict[str, str] = Field(default_factory=dict)
|
|
barcode_value: str | None = Field(default=None, max_length=64)
|
|
|
|
|
|
@router.post("/generate")
|
|
def packaging_generate(spec: PackagingSpec) -> dict[str, Any]:
|
|
spec_data = spec.model_dump()
|
|
if not spec_data["brand"]:
|
|
spec_data["brand"] = dict(FOODLINKK_BRAND)
|
|
svg = generate_packaging(spec_data)
|
|
project_id = uuid4().hex
|
|
now = datetime.utcnow().isoformat() + "Z"
|
|
_PROJECTS[project_id] = {
|
|
"id": project_id,
|
|
"created_at": now,
|
|
"spec": spec_data,
|
|
"svg": svg,
|
|
}
|
|
return {"id": project_id, "created_at": now, "svg": svg, "spec": spec_data}
|
|
|
|
|
|
@router.get("/projects")
|
|
def packaging_projects(limit: int = Query(default=30, ge=1, le=200)) -> dict[str, Any]:
|
|
items = sorted(_PROJECTS.values(), key=lambda x: x["created_at"], reverse=True)[:limit]
|
|
return {
|
|
"items": [{"id": p["id"], "created_at": p["created_at"], "spec": p["spec"]} for p in items],
|
|
"count": len(items),
|
|
}
|
|
|
|
|
|
@router.get("/download/{project_id}")
|
|
def packaging_download(project_id: str, format: str = Query(default="svg", pattern="^(svg|png|pdf)$")):
|
|
project = _PROJECTS.get(project_id)
|
|
if not project:
|
|
raise HTTPException(status_code=404, detail="Packaging project not found")
|
|
|
|
svg = project["svg"]
|
|
filename = f"foodlinkk-packaging-{project_id[:8]}.{format}"
|
|
if format == "svg":
|
|
return Response(
|
|
content=svg.encode("utf-8"),
|
|
media_type="image/svg+xml",
|
|
headers={"Content-Disposition": f'attachment; filename="{filename}"'},
|
|
)
|
|
if format == "png":
|
|
return Response(
|
|
content=svg_to_png_bytes(svg),
|
|
media_type="image/png",
|
|
headers={"Content-Disposition": f'attachment; filename="{filename}"'},
|
|
)
|
|
return Response(
|
|
content=svg_to_pdf_bytes(svg),
|
|
media_type="application/pdf",
|
|
headers={"Content-Disposition": f'attachment; filename="{filename}"'},
|
|
)
|