Compare commits

..

No commits in common. "main" and "1.4.2" have entirely different histories.
main ... 1.4.2

18 changed files with 47 additions and 275 deletions

6
.env
View File

@ -11,13 +11,9 @@ CARD_SUBTITLE=Kaya ist cool
CARD_BARCODEFORMAT=ean13
# CARD_BARCODEPREFIX=
SPONSORING_RECEIPTMINIMUM=40
SPONSOING_RECEIPTMINIMUM=40
SPONSORING_DISCLAIMER=Kaya ist cool, aber pass auf, dass du nicht zu viel Geld sammelst!
SPONSORING_BARCODEFORMAT=code128
# SPONSORING_BARCODEPREFIX=
CERTIFICATE_FOOTER=Kaya ist cool, danke für deine Unterstützung!
SEPA_BIC=FNOMDEB2
SEPA_NAME=ODIT.Services
SEPA_IBAN=DE25100180000690238989

View File

@ -8,9 +8,8 @@ RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server
FROM alpine:3.18
RUN mkdir -p /tmp && chmod 1777 /tmp
FROM scratch
COPY --from=builder /app/server /server
COPY static /static
ADD https://curl.haxx.se/ca/cacert.pem /etc/ssl/certs/ca-certificates.crt
ENTRYPOINT [ "/server" ]

16
go.mod
View File

