Skip to content

Commit

Permalink
feat: replace treepoem/ghostscript by zint/pyzint for barcode generation
Browse files Browse the repository at this point in the history
  • Loading branch information
danh91 committed Nov 30, 2024
1 parent 15fa9af commit db8e445
Show file tree
Hide file tree
Showing 17 changed files with 37,902 additions and 35,218 deletions.
3 changes: 3 additions & 0 deletions apps/dashboard/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const moduleExports = {
reactStrictMode: true,
transpilePackages: ['@karrio/core', '@karrio/hooks', '@karrio/ui', '@karrio/lib', '@karrio/types'],
basePath: BASE_PATH,
experimental: {
missingSuspenseWithCSRBailout: false,
},
sassOptions: {
includePaths: [path.join(__dirname, 'src', 'styles')],
},
Expand Down
12 changes: 6 additions & 6 deletions apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "^3.6.1",
"@docusaurus/plugin-client-redirects": "^3.6.1",
"@docusaurus/preset-classic": "^3.6.1",
"@docusaurus/theme-mermaid": "^3.6.1",
"@docusaurus/core": "^3.6.3",
"@docusaurus/plugin-client-redirects": "^3.6.3",
"@docusaurus/preset-classic": "^3.6.3",
"@docusaurus/theme-mermaid": "^3.6.3",
"@fortawesome/fontawesome-free": "^6.4.2",
"@heroicons/react": "^2.1.5",
"@mdx-js/react": "^3.0.0",
Expand All @@ -39,8 +39,8 @@
"tailwind-loader": "file:plugins/tailwind-loader"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.6.1",
"@docusaurus/types": "^3.6.1",
"@docusaurus/module-type-aliases": "^3.6.3",
"@docusaurus/types": "^3.6.3",
"tailwindcss": "^3.3.5"
},
"browserslist": {
Expand Down
4 changes: 2 additions & 2 deletions bin/install-binaries
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
# Install system dependencies
if [ "$(uname)" == "Darwin" ]; then
# Mac OS X platform
brew install gcc pango libffi ghostscript
brew install gcc pango libffi zint
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
# GNU/Linux platform
apt update -y && apt install -y libpango1.0-0 libpangoft2-1.0-0 gcc ghostscript
apt update -y && apt install -y libpango1.0-0 libpangoft2-1.0-0 gcc zint
fi
8 changes: 3 additions & 5 deletions docker/api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,18 @@ LABEL org.opencontainers.image.authors="hello@karrio.io"
ENV DEBUG_MODE=False
ENV USE_HTTPS=False
ENV ALLOWED_HOSTS=*
ENV KARRIO_WORKERS 2
ENV KARRIO_WORKERS=2
ENV BACKGROUND_WORKERS=2
ENV DETACHED_WORKER=False
ENV ADMIN_EMAIL=admin@example.com
ENV ADMIN_PASSWORD=demo
ENV SECRET_KEY="w;l5kj65lk6j;lj56kl56jk5l656j5k6jl5"
ENV WORK_DIR=/karrio/app
ENV LOG_DIR=/karrio/log
ENV WORKER_DB_DIR=/karrio/data
ENV STATIC_ROOT_DIR=/karrio/static

RUN apt-get update -y && apt-get install -y libpango1.0-0 libpangoft2-1.0-0 gcc ghostscript curl
RUN apt-get update -y && apt-get install -y libpango1.0-0 libpangoft2-1.0-0 gcc zint curl
RUN useradd -m karrio -d /karrio
USER karrio

COPY --chown=karrio:karrio --from=compile-image /karrio/ /karrio/
RUN mkdir -p $WORK_DIR $LOG_DIR $WORKER_DB_DIR $STATIC_ROOT_DIR
COPY apps/api/gunicorn-cfg.py docker/api/entrypoint docker/api/worker $WORK_DIR/
Expand Down
20 changes: 10 additions & 10 deletions docker/api/entrypoint
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/bin/bash

export SECRET_KEY=${SECRET_KEY:="0/zfUEetNIle3iNekk4npo4T1pLFAWOyBFgbAu0afB4="}

# Setup DB and static files
karrio migrate || exit
karrio collectstatic --noinput 1> /dev/null || exit
karrio collectstatic --noinput 1>/dev/null || exit

# Setup Default super admin
(echo "
Expand All @@ -14,18 +16,16 @@ if not any(get_user_model().objects.all()):
get_user_model().objects.create_superuser(ADMIN_EMAIL, ADMIN_PASSWORD)
" | karrio shell) || exit


# Start services
if [[ "$DETACHED_WORKER" == "False" ]];
then
set -e # turn on bash's job control
trap 'kill 0' INT
if [[ "$DETACHED_WORKER" == "False" ]]; then
set -e # turn on bash's job control
trap 'kill 0' INT

gunicorn --config gunicorn-cfg.py karrio.server.asgi -k karrio.server.workers.UvicornWorker &
/bin/bash ./worker &
gunicorn --config gunicorn-cfg.py karrio.server.asgi -k karrio.server.workers.UvicornWorker &
/bin/bash ./worker &

wait -n
wait -n

else
gunicorn --config gunicorn-cfg.py karrio.server.asgi -k karrio.server.workers.UvicornWorker
gunicorn --config gunicorn-cfg.py karrio.server.asgi -k karrio.server.workers.UvicornWorker
fi
4 changes: 4 additions & 0 deletions docker/api/worker
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#!/bin/bash

export SECRET_KEY=${SECRET_KEY:="0/zfUEetNIle3iNekk4npo4T1pLFAWOyBFgbAu0afB4="}
export ADMIN_EMAIL=${ADMIN_EMAIL:="admin@example.com"}
export ADMIN_PASSWORD=${ADMIN_PASSWORD:="demo"}

karrio run_huey -w $BACKGROUND_WORKERS
7 changes: 3 additions & 4 deletions docker/dashboard/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV SENTRY_IGNORE_API_RESOLUTION_ERROR=1
ENV NEXTAUTH_SECRET="nasdlfij34l5kj5k6j5kl6lp+lsick5bi*90!mbk7rc3iy_op1r"
ENV NEXT_PUBLIC_KARRIO_PUBLIC_URL=http://locahost:5002
ENV NEXT_PUBLIC_DASHBOARD_URL=http://localhost:3000
ENV NEXT_PUBLIC_DASHBOARD_VERSION=${VERSION}
ENV NEXT_PUBLIC_DASHBOARD_URL=http://localhost:3000
ENV NEXT_PUBLIC_KARRIO_PUBLIC_URL=http://locahost:5002

RUN addgroup -g 1001 -S nodejs
RUN adduser -S karrio -u 1001
USER karrio


COPY --from=builder /app/apps/dashboard/public ./public
Expand All @@ -42,7 +42,6 @@ COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/apps/dashboard/package.json ./package.json
COPY --from=builder /app/docker/dashboard/entrypoint ./entrypoint

USER karrio

EXPOSE 3000

Expand Down
3 changes: 2 additions & 1 deletion docker/dashboard/entrypoint
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#!/bin/bash

# Setup environment variables
export NEXTAUTH_URL=${NEXTAUTH_URL:=$NEXT_PUBLIC_DASHBOARD_URL}
export AUTH_TRUST_HOST=${AUTH_TRUST_HOST:=true}
export NEXTAUTH_URL=${NEXTAUTH_URL:=$NEXT_PUBLIC_DASHBOARD_URL}
export NEXTAUTH_SECRET=${NEXTAUTH_SECRET:="0/zfUEetNIle3iNekk4npo4T1pLFAWOyBFgbAu0afB4="}

# Start services
set -e
Expand Down
4 changes: 2 additions & 2 deletions docker/dev.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
FROM python:3.11-slim-bullseye


RUN apt-get update -y && apt-get install -y gcc libpango1.0-0 libpangoft2-1.0-0 ghostscript
RUN apt-get update -y && apt-get install -y gcc libpango1.0-0 libpangoft2-1.0-0 zint

WORKDIR /karrio
ENV PATH="/karrio/.venv/karrio/bin:$PATH"
EXPOSE 5002

ENV PORT 5002
ENV PORT 5002
3 changes: 1 addition & 2 deletions docker/insiders/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,12 @@ ENV MULTI_ORGANIZATIONS=True
ENV ALLOW_MULTI_ACCOUNT=True
ENV ADMIN_EMAIL=admin@example.com
ENV ADMIN_PASSWORD=demo
ENV SECRET_KEY="w;l5kj65lk6j;lj56kl56jk5l656j5k6jl5"
ENV WORK_DIR=/karrio/app
ENV LOG_DIR=/karrio/log
ENV WORKER_DB_DIR=/karrio/data
ENV STATIC_ROOT_DIR=/karrio/static

RUN apt-get update -y && apt-get install -y libpango1.0-0 libpangoft2-1.0-0 gcc ghostscript curl
RUN apt-get update -y && apt-get install -y libpango1.0-0 libpangoft2-1.0-0 gcc zint curl

RUN useradd -m karrio -d /karrio
USER karrio
Expand Down
20 changes: 10 additions & 10 deletions docker/insiders/entrypoint
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/bin/bash

export SECRET_KEY=${SECRET_KEY:="0/zfUEetNIle3iNekk4npo4T1pLFAWOyBFgbAu0afB4="}

# Setup DB and static files
karrio migrate || exit
karrio collectstatic --noinput 1> /dev/null || exit
karrio collectstatic --noinput 1>/dev/null || exit

# Setup Default super admin
(echo "
Expand All @@ -14,18 +16,16 @@ if not any(get_user_model().objects.all()):
get_user_model().objects.create_superuser(ADMIN_EMAIL, ADMIN_PASSWORD)
" | karrio shell) || exit


# Start services
if [[ "$DETACHED_WORKER" == "False" ]];
then
set -e # turn on bash's job control
trap 'kill 0' INT
if [[ "$DETACHED_WORKER" == "False" ]]; then
set -e # turn on bash's job control
trap 'kill 0' INT

gunicorn --config gunicorn-cfg.py karrio.server.asgi -k karrio.server.workers.UvicornWorker &
/bin/bash ./worker &
gunicorn --config gunicorn-cfg.py karrio.server.asgi -k karrio.server.workers.UvicornWorker &
/bin/bash ./worker &

wait -n
wait -n

else
gunicorn --config gunicorn-cfg.py karrio.server.asgi -k karrio.server.workers.UvicornWorker
gunicorn --config gunicorn-cfg.py karrio.server.asgi -k karrio.server.workers.UvicornWorker
fi
4 changes: 4 additions & 0 deletions docker/insiders/worker
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#!/bin/bash

export SECRET_KEY=${SECRET_KEY:="0/zfUEetNIle3iNekk4npo4T1pLFAWOyBFgbAu0afB4="}
export ADMIN_EMAIL=${ADMIN_EMAIL:="admin@example.com"}
export ADMIN_PASSWORD=${ADMIN_PASSWORD:="demo"}

karrio run_huey -w $BACKGROUND_WORKERS
22 changes: 18 additions & 4 deletions modules/documents/karrio/server/documents/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import base64
import jinja2
import weasyprint
import django.db.models as models
from django.db.models import Sum
import weasyprint.text.fonts as fonts

import karrio.lib as lib
Expand All @@ -18,7 +18,19 @@

FONT_CONFIG = fonts.FontConfiguration()
PAGE_SEPARATOR = '<p style="page-break-before: always"></p>'
STYLESHEETS = ["https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"]
STYLESHEETS = [
weasyprint.CSS(url="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"),
weasyprint.CSS(
string="""
@page { margin: 1cm }
@font-face {
font-family: 'system';
src: local('Arial');
}
body { font-family: 'system', sans-serif; }
"""
),
]
UNITS = {
"PAGE_SEPARATOR": PAGE_SEPARATOR,
"CountryISO": lib.units.CountryISO.as_dict(),
Expand Down Expand Up @@ -66,8 +78,8 @@ def generate(
utils=utils,
lib=lib,
)
or ""
)
or ""
)
},
[
Expand All @@ -94,10 +106,12 @@ def generate(
content = PAGE_SEPARATOR.join(rendered_pages)

buffer = io.BytesIO()
weasyprint.HTML(string=content).write_pdf(
html = weasyprint.HTML(string=content, encoding="utf-8")
html.write_pdf(
buffer,
stylesheets=STYLESHEETS,
font_config=FONT_CONFIG,
optimize_size=("fonts", "images"),
)

return buffer
Expand Down
66 changes: 55 additions & 11 deletions modules/documents/karrio/server/documents/utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import io
import PIL
import pyzint
import base64
import treepoem
from barcode import Code128
from datetime import datetime
from barcode.writer import ImageWriter
import karrio.lib as lib


datetime = datetime
date_format = lib.fdatetime

Expand Down Expand Up @@ -2427,16 +2427,60 @@ def create_barcode(
def generate_code(
data,
code_type: str = "code128",
options: dict = {},
format: str = "PNG",
quality: int = 50,
options: dict = None,
format: str = "BMP",
**kwargs,
) -> str:
barcode = treepoem.generate_barcode(
barcode_type=code_type,
data=data,
options=options,
)
"""Generate a barcode using the pyzint library.
Supported formats:
- PNG: Portable Network Graphics format
- BMP: Bitmap image format
- SVG: Scalable Vector Graphics format
Supported barcode types:
- code128: Code 128 barcode (default)
- qr: QR Code
- datamatrix: Data Matrix
- pdf417: PDF417
- aztec: Aztec Code
- And many more supported by pyzint
Customization:
To customize the barcode appearance and encoding, pass options dict with:
- height: Height of barcode (default 50)
- whitespace_width: Width of whitespace border (default 0)
- border_width: Width of border (default 0)
- scale: Scale factor for barcode (default 1.0)
- show_text: Show human readable text (default True)
- font_size: Size of text (default 10)
Example:
options = {
'height': 100,
'scale': 2.0,
'show_text': False
}
barcode = generate_code('123456', code_type='code128', options=options)
"""
# Get the barcode type class dynamically from pyzint
if options is None:
options = {
"scale": 2,
"show_text": False,
**({"eci": 17} if code_type == "datamatrix" else {}),
**(options or {}),
}

barcode_class = getattr(pyzint.Barcode, code_type.upper())
symbol = barcode_class(data, **options)

buffer = io.BytesIO()
barcode.convert("1").save(buffer, format, quality=quality, optimize=True)
if format.upper() == "SVG":
buffer.write(symbol.render_svg())
else:
# Get BMP data
bmp_data = symbol.render_bmp()
buffer.write(bmp_data)

return base64.b64encode(buffer.getvalue()).decode("utf-8")
2 changes: 1 addition & 1 deletion modules/documents/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
license="Apache-2.0",
packages=find_namespace_packages(exclude=["tests.*", "tests"]),
install_requires=[
"treepoem",
"pyzint",
"weasyprint",
"karrio.server.core",
"karrio.server.graph",
Expand Down
Loading

0 comments on commit db8e445

Please sign in to comment.