diff --git a/app/admin/apis/market/marketing.go b/app/admin/apis/market/marketing.go index 11873bc..90b3db0 100644 --- a/app/admin/apis/market/marketing.go +++ b/app/admin/apis/market/marketing.go @@ -58,7 +58,7 @@ func ErpMarketingCouponCreate(c *gin.Context) { err := tools.Validate(req) //必填参数校验 if err != nil { - app.Error(c, http.StatusBadRequest, err, "参数错误:缺少必填参数") + app.Error(c, http.StatusBadRequest, err, err.Error()) return } @@ -96,7 +96,7 @@ func ErpMarketingCouponEdit(c *gin.Context) { err := tools.Validate(req) //必填参数校验 if err != nil { - app.Error(c, http.StatusBadRequest, err, "参数错误:缺少必填参数") + app.Error(c, http.StatusBadRequest, err, err.Error()) return } @@ -129,7 +129,7 @@ func ErpMarketingCouponDelete(c *gin.Context) { err := tools.Validate(req) //必填参数校验 if err != nil { - app.Error(c, http.StatusBadRequest, err, "参数错误:优惠券id为空") + app.Error(c, http.StatusBadRequest, err, err.Error()) return } @@ -162,7 +162,7 @@ func ErpMarketingCouponStart(c *gin.Context) { err := tools.Validate(req) //必填参数校验 if err != nil { - app.Error(c, http.StatusBadRequest, err, "参数错误:优惠券id为空") + app.Error(c, http.StatusBadRequest, err, err.Error()) return } @@ -174,18 +174,21 @@ func ErpMarketingCouponStart(c *gin.Context) { } var waitSendTaskList []model.CouponIssuanceTask - for _, task := range taskList { - switch task.Status { - case model.TaskInProgress: // 执行中 - app.Error(c, http.StatusInternalServerError, errors.New(fmt.Sprintf("[%s]已在执行中,请勿重复启动", task.ErpCouponName)), - fmt.Sprintf("[%s]已在执行中,请勿重复启动", task.ErpCouponName)) - return - case model.TaskCompleted: // 已完成 - app.Error(c, http.StatusInternalServerError, errors.New(fmt.Sprintf("[%s]已执行完成", task.ErpCouponName)), - fmt.Sprintf("[%s]已执行完成", task.ErpCouponName)) - return - default: - waitSendTaskList = append(waitSendTaskList, task) + + if len(taskList) != 0 { + for _, task := range taskList { + switch task.Status { + case model.TaskInProgress: // 执行中 + app.Error(c, http.StatusInternalServerError, errors.New(fmt.Sprintf("[%s]已在执行中,请勿重复启动", task.ErpCouponName)), + fmt.Sprintf("[%s]已在执行中,请勿重复启动", task.ErpCouponName)) + return + case model.TaskCompleted: // 已完成 + app.Error(c, http.StatusInternalServerError, errors.New(fmt.Sprintf("[%s]已执行完成", task.ErpCouponName)), + fmt.Sprintf("[%s]已执行完成", task.ErpCouponName)) + return + default: + waitSendTaskList = append(waitSendTaskList, task) + } } } @@ -195,9 +198,11 @@ func ErpMarketingCouponStart(c *gin.Context) { } // 更新短信和备注 - err = orm.Eloquent.Table("erp_coupon").Where("erp_coupon_id in ?", req.ErpCouponId). + err = orm.Eloquent.Table("erp_coupon").Where("id in ?", req.ErpCouponId). Updates(map[string]interface{}{ "remark": req.Remark, + "state": model.ErpCouponSending, + "start_time": time.Now(), "sms_content": req.SmsContent, "updated_at": time.Now(), }).Error diff --git a/app/admin/models/greentown_sms.go b/app/admin/models/greentown_sms.go index 203541e..7cf3df5 100644 --- a/app/admin/models/greentown_sms.go +++ b/app/admin/models/greentown_sms.go @@ -5,7 +5,6 @@ import ( "crypto/md5" "encoding/hex" "encoding/json" - "errors" "fmt" "go-admin/logger" "io" @@ -51,9 +50,9 @@ type GtSendMessageResp struct { } func GtSendMessage(phoneList []string, content string) error { - if len(phoneList) > GetSmsNumberRemaining() { // 待发送短信超出剩余可用数量 - return errors.New("短信剩余数量不足") - } + //if len(phoneList) > GetSmsNumberRemaining() { // 待发送短信超出剩余可用数量 + // return errors.New("短信剩余数量不足") + //} params := make(map[string]interface{}, 0) nowTime := time.Now() @@ -70,12 +69,12 @@ func GtSendMessage(phoneList []string, content string) error { } fmt.Println("resp:", resp) - // 更新已使用的短信数量 - err = UpdateSmsUsedCount(len(phoneList)) - if err != nil { - logger.Error("UpdateSmsUsedCount err", logger.Field("sms count", len(phoneList)), logger.Field("err", err)) - return err - } + //// 更新已使用的短信数量 + //err = UpdateSmsUsedCount(len(phoneList)) + //if err != nil { + // logger.Error("UpdateSmsUsedCount err", logger.Field("sms count", len(phoneList)), logger.Field("err", err)) + // return err + //} return nil } diff --git a/app/admin/models/marketing.go b/app/admin/models/marketing.go index 1292531..a11d302 100644 --- a/app/admin/models/marketing.go +++ b/app/admin/models/marketing.go @@ -1,12 +1,17 @@ package models import ( + "bytes" + "encoding/json" "errors" "fmt" utils "go-admin/app/admin/models/tools" orm "go-admin/common/global" "go-admin/logger" + "io/ioutil" "log" + "net/http" + "net/url" "time" ) @@ -20,8 +25,24 @@ const ( TaskInProgress = "in_progress" // 执行中 TaskCompleted = "completed" // 已完成 TaskFailed = "failed" // 发送失败 + + AccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token" + WXAppID = "wx806c079463b5b56c" + WXSecret = "cb125688bf4e482f66e8c46062d568fc" + + WxSubscribeMessage = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + TemplateId = "aP3c503T3wn-tJtpDccvxtNi7b1qjrwavFFfo-k2SAQ" + WxJumpUrl = "/pages/voucher/voucher" // 跳转微信小程序的页面路径 ) +// WxAccessToken 微信access_token +type WxAccessToken struct { + Model + Appid string `json:"appid"` // 小程序appid + AccessToken string `json:"access_token"` // 获取到的凭证 + ExpiresTime time.Time `json:"expires_time"` // 凭证有效时间 +} + // CouponIssuanceTask 优惠券发放任务表 type CouponIssuanceTask struct { Model @@ -35,21 +56,22 @@ type CouponIssuanceTask struct { // ErpCoupon 营销管理-优惠券 type ErpCoupon struct { Model - Name string `json:"name" gorm:"index"` // 优惠券名称 - Remark string `json:"remark"` // 名称备注 - Describe string `json:"describe" gorm:"type:text"` // 优惠券简介 - Rule string `json:"rule" gorm:"type:text"` // 优惠券使用规则 - CategoryNumber string `json:"category_number"` // 可以使用该优惠券的商品分类,如果为空则表示没限制 - ActiveDate uint32 `json:"active_date"` // 有效期(天) - Amount uint32 `json:"amount"` // 金额(元) - UserType uint32 `json:"user_type"` // 领取人限制:1-所有人 2-未付费用户 3-已付费用户 4-尊享会员 - Limit uint32 `json:"limit"` // 优惠券叠加限制 0-不限制;1-仅限原价购买时使用 - State uint32 `json:"state" gorm:"index"` // 当前状态 1-未开始;2-发放中;3-进行中;4-已结束;5-发放失败 - SendCount uint32 `json:"send_count"` // 已发放 - UsedCount uint32 `json:"used_count"` // 已使用 - TotalPayAmount float64 `json:"total_pay_amount"` // 支付金额(元) - PerCustomerAmount float64 `json:"per_customer_amount"` // 客单价(元) - SmsContent string `json:"sms_content" gorm:"type:text"` // 短信提示内容 + Name string `json:"name" gorm:"index"` // 优惠券名称 + Remark string `json:"remark"` // 备注 + Describe string `json:"describe" gorm:"type:text"` // 优惠券简介 + Rule string `json:"rule" gorm:"type:text"` // 优惠券使用规则 + CategoryNumber string `json:"category_number"` // 可以使用该优惠券的商品分类,如果为空则表示没限制 + ActiveDate uint32 `json:"active_date"` // 有效期(天) + Amount uint32 `json:"amount"` // 金额(元) + UserType uint32 `json:"user_type"` // 领取人限制:1-所有人 2-未付费用户 3-已付费用户 4-尊享会员 + Limit uint32 `json:"limit"` // 优惠券叠加限制 0-不限制;1-仅限原价购买时使用 + StartTime *time.Time `json:"start_time"` // 启动时间 + State uint32 `json:"state" gorm:"index"` // 当前状态 1-未开始;2-发放中;3-进行中;4-已结束;5-发放失败 + SendCount uint32 `json:"send_count"` // 已发放 + UsedCount uint32 `json:"used_count"` // 已使用 + TotalPayAmount float64 `json:"total_pay_amount"` // 支付金额(元) + PerCustomerAmount float64 `json:"per_customer_amount"` // 客单价(元) + SmsContent string `json:"sms_content" gorm:"type:text"` // 短信提示内容 } // ErpMarketingCouponListReq 优惠券列表入参 @@ -75,7 +97,7 @@ type ErpMarketingCouponListResp struct { // ErpMarketingCouponCreateReq 新增优惠券入参 type ErpMarketingCouponCreateReq struct { Name string `json:"name" validate:"required"` // 优惠券名称 - Remark string `json:"remark"` // 名称备注 + Remark string `json:"remark"` // 备注 Describe string `json:"describe" gorm:"type:text"` // 优惠券简介 Rule string `json:"rule" gorm:"type:text"` // 优惠券使用规则 CategoryNumber string `json:"category_number" validate:"required"` // 可以使用该优惠券的商品分类编号,如果为空则表示没限制 @@ -187,7 +209,7 @@ func CreateErpMarketingCoupon(req *ErpMarketingCouponCreateReq) error { Rule: req.Rule, CategoryNumber: req.CategoryNumber, ActiveDate: req.ActiveDate, - Amount: req.Amount, + Amount: req.Amount * 100, UserType: req.UserType, Limit: req.Limit, State: ErpCouponUnStarted, @@ -204,9 +226,10 @@ func CreateErpMarketingCoupon(req *ErpMarketingCouponCreateReq) error { Describe: req.Describe, Rule: req.Rule, CouponType: "deduction", - Value: req.Amount, + Value: req.Amount * 100, CategoryNumber: req.CategoryNumber, ErpCouponId: erpCoupon.ID, + ActiveEnd: Now().AddDate(0, 0, int(req.ActiveDate)), } err = orm.Eloquent.Create(coupon).Error @@ -385,10 +408,11 @@ func StartCouponIssuanceTask(req *ErpMarketingCouponStartReq, taskList []CouponI } } + var nTotalCount int // 处理任务,从上次中断的用户ID开始 for { // 查询用户ID大于 lastUserID 的用户 - users, err := getUsersAfterID(lastUserID) + users, err := getUsersAfterID(lastUserID, erpCouponList[0].UserType) if err != nil || len(users) == 0 { log.Println("没有更多用户,任务结束") break @@ -403,6 +427,7 @@ func StartCouponIssuanceTask(req *ErpMarketingCouponStartReq, taskList []CouponI // 更新任务进度:记录处理到的最后一个用户ID lastUserID = users[len(users)-1].ID + nTotalCount += len(users) //err = updateTaskProgress(req.ErpCouponId, lastUserID, err.Error()) //if err != nil { // log.Printf("更新任务进度失败: %v", err) @@ -411,7 +436,7 @@ func StartCouponIssuanceTask(req *ErpMarketingCouponStartReq, taskList []CouponI } // 任务完成,更新状态 - err = markTaskAsCompleted(req.ErpCouponId) + err = markTaskAsCompleted(req.ErpCouponId, nTotalCount) if err != nil { return nil } @@ -447,17 +472,33 @@ func GetTaskProgress(erpCouponId []uint32) ([]CouponIssuanceTask, error) { var task []CouponIssuanceTask err := orm.Eloquent.Table("coupon_issuance_task").Where("erp_coupon_id in ?", erpCouponId). Order("updated_at desc").First(&task).Error - if err != nil { + if err != nil && err.Error() != "record not found" { return nil, err } return task, nil } -func getUsersAfterID(lastUserID uint32) ([]UserInfo, error) { +func getUsersAfterID(lastUserID, userType uint32) ([]UserInfo, error) { + var err error var users []UserInfo - err := orm.Eloquent.Model(&UserInfo{}).Where("id > ? ", lastUserID). - Order("id asc").Limit(100).Find(&users).Error + + switch userType { + case 2: // 2-未付费用户:MemberLevel 不能是 (2, 3, 4, 5) + err = orm.Eloquent.Model(&UserInfo{}).Where("id > ? and member_level not in ?", lastUserID, []uint32{ + MemberLevelGold, MemberLevelPeriod, MemberLevelPlatinum, MemberLevelBlackGold}). + Order("id asc").Limit(100).Find(&users).Error + case 3: + // 3-已付费用户:MemberLevel 必须是 (2, 3, 4, 5) + err = orm.Eloquent.Model(&UserInfo{}).Where("id > ? and member_level in ?", lastUserID, []uint32{ + MemberLevelGold, MemberLevelPeriod, MemberLevelPlatinum, MemberLevelBlackGold}). + Order("id asc").Limit(100).Find(&users).Error + case 1: // 1-所有人:不限制会员等级,所有人均可领取 + default: + err = orm.Eloquent.Model(&UserInfo{}).Where("id > ?", lastUserID). + Order("id asc").Limit(100).Find(&users).Error + } + if err != nil { return nil, err } @@ -477,7 +518,7 @@ func updateTaskProgress(erpCouponId []uint32, lastUserID uint32, errMsg string) return nil } -func markTaskAsCompleted(erpCouponId []uint32) error { +func markTaskAsCompleted(erpCouponId []uint32, nTotalCount int) error { err := orm.Eloquent.Table("coupon_issuance_task").Where("erp_coupon_id in ?", erpCouponId). Updates(map[string]interface{}{ "Status": TaskCompleted, @@ -488,6 +529,17 @@ func markTaskAsCompleted(erpCouponId []uint32) error { return err } + err = orm.Eloquent.Table("erp_coupon").Where("id in ?", erpCouponId). + Updates(map[string]interface{}{ + "state": ErpCouponInProgress, + "send_count": nTotalCount, + "updated_at": time.Now(), + }).Error + if err != nil { + log.Printf("更新任务完成状态失败: %v", err) + return err + } + log.Println("任务完成") return nil } @@ -550,7 +602,7 @@ func issueCouponsToUsers(users []UserInfo, erpCouponId []uint32) error { Value: coupon.Value, State: 1, ActiveStart: time.Now(), - ActiveEnd: time.Now().AddDate(0, 0, 7), + ActiveEnd: coupon.ActiveEnd, RedeemCode: "", CategoryNumber: coupon.CategoryNumber, Code: couponCode, @@ -567,12 +619,192 @@ func issueCouponsToUsers(users []UserInfo, erpCouponId []uint32) error { } } - // 发送短信或者消息订阅通知 - err = GtSendMessage([]string{user.Tel}, erpCoupon[0].SmsContent) + // 发送订阅通知 + var wxToken WxAccessToken + err = orm.Eloquent.Table("wx_access_token").Where("appid = ?", WXAppID).First(&wxToken).Error if err != nil { - logger.Error(err.Error()) + logger.Error("query wx_access_token err:", logger.Field("err", err)) + } + + if wxToken.ID == 0 || wxToken.ExpiresTime.Before(time.Now()) { + CheckAccessToken() + + err = orm.Eloquent.Table("wx_access_token").Where("appid = ?", WXAppID).First(&wxToken).Error + if err != nil { + logger.Error("query wx_access_token err:", logger.Field("err", err)) + } + } + + toUserOpenid := user.WxOpenID + templateId := TemplateId + data := map[string]interface{}{ + "thing1": map[string]interface{}{"value": coupons[0].Name}, + "thing5": map[string]interface{}{"value": coupons[0].Describe}, + "date3": map[string]interface{}{"value": coupons[0].ActiveEnd.Format("2006年01月02日")}, + "thing4": map[string]interface{}{"value": coupons[0].Rule}, + } + //developer为开发版;trial为体验版;formal为正式版;默认为正式版 + _, err = SendMessage(wxToken.AccessToken, toUserOpenid, templateId, data, WxJumpUrl, "trial") + if err != nil { + // 如果订阅通知发送失败,则发送短信 + err = GtSendMessage([]string{user.Tel}, erpCoupon[0].SmsContent) + if err != nil { + logger.Error(err.Error()) + } } } } return nil } + +// Response 请求微信返回基础数据 +type Response struct { + Errcode int `json:"errcode"` + Errmsg string `json:"errmsg"` +} + +// AccessTokenResponse 返回给用户的数据 +type AccessTokenResponse struct { + AccessToken string `json:"access_token"` // 获取到的凭证 + ExpiresIn int64 `json:"expires_in"` // 凭证有效时间,单位:秒。目前是7200秒之内的值。 +} + +type accessTokenResponse struct { + Response + AccessTokenResponse +} + +// CheckAccessToken 定期更新access_token +func CheckAccessToken() { + accessToken, err := GetWxAccessToken() + if err != nil { + logger.Error("query wx_access_token err:", logger.Field("err", err)) + } else { + now := time.Now() + twoHoursLater := now.Add(2 * time.Hour) + + // 查询access_token + var wxToken WxAccessToken + err = orm.Eloquent.Table("wx_access_token").Where("appid = ?", WXAppID).First(&wxToken).Error + if err != nil { + logger.Error("query wx_access_token err:", logger.Field("err", err)) + } + + if wxToken.ID != 0 { // 更新 + // 更新access_token + err = orm.Eloquent.Table("wx_access_token").Where("appid = ?", WXAppID). + Updates(map[string]interface{}{ + "access_token": accessToken, + "expires_time": twoHoursLater, + }).Error + if err != nil { + logger.Errorf("更新wx_access_token失败: %v", err) + } + } else { // 插入 + tempToken := &WxAccessToken{ + Appid: WXAppID, + AccessToken: accessToken.AccessToken, + ExpiresTime: twoHoursLater, + } + err = orm.Eloquent.Create(tempToken).Error + if err != nil { + logger.Error("create wx_access_token err:", logger.Field("err", err)) + } + } + } +} + +// GetWxAccessToken 获取小程序的access_token +func GetWxAccessToken() (lures AccessTokenResponse, err error) { + api, err := code2url(WXAppID, WXSecret) + if err != nil { + return + } + + res, err := http.Get(api) + if err != nil { + return + } + defer res.Body.Close() + + if res.StatusCode != 200 { + err = errors.New("微信服务器发生错误") + return + } + + var data accessTokenResponse + err = json.NewDecoder(res.Body).Decode(&data) + if err != nil { + return + } + + if data.Errcode != 0 { + err = errors.New(data.Errmsg) + return + } + + lures = data.AccessTokenResponse + return +} + +// 拼接 获取 session_key 的 URL +func code2url(appID, secret string) (string, error) { + url, err := url.Parse(AccessTokenUrl) + if err != nil { + return "", err + } + + query := url.Query() + + query.Set("appid", appID) + query.Set("secret", secret) + query.Set("grant_type", "client_credential") + + url.RawQuery = query.Encode() + + return url.String(), nil +} + +// SendMessage 发送订阅消息 +func SendMessage(accessToken, toUserOpenid, templateId string, data interface{}, page, miniprogramState string) ( + []byte, error) { + url := fmt.Sprintf("%s%s", WxSubscribeMessage, accessToken) + body := map[string]interface{}{ + "touser": toUserOpenid, + "template_id": templateId, + "data": data, + "page": page, + "miniprogramState": miniprogramState, + "lang": "zh_CN", + } + + rsp, err := HttpRequest(http.MethodPost, url, body) + return rsp, err +} + +func HttpRequest(method, url string, reqBody interface{}) ([]byte, error) { + client := http.Client{} + reqBodyBytes, err := json.Marshal(reqBody) + if err != nil { + return nil, err + } + reqBodyReader := bytes.NewReader(reqBodyBytes) + req, err := http.NewRequest(method, url, reqBodyReader) + if err != nil { + return nil, err + } + + rsp, err := client.Do(req) + if err != nil { + return nil, err + } + defer rsp.Body.Close() + if rsp.StatusCode != 200 { + return nil, errors.New(fmt.Sprintf("response Status err:%d", rsp.StatusCode)) + } + rspBody, err := ioutil.ReadAll(rsp.Body) + if err != nil { + return nil, err + } + return rspBody, nil +} diff --git a/cmd/api/server.go b/cmd/api/server.go index fc35260..162651c 100644 --- a/cmd/api/server.go +++ b/cmd/api/server.go @@ -181,6 +181,13 @@ func run() error { if err != nil { fmt.Println("err:", err) } + + // 刷新access_token + err = s.Every(1).Hour().Do(models.CheckAccessToken) + if err != nil { + fmt.Println("err:", err) + } + <-s.Start() }() diff --git a/docs/docs.go b/docs/docs.go index efd1cdd..bf7e186 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -8982,20 +8982,20 @@ const docTemplate = `{ }, "amount": { "description": "金额(元)", - "type": "number" + "type": "integer" }, "category_number": { "description": "可以使用该优惠券的商品分类,如果为空则表示没限制", "type": "string" }, - "content": { - "description": "优惠内容", - "type": "string" - }, "createdAt": { "description": "创建时间", "type": "string" }, + "describe": { + "description": "优惠券简介", + "type": "string" + }, "id": { "description": "数据库记录编号", "type": "integer" @@ -9013,15 +9013,27 @@ const docTemplate = `{ "type": "number" }, "remark": { - "description": "名称备注", + "description": "备注", + "type": "string" + }, + "rule": { + "description": "优惠券使用规则", "type": "string" }, "send_count": { "description": "已发放", "type": "integer" }, + "sms_content": { + "description": "短信提示内容", + "type": "string" + }, + "start_time": { + "description": "启动时间", + "type": "string" + }, "state": { - "description": "当前状态 1-未开始;2-发放中;3-进行中;4-已结束", + "description": "当前状态 1-未开始;2-发放中;3-进行中;4-已结束;5-发放失败", "type": "integer" }, "total_pay_amount": { @@ -9595,14 +9607,14 @@ const docTemplate = `{ }, "amount": { "description": "金额(元)", - "type": "number" + "type": "integer" }, "category_number": { "description": "可以使用该优惠券的商品分类编号,如果为空则表示没限制", "type": "string" }, - "content": { - "description": "优惠内容/使用说明", + "describe": { + "description": "优惠券简介", "type": "string" }, "limit": { @@ -9614,7 +9626,11 @@ const docTemplate = `{ "type": "string" }, "remark": { - "description": "名称备注", + "description": "备注", + "type": "string" + }, + "rule": { + "description": "优惠券使用规则", "type": "string" }, "user_type": { @@ -9667,14 +9683,14 @@ const docTemplate = `{ }, "amount": { "description": "金额(元)", - "type": "number" + "type": "integer" }, "category_number": { "description": "可以使用该优惠券的商品分类,如果为空则表示没限制", "type": "string" }, - "content": { - "description": "优惠内容/使用说明", + "describe": { + "description": "优惠券简介", "type": "string" }, "erp_coupon_id": { @@ -9693,6 +9709,10 @@ const docTemplate = `{ "description": "名称备注", "type": "string" }, + "rule": { + "description": "优惠券使用规则", + "type": "string" + }, "user_type": { "description": "领取人限制:1-所有人 2-未付费用户 3-已付费用户 4-尊享会员", "type": "integer" @@ -9762,12 +9782,25 @@ const docTemplate = `{ "models.ErpMarketingCouponStartReq": { "type": "object", "required": [ - "erp_coupon_id" + "erp_coupon_id", + "remark", + "sms_content" ], "properties": { "erp_coupon_id": { "description": "优惠券id", - "type": "integer" + "type": "array", + "items": { + "type": "integer" + } + }, + "remark": { + "description": "活动名称备注", + "type": "string" + }, + "sms_content": { + "description": "短信提示内容", + "type": "string" } } }, diff --git a/docs/swagger.json b/docs/swagger.json index 3750f37..b12a5fa 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -8971,20 +8971,20 @@ }, "amount": { "description": "金额(元)", - "type": "number" + "type": "integer" }, "category_number": { "description": "可以使用该优惠券的商品分类,如果为空则表示没限制", "type": "string" }, - "content": { - "description": "优惠内容", - "type": "string" - }, "createdAt": { "description": "创建时间", "type": "string" }, + "describe": { + "description": "优惠券简介", + "type": "string" + }, "id": { "description": "数据库记录编号", "type": "integer" @@ -9002,15 +9002,27 @@ "type": "number" }, "remark": { - "description": "名称备注", + "description": "备注", + "type": "string" + }, + "rule": { + "description": "优惠券使用规则", "type": "string" }, "send_count": { "description": "已发放", "type": "integer" }, + "sms_content": { + "description": "短信提示内容", + "type": "string" + }, + "start_time": { + "description": "启动时间", + "type": "string" + }, "state": { - "description": "当前状态 1-未开始;2-发放中;3-进行中;4-已结束", + "description": "当前状态 1-未开始;2-发放中;3-进行中;4-已结束;5-发放失败", "type": "integer" }, "total_pay_amount": { @@ -9584,14 +9596,14 @@ }, "amount": { "description": "金额(元)", - "type": "number" + "type": "integer" }, "category_number": { "description": "可以使用该优惠券的商品分类编号,如果为空则表示没限制", "type": "string" }, - "content": { - "description": "优惠内容/使用说明", + "describe": { + "description": "优惠券简介", "type": "string" }, "limit": { @@ -9603,7 +9615,11 @@ "type": "string" }, "remark": { - "description": "名称备注", + "description": "备注", + "type": "string" + }, + "rule": { + "description": "优惠券使用规则", "type": "string" }, "user_type": { @@ -9656,14 +9672,14 @@ }, "amount": { "description": "金额(元)", - "type": "number" + "type": "integer" }, "category_number": { "description": "可以使用该优惠券的商品分类,如果为空则表示没限制", "type": "string" }, - "content": { - "description": "优惠内容/使用说明", + "describe": { + "description": "优惠券简介", "type": "string" }, "erp_coupon_id": { @@ -9682,6 +9698,10 @@ "description": "名称备注", "type": "string" }, + "rule": { + "description": "优惠券使用规则", + "type": "string" + }, "user_type": { "description": "领取人限制:1-所有人 2-未付费用户 3-已付费用户 4-尊享会员", "type": "integer" @@ -9751,12 +9771,25 @@ "models.ErpMarketingCouponStartReq": { "type": "object", "required": [ - "erp_coupon_id" + "erp_coupon_id", + "remark", + "sms_content" ], "properties": { "erp_coupon_id": { "description": "优惠券id", - "type": "integer" + "type": "array", + "items": { + "type": "integer" + } + }, + "remark": { + "description": "活动名称备注", + "type": "string" + }, + "sms_content": { + "description": "短信提示内容", + "type": "string" } } }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 99e31fb..e0e9e9b 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1728,16 +1728,16 @@ definitions: type: integer amount: description: 金额(元) - type: number + type: integer category_number: description: 可以使用该优惠券的商品分类,如果为空则表示没限制 type: string - content: - description: 优惠内容 - type: string createdAt: description: 创建时间 type: string + describe: + description: 优惠券简介 + type: string id: description: 数据库记录编号 type: integer @@ -1751,13 +1751,22 @@ definitions: description: 客单价(元) type: number remark: - description: 名称备注 + description: 备注 + type: string + rule: + description: 优惠券使用规则 type: string send_count: description: 已发放 type: integer + sms_content: + description: 短信提示内容 + type: string + start_time: + description: 启动时间 + type: string state: - description: 当前状态 1-未开始;2-发放中;3-进行中;4-已结束 + description: 当前状态 1-未开始;2-发放中;3-进行中;4-已结束;5-发放失败 type: integer total_pay_amount: description: 支付金额(元) @@ -2172,12 +2181,12 @@ definitions: type: integer amount: description: 金额(元) - type: number + type: integer category_number: description: 可以使用该优惠券的商品分类编号,如果为空则表示没限制 type: string - content: - description: 优惠内容/使用说明 + describe: + description: 优惠券简介 type: string limit: description: 优惠券叠加限制 0-不限制;1-仅限原价购买时使用 @@ -2186,7 +2195,10 @@ definitions: description: 优惠券名称 type: string remark: - description: 名称备注 + description: 备注 + type: string + rule: + description: 优惠券使用规则 type: string user_type: description: 领取人限制:1-所有人 2-未付费用户 3-已付费用户 4-尊享会员 @@ -2223,12 +2235,12 @@ definitions: type: integer amount: description: 金额(元) - type: number + type: integer category_number: description: 可以使用该优惠券的商品分类,如果为空则表示没限制 type: string - content: - description: 优惠内容/使用说明 + describe: + description: 优惠券简介 type: string erp_coupon_id: description: 优惠券id @@ -2242,6 +2254,9 @@ definitions: remark: description: 名称备注 type: string + rule: + description: 优惠券使用规则 + type: string user_type: description: 领取人限制:1-所有人 2-未付费用户 3-已付费用户 4-尊享会员 type: integer @@ -2300,9 +2315,19 @@ definitions: properties: erp_coupon_id: description: 优惠券id - type: integer + items: + type: integer + type: array + remark: + description: 活动名称备注 + type: string + sms_content: + description: 短信提示内容 + type: string required: - erp_coupon_id + - remark + - sms_content type: object models.ErpOrder: properties: diff --git a/static/导零售.xlsx b/static/导零售.xlsx new file mode 100644 index 0000000..8382a29 Binary files /dev/null and b/static/导零售.xlsx differ