feat(cards): Implement endpoint for card generation

This commit is contained in:
Nicolai Ort 2024-12-03 18:44:17 +01:00
parent ed4941b403
commit 7d22a32cb4
Signed by: niggl
GPG Key ID: 13AFA55AF62F269F
7 changed files with 250 additions and 10 deletions

View File

@ -15,6 +15,33 @@ const docTemplate = `{
"host": "{{.Host}}", "host": "{{.Host}}",
"basePath": "{{.BasePath}}", "basePath": "{{.BasePath}}",
"paths": { "paths": {
"/cards": {
"post": {
"description": "Generate cards based on the provided data",
"consumes": [
"application/json"
],
"produces": [
"application/pdf"
],
"tags": [
"cards"
],
"summary": "Generate runner cards",
"parameters": [
{
"description": "Card data",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.CardRequest"
}
}
],
"responses": {}
}
},
"/contracts": { "/contracts": {
"post": { "post": {
"description": "Generate a contract based on the provided data", "description": "Generate a contract based on the provided data",
@ -35,7 +62,7 @@ const docTemplate = `{
"in": "body", "in": "body",
"required": true, "required": true,
"schema": { "schema": {
"$ref": "#/definitions/models.Contract" "$ref": "#/definitions/models.ContractRequest"
} }
} }
], ],
@ -44,7 +71,42 @@ const docTemplate = `{
} }
}, },
"definitions": { "definitions": {
"models.Contract": { "models.Card": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"enabled": {
"type": "boolean"
},
"id": {
"type": "integer"
},
"runner": {
"$ref": "#/definitions/models.Runner"
}
}
},
"models.CardRequest": {
"type": "object",
"properties": {
"card": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Card"
}
},
"locale": {
"type": "string",
"enum": [
"en",
"de"
]
}
}
},
"models.ContractRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
"locale": { "locale": {

View File

@ -6,6 +6,33 @@
"contact": {} "contact": {}
}, },
"paths": { "paths": {
"/cards": {
"post": {
"description": "Generate cards based on the provided data",
"consumes": [
"application/json"
],
"produces": [
"application/pdf"
],
"tags": [
"cards"
],
"summary": "Generate runner cards",
"parameters": [
{
"description": "Card data",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.CardRequest"
}
}
],
"responses": {}
}
},
"/contracts": { "/contracts": {
"post": { "post": {
"description": "Generate a contract based on the provided data", "description": "Generate a contract based on the provided data",
@ -26,7 +53,7 @@
"in": "body", "in": "body",
"required": true, "required": true,
"schema": { "schema": {
"$ref": "#/definitions/models.Contract" "$ref": "#/definitions/models.ContractRequest"
} }
} }
], ],
@ -35,7 +62,42 @@
} }
}, },
"definitions": { "definitions": {
"models.Contract": { "models.Card": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"enabled": {
"type": "boolean"
},
"id": {
"type": "integer"
},
"runner": {
"$ref": "#/definitions/models.Runner"
}
}
},
"models.CardRequest": {
"type": "object",
"properties": {
"card": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Card"
}
},
"locale": {
"type": "string",
"enum": [
"en",
"de"
]
}
}
},
"models.ContractRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
"locale": { "locale": {

View File

@ -1,5 +1,28 @@
definitions: definitions:
models.Contract: models.Card:
properties:
code:
type: string
enabled:
type: boolean
id:
type: integer
runner:
$ref: '#/definitions/models.Runner'
type: object
models.CardRequest:
properties:
card:
items:
$ref: '#/definitions/models.Card'
type: array
locale:
enum:
- en
- de
type: string
type: object
models.ContractRequest:
properties: properties:
locale: locale:
enum: enum:
@ -39,6 +62,24 @@ info:
for pdf generation. for pdf generation.
title: LfK Document Server API title: LfK Document Server API
paths: paths:
/cards:
post:
consumes:
- application/json
description: Generate cards based on the provided data
parameters:
- description: Card data
in: body
name: data
required: true
schema:
$ref: '#/definitions/models.CardRequest'
produces:
- application/pdf
responses: {}
summary: Generate runner cards
tags:
- cards
/contracts: /contracts:
post: post:
consumes: consumes:
@ -50,7 +91,7 @@ paths:
name: data name: data
required: true required: true
schema: schema:
$ref: '#/definitions/models.Contract' $ref: '#/definitions/models.ContractRequest'
produces: produces:
- application/pdf - application/pdf
responses: {} responses: {}

74
handlers/card.go Normal file
View File

@ -0,0 +1,74 @@
package handlers
import (
"log"
"slices"
"git.odit.services/lfk/document-server/models"
"git.odit.services/lfk/document-server/services"
"git.odit.services/lfk/document-server/templates"
"github.com/gofiber/fiber/v2"
)
// GenerateCard godoc
// @Summary Generate runner cards
// @Description Generate cards based on the provided data
// @Tags cards
// @Accept json
// @Param data body models.CardRequest true "Card data"
// @Produce application/pdf
// @Router /cards [post]
func GenerateCard(c *fiber.Ctx) error {
cardRequest := new(models.CardRequest)
if err := c.BodyParser(cardRequest); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": err.Error(),
})
}
if !slices.Contains([]string{"en", "de"}, cardRequest.Locale) {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Invalid locale",
})
}
generator := services.DefaultTemplater{}
templateString, err := templates.GetTemplate(cardRequest.Locale, "card")
if err != nil {
log.Println(err)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Template not found",
})
}
template, err := generator.StringToTemplate(templateString)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": err.Error(),
})
}
genConfig := &models.CardTemplateOptions{
Cards: cardRequest.Cards,
EventName: "Event name",
CardSubtitle: "Card subtitle",
BarcodeFormat: "ean13",
BarcodePrefix: "",
}
result, err := generator.Execute(template, genConfig)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": err.Error(),
})
}
converter := services.GotenbergConverter{BaseUrl: "http://localhost:3001"}
pdf, err := converter.ToPdf(result, "a5", true)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": err.Error(),
})
}
c.Set(fiber.HeaderContentType, "application/pdf")
return c.Send(pdf)
}

View File

@ -59,7 +59,7 @@ func GenerateContract(c *fiber.Ctx) error {
BarcodePrefix: "1", BarcodePrefix: "1",
} }
result, err := generator.Execute(template) result, err := generator.Execute(template, genConfig)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": err.Error(), "error": err.Error(),
@ -78,9 +78,9 @@ func GenerateContract(c *fiber.Ctx) error {
return c.Send(pdf) return c.Send(pdf)
} }
func repeatRunnerArrayItems(runners []Runner, duplicates int) []Runner { func repeatRunnerArrayItems(runners []models.Runner, duplicates int) []models.Runner {
var duplicatedRunners []models.Runner var duplicatedRunners []models.Runner
for _, runner := range contract.Runners { for _, runner := range runners {
for i := 0; i < duplicates; i++ { for i := 0; i < duplicates; i++ {
duplicatedRunners = append(duplicatedRunners, runner) duplicatedRunners = append(duplicatedRunners, runner)
} }

View File

@ -35,6 +35,7 @@ func main() {
return c.SendString("Hello, World!") return c.SendString("Hello, World!")
}) })
v1.Post("/contracts", handlers.GenerateContract) v1.Post("/contracts", handlers.GenerateContract)
v1.Post("/cards", handlers.GenerateCard)
app.Use(handlers.NotFoundHandler) app.Use(handlers.NotFoundHandler)
docs.SwaggerInfo.BasePath = "/" docs.SwaggerInfo.BasePath = "/"

View File

@ -12,7 +12,7 @@ type Card struct {
Code string `json:"code"` Code string `json:"code"`
} }
type ContractTemplateOptions struct { type CardTemplateOptions struct {
Cards []Card `json:"cards"` Cards []Card `json:"cards"`
EventName string `json:"event_name"` EventName string `json:"event_name"`
CardSubtitle string `json:"card_subtitle"` CardSubtitle string `json:"card_subtitle"`