Compare commits

...

5 Commits

7 changed files with 73 additions and 30 deletions

3
.dockerignore Normal file
View File

@ -0,0 +1,3 @@
tmp
docker-compose.yaml
.air.toml

14
Dockerfile Normal file
View File

@ -0,0 +1,14 @@
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server
FROM scratch
COPY --from=builder /app/server /server
ADD https://curl.haxx.se/ca/cacert.pem /etc/ssl/certs/ca-certificates.crt
ENTRYPOINT [ "/server" ]

View File

@ -15,11 +15,11 @@ import (
// @Description Generate a contract based on the provided data
// @Tags contracts
// @Accept json
// @Param data body models.Contract true "Contract data"
// @Param data body models.ContractRequest true "Contract data"
// @Produce application/pdf
// @Router /contracts [post]
func GenerateContract(c *fiber.Ctx) error {
contract := new(models.Contract)
contract := new(models.ContractRequest)
if err := c.BodyParser(contract); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": err.Error(),
@ -31,14 +31,7 @@ func GenerateContract(c *fiber.Ctx) error {
})
}
var duplicates int = 2
var duplicatedRunners []models.Runner
for _, runner := range contract.Runners {
for i := 0; i < duplicates; i++ {
duplicatedRunners = append(duplicatedRunners, runner)
}
}
contract.Runners = duplicatedRunners
contract.Runners = repeatRunnerArrayItems(contract.Runners, 2)
generator := services.DefaultTemplater{}
templateString, err := templates.GetTemplate(contract.Locale, "contract")
@ -55,7 +48,7 @@ func GenerateContract(c *fiber.Ctx) error {
})
}
result, err := generator.Execute(template, &models.ContractTemplateOptions{
genConfig := &models.ContractTemplateOptions{
Runners: contract.Runners,
CurrencySymbol: "€",
Disclaimer: "This is a disclaimer",
@ -64,7 +57,9 @@ func GenerateContract(c *fiber.Ctx) error {
SponsoringHeader: templates.ImageSponsoringHeaderBase64,
BarcodeFormat: "ean13",
BarcodePrefix: "1",
})
}
result, err := generator.Execute(template)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": err.Error(),
@ -82,3 +77,13 @@ func GenerateContract(c *fiber.Ctx) error {
c.Set(fiber.HeaderContentType, "application/pdf")
return c.Send(pdf)
}
func repeatRunnerArrayItems(runners []Runner, duplicates int) []Runner {
var duplicatedRunners []models.Runner
for _, runner := range contract.Runners {
for i := 0; i < duplicates; i++ {
duplicatedRunners = append(duplicatedRunners, runner)
}
}
return duplicatedRunners
}

21
models/card.go Normal file
View File

@ -0,0 +1,21 @@
package models
type CardRequest struct {
Cards []Card `json:"card"`
Locale string `json:"locale" enums:"en,de"`
}
type Card struct {
ID int `json:"id"`
Enabled bool `json:"enabled"`
Runner Runner `json:"runner"`
Code string `json:"code"`
}
type ContractTemplateOptions struct {
Cards []Card `json:"cards"`
EventName string `json:"event_name"`
CardSubtitle string `json:"card_subtitle"`
BarcodeFormat string `json:"barcode_format"`
BarcodePrefix string `json:"barcode_prefix"`
}

View File

@ -1,6 +1,6 @@
package models
type Contract struct {
type ContractRequest struct {
Runners []Runner `json:"runners"`
Locale string `json:"locale" enums:"en,de"`
}

View File

@ -30,25 +30,25 @@
<body class="A4 landscape">
<div class="sheet">
<div class="columns is-multiline">
{{#each cards}}
{{ range .cards }}
<div class="column is-half runnercard">
<p class="title is-5" style="text-align: center; padding-bottom: 0; margin-top: -0.75rem;">{{../eventname}}</p>
<p style="text-align: center; margin-top: -1.5rem; font-size: small;">{{../card_subtitle}}</p>
<p class="title is-5" style="text-align: center; padding-bottom: 0; margin-top: -0.75rem;">{{ $.EventName }}</p>
<p style="text-align: center; margin-top: -1.5rem; font-size: small;">{{ $.CardSubtitle }}</p>
<p style="font-size: small;">Mit Unterstützung von:</p>
<div class="columns" style="height: 6rem; overflow: hidden;">
<div class="column is-half">
<!--SPONSOR LOGO HERE-->
<img style="vertical-align: revert; margin-top: auto; object-fit: cover; max-height: 2cm;"
src="{{--sponsor this.id}}" />
src="data:image/png;base64,{{ sponsorLogo .ID }}" />
</div>
<div class="column is-half">
<!--BARCODE HERE-->
<img style="vertical-align: revert; margin-top: auto; object-fit: cover; max-height: 2cm;"
src="{{--bc this.code ../codeformat}}" />
src="data:image/png;base64,{{ barcode .Code $.BarcodeFormat $.BarcodePrefix }}" />
</div>
</div>
<p>{{this.runner.lastname}}, {{this.runner.firstname}} {{this.runner.middlename}}</p>
<p>{{this.runner.group.fullName}}</p>
<p>{{ .Runner.LastName }}, {{ .Runner.FirstName }} {{ .Runner.MiddleName }}</p>
<p>{{ .Runner.Group.Name }}</p>
</div>
{{/each}}
</div>
@ -59,9 +59,9 @@
<div class="column is-half runnercard" style="justify-content: center; align-items: center; text-align: center;">
<!--SPONSOR LOGO FIRST-->
<div style="height: 2cm; padding: 0 0 2.25cm 0">
<img style="object-fit: cover; max-height: 2cm;" src="{{--sponsor this.id}}" />
<img style="object-fit: cover; max-height: 2cm;" src="data:image/png;base64,{{ sponsorLogo .ID }}" />
</div>
<img style="object-fit: cover; max-height: 2.5cm; position: relative;" src="{{--bc this.code ../codeformat}}" />
<img style="object-fit: cover; max-height: 2.5cm; position: relative;" src="data:image/png;base64,{{ barcode .Code $.BarcodeFormat $.BarcodePrefix }}" />
</div>
{{/each}}
</div>

View File

@ -32,23 +32,23 @@
<div class="columns is-multiline">
{{#each cards}}
<div class="column is-half runnercard">
<p class="title is-5" style="text-align: center; padding-bottom: 0; margin-top: -0.75rem;">{{../eventname}}</p>
<p style="text-align: center; margin-top: -1.5rem; font-size: small;">{{../card_subtitle}}</p>
<p class="title is-5" style="text-align: center; padding-bottom: 0; margin-top: -0.75rem;">{{ $.EventName }}</p>
<p style="text-align: center; margin-top: -1.5rem; font-size: small;">{{ $.CardSubtitle }}</p>
<p style="font-size: small;">Supported by:</p>
<div class="columns" style="height: 6rem; overflow: hidden;">
<div class="column is-half">
<!--SPONSOR LOGO HERE-->
<img style="vertical-align: revert; margin-top: auto; object-fit: cover; max-height: 2cm;"
src="{{--sponsor this.id}}" />
src="data:image/png;base64,{{ sponsorLogo .ID }}" />
</div>
<div class="column is-half">
<!--BARCODE HERE-->
<img style="vertical-align: revert; margin-top: auto; object-fit: cover; max-height: 2cm;"
src="{{--bc this.code ../codeformat}}" />
src="data:image/png;base64,{{ barcode .Code $.BarcodeFormat $.BarcodePrefix }}" />
</div>
</div>
<p>{{this.runner.lastname}}, {{this.runner.firstname}} {{this.runner.middlename}}</p>
<p>{{this.runner.group.fullName}}</p>
<p>{{ .Runner.LastName }}, {{ .Runner.FirstName }} {{ .Runner.MiddleName }}</p>
<p>{{ .Runner.Group.Name }}</p>
</div>
{{/each}}
</div>
@ -59,9 +59,9 @@
<div class="column is-half runnercard" style="justify-content: center; align-items: center; text-align: center;">
<!--SPONSOR LOGO FIRST-->
<div style="height: 2cm; padding: 0 0 2.25cm 0">
<img style="object-fit: cover; max-height: 2cm;" src="{{--sponsor this.id}}" />
<img style="object-fit: cover; max-height: 2cm;" src="data:image/png;base64,{{ sponsorLogo .ID }}" />
</div>
<img style="object-fit: cover; max-height: 2.5cm; position: relative;" src="{{--bc this.code ../codeformat}}" />
<img style="object-fit: cover; max-height: 2.5cm; position: relative;" src="data:image/png;base64,{{ barcode .Code $.BarcodeFormat $.BarcodePrefix }}" />
</div>
{{/each}}
</div>