package invoice import ( "errors" "fmt" "strings" ) // Quantity stores hundredths (e.g. 0.5 => 50). func ParseQuantity(input string) (Quantity, error) { clean := strings.TrimSpace(input) if clean == "" { return 0, errors.New("empty quantity") } clean = strings.ReplaceAll(clean, " ", "") clean = strings.ReplaceAll(clean, ",", ".") if strings.HasPrefix(clean, ".") || strings.HasSuffix(clean, ".") { return 0, fmt.Errorf("invalid quantity: %q", input) } parts := strings.Split(clean, ".") if len(parts) > 2 { return 0, fmt.Errorf("invalid quantity: %q", input) } whole := parts[0] frac := "" if len(parts) == 2 { frac = parts[1] } if whole == "" { whole = "0" } for _, r := range whole { if r < '0' || r > '9' { return 0, fmt.Errorf("invalid quantity: %q", input) } } for _, r := range frac { if r < '0' || r > '9' { return 0, fmt.Errorf("invalid quantity: %q", input) } } if len(frac) > 2 { return 0, fmt.Errorf("invalid quantity: %q", input) } for len(frac) < 2 { frac += "0" } var wholeValue int64 for _, r := range whole { wholeValue = wholeValue*10 + int64(r-'0') } var fracValue int64 for _, r := range frac { fracValue = fracValue*10 + int64(r-'0') } return Quantity(wholeValue*100 + fracValue), nil } func FormatQuantity(q Quantity) string { value := int64(q) whole := value / 100 frac := value % 100 if frac == 0 { return fmt.Sprintf("%d", whole) } if frac%10 == 0 { return fmt.Sprintf("%d.%d", whole, frac/10) } return fmt.Sprintf("%d.%02d", whole, frac) }