235 lines
5.4 KiB
Go
235 lines
5.4 KiB
Go
package finance
|
|
|
|
import (
|
|
. "kjol/basic"
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// takes a number such as 123456, and outputs (1234, 56) as strings
|
|
func SplitInt64(n int64) (string, string) {
|
|
// Calculate the first part as string
|
|
firstPart := fmt.Sprintf("%d", n/100)
|
|
// Calculate the second part as string with leading zero if necessary
|
|
secondPart := fmt.Sprintf("%02d", n%100)
|
|
return firstPart, secondPart
|
|
}
|
|
|
|
func Int64ToMoney(value int64) string {
|
|
decimalValue := float64(value) / 100.0
|
|
moneyString := fmt.Sprintf("%.2f", decimalValue)
|
|
return moneyString
|
|
}
|
|
|
|
func Int64ToMoneyWithCommas(value int64) string {
|
|
decimalValue := float64(value) / 100.0
|
|
moneyString := fmt.Sprintf("%.2f", decimalValue)
|
|
|
|
parts := strings.Split(moneyString, ".")
|
|
dollars := parts[0]
|
|
cents := parts[1]
|
|
|
|
negative := false
|
|
if strings.HasPrefix(dollars, "-") {
|
|
negative = true
|
|
dollars = dollars[1:]
|
|
}
|
|
|
|
result := ""
|
|
for i, char := range dollars {
|
|
if i > 0 && (len(dollars)-i)%3 == 0 {
|
|
result += ","
|
|
}
|
|
result += string(char)
|
|
}
|
|
|
|
if negative {
|
|
result = "-" + result
|
|
}
|
|
|
|
return result + "." + cents
|
|
}
|
|
|
|
func MoneyToInt64(input string) int64 {
|
|
if !strings.Contains(input, ".") {
|
|
input += ".00"
|
|
} else if strings.Count(input, ".") == 1 {
|
|
digits := strings.Split(input, ".")
|
|
if len(digits[1]) == 1 {
|
|
input += "0"
|
|
}
|
|
}
|
|
processedString := strings.ReplaceAll(input, ".", "")
|
|
processedString = strings.ReplaceAll(processedString, ",", "")
|
|
processedString = strings.ReplaceAll(processedString, " ", "")
|
|
result, _ := strconv.Atoi(processedString)
|
|
return int64(result)
|
|
}
|
|
|
|
func Int64ToRate(rate int64) string {
|
|
decimalValue := float64(rate) / 1000.0
|
|
rateString := fmt.Sprintf("%.3f", decimalValue)
|
|
return rateString
|
|
}
|
|
|
|
func RoundUpToCeiling(input int64) int64 {
|
|
remainder := input % 100
|
|
if remainder == 0 {
|
|
return input
|
|
}
|
|
return input + 100 - remainder
|
|
}
|
|
|
|
func RoundDownToFloor(input int64) int64 {
|
|
remainder := input % 100
|
|
if remainder == 0 {
|
|
return input
|
|
}
|
|
return input - remainder
|
|
}
|
|
|
|
func MultiplyByPercentageS64(amount int64, percentage float64) int64 {
|
|
amount_float64 := float64(amount) / 100
|
|
out_float64 := (amount_float64 * (percentage / 100))
|
|
|
|
out_int64 := int64(math.Round(out_float64 * 100))
|
|
|
|
return out_int64
|
|
}
|
|
|
|
func MultiplyByPercentageF64(amount int64, percentage float64) float64 {
|
|
amount_float64 := float64(amount) / 100
|
|
|
|
return amount_float64 * percentage
|
|
}
|
|
|
|
func ProcessDiscount(discount string) float64 {
|
|
discount_f64, _ := strconv.ParseFloat(discount, 64)
|
|
|
|
if discount_f64 < 0 {
|
|
return 0
|
|
} else if discount_f64 > 100 {
|
|
return 100
|
|
}
|
|
|
|
return discount_f64
|
|
}
|
|
|
|
// DaysToRateTerm Takes days as an input and outputs the string representation of the number of
|
|
// days, months, or years in the term based on which unit is the best fit for the amount of days
|
|
// along with the corresponding unit string.
|
|
func DaysToRateTerm(days int32) (string, string) {
|
|
years := days / 365
|
|
months := (days - years*365) / 30
|
|
dayRemainder := days - years*365 - months*30
|
|
|
|
if days == 0 { // Return empty string for value
|
|
return "", "days"
|
|
} else if days <= 270 || dayRemainder > 0 {
|
|
return ToString(days), "days"
|
|
} else if months > 0 {
|
|
return ToString(months + years*12), "months"
|
|
} else {
|
|
return ToString(years), "years"
|
|
}
|
|
}
|
|
|
|
func RateTermToDays(value string, unit string) int32 {
|
|
valueInt := StringToInt32(value)
|
|
switch unit {
|
|
case "months":
|
|
years := valueInt / 12
|
|
months := valueInt % 12
|
|
return years*365 + months*30
|
|
case "years":
|
|
return valueInt * 365
|
|
default: // case "days":
|
|
return valueInt
|
|
}
|
|
}
|
|
|
|
func RateToString(rateValue float64) string {
|
|
str, err := NumberToString(rateValue, 3, "%", true)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return fmt.Sprint(rateValue)
|
|
}
|
|
return str
|
|
}
|
|
|
|
func RatePlainToString(rateValue float64) string {
|
|
str, err := NumberToString(rateValue, 3, "", false)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return fmt.Sprint(rateValue)
|
|
}
|
|
return str
|
|
}
|
|
|
|
func DollarAmountToString(amount float64) string {
|
|
str, err := NumberToString(amount, 2, "", false)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return fmt.Sprint(amount)
|
|
}
|
|
return str
|
|
}
|
|
|
|
func DollarAmountPlainToString(amount float64) string {
|
|
str, err := NumberToString(amount, 2, "$", false)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return fmt.Sprint(amount)
|
|
}
|
|
return str
|
|
}
|
|
|
|
func NumberToString(i any, precision int, symbol string, symbolLast bool) (string, error) {
|
|
var numberFloat float64 = 0.0
|
|
err := fmt.Errorf("error: could not convert %s to a decimal value", i)
|
|
switch i.(type) {
|
|
case int32, int64, int, uint64, uint32, uint, float32, float64:
|
|
if val, ok := i.(float64); ok {
|
|
numberFloat = val
|
|
} else {
|
|
return "", err
|
|
}
|
|
default:
|
|
return "", fmt.Errorf("error: could not convert %s to a decimal value", i)
|
|
}
|
|
|
|
s := fmt.Sprintf("%.[2]*[1]f", numberFloat, precision)
|
|
|
|
parts := strings.Split(s, ".")
|
|
if len(parts) == 0 {
|
|
return "", fmt.Errorf("error: could not convert '%s' to a decimal value", s)
|
|
}
|
|
|
|
numberLeftSide := parts[0][len(parts[0])-1:]
|
|
|
|
for i := len(parts[0]) - 2; i >= 0; i-- {
|
|
|
|
if len(strings.Replace(numberLeftSide, ",", "", -1))%3 == 0 {
|
|
numberLeftSide = "," + numberLeftSide
|
|
}
|
|
numberLeftSide = string(parts[0][i]) + numberLeftSide
|
|
|
|
}
|
|
numberToReturn := numberLeftSide
|
|
if len(parts) > 1 {
|
|
numberToReturn = numberToReturn + "." + parts[1]
|
|
}
|
|
|
|
if symbol != "" {
|
|
if symbolLast {
|
|
numberToReturn = numberToReturn + symbol
|
|
} else {
|
|
numberToReturn = symbol + numberToReturn
|
|
}
|
|
}
|
|
|
|
return numberToReturn, nil
|
|
}
|