Deploy to K8s / deploy (push) Successful in 20s
Go (go/) becomes the primary implementation. The original Python version moves to legacy/ and is kept runnable; new features are still built in both (see the Dual implementation rule in CLAUDE.md). - git mv app.py, scripts/, templates/, tests/, pyproject.toml, uv.lock and build/ into legacy/ - Makefile: Python targets point at legacy/, venv in legacy/.venv, CREDENTIALS_PATH exported for the root .secret/ file - CI and make image build the Python image with legacy/ as context; the Makefile is no longer copied into the image - legacy/.dockerignore moved to the context root so it takes effect - CLAUDE.md, docs/README.md, Go comments, fixture README, capture script and VS Code launch config updated to the new layout Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
50 lines
1.5 KiB
Go
50 lines
1.5 KiB
Go
// Package money ports Czech-locale currency parsing from legacy/scripts/infer_payments.py.
|
|
package money
|
|
|
|
import (
|
|
"errors"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// ErrInvalidAmount is returned by ParseCZK when the input cannot be parsed.
|
|
var ErrInvalidAmount = errors.New("money: invalid CZK amount")
|
|
|
|
// ParseCZK parses a Czech-locale amount string and returns the value in CZK
|
|
// as a float64. Mirrors legacy/scripts/infer_payments.py parse_czk_amount:
|
|
//
|
|
// - empty input → (0, nil)
|
|
// - "Kč"/"CZK" suffixes stripped (case-sensitive, like Python)
|
|
// - comma present → comma is decimal sep, dots/spaces are thousand seps
|
|
// ("1.500,00" → 1500.0)
|
|
// - no comma, 2+ dots → all dots are thousand seps ("1.500.000" → 1500000.0)
|
|
// - no comma, ≤1 dot → dot is decimal sep ("1.500" → 1.5)
|
|
// - on parse failure → (0, ErrInvalidAmount); callers wanting Python's
|
|
// silent-zero behaviour can discard the error: v, _ := ParseCZK(s)
|
|
func ParseCZK(s string) (float64, error) {
|
|
if s == "" {
|
|
return 0, nil
|
|
}
|
|
|
|
s = strings.ReplaceAll(s, "Kč", "")
|
|
s = strings.ReplaceAll(s, "CZK", "")
|
|
s = strings.TrimSpace(s)
|
|
|
|
if strings.ContainsRune(s, ',') {
|
|
s = strings.ReplaceAll(s, ".", "")
|
|
s = strings.ReplaceAll(s, " ", "")
|
|
s = strings.ReplaceAll(s, ",", ".")
|
|
} else if strings.Count(s, ".") > 1 {
|
|
s = strings.ReplaceAll(s, ".", "")
|
|
s = strings.ReplaceAll(s, " ", "")
|
|
} else {
|
|
s = strings.ReplaceAll(s, " ", "")
|
|
}
|
|
|
|
v, err := strconv.ParseFloat(s, 64)
|
|
if err != nil {
|
|
return 0, ErrInvalidAmount
|
|
}
|
|
return v, nil
|
|
}
|