Files
soul-yongping/soul-api/internal/handler/referral_commission.go

80 lines
2.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handler
import (
"encoding/json"
"time"
"soul-api/internal/model"
"gorm.io/gorm"
)
// computeOrderCommission 按订单计算应付给推广者的佣金
// 会员订单:推广者会员 20%、非会员 10%内容订单90%(好友优惠 5% 仅针对内容)
// order: 已支付订单,需有 product_type、amount、referrer_id
// referrerUser: 推广者用户信息,用于判断 is_vip可为 nil会查库
// preloadConfig: 可选,预加载的 referral_config避免 N+1 查询
func computeOrderCommission(db *gorm.DB, order *model.Order, referrerUser *model.User, preloadConfig ...*model.SystemConfig) float64 {
if order == nil || order.ReferrerID == nil || *order.ReferrerID == "" {
return 0
}
// 读取推广配置
distributorShare := 0.9
userDiscount := 0.0
vipOrderShareVip := 20.0
vipOrderShareNonVip := 10.0
var cfg *model.SystemConfig
if len(preloadConfig) > 0 && preloadConfig[0] != nil {
cfg = preloadConfig[0]
} else if row, err := (func() (*model.SystemConfig, error) {
var r model.SystemConfig
e := db.Where("config_key = ?", "referral_config").First(&r).Error
return &r, e
})(); err == nil {
cfg = row
}
if cfg != nil {
var config map[string]interface{}
if err := json.Unmarshal(cfg.ConfigValue, &config); err == nil {
if share, ok := config["distributorShare"].(float64); ok {
distributorShare = share / 100
}
if disc, ok := config["userDiscount"].(float64); ok {
userDiscount = disc / 100
}
if v, ok := config["vipOrderShareVip"].(float64); ok {
vipOrderShareVip = v / 100
}
if v, ok := config["vipOrderShareNonVip"].(float64); ok {
vipOrderShareNonVip = v / 100
}
}
}
// 会员订单:无好友优惠,按推广者是否会员分 20%/10%
if order.ProductType == "vip" {
base := order.Amount
var referrer model.User
if referrerUser != nil {
referrer = *referrerUser
} else if err := db.Where("id = ?", *order.ReferrerID).First(&referrer).Error; err != nil {
return 0
}
isVip := referrer.IsVip != nil && *referrer.IsVip
if referrer.VipExpireDate != nil && referrer.VipExpireDate.Before(time.Now()) {
isVip = false
}
if isVip {
return base * vipOrderShareVip
}
return base * vipOrderShareNonVip
}
// 内容订单:若有推荐人且 userDiscount>0反推原价否则按实付
commissionBase := order.Amount
if userDiscount > 0 && (order.ReferrerID != nil && *order.ReferrerID != "" || (order.ReferralCode != nil && *order.ReferralCode != "")) {
if (1 - userDiscount) > 0 {
commissionBase = order.Amount / (1 - userDiscount)
}
}
return commissionBase * distributorShare
}