18 Commits
1.4.3 ... 1.5.5

Author SHA1 Message Date
a38a0149b7 fix(templates/certificates): Add point at end of sentence
All checks were successful
Build latest image / build-container (push) Successful in 2m4s
Build release images / build-container (push) Successful in 2m27s
2025-04-25 17:33:43 +02:00
af587b0ac1 feat(certificate): update footer image
All checks were successful
Build latest image / build-container (push) Successful in 1m31s
Build release images / build-container (push) Successful in 1m34s
2025-04-25 16:46:28 +02:00
50e3eff294 feat(certificates): Update footer to generation
All checks were successful
Build latest image / build-container (push) Successful in 1m35s
Build release images / build-container (push) Successful in 1m43s
2025-04-25 16:41:32 +02:00
bc17f7256b Merge branch 'main' of git.odit.services:lfk/document-server
All checks were successful
Build latest image / build-container (push) Successful in 1m34s
2025-04-25 15:50:45 +02:00
d2f3eea8a5 fix(templater): Fix epc generation 2025-04-25 15:50:28 +02:00
f902c61490 feat(certificate): update footer image
All checks were successful
Build release images / build-container (push) Successful in 2m13s
Build latest image / build-container (push) Successful in 2m19s
2025-04-23 11:57:44 +02:00
11e8cc5b1d feat(certificate): Add SepaConfig to certificate generation and CombinedGroupName to runners
All checks were successful
Build release images / build-container (push) Successful in 1m57s
Build latest image / build-container (push) Successful in 2m22s
2025-04-17 22:22:50 +02:00
84155b7404 feat(templater): Add GenerateEPC method for generating EPC QR codes 2025-04-17 22:22:46 +02:00
45b37197ec feat(models): Add CombinedGroupName to RunnerWithDonations and introduce SepaConfig struct 2025-04-17 22:22:43 +02:00
f65848924c feat(templates): Update donation transfer text and add SEPA support in certificate templates 2025-04-17 22:22:37 +02:00
98d584867e feat(config): Add SEPA fields to environment configuration 2025-04-17 22:22:29 +02:00
376e8de1a4 feat(config): Add CurrencyIdentifier to configuration 2025-04-17 22:01:02 +02:00
2911391fb9 feat(config): Add SEPA fields to configuration 2025-04-17 21:51:27 +02:00
6d2e0241c9 feat(templates): Added selfservice qr
All checks were successful
Build release images / build-container (push) Successful in 2m12s
Build latest image / build-container (push) Successful in 2m26s
2025-04-17 21:44:58 +02:00
afc5b1f0c6 fix(models): Add required SelfServiceLink field to RunnerWithDonations struct 2025-04-17 21:43:54 +02:00
4a76ee469b fix(barcode): Use auto encoding for QR code generation to support all characters 2025-04-17 21:43:44 +02:00
b58bf700df chore(static) Add base64 encoded image for new sponsors
All checks were successful
Build latest image / build-container (push) Successful in 2m2s
Build release images / build-container (push) Successful in 2m6s
2025-04-14 18:08:03 +02:00
efd3a35802 fix(templates): Update titles for runner and certificate templates 2025-04-14 17:56:49 +02:00
14 changed files with 117 additions and 18 deletions

6
.env
View File

@@ -16,4 +16,8 @@ SPONSORING_DISCLAIMER=Kaya ist cool, aber pass auf, dass du nicht zu viel Geld s
SPONSORING_BARCODEFORMAT=code128
# SPONSORING_BARCODEPREFIX=
CERTIFICATE_FOOTER=Kaya ist cool, danke für deine Unterstützung!
CERTIFICATE_FOOTER=Kaya ist cool, danke für deine Unterstützung!
SEPA_BIC=FNOMDEB2
SEPA_NAME=ODIT.Services
SEPA_IBAN=DE25100180000690238989

View File

@@ -58,6 +58,12 @@ 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")
@@ -90,6 +96,13 @@ 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,6 +44,7 @@ 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", "")
@@ -54,6 +55,9 @@ 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,10 +11,12 @@ 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 {
@@ -38,4 +40,12 @@ 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,6 +7,7 @@ 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"`
@@ -17,4 +18,7 @@ type Config struct {
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,7 +69,11 @@ func (b *DefaultBarcodeService) GenerateBarcode(format string, content string, w
}
break
case "qr":
generatedCode, err = qr.Encode(content, qr.M, qr.AlphaNumeric)
// 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)
if err != nil {
return bytes.Buffer{}, err
}

View File

@@ -35,6 +35,28 @@ 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
@@ -88,6 +110,7 @@ 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>Sponsoring contract</title>
<title>Läuferkarten</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
<style>
.sheet {

View File

@@ -2,7 +2,7 @@
<head>
<meta charset="utf8">
<title>Sponsoring contract</title>
<title>Runner cards</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
<style>
.sheet {

View File

@@ -2,7 +2,7 @@
<head>
<meta charset="utf8">
<title>Sponsoring contract</title>
<title>Läuferurkunde</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
<style>
.sheet {
@@ -57,7 +57,7 @@
</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}}km</p>
<p style="font-size: 1cm;">für den guten Zweck zurückgelegt</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,13 +87,30 @@
<td>Gesamt</td>
<td>{{ formatUnit "euro" $.Locale .TotalPerDistance }} {{ $.CurrencySymbol }}</td>
<td>{{ formatUnit "euro" $.Locale .TotalDonations }} {{ $.CurrencySymbol }}</td>
</tfoot>
</table>
</main>
<footer class="certificate-footer">
<p>
{{ $.Footer }}
</p>
</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>
</article>
{{ end }}

View File

@@ -2,7 +2,7 @@
<head>
<meta charset="utf8">
<title>Sponsoring contract</title>
<title>Runner certificate</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
<style>
.sheet {
@@ -57,7 +57,7 @@
</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}}km</p>
<p style="font-size: 1cm;">for our good cause at the {{ $.EventName }}</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,8 +91,26 @@
</table>
</main>
<footer class="certificate-footer">
<p>
{{ $.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>
</article>