@ -23,11 +23,8 @@ require (
github.com/go-openapi/swag v0.23.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hhrutter/lzw v1.0.0 // indirect
github.com/hhrutter/pkcs7 v0.2.0 // indirect
github.com/hhrutter/tiff v1.0.2 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/makiuchi-d/gozxing v0.1.1 // indirect
@ -36,9 +33,7 @@ require (
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/oxplot/papersizes v0.0.0-20181201065918-90a3a5ae1915 // indirect
github.com/pdfcpu/pdfcpu v0.10.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/redis/go-redis/v9 v9.7.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
@ -51,19 +46,16 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect
github.com/swaggo/files/v2 v2.0.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.61.0 // indirect
github.com/valyala/fasthttp v1.57.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/image v0.26.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/tools v0.27.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

24
go.sum
View File

@ -29,18 +29,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hhrutter/lzw v1.0.0 h1:laL89Llp86W3rRs83LvKbwYRx6INE8gDn0XNb1oXtm0=
github.com/hhrutter/lzw v1.0.0/go.mod h1:2HC6DJSn/n6iAZfgM3Pg+cP1KxeWc3ezG8bBqW5+WEo=
github.com/hhrutter/pkcs7 v0.2.0 h1:i4HN2XMbGQpZRnKBLsUwO3dSckzgX142TNqY/KfXg+I=
github.com/hhrutter/pkcs7 v0.2.0/go.mod h1:aEzKz0+ZAlz7YaEMY47jDHL14hVWD6iXt0AgqgAvWgE=
github.com/hhrutter/tiff v1.0.2 h1:7H3FQQpKu/i5WaSChoD1nnJbGx4MxU5TlNqqpxw55z8=
github.com/hhrutter/tiff v1.0.2/go.mod h1:pcOeuK5loFUE7Y/WnzGw20YxUdnqjY1P0Jlcieb/cCw=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -62,12 +54,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/oxplot/papersizes v0.0.0-20181201065918-90a3a5ae1915 h1:4WzMzgExTgBfuUQ/HegMf+jcHtH+c3fl7eySUQUbfzg=
github.com/oxplot/papersizes v0.0.0-20181201065918-90a3a5ae1915/go.mod h1:LJRTnhoARxQgMyT7T9L+ZzwR4OrmyHTy5LPxZEzE1CM=
github.com/pdfcpu/pdfcpu v0.10.2 h1:DB2dWuoq0eF0QwHjgyLirYKLTCzFOoZdmmIUSu72aL0=
github.com/pdfcpu/pdfcpu v0.10.2/go.mod h1:Q2Z3sqdRqHTdIq1mPAUl8nfAoim8p3c1ASOaQ10mCpE=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
@ -111,8 +99,6 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.57.0 h1:Xw8SjWGEP/+wAAgyy5XTvgrWlOD1+TxbbvNADYCm1Tg=
github.com/valyala/fasthttp v1.57.0/go.mod h1:h6ZBaPRlzpZ6O3H5t2gEk1Qi33+TmLvfwgLLp0t9CpE=
github.com/valyala/fasthttp v1.61.0 h1:VV08V0AfoRaFurP1EWKvQQdPTZHiUzaVoulX1aBDgzU=
github.com/valyala/fasthttp v1.61.0/go.mod h1:wRIV/4cMwUPWnRcDno9hGnYZGh78QzODFfo1LTUhBog=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
@ -125,12 +111,8 @@ go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/image v0.26.0 h1:4XjIFEZWQmCZi6Wv8BoxsDhRU3RVnLX04dToTDAEPlY=
golang.org/x/image v0.26.0/go.mod h1:lcxbMFAovzpnJxzXS3nyL83K27tmqtKzIJpctK8YO5c=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
@ -139,12 +121,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
@ -155,8 +133,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,14 +1,10 @@
package handlers
import (
"fmt"
"os"
"slices"
"git.odit.services/lfk/document-server/models"
"github.com/gofiber/fiber/v2"
"github.com/pdfcpu/pdfcpu/pkg/api"
"github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model"
)
// GenerateCard godoc
@ -22,6 +18,7 @@ import (
// @Security ApiKeyAuth
// @Router /v1/pdfs/cards [post]
func (h *DefaultHandler) GenerateCard(c *fiber.Ctx) error {
logger := h.Logger.Named("GenerateCard")
cardRequest := new(models.CardRequest)
@ -55,17 +52,8 @@ func (h *DefaultHandler) GenerateCard(c *fiber.Ctx) error {
})
}
segmentLength := calculateOptimalSegmentSize(len(cardRequest.Cards))
pdfs := []string{}
for i := 0; i < len(cardRequest.Cards); i += segmentLength {
segment := cardRequest.Cards[i:]
if len(segment) > segmentLength {
segment = cardRequest.Cards[i : i+segmentLength]
}
genConfig := &models.CardTemplateOptions{
CardSegments: splitCardSegments(segment),
CardSegments: splitCardSegments(cardRequest.Cards),
EventName: h.Config.EventName,
CardSubtitle: h.Config.CardSubtitle,
BarcodeFormat: h.Config.CardBarcodeFormat,
@ -91,79 +79,11 @@ func (h *DefaultHandler) GenerateCard(c *fiber.Ctx) error {
"error": err.Error(),
})
}
tempFile, err := os.CreateTemp("", fmt.Sprintf("cards-%d-*.pdf", i/segmentLength))
if err != nil {
logger.Errorw("Error creating temp file", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": err.Error(),
})
}
defer os.Remove(tempFile.Name()) // Ensure cleanup even on error paths
if _, err := tempFile.Write(pdf); err != nil {
logger.Errorw("Error writing pdf to temp file", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": err.Error(),
})
}
tempFile.Close()
pdfs = append(pdfs, tempFile.Name())
}
outputFile := "./output.pdf"
conf := model.NewDefaultConfiguration()
err = api.MergeCreateFile(pdfs, outputFile, false, conf)
if err != nil {
logger.Errorw("Failed to merge PDFs", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": err.Error(),
})
}
// Clean up individual PDF files
for _, file := range pdfs {
if err := os.Remove(file); err != nil {
logger.Warnw("Failed to remove temporary PDF file", "file", file, "error", err)
}
}
// Set headers and return the merged PDF
c.Set(fiber.HeaderContentType, "application/pdf")
c.Set(fiber.HeaderContentDisposition, "attachment; filename=runner-cards.pdf")
pdfBytes, err := os.ReadFile(outputFile)
if err != nil {
logger.Errorw("Failed to read merged PDF", "error", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": err.Error(),
})
}
os.Remove(outputFile) // Clean up the merged file
logger.Info("Converted html to pdf")
c.Set(fiber.HeaderContentType, "application/pdf")
c.Set(fiber.HeaderContentDisposition, "attachment; filename=runner-cards.pdf")
return c.Send(pdfBytes)
}
func calculateOptimalSegmentSize(totalCards int) int {
if totalCards < 30 {
return 25 // Reduces overhead for really small batches
}
// Base size for small batches
if totalCards < 100 {
return 50
}
// For medium batches
if totalCards < 500 {
return 75
}
// For large batches, be more conservative
return 100
return c.Send(pdf)
}
func invertCardArrayItemPairs(cards []models.Card) []models.Card {

View File

@ -58,12 +58,6 @@ func (h *DefaultHandler) GenerateCertificate(c *fiber.Ctx) error {
Footer: h.Config.CertificateFooter,
CurrencySymbol: h.Config.CurrencySymbol,
Locale: certificateRequest.Locale,
SepaConfig: &models.SepaConfig{
BIC: h.Config.SepaBic,
HolderName: h.Config.SepaName,
IBAN: h.Config.SepaIban,
CurrencyIdentifier: h.Config.CurrencyIdentifier,
},
}
logger.Info("Generating certificate html")
@ -96,13 +90,6 @@ func addUpRunnerDonations(runners []models.RunnerWithDonations) []models.RunnerW
runners[i].TotalDonations += runners[i].DistanceDonations[j].Amount
runners[i].TotalPerDistance += runners[i].DistanceDonations[j].AmountPerDistance
}
if runners[i].Group.ParentGroup.Name != "" {
runners[i].CombinedGroupName = runners[i].Group.ParentGroup.Name + " - " + runners[i].Group.Name
} else {
runners[i].CombinedGroupName = runners[i].Group.Name
}
}
return runners
}

