This commit is contained in:
Pavel Flegr 2026-04-08 17:53:30 +02:00
commit ef105e1cac
22 changed files with 3001 additions and 0 deletions

25
internal/platform/id.go Normal file
View file

@ -0,0 +1,25 @@
package platform
import (
"crypto/rand"
"encoding/hex"
"fmt"
)
func NewID() (string, error) {
buf := make([]byte, 16)
if _, err := rand.Read(buf); err != nil {
return "", fmt.Errorf("read random id bytes: %w", err)
}
return hex.EncodeToString(buf), nil
}
func NewToken() (string, error) {
buf := make([]byte, 32)
if _, err := rand.Read(buf); err != nil {
return "", fmt.Errorf("read random token bytes: %w", err)
}
return hex.EncodeToString(buf), nil
}

View file

@ -0,0 +1,79 @@
package platform
import (
"fmt"
"strconv"
"strings"
)
func FormatCZK(amountMinor int64) string {
sign := ""
if amountMinor < 0 {
sign = "-"
amountMinor = -amountMinor
}
whole := amountMinor / 100
fraction := amountMinor % 100
return fmt.Sprintf("%s%s,%02d CZK", sign, formatThousands(whole), fraction)
}
func ParseCZK(input string) (int64, error) {
clean := strings.TrimSpace(strings.ReplaceAll(input, " ", ""))
clean = strings.ReplaceAll(clean, ",", ".")
if clean == "" {
return 0, fmt.Errorf("amount is required")
}
parts := strings.Split(clean, ".")
if len(parts) > 2 {
return 0, fmt.Errorf("invalid amount")
}
whole, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil {
return 0, fmt.Errorf("invalid whole amount")
}
var fraction int64
if len(parts) == 2 {
frac := parts[1]
if len(frac) > 2 {
return 0, fmt.Errorf("too many decimal places")
}
if len(frac) == 1 {
frac += "0"
}
if len(frac) == 0 {
frac = "00"
}
fraction, err = strconv.ParseInt(frac, 10, 64)
if err != nil {
return 0, fmt.Errorf("invalid decimal amount")
}
}
if whole < 0 || fraction < 0 {
return 0, fmt.Errorf("amount must be positive")
}
return whole*100 + fraction, nil
}
func formatThousands(value int64) string {
plain := strconv.FormatInt(value, 10)
if len(plain) <= 3 {
return plain
}
var parts []string
for len(plain) > 3 {
parts = append([]string{plain[len(plain)-3:]}, parts...)
plain = plain[:len(plain)-3]
}
parts = append([]string{plain}, parts...)
return strings.Join(parts, " ")
}

View file

@ -0,0 +1,31 @@
package platform
import "testing"
func TestParseCZK(t *testing.T) {
tests := []struct {
input string
want int64
}{
{input: "100", want: 10000},
{input: "100.50", want: 10050},
{input: "100,5", want: 10050},
}
for _, tt := range tests {
got, err := ParseCZK(tt.input)
if err != nil {
t.Fatalf("ParseCZK(%q) returned error: %v", tt.input, err)
}
if got != tt.want {
t.Fatalf("ParseCZK(%q) = %d, want %d", tt.input, got, tt.want)
}
}
}
func TestFormatCZK(t *testing.T) {
got := FormatCZK(1234567)
if got != "12 345,67 CZK" {
t.Fatalf("FormatCZK() = %q", got)
}
}