1、配置文件增加消息订阅环境和短信url配置项;
2、coupon和user_coupon表增加limit字段; 3、零售开单时,如果使用优惠券,则同步更新优惠券对应的数据; 4、增加优惠券数据接口; 5、增加获取小程序跳转链接接口; 6、增加保定金自动审核的定时任务,每天早上9点30分退前一天的保证金,最多10条;
This commit is contained in:
parent
40227538f9
commit
cafc26e5bd
|
@ -226,7 +226,134 @@ func ErpMarketingCouponStart(c *gin.Context) {
|
|||
// @Success 200 {object} models.ErpMarketingCouponDataResp
|
||||
// @Router /api/v1/marketing/coupon/data [post]
|
||||
func ErpMarketingCouponData(c *gin.Context) {
|
||||
var req model.ErpMarketingCouponDataReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
app.Error(c, http.StatusBadRequest, err, "参数错误:"+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
app.OK(c, nil, "OK")
|
||||
return
|
||||
userCouponIds, err := model.GetUserCouponIdsByErpCouponId(req.ErpCouponId)
|
||||
if err != nil {
|
||||
app.Error(c, http.StatusInternalServerError, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 查询使用该优惠券的订单商品
|
||||
var orderCommodities []model.ErpOrderCommodity
|
||||
err = orm.Eloquent.Where("coupon_id in ?", userCouponIds).
|
||||
Joins("JOIN erp_order ON erp_order.id = erp_order_commodity.erp_order_id").
|
||||
Where("erp_order.state = 'audited'").Find(&orderCommodities).Error
|
||||
if err != nil {
|
||||
app.Error(c, http.StatusInternalServerError, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 初始化统计数据
|
||||
var totalAmount, totalDiscount float64
|
||||
var orderCount, customerCount, productCount int
|
||||
productsMap := make(map[uint32]model.ProductInfo)
|
||||
customers := make(map[int]bool) // 用来去重客户
|
||||
|
||||
// 统计订单数据
|
||||
for _, orderCommodity := range orderCommodities {
|
||||
// 获取订单详情
|
||||
var order model.ErpOrder
|
||||
err = orm.Eloquent.First(&order, orderCommodity.ErpOrderId).Error
|
||||
if err != nil {
|
||||
app.Error(c, http.StatusInternalServerError, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 计算用券总成交额和总优惠金额
|
||||
totalAmount += orderCommodity.ReceivedAmount
|
||||
totalDiscount += orderCommodity.CouponDiscount
|
||||
|
||||
// 计算订单数
|
||||
orderCount++
|
||||
|
||||
// 计算客户数
|
||||
if _, exists := customers[order.Uid]; !exists {
|
||||
customers[order.Uid] = true
|
||||
customerCount++
|
||||
}
|
||||
|
||||
// 计算购买商品总件数
|
||||
productCount += int(orderCommodity.Count)
|
||||
if _, exists := productsMap[orderCommodity.ErpCommodityId]; !exists {
|
||||
productsMap[orderCommodity.ErpCommodityId] = model.ProductInfo{
|
||||
ProductID: int(orderCommodity.ErpCommodityId),
|
||||
ProductName: orderCommodity.ErpCommodityName,
|
||||
PayCount: int(orderCommodity.Count),
|
||||
PayCustomer: 1,
|
||||
}
|
||||
} else {
|
||||
productInfo := productsMap[orderCommodity.ErpCommodityId]
|
||||
productInfo.PayCount += int(orderCommodity.Count)
|
||||
productInfo.PayCustomer++
|
||||
productsMap[orderCommodity.ErpCommodityId] = productInfo
|
||||
}
|
||||
}
|
||||
|
||||
// 计算费效比
|
||||
var costEffectiveness float64
|
||||
if totalAmount > 0 {
|
||||
costEffectiveness = tools.RoundFloat(totalDiscount / totalAmount)
|
||||
}
|
||||
|
||||
// 计算用券笔单价
|
||||
var unitPrice float64
|
||||
if orderCount > 0 {
|
||||
unitPrice = tools.RoundFloat(totalAmount / float64(orderCount))
|
||||
}
|
||||
|
||||
// 构造返回的数据结构
|
||||
resp := model.ErpMarketingCouponDataResp{
|
||||
TotalAmount: totalAmount,
|
||||
TotalDiscount: totalDiscount,
|
||||
CostEffectiveness: costEffectiveness,
|
||||
OrderCount: orderCount,
|
||||
UnitPrice: unitPrice,
|
||||
CustomerCount: customerCount,
|
||||
ProductCount: productCount,
|
||||
}
|
||||
|
||||
// 转换商品数据
|
||||
for _, productInfo := range productsMap {
|
||||
resp.Products = append(resp.Products, productInfo)
|
||||
}
|
||||
|
||||
// 返回结果
|
||||
app.OK(c, resp, "OK")
|
||||
}
|
||||
|
||||
// GenerateScheme 获取小程序跳转链接
|
||||
// @Summary 获取小程序跳转链接
|
||||
// @Tags 营销管理,V1.4.4
|
||||
// @Produce json
|
||||
// @Accept json
|
||||
// @Param request body models.GenerateSchemeReq true "获取小程序跳转链接模型"
|
||||
// @Success 200 {object} models.GenerateSchemeResp
|
||||
// @Router /api/v1/marketing/generateScheme [post]
|
||||
func GenerateScheme(c *gin.Context) {
|
||||
var req model.GenerateSchemeReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
app.Error(c, http.StatusBadRequest, err, "参数错误:"+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err := tools.Validate(req) //必填参数校验
|
||||
if err != nil {
|
||||
app.Error(c, http.StatusBadRequest, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := model.WXGenerateScheme(&req)
|
||||
if err != nil {
|
||||
logger.Error("WXGenerateScheme err:", logger.Field("err", err))
|
||||
app.Error(c, http.StatusInternalServerError, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 返回结果
|
||||
app.OK(c, resp, "OK")
|
||||
}
|
||||
|
|
|
@ -538,6 +538,214 @@ func ArticleDel(c *gin.Context) {
|
|||
app.OK(c, nil, "绑定店员成功")
|
||||
}
|
||||
|
||||
// AutoDepositRefund 每天早上9点30分退前一天的保证金
|
||||
func AutoDepositRefund() {
|
||||
// 查询待审核的订单
|
||||
var depositRefunds []models.DepositRefundRecord
|
||||
err := orm.Eloquent.Table("deposit_refund_record").
|
||||
Where("status = ?", models.DepositRefundStatusUnconfirmed).Order("id ASC").Limit(10).Find(&depositRefunds).Error
|
||||
if err != nil {
|
||||
logger.Error("AutoDepositRefund query deposit_refund_record err:", logger.Field("err", err))
|
||||
return
|
||||
}
|
||||
|
||||
for _, depositInfo := range depositRefunds {
|
||||
err = NotarizeUserDepositRefundByID(depositInfo.ID)
|
||||
if err.Error() == "押金退款失败,请检查余额" { // 余额不足,停止退款并发短信
|
||||
models.GtSendMessage([]string{"15019230751", "13510508605"}, "【go2ns】用户押金退款失败,请检查微信商户余额。")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NotarizeUserDepositRefundByID(depositRefundRecordId uint32) error {
|
||||
if depositRefundRecordId == 0 {
|
||||
return errors.New("invalid deposit refund record ID")
|
||||
}
|
||||
|
||||
fmt.Println("DepositRefundRecordId:", depositRefundRecordId)
|
||||
var depositRefund models.DepositRefundRecord
|
||||
err := orm.Eloquent.Table("deposit_refund_record").Where("id = ?", depositRefundRecordId).Find(&depositRefund).Error
|
||||
if err != nil {
|
||||
logger.Error("err:", logger.Field("err", err))
|
||||
return err
|
||||
}
|
||||
if depositRefund.Status != models.DepositRefundStatusUnconfirmed {
|
||||
logger.Error("status not DepositRefundStatusUnconfirmed")
|
||||
return err
|
||||
}
|
||||
|
||||
unreturnedOrders, err := models.IsUserHaveUnreturnedOrders(depositRefund.Uid)
|
||||
if err != nil {
|
||||
logger.Error("IsUserHaveUnreturnedOrders err:", logger.Field("err", err))
|
||||
return err
|
||||
}
|
||||
if unreturnedOrders {
|
||||
logger.Error("unreturnedOrders")
|
||||
return errors.New("用户有未完成订单")
|
||||
}
|
||||
|
||||
userInfo, err := models.GetUserInfoByUid(depositRefund.Uid)
|
||||
if err != nil {
|
||||
logger.Error("err:", logger.Field("err", err))
|
||||
return err
|
||||
}
|
||||
var transfer *pay.WxTransferResp
|
||||
//if userInfo.Deposit == 80 {
|
||||
nTempDeposit := userInfo.Deposit // 用户押金
|
||||
fmt.Println("******userInfo.Deposit is:******", nTempDeposit)
|
||||
if userInfo.Deposit == 60000 {
|
||||
for i := 0; i < 2; i++ {
|
||||
transfer, err = pay.Transfer(userInfo.Deposit/2, userInfo.WxOpenID, fmt.Sprintf("押金退款(共2次到账)%d/2", i+1))
|
||||
if err != nil {
|
||||
logger.Errorf("pay.Transfer 600 err, i is:", i)
|
||||
logger.Error("pay.Transfer 600 err:", logger.Field("err", err))
|
||||
|
||||
if i != 0 { // 非首次退款报错
|
||||
updateUser := map[string]interface{}{
|
||||
"deposit": nTempDeposit,
|
||||
"member_level": 1,
|
||||
}
|
||||
if userInfo.MemberExpire.After(time.Now()) {
|
||||
updateUser["member_expire"] = time.Now()
|
||||
}
|
||||
err = orm.Eloquent.Table("user").Where("uid = ?", userInfo.Uid).Updates(updateUser).Error
|
||||
if err != nil {
|
||||
logger.Error("pay.Transfer 600 update deposit err:", logger.Field("err", err))
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("押金退款失败,请检查余额")
|
||||
}
|
||||
nTempDeposit -= 300
|
||||
}
|
||||
} else if userInfo.Deposit == 150000 {
|
||||
for i := 0; i < 5; i++ {
|
||||
transfer, err = pay.Transfer(userInfo.Deposit/5, userInfo.WxOpenID, fmt.Sprintf("押金退款(共5次到账)%d/5", i+1))
|
||||
if err != nil {
|
||||
logger.Errorf("pay.Transfer 1500 err, i is:", i)
|
||||
logger.Error("pay.Transfer 1500 err:", logger.Field("err", err))
|
||||
|
||||
if i != 0 { // 非首次退款报错
|
||||
updateUser := map[string]interface{}{
|
||||
"deposit": nTempDeposit,
|
||||
"member_level": 1,
|
||||
}
|
||||
if userInfo.MemberExpire.After(time.Now()) {
|
||||
updateUser["member_expire"] = time.Now()
|
||||
}
|
||||
err = orm.Eloquent.Table("user").Where("uid = ?", userInfo.Uid).Updates(updateUser).Error
|
||||
if err != nil {
|
||||
logger.Error("pay.Transfer 1500 update deposit err:", logger.Field("err", err))
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("押金退款失败,请检查余额")
|
||||
}
|
||||
nTempDeposit -= 300
|
||||
}
|
||||
} else if userInfo.Deposit == 120000 {
|
||||
for i := 0; i < 4; i++ {
|
||||
transfer, err = pay.Transfer(userInfo.Deposit/4, userInfo.WxOpenID, fmt.Sprintf("押金退款(共4次到账)%d/4", i+1))
|
||||
if err != nil {
|
||||
logger.Errorf("pay.Transfer 1200 err, i is:", i)
|
||||
logger.Error("pay.Transfer 1200 err:", logger.Field("err", err))
|
||||
|
||||
if i != 0 { // 非首次退款报错
|
||||
updateUser := map[string]interface{}{
|
||||
"deposit": nTempDeposit,
|
||||
"member_level": 1,
|
||||
}
|
||||
if userInfo.MemberExpire.After(time.Now()) {
|
||||
updateUser["member_expire"] = time.Now()
|
||||
}
|
||||
err = orm.Eloquent.Table("user").Where("uid = ?", userInfo.Uid).Updates(updateUser).Error
|
||||
if err != nil {
|
||||
logger.Error("pay.Transfer 1200 update deposit err:", logger.Field("err", err))
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("押金退款失败,请检查余额")
|
||||
}
|
||||
nTempDeposit -= 300
|
||||
}
|
||||
} else if userInfo.Deposit == 90000 {
|
||||
for i := 0; i < 3; i++ {
|
||||
transfer, err = pay.Transfer(userInfo.Deposit/3, userInfo.WxOpenID, fmt.Sprintf("押金退款(共3次到账)%d/3", i+1))
|
||||
if err != nil {
|
||||
logger.Errorf("pay.Transfer 900 err, i is:", i)
|
||||
logger.Error("pay.Transfer 900 err:", logger.Field("err", err))
|
||||
|
||||
if i != 0 { // 非首次退款报错
|
||||
updateUser := map[string]interface{}{
|
||||
"deposit": nTempDeposit,
|
||||
"member_level": 1,
|
||||
}
|
||||
if userInfo.MemberExpire.After(time.Now()) {
|
||||
updateUser["member_expire"] = time.Now()
|
||||
}
|
||||
err = orm.Eloquent.Table("user").Where("uid = ?", userInfo.Uid).Updates(updateUser).Error
|
||||
if err != nil {
|
||||
logger.Error("pay.Transfer 900 update deposit err:", logger.Field("err", err))
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("押金退款失败,请检查余额")
|
||||
}
|
||||
nTempDeposit -= 300
|
||||
}
|
||||
} else if userInfo.Deposit == 30000 {
|
||||
transfer, err = pay.Transfer(userInfo.Deposit, userInfo.WxOpenID, "押金退款")
|
||||
if err != nil {
|
||||
logger.Error("pay.Transfer 300 err:", logger.Field("err", err))
|
||||
return errors.New("押金退款失败,请检查余额")
|
||||
}
|
||||
} else {
|
||||
logger.Errorf("押金退款失败, 押金额有误,userInfo.Deposit is:", userInfo.Deposit)
|
||||
return errors.New("押金退款失败,金额有误")
|
||||
}
|
||||
|
||||
fmt.Println("transfer:", transfer)
|
||||
updateUser := map[string]interface{}{
|
||||
"deposit": 0,
|
||||
"member_level": 1,
|
||||
}
|
||||
if userInfo.MemberExpire.After(time.Now()) {
|
||||
updateUser["member_expire"] = time.Now()
|
||||
}
|
||||
err = orm.Eloquent.Table("user").Where("uid = ?", userInfo.Uid).Updates(updateUser).Error
|
||||
if err != nil {
|
||||
logger.Error("update deposit err:", logger.Field("err", err))
|
||||
return err
|
||||
}
|
||||
|
||||
err = orm.Eloquent.Table("deposit_refund_record").Where("id = ?", depositRefund.ID).Updates(map[string]interface{}{
|
||||
"status": models.DepositRefundStatusRefunded,
|
||||
"confirm_time": time.Now(),
|
||||
}).Error
|
||||
if err != nil {
|
||||
logger.Error("update deposit refund record err:", logger.Field("err", err))
|
||||
return err
|
||||
}
|
||||
fundRecord := &models.FundRecord{
|
||||
Uid: depositRefund.Uid,
|
||||
FundType: models.FundTypeDepositRefund,
|
||||
Amount: int64(depositRefund.Amount) * (-1),
|
||||
OutTradeNo: transfer.PartnerTradeNo,
|
||||
PaymentNo: transfer.PaymentNo,
|
||||
Status: 2,
|
||||
Remark: "退还押金",
|
||||
|
||||
//TransactionId: ,
|
||||
}
|
||||
err = orm.Eloquent.Create(fundRecord).Error
|
||||
if err != nil {
|
||||
logger.Error("create fund record err:", logger.Field("err", err))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func UserDepositRefundRecordList(c *gin.Context) {
|
||||
req := &models.UserDepositRefundRecordListReq{}
|
||||
if c.ShouldBindJSON(req) != nil {
|
||||
|
|
|
@ -27,6 +27,7 @@ type Coupon struct {
|
|||
CategoryNumber string `json:"category_number"` // 可以使用该优惠券的商品分类,如果为空则表示没限制
|
||||
CommodityNumber string `json:"commodity_number"` // 可以使用该优惠券的商品编号,如果为空则表示没限制
|
||||
ErpCouponId uint32 `json:"erp_coupon_id"` // 零售业务推送优惠券ID
|
||||
Limit uint32 `json:"limit"` // 优惠券叠加限制 0-不限制;1-仅限原价购买时使用
|
||||
IsDraw bool `json:"is_draw" gorm:"-"` //
|
||||
}
|
||||
|
||||
|
@ -51,6 +52,7 @@ type UserCoupon struct {
|
|||
CategoryNumber string `json:"category_number"` // 可以使用该优惠券的商品分类,如果为空则表示没限制
|
||||
CommodityNumber string `json:"commodity_number"` // 可以使用该优惠券的商品编号,如果为空则表示没限制
|
||||
Code string `json:"code"` // 优惠券券码
|
||||
Limit uint32 `json:"limit"` // 优惠券叠加限制 0-不限制;1-仅限原价购买时使用
|
||||
Coupon *Coupon `json:"coupon" gorm:"-"` //
|
||||
UserInfo UserInfo `json:"user_info" gorm:"-"` //
|
||||
}
|
||||
|
|
|
@ -1268,7 +1268,7 @@ func UpdateCoupon(gdb *gorm.DB, erpOrder ErpOrder, state int) error {
|
|||
|
||||
for i, _ := range commodities {
|
||||
var userCoupon UserCoupon
|
||||
err := orm.Eloquent.Table("user_coupon").Where("id = ?", commodities[i].CouponID).
|
||||
err = orm.Eloquent.Table("user_coupon").Where("id = ?", commodities[i].CouponID).
|
||||
Find(&userCoupon).Error
|
||||
if err != nil || err == RecordNotFound {
|
||||
return errors.New("未查询到优惠券")
|
||||
|
@ -1327,6 +1327,36 @@ func UpdateCoupon(gdb *gorm.DB, erpOrder ErpOrder, state int) error {
|
|||
logger.Error("UpdateCoupon err:", logger.Field("err", err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 根据优惠券状态执行相应的处理逻辑
|
||||
switch couponState {
|
||||
case 1, 3: // 未使用,已过期;则扣减支付金额和已使用数量
|
||||
// 这里可以根据需要添加扣减的 SQL 更新逻辑,例如:
|
||||
sql := `
|
||||
UPDATE erp_coupon
|
||||
SET used_count = used_count - 1,
|
||||
total_pay_amount = total_pay_amount - ?,
|
||||
per_customer_amount = (total_pay_amount - ?) / (used_count - 1)
|
||||
WHERE ID = ?`
|
||||
err = gdb.Exec(sql, commodities[i].ReceivedAmount, commodities[i].ReceivedAmount, coupon.ErpCouponId).Error
|
||||
if err != nil {
|
||||
logger.Error("扣减优惠券数据失败:", logger.Field("err", err))
|
||||
//return err
|
||||
}
|
||||
case 2: // 已使用;则增加支付金额和已使用数量
|
||||
// 增加支付金额和已使用数量
|
||||
sql := `
|
||||
UPDATE erp_coupon
|
||||
SET used_count = used_count + 1,
|
||||
total_pay_amount = total_pay_amount + ?,
|
||||
per_customer_amount = (total_pay_amount + ?) / (used_count + 1)
|
||||
WHERE ID = ?`
|
||||
err = gdb.Exec(sql, commodities[i].ReceivedAmount, commodities[i].ReceivedAmount, coupon.ErpCouponId).Error
|
||||
if err != nil {
|
||||
logger.Error("更新优惠券数据失败:", logger.Field("err", err))
|
||||
//return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go-admin/logger"
|
||||
"io"
|
||||
|
@ -50,9 +51,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()
|
||||
|
@ -69,12 +70,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
|
||||
}
|
||||
|
|
|
@ -8,10 +8,12 @@ import (
|
|||
utils "go-admin/app/admin/models/tools"
|
||||
orm "go-admin/common/global"
|
||||
"go-admin/logger"
|
||||
"go-admin/tools/config"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -33,6 +35,10 @@ const (
|
|||
WxSubscribeMessage = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="
|
||||
TemplateId = "aP3c503T3wn-tJtpDccvxtNi7b1qjrwavFFfo-k2SAQ"
|
||||
WxJumpUrl = "/pages/voucher/voucher" // 跳转微信小程序的页面路径
|
||||
|
||||
WXGenerateSchema = "https://api.weixin.qq.com/wxa/generatescheme?access_token="
|
||||
|
||||
SMSHead = "【go2ns】"
|
||||
)
|
||||
|
||||
// WxAccessToken 微信access_token
|
||||
|
@ -140,6 +146,37 @@ type ErpMarketingCouponDataReq struct {
|
|||
|
||||
// ErpMarketingCouponDataResp 优惠券数据出参
|
||||
type ErpMarketingCouponDataResp struct {
|
||||
TotalAmount float64 `json:"total_amount"` // 用券总成交额:使用该优惠券的订单付款总金额
|
||||
TotalDiscount float64 `json:"total_discount"` // 优惠总金额:使用该优惠券优惠的总金额
|
||||
CostEffectiveness float64 `json:"cost_effectiveness"` // 费效比:优惠总金额 / 用券总成交额
|
||||
OrderCount int `json:"order_count"` // 订单数:使用该优惠券的付款订单数
|
||||
UnitPrice float64 `json:"unit_price"` // 用券笔单价:用券总成交额 / 使用该优惠券的付款订单数
|
||||
CustomerCount int `json:"customer_count"` // 用券客户数:使用该优惠券的成交客户数
|
||||
ProductCount int `json:"product_count"` // 购买商品件数:使用该优惠券购买的商品数量
|
||||
Products []ProductInfo `json:"products"` // 商品信息:包含每个商品的ID、名称、付款件数、付款人数等信息
|
||||
}
|
||||
|
||||
// ProductInfo 商品信息结构体
|
||||
type ProductInfo struct {
|
||||
ProductID int `json:"product_id"` // 商品ID
|
||||
ProductName string `json:"product_name"` // 商品名称
|
||||
PayCount int `json:"pay_count"` // 付款件数:使用该优惠券购买该商品的付款件数
|
||||
PayCustomer int `json:"pay_customer"` // 付款人数:购买该商品并使用优惠券的客户人数
|
||||
}
|
||||
|
||||
type GenerateSchemeReq struct {
|
||||
Path string `json:"path" validate:"required"` // 跳转小程序页面
|
||||
EnvVersion string `json:"env_version"` // 默认值"release"。要打开的小程序版本。正式版为"release",体验版为"trial",开发版为"develop"
|
||||
}
|
||||
|
||||
type GenerateSchemeResp struct {
|
||||
Openlink string `json:"openlink"` // 小程序跳转链接
|
||||
}
|
||||
|
||||
type WXGenerateSchemeResponse struct {
|
||||
Errcode int `json:"errcode"`
|
||||
Errmsg string `json:"errmsg"`
|
||||
Openlink string `json:"openlink"`
|
||||
}
|
||||
|
||||
// List 查询优惠券列表
|
||||
|
@ -228,8 +265,10 @@ func CreateErpMarketingCoupon(req *ErpMarketingCouponCreateReq) error {
|
|||
CouponType: "deduction",
|
||||
Value: req.Amount * 100,
|
||||
CategoryNumber: req.CategoryNumber,
|
||||
ActivityType: 666,
|
||||
ErpCouponId: erpCoupon.ID,
|
||||
ActiveEnd: Now().AddDate(0, 0, int(req.ActiveDate)),
|
||||
Limit: req.Limit,
|
||||
}
|
||||
|
||||
err = orm.Eloquent.Create(coupon).Error
|
||||
|
@ -263,7 +302,7 @@ func EditErpMarketingCoupon(req *ErpMarketingCouponEditReq) error {
|
|||
erpCoupon.Describe = req.Describe
|
||||
erpCoupon.CategoryNumber = req.CategoryNumber
|
||||
erpCoupon.ActiveDate = req.ActiveDate
|
||||
erpCoupon.Amount = req.Amount
|
||||
erpCoupon.Amount = req.Amount * 100
|
||||
erpCoupon.UserType = req.UserType
|
||||
erpCoupon.Limit = req.Limit
|
||||
|
||||
|
@ -288,7 +327,7 @@ func EditErpMarketingCoupon(req *ErpMarketingCouponEditReq) error {
|
|||
coupon.Name = req.Name
|
||||
coupon.Describe = req.Describe
|
||||
coupon.Rule = req.Rule
|
||||
coupon.Value = req.Amount
|
||||
coupon.Value = req.Amount * 100
|
||||
|
||||
err = begin.Model(&Coupon{}).Where("erp_coupon_id = ?", req.ErpCouponId).
|
||||
Omit("created_at").Save(coupon).Error
|
||||
|
@ -546,6 +585,19 @@ func markTaskAsCompleted(erpCouponId []uint32, nTotalCount int) error {
|
|||
|
||||
// 校验用户是否符合领取优惠券的条件
|
||||
func isEligibleForCoupon(user UserInfo, erpCoupon ErpCoupon) bool {
|
||||
// 获取尊享会员信息
|
||||
var privilegeUserInfo PrivilegeMember
|
||||
if err := orm.Eloquent.Table("privilege_member").Where("uid = ?", user.Uid).Find(&privilegeUserInfo).Error; err != nil {
|
||||
logger.Errorf("获取尊享会员信息出错:", logger.Field("err", err))
|
||||
return false
|
||||
}
|
||||
|
||||
// 如果是尊享会员,将其视为付费会员
|
||||
if privilegeUserInfo.MemberLevel == MemberLevelPrivilege {
|
||||
// 尊享会员归类为已付费用户
|
||||
user.MemberLevel = MemberLevelGold // 可以选择将尊享会员设为任意一个付费会员等级,通常设为黄金会员
|
||||
}
|
||||
|
||||
switch erpCoupon.UserType {
|
||||
case 1:
|
||||
// 1-所有人:不限制会员等级,所有人均可领取
|
||||
|
@ -587,7 +639,7 @@ func issueCouponsToUsers(users []UserInfo, erpCouponId []uint32) error {
|
|||
if isEligibleForCoupon(user, erpCoupon[0]) {
|
||||
// 发放优惠券
|
||||
var coupons []Coupon
|
||||
err = orm.Eloquent.Table("coupon").Where("erp_coupon_id in ?", erpCouponId).First(&coupons).Error
|
||||
err = orm.Eloquent.Table("coupon").Where("erp_coupon_id in ?", erpCouponId).Find(&coupons).Error
|
||||
if err != nil {
|
||||
logger.Error("query coupon err:", logger.Field("err", err))
|
||||
return err
|
||||
|
@ -606,6 +658,8 @@ func issueCouponsToUsers(users []UserInfo, erpCouponId []uint32) error {
|
|||
RedeemCode: "",
|
||||
CategoryNumber: coupon.CategoryNumber,
|
||||
Code: couponCode,
|
||||
ActivityType: coupon.ActivityType,
|
||||
Limit: coupon.Limit,
|
||||
}
|
||||
|
||||
err = orm.Eloquent.Create(userCoupon).Error
|
||||
|
@ -644,10 +698,12 @@ func issueCouponsToUsers(users []UserInfo, erpCouponId []uint32) error {
|
|||
"thing4": map[string]interface{}{"value": coupons[0].Rule},
|
||||
}
|
||||
//developer为开发版;trial为体验版;formal为正式版;默认为正式版
|
||||
_, err = SendMessage(wxToken.AccessToken, toUserOpenid, templateId, data, WxJumpUrl, "trial")
|
||||
miniProgramState := config.MessageConfig.MiniProgramState
|
||||
_, err = SendMessage(wxToken.AccessToken, toUserOpenid, templateId, data, WxJumpUrl, miniProgramState)
|
||||
if err != nil {
|
||||
logger.Errorf("SendMessage err:", err)
|
||||
// 如果订阅通知发送失败,则发送短信
|
||||
err = GtSendMessage([]string{user.Tel}, erpCoupon[0].SmsContent)
|
||||
err = GtSendMessage([]string{user.Tel}, ComposeSMSContent(erpCoupon[0].SmsContent))
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
}
|
||||
|
@ -657,6 +713,20 @@ func issueCouponsToUsers(users []UserInfo, erpCouponId []uint32) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func ComposeSMSContent(content string) string {
|
||||
// 1. 判断短信内容开头是否有【go2ns】,没有的话添加上
|
||||
if !strings.HasPrefix(content, SMSHead) {
|
||||
content = SMSHead + content
|
||||
}
|
||||
|
||||
// 2. 判断短信内容中是否有 http 开头的链接,没有的话在最后加上
|
||||
if !strings.Contains(content, "http") {
|
||||
content += " 详情请点击:" + config.MessageConfig.SmsUrl
|
||||
}
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
// Response 请求微信返回基础数据
|
||||
type Response struct {
|
||||
Errcode int `json:"errcode"`
|
||||
|
@ -694,7 +764,7 @@ func CheckAccessToken() {
|
|||
// 更新access_token
|
||||
err = orm.Eloquent.Table("wx_access_token").Where("appid = ?", WXAppID).
|
||||
Updates(map[string]interface{}{
|
||||
"access_token": accessToken,
|
||||
"access_token": accessToken.AccessToken,
|
||||
"expires_time": twoHoursLater,
|
||||
}).Error
|
||||
if err != nil {
|
||||
|
@ -765,21 +835,41 @@ func code2url(appID, secret string) (string, error) {
|
|||
return url.String(), nil
|
||||
}
|
||||
|
||||
// SendMessageReq 消息订阅请求参数
|
||||
type SendMessageReq struct {
|
||||
TemplateId string `json:"template_id"`
|
||||
Page string `json:"page"`
|
||||
Touser string `json:"touser"`
|
||||
Data interface{} `json:"data"`
|
||||
MiniprogramState string `json:"miniprogram_state"`
|
||||
Lang string `json:"lang"`
|
||||
}
|
||||
|
||||
// SendMessage 发送订阅消息
|
||||
func SendMessage(accessToken, toUserOpenid, templateId string, data interface{}, page, miniprogramState string) (
|
||||
[]byte, error) {
|
||||
func SendMessage(accessToken, toUserOpenid, templateId string, data interface{}, page, miniProgramState string) (
|
||||
sendMessageRsp *Response, err 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",
|
||||
|
||||
body := SendMessageReq{
|
||||
TemplateId: templateId,
|
||||
Page: page,
|
||||
Touser: toUserOpenid,
|
||||
Data: data,
|
||||
MiniprogramState: miniProgramState,
|
||||
Lang: "zh_CN",
|
||||
}
|
||||
|
||||
rsp, err := HttpRequest(http.MethodPost, url, body)
|
||||
return rsp, err
|
||||
respRaw, err := HttpRequest(http.MethodPost, url, body)
|
||||
|
||||
rsp := Response{}
|
||||
|
||||
if err = json.Unmarshal(respRaw, &rsp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rsp.Errcode != 0 {
|
||||
return nil, errors.New(rsp.Errmsg)
|
||||
}
|
||||
return &rsp, err
|
||||
}
|
||||
|
||||
func HttpRequest(method, url string, reqBody interface{}) ([]byte, error) {
|
||||
|
@ -808,3 +898,93 @@ func HttpRequest(method, url string, reqBody interface{}) ([]byte, error) {
|
|||
}
|
||||
return rspBody, nil
|
||||
}
|
||||
|
||||
// GetUserCouponIdsByErpCouponId 通过erp的优惠券id查找用户的优惠券id列表
|
||||
func GetUserCouponIdsByErpCouponId(erpCouponId uint32) ([]uint32, error) {
|
||||
// 先查询 Coupon 表,根据 ErpCouponId 获取 coupon_id
|
||||
var coupon Coupon
|
||||
err := orm.Eloquent.Where("erp_coupon_id = ?", erpCouponId).First(&coupon).Error
|
||||
if err != nil {
|
||||
// 如果未找到对应优惠券ID,返回错误
|
||||
return nil, fmt.Errorf("优惠券ID不存在或查询失败")
|
||||
}
|
||||
|
||||
// 使用 coupon_id 查找 UserCoupon 表中的记录,获取所有符合条件的记录
|
||||
var userCoupons []UserCoupon
|
||||
err = orm.Eloquent.Where("coupon_id = ?", coupon.ID).Find(&userCoupons).Error
|
||||
if err != nil {
|
||||
// 如果查询失败,返回错误
|
||||
return nil, fmt.Errorf("查询 UserCoupon 记录失败")
|
||||
}
|
||||
|
||||
// 提取所有找到的 userCoupon 的 ID
|
||||
var userCouponIds []uint32
|
||||
for _, userCoupon := range userCoupons {
|
||||
userCouponIds = append(userCouponIds, userCoupon.ID)
|
||||
}
|
||||
|
||||
// 返回所有 UserCoupon ID
|
||||
return userCouponIds, nil
|
||||
}
|
||||
|
||||
// WXGenerateScheme 获取小程序跳转链接
|
||||
func WXGenerateScheme(req *GenerateSchemeReq) (*GenerateSchemeResp, error) {
|
||||
var rsp WXGenerateSchemeResponse
|
||||
|
||||
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 || 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))
|
||||
}
|
||||
}
|
||||
|
||||
url := WXGenerateSchema + wxToken.AccessToken
|
||||
/*
|
||||
{
|
||||
"jump_wxa": {
|
||||
"path": "/pages/startPage/index",
|
||||
"query": "",
|
||||
"env_version": "release"
|
||||
|
||||
},
|
||||
"expire_type": 1,
|
||||
"expire_interval": 30
|
||||
}
|
||||
*/
|
||||
reqScheme := map[string]interface{}{
|
||||
"jump_wxa": map[string]string{
|
||||
"path": req.Path,
|
||||
"env_version": req.EnvVersion,
|
||||
},
|
||||
"expire_type": 1, //小程序 URL Link 失效类型,时间戳:0,间隔天数:1
|
||||
"expire_interval": 30, //最长间隔天数为30天。expire_type 为 1 必填
|
||||
}
|
||||
|
||||
data, err := HttpRequest(http.MethodPost, url, reqScheme)
|
||||
/*
|
||||
{
|
||||
"errcode": 0, //成功返回
|
||||
"errmsg": "ok",
|
||||
"url_link": "https://wxaurl.cn/pjKMfcQsULj"
|
||||
}
|
||||
*/
|
||||
if err = json.Unmarshal(data, &rsp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rsp.Errcode != 0 {
|
||||
return nil, errors.New(fmt.Sprintf("生成小程序跳转链接失败:errcode %d,errmsg %s", rsp.Errcode, rsp.Errmsg))
|
||||
}
|
||||
|
||||
resp := GenerateSchemeResp{
|
||||
Openlink: rsp.Openlink,
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
|
|
@ -17,3 +17,9 @@ func registerMarketingManageRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJ
|
|||
r.POST("coupon/start", market.ErpMarketingCouponStart) // 启动优惠券发放
|
||||
r.POST("coupon/data", market.ErpMarketingCouponData) // 优惠券数据
|
||||
}
|
||||
|
||||
func registerMarketingManageUnAuthRouter(v1 *gin.RouterGroup) {
|
||||
r := v1.Group("/marketing")
|
||||
|
||||
r.POST("generateScheme", market.GenerateScheme) // 获取小程序跳转链接
|
||||
}
|
||||
|
|
|
@ -58,6 +58,9 @@ func examplesNoCheckRoleRouter(r *gin.Engine) {
|
|||
registerCooperativeManageUnAuthRouter(v1)
|
||||
// 回收卡
|
||||
registerRecycleCardManageUnAuthRouter(v1)
|
||||
|
||||
// 营销管理
|
||||
registerMarketingManageUnAuthRouter(v1)
|
||||
}
|
||||
|
||||
// 需要认证的路由示例
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"github.com/jasonlvhit/gocron"
|
||||
"go-admin/app/admin/apis/usermanage"
|
||||
"go-admin/app/admin/models"
|
||||
"go-admin/app/admin/router"
|
||||
"go-admin/logger"
|
||||
|
@ -188,6 +189,12 @@ func run() error {
|
|||
fmt.Println("err:", err)
|
||||
}
|
||||
|
||||
// 每天早上9点30分退前一天的保证金
|
||||
err = s.Every(1).Day().At("09:30").Do(usermanage.AutoDepositRefund)
|
||||
if err != nil {
|
||||
fmt.Println("err:", err)
|
||||
}
|
||||
|
||||
<-s.Start()
|
||||
}()
|
||||
|
||||
|
|
|
@ -59,4 +59,9 @@ func run() {
|
|||
}
|
||||
fmt.Println("logger:", string(loggerConfig))
|
||||
|
||||
messageConfig, errs := json.MarshalIndent(config.MessageConfig, "", " ") //转换成JSON返回的是byte[]
|
||||
if errs != nil {
|
||||
fmt.Println(errs.Error())
|
||||
}
|
||||
fmt.Println("messageConfig:", string(messageConfig))
|
||||
}
|
||||
|
|
|
@ -43,15 +43,16 @@ settings:
|
|||
# source: mh_pro:c5JBW3X6EEVQluYM@tcp(39.108.188.218:3306)/mh_pro?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
|
||||
# source: mh_test:GPLzZ8rMmbJbKtMh@tcp(112.33.14.191:3306)/mh_test?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
|
||||
# source: mh_new_pro:YnzexdTfBHMSGZki@tcp(39.108.188.218:3306)/mh_new_pro?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
|
||||
|
||||
gen:
|
||||
# 代码生成读取的数据库名称
|
||||
dbname: dbname
|
||||
# 代码生成是使用前端代码存放位置,需要指定到src文件夹,相对路径
|
||||
frontpath: ../go-admin-ui/src
|
||||
|
||||
export:
|
||||
path: /Users/max/Documents/
|
||||
url: /Users/max/Documents/
|
||||
# path: /www/server/images/export/
|
||||
# url: https://dev.admin.deovo.com/load/export/
|
||||
message:
|
||||
mini_program_state: trial # 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
|
||||
sms_url: https://dev.admin.deovo.com/visit.html # 短信调整微信小程序的链接地址,需要区分环境
|
||||
|
|
118
docs/docs.go
118
docs/docs.go
|
@ -4480,6 +4480,39 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/marketing/generateScheme": {
|
||||
"post": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"营销管理,V1.4.4"
|
||||
],
|
||||
"summary": "获取小程序跳转链接",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "获取小程序跳转链接模型",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.GenerateSchemeReq"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.GenerateSchemeResp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/menu": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
@ -9652,7 +9685,44 @@ const docTemplate = `{
|
|||
}
|
||||
},
|
||||
"models.ErpMarketingCouponDataResp": {
|
||||
"type": "object"
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cost_effectiveness": {
|
||||
"description": "费效比:优惠总金额 / 用券总成交额",
|
||||
"type": "number"
|
||||
},
|
||||
"customer_count": {
|
||||
"description": "用券客户数:使用该优惠券的成交客户数",
|
||||
"type": "integer"
|
||||
},
|
||||
"order_count": {
|
||||
"description": "订单数:使用该优惠券的付款订单数",
|
||||
"type": "integer"
|
||||
},
|
||||
"product_count": {
|
||||
"description": "购买商品件数:使用该优惠券购买的商品数量",
|
||||
"type": "integer"
|
||||
},
|
||||
"products": {
|
||||
"description": "商品信息:包含每个商品的ID、名称、付款件数、付款人数等信息",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.ProductInfo"
|
||||
}
|
||||
},
|
||||
"total_amount": {
|
||||
"description": "用券总成交额:使用该优惠券的订单付款总金额",
|
||||
"type": "number"
|
||||
},
|
||||
"total_discount": {
|
||||
"description": "优惠总金额:使用该优惠券优惠的总金额",
|
||||
"type": "number"
|
||||
},
|
||||
"unit_price": {
|
||||
"description": "用券笔单价:用券总成交额 / 使用该优惠券的付款订单数",
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ErpMarketingCouponDeleteReq": {
|
||||
"type": "object",
|
||||
|
@ -13048,6 +13118,31 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"models.GenerateSchemeReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"env_version": {
|
||||
"description": "默认值\"release\"。要打开的小程序版本。正式版为\"release\",体验版为\"trial\",开发版为\"develop\"",
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"description": "跳转小程序页面",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.GenerateSchemeResp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"openlink": {
|
||||
"description": "小程序跳转链接",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.GetErpPurchaseDemandReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -15676,6 +15771,27 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"models.ProductInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pay_count": {
|
||||
"description": "付款件数:使用该优惠券购买该商品的付款件数",
|
||||
"type": "integer"
|
||||
},
|
||||
"pay_customer": {
|
||||
"description": "付款人数:购买该商品并使用优惠券的客户人数",
|
||||
"type": "integer"
|
||||
},
|
||||
"product_id": {
|
||||
"description": "商品ID",
|
||||
"type": "integer"
|
||||
},
|
||||
"product_name": {
|
||||
"description": "商品名称",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ProductInventoryAddReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
|
|
@ -4469,6 +4469,39 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/marketing/generateScheme": {
|
||||
"post": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"营销管理,V1.4.4"
|
||||
],
|
||||
"summary": "获取小程序跳转链接",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "获取小程序跳转链接模型",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.GenerateSchemeReq"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.GenerateSchemeResp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/menu": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
@ -9641,7 +9674,44 @@
|
|||
}
|
||||
},
|
||||
"models.ErpMarketingCouponDataResp": {
|
||||
"type": "object"
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cost_effectiveness": {
|
||||
"description": "费效比:优惠总金额 / 用券总成交额",
|
||||
"type": "number"
|
||||
},
|
||||
"customer_count": {
|
||||
"description": "用券客户数:使用该优惠券的成交客户数",
|
||||
"type": "integer"
|
||||
},
|
||||
"order_count": {
|
||||
"description": "订单数:使用该优惠券的付款订单数",
|
||||
"type": "integer"
|
||||
},
|
||||
"product_count": {
|
||||
"description": "购买商品件数:使用该优惠券购买的商品数量",
|
||||
"type": "integer"
|
||||
},
|
||||
"products": {
|
||||
"description": "商品信息:包含每个商品的ID、名称、付款件数、付款人数等信息",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.ProductInfo"
|
||||
}
|
||||
},
|
||||
"total_amount": {
|
||||
"description": "用券总成交额:使用该优惠券的订单付款总金额",
|
||||
"type": "number"
|
||||
},
|
||||
"total_discount": {
|
||||
"description": "优惠总金额:使用该优惠券优惠的总金额",
|
||||
"type": "number"
|
||||
},
|
||||
"unit_price": {
|
||||
"description": "用券笔单价:用券总成交额 / 使用该优惠券的付款订单数",
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ErpMarketingCouponDeleteReq": {
|
||||
"type": "object",
|
||||
|
@ -13037,6 +13107,31 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"models.GenerateSchemeReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"env_version": {
|
||||
"description": "默认值\"release\"。要打开的小程序版本。正式版为\"release\",体验版为\"trial\",开发版为\"develop\"",
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"description": "跳转小程序页面",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.GenerateSchemeResp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"openlink": {
|
||||
"description": "小程序跳转链接",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.GetErpPurchaseDemandReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -15665,6 +15760,27 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"models.ProductInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pay_count": {
|
||||
"description": "付款件数:使用该优惠券购买该商品的付款件数",
|
||||
"type": "integer"
|
||||
},
|
||||
"pay_customer": {
|
||||
"description": "付款人数:购买该商品并使用优惠券的客户人数",
|
||||
"type": "integer"
|
||||
},
|
||||
"product_id": {
|
||||
"description": "商品ID",
|
||||
"type": "integer"
|
||||
},
|
||||
"product_name": {
|
||||
"description": "商品名称",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ProductInventoryAddReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
|
|
@ -2219,6 +2219,33 @@ definitions:
|
|||
- erp_coupon_id
|
||||
type: object
|
||||
models.ErpMarketingCouponDataResp:
|
||||
properties:
|
||||
cost_effectiveness:
|
||||
description: 费效比:优惠总金额 / 用券总成交额
|
||||
type: number
|
||||
customer_count:
|
||||
description: 用券客户数:使用该优惠券的成交客户数
|
||||
type: integer
|
||||
order_count:
|
||||
description: 订单数:使用该优惠券的付款订单数
|
||||
type: integer
|
||||
product_count:
|
||||
description: 购买商品件数:使用该优惠券购买的商品数量
|
||||
type: integer
|
||||
products:
|
||||
description: 商品信息:包含每个商品的ID、名称、付款件数、付款人数等信息
|
||||
items:
|
||||
$ref: '#/definitions/models.ProductInfo'
|
||||
type: array
|
||||
total_amount:
|
||||
description: 用券总成交额:使用该优惠券的订单付款总金额
|
||||
type: number
|
||||
total_discount:
|
||||
description: 优惠总金额:使用该优惠券优惠的总金额
|
||||
type: number
|
||||
unit_price:
|
||||
description: 用券笔单价:用券总成交额 / 使用该优惠券的付款订单数
|
||||
type: number
|
||||
type: object
|
||||
models.ErpMarketingCouponDeleteReq:
|
||||
properties:
|
||||
|
@ -4687,6 +4714,23 @@ definitions:
|
|||
total_page:
|
||||
type: integer
|
||||
type: object
|
||||
models.GenerateSchemeReq:
|
||||
properties:
|
||||
env_version:
|
||||
description: 默认值"release"。要打开的小程序版本。正式版为"release",体验版为"trial",开发版为"develop"
|
||||
type: string
|
||||
path:
|
||||
description: 跳转小程序页面
|
||||
type: string
|
||||
required:
|
||||
- path
|
||||
type: object
|
||||
models.GenerateSchemeResp:
|
||||
properties:
|
||||
openlink:
|
||||
description: 小程序跳转链接
|
||||
type: string
|
||||
type: object
|
||||
models.GetErpPurchaseDemandReq:
|
||||
properties:
|
||||
call_type:
|
||||
|
@ -6574,6 +6618,21 @@ definitions:
|
|||
description: 总条数
|
||||
type: integer
|
||||
type: object
|
||||
models.ProductInfo:
|
||||
properties:
|
||||
pay_count:
|
||||
description: 付款件数:使用该优惠券购买该商品的付款件数
|
||||
type: integer
|
||||
pay_customer:
|
||||
description: 付款人数:购买该商品并使用优惠券的客户人数
|
||||
type: integer
|
||||
product_id:
|
||||
description: 商品ID
|
||||
type: integer
|
||||
product_name:
|
||||
description: 商品名称
|
||||
type: string
|
||||
type: object
|
||||
models.ProductInventoryAddReq:
|
||||
properties:
|
||||
commodities:
|
||||
|
@ -11713,6 +11772,27 @@ paths:
|
|||
summary: 启动优惠券发放
|
||||
tags:
|
||||
- 营销管理,V1.4.4
|
||||
/api/v1/marketing/generateScheme:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: 获取小程序跳转链接模型
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/models.GenerateSchemeReq'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/models.GenerateSchemeResp'
|
||||
summary: 获取小程序跳转链接
|
||||
tags:
|
||||
- 营销管理,V1.4.4
|
||||
/api/v1/menu:
|
||||
get:
|
||||
description: 获取JSON
|
||||
|
|
|
@ -14,5 +14,5 @@ func TestSend(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGtSendMessage(t *testing.T) {
|
||||
models.GtSendMessage([]string{"15019230751"}, "【go2ns】绿城短信推送测试,测试")
|
||||
models.GtSendMessage([]string{"18872141360", "15019230751"}, "【go2ns】圣诞活动已开启,优惠券已发放到您的账户。详情点击:https://dev.admin.deovo.com/visit.html")
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ var cfgGen *viper.Viper
|
|||
// 导出文件配置项 非必须
|
||||
var cfgExport *viper.Viper
|
||||
|
||||
var cfgMessage *viper.Viper
|
||||
|
||||
// Setup 载入配置文件
|
||||
func Setup(path string) {
|
||||
viper.SetConfigFile(path)
|
||||
|
@ -90,4 +92,10 @@ func Setup(path string) {
|
|||
panic("No found settings.export")
|
||||
}
|
||||
ExportConfig = InitExport(cfgExport)
|
||||
|
||||
cfgMessage = viper.Sub("settings.message")
|
||||
if cfgMessage == nil {
|
||||
panic("No found settings.message")
|
||||
}
|
||||
MessageConfig = InitMessage(cfgMessage)
|
||||
}
|
||||
|
|
17
tools/config/message.go
Normal file
17
tools/config/message.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package config
|
||||
|
||||
import "github.com/spf13/viper"
|
||||
|
||||
type Message struct {
|
||||
MiniProgramState string
|
||||
SmsUrl string
|
||||
}
|
||||
|
||||
func InitMessage(cfg *viper.Viper) *Message {
|
||||
return &Message{
|
||||
MiniProgramState: cfg.GetString("mini_program_state"),
|
||||
SmsUrl: cfg.GetString("sms_url"),
|
||||
}
|
||||
}
|
||||
|
||||
var MessageConfig = new(Message)
|
Loading…
Reference in New Issue
Block a user