diff --git a/business/jxstore/cms/cms.go b/business/jxstore/cms/cms.go index ceccd8f3b..af247fba6 100644 --- a/business/jxstore/cms/cms.go +++ b/business/jxstore/cms/cms.go @@ -5,22 +5,16 @@ import ( "reflect" "regexp" "strconv" - "strings" "time" "git.rosy.net.cn/baseapi/utils/errlist" "git.rosy.net.cn/jx-callback/globals/api2" - "git.rosy.net.cn/baseapi/platformapi/dingdingapi" - - "git.rosy.net.cn/jx-callback/business/auth2/authprovider/mobile" "git.rosy.net.cn/jx-callback/business/authz/autils" - "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/baseapi/utils" - "git.rosy.net.cn/jx-callback/business/jxutils/ddmsg" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/jx-callback/business/model" @@ -66,36 +60,6 @@ var ( needConfirmRequestMap = map[string]int{ SendMsgTypeOpenStoreRequest: 1, } - - SysConfigLimitMap = map[string]*SysConfigLimit{ - model.ConfigSysEbaiBoxFee: &SysConfigLimit{ - ValueType: reflect.Int, - MinValue: 0, - MaxValue: 500, - AfterChanged: func() (err error) { - _, err = dao.SetStoreMapSyncStatus(dao.GetDB(), []int{model.VendorIDEBAI}, nil, model.SyncFlagModifiedMask) - return err - }, - }, - model.ConfigSysMtwmBoxFee: &SysConfigLimit{ - ValueType: reflect.Int, - MinValue: 0, - MaxValue: 500, - AfterChanged: func() (err error) { - _, err = dao.SetStoreMapSyncStatus(dao.GetDB(), []int{model.VendorIDMTWM}, nil, model.SyncFlagModifiedMask) - return err - }, - }, - model.ConfigSysMtwmSkuBoxFee: &SysConfigLimit{ - ValueType: reflect.Int, - MinValue: 0, - MaxValue: 50, - AfterChanged: func() (err error) { - _, err = dao.SetStoreSkuSyncStatus(dao.GetDB(), model.VendorIDMTWM, nil, nil, model.SyncFlagModifiedMask) - return err - }, - }, - } ) func InitServiceInfo(version string, buildTime time.Time, gitCommit string) { @@ -109,22 +73,12 @@ func InitServiceInfo(version string, buildTime time.Time, gitCommit string) { "buildTime": buildTimeStr, "gitCommit": gitCommit, "metaData": map[string]interface{}{ - "skuNamePrefix": model.SkuNamePrefixNames, - "skuNameUnit": model.UnitNames, - "skuSpecUnit": model.SpecUnitNames, - "skuStatus": model.SkuStatusName, - "storeDeliveryRangeType": model.DeliveryRangeTypeName, - "storeDeliveryType": model.DeliveryTypeName, - "storeStatus": model.StoreStatusName, - "categoryType": model.CategoryTypeName, "vendorTypeName": model.VendorTypeName, "vendorName": model.VendorChineseNames, "orderStatus": model.OrderStatusName, "waybillStatus": model.WaybillStatusName, "orderTypeName": model.OrderTypeName, "taskStatusName": tasksch.TaskStatusName, - "opRequestTypeName": model.RequestTypeName, - "opRequestStatusName": model.RequestStatusName, "storeMsgSendStatusName": model.StoreMsgSendStatusName, "shopChineseNames": model.ShopChineseNames, "printerVendorInfo": model.PrinterVendorInfo, @@ -135,17 +89,13 @@ func InitServiceInfo(version string, buildTime time.Time, gitCommit string) { "actTypeName": model.ActTypeName, "actStatusName": model.ActStatusName, "actCreateTypeName": model.ActCreateTypeName, - "storeAuditStatusName": model.StoreAuditStatusName, "configTypeName": model.ConfigTypeName, "userTypeName": model.UserTypeName, - "storePriceTypeName": model.StorePriceTypeName, "payStatusName": model.PayStatusName, "refundStatusName": model.RefundStatusName, - "autoReplyTypeName": model.AutoReplyTypeName, "complaintReasons": model.ComplaintReasons, "supplementType": model.SupplementTypeName, "operateType": model.OperateTypeName, - "thingType": model.ThingTypeName, "apiFunctionName": model.ApiFunctionName, "vendorStatus": model.VendorStatus, }, @@ -199,175 +149,14 @@ func GetCoordinateCityInfo(ctx *jxcontext.Context, lng, lat float64) (name strin } func SendMsg2Somebody(ctx *jxcontext.Context, mobileNum, verifyCode, msgType, msgContent string) (err error) { - if needConfirmRequestMap[msgType] == 1 { - if _, err = mobile.AutherObj.VerifySecret(mobileNum, verifyCode); err != nil { - return err - } - } - db := dao.GetDB() - //获取门店信息 - var ( - stores []*model.Store - authBinds []*model.AuthBind - order *model.GoodsOrder - storeName string - storeID int - vendorOrderID string - ) - if mobileNum != "" { - sql := ` - SELECT * FROM store WHERE (tel1 = ? OR tel2 = ?) AND deleted_at = ? - ` - sqlParams := []interface{}{mobileNum, mobileNum, utils.DefaultTimeValue} - err = dao.GetRows(db, &stores, sql, sqlParams) - if len(stores) > 0 { - storeName = stores[0].Name - storeID = stores[0].ID - } - if storeID == 0 { - results := regexpMsgContentOpID.FindStringSubmatch(msgContent) - if len(results) > 0 { - sql3 := ` - SELECT * FROM auth_bind WHERE auth_id = ? OR auth_id2 = ? - ` - sqlParams3 := []interface{}{results[1], results[1]} - err = dao.GetRows(db, &authBinds, sql3, sqlParams3) - if len(authBinds) > 0 { - user, _ := dao.GetUserByID(db, "user_id", authBinds[0].UserID) - mobileNum = *user.Mobile - sqlParams4 := []interface{}{mobileNum, mobileNum, utils.DefaultTimeValue} - err = dao.GetRows(db, &stores, sql, sqlParams4) - if len(stores) > 0 { - storeName = stores[0].Name - storeID = stores[0].ID - } - } - } - } - } else { - results := regexpMsgContentOpID.FindStringSubmatch(msgContent) - if len(results) > 0 { - sql3 := ` - SELECT * FROM auth_bind WHERE auth_id = ? OR auth_id2 = ? - ` - sqlParams3 := []interface{}{results[1], results[1]} - err = dao.GetRows(db, &authBinds, sql3, sqlParams3) - if len(authBinds) > 0 { - user, _ := dao.GetUserByID(db, "user_id", authBinds[0].UserID) - mobileNum = *user.Mobile - sql4 := ` - SELECT * FROM store WHERE (tel1 = ? OR tel2 = ?) AND deleted_at = ? - ` - sqlParams4 := []interface{}{mobileNum, mobileNum, utils.DefaultTimeValue} - err = dao.GetRows(db, &stores, sql4, sqlParams4) - if len(stores) > 0 { - storeName = stores[0].Name - storeID = stores[0].ID - } - } - } - } - sql2 := ` - SELECT * - FROM goods_order - WHERE IF(store_id <> '', store_id, jx_store_id) = ? - ORDER BY order_created_at DESC - LIMIT 1 - ` - sqlParams2 := []interface{}{storeID} - err = dao.GetRow(db, &order, sql2, sqlParams2) - if order != nil { - vendorOrderID = order.VendorOrderID - } - if storeID == 0 { - vendorOrderID = "" - } - msgContent = msgContent + " 门店名称:" + storeName + " 门店ID:" + utils.Int2Str(storeID) + " 最新订单号:" + vendorOrderID - for _, v := range receiveMsgUsersMap[msgType] { - user, err2 := dao.GetUserByID(db, "name", v) - if err2 == nil { - ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.GetID(), msgType, msgContent) - } else if err == nil { - err = err2 - } - } - return err -} -func checkSysConfig(key, value string) (err error) { - if limit := SysConfigLimitMap[key]; limit != nil { - if limit.ValueType == reflect.Int { - int64Value, err2 := strconv.ParseInt(value, 10, 64) - if err = err2; err == nil { - if int64Value < limit.MinValue || int64Value > limit.MaxValue { - err = fmt.Errorf("配置%s,值%s超范围[%d,%d]", key, value, limit.MinValue, limit.MaxValue) - } - } - } - } - return err -} - -func onSysConfigChanged(key, value string) (err error) { - if limit := SysConfigLimitMap[key]; limit != nil && limit.AfterChanged != nil { - err = limit.AfterChanged() - } - return err -} - -func checkConfig(opFlag int, configType, key, value string) (err error) { - switch configType { - case model.ConfigTypePricePack: - if value != "" { - pricePack := dao.PricePercentagePack2Obj(value) - if pricePack == nil { - err = fmt.Errorf("配置:%s不合法", value) - } - } - case model.ConfigTypeFreightPack: - if value != "" { - freightPack := dao.FreightDeductionPack2Obj(value) - if freightPack == nil { - err = fmt.Errorf("配置:%s不合法", value) - } else { - var lastStage *model.FreightDeductionItem - for _, v := range freightPack.FreightDeductionList { - if lastStage != nil && lastStage.DeductFreight > v.DeductFreight { - err = fmt.Errorf("免运设置不合理:门槛:%s,免运金额:%s,门槛:%s,免运金额:%s", - jxutils.IntPrice2StandardString(int64(lastStage.BeginPrice)), jxutils.IntPrice2StandardString(int64(lastStage.DeductFreight)), - jxutils.IntPrice2StandardString(int64(v.BeginPrice)), jxutils.IntPrice2StandardString(int64(v.DeductFreight))) - return err - } - lastStage = v - } - } - } - case model.ConfigTypeBank: - if value != "" { - if model.BankName[key] == "" { - err = fmt.Errorf("此银行代码:%s不支持,请联系开发", value) - } - } - case model.ConfigTypeRole: - case model.ConfigTypeSys: - if opFlag&( /*model.SyncFlagNewMask|*/ model.SyncFlagDeletedMask) != 0 { - err = fmt.Errorf("系统参数只支持修改或添加,不支持删除") - } else { - err = checkSysConfig(key, value) - } - case model.ConfigTypeJxStore: - case model.ConfigTypeCookie: - case model.ConfigTypeDiscountCard: - default: - err = fmt.Errorf("当前只支持配置:%s, 传入的配置类型:%s", utils.Format4Output(model.ConfigTypeName, true), configType) - } return err } func AddConfig(ctx *jxcontext.Context, key, configType, value string) (err error) { - if err = checkConfig(model.SyncFlagNewMask, configType, key, value); err != nil { - return err - } + // if err = checkConfig(model.SyncFlagNewMask, configType, key, value); err != nil { + // return err + // } db := dao.GetDB() conf := &model.NewConfig{ @@ -378,41 +167,21 @@ func AddConfig(ctx *jxcontext.Context, key, configType, value string) (err error dao.WrapAddIDCULDEntity(conf, ctx.GetUserName()) err = dao.CreateEntity(db, conf) if configType == model.ConfigTypeSys && err == nil { - err = onSysConfigChanged(key, value) + // err = onSysConfigChanged(key, value) } return err } func DeleteConfig(ctx *jxcontext.Context, key, configType string) (err error) { - if err = checkConfig(model.SyncFlagDeletedMask, configType, key, ""); err != nil { - return err - } + // if err = checkConfig(model.SyncFlagDeletedMask, configType, key, ""); err != nil { + // return err + // } db := dao.GetDB() switch configType { case model.ConfigTypePricePack: - storeMapList, err2 := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, key, "") - if err = err2; err == nil { - var storeInfo []string - for _, v := range storeMapList { - storeInfo = append(storeInfo, fmt.Sprintf("门店:%d, 平台:%s", v.StoreID, model.VendorChineseNames[v.VendorID])) - } - if len(storeInfo) > 0 { - err = fmt.Errorf("还有门店在使用价格包:%s,门店信息:%s", key, strings.Join(storeInfo, ",")) - } - } + case model.ConfigTypeFreightPack: - storeMapList, err2 := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "") - if err = err2; err == nil { - var storeInfo []string - for _, v := range storeMapList { - if v.FreightDeductionPack == key { - storeInfo = append(storeInfo, fmt.Sprintf("门店:%d, 平台:%s", v.StoreID, model.VendorChineseNames[v.VendorID])) - } - } - if len(storeInfo) > 0 { - err = fmt.Errorf("还有门店在使用价格包:%s,门店信息:%s", key, strings.Join(storeInfo, ",")) - } - } + case model.ConfigTypeBank: //todo return fmt.Errorf("暂不支持删除银行") @@ -428,14 +197,7 @@ func DeleteConfig(ctx *jxcontext.Context, key, configType string) (err error) { } } errList.AddErr(err) - storeList, err2 := dao.GetStoreList(db, nil, nil, nil, nil, key) - if err = err2; err == nil && len(storeList) > 0 { - storeIDs := make([]int, len(storeList)) - for k, v := range storeList { - storeIDs[k] = v.ID - } - err = fmt.Errorf("还有门店在使用角色:%s,门店信息:%s", key, utils.MustMarshal(storeIDs)) - } + errList.AddErr(err) err = errList.GetErrListAsOne() } @@ -446,7 +208,7 @@ func DeleteConfig(ctx *jxcontext.Context, key, configType string) (err error) { }) } if configType == model.ConfigTypeSys && err == nil { - err = onSysConfigChanged(key, "") + // err = onSysConfigChanged(key, "") } return err } @@ -455,9 +217,6 @@ func UpdateConfig(ctx *jxcontext.Context, key, configType, value string) (hint s if key == "" { return "", fmt.Errorf("修改配置必须给定key") } - if err = checkConfig(model.SyncFlagModifiedMask, configType, key, value); err != nil { - return "", err - } hint = "1" db := dao.GetDB() @@ -486,7 +245,7 @@ func UpdateConfig(ctx *jxcontext.Context, key, configType, value string) (hint s dao.Commit(db) } if configType == model.ConfigTypeSys && err == nil { - err = onSysConfigChanged(key, value) + // err = onSysConfigChanged(key, value) } return hint, err } @@ -494,17 +253,3 @@ func UpdateConfig(ctx *jxcontext.Context, key, configType, value string) (hint s func QueryConfigs(key, configType, keyword string) (configList []*model.NewConfig, err error) { return dao.QueryConfigs(dao.GetDB(), key, configType, keyword) } - -func GetCityBankBranches(ctx *jxcontext.Context, cityCode int, bankCode string) (info map[int]map[string][]string, err error) { - list, err := dao.GetCityBankBranches(dao.GetDB(), cityCode, bankCode) - if err == nil && len(list) > 0 { - info = make(map[int]map[string][]string) - for _, v := range list { - if info[v.CityCode] == nil { - info[v.CityCode] = make(map[string][]string) - } - info[v.CityCode][v.PayeeBankCode] = append(info[v.CityCode][v.PayeeBankCode], v.PayeeBankBranchName) - } - } - return info, err -} diff --git a/business/jxstore/cms/storeman.go b/business/jxstore/cms/storeman.go deleted file mode 100644 index d77e02159..000000000 --- a/business/jxstore/cms/storeman.go +++ /dev/null @@ -1,127 +0,0 @@ -package cms - -import ( - "git.rosy.net.cn/baseapi/utils" - "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" - "git.rosy.net.cn/jx-callback/business/model" - "git.rosy.net.cn/jx-callback/business/model/dao" - "git.rosy.net.cn/jx-callback/business/partner" - "git.rosy.net.cn/jx-callback/globals" -) - -type StoreManager struct { -} - -var ( - FixedStoreManager *StoreManager -) - -func init() { - FixedStoreManager = &StoreManager{} - partner.InitStoreManager(FixedStoreManager) -} - -func (s *StoreManager) OnStoreStatusChanged(vendorStoreID string, vendorID int, storeStatus int) (err error) { - return err - globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeStatus:%d", vendorStoreID, storeStatus) - db := dao.GetDB() - storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, vendorStoreID, vendorID) - if err == nil { - var storeKV, storeMapKV map[string]interface{} - if storeStatus == model.StoreStatusOpened { - if storeDetail.Status != model.StoreStatusOpened { - storeKV = map[string]interface{}{ - "Status": model.StoreStatusOpened, - } - } - if storeDetail.VendorStatus != model.StoreStatusOpened { - storeMapKV = map[string]interface{}{ - "Status": model.StoreStatusOpened, - } - } - } else { - if storeDetail.Status == model.StoreStatusOpened { - if storeDetail.VendorStatus != storeStatus { - storeMapKV = map[string]interface{}{ - "Status": storeStatus, - } - } - } else if storeDetail.Status <= storeStatus { - if storeDetail.VendorStatus != model.StoreStatusOpened { - storeMapKV = map[string]interface{}{ - "Status": model.StoreStatusOpened, - } - } - } - } - if err == nil && (storeKV != nil || storeMapKV != nil) { - dao.Begin(db) - defer func() { - if r := recover(); r != nil || err != nil { - dao.Rollback(db) - if r != nil { - panic(r) - } - } - }() - if storeKV != nil { - globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeKV:%s", vendorStoreID, utils.Format4Output(storeKV, true)) - store := &model.Store{} - store.ID = storeDetail.Store.ID - if err = utils.CallFuncLogError(func() error { - _, err = dao.UpdateEntityLogically(db, store, storeKV, model.AdminName, nil) - return err - }, "OnStoreStatusChanged Update Store venvendorStoreID:%s", vendorStoreID); err != nil { - return err - } - } - if storeMapKV != nil { - globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeMapKV:%s", vendorStoreID, utils.Format4Output(storeMapKV, true)) - if err = utils.CallFuncLogError(func() error { - _, err = dao.UpdateEntityLogically(db, &model.StoreMap{}, storeMapKV, model.AdminName, map[string]interface{}{ - model.FieldStoreID: storeDetail.Store.ID, - model.FieldVendorID: vendorID, - model.FieldDeletedAt: utils.DefaultTimeValue, - }) - return err - }, "OnStoreStatusChanged Update StoreMap venvendorStoreID:%s", vendorStoreID); err != nil { - return err - } - } - if storeStatus != model.StoreStatusOpened { - // 因为storeStatus != model.StoreStatusOpened不会修改京西门店的状态,所以直接用storeDetail.Status是合适的 - if err = utils.CallFuncLogError(func() error { - return dao.FormalizeStoreStatus(db, storeDetail.Store.ID, storeDetail.Status) - }, "OnStoreStatusChanged FormalizeStoreStatus venvendorStoreID:%s", vendorStoreID); err != nil { - return err - } - } - dao.Commit(db) - } - } - return err -} - -func (s *StoreManager) OnCourierStoreStatusChanged(ctx *jxcontext.Context, vendorStoreID string, vendorID int, auditStatus int) (err error) { - if vendorStoreID != "" { - db := dao.GetDB() - _, err2 := dao.GetStoreDetail2(db, 0, vendorStoreID, vendorID) - if err = err2; err == nil { - status := model.StoreStatusOpened - if auditStatus != model.StoreAuditStatusOnline { - status = model.StoreStatusDisabled - } - _, err = dao.UpdateEntityLogically(db, &model.StoreCourierMap{}, map[string]interface{}{ - model.FieldStatus: status, - "AuditStatus": auditStatus, - }, ctx.GetUserName(), map[string]interface{}{ - model.FieldVendorStoreID: vendorStoreID, - model.FieldVendorID: vendorID, - }) - } else if dao.IsNoRowsError(err) { - err = nil - } - } - globals.SugarLogger.Debugf("OnCourierStoreStatusChanged vendorStoreID:%s, auditStatus:%d, err:%v", vendorStoreID, auditStatus, err) - return err -} diff --git a/business/jxstore/cms/sync.go b/business/jxstore/cms/sync.go index 9212cba25..d5a72a758 100644 --- a/business/jxstore/cms/sync.go +++ b/business/jxstore/cms/sync.go @@ -7,7 +7,6 @@ import ( "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" - "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/partner" ) @@ -29,8 +28,8 @@ type SyncErrResultLock struct { } type LoopStoreMapInfo struct { - VendorID int - StoreMapList []*model.StoreMap + VendorID int + // StoreMapList []*model.StoreMap } type VendorSync struct { diff --git a/business/jxstore/cms/user2.go b/business/jxstore/cms/user2.go index 22ad6d821..c92d4c9f3 100644 --- a/business/jxstore/cms/user2.go +++ b/business/jxstore/cms/user2.go @@ -3,29 +3,18 @@ package cms import ( "errors" "fmt" - "sort" - "strings" "sync" "time" - "git.rosy.net.cn/jx-callback/business/partner/purchase/jd" - - "git.rosy.net.cn/jx-callback/globals/api/apimanager" - "git.rosy.net.cn/baseapi" - "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/jx-callback/business/jxutils/excel" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" - "git.rosy.net.cn/baseapi/utils/errlist" - "git.rosy.net.cn/baseapi/platformapi/dingdingapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/auth2" "git.rosy.net.cn/jx-callback/business/auth2/authprovider/dingding" - "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" "git.rosy.net.cn/jx-callback/business/authz" - "git.rosy.net.cn/jx-callback/business/authz/autils" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/jsonerr" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" @@ -209,7 +198,7 @@ func RegisterUserWithMobile(ctx *jxcontext.Context, user *model.User, mobileVeri } if err = CreateUser(user, utils.LimitUTF8StringLen(createName, 32)); err == nil { userProvider.UpdateLastLogin(user.GetID(), authType, ctx.GetRealRemoteIP()) - TryAddStoreBossRole4User(ctx, user) + // TryAddStoreBossRole4User(ctx, user) if mobileAuth != nil { if outAuthInfo, err = auth2.BindUser(mobileAuth, user); err == nil && inAuthInfo != nil { err = auth2.AddAuthBind(&outAuthInfo.UserBasic, inAuthInfo) @@ -223,146 +212,6 @@ func RegisterUserWithMobile(ctx *jxcontext.Context, user *model.User, mobileVeri return outAuthInfo, err } -func TryAddStoreBossRole4User(ctx *jxcontext.Context, user *model.User) (err error) { - if user.Type&model.UserTypeStoreBoss != 0 { - userMobile := user.GetMobile() - if userMobile != "" { - if storeList, err := dao.GetStoreList(dao.GetDB(), nil, nil, nil, []string{userMobile}, ""); err == nil && len(storeList) > 0 { - roleList := make([]*authz.RoleInfo, len(storeList)) - for k, v := range storeList { - roleList[k] = autils.NewStoreBossRole(v.ID) - } - err = AddRoles4User(ctx, user.GetID(), roleList) - } - } - } - return err -} - -func TryAddStoreBossRole4StoreByMobile(ctx *jxcontext.Context, storeID int, mobileList []string) (err error) { - if storeID > 0 { - var userIDs []string - for _, v := range mobileList { - if v != "" { - if userList, _, err := dao.GetUsers(dao.GetDB(), model.UserTypeStoreBoss, "", nil, nil, []string{v}, 0, -1); err == nil && len(userList) > 0 { - userIDs = append(userIDs, userList[0].GetID()) - } - } - } - if len(userIDs) > 0 { - role := autils.NewStoreBossRole(storeID) - err = AddUsers4Role(ctx, role, userIDs) - } - } - return err -} - -func HandleOrder4Consignee(order *model.GoodsOrder) (err error) { - var user *model.User - mobileNumber := jxutils.GetRealMobile4Order(order) - if mobileNumber == "" && order.VendorUserID == "" { - return fmt.Errorf("订单:%s手机号与平台用户标识都是空", order.VendorOrderID) - } - authType := dao.GetAuthType4Vendor(order.VendorID) - if authType == "" { - msg := fmt.Sprintf("平台ID:%d当前不被支持,请联系开发", order.VendorID) - globals.SugarLogger.Warn(msg) - return fmt.Errorf(msg) - } - - oeratorName := order.VendorOrderID - db := dao.GetDB() - if mobileNumber != "" { - userList, _, err2 := dao.GetUsers(db, 0, "", nil, nil, []string{mobileNumber}, 0, 0) - if err = err2; err != nil { - return err - } - if len(userList) > 0 { - user = userList[0] - } - } - - vendorUserID := order.VendorUserID - if vendorUserID != "" { - authInfo, err2 := dao.GetAuthBind(db, model.AuthBindTypeID, authType, vendorUserID) - if err = err2; err != nil && !dao.IsNoRowsError(err) { - return err - } - if err == nil { - vendorUserID = "" - if user == nil { - if user, err = dao.GetUserByID(db, "user_id", authInfo.UserID); err != nil { - return err - } - } - } else { - err = nil - } - } - - const Remark = "fromOrder" - if user == nil { - user = &model.User{ - UserID2: mobileNumber, - Name: order.ConsigneeName, - Mobile: &mobileNumber, - Type: model.UserTypeConsumer, - Address: order.ConsigneeAddress, - Remark: Remark, - } - setUserAddress(db, user, order) - - if user.GetID2() == "" { - user.UserID2 = order.VendorUserID - } - if user.GetID2() == "" { - user.UserID2 = order.VendorOrderID - } - - user.Type = model.UserTypeConsumer - err = CreateUser(user, oeratorName) - } else { - if user.GetMobile() == "" && mobileNumber != "" { - user.Mobile = &mobileNumber - dao.UpdateEntity(db, user, "Mobile") - } - } - if err == nil { - order.UserID = user.GetID() - if vendorUserID != "" { - authBind := &model.AuthBind{ - UserID: user.GetID(), - BindType: model.AuthBindTypeID, - AuthID: vendorUserID, - Type: authType, - Remark: Remark, - } - dao.WrapAddIDCULDEntity(authBind, oeratorName) - authBind.Status = model.AuthBindStatusNormal - err = dao.CreateEntity(nil, authBind) - } - } - return err -} - -func setUserAddress(db *dao.DaoDB, user *model.User, order *model.GoodsOrder) { - user.Address = order.ConsigneeAddress - store := &model.Store{} - store.ID = jxutils.GetSaleStoreIDFromOrder(order) - if err := dao.GetEntity(db, store); err == nil { - user.CityCode = store.CityCode - user.DistrictCode = store.DistrictCode - } else if dao.IsNoRowsError(err) { - if order.ConsigneeLng != 0 && order.ConsigneeLat != 0 { - if user.DistrictCode = api.AutonaviAPI.GetCoordinateDistrictCode(jxutils.IntCoordinate2Standard(order.ConsigneeLng), jxutils.IntCoordinate2Standard(order.ConsigneeLat)); user.DistrictCode > 0 { - if placeInfo, err := dao.GetPlaceByCode(db, user.DistrictCode); err == nil { - user.CityCode = placeInfo.ParentCode - } - } - } - } -} - func GetUserBindAuthInfo(ctx *jxcontext.Context) (authList []*model.AuthBind, err error) { authInfo, err := ctx.GetV2AuthInfo() if err == nil { @@ -435,55 +284,6 @@ func GetUsers(ctx *jxcontext.Context, userType int, keyword string, userIDs []st return pagedInfo, err } -func GetStoreList4User(ctx *jxcontext.Context, mobileNum, userID string) (storeList []*dao.StoreWithCityName, err error) { - roleList, err := api2.RoleMan.GetUserRoleList(userID) - if err != nil { - return nil, err - } - var ( - storeIDs []int - shortRoleNameList []string - ) - for _, v := range roleList { - if v.StoreID == 0 { - shortRoleNameList = append(shortRoleNameList, v.Name) - } else { - storeIDs = append(storeIDs, v.StoreID) - } - } - storeList, err = dao.GetStoreListByMobileOrStoreIDs(dao.GetDB(), mobileNum, shortRoleNameList, storeIDs) - return storeList, err -} - -func GetMyStoreListNew(ctx *jxcontext.Context) (storesInfo interface{}, errCode string, err error) { - if !auth2.IsV2Token(ctx.GetToken()) { - return nil, model.ErrCodeTokenIsInvalid, model.ErrTokenIsInvalid - } - mobileNum, userID := ctx.GetMobileAndUserID() - if mobileNum == "" { - return nil, "", fmt.Errorf("不能得到用户手机号") - } - var storeList []*dao.StoreWithCityName - if storeList, err = GetStoreList4User(ctx, mobileNum, userID); err == nil && len(storeList) > 0 { - // todo,应该用通用方法 - mapDataList := make([]map[string]interface{}, len(storeList)) - for k, v := range storeList { - mapDataList[k] = map[string]interface{}{ - "id": v.ID, - "address": v.Address, - "cityName": v.CityName, - "name": v.Name, - "tel1": v.Tel1, - "tel2": v.Tel2, - "payeeName": v.PayeeName, - "status": v.Status, - } - } - storesInfo = mapDataList - } - return storesInfo, "", err -} - func GetStoreRoleList(ctx *jxcontext.Context) (roleList []*authz.RoleInfo, err error) { return authz.StoreRoleList, nil } @@ -523,68 +323,6 @@ func checkUserType(userID string, userType int8) (err error) { return nil } -func AddRoles4User(ctx *jxcontext.Context, userID string, rList []*authz.RoleInfo) (err error) { - errList := errlist.New() - if err = checkUserType(userID, model.UserTypeNonConsumer); err != nil { - return err - } - for _, v := range rList { - if err = autils.ValidateRole(v.Name, v.StoreID); err == nil { - if err = api2.RoleMan.AddRole4User(userID, v); err != nil { - errList.AddErr(err) - } else if v.StoreID > 0 { - HandleUserWXRemark(dao.GetDB(), userID, true) - } - } else { - errList.AddErr(err) - } - } - return errList.GetErrListAsOne() -} - -func DeleteRoles4User(ctx *jxcontext.Context, userID string, rList []*authz.RoleInfo) (err error) { - errList := errlist.New() - for _, v := range rList { - if err = api2.RoleMan.DeleteRole4User(userID, v); err != nil { - errList.AddErr(err) - } else if v.StoreID > 0 { - HandleUserWXRemark(dao.GetDB(), userID, true) - } - } - return errList.GetErrListAsOne() -} - -func AddUsers4Role(ctx *jxcontext.Context, r *authz.RoleInfo, userIDList []string) (err error) { - if err = autils.ValidateRole(r.Name, r.StoreID); err != nil { - return err - } - - errList := errlist.New() - for _, v := range userIDList { - if err = checkUserType(v, model.UserTypeNonConsumer); err != nil { - return err - } - if err = api2.RoleMan.AddRole4User(v, r); err != nil { - errList.AddErr(err) - } else if r.StoreID > 0 { - HandleUserWXRemark(dao.GetDB(), v, true) - } - } - return errList.GetErrListAsOne() -} - -func DeleteUsers4Role(ctx *jxcontext.Context, r *authz.RoleInfo, userIDList []string) (err error) { - errList := errlist.New() - for _, v := range userIDList { - if err = api2.RoleMan.DeleteRole4User(v, r); err != nil { - errList.AddErr(err) - } else if r.StoreID > 0 { - HandleUserWXRemark(dao.GetDB(), v, true) - } - } - return errList.GetErrListAsOne() -} - func getAddressInfoFromCoord(db *dao.DaoDB, lng, lat float64) (formattedAddress string, districtCode, cityCode int, err error) { regeoInfo, err := api.AutonaviAPI.GeoCodeRegeoSingle(lng, lat, 0, false, nil, 0, 0) if err == nil { @@ -792,167 +530,6 @@ func GetSelfInfo(ctx *jxcontext.Context) (getSelfInfoResult *dao.GetSelfInfoResu return getSelfInfoResult, err } -func HandleUserWXRemark(db *dao.DaoDB, mobile string, mobileIsUerID bool) (err error) { - if db == nil { - db = dao.GetDB() - } - openIDs := []string{} - storeID := 0 - remark := "" - - // if !globals.DisableWXAuth1 { - // wxinfo, err := dao.GetUserStoreInfo(db, "tel", mobile) - // if err == nil { - // openIDs = []string{wxinfo.OpenID} - // storeID = wxinfo.JxStoreID - // } - // } - if globals.EnableWXAuth2 { - userID := "" - if mobileIsUerID { - userID = mobile - } else { - userList, _, err2 := dao.GetUsers(db, model.UserTypeStoreBoss, "", nil, nil, []string{mobile}, 0, -1) - if err = err2; len(userList) > 0 { - userID = userList[0].GetID() - } - } - if userID != "" { - authBindList, err2 := dao.GetUserBindAuthInfo(db, userID, model.AuthBindTypeAuth, []string{weixin.AuthTypeMP}, "", "", "") - if err = err2; err == nil { - for _, v := range authBindList { - openIDs = append(openIDs, v.AuthID) - } - } - roleList, err2 := api2.RoleMan.GetUserRoleList(userID) - if err = err2; err == nil && len(roleList) > 0 { - storeID = roleList[0].StoreID - } - } - } - - if len(openIDs) > 0 { - if storeID > 0 { - store := &model.Store{} - store.ID = storeID - if err = dao.GetEntity(db, store); err == nil { - city := &model.Place{ - Code: store.CityCode, - } - if err = dao.GetEntity(db, city, "Code"); err == nil { - remark = city.Name + "-" + store.Name - } - } - } - if err == nil { - if globals.EnableStoreWrite { - for _, openID := range openIDs { - err = api.WeixinAPI.CBUpdateRemark(openID, remark) - } - } - } - } - return err -} - -func GetJdUsers(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { - var ( - jxVendorIDsMap = make(map[string]string) - pageNoList []int - storeUserList []interface{} - disabledIdList []interface{} - ) - db := dao.GetDB() - jdUsersStruct.userMap = jdUsersStruct.userMap[0:0] - taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { - switch step { - case 0: - //获取京东商城所有用户 - apiList := apimanager.CurAPIManager.GetAppOrgCodeList(model.VendorIDJD) - for _, v := range apiList { - _, _, toatlPage, _ := jd.GetAPI(v).PrivilegeSearchUser(1) - for i := 1; i <= toatlPage; i++ { - pageNoList = append(pageNoList, i) - } - storeMapList, _ := dao.GetStoreMapsListWithoutDisabled(db, []int{model.VendorIDJD}, model.StoreStatusDisabled) - for _, v := range storeMapList { - jxVendorIDsMap[v.VendorStoreID] = utils.Int64ToStr(int64(v.StoreID)) - } - taskFunc1 := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - pageNo := batchItemList[0].(int) - storeUserLists, _, _, err := jd.GetAPI(v).PrivilegeSearchUser(pageNo) - retVal = storeUserLists - return retVal, err - } - taskParallel1 := tasksch.NewParallelTask("获取京东商城所有用户列表", tasksch.NewParallelConfig(), ctx, taskFunc1, pageNoList) - tasksch.HandleTask(taskParallel1, task, true).Run() - storeUserList, err = taskParallel1.GetResult(0) - - taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - vv := batchItemList[0].(*jdapi.StoreUserInfo) - vendorStoreIDs, err := jd.GetAPI(v).GetJdUserBindStoreIDs(vv.ID) - var vendorStoreIDsMap = make(map[string]string, len(vendorStoreIDs)) - var vendorStoreIDsResult []string - var roleNameStr string - for _, v := range vendorStoreIDs { - if jxVendorIDsMap[v] == "" { - continue - } - vendorStoreIDsMap[v] = jxVendorIDsMap[v] - } - if vv.RoleNameStr != "" { - roleNameStr = strings.ReplaceAll(vv.RoleNameStr, " ", "") - if roleNameStr != jdapi.JdUserRoleJHYName && roleNameStr != jdapi.JdUserRolesName && roleNameStr != jdapi.JdUserNoRole { - jd.GetAPI(v).UpdateJdUserRoles(int64(vv.ID), []string{jdapi.JdUserRoleJHYId}) - } - } - if len(vendorStoreIDsMap) == 0 { - isManager, _ := jd.GetAPI(v).IsJdManagerUser(int64(vv.ID)) - if isManager { - jdStruct := JdUserStruct{vv.LoginName, "商家管理员", vv.RoleNameStr, vv.LockStatus} - jdUsersStruct.AppendData(jdStruct) - } else { - retVal = []int64{int64(vv.ID)} - } - } else { - for _, m := range vendorStoreIDsMap { - vendorStoreIDsResult = append(vendorStoreIDsResult, m) - } - sort.Strings(vendorStoreIDsResult[:]) - jdStruct := JdUserStruct{vv.LoginName, strings.Join(vendorStoreIDsResult, ","), vv.RoleNameStr, vv.LockStatus} - jdUsersStruct.AppendData(jdStruct) - } - return retVal, err - } - taskParallel := tasksch.NewParallelTask("获取京东商城用户关联门店列表", tasksch.NewParallelConfig(), ctx, taskFunc, storeUserList) - tasksch.HandleTask(taskParallel, task, true).Run() - disabledIdList, err = taskParallel.GetResult(0) - - taskFunc2 := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - id := batchItemList[0].(int64) - jd.GetAPI(v).PrivilegeUpdateJdUserStatus(id, jdapi.JdUserStatusDisable) - return retVal, err - } - taskParallel2 := tasksch.NewParallelTask("禁用未关联活跃门店用户", tasksch.NewParallelConfig(), ctx, taskFunc2, disabledIdList) - tasksch.HandleTask(taskParallel2, task, true).Run() - _, err = taskParallel2.GetResult(0) - } - case 1: - WriteToExcelJd(task, jdUsersStruct.userMap) - } - return result, err - } - taskSeq := tasksch.NewSeqTask2("获取京东商城用户关联门店列表-序列任务", ctx, isContinueWhenError, taskSeqFunc, 2) - tasksch.HandleTask(taskSeq, nil, true).Run() - if !isAsync { - _, err = taskSeq.GetResult(0) - hint = "1" - } else { - hint = taskSeq.GetID() - } - return hint, err -} - func (d *GetJdUsersStruct) AppendData(jd JdUserStruct) { d.locker.RLock() defer d.locker.RUnlock() @@ -1069,34 +646,6 @@ func DeleteUserInfo(ctx *jxcontext.Context, userID string) (err error) { return err } -func GetMyJxStoreList(ctx *jxcontext.Context, mobile string) (storesInfo interface{}, err error) { - db := dao.GetDB() - user, err := dao.GetUserByID(db, "mobile", mobile) - if err != nil { - return nil, err - } - userID := user.UserID - var storeList []*dao.StoreWithCityName - if storeList, err = GetStoreList4User(ctx, mobile, userID); err == nil && len(storeList) > 0 { - // todo,应该用通用方法 - mapDataList := make([]map[string]interface{}, len(storeList)) - for k, v := range storeList { - mapDataList[k] = map[string]interface{}{ - "id": v.ID, - "address": v.Address, - "cityName": v.CityName, - "name": v.Name, - "tel1": v.Tel1, - "tel2": v.Tel2, - "payeeName": v.PayeeName, - "status": v.Status, - } - } - storesInfo = mapDataList - } - return storesInfo, err -} - func CreateUserAgreement(ctx *jxcontext.Context, userAgrs []*model.UserAgreement) (err error) { var ( db = dao.GetDB() diff --git a/business/jxstore/cms/validation.go b/business/jxstore/cms/validation.go deleted file mode 100644 index 4797f8d39..000000000 --- a/business/jxstore/cms/validation.go +++ /dev/null @@ -1,50 +0,0 @@ -package cms - -import ( - "fmt" - - "gopkg.in/go-playground/validator.v9" - - "git.rosy.net.cn/jx-callback/business/jxutils" - "git.rosy.net.cn/jx-callback/business/model" -) - -var ( - unitNamesMap map[string]int - specUnitNamesMap map[string]int - validate = validator.New() -) - -func init() { - unitNamesMap = jxutils.MakeValidationMapFromSlice(model.UnitNames, 1) - specUnitNamesMap = jxutils.MakeValidationMapFromSlice(model.SpecUnitNames, 1) -} - -func validateStringInMap(name string, value interface{}, flagMap map[string]int) (err error) { - if strValue, ok := value.(string); ok { - if flagMap[strValue] == 1 { - return nil - } - } - return fmt.Errorf("属性%s类型或取值不合法,要求string", name) -} - -func ValidateUnit(value interface{}) (err error) { - return validateStringInMap("Unit", value, unitNamesMap) -} - -func ValidateSpecUnit(value interface{}) (err error) { - return validateStringInMap("SpecUnit", value, specUnitNamesMap) -} - -func ValidateStruct(value interface{}) (err error) { - return validate.Struct(value) -} - -func ValidateVar(value interface{}, tag string) (err error) { - return validate.Var(value, tag) -} - -func ValidateStructPartial(value interface{}, fields ...string) (err error) { - return validate.StructPartial(value, fields...) -} diff --git a/business/jxutils/netprinter/netprinter.go b/business/jxutils/netprinter/netprinter.go deleted file mode 100644 index c1af8db20..000000000 --- a/business/jxutils/netprinter/netprinter.go +++ /dev/null @@ -1,231 +0,0 @@ -package netprinter - -import ( - "fmt" - "strings" - "time" - - "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" - - "git.rosy.net.cn/baseapi/utils" - "git.rosy.net.cn/jx-callback/business/partner" - - "git.rosy.net.cn/jx-callback/business/jxutils" - "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" - "git.rosy.net.cn/jx-callback/business/model" - "git.rosy.net.cn/jx-callback/business/model/dao" - "git.rosy.net.cn/jx-callback/globals" -) - -const ( - testVendorOrderID = "test" - realTestVendorOrderID = "901234567890123" - realTestOrderVendorID = model.VendorIDJD -) - -const ( - PrinterNotifyUserApplyCancel = 1 - PrinterNotifyNewAfsOrder = 2 -) - -func PrintOrder(ctx *jxcontext.Context, vendorOrderID string, vendorID int) (printResult *partner.PrinterStatus, err error) { - storeID := vendorID - if vendorOrderID == testVendorOrderID { - vendorOrderID = realTestVendorOrderID - vendorID = realTestOrderVendorID - } - order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID) - if err == nil { - if vendorOrderID == realTestVendorOrderID { - order.StoreID = storeID - order.JxStoreID = storeID - } - printResult, err = PrintOrderByOrder(ctx, order) - } - return printResult, err -} - -func PrintOrderByOrder(ctx *jxcontext.Context, order *model.GoodsOrder) (printResult *partner.PrinterStatus, err error) { - return PrintOrderByOrder4Store(ctx, order, jxutils.GetSaleStoreIDFromOrder(order)) -} - -func getStore4Print(db *dao.DaoDB, storeID int) (store *model.Store, err error) { - for i := 0; i < 3; i++ { - store2 := &model.Store{} - store2.ID = storeID - if err = dao.GetEntity(db, store2); err == nil { - store = store2 - if store.LinkStoreID != 0 { - storeID = store.LinkStoreID - } else { - break - } - } else { - break - } - } - if store != nil { - err = nil - } - return store, err -} - -func PrintOrderByOrder4Store(ctx *jxcontext.Context, order *model.GoodsOrder, storeID int) (printResult *partner.PrinterStatus, err error) { - globals.SugarLogger.Debugf("PrintOrderByOrder4Store orderID:%s", order.VendorOrderID) - db := dao.GetDB() - store, err := getStore4Print(db, storeID) - if err == nil { - handler, err := GetHandlerFromStore(store) - if err != nil { - return &partner.PrinterStatus{ - PrintResult: partner.PrintResultNoPrinter, - }, nil - } - printResult, err = handler.PrintOrder(ctx, store, order) - if err == nil { - dao.SetOrderPrintFlag(db, ctx.GetUserName(), order.VendorOrderID, order.VendorID, true) - } - } - if err != nil { - globals.SugarLogger.Infof("PrintOrderByOrder4Store orderID:%s failed with error:%v", order.VendorOrderID, err) - } - return printResult, err -} - -func GetNetPrinterStatus(ctx *jxcontext.Context, storeID int) (printResult *partner.PrinterStatus, err error) { - store := &model.Store{} - store.ID = storeID - db := dao.GetDB() - if err = dao.GetEntity(db, store); err == nil { - return getNetPrinterStatus(ctx, store) - } - return nil, err -} - -func getNetPrinterStatus(ctx *jxcontext.Context, store *model.Store) (printResult *partner.PrinterStatus, err error) { - handler, err := GetHandlerFromStore(store) - if err != nil { - return &partner.PrinterStatus{ - PrintResult: partner.PrintResultNoPrinter, - }, nil - } - return handler.GetPrinterStatus(ctx, store.PrinterSN, store.PrinterKey) -} - -func GetHandlerFromStore(store *model.Store) (printerHandler partner.IPrinterHandler, err error) { - if store.IsPrinterDisabled() { - return nil, fmt.Errorf("门店%s没有启用网络打印机", store.Name) - } - if printerHandler = partner.GetPrinterPlatformFromVendorID(store.PrinterVendorID); printerHandler == nil { - return nil, fmt.Errorf("门店%s没有配置网络打印机", store.Name) - } - return printerHandler, nil -} - -func BindPrinter(ctx *jxcontext.Context, storeID int, data string) (printResult *partner.PrinterStatus, err error) { - store := &model.Store{} - store.ID = storeID - db := dao.GetDB() - if err = dao.GetEntity(db, store); err == nil { - var mapData map[string]interface{} - if err = utils.UnmarshalUseNumber([]byte(data), &mapData); err == nil { - printerVendorID := model.VendorIDUnknown - if mapData["machineCode"] != nil { - printerVendorID = model.VendorIDYiLianYun - } - if handler := partner.GetPrinterPlatformFromVendorID(printerVendorID); handler != nil { - if store.PrinterVendorID > 0 && store.PrinterVendorID != printerVendorID { - err = fmt.Errorf("门店:%d已经绑定了%s打印机,如果需要重新绑定,请联系运营先解绑", storeID, model.VendorChineseNames[store.PrinterVendorID]) - } else { - bindResult, err2 := handler.BindPrinter(ctx, mapData) - if err = err2; err == nil { - store.PrinterVendorID = printerVendorID - store.PrinterSN = bindResult.PrinterSN - store.PrinterKey = bindResult.PrinterKey - store.PrinterBindInfo = string(utils.MustMarshal(bindResult)) - if _, err = dao.UpdateEntity(db, store); err == nil { - err = handler.EmptyPrintList(ctx, bindResult.PrinterSN, bindResult.PrinterKey) - printResult, err = handler.GetPrinterStatus(ctx, bindResult.PrinterSN, bindResult.PrinterKey) - } - } - } - } else { - err = fmt.Errorf("打印机类型:%d当前不支持", printerVendorID) - } - } else { - err = fmt.Errorf("请扫描正确的二维码,如需要帮助,请联系运营!") - } - } - return printResult, err -} - -func RebindAllPrinters(ctx *jxcontext.Context, isForce, isAsync bool) (hint string, err error) { - storeList, err := dao.GetRebindPrinterStoreList(dao.GetDB()) - if err == nil { - var needRebindList []*model.Store - bindResultMap := make(map[int]*partner.BindPrinterResult) - now := time.Now() - for _, v := range storeList { - var bindResult partner.BindPrinterResult - if err = utils.UnmarshalUseNumber([]byte(v.PrinterBindInfo), &bindResult); err == nil { - if isForce || now.Sub(utils.Timestamp2Time(bindResult.ExpiresAt)) > -3*24*time.Hour { - needRebindList = append(needRebindList, v) - bindResultMap[v.ID] = &bindResult - } - } - } - - globals.SugarLogger.Debugf("RebindAllPrinters len(needRebindList):%d", len(needRebindList)) - if len(needRebindList) > 0 { - db := dao.GetDB() - task := tasksch.NewParallelTask("RebindAllPrinters", tasksch.NewParallelConfig().SetIsContinueWhenError(true).SetParallelCount(4), ctx, - func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - store := batchItemList[0].(*model.Store) - if handler := partner.GetPrinterPlatformFromVendorID(store.PrinterVendorID); handler != nil { - bindResult, err2 := handler.RebindPrinter(ctx, bindResultMap[store.ID]) - globals.SugarLogger.Debugf("RebindAllPrinters storeID:%d, result:%s, err:%v", store.ID, utils.Format4Output(bindResult, true), err2) - if err = err2; err == nil { - store.PrinterSN = bindResult.PrinterSN - store.PrinterKey = bindResult.PrinterKey - store.PrinterBindInfo = string(utils.MustMarshal(bindResult)) - if _, err = dao.UpdateEntity(db, store); err == nil { - retVal = []int{1} - } - } - } else { - globals.SugarLogger.Warnf("RebindAllPrinters strange PrinterVendorID:%d", store.PrinterVendorID) - } - return retVal, err - }, needRebindList) - - tasksch.ManageTask(task).Run() - if !isAsync { - hint = task.GetID() - } else { - result, err2 := task.GetResult(0) - if err = err2; err == nil { - hint = utils.Int2Str(len(result)) - } - } - } - } - return hint, err -} - -func NofityOrderMsg(ctx *jxcontext.Context, storeID int, orderID, notifyMsg string) (err error) { - if notifyMsg != "" { - notifyMsg = strings.ReplaceAll(notifyMsg, ",", "") - db := dao.GetDB() - store := &model.Store{} - store.ID = storeID - if err = dao.GetEntity(db, store); err == nil { - handler, err := GetHandlerFromStore(store) - if err == nil { - if globals.EnableStoreWrite { - _, err = handler.PlayText(ctx, store.PrinterSN, store.PrinterKey, orderID, notifyMsg) - } - } - } - } - return err -} diff --git a/business/jxutils/weixinmsg/weixinmsg.go b/business/jxutils/weixinmsg/weixinmsg.go index a0d2d1a80..1a93692df 100644 --- a/business/jxutils/weixinmsg/weixinmsg.go +++ b/business/jxutils/weixinmsg/weixinmsg.go @@ -10,7 +10,6 @@ import ( "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" "git.rosy.net.cn/jx-callback/business/authz/autils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" - "git.rosy.net.cn/jx-callback/business/jxutils/netprinter" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/jx-callback/business/partner" @@ -299,7 +298,6 @@ func NotifyWaybillStatus(bill *model.Waybill, order *model.GoodsOrder, isBillAlr }, } err = SendMsgToStore(jxutils.GetSaleStoreIDFromOrder(order), templateID, "", "", data) - netprinter.NofityOrderMsg(jxcontext.AdminCtx, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, title) } return err } @@ -339,7 +337,6 @@ func NotifyUserApplyCancel(order *model.GoodsOrder, cancelReason string) (err er } storeID := jxutils.GetSaleStoreIDFromOrder(order) err = SendMsgToStore(storeID, WX_ORDER_APPLY_CANCEL_TEMPLATE_ID, "", "", data) - netprinter.NofityOrderMsg(jxcontext.AdminCtx, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, title) return err } @@ -377,7 +374,6 @@ func NotifyOrderChanged(order *model.GoodsOrder) (err error) { } storeID := jxutils.GetSaleStoreIDFromOrder(order) err = SendMsgToStore(storeID, WX_ORDER_CHANGE_INFO_TEMPLATE_ID, "", "", data) - netprinter.NofityOrderMsg(jxcontext.AdminCtx, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, title) return err } @@ -420,7 +416,6 @@ func NotifyOrderCanceled(order *model.GoodsOrder) (err error) { } storeID := jxutils.GetSaleStoreIDFromOrder(order) err = SendMsgToStore(storeID, WX_ORDER_ORDER_CANCELED_TEMPLATE_ID, "", "", data) - netprinter.NofityOrderMsg(jxcontext.AdminCtx, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, title) return err } @@ -474,7 +469,6 @@ func PushJDBadCommentToWeiXin(comment *legacymodel.JxBadComments, isBadComment b } storeID := int(utils.Str2Int64(comment.Jxstoreid)) err = SendMsgToStore(storeID, WX_BAD_COMMENT_PUSH_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_SHOW_COMMENTS_DETAIL_URL, storeID), WX_MINI_TO_SHOW_COMMENTS_DETAIL_URL, data) - netprinter.NofityOrderMsg(jxcontext.AdminCtx, int(utils.Str2Int64(comment.Jxstoreid)), comment.OrderId, title) return err } @@ -636,7 +630,6 @@ func NotifyAfsOrderStatus(afsOrder *model.AfsOrder) (err error) { } storeID := jxutils.GetSaleStoreIDFromAfsOrder(afsOrder) err = SendMsgToStore(storeID, templateID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data) - netprinter.NofityOrderMsg(jxcontext.AdminCtx, jxutils.GetSaleStoreIDFromAfsOrder(afsOrder), afsOrder.VendorOrderID, comment) return err } diff --git a/business/partner/partner.go b/business/partner/partner.go new file mode 100644 index 000000000..36d5a3d2d --- /dev/null +++ b/business/partner/partner.go @@ -0,0 +1,307 @@ +package partner + +import ( + "errors" + "fmt" + "time" + + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" +) + +const ( + StoreNameSeparator = "-" +) + +const ( + CreatedPeration = "create" + UpdatedPeration = "update" +) + +const ( + CancelWaybillReasonNotAcceptIntime = 1 + CancelWaybillReasonSwitch2SelfFailed = 2 + CancelWaybillReasonOther = 10 +) + +const ( + AfsApproveTypeRefund = 1 // 退款 + AfsApproveTypeReturnGoods = 2 // 退货 + AfsApproveTypeRefused = 3 // 驳回 +) + +const ( + TimerTypeNoOverride = 0 // GetStatusActionConfig 返回表示不修改缺省配置 + TimerTypeByPass = 1 + TimerTypeBaseNow = 2 + TimerTypeBaseStatusTime = 3 + TimerTypeBaseOrderCreatedAt = 4 +) + +type StatusActionParams struct { + TimerType int // 参见上面的相关常量定义 + Timeout time.Duration // 超时时间,0在GetStatusActionConfig返回时表示不修改缺省 + TimeoutGap int // 以秒为单位的随机时间,0在GetStatusActionConfig返回时表示不修改缺省 +} + +type OrderInFoChange struct { +} + +func (s *StatusActionParams) GetRefTimeout(statusTime time.Time, orderCreatedAt time.Time) (timeout time.Duration) { + switch s.TimerType { + case TimerTypeBaseNow: + timeout = s.Timeout + case TimerTypeBaseStatusTime: + timeout = statusTime.Sub(time.Now()) + s.Timeout + case TimerTypeBaseOrderCreatedAt: + timeout = orderCreatedAt.Sub(time.Now()) + s.Timeout + default: + timeout = 0 + } + if timeout < 0 { + timeout = 0 + } + return timeout +} + +var ( + CancelWaybillReasonStrNotAcceptIntime = "没有及时抢单" + CancelWaybillReasonStrSwitch2SelfFailed = "转自送失败" + CancelWaybillReasonStrOrderAlreadyFinished = "订单已经结束" + CancelWaybillReasonStrActive = "操作由人员主动发起" + CancelWaybillReasonNotInStoreOpenTime = "不在门店的营业时间范围内" +) + +var ( + ErrCanNotFindItem = errors.New("没有找到指定的东西") + ErrStoreHaveNoCourier = errors.New("门店没有绑定相应的配送信息") +) + +var ( + CurOrderManager IOrderManager + CurStoreManager IStoreManager + + PurchasePlatformHandlers map[int]IPurchasePlatformHandler + PurchaseOrderHandlers map[int]IPurchasePlatformOrderHandler +) + +type IOrderManager interface { + SaveOrder(order *model.GoodsOrder, isAdjust bool, db *dao.DaoDB) (isDuplicated bool, err error) + + OnOrderNew(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error) + OnOrderAdjust(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error) + OnOrderStatusChanged(vendorOrgCode string, orderStatus *model.OrderStatus) (err error) + OnOrderMsg(order *model.GoodsOrder, vendorStatus, remark string) (err error) + + OnWaybillStatusChanged(bill *model.Waybill) (err error) + + CreateAfsOrderFromOrder(vendorOrderID string, vendorID int) (afsOrder *model.AfsOrder, err error) + LoadOrder(vendorOrderID string, vendorID int) (order *model.GoodsOrder, err error) + LoadOrder2(vendorOrderID2 string, vendorID int) (order *model.GoodsOrder, err error) + + LoadOrderFinancial(vendorOrderID string, vendorID int) (order *model.OrderFinancial, err error) + LoadOrderFinancial2(vendorOrderID2 string, vendorID int) (order *model.OrderFinancial, err error) + + UpdateOrderStatusAndDeliveryFlag(order *model.GoodsOrder) (err error) + UpdateOrderFields(order *model.GoodsOrder, fieldList []string) (err error) + // LoadStoreDetail(storeID, vendorID int) (storeDetail *dao.StoreDetail, err error) + + LoadWaybill(vendorWaybillID string, waybillVendorID int) (bill *model.Waybill, err error) + OnOrderComments(orderCommentList []*model.OrderComment) (err error) + + SaveOrderFinancialInfo(order *model.OrderFinancial, operation string) (err error) + SaveAfsOrderFinancialInfo(afsOrder *model.AfsOrder) (err error) + + GetOrderWaybillInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID int, isNotEnded, isGetPos bool) (bills []*model.WaybillExt, err error) + + ChangeOrderInfo(order *model.GoodsOrder) (err error) + // afs order + OnAfsOrderAdjust(afsOrder *model.AfsOrder, orderStatus *model.OrderStatus) (err error) + OnAfsOrderNew(afsOrder *model.AfsOrder, orderStatus *model.OrderStatus) (err error) + OnAfsOrderStatusChanged(orderStatus *model.OrderStatus) (err error) + LoadAfsOrder(vendorAfsOrderID string, vendorID int) (afsOrder *model.AfsOrder, err error) + UpdateAfsOrderFields(afsOrder *model.AfsOrder, fieldList []string) (err error) + + GetStatusDuplicatedCount(status *model.OrderStatus) (duplicatedCount int) +} + +type IStoreManager interface { + OnStoreStatusChanged(vendorStoreID string, vendorID int, storeStatus int) (err error) + OnCourierStoreStatusChanged(ctx *jxcontext.Context, vendorStoreID string, vendorID int, auditStatus int) (err error) +} + +// purchase handler中 +// 所有Sync,Refresh开头的函数都必须自己清理sync_status标记 +// 所有非以Sync,Refresh开头的函数不用自己清理sync_status标记(VendorSync统一处理) + +type IPurchasePlatformHandler interface { + IPurchasePlatformActHandler + IPurchasePlatformOrderHandler + + GetVendorID() int + + // 只与平台相关 + // GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) + + //////// + // Store + // ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string) (store *dao.StoreDetail, err error) + UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) + CreateStore2(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) + DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error) + GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) + UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string, storeID int64) (err error) + + RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) + + UploadImg(ctx *jxcontext.Context, vendorOrgCode, imgURL string, imgData []byte, imgName string, imgType int) (imgHint string, err error) +} + +// db *dao.DaoDB, +type IMultipleStoresHandler interface { + IPurchasePlatformHandler + GetAllCategories(ctx *jxcontext.Context, vendorOrgCode string) (cats []*BareCategoryInfo, err error) + + // CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) + // UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error + // DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error + // ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error) + + // CreateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error) + // UpdateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error) + DeleteCategory2(ctx *jxcontext.Context, vendorOrgCode, vendorCatID string) (err error) + ReorderCategories2(ctx *jxcontext.Context, vendorOrgCode, vendorParentCatID string, vendorCatIDList []string) (err error) + + // sku + // CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) + // UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) + // DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) + + // ReadSku(ctx *jxcontext.Context, vendorOrgCode, vendorSkuID string) (skuNameExt *model.SkuNameExt, err error) + // CreateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error) + // UpdateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error) + DeleteSku2(ctx *jxcontext.Context, vendorOrgCode string, sku *StoreSkuInfo) (err error) + + // RefreshAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) + + GetSkus(ctx *jxcontext.Context, vendorOrgCode string, skuID int, vendorSkuID string) (skuNameList []*SkuNameInfo, err error) +} + +type ISingleStoreHandler interface { + IPurchasePlatformHandler + ISingleStoreStoreSkuHandler + // SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) + + // RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error) +} + +type BasePurchasePlatform struct { +} + +func (p *BasePurchasePlatform) GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *StatusActionParams) { + return params +} + +func (c *BasePurchasePlatform) CanSwitch2SelfDeliver(order *model.GoodsOrder) (isCan bool, err error) { + return true, nil +} + +func init() { + PurchasePlatformHandlers = make(map[int]IPurchasePlatformHandler) + PurchaseOrderHandlers = make(map[int]IPurchasePlatformOrderHandler) + DeliveryPlatformHandlers = make(map[int]*DeliveryPlatformHandlerInfo) +} + +func InitOrderManager(curOrderManager IOrderManager) { + CurOrderManager = curOrderManager +} + +func InitStoreManager(curStoreManager IStoreManager) { + CurStoreManager = curStoreManager +} + +func RegisterPurchasePlatform(handler IPurchasePlatformHandler) { + vendorID := handler.GetVendorID() + if !(model.IsPurchaseVendorExist(vendorID)) { + panic(fmt.Sprintf("purchase vendor:%d is illegal", vendorID)) + } + if _, ok := PurchasePlatformHandlers[vendorID]; ok { + panic(fmt.Sprintf("purchase vendor:%d, already exists", vendorID)) + } + _, isSingleStore := handler.(ISingleStoreHandler) + _, isMultiStore := handler.(IMultipleStoresHandler) + if !isSingleStore && !isMultiStore { + panic(fmt.Sprintf("platform:%d type is wrong!", vendorID)) + } + PurchasePlatformHandlers[vendorID] = handler +} + +func RegisterPurchaseOrderHandler(vendorID int, handler IPurchasePlatformOrderHandler) { + PurchaseOrderHandlers[vendorID] = handler +} + +func GetPurchasePlatformFromVendorID(vendorID int) IPurchasePlatformHandler { + return PurchasePlatformHandlers[vendorID] +} + +func GetPurchaseOrderHandlerFromVendorID(vendorID int) (handler IPurchasePlatformOrderHandler) { + handler = PurchasePlatformHandlers[vendorID] + if handler == nil { + handler = PurchaseOrderHandlers[vendorID] + } + return handler +} + +func GetPurchasePlatformVendorIDs() (vendorIDs []int) { + for k := range PurchasePlatformHandlers { + vendorIDs = append(vendorIDs, k) + } + return vendorIDs +} + +func GetMultiStoreVendorIDs() (vendorIDs []int) { + for k, v := range PurchasePlatformHandlers { + if _, ok := v.(IMultipleStoresHandler); ok { + vendorIDs = append(vendorIDs, k) + } + } + return vendorIDs +} + +func GetSingleStoreVendorIDs() (vendorIDs []int) { + for k, v := range PurchasePlatformHandlers { + if _, ok := v.(ISingleStoreHandler); ok { + vendorIDs = append(vendorIDs, k) + } + } + return vendorIDs +} + +func IsMultiStore(vendorID int) bool { + if _, ok := GetPurchasePlatformFromVendorID(vendorID).(IMultipleStoresHandler); ok { + return true + } + return false +} + +func GetRidderPositionGetter(vendorID int) (handler IRidderPositionGetter) { + if handlerInfo := GetDeliveryPlatformFromVendorID(vendorID); handlerInfo != nil { + if handler, _ = handlerInfo.Handler.(IRidderPositionGetter); handler != nil { + return handler + } + } + handler, _ = GetPurchasePlatformFromVendorID(vendorID).(IRidderPositionGetter) + return handler +} + +func GetWaybillTipUpdater(vendorID int) (handler IAddWaybillTip) { + if handlerInfo := GetDeliveryPlatformFromVendorID(vendorID); handlerInfo != nil { + if handler, _ = handlerInfo.Handler.(IAddWaybillTip); handler != nil { + return handler + } + } + handler, _ = GetPurchasePlatformFromVendorID(vendorID).(IAddWaybillTip) + return handler +} diff --git a/business/partner/partner_act.go b/business/partner/partner_act.go new file mode 100644 index 000000000..e4db7ec86 --- /dev/null +++ b/business/partner/partner_act.go @@ -0,0 +1,130 @@ +package partner + +import ( + "time" + + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" +) + +type IActManager interface { + IsVendorActExist(ctx *jxcontext.Context, vendorActID string, vendorID int) (isExist bool) + CreateActFromVendor(ctx *jxcontext.Context, act2 *model.Act2, actStoreSku []*model.ActStoreSku2) (actID int, err error) +} + +type IPurchasePlatformActHandler interface { + // // 如果是单品级活动,actOrderRules为空 + // // 如果是订单级活动,actStoreSku可以为空(表示不限制SKU) + // CreateAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSku []*model.ActStoreSku2) (err error) + // UpdateAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSku []*model.ActStoreSku2) (err error) + // // 取消整个京西活动 + // CancelAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actStoreSku []*model.ActStoreSku2) (err error) + + SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) +} + +type IPurchasePlatformPageActHandler interface { + GetPageActList(ctx *jxcontext.Context, createdFrom time.Time) (actList []*model.Act2, err error) + GetPageActSkuList(ctx *jxcontext.Context, vendorPageActID string) (actStoreSkuList []*model.ActStoreSku2, err error) +} + +var ( + CurActManager IActManager +) + +func InitActManager(p IActManager) { + CurActManager = p +} + +func SplitActStoreSku(actStoreSkuList []*model.ActStoreSku2) (actStoreSkuMap map[int][]*model.ActStoreSku2) { + actStoreSkuMap = make(map[int][]*model.ActStoreSku2) + for _, v := range actStoreSkuList { + actStoreSkuMap[v.StoreID] = append(actStoreSkuMap[v.StoreID], v) + } + return actStoreSkuMap +} + +func SplitActStoreSku2List(actStoreSkuList []*model.ActStoreSku2) (actStoreSkuListList [][]*model.ActStoreSku2) { + actStoreSkuMap := SplitActStoreSku(actStoreSkuList) + for _, v := range actStoreSkuMap { + actStoreSkuListList = append(actStoreSkuListList, v) + } + return actStoreSkuListList +} + +func Act2ActMap(act *model.Act2) (actMap *model.ActMap) { + actMap = &model.ActMap{} + actMap.ID = act.MapID + return actMap +} + +func ActStoreSku2ActStoreSkuMap(actStoreSku *model.ActStoreSku2) (actStoreSkuMap *model.ActStoreSkuMap) { + actStoreSkuMap = &model.ActStoreSkuMap{ + ModelIDCULD: actStoreSku.ModelIDCULD, + BindID: actStoreSku.MapID, + + ActID: actStoreSku.ActID, + StoreID: actStoreSku.StoreID, + SkuID: actStoreSku.SkuID, + VendorID: actStoreSku.VendorID, + VendorActID: actStoreSku.VendorActID, + SyncStatus: actStoreSku.SyncStatus, + VendorPrice: actStoreSku.VendorPrice, + ActualActPrice: actStoreSku.ActualActPrice, + + EarningPrice: actStoreSku.EarningPrice, + } + actStoreSkuMap.ID = actStoreSku.MapID + return actStoreSkuMap +} + +func Act2Update(ctx *jxcontext.Context, act *model.Act2, syncStatus int) (item *dao.KVUpdateItem) { + kvs := map[string]interface{}{ + model.FieldSyncStatus: 0, + model.FieldUpdatedAt: time.Now(), + model.FieldLastOperator: ctx.GetUserName(), + } + if syncStatus == model.SyncFlagDeletedMask { + kvs[model.FieldDeletedAt] = time.Now() + } else if syncStatus == model.SyncFlagNewMask { + kvs[model.FieldVendorActID] = act.VendorActID + } + item = &dao.KVUpdateItem{ + Item: Act2ActMap(act), + KVs: kvs, + } + return item +} + +func ActStoreSku2Update(ctx *jxcontext.Context, actStoreSkuList []*model.ActStoreSku2, syncStatus int) (items []*dao.KVUpdateItem) { + for _, v := range actStoreSkuList { + v.SyncStatus = 0 + v.UpdatedAt = time.Now() + v.LastOperator = ctx.GetUserName() + kvs := map[string]interface{}{ + model.FieldSyncStatus: v.SyncStatus, + model.FieldUpdatedAt: v.UpdatedAt, + model.FieldLastOperator: v.LastOperator, + } + if syncStatus == model.SyncFlagDeletedMask { + v.DeletedAt = time.Now() + kvs[model.FieldDeletedAt] = v.DeletedAt + } else if syncStatus == model.SyncFlagNewMask { + kvs[model.FieldVendorActID] = v.VendorActID + } + items = append(items, &dao.KVUpdateItem{ + Item: ActStoreSku2ActStoreSkuMap(v), + KVs: kvs, + }) + } + return items +} + +func GetVendorIDsFromActMap(actMap map[int]*model.Act2) (vendorIDs []int) { + for vendorID := range actMap { + vendorIDs = append(vendorIDs, vendorID) + } + return vendorIDs +} diff --git a/business/partner/partner_api.go b/business/partner/partner_api.go new file mode 100644 index 000000000..386527933 --- /dev/null +++ b/business/partner/partner_api.go @@ -0,0 +1,14 @@ +package partner + +type IAPIManager interface { + GetAPI(vendorID int, appOrgCode string) interface{} + GetAppOrgCodeList(vendorID int) (appOrgCodeList []string) +} + +var ( + CurAPIManager IAPIManager +) + +func InitAPIManager(curAPIManager IAPIManager) { + CurAPIManager = curAPIManager +} diff --git a/business/partner/partner_delivery.go b/business/partner/partner_delivery.go new file mode 100644 index 000000000..00b8a12c3 --- /dev/null +++ b/business/partner/partner_delivery.go @@ -0,0 +1,78 @@ +package partner + +import ( + "fmt" + + "git.rosy.net.cn/jx-callback/business/model" +) + +const ( + WaybillFeeErrCodeCourierNotOpen = 1 //配送门店没有启用 + WaybillFeeErrCodeCourierNotSupported = 2 //配送门店不被系统支持 + WaybillFeeErrCodeCourierForbidden = 3 //配送门店内部禁用 + WaybillFeeErrCodeCourierOthers = 10 //其它错误 +) + +type WaybillFeeInfo struct { + ErrCode int `json:"errCode"` + ErrStr string `json:"errStr"` + RefDeliveryFee int64 `json:"refDeliveryFee"` // 无用,待删除 + RefAddFee int64 `json:"refAddFee"` // 无用,待删除 + DeliveryFee int64 `json:"deliveryFee"` + TimeoutSecond int `json:"timeoutSecond"` // 系统会自动发运单的倒计时 + Waybill *model.Waybill `json:"waybill"` +} + +type CreateWaybillPolicyFunc func(refDeliveryFee, refAddFee, deliveryFee int64) (errStr string) + +type IDeliveryPlatformHandler interface { + GetVendorID() int + + // CreateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (vendorStoreID string, status int, err error) + // GetStore(ctx *jxcontext.Context, storeID int, vendorStoreID string) (storeDetail *dao.StoreDetail2, err error) + IsErrStoreNotExist(err error) bool + IsErrStoreExist(err error) bool + + CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) + CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error) + GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *WaybillFeeInfo, err error) + //投诉骑手 + ComplaintRider(bill *model.Waybill, resonID int, resonContent string) (err error) +} + +type IDeliveryUpdateStoreHandler interface { + // UpdateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (err error) +} + +type DeliveryPlatformHandlerInfo struct { + Handler IDeliveryPlatformHandler + Use4CreateWaybill bool +} + +var ( + DeliveryPlatformHandlers map[int]*DeliveryPlatformHandlerInfo + UseableDeliveryVendorIDs []int +) + +func init() { + DeliveryPlatformHandlers = make(map[int]*DeliveryPlatformHandlerInfo) +} + +func RegisterDeliveryPlatform(handler IDeliveryPlatformHandler, isUse4CreateWaybill bool) { + vendorID := handler.GetVendorID() + if !(model.IsDeliveryVendorExist(vendorID)) { + panic(fmt.Sprintf("delivery vendor:%d is illegal", vendorID)) + } + if _, ok := DeliveryPlatformHandlers[vendorID]; ok { + panic(fmt.Sprintf("delivery vendor:%d, already exists", vendorID)) + } + DeliveryPlatformHandlers[vendorID] = &DeliveryPlatformHandlerInfo{ + Handler: handler, + Use4CreateWaybill: isUse4CreateWaybill, + } + UseableDeliveryVendorIDs = append(UseableDeliveryVendorIDs, vendorID) +} + +func GetDeliveryPlatformFromVendorID(vendorID int) *DeliveryPlatformHandlerInfo { + return DeliveryPlatformHandlers[vendorID] +} diff --git a/business/partner/partner_err.go b/business/partner/partner_err.go new file mode 100644 index 000000000..e4c1e6504 --- /dev/null +++ b/business/partner/partner_err.go @@ -0,0 +1,89 @@ +package partner + +import ( + "fmt" + + "git.rosy.net.cn/jx-callback/business/model" +) + +const ( + ErrCodeUnknown = 1 + ErrCodeChangePriceFailed = 100 +) + +type ErrorWithCode struct { + errMsg string + intCode int + vendorID int + storeID int + skuID int +} + +func NewErrorCode(errMsg string, code, vendorID int) *ErrorWithCode { + retVal := &ErrorWithCode{ + errMsg: errMsg, + intCode: code, + vendorID: vendorID, + } + return retVal +} + +func (e *ErrorWithCode) SetStoreID(storeID int) { + e.storeID = storeID +} + +func (e *ErrorWithCode) SetSkuID(skuID int) { + e.skuID = skuID +} + +func (e *ErrorWithCode) Error() string { + return fmt.Sprintf("平台:%s, code:%d, %s", model.VendorChineseNames[e.VendorID()], e.intCode, e.errMsg) +} + +func (e *ErrorWithCode) String() string { + return e.Error() +} + +func (e *ErrorWithCode) Code() int { + return e.intCode +} + +func (e *ErrorWithCode) ErrMsg() string { + return e.errMsg +} + +func (e *ErrorWithCode) VendorID() int { + return e.vendorID +} + +func (e *ErrorWithCode) StoreID() int { + return e.storeID +} + +func (e *ErrorWithCode) SkuID() int { + return e.skuID +} + +func IsErrChangePriceFailed(err error) *ErrorWithCode { + if vendorErr, ok := err.(*ErrorWithCode); ok && vendorErr.Code() == ErrCodeChangePriceFailed { + return vendorErr + } + return nil +} + +func IsErrVendorError(err error) *ErrorWithCode { + if vendorErr, ok := err.(*ErrorWithCode); ok { + return vendorErr + } + return nil +} + +func AddVendorInfo2Err(inErr error, vendorID int) (outErr error) { + outErr = inErr + if inErr != nil { + if IsErrVendorError(inErr) == nil { + outErr = NewErrorCode(inErr.Error(), ErrCodeUnknown, vendorID) + } + } + return outErr +} diff --git a/business/partner/partner_order.go b/business/partner/partner_order.go new file mode 100644 index 000000000..dace71dc7 --- /dev/null +++ b/business/partner/partner_order.go @@ -0,0 +1,67 @@ +package partner + +import ( + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/model" +) + +type OrderPhoneNumberInfo struct { + VendorOrderID string + PhoneNumber string +} + +type IPurchasePlatformOrderHandler interface { + Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) + GetOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, err error) + GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) + GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *StatusActionParams) + + AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) + PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) + + AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) + CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) // 取货失败后再次招唤平台配送 + ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) // 投递失败后确认收到退货 + + // 是否可能转商家自送 + CanSwitch2SelfDeliver(order *model.GoodsOrder) (isCan bool, err error) + // 将订单从购物平台配送转为自送 + Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) + + // 将订单从购物平台配送转为自送后又送达 + Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) + + // 完全自送的门店表示开始配送 + SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) + + // 完全自送的门店表示配送完成 + SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) + + GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) + + ReplyOrderComment(ctx *jxcontext.Context, vendorOrgCode string, orderComment *model.OrderComment, replyComment string) (err error) + + AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) + CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) + // order.Skus要包含原始订单中的Sku信息,removedSkuList中是要移除的Sku信息 + AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) + + // 售后 + // 发起全款退款 + RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) + // 发起部分退款 + PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) + // 审核售后单申请 + AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) + // // 确认收到退货 + ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) +} + +type IAddWaybillTip interface { + GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error) + UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error) +} + +type IRidderPositionGetter interface { + GetRidderPosition(ctx *jxcontext.Context, vendorOrgCode, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (lng, lat float64, err error) +} diff --git a/business/partner/partner_printer.go b/business/partner/partner_printer.go new file mode 100644 index 000000000..0e23fa507 --- /dev/null +++ b/business/partner/partner_printer.go @@ -0,0 +1,89 @@ +package partner + +import ( + "fmt" + + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/model" +) + +const ( + PrinterStatusUnknown = 0 + PrinterStatusOffline = 1 + PrinterStatusOnlineOK = 2 + PrinterStatusOnlineAbnormal = 3 +) + +const ( + PrintResultSuccess = 0 // 成功 + PrintResultNoPrinter = 1 // 没有配置网络打印机 +) + +const ( + PrinterFontSizeNormal = int8(0) //正常大小 + PrinterFontSizeBig = int8(1) //两倍大小 +) + +var ( + PrinterStatusName = map[int]string{ + PrinterStatusUnknown: "未知", + PrinterStatusOffline: "离线", + PrinterStatusOnlineOK: "正常", + PrinterStatusOnlineAbnormal: "异常", + } +) + +type PrinterStatus struct { + PrintResult int `json:"printResult"` + PrinterStatus int `json:"printerStatus"` + Printed int `json:"printed"` // 已经打印的单数 + Waiting int `json:"waiting"` // 等待打印的单数,超过1一般不太正常 +} + +type BindPrinterResult struct { + PrinterSN string `json:"printerSN"` + PrinterKey string `json:"printerKey"` + PrinterKey2 string `json:"printerKey2"` + ExpiresAt int64 `json:"expiresAt"` +} + +type IPrinterHandler interface { + GetVendorID() int + PrintMsg(ctx *jxcontext.Context, id1, id2, msgTitle, msgContent string) (printerStatus *PrinterStatus, err error) + GetPrinterStatus(ctx *jxcontext.Context, id1, id2 string) (printerStatus *PrinterStatus, err error) + + RegisterPrinter(ctx *jxcontext.Context, id1, id2, printerName string) (newID1, newID2 string, err error) + UnregisterPrinter(ctx *jxcontext.Context, id1, id2 string) (err error) + + BindPrinter(ctx *jxcontext.Context, mapData map[string]interface{}) (bindResult *BindPrinterResult, err error) + RebindPrinter(ctx *jxcontext.Context, lastBindResult *BindPrinterResult) (bindResult *BindPrinterResult, err error) + + // PrintOrder(ctx *jxcontext.Context, store *model.Store, order *model.GoodsOrder) (printerStatus *PrinterStatus, err error) + + EmptyPrintList(ctx *jxcontext.Context, id1, id2 string) (err error) + PlayText(ctx *jxcontext.Context, id1, id2, orderID, text string) (printerStatus *PrinterStatus, err error) + SetSound(ctx *jxcontext.Context, id1, id2, sound string) (err error) +} + +var ( + PrinterPlatformHandlers map[int]IPrinterHandler +) + +func init() { + PrinterPlatformHandlers = make(map[int]IPrinterHandler) +} + +func RegisterPrinterPlatform(handler IPrinterHandler) { + vendorID := handler.GetVendorID() + if !(model.IsPrinterVendorExist(vendorID)) { + panic(fmt.Sprintf("printer vendor:%d is illegal", vendorID)) + } + if _, ok := PrinterPlatformHandlers[vendorID]; ok { + panic(fmt.Sprintf("printer vendor:%d, already exists", vendorID)) + } + PrinterPlatformHandlers[vendorID] = handler +} + +func GetPrinterPlatformFromVendorID(vendorID int) IPrinterHandler { + return PrinterPlatformHandlers[vendorID] +} diff --git a/business/partner/partner_store.go b/business/partner/partner_store.go new file mode 100644 index 000000000..a83ac4c24 --- /dev/null +++ b/business/partner/partner_store.go @@ -0,0 +1,19 @@ +package partner + +import ( + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" +) + +type IStoreHandler interface { + GetAllStoresVendorID(ctx *jxcontext.Context, vendorOrgCode string) (vendorStoreIDs []string, err error) + + EnableAutoAcceptOrder(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, isSetEnable bool) (err error) + UpdateStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, status int) (err error) + // opTime格式为整数1130代表11:30 + UpdateStoreOpTime(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, opTimeList []int16) (err error) +} + +// 同步资质信息至平台 +type IStoreSyncQualifyHandler interface { + // SyncQualify(ctx *jxcontext.Context, storeDetail *dao.StoreDetail) (err error) +} diff --git a/business/partner/partner_store_sku.go b/business/partner/partner_store_sku.go new file mode 100644 index 000000000..b59ad933a --- /dev/null +++ b/business/partner/partner_store_sku.go @@ -0,0 +1,203 @@ +package partner + +import ( + "math" + "regexp" + "time" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/jx-callback/business/model/dao" +) + +const ( + // FuncGetStoreSkusBareInfo = 1 // 此接口要求实现为不限制批处理大小的 + FuncUpdateStoreSkusStock = 2 + FuncUpdateStoreSkusStatus = 3 + FuncUpdateStoreSkusPrice = 4 + + FuncGetStoreSkusFullInfo = 6 + FuncCreateStoreSkus = 7 + FuncUpdateStoreSkus = 8 + FuncDeleteStoreSkus = 9 + + FuncCreateActs = 10 + FuncCancelActs = 11 +) + +const ( + UnlimitedBatchSize = math.MaxInt32 + + // MaxStoreSkuStock = model.MaxStoreSkuStockQty + UnlimitedStoreSkuStock = -1 +) + +type StoreSkuInfo struct { + SkuID int `json:"skuID,omitempty"` + VendorSkuID string `json:"vendorSkuID,omitempty"` + NameID int `json:"nameID,omitempty"` + VendorNameID string `json:"vendorNameID,omitempty"` + + Stock int `json:"stock,omitempty"` + VendorPrice int64 `json:"price,omitempty"` + Status int `json:"status,omitempty"` + + Seq int `json:"seq,omitempty"` + + ActPrice int64 `json:"actPrice,omitempty"` + VendorActID string `json:"vendorActID,omitempty"` + IsSpecialty int `json:"isSpecialty,omitempty"` + JxPrice int64 `json:"jxPrice,omitempty"` + JxUnitPrice int64 `json:"jxUnitPrice,omitempty"` + VendorSkuID2 string `json:"vendorSkuID2,omitempty"` + JdsStockSwitch int `json:"jdsStockSwitch"` + IsDeletedBySku bool `json:"isDeletedBySku"` +} + +type StoreSkuInfoWithErr struct { + StoreSkuInfo *StoreSkuInfo + CategoryName string + VendoreID int + VendoreName string + StoreID int + SyncType string + ErrMsg string +} + +type SkuInfo struct { + StoreSkuInfo + SkuName string + Comment string + SpecQuality float64 + SpecUnit string + Weight int + ActPrice int64 +} + +type SkuNameInfo struct { + NameID int `json:"nameID,omitempty"` + VendorNameID string `json:"vendorNameID,omitempty"` + + Prefix string + Name string + Description string + Unit string + VendorCatIDList []string + PictureList []string + Status int `json:"status,omitempty"` + YbBarCode string + SkuList []*SkuInfo +} + +type BareStoreSkuInfoList []*StoreSkuInfo + +func (l BareStoreSkuInfoList) GetVendorSkuIDList() (vendorSkuIDList []string) { + for _, v := range l { + if !dao.IsVendorThingIDEmpty(v.VendorSkuID) { + vendorSkuIDList = append(vendorSkuIDList, v.VendorSkuID) + } + } + return vendorSkuIDList +} + +func (l BareStoreSkuInfoList) GetVendorSkuIDIntList() (vendorSkuIDIntList []int64) { + for _, v := range l { + if !dao.IsVendorThingIDEmpty(v.VendorSkuID) { + vendorSkuIDIntList = append(vendorSkuIDIntList, utils.Str2Int64(v.VendorSkuID)) + } + } + return vendorSkuIDIntList +} + +func (l BareStoreSkuInfoList) GetSkuIDList() (skuIDList []int) { + for k, v := range l { + if v.SkuID > 0 { + skuIDList[k] = v.SkuID + } + } + return skuIDList +} + +func (l BareStoreSkuInfoList) Len() int { + return len(l) +} + +func (l BareStoreSkuInfoList) Less(i, j int) bool { + if l[i].Seq != l[j].Seq { + return l[i].Seq < l[j].Seq + } + return l[i].VendorPrice < l[j].VendorPrice +} + +func (l BareStoreSkuInfoList) Swap(i, j int) { + l[i], l[j] = l[j], l[i] +} + +type BareCategoryInfo struct { + VendorCatID string `json:"vendorCatID"` + + Level int `json:"level"` + Name string `json:"name"` + Seq int `json:"seq,omitempty"` + Children []*BareCategoryInfo `json:"children,omitempty"` +} + +// 批处理函数,如果是部分失败的情况会返回失败,successedList中会返回成功的列表 + +type IPurchasePlatformStoreSkuHandler interface { + GetStoreSkusBatchSize(funcID int) int + + ListOrders(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, queryDate time.Time, vendorStoreID string) (vendorOrderIDs []string, err error) + + // 此接口要求实现为不限制批处理大小的 + GetStoreSkusBareInfo(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*StoreSkuInfo) (outStoreSkuList []*StoreSkuInfo, err error) + UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (failedList []*StoreSkuInfoWithErr, err error) + UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo, status int) (failedList []*StoreSkuInfoWithErr, err error) + UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (failedList []*StoreSkuInfoWithErr, err error) + + CreateStoreSkusAct(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (failedList []*StoreSkuInfoWithErr, err error) + CancelActs(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (failedList []*StoreSkuInfoWithErr, err error) + UpdateStoreSkusSpecTag(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (err error) +} + +type ISingleStoreStoreSkuHandler interface { + IPurchasePlatformStoreSkuHandler + + GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (outSkuNameList []*SkuNameInfo, err error) + // CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*StoreSkuInfoWithErr, err error) + // UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*StoreSkuInfoWithErr, err error) + DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (failedList []*StoreSkuInfoWithErr, err error) + DeleteStoreAllSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, isContinueWhenError bool) (err error) + IsErrSkuExist(err error) (isExist bool) + IsErrSkuNotExist(err error) (isNotExist bool) + + GetStoreAllCategories(ctx *jxcontext.Context, storeID int, vendorStoreID string) (cats []*BareCategoryInfo, err error) + GetStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, catName string) (cat *BareCategoryInfo, err error) + // CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) + // UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) + DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) + DeleteStoreAllCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, isContinueWhenError bool) (err error) + + IsErrCategoryExist(err error) (isExist bool) + IsErrCategoryNotExist(err error) (isNotExist bool) + + GetSensitiveWordRegexp() *regexp.Regexp +} + +type IStoreSkuSorter interface { + ReorderStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, vendorCatID string, storeSkuList []*StoreSkuInfo) (err error) +} + +func BuildSkuName(skuID int, vendorSkuID string) (skuName *SkuNameInfo) { + return &SkuNameInfo{ + SkuList: []*SkuInfo{ + &SkuInfo{ + StoreSkuInfo: StoreSkuInfo{ + SkuID: skuID, + VendorSkuID: vendorSkuID, + }, + }, + }, + } +} diff --git a/business/partner/pay/pay.go b/business/partner/pay/pay.go new file mode 100644 index 000000000..246d86afa --- /dev/null +++ b/business/partner/pay/pay.go @@ -0,0 +1,51 @@ +package pay + +import ( + "time" + + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" +) + +type PayOpStatus int + +const ( + OpStatusFailed PayOpStatus = 0 + OpStatusSuccessed PayOpStatus = 1 +) + +type CreatePayParam struct { + PayOrderID string + VendorPayType string + + VendorOrderID string + ProductDesc string + ProductDetail string + FeeType string + TotalFee int + TimeStart time.Time + TimeExpire time.Time + + UserData string +} + +type PayOpResult struct { + Status PayOpStatus + VendorStatus string + ErrMsg string + + ID string + VendorID string + + OriginalData string +} + +type ResponseHandler interface { + OnCreatePay(vendorID int, result *PayOpResult) (err error) + OnRefundPay(vendorID int, result *PayOpResult) (err error) +} + +type IPayPlatformHandler interface { + CreatePay(ctx *jxcontext.Context, param *CreatePayParam, isOffline bool) (prepayID, qrCodeURL string, err error) + ClosePay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID string) (err error) + RefundPay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID, refundID, reason string, totalFee, refundFee int) (vendorRefundID string, err error) +} diff --git a/business/partner/pay/wxpay/callback.go b/business/partner/pay/wxpay/callback.go new file mode 100644 index 000000000..e76447652 --- /dev/null +++ b/business/partner/pay/wxpay/callback.go @@ -0,0 +1,60 @@ +package wxpay + +import ( + "git.rosy.net.cn/baseapi/platformapi/wxpayapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner/pay" + "git.rosy.net.cn/jx-callback/globals" +) + +func OnCallback(msg *wxpayapi.CallbackMsg) (err error) { + globals.SugarLogger.Debugf("wxpay OnCallback msg:%s", utils.Format4Output(msg, true)) + switch msg.MsgType { + case wxpayapi.MsgTypePay: + err = onWxpayFinished(msg.Data.(*wxpayapi.PayResultMsg)) + case wxpayapi.MsgTypeRefund: + err = onWxpayRefund(msg.Data.(*wxpayapi.RefundResultMsg)) + } + return err +} + +func onWxpayFinished(msg *wxpayapi.PayResultMsg) (err error) { + opResult := &pay.PayOpResult{ + OriginalData: string(utils.MustMarshal(msg)), + } + if msg.ReturnCode == wxpayapi.ResponseCodeSuccess { + opResult.Status = pay.OpStatusSuccessed + opResult.ID = msg.OutTradeNo + if msg.ResultCode == wxpayapi.ResponseCodeSuccess { + opResult.VendorID = msg.TransactionID + } else { + opResult.VendorStatus = msg.ErrCode + opResult.ErrMsg = msg.ErrCodeDes + } + } else { + opResult.Status = pay.OpStatusFailed + } + err = payHandler.responseHandler.OnCreatePay(model.VendorIDWXPay, opResult) + return err +} + +func onWxpayRefund(msg *wxpayapi.RefundResultMsg) (err error) { + opResult := &pay.PayOpResult{ + OriginalData: string(utils.MustMarshal(msg)), + } + if msg.ReturnCode == wxpayapi.ResponseCodeSuccess { + opResult.Status = pay.OpStatusSuccessed + if msg.ResultCode == wxpayapi.ResponseCodeSuccess { + opResult.ID = msg.ReqInfoObj.OutRefundNo + opResult.VendorID = msg.ReqInfoObj.RefundID + } else { + opResult.VendorStatus = msg.ErrCode + opResult.ErrMsg = msg.ErrCodeDes + } + } else { + opResult.Status = pay.OpStatusFailed + } + err = payHandler.responseHandler.OnRefundPay(model.VendorIDWXPay, opResult) + return err +} diff --git a/business/partner/pay/wxpay/wxpay.go b/business/partner/pay/wxpay/wxpay.go new file mode 100644 index 000000000..b0f1d767a --- /dev/null +++ b/business/partner/pay/wxpay/wxpay.go @@ -0,0 +1,74 @@ +package wxpay + +import ( + "git.rosy.net.cn/baseapi/platformapi/wxpayapi" + "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/partner/pay" + "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/globals/api" +) + +type PayHandler struct { + responseHandler pay.ResponseHandler +} + +var ( + payHandler *PayHandler +) + +func New(responseHandler pay.ResponseHandler) (handler *PayHandler) { + return &PayHandler{ + responseHandler: responseHandler, + } +} + +func vendorPayType2WxpayType(vendorPayType string) string { + return vendorPayType +} + +func (p *PayHandler) CreatePay(ctx *jxcontext.Context, createParam *pay.CreatePayParam, isOffline bool) (prepayID, qrCodeURL string, err error) { + param := &wxpayapi.CreateOrderParam{ + OutTradeNo: createParam.PayOrderID, + Body: createParam.ProductDesc, + NotifyURL: globals.WxpayNotifyURL, + SpbillCreateIP: ctx.GetRealRemoteIP(), + TradeType: vendorPayType2WxpayType(createParam.VendorPayType), + TotalFee: createParam.TotalFee, + + TimeStart: wxpayapi.Time2PayTime(createParam.TimeStart), + TimeExpire: wxpayapi.Time2PayTime(createParam.TimeExpire), + ProfitSharing: wxpayapi.OptYes, + } + if isOffline { + param.TradeType = wxpayapi.TradeTypeNative + } + if authInfo, err := ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini { + param.OpenID = authInfo.GetAuthID() + } + if result, err := api.WxpayAPI.CreateUnifiedOrder(param); err == nil { + prepayID = result.PrepayID + qrCodeURL = result.CodeURL + } + return prepayID, qrCodeURL, err +} + +func (p *PayHandler) ClosePay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID string) (err error) { + return api.WxpayAPI.CloseOrder(payOrderID) +} + +func (p *PayHandler) RefundPay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID, refundID, reason string, totalFee, refundFee int) (vendorRefundID string, err error) { + param := &wxpayapi.PayRefundParam{ + OutTradeNo: payOrderID, + NotifyURL: globals.WxpayNotifyURL, + OutRefundNo: refundID, + TotalFee: totalFee, + RefundFee: refundFee, + RefundDesc: wxpayapi.CData(reason), + } + retVal, err := api.WxpayAPI.PayRefund(param) + if err == nil { + vendorRefundID = retVal.RefundID + } + return vendorRefundID, err +} diff --git a/business/partner/purchase/jx/act.go b/business/partner/purchase/jx/act.go new file mode 100644 index 000000000..6894b5b4a --- /dev/null +++ b/business/partner/purchase/jx/act.go @@ -0,0 +1,11 @@ +package jx + +import ( + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/jx-callback/business/model" +) + +func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) { + return err +} diff --git a/business/partner/purchase/jx/jx.go b/business/partner/purchase/jx/jx.go new file mode 100644 index 000000000..24dc7beeb --- /dev/null +++ b/business/partner/purchase/jx/jx.go @@ -0,0 +1,34 @@ +package jx + +import ( + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals" +) + +type PurchaseHandler struct { + partner.BasePurchasePlatform +} + +var ( + CurPurchaseHandler *PurchaseHandler +) + +func init() { + globals.SugarLogger.Debug("init jx") + if true { + CurPurchaseHandler = new(PurchaseHandler) + // 不能注册京西 + // partner.RegisterPurchasePlatform(CurPurchaseHandler) + partner.RegisterPurchaseOrderHandler(CurPurchaseHandler.GetVendorID(), CurPurchaseHandler) + } +} + +func (c *PurchaseHandler) GetVendorID() int { + return model.VendorIDJX +} + +func (p *PurchaseHandler) UploadImg(ctx *jxcontext.Context, vendorOrgCode, imgURL string, imgData []byte, imgName string, imgType int) (imgHint string, err error) { + return imgHint, err +} diff --git a/business/partner/purchase/jx/localjx/order.go b/business/partner/purchase/jx/localjx/order.go new file mode 100644 index 000000000..d4345a68e --- /dev/null +++ b/business/partner/purchase/jx/localjx/order.go @@ -0,0 +1,740 @@ +package localjx + +import ( + "fmt" + "math" + "regexp" + "time" + + "git.rosy.net.cn/baseapi/platformapi/jdshopapi" + + "git.rosy.net.cn/baseapi/platformapi/wxpayapi" + + "git.rosy.net.cn/jx-callback/globals/api" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/business/partner" +) + +const ( + OrderCreateTypePre = 0 // 预创建 + OrderCreateTypeNormal = 1 // 正常创建 + + PayWaitingTime = 10 * time.Minute // 等待支付的最长时间 + DingShiDaMinTime = 1 * time.Hour + + specialStoreID = 100274 + specialFreightPrice = 1500 + + wxAppID = "wx4b5930c13f8b1170" + + autoCancelOrderReason = "支付超时,系统自动取消!" + cancelMatterOrderReason = "失败重发!" + settleDiscountActRefundReason = "守价订单生成补退款" + + splitMatterOrderMinWeight = 4500 //物料订单分包最少要4.5kg + jxwxfMatterEclpID = "EMG4418113943423" //京西五香粉物料编码 +) + +type JxSkuInfo struct { + SkuID int `json:"skuID"` + Count int `json:"count"` + + Price int64 `json:"price,omitempty"` // 原价 + SalePrice int64 `json:"salePrice,omitempty"` // 售卖价 + + Name string `json:"name"` + Weight int `json:"weight"` + GroupSign bool `json:"groupSign"` + + DefendPrice int64 `json:"defendPrice"` //守价 +} + +type JxSkuInfo2 struct { + SkuID int `json:"skuID"` + Count int `json:"count"` + + Price int64 `json:"price,omitempty"` // 原价 + SalePrice int64 `json:"salePrice,omitempty"` // 售卖价 + + Name string `json:"name"` + Weight int `json:"weight"` + GroupSign bool `json:"groupSign"` +} + +type JxSkuInfoList []*JxSkuInfo + +func (l JxSkuInfoList) Len() int { + return len(l) +} + +func (l JxSkuInfoList) Less(i, j int) bool { + if l[i].SkuID == l[j].SkuID { + return l[i].SalePrice < l[j].SalePrice + } + return l[i].SkuID < l[j].SkuID +} + +func (l JxSkuInfoList) Swap(i, j int) { + l[i], l[j] = l[j], l[i] +} + +type JxOrderInfo struct { + BuyerComment string `json:"buyerComment"` + StoreID int `json:"storeID"` + Skus []*JxSkuInfo `json:"skus"` + + ExpectedDeliveredTimestamp int64 `json:"expectedDeliveredTimestamp"` // 预期送达时间 + + TotalPrice int64 `json:"totalPrice"` // 单位为分 订单总价 + FreightPrice int64 `json:"freightPrice"` // 单位为分 订单配送费 + OrderPrice int64 `json:"orderPrice"` // 单位为分 订单商品价格 + ActualPayPrice int64 `json:"actualPayPrice"` // 单位为分 顾客实际支付 + + OrderID int64 `json:"orderID"` + StoreName string `json:"storeName"` + Weight int `json:"weight"` + FromStoreID int `json:"fromStoreID"` + EarningType int `json:"earningType"` + OrderType int `json:"orderType"` + IsBuyNowPrice int `json:"isBuyNowPrice"` + IsPriceDefend int `json:"isPriceDefend"` + OrderID2 string `json:"-"` + UserID string `json:"userID"` +} + +type DeliveryTimeItem struct { + ViewTime string `json:"viewTime"` + UnixTime int64 `json:"unixTime"` + ViewShippingFee string `json:"viewShippingFee"` +} + +type DeliveryDayTimeInfo struct { + Date string `json:"date"` + TimeList []*DeliveryTimeItem `json:"timeList"` +} + +type MatterOrderStatus struct { + Time time.Time `json:"time"` + Status string `json:"status"` + Name string `json:"name"` + Sign int `sign` +} + +var ( + weekdayMap = map[int]string{ + 1: "一", + 2: "二", + 3: "三", + 4: "四", + 5: "五", + 6: "六", + 0: "日", + } + dayList = []string{"今天", "明天", "后天"} + + bagMap = map[int]int{ + 6039382: 100, + 6039383: 200, + 6039384: 200, + 6039387: 200, + 6039390: 200, + } + + regexpCnameAndCmobile = regexp.MustCompile(`配送员,(.*),手机号,(.*)`) + regexpCnameAndCmobile2 = regexp.MustCompile(`(快递员:(.*),联系电话:(.*))`) + + bagSkuMap = map[int]int{ //京西物料袋子skuid + 6039382: 6039382, + 6039383: 6039383, + 6039384: 6039384, + 6039387: 6039387, + 6039390: 6039390, + } +) + +func init() { +} + +func buildDefendPriceOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64) (vendorOrderID string) { + var ( + issue = 0 + db = dao.GetDB() + ) + issue = jxutils.GetDefendPriceIssue() + priceDefendOrder := &model.PriceDefendOrder{ + VendorOrderID: utils.Int64ToStr(jxutils.GenOrderNo()), + StoreID: jxOrder.StoreID, + SkuID: jxOrder.Skus[0].SkuID, + AddressID: addressID, + Count: jxOrder.Skus[0].Count, + DefendPrice: jxOrder.Skus[0].DefendPrice, + OriginPrice: jxOrder.Skus[0].Price, + IsBuyNowPrice: jxOrder.IsBuyNowPrice, + Issue: issue, + IsSuccess: model.NO, //默认是不成功 + IsPay: model.NO, + } + dao.WrapAddIDCULDEntity(priceDefendOrder, ctx.GetUserName()) + priceDefendOrder.ActualPayPrice = int64(priceDefendOrder.Count)*jxOrder.Skus[0].Price + jxOrder.FreightPrice + dao.CreateEntity(db, priceDefendOrder) + return priceDefendOrder.VendorOrderID +} + +// 买家取消(或申请取消)订单 +func BuyerCancelOrder(ctx *jxcontext.Context, orderID int64, reason string) (canceled bool, err error) { + order, err := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(orderID), model.VendorIDJX) + if err == nil { + if order.Status < model.OrderStatusNew { + order.Status = model.OrderStatusCanceled + order.VendorStatus = utils.Int2Str(model.OrderStatusCanceled) + if err = partner.CurOrderManager.UpdateOrderFields(order, []string{model.FieldStatus, "VendorStatus"}); err == nil { + canceled = true + } + } else { + err = fmt.Errorf("暂不支持自行取消订单,请联系商家取消") + // err = changeOrderStatus(utils.Int64ToStr(orderID), model.OrderStatusApplyCancel, fmt.Sprintf("用户%s主动取消", ctx.GetUserName())) + } + } + return canceled, err +} + +func Pay4Order(ctx *jxcontext.Context, orderID int64, payType int, vendorPayType string) (orderPay *model.OrderPay, err error) { + order, err := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(orderID), model.VendorIDJX) + if err == nil { + switch payType { + case model.PayTypeWX: + if orderPay, err = pay4OrderByWX(ctx, order, vendorPayType); err == nil { + dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName()) + err = dao.CreateEntity(dao.GetDB(), orderPay) + } + case model.PayTypeTL: + if orderPay, err = pay4OrderByTL(ctx, order, payType, vendorPayType); err == nil && orderPay != nil { + dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName()) + err = dao.CreateEntity(dao.GetDB(), orderPay) + } + default: + err = fmt.Errorf("支付方式:%d当前不支持", payType) + } + } else { + // priceDefendOrders, _ := dao.GetPriceDefendOrder(db, utils.Int64ToStr(orderID), nil, nil, []int{jxutils.GetDefendPriceIssue()}, 0, -1, -1, 0, "", utils.ZeroTimeValue, utils.ZeroTimeValue, false) + // if len(priceDefendOrders) == 0 { + // err = fmt.Errorf("未查询到待支付订单!order_id: %v", orderID) + // } + // order2 := &model.GoodsOrder{ + // VendorOrderID: priceDefendOrders[0].VendorOrderID, + // ActualPayPrice: priceDefendOrders[0].ActualPayPrice, + // VendorID: model.VendorIDJX, + // } + // if orderPay, err = pay4OrderByTL(ctx, order2, payType, vendorPayType); err == nil && orderPay != nil { + // dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName()) + // err = dao.CreateEntity(dao.GetDB(), orderPay) + // } + } + return orderPay, err +} + +func Pay4User(ctx *jxcontext.Context, thingID, payType int, vendorPayType string) (orderPay *model.OrderPay, err error) { + var ( + db = dao.GetDB() + order *model.GoodsOrder + dicountCards []*model.DiscountCard + vendorOrderID string + ) + switch payType { + case model.PayTypeTL_DiscountCard: + if configList, err := dao.QueryConfigs(db, "会员折扣卡", model.ConfigTypeDiscountCard, ""); err == nil { + jxutils.Strings2Objs(configList[0].Value, &dicountCards) + if err != nil { + return nil, err + } + discountCard := findDiscountCard(dicountCards, thingID) + // flag, userMemberOrigin, err := checkMember(db, ctx.GetUserID(), discountCard) + if err != nil { + return nil, err + } + vendorOrderID = utils.Int64ToStr(jxutils.GenOrderNo()) + order = &model.GoodsOrder{ + VendorOrderID: vendorOrderID, + ActualPayPrice: int64(discountCard.Price), + VendorID: model.VendorIDJX, + } + if orderPay, err = pay4OrderByTL(ctx, order, payType, vendorPayType); err == nil && orderPay != nil { + dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName()) + err = dao.CreateEntity(dao.GetDB(), orderPay) + } + // userMember := &model.UserMember{ + // VendorOrderID: vendorOrderID, + // UserID: ctx.GetUserID(), + // MemberType: model.MemberTypeDiscountCard, + // EndAt: utils.Str2Time(time.Now().AddDate(0, 1, 0).AddDate(0, 0, -1).Format("2006-01-02") + " 23:59:59"), + // MemberTypeID: thingID, + // IsPay: model.NO, + // } + // dao.WrapAddIDCULDEntity(userMember, ctx.GetUserName()) + // if flag == 0 { + // dao.CreateEntity(db, userMember) + // } else if flag == 1 { + // userMemberOrigin.EndAt = userMemberOrigin.EndAt.AddDate(0, 1, 0) + // dao.UpdateEntity(db, userMemberOrigin, "EndAt") + // } + } + default: + err = fmt.Errorf("支付方式:%d当前不支持", payType) + } + return orderPay, err +} + +//flag +//0 正常购买 +//1 续费 +//-1 不能购买 +func checkMember(db *dao.DaoDB, userID string, discountCard *model.DiscountCard) (flag int, userMember *model.UserMember, err error) { + // userMembers, err := dao.GetUserMember(db, userID, "", model.MemberTypeDiscountCard, model.YES) + // if len(userMembers) > 0 { + // userMember = userMembers[0] + // if userMember.ID < discountCard.ID { + // return 0, userMember, err + // } else if userMember.ID == discountCard.ID { + // return 1, userMember, err + // } else { + // return -1, userMember, fmt.Errorf("已购买更高档次的会员,无法继续购买!") + // } + // } + return 0, userMember, err +} + +func time2ShortTimeStr(t time.Time) string { + return t.Format("15:04") +} + +func findDiscountCard(dicountCards []*model.DiscountCard, thingID int) (dicountCard *model.DiscountCard) { + for _, v := range dicountCards { + if v.ID == thingID { + return v + } + } + return dicountCard +} + +func OnPayFinished(orderPay *model.OrderPay) (err error) { + order, err := partner.CurOrderManager.LoadOrder(orderPay.VendorOrderID, orderPay.VendorID) + if err == nil { + db := dao.GetDB() + dao.UpdateEntity(db, orderPay) + // if count, err2 := dao.GetJxOrderCount(db, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, order.OrderCreatedAt); err2 == nil { + // order.OrderSeq = count + 1 + // partner.CurOrderManager.UpdateOrderFields(order, []string{"OrderSeq"}) + // } + order.Status = model.OrderStatusNew + order.VendorStatus = utils.Int2Str(model.OrderStatusNew) + order.StatusTime = *orderPay.PayFinishedAt + err = callNewOrder(order) + //如果是物料的订单,直接到拣货完成,配送中的状态 + if order.OrderType != model.OrderTypeNormal { + // if order.FromStoreID != 0 { + if order.OrderType != model.OrderTypeDefendPrice { + // netprinter.PrintOrderByOrder(jxcontext.AdminCtx, order) + } + // PickupGoods(order, false, "jxadmin") + // } + } + } else { + switch orderPay.PayType { + case model.PayTypeTL_DiscountCard: + // userMembers, _ := dao.GetUserMember(dao.GetDB(), "", orderPay.VendorOrderID, model.MemberTypeDiscountCard, model.NO) + // if len(userMembers) > 0 { + // userMembers[0].IsPay = model.YES + // dao.UpdateEntity(dao.GetDB(), userMembers[0], "IsPay") + // err = nil + // } + default: + + } + } + return err +} + +func GenPayOrderID(order *model.GoodsOrder) (payOrderID int64) { + return utils.Str2Int64(order.VendorOrderID) +} + +func GenRefundID(order *model.GoodsOrder) (refundID int64) { + const suffix = 100000 + refundID = utils.Str2Int64(order.VendorOrderID) * suffix + refundID += int64(time.Now().Sub(order.OrderFinishedAt) / time.Minute) + return refundID +} + +func formalizeSkus(skus []*JxSkuInfo) (outSkus []*JxSkuInfo) { + skuMap := make(map[int]int) + for _, v := range skus { + skuMap[v.SkuID] += v.Count + } + for skuID, skuCount := range skuMap { + outSkus = append(outSkus, &JxSkuInfo{ + SkuID: skuID, + Count: skuCount, + }) + } + return outSkus +} + +func isTimeInOpTime(openTime1, closeTime1, openTime2, closeTime2 int16, time2Check time.Time) bool { + timeStrList := []string{ + jxutils.OperationTime2StrWithSecond(openTime1), + jxutils.OperationTime2StrWithSecond(closeTime1), + } + if openTime1 > 0 { + timeStrList = append(timeStrList, + jxutils.OperationTime2StrWithSecond(openTime2), + jxutils.OperationTime2StrWithSecond(closeTime2), + ) + } + checkTimeStr := utils.Time2TimeStr(time2Check) + for i := 0; i < len(timeStrList); i += 2 { + if checkTimeStr >= timeStrList[i] && checkTimeStr <= timeStrList[i+1] { + return true + } + } + return false +} +func jxOrder2GoodsOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, deliveryAddress *dao.UserDeliveryAddressEx, userID string, IsDeliverySelf bool) (order *model.GoodsOrder, err error) { + order = &model.GoodsOrder{ + VendorOrderID: utils.Int64ToStr(jxOrder.OrderID), + VendorID: model.VendorIDJX, + VendorStoreID: utils.Int2Str(jxOrder.StoreID), + StoreID: jxOrder.StoreID, + StoreName: jxOrder.StoreName, + // UserID: ctx.GetUserID(), + + ConsigneeName: deliveryAddress.ConsigneeName, + ConsigneeMobile: deliveryAddress.ConsigneeMobile, + ConsigneeMobile2: deliveryAddress.ConsigneeMobile, + ConsigneeAddress: fmt.Sprintf("%s%s", deliveryAddress.Address, deliveryAddress.DetailAddress), + CoordinateType: model.CoordinateTypeMars, + ConsigneeLng: jxutils.StandardCoordinate2Int(deliveryAddress.Lng), + ConsigneeLat: jxutils.StandardCoordinate2Int(deliveryAddress.Lat), + + Status: model.OrderStatusUnknown, + VendorStatus: "realnew", + OrderSeq: 0, + BuyerComment: jxOrder.BuyerComment, + + DeliveryType: model.OrderDeliveryTypeStoreSelf, + StatusTime: time.Now(), + EarningType: jxOrder.EarningType, + OrderType: jxOrder.OrderType, + VendorOrderID2: jxOrder.OrderID2, + } + if userID == "" { + order.UserID = ctx.GetUserID() + } else { + order.UserID = userID + } + order.OrderCreatedAt = order.StatusTime + order.VendorUserID = order.UserID + if order.UserID == "" && order.VendorUserID == "" { + if jxOrder.UserID != "" { + order.UserID = jxOrder.UserID + order.VendorUserID = jxOrder.UserID + } + } + if jxOrder.ExpectedDeliveredTimestamp != 0 { + order.ExpectedDeliveredTime = utils.Timestamp2Time(jxOrder.ExpectedDeliveredTimestamp) + order.BusinessType = model.BusinessTypeDingshida + } else { + order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour) + order.BusinessType = model.BusinessTypeImmediate + } + for _, sku := range jxOrder.Skus { + order.Skus = append(order.Skus, &model.OrderSku{ + Count: sku.Count, + VendorSkuID: utils.Int2Str(sku.SkuID), + SkuID: sku.SkuID, + SkuName: sku.Name, + VendorPrice: sku.Price, + SalePrice: sku.SalePrice, + }) + order.TotalShopMoney += int64(sku.Count) * sku.SalePrice + } + order.TotalShopMoney += jxOrder.FreightPrice + order.ActualPayPrice = jxOrder.ActualPayPrice + order.TotalShopMoney = utils.Float64TwoInt64(float64(order.TotalShopMoney) * jdshopapi.JdsPayPercentage) + if jxOrder.FromStoreID != 0 { + order.FromStoreID = jxOrder.FromStoreID + order.DeliveryFlag = model.OrderDeliveryFlagMaskScheduleDisabled + order.Flag = 1 + if jxOrder.OrderType == model.OrderTypeMatter { + order.WaybillVendorID = model.VendorIDJDWL + order.ConsigneeAddress = deliveryAddress.Address + } + } + //如果是自提单就设置 + if IsDeliverySelf { + order.DeliveryType = model.OrderDeliveryTypeSelfTake + } + return order, err +} + +func AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) { + var status int + if isAcceptIt { + status = model.OrderStatusAccepted + } else { + status = model.OrderStatusCanceled + } + return changeOrderStatus(order.VendorOrderID, status, "") +} + +func AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) { + return err +} + +func MarkArrears(db *dao.DaoDB, order *model.GoodsOrder, orderPay *model.OrderPay) { + //退款后,若此订单下单用户有推广人,则需要将分给推广人的金额记录到该推广人的欠款中 + // orders, _ := dao.QueryOrders(db, order.VendorOrderID, 0, []int{model.VendorIDJX}, 0, utils.DefaultTimeValue, utils.DefaultTimeValue) + // if len(orders) > 0 { + // user, _ := dao.GetUserByID(db, "user_id", orders[0].UserID) + // if user.ParentMobile != "" { + // user2, _ := dao.GetUserByID(db, "mobile", user.ParentMobile) + // user2.Arrears = user2.Arrears + (orderPay.TotalFee * user2.DividePercentage / 100) + // dao.UpdateEntity(db, user2, "Arrears") + // if user2.ParentMobile != "" { + // user3, _ := dao.GetUserByID(db, "mobile", user2.ParentMobile) + // user3.Arrears = user3.Arrears + ((orderPay.TotalFee - user2.Arrears) * user3.DividePercentage / 100) + // dao.UpdateEntity(db, user3, "Arrears") + // } + // } + // } +} + +// todo 消息用异步可能导致丢失,单同步又有重入相关的问题 +func callNewOrder(order *model.GoodsOrder) (err error) { + jxutils.CallMsgHandlerAsync(func() { + err = partner.CurOrderManager.OnOrderNew(order, model.Order2Status(order)) + }, jxutils.ComposeUniversalOrderID(order.VendorOrderID, model.VendorIDJX)) + return err +} + +func changeOrderStatus(vendorOrderID string, status int, remark string) (err error) { + orderStatus := &model.OrderStatus{ + VendorOrderID: vendorOrderID, + VendorID: model.VendorIDJX, + OrderType: model.OrderTypeOrder, + RefVendorOrderID: vendorOrderID, + RefVendorID: model.VendorIDJX, + VendorStatus: utils.Int2Str(status), + Status: status, + StatusTime: time.Now(), + Remark: remark, + } + jxutils.CallMsgHandlerAsync(func() { + err = partner.CurOrderManager.OnOrderStatusChanged("", orderStatus) + }, jxutils.ComposeUniversalOrderID(vendorOrderID, model.VendorIDJX)) + return err +} + +func PayForPopluarMan(ctx *jxcontext.Context, vendorOrderID, userID string, price int) (err error) { + db := dao.GetDB() + user, err := dao.GetUserByID(db, "user_id", userID) + if user == nil { + return fmt.Errorf("未找到此用户!用户ID:[%v]\n", userID) + } + auth, err := dao.GetUserBindAuthInfo(db, userID, model.AuthBindTypeAuth, []string{"weixinmini"}, "", "", "wx4b5930c13f8b1170") + if len(auth) == 0 { + return fmt.Errorf("未找到此用户的微信验证方式!用户ID:[%v]\n", userID) + } + // goods, err := dao.QueryOrders(db, vendorOrderID, 0, []int{model.VendorIDJX}, 0, utils.ZeroTimeValue, utils.ZeroTimeValue) + // if len(goods) == 0 { + // return fmt.Errorf("未找到此订单!订单ID:[%v]\n", vendorOrderID) + // } + param := &wxpayapi.TransfersParam{ + CheckName: wxpayapi.CheckName, + PartnerTradeNo: vendorOrderID, + Desc: "每日推广人订单分成分到个人", + SpbillCreateIP: ctx.GetRealRemoteIP(), + OpenID: auth[0].AuthID, + Amount: price, + } + _, err = api.WxpayAPI.Transfers(param) + return err +} + +//自动打款给市场推广人 +func AutoPayForPopluarMan(ctx *jxcontext.Context) (err error) { + // var ( + // errMsg string + // // errCode string + // db = dao.GetDB() + // fromDateStr = time.Now().AddDate(0, 0, -1).Format("2006-1-2") + " 00:00:00" + // toDateStr = time.Now().AddDate(0, 0, -1).Format("2006-1-2") + " 23:59:59" + // mapResult = make(map[string]interface{}) + // ) + // result, err := dao.GetOrdersForJxPay(db, utils.Str2Time(fromDateStr), utils.Str2Time(toDateStr)) + // for _, goods := range result { + // var ( + // param = &wxpayapi.TransfersParam{ + // CheckName: wxpayapi.CheckName, + // Desc: "每日推广人订单分成分到个人", + // SpbillCreateIP: ctx.GetRealRemoteIP(), + // } + // payPrice1 int + // payPrice2 int + // ) + // user, err := dao.GetUserByID(db, "user_id", goods.UserID) + // if user.ParentMobile == "" { + // return err + // } + // user2, err := dao.GetUserByID(db, "mobile", user.ParentMobile) + // auths, err := dao.GetUserBindAuthInfo(db, user2.UserID, model.AuthBindTypeAuth, []string{"weixinmini"}, "", "", "wx4b5930c13f8b1170") + // if err != nil { + // return err + // } + // if len(auths) == 0 { + // errMsg += fmt.Sprintf("打款失败!未找到此用户的微信验证方式!订单号:[%v],用户ID:[%v]\n", goods.VendorOrderID, user2.UserID) + // } else { + // var openID string + // for _, auth := range auths { + // if auth.TypeID == wxAppID { + // openID = auth.AuthID + // } + // } + // payPrice1 = int(goods.ActualPayPrice) * user2.DividePercentage / 100 + // //表示这个人之前有欠款,意思是取消订单退款时,这个推广人的分成收不回来,算作欠款,打钱的时候要扣除 + // //表示这个人之前有小于3毛钱的款没有打(微信付款api付款最低3毛),记录下来加到以后的款项中 + // rPrice := payPrice1 - user2.Arrears + user2.Profit + // err = updateUserAndTransfers(db, param, user2, openID, rPrice) + // if err != nil { + // errMsg += err.Error() + // } + // mapResult["打款人1"] = user2.Name + // mapResult["打款人金额1"] = rPrice + // mapResult["打款人电话1"] = user2.Mobile + // mapResult["打款人1userID"] = user2.UserID + // } + // if user2.ParentMobile != "" { + // user3, err := dao.GetUserByID(db, "mobile", user2.ParentMobile) + // auths, err := dao.GetUserBindAuthInfo(db, user3.UserID, model.AuthBindTypeAuth, []string{"weixinmini"}, "", "", "wx4b5930c13f8b1170") + // if err != nil { + // return err + // } + // if len(auths) == 0 { + // errMsg += fmt.Sprintf("打款失败!未找到此用户的微信验证方式!订单号:[%v],用户ID:[%v]\n", goods.VendorOrderID, user3.UserID) + // } else { + // var openID string + // for _, auth := range auths { + // if auth.TypeID == wxAppID { + // openID = auth.AuthID + // } + // } + // payPrice2 = (int(goods.ActualPayPrice) - payPrice1) * user3.DividePercentage / 100 + // rPrice := payPrice2 - user3.Arrears + user3.Profit + // err = updateUserAndTransfers(db, param, user3, openID, rPrice) + // if err != nil { + // errMsg += err.Error() + // } + // mapResult["打款人2"] = user3.Name + // mapResult["打款人金额2"] = rPrice + // mapResult["打款人电话2"] = user3.Mobile + // mapResult["打款人2userID"] = user3.UserID + // } + // } + // } + // user, _ := dao.GetUserByID(dao.GetDB(), "mobile", "18160030913") + // if user != nil && errMsg != "" { + // ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.UserID, "每日打款错误", errMsg) + // } + // if err != nil || errMsg != "" { + // errMsg += err.Error() + // errCode = model.ErrCodeGeneralFailed + // } else { + // errCode = model.ErrCodeSuccess + // } + // err = event.AddOperateEvent(ctx, ctx.GetTrackInfo(), cms.BuildDiffData(mapResult), errCode, errMsg, 0, "AutoPayForPopluarMan") + // globals.SugarLogger.Debugf("每日订单打款:[%v]", cms.BuildDiffData(mapResult)) + return err +} + +func updateUserAndTransfers(db *dao.DaoDB, param *wxpayapi.TransfersParam, user *model.User, authID string, rPrice int) (err error) { + if rPrice >= 30 { + param.OpenID = authID + param.Amount = rPrice + param.PartnerTradeNo = utils.GetUUID() + _, err = api.WxpayAPI.Transfers(param) + user.ProfitSum = user.ProfitSum + rPrice + user.Profit = 0 + user.Arrears = 0 + } else if rPrice >= 0 && rPrice < 30 { + user.Profit = rPrice + user.Arrears = 0 + } else { + user.Profit = 0 + user.Arrears = int(utils.Float64TwoInt64(math.Abs(utils.Int2Float64(rPrice)))) + } + _, err = dao.UpdateEntity(db, user, "ProfitSum", "Profit", "Arrears") + return err +} + +func CancelPayTimeOutOrder(ctx *jxcontext.Context) (err error) { + db := dao.GetDB() + var orders []*model.GoodsOrder + sql := ` + SELECT * + FROM goods_order + WHERE order_created_at >= ? AND order_created_at <= NOW() + AND status = ? + AND vendor_id = ? + ` + sqlParams := []interface{}{ + time.Now().Add(-time.Minute * 30), + model.OrderStatusWait4Pay, + model.VendorIDJX, + } + err = dao.GetRows(db, &orders, sql, sqlParams) + for _, v := range orders { + if v.OrderCreatedAt.Add(PayWaitingTime).Before(time.Now()) { + err2 := changeOrderStatus(v.VendorOrderID, model.OrderStatusCanceled, autoCancelOrderReason) + err = err2 + } + } + return err +} + +func GetHalfHoursList() (strs []string) { + for k := 0; k < 3; k++ { + for i := 0; i < 10; i++ { + for j := 0; j < 4; j += 3 { + if k == 2 && i > 3 { + break + } + strs = append(strs, utils.Int2Str(k)+utils.Int2Str(i)+":"+utils.Int2Str(j)+"0"+":00") + } + } + } + return strs +} + +func GetDiscountActHoursList() (str []string) { + for k := 1; k < 3; k++ { + for i := 0; i < 10; i++ { + for j := 0; j < 6; j++ { + if k == 1 && i == 0 && j == 0 { + continue + } + if k == 2 && i > 2 { + break + } + if k == 2 && i == 2 && j > 0 { + break + } + str = append(str, utils.Int2Str(k)+utils.Int2Str(i)+":"+utils.Int2Str(j)+"0"+":00") + } + } + } + return str +} diff --git a/business/partner/purchase/jx/localjx/tonglianpay.go b/business/partner/purchase/jx/localjx/tonglianpay.go new file mode 100644 index 000000000..933b368af --- /dev/null +++ b/business/partner/purchase/jx/localjx/tonglianpay.go @@ -0,0 +1,182 @@ +package localjx + +import ( + "encoding/json" + "strings" + "time" + + "git.rosy.net.cn/jx-callback/globals" + + "git.rosy.net.cn/baseapi/platformapi/tonglianpayapi" + "git.rosy.net.cn/baseapi/utils" + + "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/globals/api" +) + +func pay4OrderByTL(ctx *jxcontext.Context, order *model.GoodsOrder, payType int, vendorPayType string) (orderPay *model.OrderPay, err error) { + // if order.FromStoreID != 0 { + // result, _ := orderman.GetMatterStoreOrderCount(nil, order.FromStoreID) + // if !result.Flag { + // return nil, fmt.Errorf("该门店[%v]已在一周内申请过物料,请勿重复申请!", order.FromStoreID) + // } + // } + payCreatedAt := time.Now() + param := &tonglianpayapi.CreateUnitorderOrderParam{ + Trxamt: int(order.ActualPayPrice), + NotifyUrl: globals.TLPayNotifyURL, + Reqsn: order.VendorOrderID, + PayType: vendorPayType, + } + //暂时做兼容处理 + if vendorPayType == "JSAPI" { + param.PayType = tonglianpayapi.PayTypeWxXcx + } + if vendorPayType == tonglianpayapi.PayTypeWxXcx { + if authInfo, err := ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini { + param.Acct = authInfo.GetAuthID() + } + } + if vendorPayType == tonglianpayapi.PayTypeH5 { + param2 := &tonglianpayapi.CreateH5UnitorderOrderParam{ + Trxamt: int(order.ActualPayPrice), + NotifyUrl: globals.TLPayNotifyURL, + Body: "京西菜市", + Charset: "UTF-8", + } + err = api.TLpayAPI.CreateH5UnitorderOrder(param2) + } else { + result, err := api.TLpayAPI.CreateUnitorderOrder(param) + if err == nil { + var result2 tonglianpayapi.PayInfo + json.Unmarshal([]byte(result.PayInfo), &result2) + prePayID := result2.Package[strings.LastIndex(result2.Package, "=")+1 : len(result2.Package)] + orderPay = &model.OrderPay{ + PayOrderID: param.Reqsn, + PayType: payType, + VendorPayType: vendorPayType, + TransactionID: result.TrxID, + VendorOrderID: order.VendorOrderID, + VendorID: order.VendorID, + Status: 0, + PayCreatedAt: payCreatedAt, + PrepayID: prePayID, + CodeURL: utils.LimitUTF8StringLen(result.PayInfo, 3200), + TotalFee: int(order.ActualPayPrice), + } + } + } + return orderPay, err +} + +func OnTLPayCallback(call *tonglianpayapi.CallBackResult) (err error) { + globals.SugarLogger.Debugf("OnTLPayCallback msg:%s", utils.Format4Output(call, true)) + switch call.TrxCode { + case tonglianpayapi.MsgTypePay: + err = onTLpayFinished(call) + case tonglianpayapi.MsgTypeRefund: + err = onTLpayRefund(call) + } + return err +} + +func onTLpayFinished(call *tonglianpayapi.CallBackResult) (err error) { + orderPay := &model.OrderPay{ + PayOrderID: call.CusorderID, + // PayType: model.PayTypeTL, + } + orderPay.DeletedAt = utils.DefaultTimeValue + db := dao.GetDB() + if err = dao.GetEntity(db, orderPay, "PayOrderID", "DeletedAt"); err == nil { + if orderPay.Status != 0 { + globals.SugarLogger.Debugf("already pay msg:%s, err:%v", utils.Format4Output(call, true), err) + return err + } + loc, _ := time.LoadLocation("Local") + t1, _ := time.ParseInLocation("20060102150405", call.PayTime, loc) + orderPay.PayFinishedAt = utils.Time2Pointer(t1) + // orderPay.TransactionID = call.ChnlTrxID + orderPay.OriginalData = utils.Format4Output(call, true) + if call.TrxStatus == tonglianpayapi.TrxStatusSuccess { + orderPay.Status = model.PayStatusYes + } else { + orderPay.Status = model.PayStatusFailed + } + dao.UpdateEntity(db, orderPay) + if call.TrxStatus == tonglianpayapi.TrxStatusSuccess { + err = OnPayFinished(orderPay) + } + } else { + globals.SugarLogger.Debugf("onTLpayFinished msg:%s, err:%v", utils.Format4Output(call, true), err) + } + return err +} + +func onTLpayRefund(call *tonglianpayapi.CallBackResult) (err error) { + orderPayRefund := &model.OrderPayRefund{ + RefundID: call.CusorderID, + } + db := dao.GetDB() + if err = dao.GetEntity(db, orderPayRefund, "RefundID"); err == nil { + if call.TrxStatus == tonglianpayapi.TrxStatusSuccess { + orderPayRefund.Status = model.RefundStatusYes + } else { + orderPayRefund.Status = model.RefundStatusFailed + } + orderPayRefund.OriginalData = utils.Format4Output(call, true) + dao.UpdateEntity(db, orderPayRefund) + } else if dao.IsNoRowsError(err) { + globals.SugarLogger.Warnf("收到异常的退款事件, call:%s", utils.Format4Output(call, true)) + } + + orderPay := &model.OrderPay{ + VendorOrderID: orderPayRefund.VendorOrderID, + VendorID: jxutils.GetPossibleVendorIDFromVendorOrderID(orderPayRefund.VendorOrderID), + PayType: model.PayTypeWX, + Status: model.PayStatusYes, + } + orderPay.DeletedAt = utils.DefaultTimeValue + if err = dao.GetEntity(db, orderPay, "VendorOrderID", "VendorID", "PayType", "Status", "DeletedAt"); err == nil { + orderPay.Status = model.PayStatusRefund + dao.UpdateEntity(db, orderPay) + } + return err +} + +func RefundOrderByTL(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID string, refundFee int, refundDesc string) (orderPayRefund *model.OrderPayRefund, err error) { + result, err := api.TLpayAPI.PayRefund(&tonglianpayapi.PayRefundParam{ + Trxamt: refundFee, + Reqsn: utils.GetUUID(), + Remark: refundDesc, + OldTrxID: orderPay.TransactionID, + }) + if err == nil { + orderPayRefund = &model.OrderPayRefund{ + RefundID: refundID, + VendorRefundID: result.TrxID, + VendorOrderID: orderPay.VendorOrderID, + VendorID: orderPay.VendorID, + Status: model.RefundStatusNo, + TransactionID: orderPay.TransactionID, + RefundFee: refundFee, + RefundCreatedAt: time.Now(), + } + dao.WrapAddIDCULDEntity(orderPayRefund, ctx.GetUserName()) + db := dao.GetDB() + if result.TrxStatus == tonglianpayapi.TrxStatusSuccess { + orderPayRefund.Status = model.RefundStatusYes + } else { + orderPayRefund.Status = model.RefundStatusFailed + } + orderPayRefund.OriginalData = utils.Format4Output(result, true) + dao.CreateEntity(db, orderPayRefund) + + orderPay.Status = model.PayStatusRefund + dao.UpdateEntity(db, orderPay) + } + return orderPayRefund, err +} diff --git a/business/partner/purchase/jx/localjx/wxpay.go b/business/partner/purchase/jx/localjx/wxpay.go new file mode 100644 index 000000000..edebf972e --- /dev/null +++ b/business/partner/purchase/jx/localjx/wxpay.go @@ -0,0 +1,152 @@ +package localjx + +import ( + "fmt" + "time" + + "git.rosy.net.cn/baseapi/platformapi/wxpayapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/globals/api" +) + +func vendorPayType2WxpayType(vendorPayType string) string { + return vendorPayType +} + +func getOrderBrief(order *model.GoodsOrder) string { + return fmt.Sprintf("%s等共%d件商品", order.Skus[0].SkuName, order.GoodsCount) +} + +func pay4OrderByWX(ctx *jxcontext.Context, order *model.GoodsOrder, vendorPayType string) (orderPay *model.OrderPay, err error) { + payCreatedAt := time.Now() + param := &wxpayapi.CreateOrderParam{ + OutTradeNo: utils.Int64ToStr(GenPayOrderID(order)), + Body: getOrderBrief(order), + NotifyURL: globals.WxpayNotifyURL, + SpbillCreateIP: ctx.GetRealRemoteIP(), + TradeType: vendorPayType2WxpayType(vendorPayType), + TotalFee: int(order.ActualPayPrice), + + TimeStart: wxpayapi.Time2PayTime(payCreatedAt), + // TimeExpire: wxpayapi.Time2PayTime(payCreatedAt.Add(PayWaitingTime)), + ProfitSharing: wxpayapi.OptYes, + } + if authInfo, err := ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini { + param.OpenID = authInfo.GetAuthID() + } + result, err := api.WxpayAPI.CreateUnifiedOrder(param) + if err == nil { + orderPay = &model.OrderPay{ + PayOrderID: param.OutTradeNo, + PayType: model.PayTypeWX, + VendorPayType: vendorPayType, + + VendorOrderID: order.VendorOrderID, + VendorID: order.VendorID, + Status: 0, + PayCreatedAt: payCreatedAt, + PrepayID: result.PrepayID, + CodeURL: result.CodeURL, + TotalFee: int(order.ActualPayPrice), + } + } + return orderPay, err +} + +func OnWxPayCallback(msg *wxpayapi.CallbackMsg) (err error) { + globals.SugarLogger.Debugf("OnWxPayCallback msg:%s", utils.Format4Output(msg, true)) + switch msg.MsgType { + case wxpayapi.MsgTypePay: + err = onWxpayFinished(msg.Data.(*wxpayapi.PayResultMsg)) + case wxpayapi.MsgTypeRefund: + err = onWxpayRefund(msg.Data.(*wxpayapi.RefundResultMsg)) + } + return err +} + +func onWxpayFinished(msg *wxpayapi.PayResultMsg) (err error) { + orderPay := &model.OrderPay{ + PayOrderID: msg.OutTradeNo, + PayType: model.PayTypeWX, + } + orderPay.DeletedAt = utils.DefaultTimeValue + db := dao.GetDB() + if err = dao.GetEntity(db, orderPay, "PayOrderID", "PayType", "DeletedAt"); err == nil { + orderPay.PayFinishedAt = utils.Time2Pointer(wxpayapi.PayTime2Time(msg.TimeEnd)) + orderPay.TransactionID = msg.TransactionID + orderPay.OriginalData = utils.Format4Output(msg, true) + if msg.ResultCode == wxpayapi.ResponseCodeSuccess { + orderPay.Status = model.PayStatusYes + } else { + orderPay.Status = model.PayStatusFailed + } + dao.UpdateEntity(db, orderPay) + if msg.ResultCode == wxpayapi.ResponseCodeSuccess { + err = OnPayFinished(orderPay) + } + } else { + globals.SugarLogger.Debugf("onWxpayFinished msg:%s, err:%v", utils.Format4Output(msg, true), err) + } + return err +} + +func onWxpayRefund(msg *wxpayapi.RefundResultMsg) (err error) { + orderPayRefund := &model.OrderPayRefund{ + RefundID: msg.ReqInfoObj.OutRefundNo, + } + db := dao.GetDB() + if err = dao.GetEntity(db, orderPayRefund, "RefundID"); err == nil { + if msg.ResultCode == wxpayapi.ResponseCodeSuccess { + orderPayRefund.Status = model.RefundStatusYes + } else { + orderPayRefund.Status = model.RefundStatusFailed + } + orderPayRefund.OriginalData = utils.Format4Output(msg, true) + dao.UpdateEntity(db, orderPayRefund) + } else if dao.IsNoRowsError(err) { + globals.SugarLogger.Warnf("收到异常的退款事件, msg:%s", utils.Format4Output(msg, true)) + } + + orderPay := &model.OrderPay{ + VendorOrderID: orderPayRefund.VendorOrderID, + VendorID: jxutils.GetPossibleVendorIDFromVendorOrderID(orderPayRefund.VendorOrderID), + PayType: model.PayTypeWX, + Status: model.PayStatusYes, + } + orderPay.DeletedAt = utils.DefaultTimeValue + if err = dao.GetEntity(db, orderPay, "VendorOrderID", "VendorID", "PayType", "Status", "DeletedAt"); err == nil { + orderPay.Status = model.PayStatusRefund + dao.UpdateEntity(db, orderPay) + } + return err +} + +func refundOrderByWX(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID string, refundFee int, refundDesc string) (orderPayRefund *model.OrderPayRefund, err error) { + result, err := api.WxpayAPI.PayRefund(&wxpayapi.PayRefundParam{ + OutTradeNo: orderPay.VendorOrderID, + NotifyURL: globals.WxpayNotifyURL, + OutRefundNo: refundID, + TotalFee: orderPay.TotalFee, + RefundFee: refundFee, + RefundDesc: wxpayapi.CData(refundDesc), + }) + if err == nil { + orderPayRefund = &model.OrderPayRefund{ + RefundID: refundID, + VendorRefundID: result.RefundID, + VendorOrderID: orderPay.VendorOrderID, + VendorID: orderPay.VendorID, + Status: model.RefundStatusNo, + TransactionID: orderPay.TransactionID, + RefundFee: orderPay.TotalFee, + RefundCreatedAt: time.Now(), + } + } + return orderPayRefund, err +} diff --git a/business/partner/purchase/jx/order.go b/business/partner/purchase/jx/order.go new file mode 100644 index 000000000..4c36f9c25 --- /dev/null +++ b/business/partner/purchase/jx/order.go @@ -0,0 +1,134 @@ +package jx + +import ( + "time" + + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/business/partner/purchase/jx/localjx" + "git.rosy.net.cn/jx-callback/business/partner/purchase/jx/phpjx" +) + +func (c *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) { + return order +} + +func (c *PurchaseHandler) GetOrder(vendorOrgCode, orderID string) (order *model.GoodsOrder, err error) { + order, err = partner.CurOrderManager.LoadOrder(orderID, model.VendorIDJX) + return order, err +} + +func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) { + order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJX) + if err == nil { + status = order.Status + } + return status, err +} + +func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) { + var status int + if isAcceptIt { + status = model.OrderStatusAccepted + } else { + status = model.OrderStatusCanceled + } + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, status) + } else { + err = localjx.AcceptOrRefuseOrder(order, isAcceptIt, userName) + } + return err +} + +func (c *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) { + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusFinishedPickup) + } else { + err = localjx.PickupGoods(order, isSelfDelivery, userName) + } + return err +} + +func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) { + return err +} + +func (p *PurchaseHandler) CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 拣货失败后再次招唤平台配送 + return err +} + +func (p *PurchaseHandler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 投递失败后确认收到退货 + return err +} + +func (c *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) { + return err +} + +func (c *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) { + return err +} + +func (c *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) { + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusDelivering) + } else { + err = localjx.SelfDeliverDelivering(order, userName) + } + return err +} + +func (c *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) { + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusFinished) + } else { + err = localjx.SelfDeliverDelivered(order, userName) + } + return err +} + +func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) { + return mobile, err +} + +func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) { + if model.IsOrderJXTemp(order) { + } else { + err = localjx.AgreeOrRefuseCancel(ctx, order, isAgree, reason) + } + return err +} + +func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusCanceled) + } else { + err = localjx.CancelOrder(ctx, order, reason) + } + return err +} + +func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) { + if model.IsOrderJXTemp(order) { + } else { + err = localjx.AdjustOrder(ctx, order, removedSkuList, reason) + } + return err +} + +func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, queryDate time.Time, vendorStoreID string) (vendorOrderIDs []string, err error) { + return vendorOrderIDs, err +} + +func (c *PurchaseHandler) ConfirmSelfTake(ctx *jxcontext.Context, vendorOrderID, selfTakeCode string) (err error) { + order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJX) + if err == nil { + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusFinished) + } + } + return err +} diff --git a/business/partner/purchase/jx/order_afs.go b/business/partner/purchase/jx/order_afs.go new file mode 100644 index 000000000..c67602161 --- /dev/null +++ b/business/partner/purchase/jx/order_afs.go @@ -0,0 +1,170 @@ +package jx + +import ( + "fmt" + "strings" + "time" + + "git.rosy.net.cn/jx-callback/business/jxutils" + + "git.rosy.net.cn/jx-callback/globals" + + "git.rosy.net.cn/jx-callback/business/model/dao" + + "git.rosy.net.cn/jx-callback/globals/api" + + "git.rosy.net.cn/jx-callback/business/partner/purchase/jx/localjx" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" +) + +// 审核售后单申请 +func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) { + var status int + if approveType == partner.AfsApproveTypeRefused { + status = model.AfsOrderStatusFailed + } else { + status = model.AfsOrderStatusFinished + } + orderStatus := &model.OrderStatus{ + VendorOrderID: order.AfsOrderID, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中 + VendorID: order.VendorID, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: order.VendorOrderID, + RefVendorID: order.VendorID, + VendorStatus: utils.Int2Str(status), + Status: status, + StatusTime: time.Now(), + Remark: reason, + } + if status == model.AfsOrderStatusFinished { + orderPays, err := dao.GetOrderPayList(dao.GetDB(), order.VendorOrderID, order.VendorID) + if err == nil { + _, err = localjx.RefundOrderByTL(ctx, orderPays[0], order.VendorOrderID, int(order.SkuUserMoney), reason) + if err != nil { + return err + } else { + partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus) + } + } + } else { + partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus) + } + return err +} + +// 确认收到退货 +func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) { + err = fmt.Errorf("京西商城当前不支持ConfirmReceivedReturnGoods") + return err +} + +// 发起全款退款 +func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { + err = c.PartRefundOrder(ctx, order, order.Skus, reason) + return err +} + +// 发起部分退款 +func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) { + globals.SugarLogger.Debugf("PartRefundOrder jx, orderID :%v", order.VendorOrderID) + var ( + skuMap = make(map[int]*model.OrderSku) + appID = "" + salePrice int64 + db = dao.GetDB() + ) + if time.Now().Sub(order.OrderCreatedAt) > 24*time.Hour { + return fmt.Errorf("已超过售后申请时间,如有疑问请联系门店!") + } + referer := ctx.GetRequest().Referer() + index := strings.Index(referer, "//") + if index > 0 { + list := strings.Split(referer[index+2:], "/") + if len(list) >= 2 { + appID = list[1] + } + } + for _, sku := range order.Skus { + skuMap[sku.SkuID] = sku + } + orderStatus := buildOrderStatus(ctx, order, reason, isJxShop(appID)) + afsOrder := &model.AfsOrder{ + VendorID: order.VendorID, + AfsOrderID: orderStatus.VendorOrderID, + VendorOrderID: orderStatus.RefVendorOrderID, + VendorStoreID: order.VendorStoreID, + StoreID: order.StoreID, + AfsCreatedAt: time.Now(), + VendorAppealType: "", + AppealType: model.AfsAppealTypeRefund, + VendorReasonType: utils.Int2Str(model.AfsReasonNotOthers), + ReasonType: model.AfsReasonNotOthers, + ReasonDesc: utils.LimitUTF8StringLen(reason, 1024), + ReasonImgList: "", + RefundType: model.AfsTypePartRefund, + + VendorOrgCode: "", + } + for _, sku := range refundSkuList { + orderSku := &model.OrderSkuFinancial{ + Count: sku.Count, + VendorSkuID: utils.Int2Str(sku.SkuID), + SkuID: sku.SkuID, + } + if skuMap[sku.SkuID] != nil { + orderSku.Name = skuMap[sku.SkuID].SkuName + orderSku.UserMoney = skuMap[sku.SkuID].SalePrice * int64(sku.Count) + salePrice += skuMap[sku.SkuID].SalePrice * int64(sku.Count) + } + afsOrder.SkuUserMoney += orderSku.UserMoney + afsOrder.Skus = append(afsOrder.Skus, orderSku) + } + + if !isJxShop(appID) { + orderPays, err := dao.GetOrderPayList(db, order.VendorOrderID, order.VendorID) + if err == nil { + _, err = localjx.RefundOrderByTL(ctx, orderPays[0], order.VendorOrderID, int(salePrice), reason) + if err != nil { + return err + } else { + if afsOrder != nil { + err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus) + } + } + } + } else { + err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus) + } + return err +} + +func buildOrderStatus(ctx *jxcontext.Context, order *model.GoodsOrder, reason string, isJxShop bool) (orderStatus *model.OrderStatus) { + orderStatus = &model.OrderStatus{ + VendorOrderID: utils.Int64ToStr(jxutils.GenAfsOrderNo()), // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中 + VendorID: order.VendorID, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: order.VendorOrderID, + RefVendorID: order.VendorID, + VendorStatus: utils.Int2Str(model.AfsOrderStatusWait4Approve), + // Status: model.AfsOrderStatusWait4Approve, + StatusTime: time.Now(), + Remark: reason, + } + if isJxShop { + orderStatus.Status = model.AfsOrderStatusWait4Approve + } else { + orderStatus.Status = model.AfsOrderStatusFinished + } + return orderStatus +} + +func isJxShop(appID string) bool { + if appID == api.WeixinMiniAppID2 { + return true + } + return false +} diff --git a/business/partner/purchase/jx/order_comment.go b/business/partner/purchase/jx/order_comment.go new file mode 100644 index 000000000..20553a214 --- /dev/null +++ b/business/partner/purchase/jx/order_comment.go @@ -0,0 +1,10 @@ +package jx + +import ( + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/model" +) + +func (c *PurchaseHandler) ReplyOrderComment(ctx *jxcontext.Context, vendorOrgCode string, orderComment *model.OrderComment, replyComment string) (err error) { + return err +} diff --git a/business/partner/purchase/jx/phpjx/callback.go b/business/partner/purchase/jx/phpjx/callback.go new file mode 100644 index 000000000..49dc06968 --- /dev/null +++ b/business/partner/purchase/jx/phpjx/callback.go @@ -0,0 +1,55 @@ +package phpjx + +import ( + "fmt" + "time" + + "git.rosy.net.cn/baseapi/utils" +) + +const ( + appKey = "4A86853D-E4B6-454E-940A-B68ECDA2B73E" + + MsgTypeOrder = "order" + MsgTypeAfsOrder = "afsOrder" +) + +type CallbackResponse struct { + Code int `json:"code"` + Data string `json:"data"` +} + +type CallbackMsg struct { + AppKey string `json:"appKey"` + MsgType string `json:"msgType"` + SubMsgType string `json:"subMsgType"` + ThingID string `json:"thingID"` + ThingID2 string `json:"thingID2"` + Data string `json:"data"` + Timestamp int64 `json:"timestamp"` +} + +func OnCallbackMsg(msg *CallbackMsg) (retVal, errCode string, err error) { + if msg.AppKey != appKey { + return retVal, errCode, fmt.Errorf("无效的AppKey:%s", msg.AppKey) + } + if msg.MsgType == MsgTypeOrder { + retVal, errCode, err = OnOrderMsg(msg) + } else if msg.MsgType == MsgTypeAfsOrder { + err = OnAfsOrderMsg(msg) + } + return retVal, errCode, err +} + +func postFakeMsg(orderNo string, status int) { + msg := &CallbackMsg{ + AppKey: appKey, + MsgType: MsgTypeOrder, + SubMsgType: utils.Int2Str(status), + ThingID: orderNo, + Timestamp: time.Now().Unix(), + } + utils.CallFuncAsync(func() { + OnCallbackMsg(msg) + }) +} diff --git a/business/partner/purchase/jx/phpjx/callback_test.go b/business/partner/purchase/jx/phpjx/callback_test.go new file mode 100644 index 000000000..361777628 --- /dev/null +++ b/business/partner/purchase/jx/phpjx/callback_test.go @@ -0,0 +1,52 @@ +package phpjx + +import ( + "testing" + + _ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals/testinit" +) + +func init() { + testinit.Init() +} + +func TestBuildNewJxOrder(t *testing.T) { + order, err := partner.CurOrderManager.LoadOrder("920931913000041", model.VendorIDJD) + if err != nil { + t.Fatal(err) + } + order.VendorID = model.VendorIDJX + order.VendorStoreID = utils.Int2Str(order.StoreID) + for _, sku := range order.Skus { + sku.VendorID = model.VendorIDJX + sku.VendorSkuID = utils.Int2Str(sku.SkuID) + } + order2 := &Data4Neworder{ + GoodsOrder: *order, + Skus: order.Skus, + } + msg := &CallbackMsg{ + AppKey: appKey, + MsgType: MsgTypeOrder, + SubMsgType: utils.Int2Str(model.OrderStatusNew), + ThingID: order.VendorOrderID, + Data: utils.Format4Output(order2, true), + } + t.Logf("\n%s", msg.AppKey) + t.Logf("\n%s", msg.MsgType) + t.Logf("\n%s", msg.SubMsgType) + t.Logf("\n%s", msg.ThingID) + t.Logf("\n%s", msg.Data) + + var order3 *model.GoodsOrder + err = utils.UnmarshalUseNumber([]byte(msg.Data), &order3) + if err != nil { + t.Fatal(err) + } + t.Log(order3.OrderCreatedAt) +} diff --git a/business/partner/purchase/jx/phpjx/jxapi.go b/business/partner/purchase/jx/phpjx/jxapi.go new file mode 100644 index 000000000..1c6cd25a4 --- /dev/null +++ b/business/partner/purchase/jx/phpjx/jxapi.go @@ -0,0 +1,99 @@ +package phpjx + +import ( + "fmt" + "net/http" + "strings" + + "git.rosy.net.cn/baseapi" + "git.rosy.net.cn/baseapi/platformapi" + "git.rosy.net.cn/baseapi/utils" +) + +type API struct { + token string + appKey string + appSecret string + client *http.Client + config *platformapi.APIConfig +} + +const ( + ResponseCodeSuccess = 200 +) + +const ( + prodURL = "https://www.jingxicaishi.com/index.php/Weimendian/index" +) + +var ( + exceedLimitCodes = map[int]int{} + canRetryCodes = map[int]int{} +) + +var ( + jxAPI *API +) + +func NewAPI(token, appKey, appSecret string, config ...*platformapi.APIConfig) *API { + curConfig := platformapi.DefAPIConfig + if len(config) > 0 { + curConfig = *config[0] + } + return &API{ + token: token, + appKey: appKey, + appSecret: appSecret, + client: &http.Client{Timeout: curConfig.ClientTimeout}, + config: &curConfig, + } +} + +func init() { + jxAPI = NewAPI("", "", "") +} + +func (a *API) AccessAPI(apiStr string, jxParams map[string]interface{}, traceInfo string) (retVal map[string]interface{}, err error) { + err = platformapi.AccessPlatformAPIWithRetry(a.client, + func() *http.Request { + params := utils.MergeMaps(jxParams, map[string]interface{}{ + "timestamp": utils.GetCurTimeStr(), + }) + var request *http.Request + if false { + + } else { + fullURL := prodURL + "/" + apiStr + // baseapi.SugarLogger.Debug(utils.Map2URLValues(params).Encode()) + request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode())) + request.Header.Set("charset", "UTF-8") + request.Header.Set("Content-Type", "application/x-www-form-urlencoded") + } + if traceInfo != "" { + request.Header.Set(platformapi.KeyTrackInfo, traceInfo) + } + // request.Close = true //todo 为了性能考虑还是不要关闭 + return request + }, + a.config, + func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) { + if jsonResult1 == nil { + return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil") + } + code := int(utils.Interface2Int64WithDefault(jsonResult1["code"], 0)) + if code == ResponseCodeSuccess { + retVal = jsonResult1 + return platformapi.ErrLevelSuccess, nil + } + newErr := utils.NewErrorIntCode(jsonResult1["msg"].(string), code) + if _, ok := exceedLimitCodes[code]; ok { + return platformapi.ErrLevelExceedLimit, newErr + } else if _, ok := canRetryCodes[code]; ok { + return platformapi.ErrLevelRecoverableErr, newErr + } else { + baseapi.SugarLogger.Debugf("jx AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true)) + return platformapi.ErrLevelCodeIsNotOK, newErr + } + }) + return retVal, err +} diff --git a/business/partner/purchase/jx/phpjx/jxapi_order.go b/business/partner/purchase/jx/phpjx/jxapi_order.go new file mode 100644 index 000000000..ef2befb2f --- /dev/null +++ b/business/partner/purchase/jx/phpjx/jxapi_order.go @@ -0,0 +1,45 @@ +package phpjx + +import ( + "git.rosy.net.cn/jx-callback/business/model" +) + +var ( + orderStatusMap = map[int]int{ + model.OrderStatusFinishedPickup: 7, + model.OrderStatusDelivering: 8, + // 4, + model.OrderStatusFinished: 3, + model.OrderStatusCanceled: 3, + } +) + +func translateOrderStatus(status int) (outStatus int) { + return status //orderStatusMap[status] +} + +func (a *API) NotifyOrderStatusChanged(order *model.GoodsOrder) (err error) { + status := translateOrderStatus(order.Status) + if status > 0 { + _, err = a.AccessAPI("orderChangeStatus", map[string]interface{}{ + "orderid": order.VendorOrderID, + "status": status, + "data": "", //string(utils.MustMarshal(order)), + }, "") + } + return err +} + +func (a *API) NotifyAfsOrderStatusChanged(afsOrder *model.AfsOrder) (err error) { + status := translateOrderStatus(afsOrder.Status) + if status > 0 { + _, err = a.AccessAPI("afsOrderChangeStatus", map[string]interface{}{ + "orderid": afsOrder.VendorOrderID, + "afsOrderID": afsOrder.AfsOrderID, + "status": status, + "data": "", //string(utils.MustMarshal(order)), + }, "") + } + return err +} + diff --git a/business/partner/purchase/jx/phpjx/jxapi_order_test.go b/business/partner/purchase/jx/phpjx/jxapi_order_test.go new file mode 100644 index 000000000..d74be9133 --- /dev/null +++ b/business/partner/purchase/jx/phpjx/jxapi_order_test.go @@ -0,0 +1,21 @@ +package phpjx + +import ( + "testing" + + _ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman" + + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" +) + +func TestNotifyOrderStatusChanged(t *testing.T) { + order, err := partner.CurOrderManager.LoadOrder("920931913000041", model.VendorIDJX) + if err != nil { + t.Fatal(err) + } + err = jxAPI.NotifyOrderStatusChanged(order) + if err != nil { + t.Fatal(err) + } +} diff --git a/business/partner/purchase/jx/phpjx/order.go b/business/partner/purchase/jx/phpjx/order.go new file mode 100644 index 000000000..c4dd0b068 --- /dev/null +++ b/business/partner/purchase/jx/phpjx/order.go @@ -0,0 +1,84 @@ +package phpjx + +import ( + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals" +) + +func NotifyOrderStatusChanged(order *model.GoodsOrder, status int) (err error) { + orderMsg := *order + orderMsg.Status = status + if err = jxAPI.NotifyOrderStatusChanged(&orderMsg); err == nil { + postFakeMsg(orderMsg.VendorOrderID, orderMsg.Status) + } + return err +} + +type Data4Neworder struct { + model.GoodsOrder + Skus []*model.OrderSku `json:"skus"` +} + +func OnOrderMsg(msg *CallbackMsg) (retVal, errCode string, err error) { + jxutils.CallMsgHandler(func() { + retVal, errCode, err = onOrderMsg(msg) + }, jxutils.ComposeUniversalOrderID(msg.ThingID, model.VendorIDJX)) + return retVal, errCode, err +} + +func onOrderMsg(msg *CallbackMsg) (retVal, errCode string, err error) { + subMsgType := int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)) + if subMsgType == model.OrderStatusNew || subMsgType == model.OrderStatusAdjust { + var order *Data4Neworder + if err = utils.UnmarshalUseNumber([]byte(msg.Data), &order); err == nil { + if order.VendorStatus == "" { + order.VendorStatus = utils.Int2Str(order.Status) + } + retVal, errCode, err = onOrderNew(msg, subMsgType, order) + } + } else { + status := callbackMsg2Status(msg) + err = partner.CurOrderManager.OnOrderStatusChanged("", status) + } + return retVal, errCode, err +} + +func callbackMsg2Status(msg *CallbackMsg) *model.OrderStatus { + orderStatus := &model.OrderStatus{ + VendorOrderID: msg.ThingID, + VendorID: model.VendorIDJX, + OrderType: model.OrderTypeOrder, + RefVendorOrderID: msg.ThingID, + RefVendorID: model.VendorIDJX, + VendorStatus: msg.SubMsgType, + Status: int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)), + StatusTime: utils.Timestamp2Time(msg.Timestamp), + Remark: "", + } + return orderStatus +} + +func onOrderNew(msg *CallbackMsg, subMsgType int, order *Data4Neworder) (retVal, errCode string, err error) { + globals.SugarLogger.Debugf("onOrderNew orderID:%s", msg.ThingID) + order.StoreID = int(utils.Str2Int64WithDefault(order.VendorStoreID, 0)) + if order.DeliveryType == "" { + order.DeliveryType = model.OrderDeliveryTypeStoreSelf + } + order.GoodsOrder.Skus = order.Skus + order.VendorID = model.VendorIDJX + order.Flag = model.OrderFlagMaskTempJX + for _, v := range order.GoodsOrder.Skus { + v.SkuID = int(utils.Str2Int64WithDefault(v.VendorSkuID, 0)) + } + jxutils.RefreshOrderSkuRelated(&order.GoodsOrder) + orderStatus := model.Order2Status(&order.GoodsOrder) + if subMsgType == model.OrderStatusNew { + err = partner.CurOrderManager.OnOrderNew(&order.GoodsOrder, orderStatus) + } else if subMsgType == model.OrderStatusAdjust { + err = partner.CurOrderManager.OnOrderAdjust(&order.GoodsOrder, orderStatus) + } + return retVal, errCode, err +} diff --git a/business/partner/purchase/jx/phpjx/order_afs.go b/business/partner/purchase/jx/phpjx/order_afs.go new file mode 100644 index 000000000..2e2fbd109 --- /dev/null +++ b/business/partner/purchase/jx/phpjx/order_afs.go @@ -0,0 +1,130 @@ +package phpjx + +import ( + "time" + + "git.rosy.net.cn/baseapi/platformapi/jdapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" +) + +type Data4AfsOrderSku struct { + VendorSkuID string `orm:"column(vendor_sku_id);size(48)" json:"vendorSkuID"` // 平台skuid + PromotionType int `json:"promotionType"` // 商品级别促销类型 (1、无优惠;2、秒杀(已经下线);3、单品直降;4、限时抢购;1202、加价购;1203、满赠(标识商品);6、买赠(买A送B,标识B);9999、表示一个普通商品参与捆绑促销,设置的捆绑类型;9998、表示一个商品参与了捆绑促销,并且还参与了其他促销类型;9997、表示一个商品参与了捆绑促销,但是金额拆分不尽,9996:组合购,8001:轻松购会员价,8:第二件N折,9:拼团促销) + Name string `orm:"size(255)" json:"name"` // 商品名 + SalePrice int64 `json:"salePrice"` // 售卖价 + Count int `json:"count"` // 订单下单数量 +} + +type Data4AfsOrder struct { + VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` // 关联原始订单ID + AfsOrderID string `orm:"column(afs_order_id);size(48)" json:"afsOrderID"` // 售后订单ID + AfsCreatedAt time.Time `orm:"type(datetime);null;index" json:"afsCreatedAt"` // 售后单生成时间 + VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` // 外部系统里记录的storeid + + VendorStatus string `orm:"size(255)" json:"vendorStatus"` + VendorReasonType string `orm:"size(255)" json:"vendorReasonType"` // 原始售后原因 + ReasonDesc string `orm:"size(1024)" json:"reasonDesc"` // 售后原因描述 + ReasonImgList string `orm:"size(1024)" json:"reasonImgList"` // 售后描述图片 + VendorAppealType string `orm:"size(255)" json:"vendorAppealType"` // 原始售后方式 + Skus []*Data4AfsOrderSku +} + +func OnAfsOrderMsg(msg *CallbackMsg) (err error) { + jxutils.CallMsgHandlerAsync(func() { + err = onAfsOrderMsg(msg) + }, jxutils.ComposeUniversalOrderID(msg.ThingID, model.VendorIDJX)) + return err +} + +func buildAfsOrder(msg *CallbackMsg) (outAfsOrder *model.AfsOrder, err error) { + var afsOrder *Data4AfsOrder + if err = utils.UnmarshalUseNumber([]byte(msg.Data), &afsOrder); err == nil { + outAfsOrder = &model.AfsOrder{ + VendorID: model.VendorIDJX, + AfsOrderID: afsOrder.AfsOrderID, + VendorOrderID: afsOrder.VendorOrderID, + VendorStoreID: afsOrder.VendorStoreID, + StoreID: int(utils.Str2Int64WithDefault(afsOrder.VendorStoreID, 0)), + AfsCreatedAt: afsOrder.AfsCreatedAt, + + VendorStatus: afsOrder.VendorStatus, + VendorReasonType: afsOrder.VendorReasonType, + ReasonType: int8(utils.Str2Int64WithDefault(afsOrder.VendorReasonType, 0)), + ReasonDesc: utils.LimitUTF8StringLen(afsOrder.ReasonDesc, 1024), + ReasonImgList: afsOrder.ReasonImgList, + VendorAppealType: afsOrder.VendorAppealType, + AppealType: int8(utils.Str2Int64WithDefault(afsOrder.VendorAppealType, 0)), + Flag: model.OrderFlagMaskTempJX, + } + outAfsOrder.Status = int(utils.Str2Int64WithDefault(afsOrder.VendorStatus, 0)) + + for _, x := range afsOrder.Skus { + orderSku := &model.OrderSkuFinancial{ + Count: x.Count, + VendorSkuID: x.VendorSkuID, + SkuID: int(utils.Str2Int64WithDefault(x.VendorSkuID, 0)), + Name: x.Name, + } + if x.PromotionType != 0 && x.PromotionType != jdapi.PromotionTypeNormal { + orderSku.StoreSubName = utils.Int2Str(x.PromotionType) + } + outAfsOrder.Skus = append(outAfsOrder.Skus, orderSku) + } + } + return outAfsOrder, err +} + +func callbackAfsMsg2Status(msg *CallbackMsg) *model.OrderStatus { + orderStatus := &model.OrderStatus{ + VendorOrderID: msg.ThingID2, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中 + VendorID: model.VendorIDJX, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: msg.ThingID, + RefVendorID: model.VendorIDJX, + VendorStatus: msg.SubMsgType, + Status: int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)), + StatusTime: utils.Timestamp2Time(msg.Timestamp), + Remark: "", + } + return orderStatus +} + +func onAfsOrderMsg(msg *CallbackMsg) (err error) { + subMsgType := int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)) + status := callbackAfsMsg2Status(msg) + if subMsgType == model.AfsOrderStatusWait4Approve || subMsgType == model.AfsOrderStatusNew { + afsOrder, err2 := buildAfsOrder(msg) + if err = err2; err == nil { + err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, status) + } + } else { + err = partner.CurOrderManager.OnOrderStatusChanged("", status) + } + return err +} + +func postFakeAfsMsg(orderNo, afsOrderID string, status int) { + msg := &CallbackMsg{ + AppKey: appKey, + MsgType: MsgTypeAfsOrder, + SubMsgType: utils.Int2Str(status), + ThingID: orderNo, + ThingID2: afsOrderID, + Timestamp: time.Now().Unix(), + } + utils.CallFuncAsync(func() { + OnCallbackMsg(msg) + }) +} + +func NotifyAfsOrderStatusChanged(order *model.AfsOrder, status int) (err error) { + orderMsg := *order + orderMsg.Status = status + if err = jxAPI.NotifyAfsOrderStatusChanged(&orderMsg); err == nil { + postFakeAfsMsg(orderMsg.VendorOrderID, orderMsg.AfsOrderID, orderMsg.Status) + } + return err +} diff --git a/business/partner/purchase/jx/sku.go b/business/partner/purchase/jx/sku.go new file mode 100644 index 000000000..32daa9b18 --- /dev/null +++ b/business/partner/purchase/jx/sku.go @@ -0,0 +1,82 @@ +package jx + +// 这里函数取得的信息,除了与自身实体相关的ID(比如PARENT ID),都已经转换成了本地ID了 + +import ( + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/business/partner" +) + +// func (p *PurchaseHandler) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) { +// return err +// } + +func (p *PurchaseHandler) GetAllCategories(ctx *jxcontext.Context, vendorOrgCode string) (cats []*partner.BareCategoryInfo, err error) { + return cats, err +} + +// func (p *PurchaseHandler) UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error { +// return nil +// } + +// func (p *PurchaseHandler) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error { +// return nil +// } + +// func (p *PurchaseHandler) ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error) { +// return err +// } + +func (p *PurchaseHandler) CreateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error) { + return err +} + +func (p *PurchaseHandler) UpdateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error) { + return err +} + +func (p *PurchaseHandler) DeleteCategory2(ctx *jxcontext.Context, vendorOrgCode, vendorCatID string) (err error) { + return err +} + +func (p *PurchaseHandler) ReorderCategories2(ctx *jxcontext.Context, vendorOrgCode, vendorParentCatID string, vendorCatIDList []string) (err error) { + return err +} + +// func (p *PurchaseHandler) CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) { +// return err +// } + +// func (p *PurchaseHandler) ReadSku(ctx *jxcontext.Context, vendorOrgCode, vendorSkuID string) (skuNameExt *model.SkuNameExt, err error) { +// return skuNameExt, err +// } + +// func (p *PurchaseHandler) UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) { +// return err +// } + +// func (p *PurchaseHandler) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) { +// return err +// } + +func (p *PurchaseHandler) CreateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error) { + return err +} + +func (p *PurchaseHandler) UpdateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error) { + return err +} + +func (p *PurchaseHandler) DeleteSku2(ctx *jxcontext.Context, vendorOrgCode string, sku *partner.StoreSkuInfo) (err error) { + return err +} + +func (p *PurchaseHandler) GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) { + return vendorCats, err +} + +func (p *PurchaseHandler) GetSkus(ctx *jxcontext.Context, vendorOrgCode string, skuID int, vendorSkuID string) (skuNameList []*partner.SkuNameInfo, err error) { + return skuNameList, err +} diff --git a/business/partner/purchase/jx/store.go b/business/partner/purchase/jx/store.go new file mode 100644 index 000000000..c5b1c17d5 --- /dev/null +++ b/business/partner/purchase/jx/store.go @@ -0,0 +1,44 @@ +package jx + +import ( + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/jx-callback/business/model/dao" +) + +func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string) (storeDetail *dao.StoreDetail, err error) { + return storeDetail, err +} + +// stoerIDs为nil表示所有 +func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) { + return err +} + +func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) { + return hint, err +} + +func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) { + return storeStatus, err +} + +func (p *PurchaseHandler) EnableAutoAcceptOrder(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, isSetEnable bool) (err error) { + return err +} + +func (c *PurchaseHandler) UpdateStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, status int) (err error) { + return err +} + +func (c *PurchaseHandler) UpdateStoreOpTime(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, opTimeList []int16) (err error) { + return err +} + +func (c *PurchaseHandler) GetAllStoresVendorID(ctx *jxcontext.Context, vendorOrgCode string) (vendorStoreIDs []string, err error) { + return vendorStoreIDs, err +} + +func (c *PurchaseHandler) UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string, storeID int64) (err error) { + return err +} diff --git a/business/partner/purchase/jx/store_sku2.go b/business/partner/purchase/jx/store_sku2.go new file mode 100644 index 000000000..b9d87af6a --- /dev/null +++ b/business/partner/purchase/jx/store_sku2.go @@ -0,0 +1,36 @@ +package jx + +import ( + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/jx-callback/business/partner" +) + +func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) { + batchSize = 1 + return batchSize +} + +func (p *PurchaseHandler) GetStoreSkusBareInfo(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*partner.StoreSkuInfo) (outStoreSkuList []*partner.StoreSkuInfo, err error) { + return outStoreSkuList, err +} + +func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (successList []*partner.StoreSkuInfo, err error) { + return successList, err +} + +func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { + return successList, err +} + +func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { + return successList, err +} + +func (p *PurchaseHandler) CreateStoreSkusAct(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { + return failedList, err +} + +func (p *PurchaseHandler) CancelActs(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { + return failedList, err +} diff --git a/business/partner/putils/store_sku.go b/business/partner/putils/store_sku.go new file mode 100644 index 000000000..6a93f73c7 --- /dev/null +++ b/business/partner/putils/store_sku.go @@ -0,0 +1,304 @@ +package putils + +import ( + "fmt" + "sort" + "time" + + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/jx-callback/business/partner" +) + +type DefSingleStorePlatform struct { + partner.ISingleStoreStoreSkuHandler +} + +func (p *DefSingleStorePlatform) DeleteStoreAllSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, isContinueWhenError bool) (err error) { + skuNameList, err := p.GetStoreSkusFullInfo(ctx, parentTask, storeID, vendorStoreID, nil) + if err != nil || len(skuNameList) == 0 { + return err + } + storeStoreList := make([]*partner.StoreSkuInfo, len(skuNameList)) + for k, v := range skuNameList { + storeStoreList[k] = &partner.StoreSkuInfo{ + SkuID: v.SkuList[0].SkuID, + VendorSkuID: v.SkuList[0].VendorSkuID, + } + } + _, err = FreeBatchStoreSkuInfo("删除门店商品", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { + _, err = p.DeleteStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList) + return nil, 0, err + }, ctx, parentTask, storeStoreList, p.GetStoreSkusBatchSize(partner.FuncDeleteStoreSkus), isContinueWhenError) + return err +} + +func (p *DefSingleStorePlatform) DeleteStoreAllCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, isContinueWhenError bool) (err error) { + catList, err := p.GetStoreAllCategories(ctx, storeID, vendorStoreID) + if err != nil { + return err + } + catListMap := make(map[int][]*partner.BareCategoryInfo) + flattedCatList := flatCatList(catList) + for _, v := range flattedCatList { + catListMap[v.Level] = append(catListMap[v.Level], v) + } + var levelList []int + for k := range catListMap { + levelList = append(levelList, k) + } + sort.Sort(sort.Reverse(sort.IntSlice(levelList))) + task1 := tasksch.NewSeqTask2(fmt.Sprintf("DeleteStoreAllCategories1, vendorStoreID:%s", vendorStoreID), ctx, true, + func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { + vendorCatIDs := make([]string, len(catListMap[levelList[step]])) + for k, v := range catListMap[levelList[step]] { + vendorCatIDs[k] = v.VendorCatID + } + err = FreeBatchCategoryIDOp(func(vendorCatID string) (err error) { + err2 := p.DeleteStoreCategory(ctx, storeID, vendorStoreID, vendorCatID, step) + return err2 + }, ctx, task, vendorCatIDs, isContinueWhenError) + return nil, err + }, len(levelList)) + tasksch.HandleTask(task1, parentTask, true).Run() + _, err = task1.GetResult(0) + return err +} + +func flatCatList(catList []*partner.BareCategoryInfo) (flattedCatList []*partner.BareCategoryInfo) { + flattedCatList = append(flattedCatList, catList...) + for _, v := range catList { + flattedCatList = append(flattedCatList, flatCatList(v.Children)...) + } + return flattedCatList +} + +func (p *DefSingleStorePlatform) GetStoreSkusBareInfo(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*partner.StoreSkuInfo) (outStoreSkuList []*partner.StoreSkuInfo, err error) { + resultList, err := FreeBatchStoreSkuInfo("获取门店商品信息", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { + result, err = p.GetStoreSkusFullInfo(ctx, parentTask, storeID, vendorStoreID, batchedStoreSkuList) + return result, successCount, err + }, ctx, parentTask, inStoreSkuList, p.GetStoreSkusBatchSize(partner.FuncGetStoreSkusFullInfo), true) + if err != nil || len(resultList) == 0 { + return nil, err + } + inStoreSkuMap := make(map[string]*partner.StoreSkuInfo) + for _, v := range inStoreSkuList { + if v.VendorSkuID != "" { + inStoreSkuMap[v.VendorNameID] = v + } + } + for _, v := range resultList { + skuName := v.(*partner.SkuNameInfo) + for _, v2 := range skuName.SkuList { + storeSkuBareInfo := &v2.StoreSkuInfo + if storeSkuBareInfo.SkuID == 0 && inStoreSkuMap[storeSkuBareInfo.VendorSkuID] != nil { + storeSkuBareInfo.SkuID = inStoreSkuMap[storeSkuBareInfo.VendorSkuID].SkuID + storeSkuBareInfo.NameID = inStoreSkuMap[storeSkuBareInfo.VendorSkuID].NameID + } + outStoreSkuList = append(outStoreSkuList, storeSkuBareInfo) + } + } + return outStoreSkuList, err +} + +func StoreSkuFullList2Bare(storeSkuFull []*partner.SkuNameInfo) (bareStoreSkuList []*partner.StoreSkuInfo) { + for _, v := range storeSkuFull { + for _, v2 := range v.SkuList { + bareStoreSkuList = append(bareStoreSkuList, &v2.StoreSkuInfo) + } + } + return bareStoreSkuList +} + +func findCategoryByName(catList []*partner.BareCategoryInfo, catName string) (cat *partner.BareCategoryInfo) { + catName2 := utils.FilterEmoji(catName) + for _, v := range catList { + if v.Name == catName || v.Name == catName2 { + cat = v + break + } + if cat = findCategoryByName(v.Children, catName); cat != nil { + break + } + } + return cat +} +func (p *DefSingleStorePlatform) GetStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, catName string) (cat *partner.BareCategoryInfo, err error) { + catList, err := p.GetStoreAllCategories(ctx, storeID, vendorStoreID) + if err == nil { + if cat = findCategoryByName(catList, catName); cat == nil { + err = fmt.Errorf("门店:%d,%s不能找到商家分类:%s", storeID, vendorStoreID, catName) + } + } + return cat, err +} + +func FreeBatchStoreSkuInfo(name string, handler func(tasksch.ITask, []*partner.StoreSkuInfo) (interface{}, int, error), ctx *jxcontext.Context, parentTask tasksch.ITask, storeSkuList []*partner.StoreSkuInfo, batchSize int, isContinueWhenError bool) (resultList []interface{}, err error) { + if true { //len(storeSkuList) > batchSize { + task := tasksch.NewParallelTask2(fmt.Sprintf("FreeBatchStoreSkuInfo:%s", name), tasksch.NewParallelConfig().SetParallelCount(1).SetBatchSize(batchSize).SetIsContinueWhenError(isContinueWhenError), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, successCount int, err error) { + batchStoreSkuList := make([]*partner.StoreSkuInfo, len(batchItemList)) + for k, v := range batchItemList { + batchStoreSkuList[k] = v.(*partner.StoreSkuInfo) + } + retVal, successCount, err = handler(task, batchStoreSkuList) + if err != nil { + retVal = nil + } + return retVal, successCount, err + }, storeSkuList) + tasksch.HandleTask(task, parentTask, false).Run() + resultList, err = task.GetResult(0) + } else { + result, _, err2 := handler(parentTask, storeSkuList) + if err = err2; err == nil { + resultList = utils.Interface2Slice(result) + } + } + return resultList, err +} + +func FreeBatchCategoryIDOp(handler func(vendorCatID string) (err error), ctx *jxcontext.Context, parentTask tasksch.ITask, vendorCatIDs []string, isContinueWhenError bool) (err error) { + if len(vendorCatIDs) > 1 { + task := tasksch.NewParallelTask("FreeBatchCategoryIDOp", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + err = handler(batchItemList[0].(string)) + return nil, err + }, vendorCatIDs) + tasksch.HandleTask(task, parentTask, false).Run() + _, err = task.GetResult(0) + } else if len(vendorCatIDs) > 0 { + err = handler(vendorCatIDs[0]) + } + return err +} + +func StoreSkuList2MapByVendorSkuID(storeSkuList []*partner.StoreSkuInfo) (storeSkuMap map[string]*partner.StoreSkuInfo) { + storeSkuMap = make(map[string]*partner.StoreSkuInfo) + for _, v := range storeSkuList { + storeSkuMap[v.VendorSkuID] = v + } + return storeSkuMap +} + +func StoreSkuList2MapBySkuID(storeSkuList []*partner.StoreSkuInfo) (storeSkuMap map[int]*partner.StoreSkuInfo) { + storeSkuMap = make(map[int]*partner.StoreSkuInfo) + for _, v := range storeSkuList { + storeSkuMap[v.SkuID] = v + } + return storeSkuMap +} + +func StoreSkuList2IDs(storeSkuList []*partner.StoreSkuInfo) (ids []int) { + ids = make([]int, len(storeSkuList)) + for k, v := range storeSkuList { + ids[k] = v.SkuID + } + return ids +} + +func UnselectStoreSkuListByVendorSkuIDs(storeSkuList []*partner.StoreSkuInfo, vendorSkuIDs []string) (selectedStoreSkuList []*partner.StoreSkuInfo) { + if len(vendorSkuIDs) > 0 { + vendorSkuIDMap := jxutils.StringList2Map(vendorSkuIDs) + for _, v := range storeSkuList { + if vendorSkuIDMap[v.VendorSkuID] == 0 { + selectedStoreSkuList = append(selectedStoreSkuList, v) + } + } + } else { + selectedStoreSkuList = storeSkuList + } + return selectedStoreSkuList +} + +func GetErrMsg2FailedSingleList(storeSkuList interface{}, err error, storeID int, vendorName, syncType string) (failedList []*partner.StoreSkuInfoWithErr) { + + return failedList +} + +func UnselectStoreSkuListBySkuIDs(storeSkuList []*partner.StoreSkuInfo, skuIDs []int) (selectedStoreSkuList []*partner.StoreSkuInfo) { + if len(skuIDs) > 0 { + skuIDMap := jxutils.IntList2Map(skuIDs) + for _, v := range storeSkuList { + if skuIDMap[v.SkuID] == 0 { + selectedStoreSkuList = append(selectedStoreSkuList, v) + } + } + } else { + selectedStoreSkuList = storeSkuList + } + return selectedStoreSkuList +} + +func GenPartialFailedErr(failedInfo interface{}, failedCount int) (err error) { + if failedCount > 0 { + err = fmt.Errorf("部分失败了%d个:%s", failedCount, utils.Format4Output(failedInfo, true)) + } + return err +} + +func StoreSku2ActStoreSku(syncStatus int8, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (actStoreSku []*model.ActStoreSku2) { + for _, v := range storeSkuList { + actStoreSku = append(actStoreSku, &model.ActStoreSku2{ + ActStoreSku: model.ActStoreSku{ + SkuID: v.SkuID, + Stock: 200, + }, + VendorStoreID: vendorStoreID, + VendorSkuID: v.VendorSkuID, + VendorActID: v.VendorActID, + ActualActPrice: v.ActPrice, + SyncStatus: syncStatus, + }) + } + return actStoreSku +} + +func UpdateStoreSkuByActStoreSku(storeSkuList []*partner.StoreSkuInfo, actStoreSku []*model.ActStoreSku2) []*partner.StoreSkuInfo { + storeSkuMap := StoreSkuList2MapBySkuID(storeSkuList) + for _, v := range actStoreSku { + if storeSku := storeSkuMap[v.SkuID]; storeSku != nil { + storeSku.VendorActID = v.VendorActID + } + } + return storeSkuList +} + +func GetFixDirectDownAct(vendorOrgCode string, storeID, skuID int) (act *model.Act2) { + name := fmt.Sprintf("自动直降活动%d:%d:%d", storeID, skuID, time.Now().Unix()) + act = &model.Act2{ + Act: model.Act{ + Name: name, + Advertising: name, + Type: model.ActSkuDirectDown, + Status: model.ActStatusCreated, + LimitUser: 1, + LimitCount: 1, + BeginAt: utils.Time2Date(time.Now()), + EndAt: utils.Time2Date(time.Now().Add(50 * 24 * time.Hour)), // 饿百平台要求只能是2个月长的活动 + }, + VendorOrgCode: vendorOrgCode, + } + return act +} + +func StoreSkuInfoWithErrList2SkuIDs(list []*partner.StoreSkuInfoWithErr) (skuIDs []int) { + for _, v := range list { + if v.StoreSkuInfo != nil && v.StoreSkuInfo.SkuID > 0 { + skuIDs = append(skuIDs, v.StoreSkuInfo.SkuID) + } + } + return skuIDs +} + +func StoreSkuInfoWithErrList2MapBySku(list []*partner.StoreSkuInfoWithErr) (mapInfo map[int]*partner.StoreSkuInfoWithErr) { + mapInfo = make(map[int]*partner.StoreSkuInfoWithErr) + for _, v := range list { + mapInfo[v.StoreSkuInfo.SkuID] = v + } + return mapInfo +} diff --git a/controllers/cms_user2.go b/controllers/cms_user2.go index a52dbf392..6d18b645a 100644 --- a/controllers/cms_user2.go +++ b/controllers/cms_user2.go @@ -5,8 +5,6 @@ import ( "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/auth2" "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" - "git.rosy.net.cn/jx-callback/business/authz" - "git.rosy.net.cn/jx-callback/business/authz/autils" "git.rosy.net.cn/jx-callback/business/jxstore/cms" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/jsonerr" @@ -85,178 +83,6 @@ func (c *User2Controller) GetUsers() { }) } -// @Title 得到用户自己的门店列表 -// @Description 得到用户自己的门店列表 -// @Param token header string true "认证token" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /GetMyStoreList [get] -func (c *User2Controller) GetMyStoreList() { - c.callGetMyStoreList(func(params *tUser2GetMyStoreListParams) (retVal interface{}, errCode string, err error) { - retVal, errCode, err = cms.GetMyStoreListNew(params.Ctx) - return retVal, errCode, err - }) -} - -// @Title 得到可用的门店角色列表 -// @Description 得到可用的门店角色列表 -// @Param token header string true "认证token" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /GetStoreRoleList [get] -func (c *User2Controller) GetStoreRoleList() { - c.callGetStoreRoleList(func(params *tUser2GetStoreRoleListParams) (retVal interface{}, errCode string, err error) { - retVal, err = cms.GetStoreRoleList(params.Ctx) - return retVal, "", err - }) -} - -// @Title 得到用户所具有的角色列表 -// @Description 得到用户所具有的角色列表 -// @Param token header string true "认证token" -// @Param userID query string true "用户i" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /GetUserRoleList [get] -func (c *User2Controller) GetUserRoleList() { - c.callGetUserRoleList(func(params *tUser2GetUserRoleListParams) (retVal interface{}, errCode string, err error) { - retVal, err = cms.GetUserRoleList(params.Ctx, params.UserID) - return retVal, "", err - }) -} - -// @Title 得到角色包括的用户列表 -// @Description 得到角色包括的用户列表 -// @Param token header string true "认证token" -// @Param roleName query string true "角色名" -// @Param storeID query int false "门店ID(如果是全局角色不用填)" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /GetRoleUserList [get] -func (c *User2Controller) GetRoleUserList() { - c.callGetRoleUserList(func(params *tUser2GetRoleUserListParams) (retVal interface{}, errCode string, err error) { - retVal, err = cms.GetRoleUserList(params.Ctx, autils.NewRole(params.RoleName, params.StoreID)) - return retVal, "", err - }) -} - -// @Title 批量得到角色包括的用户列表 -// @Description 批量得到角色包括的用户列表 -// @Param token header string true "认证token" -// @Param roleNames query string true "角色名" -// @Param storeIDs query string false "门店ID(如果是全局角色不用填)" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /GetRolesUserList [get] -func (c *User2Controller) GetRolesUserList() { - c.callGetRolesUserList(func(params *tUser2GetRolesUserListParams) (retVal interface{}, errCode string, err error) { - var roleNames []string - var storeIDs []int - if err = jxutils.Strings2Objs(params.RoleNames, &roleNames, params.StoreIDs, &storeIDs); err == nil { - var roleList []*authz.RoleInfo - for _, roleName := range roleNames { - if roleName == authz.StoreRoleBoss { - for _, storeID := range storeIDs { - roleList = append(roleList, autils.NewRole(roleName, storeID)) - } - } else { - roleList = append(roleList, autils.NewRole(roleName, 0)) - } - } - retVal, err = cms.GetRolesUserList(params.Ctx, roleList) - } - return retVal, "", err - }) -} - -// @Title 给指定用户添加角色列表 -// @Description 给指定用户添加角色列表 -// @Param token header string true "认证token" -// @Param userID formData string true "用户ID" -// @Param roleList formData string true "角色列表" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /AddRoles4User [post] -func (c *User2Controller) AddRoles4User() { - c.callAddRoles4User(func(params *tUser2AddRoles4UserParams) (retVal interface{}, errCode string, err error) { - var roleList []*authz.RoleInfo - if err = jxutils.Strings2Objs(params.RoleList, &roleList); err == nil { - err = cms.AddRoles4User(params.Ctx, params.UserID, roleList) - } - return retVal, "", err - }) -} - -// @Title 给指定用户删除角色列表 -// @Description 给指定用户删除角色列表 -// @Param token header string true "认证token" -// @Param userID query string true "用户ID" -// @Param roleList query string true "角色列表" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /DeleteRoles4User [delete] -func (c *User2Controller) DeleteRoles4User() { - c.callDeleteRoles4User(func(params *tUser2DeleteRoles4UserParams) (retVal interface{}, errCode string, err error) { - var roleList []*authz.RoleInfo - if err = jxutils.Strings2Objs(params.RoleList, &roleList); err == nil { - err = cms.DeleteRoles4User(params.Ctx, params.UserID, roleList) - } - return retVal, "", err - }) -} - -// @Title 给指定角色添加用户列表 -// @Description 给指定角色添加用户列表 -// @Param token header string true "认证token" -// @Param roleName formData string true "角色名" -// @Param storeID formData int false "门店ID" -// @Param userIDs formData string true "用户ID列表" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /AddUsers4Role [post] -func (c *User2Controller) AddUsers4Role() { - c.callAddUsers4Role(func(params *tUser2AddUsers4RoleParams) (retVal interface{}, errCode string, err error) { - var userIDs []string - if err = jxutils.Strings2Objs(params.UserIDs, &userIDs); err == nil { - err = cms.AddUsers4Role(params.Ctx, autils.NewRole(params.RoleName, params.StoreID), userIDs) - } - return retVal, "", err - }) -} - -// @Title 给指定角色删除用户列表 -// @Description 给指定角色删除用户列表 -// @Param token header string true "认证token" -// @Param roleName query string true "角色名" -// @Param storeID query int false "门店ID" -// @Param userIDs query string true "用户ID列表" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /DeleteUsers4Role [delete] -func (c *User2Controller) DeleteUsers4Role() { - c.callDeleteUsers4Role(func(params *tUser2DeleteUsers4RoleParams) (retVal interface{}, errCode string, err error) { - var userIDs []string - if err = jxutils.Strings2Objs(params.UserIDs, &userIDs); err == nil { - err = cms.DeleteUsers4Role(params.Ctx, autils.NewRole(params.RoleName, params.StoreID), userIDs) - } - return retVal, "", err - }) -} - -// @Title 给指定角色添加用户列表 -// @Description 给指定角色添加用户列表 -// @Param token header string true "认证token" -// @Param mobile formData string false "手机号" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /TransferLegacyWeixins [post] -func (c *User2Controller) TransferLegacyWeixins() { - c.callTransferLegacyWeixins(func(params *tUser2TransferLegacyWeixinsParams) (retVal interface{}, errCode string, err error) { - err = cms.TransferLegacyWeixins(params.Mobile) - return retVal, "", err - }) -} - // @Title 用户自己增加配送地址 // @Description 用户自己增加配送地址 // @Param token header string true "认证token" @@ -438,21 +264,6 @@ func (c *Auth2Controller) UpdateUserByMiniInfo() { }) } -// @Title 查找京东用户 -// @Description 查找京东用户 -// @Param token header string true "认证token" -// @Param isAsync formData bool false "是否异步操作" -// @Param isContinueWhenError formData bool false "单个同步失败是否继续,缺省false" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /GetJdUsers [post] -func (c *User2Controller) GetJdUsers() { - c.callGetJdUsers(func(params *tUser2GetJdUsersParams) (retVal interface{}, errCode string, err error) { - retVal, err = cms.GetJdUsers(params.Ctx, params.IsAsync, params.IsContinueWhenError) - return retVal, "", err - }) -} - // @Title 更新用户分成比例 // @Description 更新用户分成比例 // @Param token header string true "认证token" @@ -486,20 +297,6 @@ func (c *User2Controller) DeleteUserInfo() { }) } -// @Title 得到用户自己的门店列表(商城用) -// @Description 得到用户自己的门店列表(商城用) -// @Param token header string false "认证token" -// @Param mobile query string true "电话" -// @Success 200 {object} controllers.CallResult -// @Failure 200 {object} controllers.CallResult -// @router /GetMyJxStoreList [get] -func (c *User2Controller) GetMyJxStoreList() { - c.callGetMyJxStoreList(func(params *tUser2GetMyJxStoreListParams) (retVal interface{}, errCode string, err error) { - retVal, err = cms.GetMyJxStoreList(params.Ctx, params.Mobile) - return retVal, "", err - }) -} - // @Title 插入用户协议表 // @Description 插入用户协议表 // @Param token header string false "认证token" diff --git a/main.go b/main.go index ca0137693..db6338b80 100644 --- a/main.go +++ b/main.go @@ -17,16 +17,6 @@ import ( "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/beegodb" - _ "git.rosy.net.cn/jx-callback/business/partner/printer/feie" - _ "git.rosy.net.cn/jx-callback/business/partner/printer/xiaowm" - _ "git.rosy.net.cn/jx-callback/business/partner/printer/yilianyun" - _ "git.rosy.net.cn/jx-callback/business/partner/printer/zhongwu" - - _ "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai" - _ "git.rosy.net.cn/jx-callback/business/partner/purchase/jd" - _ "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm" - _ "git.rosy.net.cn/jx-callback/business/partner/purchase/weimob/wsc" - _ "git.rosy.net.cn/jx-callback/business/auth2/authprovider/alipay" _ "git.rosy.net.cn/jx-callback/business/auth2/authprovider/dingding" _ "git.rosy.net.cn/jx-callback/business/auth2/authprovider/mobile" diff --git a/routers/commentsRouter_controllers.go b/routers/commentsRouter_controllers.go index 779b75c2a..5f14df485 100644 --- a/routers/commentsRouter_controllers.go +++ b/routers/commentsRouter_controllers.go @@ -223,357 +223,6 @@ func init() { Filters: nil, Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "AutoFocusStoreSkusForTopSkus", - Router: `/AutoFocusStoreSkusForTopSkus`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "BackUpStoreSkuBind", - Router: `/BackUpStoreSkuBind`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "CopyStoreSkus", - Router: `/CopyStoreSkus`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "CreateSkusAndFocusFromWx", - Router: `/CreateSkusAndFocusFromWx`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "CreateSkusAndFocusFromYb", - Router: `/CreateSkusAndFocusFromYb`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "FocusStoreSkusByExcel", - Router: `/FocusStoreSkusByExcel`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "FocusStoreSkusBySku", - Router: `/FocusStoreSkusBySku`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetMissingStoreSkuFromOrder", - Router: `/GetMissingStoreSkuFromOrder`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetSpecialtyStoreSkus", - Router: `/GetSpecialtyStoreSkus`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetStoreAbnormalSkuCount", - Router: `/GetStoreAbnormalSkuCount`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetStoreCategories", - Router: `/GetStoreCategories`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetStoreSkuAudit", - Router: `/GetStoreSkuAudit`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetStoreSkus", - Router: `/GetStoreSkus`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetStoresSkus", - Router: `/GetStoresSkus`, - AllowHTTPMethods: []string{"get","post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetStoresSkusSaleInfo", - Router: `/GetStoresSkusSaleInfo`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetTopCategoriesByStoreIDs", - Router: `/GetTopCategoriesByStoreIDs`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetTopSkusByCityCode", - Router: `/GetTopSkusByCityCode`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetTopSkusByStoreIDs", - Router: `/GetTopSkusByStoreIDs`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetVendorStoreSkuPrice", - Router: `/GetVendorStoreSkuPrice`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "GetVendorStoreSkusInfo", - Router: `/GetVendorStoreSkusInfo`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "RefershStoreSkusMidPrice", - Router: `/RefershStoreSkusMidPrice`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "RefreshJxPriceByExcel", - Router: `/RefreshJxPriceByExcel`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "RefreshJxPriceByVendor", - Router: `/RefreshJxPriceByVendor`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "RefreshJxPriceByVendor2", - Router: `/RefreshJxPriceByVendor2`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "RefreshMatterStock", - Router: `/RefreshMatterStock`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "RefreshStoresSkuByVendor", - Router: `/RefreshStoresSkuByVendor`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "ReturnStoreSkuBind", - Router: `/ReturnStoreSkuBind`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "SendSeckillSkusCountMsg", - Router: `/SendSeckillSkusCountMsg`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "StoreSkuPriceAudit", - Router: `/StoreSkuPriceAudit`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "SyncJdStoreProducts", - Router: `/SyncJdStoreProducts`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "SyncMatterC4ToGy", - Router: `/SyncMatterC4ToGy`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "SyncStoresSkus", - Router: `/SyncStoresSkus`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "UpdateStoreSku", - Router: `/UpdateStoreSku`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "UpdateStoreSkus", - Router: `/UpdateStoreSkus`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "UpdateStoreSkusSpecTag", - Router: `/UpdateStoreSkusSpecTag`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "UpdateStoresSkus", - Router: `/UpdateStoresSkus`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "UpdateStoresSkusByBind", - Router: `/UpdateStoresSkusByBind`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "UpdateStoresSkusSale", - Router: `/UpdateStoresSkusSale`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], - beego.ControllerComments{ - Method: "UpdateStoresSkusWithoutSync", - Router: `/UpdateStoresSkusWithoutSync`, - AllowHTTPMethods: []string{"put"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TaskController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TaskController"], beego.ControllerComments{ Method: "CancelTask", @@ -610,24 +259,6 @@ func init() { Filters: nil, Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "AddRoles4User", - Router: `/AddRoles4User`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "AddUsers4Role", - Router: `/AddUsers4Role`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], beego.ControllerComments{ Method: "CreateUserAgreement", @@ -646,15 +277,6 @@ func init() { Filters: nil, Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "DeleteRoles4User", - Router: `/DeleteRoles4User`, - AllowHTTPMethods: []string{"delete"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], beego.ControllerComments{ Method: "DeleteUserInfo", @@ -664,15 +286,6 @@ func init() { Filters: nil, Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "DeleteUsers4Role", - Router: `/DeleteUsers4Role`, - AllowHTTPMethods: []string{"delete"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], beego.ControllerComments{ Method: "GetBindAuthInfo", @@ -682,51 +295,6 @@ func init() { Filters: nil, Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "GetJdUsers", - Router: `/GetJdUsers`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "GetMyJxStoreList", - Router: `/GetMyJxStoreList`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "GetMyStoreList", - Router: `/GetMyStoreList`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "GetRoleUserList", - Router: `/GetRoleUserList`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "GetRolesUserList", - Router: `/GetRolesUserList`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], beego.ControllerComments{ Method: "GetSelfInfo", @@ -736,15 +304,6 @@ func init() { Filters: nil, Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "GetStoreRoleList", - Router: `/GetStoreRoleList`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], beego.ControllerComments{ Method: "GetUserAgreement", @@ -754,15 +313,6 @@ func init() { Filters: nil, Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "GetUserRoleList", - Router: `/GetUserRoleList`, - AllowHTTPMethods: []string{"get"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], beego.ControllerComments{ Method: "GetUsers", @@ -808,15 +358,6 @@ func init() { Filters: nil, Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], - beego.ControllerComments{ - Method: "TransferLegacyWeixins", - Router: `/TransferLegacyWeixins`, - AllowHTTPMethods: []string{"post"}, - MethodParams: param.Make(), - Filters: nil, - Params: nil}) - beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], beego.ControllerComments{ Method: "UpdateMyDeliveryAddress",