@ -0,0 +1,234 @@ | |||
/** | |||
* 计算佣金 | |||
* 2020/05/22 | |||
*/ | |||
package ordercalc | |||
import ( | |||
"errors" | |||
"strings" | |||
) | |||
/** | |||
* 计算某一商品对分销商的分销价 | |||
* @param business 分销商信息 | |||
* @param productSpecialPrice 分销特殊价格 | |||
* @param distributionPrice 基础分销价 | |||
* @param percentage 分销比例 | |||
* @param productPrice 商品销售价 | |||
* 2020/05/22 | |||
* gz | |||
*/ | |||
func DistributionPrice(business map[string]string, productSpecialPrice []map[string]string, distributionPrice interface{}, percentAge interface{}, productPrice interface{}) (float64, error) { | |||
product_price := ToString(productPrice) | |||
if len(business) < 1 { | |||
return 0, errors.New("参数错误") | |||
} | |||
_, idExist := business["Id"] | |||
_, levelIdExist := business["LevelId"] | |||
if !idExist || !levelIdExist { | |||
return 0, errors.New("分销商参数错误") | |||
} | |||
distribution_price := ToString(distributionPrice) | |||
distribution_price_float, err := ToFloat64(distributionPrice) | |||
if err != nil { | |||
return 0, err | |||
} | |||
percent_age := ToString(percentAge) | |||
if len(productSpecialPrice) < 1 && percent_age == "" { | |||
return distribution_price_float, nil //没有特殊价格,没有分销比例,返回原分销价 | |||
} | |||
var formula string //分销价计算公式 | |||
var is_special_price bool = false //是否使用特殊价格方式,因特殊价格中可能只能会员价,记录以供再次判断 | |||
var ok bool | |||
if len(productSpecialPrice) > 0 { //特殊价格方式 | |||
is_special_price = true //有一条特殊价格,则是使用特殊价 | |||
for _, item := range productSpecialPrice { | |||
if _, ok = item["BusinessId"]; ok { | |||
if item["BusinessId"] != "0" && item["BusinessId"] == business["Id"] { | |||
formula = item["DistributionPrice"] | |||
break | |||
} | |||
} | |||
if _, ok = item["BusinessLevelId"]; ok { | |||
if item["BusinessLevelId"] != "0" && item["BusinessLevelId"] == business["LevelId"] { | |||
formula = item["DistributionPrice"] | |||
} | |||
} | |||
} | |||
} | |||
var price []string | |||
var result float64 = 0 //最终分销价 | |||
if is_special_price { | |||
if formula != "" { | |||
formula = strings.Replace(formula, "#distribution_price#", distribution_price, 1) | |||
} else { | |||
formula = distribution_price | |||
} | |||
//计算表达式 | |||
switch { | |||
case strings.Contains(formula, "+"): | |||
price = strings.Split(formula, "+") | |||
result = FloatAdd(price[0], price[1]) | |||
case strings.Contains(formula, "-"): | |||
price = strings.Split(formula, "-") | |||
result = FloatSub(price[0], price[1]) | |||
case strings.Contains(formula, "*"): | |||
price = strings.Split(formula, "*") | |||
result = FloatMul(price[0], price[1], 2) | |||
case strings.Contains(formula, "/"): | |||
price = strings.Split(formula, "/") | |||
result = FloatQuo(price[0], price[1], 2) | |||
default: | |||
//使用固定价格或者使用基础分销价 | |||
if formula != "" { | |||
result, _ = ToFloat64(formula) | |||
} else { | |||
result = distribution_price_float | |||
} | |||
} | |||
} else { | |||
//使用分销比例 | |||
if product_price == "" { | |||
return 0, errors.New("商品价格错误") | |||
} | |||
price = strings.Split(percent_age, ":") | |||
totalCommission := FloatSub(productPrice, distributionPrice) //总佣金 | |||
if totalCommission <= 0 { | |||
return ToFloat64(productPrice) //总佣金为负,返回商品原价 | |||
} | |||
if _, ok = business["Grade"]; ok { | |||
level_count := len(price) //分销级数 | |||
var totalPercent, cent, commission float64 //总分配份数,分销比例,获得的佣金 | |||
switch level_count { | |||
case 3: | |||
totalPercent = FloatAdd(price[0], price[1], price[2]) | |||
if totalPercent <= 0 { | |||
result = distribution_price_float //佣金分配比例为0,返回基础分销价 | |||
} else { | |||
switch business["Grade"] { | |||
case "1": | |||
//一级分销商得到所有佣金 | |||
cent = 1 //分销比例 | |||
case "2": | |||
//二级分销商得到所有佣金 | |||
cent = FloatQuo(FloatAdd(price[0], price[1]), totalPercent) //分销比例 | |||
case "0", "3": | |||
//三级或无级别分销商得到所有佣金 | |||
cent = FloatQuo(price[0], totalPercent) //分销比例 | |||
} | |||
commission = FloatMul(totalCommission, cent, 2) | |||
result = FloatSub(productPrice, commission) //分销价=商品价-佣金 | |||
} | |||
case 2: | |||
totalPercent = FloatAdd(price[0], price[1]) | |||
if totalPercent <= 0 { | |||
result = distribution_price_float //佣金分配比例为0,返回基础分销价 | |||
} else { | |||
switch business["Grade"] { | |||
case "1": | |||
//一级分销商得到所有佣金 | |||
cent = 1 //分销比例 | |||
case "0", "2": | |||
//二级或无级别分销商得到所有佣金 | |||
cent = FloatQuo(price[0], totalPercent) //分销比例 | |||
} | |||
commission = FloatMul(totalCommission, cent, 2) | |||
result = FloatSub(productPrice, commission) //分销价=商品价-佣金 | |||
} | |||
case 1: | |||
//只有一级 | |||
result = distribution_price_float | |||
} | |||
} else { | |||
return 0, errors.New("分销商参数错误,没有分销级别") | |||
} | |||
} | |||
if result < 0 { | |||
result, _ = ToFloat64(productPrice) | |||
} | |||
return result, nil | |||
} | |||
/** | |||
* 计算某一商品的VIP价 | |||
* @param productSpecialPrice 特殊价格 | |||
* @param productPrice 商品销售价 | |||
* 2020/06/05 | |||
* gz | |||
*/ | |||
func VipPrice(productSpecialPrice []map[string]string, productPrice interface{}) (float64, error) { | |||
product_price := ToString(productPrice) | |||
product_price_float, _ := ToFloat64(productPrice) | |||
if len(productSpecialPrice) < 1 { | |||
return product_price_float, nil //没有特殊价格,返回原价 | |||
} | |||
var formula string //VIP价计算公式 | |||
var ok bool | |||
for _, item := range productSpecialPrice { | |||
if _, ok = item["RetailPrice"]; ok { | |||
if item["RetailPrice"] != "" { | |||
formula = item["RetailPrice"] | |||
break | |||
} | |||
} | |||
} | |||
if formula != "" { | |||
formula = strings.Replace(formula, "#retail_price#", product_price, 1) | |||
} else { | |||
formula = product_price | |||
} | |||
//计算表达式 | |||
var price []string | |||
var result float64 = 0 //最终VIP价 | |||
switch { | |||
case strings.Contains(formula, "+"): | |||
price = strings.Split(formula, "+") | |||
result = FloatAdd(price[0], price[1]) | |||
case strings.Contains(formula, "-"): | |||
price = strings.Split(formula, "-") | |||
result = FloatSub(price[0], price[1]) | |||
case strings.Contains(formula, "*"): | |||
price = strings.Split(formula, "*") | |||
result = FloatMul(price[0], price[1], 2) | |||
case strings.Contains(formula, "/"): | |||
price = strings.Split(formula, "/") | |||
result = FloatQuo(price[0], price[1], 2) | |||
default: | |||
result = product_price_float | |||
} | |||
if result < 0 || result > product_price_float { | |||
result = product_price_float | |||
} | |||
return result, nil | |||
} |
@ -0,0 +1,37 @@ | |||
package ordercalc | |||
import ( | |||
"testing" | |||
) | |||
func Test_DistributionPrice(t *testing.T) { | |||
business := map[string]string{"Id": "4", "LevelId": "3", "Grade": "3"} | |||
productSpecialPrice := make([]map[string]string, 0) | |||
price := make(map[string]string) | |||
price["BusinessId"] = "0" | |||
price["BusinessLevelId"] = "2" | |||
// price["DistributionPrice"] = "#distribution_price#+5" | |||
price["DistributionPrice"] = "0.05" | |||
// productSpecialPrice = append(productSpecialPrice, price) | |||
price = make(map[string]string) | |||
price["BusinessId"] = "0" | |||
price["BusinessLevelId"] = "3" | |||
price["DistributionPrice"] = "0.05" | |||
// productSpecialPrice = append(productSpecialPrice, price) | |||
price = make(map[string]string) | |||
price["BusinessId"] = "0" | |||
price["BusinessLevelId"] = "" | |||
price["DistributionPrice"] = "12" | |||
// productSpecialPrice = append(productSpecialPrice, price) | |||
dis, err := DistributionPrice(business, productSpecialPrice, 0.07, "7:2:1", 0.5) | |||
t.Log(dis) | |||
t.Log(err) | |||
} |
@ -0,0 +1,41 @@ | |||
package ordercalc | |||
import ( | |||
"crypto/md5" | |||
"encoding/hex" | |||
"strings" | |||
) | |||
/** | |||
* 通知订单状态时签名 | |||
* 签名方式:md5(order_sn-status--time---appid) | |||
* 2020/08/21 | |||
*gz | |||
*/ | |||
func Sign(order_sn, status, time, appid string) string { | |||
return Md5Password(StringJoin(order_sn, "--", status, "--", time, "--", appid)) | |||
} | |||
//密码加密 | |||
func Md5Password(password string) string { | |||
h := md5.New() | |||
h.Write([]byte(password)) // 需要加密的字符串 | |||
cipher2Str := h.Sum(nil) | |||
sMd5 := hex.EncodeToString(cipher2Str) // 输出加密结果 | |||
return sMd5 | |||
} | |||
/* | |||
* 连接多个字符串 | |||
* 2019/05/05 | |||
*/ | |||
func StringJoin(s ...string) string { | |||
var build strings.Builder | |||
if len(s) > 0 { | |||
for _, v := range s { | |||
build.WriteString(v) | |||
} | |||
} | |||
return build.String() | |||
} |
@ -0,0 +1,69 @@ | |||
package ordercalc | |||
import ( | |||
"math/rand" | |||
"strconv" | |||
"strings" | |||
"time" | |||
) | |||
/** | |||
* 订单号规则 | |||
* id后4位(随机4位)+当前时间(10位) | |||
* 2020/08/10 | |||
*/ | |||
func NewOrderSn(user_id string) string { | |||
var prefix string | |||
if user_id != "" { | |||
if len(user_id) > 4 { | |||
prefix = user_id[len(user_id)-4:] //截取后4位 | |||
} else { | |||
prefix = user_id | |||
} | |||
} else { | |||
//随机4位 | |||
str := "123456789" | |||
bytes := []byte(str) | |||
result := []byte{} | |||
r := rand.New(rand.NewSource(time.Now().UnixNano())) | |||
for i := 0; i < 4; i++ { | |||
result = append(result, bytes[r.Intn(len(bytes))]) | |||
} | |||
prefix = string(result) | |||
} | |||
//拼接 | |||
var build strings.Builder | |||
build.WriteString(prefix) | |||
build.WriteString(strconv.FormatInt(time.Now().Unix(), 10)) //当前时间 | |||
return build.String() | |||
} | |||
/** | |||
* 核销码规则 | |||
* 随机2位+当前时间(6位) | |||
* 2020/08/10 | |||
*/ | |||
func VerifyNumber() string { | |||
var prefix string | |||
//随机4位 | |||
str := "123456789" | |||
bytes := []byte(str) | |||
result := []byte{} | |||
r := rand.New(rand.NewSource(time.Now().UnixNano())) | |||
for i := 0; i < 1; i++ { | |||
result = append(result, bytes[r.Intn(len(bytes))]) | |||
} | |||
prefix = string(result) | |||
//拼接 | |||
var build strings.Builder | |||
build.WriteString(prefix) | |||
build.WriteString(strconv.FormatInt(time.Now().UnixNano(), 10)[10:17]) //当前时间 | |||
return build.String() | |||
} |
@ -0,0 +1,30 @@ | |||
package ordercalc | |||
import ( | |||
"testing" | |||
"time" | |||
) | |||
func Test_NewNumber(t *testing.T) { | |||
t.Log(time.Now().UnixNano()) | |||
var set map[string]int | |||
set = make(map[string]int) | |||
var i, reply int = 0, 0 | |||
var num string | |||
for i < 100000 { | |||
i++ | |||
num = VerifyNumber() | |||
if _, ok := set[num]; ok { | |||
reply++ | |||
} else { | |||
set[num] = i | |||
} | |||
} | |||
t.Log("reply:", reply) | |||
// t.Log(set) | |||
} |
@ -0,0 +1,176 @@ | |||
package ordercalc | |||
/** | |||
'0': 待支付 下单,尚未支付 created | |||
'1':已支付 付款成功,此状态可退款 payed | |||
'5':已验证 虚拟订单,验证核销码 using | |||
'6':已完成 与供应商结算后,订单结束。配送订单配送完成 finished | |||
'7':已取消 订单取消 canceled | |||
'8':自动取消 到期未支付自动取消,此状态可由管理员手动延期取消 autocanceled | |||
'9':申请退款 用户自助申请退订单,此状态可退款 | |||
'13':已退款 订单完成退款 refunded | |||
'15':自动完成 使用时间过期,自动完成。 finished | |||
cancel,received,payed,created,finished,using | |||
## 发货 | |||
is_delivery 是否发货 '1': 已发货 | |||
delivery 发货时间 | |||
## 收货 | |||
is_received 是否收货 '1': 已收货 | |||
received 收货时间 | |||
*/ | |||
var statusList map[string]string = map[string]string{ | |||
"0": "created", | |||
"1": "payed", | |||
"5": "using", | |||
"6": "finished", | |||
"7": "canceled", | |||
"8": "autocanceled", | |||
"9": "askForRefund", | |||
"13": "refunded", | |||
"15": "autofinished", | |||
} | |||
var statusExtendList map[string]string = map[string]string{ | |||
"6": "received", //已收货归入已完成, | |||
} | |||
/*串货订单,供应商系统订单状态*/ | |||
var channelOrderStatusList map[string]string = map[string]string{ | |||
"1": "nosend", | |||
"2": "created", | |||
"3": "payed", | |||
"4": "askForRefund", | |||
"5": "refunded", | |||
"6": "canceled", | |||
"7": "finished", | |||
"8": "payFailed", //支付失败 | |||
"9": "breakoff", //断开 | |||
"10": "fullRefund", //全额退款 | |||
"14": "autocanceled", | |||
"15": "autofinished", | |||
"16": "delivered", | |||
} | |||
func GetOrderStatusKey(status string) (key string) { | |||
for k, val := range statusList { | |||
if val == status { | |||
key = k | |||
break | |||
} | |||
} | |||
if key == "" { //再找扩展的状态 | |||
for k, val := range statusExtendList { | |||
if val == status { | |||
key = k | |||
break | |||
} | |||
} | |||
} | |||
return | |||
} | |||
func GetOrderStatusText(key string) (text string) { | |||
for k, val := range statusList { | |||
if k == key { | |||
text = val | |||
break | |||
} | |||
} | |||
if text == "" { //再找扩展的状态 | |||
for k, val := range statusExtendList { | |||
if k == key { | |||
text = val | |||
break | |||
} | |||
} | |||
} | |||
return | |||
} | |||
/** | |||
* 返回订单状态描述 | |||
* 2021/01/28 | |||
*/ | |||
func GetOrderStatusDescByFlag(flag string) (text string) { | |||
status := GetStatusText(flag) | |||
return GetStatusDesc(status) | |||
} | |||
/** | |||
* 返回订单状态描述 | |||
* 2020/10/22 | |||
*/ | |||
func GetOrderStatusDesc(key string) (text string) { | |||
var statusDesc map[string]string = map[string]string{ | |||
"created": "已创建", | |||
"payed": "已支付", | |||
"askForRefund": "请求退款", | |||
"using": "使用中", | |||
"finished": "已完成", | |||
"canceled": "已取消", | |||
"autocanceled": "自动取消", | |||
"refunded": "已退款", | |||
"autofinished": "自动完成", | |||
"received": "已收货", | |||
} | |||
for k, val := range statusDesc { | |||
if k == key { | |||
text = val | |||
break | |||
} | |||
} | |||
return | |||
} | |||
func GetChannelOrderStatusKey(status string) (key string) { | |||
for k, val := range channelOrderStatusList { | |||
if val == status { | |||
key = k | |||
break | |||
} | |||
} | |||
return | |||
} | |||
func GetChannelOrderStatusText(key string) (text string) { | |||
for k, val := range channelOrderStatusList { | |||
if k == key { | |||
text = val | |||
break | |||
} | |||
} | |||
return | |||
} | |||
/** | |||
* 返回订单状态描述 | |||
* 2020/10/22 | |||
*/ | |||
func GetChannelOrderStatusDesc(key string) (text string) { | |||
var statusDesc map[string]string = map[string]string{ | |||
"nosend": "未发送", | |||
"created": "已创建", | |||
"payed": "已支付", | |||
"askForRefund": "请求退款", | |||
"refunded": "已退款", | |||
"canceled": "已取消", | |||
"finished": "已完成", | |||
"payFailed": "支付失败", | |||
"breakoff": "断开", | |||
"fullRefund": "全额退款", | |||
"autocanceled": "自动取消", | |||
"autofinished": "自动取消", | |||
"delivered": "已发货", | |||
} | |||
for k, val := range statusDesc { | |||
if k == key { | |||
text = val | |||
break | |||
} | |||
} | |||
return | |||
} |