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]+([^(\[(【)\])】\-]*)[)\])】]*`) ) // 合并得到最终的门店状态 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 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 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, unitPrice int, defPricePercentage int) (pricePercentage int) { pricePercentage = defPricePercentage if len(l) > 0 { var lastItem *model.PricePercentageItem for _, v := range l { lastItem = v if v.BeginPrice > unitPrice { break } } 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 { lastItem = v if CaculateSkuVendorPrice(v.BeginPrice, v.PricePercentage, 0) > vendorPrice { break } } 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 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 IsLegalStoreID(id int) bool { return id >= 100000 && id < 200000 } // 将规格转为重量 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 { // 京东11733065,8位 vendorID = model.VendorIDJD } else if vendorStoreID > 1234567 && vendorStoreID < 9876543 { // 美团外卖 2461713,7位 vendorID = model.VendorIDMTWM } else if vendorStoreID > 1234567890 && vendorStoreID < 99876543210 { // 饿百 2167002607,10位,11位 vendorID = model.VendorIDEBAI } else if vendorStoreID > 123456789 && vendorStoreID < 987654321 { // 微盟微商城 132091048,9位 vendorID = model.VendorIDWSC } else if vendorStoreID > 123456 && vendorStoreID < 654321 { // 京西门店ID,6位 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 }