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) }