Files
jx-callback/business/jxutils/jxutils_cms.go

454 lines
12 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 jxutils
import (
"crypto/md5"
"fmt"
"io/ioutil"
"math"
"net/http"
"reflect"
"regexp"
"strings"
"sync"
"time"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/globals"
)
var (
storeNamePat = regexp.MustCompile(`([^(\[(【)\])】\-\s]*)[(\[(【\-\s]+([^(\[(【)\])】\-]*)[)\])】]*`)
mobilePat = regexp.MustCompile(`^1\d{10}$`)
)
// 合并得到最终的门店状态
func MergeStoreStatus(status int, vendorStatus int) int {
if status < vendorStatus {
return status
}
return vendorStatus
}
func MergeSkuStatus(skuStatus int, storeSkuStatus int) int {
if skuStatus < storeSkuStatus {
return skuStatus
}
return storeSkuStatus
}
func SplitSlice(list interface{}, batchCount int) (listInList [][]interface{}) {
typeInfo := reflect.TypeOf(list)
if typeInfo.Kind() != reflect.Slice {
panic("list must be slice")
}
valueInfo := reflect.ValueOf(list)
len := valueInfo.Len()
if len > 0 {
listInListLen := (len-1)/batchCount + 1
listInList = make([][]interface{}, listInListLen)
index := 0
for i := 0; i < len; i++ {
if i%batchCount == 0 {
index = i / batchCount
arrLen := len - i
if arrLen > batchCount {
arrLen = batchCount
}
listInList[index] = make([]interface{}, arrLen)
}
listInList[index][i%batchCount] = valueInfo.Index(i).Interface()
}
}
return listInList
}
func SplitStoreName(fullName, separator, defaultPrefix string) (prefix, bareName string) {
names := strings.Split(fullName, separator)
if len(names) == 2 {
prefix = names[0]
bareName = names[1]
} else {
searchResult := storeNamePat.FindStringSubmatch(fullName)
if searchResult != nil {
prefix = searchResult[1]
bareName = strings.Trim(strings.Trim(searchResult[2], defaultPrefix), separator)
} else {
prefix = defaultPrefix
bareName = strings.Trim(strings.Trim(fullName, defaultPrefix), separator)
}
}
return TrimDecorationChar(prefix), TrimDecorationChar(bareName)
}
func ComposeStoreName(bareName string, vendorID int) (fullName string) {
bareName = TrimDecorationChar(strings.Trim(bareName, "-"))
if vendorID == model.VendorIDJD {
fullName = globals.StoreName + "-" + bareName
} else {
fullName = globals.StoreName + "(" + bareName + ")"
}
return fullName
}
func StrTime2JxOperationTime(strTime string, defValue int16) int16 {
if timeValue, err := time.Parse("15:04:05", strTime); err == nil {
return int16(timeValue.Hour()*100 + timeValue.Minute())
}
return defValue
}
func JxOperationTime2StrTime(value int16) string {
return fmt.Sprintf("%02d:%02d", value/100, value%100)
}
func GetPolygonFromCircle(lng, lat, distance float64, pointCount int) (points [][2]float64) {
points = make([][2]float64, pointCount)
for k := range points {
angle := float64(k) * 360 / float64(pointCount)
points[k][0], points[k][1] = ConvertDistanceToLogLat(lng, lat, float64(distance), angle)
}
return points
}
func GetPolygonFromCircleStr(lng, lat, distance float64, pointCount int) string {
return CoordinatePoints2Str(GetPolygonFromCircle(lng, lat, distance, pointCount))
}
func CoordinatePoints2Str(points [][2]float64) string {
points2 := make([]string, len(points))
for k, v := range points {
points2[k] = fmt.Sprintf("%.6f,%.6f", v[0], v[1])
}
return strings.Join(points2, ";")
}
func CoordinateStr2Points(pointsStr string) (points [][2]float64) {
strPoints := strings.Split(pointsStr, ";")
for _, v := range strPoints {
strPoint := strings.Split(v, ",")
if len(strPoint) >= 2 {
points = append(points, [2]float64{utils.Str2Float64(strPoint[0]), utils.Str2Float64(strPoint[1])})
}
}
return points
}
func IntMap2List(intMap map[int]int) []int {
retVal := make([]int, len(intMap))
index := 0
for k := range intMap {
retVal[index] = k
index++
}
return retVal
}
func IntList2Map(intList []int) map[int]int {
retVal := make(map[int]int)
for _, v := range intList {
retVal[v] = 1
}
return retVal
}
func Int64Map2List(int64Map map[int64]int) []int64 {
retVal := make([]int64, len(int64Map))
index := 0
for k := range int64Map {
retVal[index] = k
index++
}
return retVal
}
func StringMap2List(stringMap map[string]int) []string {
retVal := make([]string, len(stringMap))
index := 0
for k := range stringMap {
retVal[index] = k
index++
}
return retVal
}
func StringList2Map(strList []string) map[string]int {
retVal := make(map[string]int)
for _, v := range strList {
retVal[v] = 1
}
return retVal
}
func RegularizeSkuQuality(specQuality float32, specUnit string) (g int) {
lowerSpecUnit := strings.ToLower(specUnit)
if lowerSpecUnit == "kg" || lowerSpecUnit == "l" {
specQuality *= 1000
}
return int(specQuality)
}
// 计算SKU价格unitPrice为一斤的单价specQuality为质量单位为克
func CaculateSkuPrice(unitPrice int, specQuality float32, specUnit string, skuNameUnit string) int {
if skuNameUnit != model.SpecialUnit {
return unitPrice
}
specQuality2 := RegularizeSkuQuality(specQuality, specUnit)
price := int(math.Round(float64(unitPrice * specQuality2 / model.SpecialSpecQuality)))
// if specQuality2 < 250 {
// price = price * 110 / 100
// } else if specQuality2 < 500 {
// price = price * 105 / 100
// }
if price <= 0 {
price = 1
}
return price
}
// 计算SKU标准价格CaculateSkuPrice的逆过程
func CaculateUnitPrice(skuPrice int, specQuality float32, specUnit string, skuNameUnit string) (unitPrice int) {
if skuNameUnit != model.SpecialUnit {
return skuPrice
}
specQuality2 := RegularizeSkuQuality(specQuality, specUnit)
unitPrice = skuPrice * model.SpecialSpecQuality / specQuality2
// if specQuality2 < 250 {
// unitPrice = unitPrice * 100 / 110
// } else if specQuality2 < 500 {
// unitPrice = unitPrice * 100 / 105
// }
if unitPrice <= 0 {
unitPrice = 1
}
return unitPrice
}
func GetSliceLen(list interface{}) int {
return reflect.ValueOf(list).Len()
}
func CaculateSkuVendorPrice(price, percentage, catPercentage int) int {
if percentage <= 10 || percentage >= 400 {
percentage = 100
}
if catPercentage <= 10 || catPercentage >= 400 {
catPercentage = 100
}
percentage = percentage * catPercentage / 100
vendorPrice := int(math.Round(float64(price*percentage) / 100))
if vendorPrice < 0 {
vendorPrice = 0
}
return vendorPrice
}
func CaculateSkuPriceFromVendor(vendorPrice, percentage, catPercentage int) int {
if percentage <= 10 || percentage >= 400 {
percentage = 100
}
if catPercentage <= 10 || catPercentage >= 400 {
catPercentage = 100
}
percentage = percentage * catPercentage / 100
price := int(math.Round(float64(vendorPrice * 100 / percentage)))
if price < 0 {
price = 0
}
return price
}
func GetPricePercentage(l model.PricePercentagePack, price int, defPricePercentage int) (pricePercentage int) {
pricePercentage = defPricePercentage
if len(l) > 0 {
var lastItem *model.PricePercentageItem
for _, v := range l {
if v.BeginPrice > price {
break
}
lastItem = v
}
if lastItem != nil {
pricePercentage = lastItem.PricePercentage
}
}
return pricePercentage
}
func GetPricePercentageByVendorPrice(l model.PricePercentagePack, vendorPrice int, defPricePercentage int) (pricePercentage int) {
pricePercentage = defPricePercentage
if len(l) > 0 {
var lastItem *model.PricePercentageItem
for _, v := range l {
if CaculateSkuVendorPrice(v.BeginPrice, v.PricePercentage, 0) > vendorPrice {
break
}
lastItem = v
}
if lastItem != nil {
pricePercentage = lastItem.PricePercentage
}
}
return pricePercentage
}
func IsSkuSpecial(specQuality float32, specUnit string) bool {
return int(specQuality) == model.SpecialSpecQuality && (specUnit == model.SpecialSpecUnit || specUnit == model.SpecialSpecUnit2)
}
var lastFakeID int64
var lastFakeIDMutex sync.RWMutex
// 生成一个不重复的临时ID
func genFakeID1() int64 {
for {
fakeID := time.Now().UnixNano() / 1000
lastFakeIDMutex.RLock()
if fakeID == lastFakeID {
lastFakeIDMutex.RUnlock()
time.Sleep(1 * time.Microsecond)
} else {
lastFakeIDMutex.RUnlock()
lastFakeIDMutex.Lock()
defer lastFakeIDMutex.Unlock()
lastFakeID = fakeID
return fakeID
}
}
}
// 这个用于没有打开远程同步时的假同步生成ID使用
func GenFakeID() int64 {
return genFakeID1() * 3
}
func IsFakeID(id int64) bool {
if IsEmptyID(id) {
return true
}
multiple := id / genFakeID1()
return multiple >= 2 && multiple <= 4
}
func IsEmptyID(id int64) bool {
return id == 0
}
func FormalizePageSize(pageSize int) int {
return dao.FormalizePageSize(pageSize)
}
func FormalizePageOffset(pageSize int) int {
return dao.FormalizePageOffset(pageSize)
}
func FormalizeName(name string) string {
return utils.TrimBlankChar(strings.Replace(strings.Replace(name, "\t", "", -1), "\"", "", -1))
}
func Int2OneZero(value int) int {
if value != 0 {
return 1
}
return 0
}
// 判断电话号码是否是假的,比如有****号
func IsMobileFake(mobile string) bool {
return len(mobile) >= 13 || mobile == ""
}
func FormalizeMobile(mobile string) string {
mobile = TrimDecorationChar(mobile)
return strings.Replace(strings.Replace(mobile, "-", ",", -1), "_", ",", -1)
}
func IsStringLikeMobile(mobile string) bool {
return mobilePat.FindStringIndex(mobile) != nil
}
func IsLegalStoreID(id int) bool {
return id >= 100000 && id < 900000
}
// 将规格转为重量
func FormatSkuWeight(specQuality float32, specUnit string) int {
return RegularizeSkuQuality(specQuality, specUnit)
}
type SkuList []*model.Sku
func (s SkuList) Len() int {
return len(s)
}
func (s SkuList) Less(i, j int) bool {
if s[i].NameID == s[j].NameID {
if s[i].SpecUnit == s[j].SpecUnit {
return s[i].SpecQuality < s[j].SpecQuality
}
return s[i].SpecUnit < s[j].SpecUnit
}
return s[i].NameID < s[j].NameID
}
func (s SkuList) Swap(i, j int) {
tmp := s[i]
s[i] = s[j]
s[j] = tmp
}
func DownloadFileByURL(fileURL string) (bodyData []byte, fileMD5 string, err error) {
response, err := http.Get(fileURL)
if err == nil {
defer response.Body.Close()
if response.StatusCode == http.StatusOK {
if bodyData, err = ioutil.ReadAll(response.Body); err == nil {
fileMD5 = fmt.Sprintf("%X", md5.Sum(bodyData))
}
} else {
err = platformapi.ErrHTTPCodeIsNot200
}
}
return bodyData, fileMD5, err
}
/////
func GenPicFileName(suffix string) string {
return fmt.Sprintf("image/%x%s", md5.Sum([]byte(utils.GetUUID()+suffix)), suffix)
}
func GuessVendorIDFromVendorStoreID(vendorStoreID int64) (vendorID int) {
vendorID = model.VendorIDUnknown
if vendorStoreID > 10040008 && vendorStoreID < 98765432 { // 京东117330658位
vendorID = model.VendorIDJD
} else if vendorStoreID > 1234567 && vendorStoreID < 9876543 { // 美团外卖 24617137位
vendorID = model.VendorIDMTWM
} else if vendorStoreID > 1234567890 && vendorStoreID < 99876543210 { // 饿百 216700260710位11位
vendorID = model.VendorIDEBAI
} else if vendorStoreID > 123456789 && vendorStoreID < 987654321 { // 微盟微商城 1320910489位
vendorID = model.VendorIDWSC
} else if vendorStoreID > 123456 && vendorStoreID < 654321 { // 京西门店ID6位
vendorID = model.VendorIDJX
}
return vendorID
}
func GetVendorName(vendorID int) (vendorName string) {
return model.VendorChineseNames[vendorID]
}
func CaculateSkuEarningPrice(shopPrice, salePrice int64, storePayPercentage int) (earningPrice int64) {
earningPrice = salePrice
if shopPrice > 0 && shopPrice < earningPrice {
earningPrice = shopPrice
}
if storePayPercentage <= 0 {
storePayPercentage = model.DefaultEarningPricePercentage
}
earningPrice = earningPrice * int64(storePayPercentage) / 100
return earningPrice
}