View File

@ -44,7 +44,6 @@ func loadEnv() error {
viper.SetDefault("APIKEY", "lfk")
viper.SetDefault("EVENTNAME", "Demo Event")
viper.SetDefault("CURRENCYSYMBOL", "€")
viper.SetDefault("CURRENCYIDENTIFIER", "EUR")
viper.SetDefault("CARD_SUBTITLE", "Runner Card")
viper.SetDefault("CARD_BARCODEFORMAT", "ean13")
viper.SetDefault("CARD_BARCODEPREFIX", "")
@ -55,9 +54,6 @@ func loadEnv() error {
viper.SetDefault("CERTIFICATE_FOOTER", "Footer")
viper.SetDefault("GOTENBERG_BASEURL", "")
viper.SetDefault("REDIS_ADDR", "")
viper.SetDefault("SEPA_BIC", "")
viper.SetDefault("SEPA_NAME", "")
viper.SetDefault("SEPA_IBAN", "")
// Load .env file
viper.SetConfigFile(".env")

View File

@ -11,12 +11,10 @@ type RunnerWithDonations struct {
MiddleName string `json:"middle_name" validate:"optional"`
LastName string `json:"last_name" validate:"required"`
Group Group `json:"group" validate:"required"`
CombinedGroupName string `json:"combined_group_name" validate:"optional"`
Distance int `json:"distance" validate:"required"`
DistanceDonations []DistanceDonation `json:"distance_donations" validate:"optional"`
TotalPerDistance int `json:"total_per_distance" validate:"optional"`
TotalDonations int `json:"total_donations" validate:"optional"`
SelfServiceLink string `json:"self_service_link" validate:"required"`
}
type DistanceDonation struct {
@ -40,12 +38,4 @@ type CertificateTemplateOptions struct {
Footer string `json:"footer"`
CurrencySymbol string `json:"currency_symbol"`
Locale string `json:"locale"`
SepaConfig *SepaConfig `json:"sepa_config"`
}
type SepaConfig struct {
IBAN string `json:"iban" validate:"required"`
HolderName string `json:"holder_name" validate:"required"`
BIC string `json:"bic" validate:"required"`
CurrencyIdentifier string `json:"currency_identifier" validate:"required"`
}

View File

@ -7,18 +7,14 @@ type Config struct {
APIKey string `mapstructure:"APIKEY"`
EventName string `mapstructure:"EVENTNAME"`
CurrencySymbol string `mapstructure:"CURRENCYSYMBOL"`
CurrencyIdentifier string `mapstructure:"CURRENCYIDENTIFIER"`
CardSubtitle string `mapstructure:"CARD_SUBTITLE"`
CardBarcodeFormat string `mapstructure:"CARD_BARCODEFORMAT"`
CardBarcodePrefix string `mapstructure:"CARD_BARCODEPREFIX"`
SponsoringReceiptMinimum string `mapstructure:"SPONSORING_RECEIPTMINIMUM"`
SponsoringReceiptMinimum string `mapstructure:"SPONSOING_RECEIPTMINIMUM"`
SponosringDisclaimer string `mapstructure:"SPONSORING_DISCLAIMER"`
SponsoringBarcodeFormat string `mapstructure:"SPONSORING_BARCODEFORMAT"`
SponsoringBarcodePrefix string `mapstructure:"SPONSORING_BARCODEPREFIX"`
CertificateFooter string `mapstructure:"CERTIFICATE_FOOTER"`
GotenbergBaseUrl string `mapstructure:"GOTENBERG_BASEURL"`
RedisAddr string `mapstructure:"REDIS_ADDR"`
SepaBic string `mapstructure:"SEPA_BIC"`
SepaName string `mapstructure:"SEPA_NAME"`
SepaIban string `mapstructure:"SEPA_IBAN"`
}

View File

@ -69,11 +69,7 @@ func (b *DefaultBarcodeService) GenerateBarcode(format string, content string, w
}
break
case "qr":
// Always use qr.Auto encoding to support all characters in the content
encoding := qr.Auto
// QR code generation with error correction level M and auto encoding
generatedCode, err = qr.Encode(content, qr.M, encoding)
generatedCode, err = qr.Encode(content, qr.M, qr.AlphaNumeric)
if err != nil {
return bytes.Buffer{}, err
}

View File

@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"html/template"
"math"
"strings"
"go.uber.org/zap"
@ -36,28 +35,6 @@ func idToEan13(id string, prefix string) (string, error) {
return id, nil
}
func (t *DefaultTemplater) GenerateEPC(iban string, bic string, name string, title string, amount int, currency string) (string, error) {
var err error
code := fmt.Sprintf(`BCD
002
1
INST
%s
%s
%s
%s%.2f
%s
`, bic, name, iban, currency, float64(amount)/100, title,
)
buf, err := t.BarcodeService.GenerateBarcode("qr", code, 500, 500, 0)
return base64.StdEncoding.EncodeToString(buf.Bytes()), err
}
func (t *DefaultTemplater) GenerateBarcode(code string, format string, prefix string) (string, error) {
var err error
@ -90,24 +67,9 @@ func (t *DefaultTemplater) LoadImage(name string) (string, error) {
func (t *DefaultTemplater) FormatUnit(unit string, locale string, amount int) (string, error) {
var formatted string
var seperator string
switch locale {
case "de":
seperator = " "
default:
seperator = ""
}
switch unit {
case "kilometer":
if amount < 1000 {
formatted = fmt.Sprintf("%d%sm", amount, seperator)
} else if (amount % 1000) == 0 {
formatted = fmt.Sprintf("%d%skm", amount/1000, seperator)
} else {
kilometers := math.Floor(float64(amount) / 1000)
meters := amount - int(kilometers)*1000
formatted = fmt.Sprintf("%d%skm %d%sm", int(kilometers), seperator, meters, seperator)
}
formatted = fmt.Sprintf("%.3f", float64(amount)/1000)
case "euro":
formatted = fmt.Sprintf("%.2f", float64(amount)/100)
default:
@ -126,7 +88,6 @@ func (t *DefaultTemplater) StringToTemplate(templateString string) (*template.Te
"sponsorLogo": t.SelectSponsorImage,
"formatUnit": t.FormatUnit,
"loadImage": t.LoadImage,
"epcCode": t.GenerateEPC,
}).Parse(templateString)
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
<head>
<meta charset="utf8">
<title>Läuferkarten</title>
<title>Sponsoring contract</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
<style>
.sheet {
@ -54,7 +54,7 @@
<p>{{ .Runner.LastName }}, {{ .Runner.FirstName }} {{ .Runner.MiddleName }}</p>
<p>{{ if ne .Runner.Group.ParentGroup.Name "" -}}{{ .Runner.Group.ParentGroup.Name }}/{{end -}}{{ .Runner.Group.Name }}</p>
{{ else }}
<p>Läufer:in</p>
<p>Kein Läufer zugewiesen</p>
{{ end}}
{{ end}}
</div>

View File

@ -2,7 +2,7 @@
<head>
<meta charset="utf8">
<title>Runner cards</title>
<title>Sponsoring contract</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
<style>
.sheet {
@ -53,7 +53,7 @@
<p>{{ .Runner.LastName }}, {{ .Runner.FirstName }} {{ .Runner.MiddleName }}</p>
<p>{{ if ne .Runner.Group.ParentGroup.Name "" -}}{{ .Runner.Group.ParentGroup.Name }}/{{end -}}{{ .Runner.Group.Name }}</p>
{{ else }}
<p>Runner</p>
<p>Blank card</p>
{{ end}}
</div>
{{ end }}

View File

@ -2,7 +2,7 @@
<head>
<meta charset="utf8">
<title>Läuferurkunde</title>
<title>Sponsoring contract</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
<style>
.sheet {
@ -56,8 +56,8 @@
{{ .MiddleName }} {{ .LastName }}
</p>
<p style="font-size: 1cm; margin-bottom: 0;">hat beim {{ $.EventName }}</p>
<p style="font-size: 2cm; font-weight: bold; margin-bottom: 0;">{{formatUnit "kilometer" $.Locale .Distance}}</p>
<p style="font-size: 1cm;">für den guten Zweck zurückgelegt.</p>
<p style="font-size: 2cm; font-weight: bold; margin-bottom: 0;">{{formatUnit "kilometer" $.Locale .Distance}}km</p>
<p style="font-size: 1cm;">für den guten Zweck zurückgelegt</p>
</main>
<footer class="certificate-footer">
<img src="data:image/png;base64,{{ loadImage "certificate_footer" }}">
@ -87,29 +87,12 @@
<td>Gesamt</td>
<td>{{ formatUnit "euro" $.Locale .TotalPerDistance }} {{ $.CurrencySymbol }}</td>
<td>{{ formatUnit "euro" $.Locale .TotalDonations }} {{ $.CurrencySymbol }}</td>
</tfoot>
</table>
</main>
<footer class="certificate-footer">
<table style="border-collapse: collapse; border: none; width: 17cm;">
<thead>
<tr>
<th style="border: none; width: 50%; text-align: center;">Link zu deinen Rundenzeiten</th>
<th style="border: none; width: 50%; text-align: center;">Spende überweisen</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: none; text-align: center;">
<img src="data:image/png;base64,{{ barcode .SelfServiceLink "qr" "" }}" style="height: 2.5cm; padding: 0.2cm">
</td>
<td style="border: none; text-align: center;">
<img src="data:image/png;base64,{{ epcCode $.SepaConfig.IBAN $.SepaConfig.BIC $.SepaConfig.HolderName (print "Spende LfK " .ID ", " .FirstName " " .LastName ", " .CombinedGroupName) .TotalDonations $.SepaConfig.CurrencyIdentifier}}" style="height: 2.5cm; padding: 0.2cm">
</td>
</tr>
</tbody>
</table>
<p style="width: 17cm; text-align: center;">
Sponsoren überweisen ihre Beträge bitte auf unser Konto: {{ $.SepaConfig.HolderName }} | IBAN: {{ $.SepaConfig.IBAN }} | BIC: {{ $.SepaConfig.BIC }} | Vz: "Spende LfK {{.ID}}, {{ .FirstName }} {{ .LastName }}, {{.CombinedGroupName}}"
<p>
{{ $.Footer }}
</p>
</footer>
</article>

View File

@ -2,7 +2,7 @@
<head>
<meta charset="utf8">
<title>Runner certificate</title>
<title>Sponsoring contract</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
<style>
.sheet {
@ -56,8 +56,8 @@
{{ .MiddleName }} {{ .LastName }}
</p>
<p style="font-size: 1cm; margin-bottom: 0;">Ran</p>
<p style="font-size: 2cm; font-weight: bold; margin-bottom: 0;">{{formatUnit "kilometer" $.Locale .Distance}}</p>
<p style="font-size: 1cm;">for our good cause at the {{ $.EventName }}.</p>
<p style="font-size: 2cm; font-weight: bold; margin-bottom: 0;">{{formatUnit "kilometer" $.Locale .Distance}}km</p>
<p style="font-size: 1cm;">for our good cause at the {{ $.EventName }}</p>
</main>
<footer class="certificate-footer">
<img src="data:image/png;base64,{{ loadImage "certificate_footer" }}">
@ -91,26 +91,8 @@
</table>
</main>
<footer class="certificate-footer">
<table style="border-collapse: collapse; border: none; width: 17cm;">
<thead>
<tr>
<th style="border: none; width: 50%; text-align: center;">Link to your lap times</th>
<th style="border: none; width: 50%; text-align: center;">Transfer donation via SEPA</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: none; text-align: center;">
<img src="data:image/png;base64,{{ barcode .SelfServiceLink "qr" "" }}" style="height: 2.5cm; padding: 0.2cm">
</td>
<td style="border: none; text-align: center;">
<img src="data:image/png;base64,{{ epcCode $.SepaConfig.IBAN $.SepaConfig.BIC $.SepaConfig.HolderName (print "Spende LfK " .ID ", " .FirstName " " .LastName ", " .CombinedGroupName) .TotalDonations $.SepaConfig.CurrencyIdentifier}}" style="height: 2.5cm; padding: 0.2cm">
</td>
</tr>
</tbody>
</table>
<p style="width: 17cm; text-align: center;">
Donors, please transfer your donation to our account: {{ $.SepaConfig.HolderName }} | IBAN: {{ $.SepaConfig.IBAN }} | BIC: {{ $.SepaConfig.BIC }} | Ref: "Spende LfK {{.ID}}, {{ .FirstName }} {{ .LastName }}, {{.CombinedGroupName}}"
<p>
{{ $.Footer }}
</p>
</footer>
</article>