bindbox-game/internal/service/finance/profit_metrics.go
2026-02-27 00:08:02 +08:00

82 lines
1.9 KiB
Go

package finance
import "strings"
const defaultMultiplierX1000 int64 = 1000
type SpendingBreakdown struct {
PaidCoupon int64
GamePass int64
Total int64
IsGamePass bool
}
// ClassifyOrderSpending applies the unified rule:
// - game pass order: spending = game pass value
// - normal order: spending = actual + discount
func ClassifyOrderSpending(sourceType int32, orderNo string, actualAmount, discountAmount int64, remark string, gamePassValue int64) SpendingBreakdown {
isGamePass := IsGamePassOrder(sourceType, orderNo, actualAmount, remark)
if isGamePass {
if gamePassValue < 0 {
gamePassValue = 0
}
return SpendingBreakdown{
PaidCoupon: 0,
GamePass: gamePassValue,
Total: gamePassValue,
IsGamePass: true,
}
}
paidCoupon := actualAmount + discountAmount
if paidCoupon < 0 {
paidCoupon = 0
}
return SpendingBreakdown{
PaidCoupon: paidCoupon,
GamePass: 0,
Total: paidCoupon,
IsGamePass: false,
}
}
func IsGamePassOrder(sourceType int32, orderNo string, actualAmount int64, remark string) bool {
if sourceType == 4 {
return true
}
if strings.HasPrefix(orderNo, "GP") {
return true
}
return actualAmount == 0 && strings.Contains(remark, "use_game_pass")
}
func ComputeGamePassValue(drawCount, activityPrice int64) int64 {
if drawCount <= 0 || activityPrice <= 0 {
return 0
}
return drawCount * activityPrice
}
func NormalizeMultiplierX1000(multiplierX1000 int64) int64 {
if multiplierX1000 <= 0 {
return defaultMultiplierX1000
}
return multiplierX1000
}
func ComputePrizeCostWithMultiplier(baseCost, multiplierX1000 int64) int64 {
if baseCost <= 0 {
return 0
}
n := NormalizeMultiplierX1000(multiplierX1000)
return baseCost * n / defaultMultiplierX1000
}
func ComputeProfit(spending, prizeCost int64) (int64, float64) {
profit := spending - prizeCost
if spending <= 0 {
return profit, 0
}
return profit, float64(profit) / float64(spending)
}