diff --git a/app/admin/apis/basic/category.go b/app/admin/apis/basic/category.go index ffe8659..19d2a88 100644 --- a/app/admin/apis/basic/category.go +++ b/app/admin/apis/basic/category.go @@ -1,6 +1,7 @@ package basic import ( + "errors" "fmt" "github.com/gin-gonic/gin" "go-admin/app/admin/middleware" @@ -41,6 +42,11 @@ func CreateCategory(c *gin.Context) { return } + if models.IsExistingCategory(req.Name) { + app.Error(c, http.StatusBadRequest, errors.New("分类名称已存在,不能重复"), "分类名称已存在,不能重复") + return + } + category := models.Category{ Name: req.Name, Display: 1, @@ -149,6 +155,12 @@ func DeleteCategory(c *gin.Context) { return } + // 删除分类之前需要判断该分类下是否有商品 + if models.CheckCommodityByCategory(req.CategoryId) { + app.Error(c, http.StatusBadRequest, errors.New("该分类或其子分类下有商品未删除"), "该分类或其子分类下有商品未删除") + return + } + err := orm.Eloquent.Where("id=?", req.CategoryId).Delete(&models.Category{}).Error if err != nil { //logger.Error("erp commodity err:", err) diff --git a/app/admin/apis/basic/commodity.go b/app/admin/apis/basic/commodity.go index cc15bc5..55dbf83 100644 --- a/app/admin/apis/basic/commodity.go +++ b/app/admin/apis/basic/commodity.go @@ -320,8 +320,8 @@ func CommodityEdit(c *gin.Context) { return } - // 同步更新库存表和库存商品表的"指导零售价"和"最低零售价" - err = models.UpdateErpStockAmountInfo(begin, req.Id, req.RetailPrice, req.MinRetailPrice) + // 同步更新库存表和库存商品表的"指导零售价"和"最低零售价";库存商品表的"商品条码" + err = models.UpdateErpStockAmountInfo(begin, req.Id, req.RetailPrice, req.MinRetailPrice, barCode) if err != nil { begin.Rollback() logger.Error("UpdateErpStockAmountInfo err:", logger.Field("err", err)) diff --git a/app/admin/apis/cooperativemanage/cooperative.go b/app/admin/apis/cooperativemanage/cooperative.go index 62d941c..17453ea 100644 --- a/app/admin/apis/cooperativemanage/cooperative.go +++ b/app/admin/apis/cooperativemanage/cooperative.go @@ -954,3 +954,21 @@ func CooperativeGetPayInfo(c *gin.Context) { app.OK(c, payInfo, "") } + +// CooperativeGetDefaultInfo 获取合作商默认用户名和密码 +// @Summary 获取合作商默认用户名和密码 +// @Tags 合作商, v1.2.0 +// @Produce json +// @Accept json +// @Success 200 {object} models.DefaultUserNameAndPasswordResp +// @Router /api/v1/cooperative/get_default_info [post] +func CooperativeGetDefaultInfo(c *gin.Context) { + userInfo, err := models.GetDefaultUserNameAndPassword() + if err != nil { + logger.Error("GetDefaultUserNameAndPassword err:", logger.Field("err", err)) + app.Error(c, http.StatusInternalServerError, err, err.Error()) + return + } + + app.OK(c, userInfo, "") +} diff --git a/app/admin/apis/purchasemanage/purchase.go b/app/admin/apis/purchasemanage/purchase.go index fa88242..98f6e9a 100644 --- a/app/admin/apis/purchasemanage/purchase.go +++ b/app/admin/apis/purchasemanage/purchase.go @@ -10,6 +10,7 @@ import ( "go-admin/tools" "go-admin/tools/app" "net/http" + "time" ) // ErpPurchaseCreate 新建采购订单 @@ -39,6 +40,14 @@ func ErpPurchaseCreate(c *gin.Context) { // return //} + // 检验参数 + err = model.CheckCreateErpPurchaseOrderParam(req) + if err != nil { + logger.Error("CheckCreateErpPurchaseOrderParam err:", logger.Field("err", err)) + app.Error(c, http.StatusInternalServerError, err, err.Error()) + return + } + if len(req.ErpPurchaseCommodities) == 0 { logger.Error("erp purchase commodities is nil") app.Error(c, http.StatusInternalServerError, err, "操作失败") @@ -86,6 +95,14 @@ func ErpPurchaseEdit(c *gin.Context) { // return //} + // 检验参数 + err = model.CheckEditErpPurchaseOrderParam(req) + if err != nil { + logger.Error("CheckCreateErpPurchaseOrderParam err:", logger.Field("err", err)) + app.Error(c, http.StatusInternalServerError, err, err.Error()) + return + } + if len(req.ErpPurchaseCommodities) == 0 { logger.Error("erp purchase commodities is nil") app.Error(c, http.StatusInternalServerError, err, "操作失败") @@ -173,7 +190,17 @@ func ErpPurchaseDetail(c *gin.Context) { // 添加实际采购入库信息 var commodityList []model.ErpPurchaseCommodity for _, v := range purchaseCommodities { - result, err := model.GetTotalsAndAveragesByCommodityID(v.ErpCommodityId) + // 查询默认员工成本价 + erpCommodity, err := model.GetCommodity(v.ErpCommodityId) + if err != nil { + logger.Error("ErpPurchaseDetail GetCommodity err:", logger.Field("err", err)) + app.Error(c, http.StatusBadRequest, err, "获取失败") + return + } + v.DefaultEmployeePrice = v.Price + float64(erpCommodity.StaffCostPrice) + + // 查询执行数量之和、平均执行单价、执行金额之和和平均员工成本价 + result, err := model.GetTotalsAndAveragesByCommodityID(v.ErpCommodityId, v.ErpPurchaseOrderId) if err != nil { logger.Error("GetTotalsAndAveragesByCommodityID err:", logger.Field("err", err)) app.Error(c, http.StatusBadRequest, err, "获取失败") @@ -215,6 +242,13 @@ func ErpPurchaseAudit(c *gin.Context) { return } + sysUser, err := model.GetSysUserByCtx(c) + if err != nil { + logger.Error("sys user err:", logger.Field("err", err)) + app.Error(c, http.StatusInternalServerError, err, "操作失败") + return + } + // todo 需要校验当前用户是否有权限 var erpPurchaseOrder model.ErpPurchaseOrder @@ -262,7 +296,10 @@ func ErpPurchaseAudit(c *gin.Context) { begin := orm.Eloquent.Begin() err = begin.Table("erp_purchase_order").Where("id = ?", erpPurchaseOrder.ID).Updates(map[string]interface{}{ - "state": orderState, + "state": orderState, + "auditor_id": sysUser.UserId, + "audit_time": time.Now(), + "auditor_name": sysUser.NickName, }).Error if err != nil { begin.Rollback() @@ -308,11 +345,11 @@ func ErpPurchaseAudit(c *gin.Context) { // @Tags 采购管理, V1.3.0 // @Produce json // @Accept json -// @Param request body models.ErpPurchaseTerminateReq true "删除采购订单模型" +// @Param request body models.ErpPurchaseDeleteReq true "删除采购订单模型" // @Success 200 {object} app.Response // @Router /api/v1/erp_purchase/delete [post] func ErpPurchaseDelete(c *gin.Context) { - var req = new(model.ErpPurchaseTerminateReq) + var req = new(model.ErpPurchaseDeleteReq) if err := c.ShouldBindJSON(&req); err != nil { logger.Error("ShouldBindJSON err:", logger.Field("err", err)) app.Error(c, http.StatusBadRequest, err, "参数错误:"+err.Error()) diff --git a/app/admin/apis/usermanage/user.go b/app/admin/apis/usermanage/user.go index fcd2a8b..5a0df21 100644 --- a/app/admin/apis/usermanage/user.go +++ b/app/admin/apis/usermanage/user.go @@ -23,7 +23,7 @@ func UserList(c *gin.Context) { Tel string `json:"tel"` // 电话 Uid int `json:"uid"` // 用户id CooperativeBusinessId int `json:"cooperative_business_id"` // 合作商id - MemberLevel int `json:"memberLevel"` // 会员等级 + MemberLevel int `json:"memberLevel"` // 当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 StoreId int `json:"store_id"` // 门店id UserType int `json:"user_type"` // 用户类型 用户类型 1-普通用户 2-店员 StartTime string `json:"startTime"` // 开始时间 @@ -681,6 +681,14 @@ func NotarizeUserDepositRefused(c *gin.Context) { app.OK(c, nil, "操作成功") } +// GroupSendMessageCreateTemplateList 查询短信模版列表 +// @Summary 短信群发 +// @Tags 短信群发, V1.2.0 +// @Produce json +// @Accept json +// @Param request body models.GroupSendMessageCreateTemplateListReq true "查询短信模版列表模型" +// @Success 200 {object} models.GroupSendMessageCreateTemplateListResp +// @Router /api/v1/group_send_message/template/list [post] func GroupSendMessageCreateTemplateList(c *gin.Context) { req := &models.GroupSendMessageCreateTemplateListReq{} if c.ShouldBindJSON(req) != nil { diff --git a/app/admin/models/analyse.go b/app/admin/models/analyse.go index d0b6795..11f7ff2 100644 --- a/app/admin/models/analyse.go +++ b/app/admin/models/analyse.go @@ -288,7 +288,7 @@ func UserMemberRecordListSetUser(list []UserMemberRecord) { //list[i].UserInfo = &v list[i].RegisterTime = v.CreatedAt list[i].MemberLevel = v.MemberLevel - list[i].MemberExpire = v.MemberExpire + list[i].MemberExpire = *v.MemberExpire } } } diff --git a/app/admin/models/category.go b/app/admin/models/category.go index ed5f411..d06b0a3 100644 --- a/app/admin/models/category.go +++ b/app/admin/models/category.go @@ -128,3 +128,29 @@ func findChildCategory(prev *CategoryModel, all bool) []*CategoryModel { return cs } + +// CheckCommodityByCategory 检查某个分类下是否有商品 +func CheckCommodityByCategory(categoryId uint32) bool { + var count int64 + err := orm.Eloquent.Table("erp_commodity").Where("erp_category_id = ? and count > 0", categoryId). + Count(&count).Error + if err != nil { + logger.Error("CheckCommodityByCategory err:", logger.Field("err", err)) + } + + return count > 0 +} + +// IsExistingCategory 查询分类资料中某个名称的分类是否存在 +func IsExistingCategory(categoryName string) bool { + if categoryName == "" { + return true + } + // 查询分类名称是否存在的逻辑 + var count int64 + orm.Eloquent.Debug().Model(&Category{}). + Where("name = ?", categoryName). + Count(&count) + + return count > 0 +} diff --git a/app/admin/models/commodity.go b/app/admin/models/commodity.go index 2079e79..3c8a675 100644 --- a/app/admin/models/commodity.go +++ b/app/admin/models/commodity.go @@ -18,7 +18,8 @@ import ( ) const ( - NoIMEICommodity = 1 // 非串码商品类型 + NoIMEICommodity = 1 // 非串码商品类型 + PurchaseInventory = 2 // 采购入库 InStock = 1 // 在库 SoldOut = 2 // 已售 @@ -1663,7 +1664,7 @@ type ErpStockCommodityListReq struct { IMEI string `json:"imei"` // 串码 StoreId uint32 `json:"store_id"` // 门店编号 SupplierId uint32 `json:"supplier_id"` // 供应商id - State uint32 `json:"state"` // 库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库 + State uint32 `json:"state"` // 库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库(前端只看1,4) Sn string `json:"sn"` // 首次入库订单编号 StorageType uint32 `json:"storage_type"` // 首次入库方式:1-系统入库 2-采购入库 StockTimeStart string `json:"stock_time_start"` // 最近入库开始时间 @@ -1743,7 +1744,7 @@ func (m *ErpStockCommodityListReq) GetDetailList() (*ErpStockCommodityListResp, } resp.ExportUrl = listExport } else { - err := qs.Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Order("id DESC").Error + err := qs.Offset(page * m.PageSize).Limit(m.PageSize).Order("stock_time DESC,id DESC").Find(&commodities).Error if err != nil && !errors.Is(err, RecordNotFound) { //logger.Error("erp commodity list err:", err) return resp, err @@ -1822,6 +1823,16 @@ func CheckScanCodeResp(scanCode string, req *ErpStockCommodityListResp) error { return nil } +// contains 函数用于检查一个整数切片中是否包含某个值 +func contains(s []int, e int) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +} + // buildQueryConditions 根据请求参数构建查询条件 func (m *ErpStockCommodityListReq) buildQueryConditions(qs *gorm.DB) { if m.ScanCode != "" { @@ -1869,8 +1880,11 @@ func (m *ErpStockCommodityListReq) buildQueryConditions(qs *gorm.DB) { qs = qs.Where("erp_supplier_id=?", m.SupplierId) } - if m.State != 0 { //库存状态 + defaultStates := []int{1, 4} + if m.State != 0 && contains(defaultStates, int(m.State)) { qs = qs.Where("state=?", m.State) + } else { + qs = qs.Where("state IN (?)", defaultStates) } if m.Sn != "" { //首次入库订单编号 @@ -2212,7 +2226,36 @@ func GetCodeList(req *QueryCodeReq) (*QueryCodeResp, error) { resp.PageSize = req.PageSize resp.List = stockList - return resp, nil + return removeDuplicates(resp), nil +} + +func removeDuplicates(resp *QueryCodeResp) *QueryCodeResp { + // 创建一个 map 用来记录已经出现过的字符串 + uniqueMap := make(map[string]bool) + + // 新建一个切片用来保存不重复的数据 + var uniqueList []string + + // 遍历原始的 List + for _, item := range resp.List { + // 如果这个字符串已经在 map 中存在,说明重复,跳过 + if _, ok := uniqueMap[item]; ok { + continue + } + // 否则,将其添加到新的切片中,并在 map 中标记为已经出现过 + uniqueList = append(uniqueList, item) + uniqueMap[item] = true + } + + // 构建新的 QueryCodeResp 结构体 + newResp := &QueryCodeResp{ + List: uniqueList, + Total: len(uniqueList), + PageIndex: resp.PageIndex, + PageSize: resp.PageSize, + } + + return newResp } func GetErpCommodityMap(ids []uint32) (map[uint32]ErpCommodity, error) { diff --git a/app/admin/models/coupon.go b/app/admin/models/coupon.go index bf9a896..bdf19f0 100644 --- a/app/admin/models/coupon.go +++ b/app/admin/models/coupon.go @@ -68,7 +68,7 @@ type ActivityMemberRenewal struct { State uint32 `json:"state" gorm:"column:state;comment:'状态'"` // 1-进行中 2-已完成 3-已过期 StartTime time.Time `json:"start_time" gorm:"column:start_time;comment:'开始时间'"` // 开始时间 IsPop bool `json:"is_pop" gorm:"column:is_pop;comment:'是否弹窗'"` // 是否弹窗 - MemberLevel uint32 `json:"member_level" gorm:"column:member_level;comment:'会员等级'"` // 会员等级 + MemberLevel uint32 `json:"member_level" gorm:"column:member_level;comment:'会员等级'"` // 当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 //StartUseTime time.Time `json:"start_use_time" gorm:"column:start_use_time;comment:'开始使用时间'"` // 开始使用时间 } diff --git a/app/admin/models/dispose_config.go b/app/admin/models/dispose_config.go index fcc23fe..a13afd2 100644 --- a/app/admin/models/dispose_config.go +++ b/app/admin/models/dispose_config.go @@ -1,10 +1,18 @@ package models import ( + "crypto/aes" + "crypto/cipher" + craned "crypto/rand" + "encoding/base64" "encoding/json" "errors" + "fmt" orm "go-admin/common/global" "go-admin/logger" + "io" + "math/rand" + "time" ) // gen:qs @@ -37,6 +45,7 @@ const ( ConfigRecycleCard = "recycle_card_config" // 回收卡配置 ConfigCooperativePayInfo = "cooperative_pay_info" // 合作商支付设置 ConfigErpOrderShowInfo = "erp_order_show_config" // 零售订单显示设置 + ConfigSystemSmsCount = "sms_config" // 获取系统每月短信限额 ) func PayConfigInfo() (*PayConfig, error) { @@ -369,6 +378,10 @@ type ErpOrderShowConfig struct { ShowAll string `json:"show_all" binding:"required"` // 展示所有订单配置:ON-打开,OFF-关闭 } +type SystemSmsConfig struct { + MonthFreeCount uint32 `json:"month_free_count" ` // 每月短信免费额度 +} + // SetErpOrderShowConfig 设置零售订单展示配置信息 func SetErpOrderShowConfig(req *ErpOrderShowConfig) error { showInfo := ErpOrderShowConfig{ @@ -430,3 +443,152 @@ func GetErpOrderShowConfig() (*ErpOrderShowConfig, error) { return erpOrderShowConfig, nil } + +type DefaultUserNameAndPasswordResp struct { + Username string `json:"username"` // 用户名 + Password string `json:"password"` // 密码 +} + +// GetDefaultUserNameAndPassword 获取合作商默认用户名和密码 +func GetDefaultUserNameAndPassword() (*DefaultUserNameAndPasswordResp, error) { + username, password := generateUsernameAndPassword() + + key := []byte("NfOM3p64ThVKX7Ck34R1mOeiniwuCwua") + // 加密用户名和密码 + encryptedUsername, err := encrypt(username, key) + if err != nil { + fmt.Println("Error encrypting username:", err) + return nil, err + } + + encryptedPassword, err := encrypt(password, key) + if err != nil { + fmt.Println("Error encrypting password:", err) + return nil, err + } + + return &DefaultUserNameAndPasswordResp{ + Username: encryptedUsername, + Password: encryptedPassword, + }, nil +} + +// 生成指定长度的随机字符串 +func generateRandomString(length int) string { + rand.Seed(time.Now().UnixNano()) + + characters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") + result := make([]rune, length) + for i := range result { + result[i] = characters[rand.Intn(len(characters))] + } + return string(result) +} + +// 生成用户名和密码 +func generateUsernameAndPassword() (string, string) { + var username, password string + for { + username = generateRandomString(4) + var count int64 + err := orm.Eloquent.Table("cooperative_business").Where("username = ?", username).Count(&count).Error + if err == nil && count > 0 { + continue + } + break + } + + for { + password = generateRandomString(6) + var count int64 + err := orm.Eloquent.Table("cooperative_business").Where("password = ?", password).Count(&count).Error + if err == nil && count > 0 { + continue + } + break + } + return username, password +} + +// 加密字符串 +func encrypt(plainText string, key []byte) (string, error) { + block, err := aes.NewCipher(key) + if err != nil { + return "", err + } + + // 对明文进行填充 + plainBytes := []byte(plainText) + padLen := aes.BlockSize - len(plainBytes)%aes.BlockSize + padText := append(plainBytes, bytesRepeating(byte(padLen), padLen)...) + + // 创建一个加密分组链,使用 key 进行加密 + cipherText := make([]byte, aes.BlockSize+len(padText)) + iv := cipherText[:aes.BlockSize] + if _, err := io.ReadFull(craned.Reader, iv); err != nil { + return "", err + } + cfb := cipher.NewCFBEncrypter(block, iv) + cfb.XORKeyStream(cipherText[aes.BlockSize:], padText) + + return base64.URLEncoding.EncodeToString(cipherText), nil +} + +// bytesRepeating 重复生成一个字节的切片 +func bytesRepeating(b byte, count int) []byte { + result := make([]byte, count) + for i := 0; i < count; i++ { + result[i] = b + } + return result +} + +// 解密字符串 +func decrypt(cipherText string, key []byte) (string, error) { + cipherBytes, err := base64.URLEncoding.DecodeString(cipherText) + if err != nil { + return "", err + } + + block, err := aes.NewCipher(key) + if err != nil { + return "", err + } + + if len(cipherBytes) < aes.BlockSize { + return "", fmt.Errorf("cipher text too short") + } + + iv := cipherBytes[:aes.BlockSize] + cipherBytes = cipherBytes[aes.BlockSize:] + + cfb := cipher.NewCFBDecrypter(block, iv) + cfb.XORKeyStream(cipherBytes, cipherBytes) + + // 去除填充部分 + padLen := int(cipherBytes[len(cipherBytes)-1]) + if padLen < 1 || padLen > aes.BlockSize { + return "", fmt.Errorf("invalid padding length") + } + + return string(cipherBytes[:len(cipherBytes)-padLen]), nil +} + +// GetSystemSmsConfig 获取系统每月短信限额 +func GetSystemSmsConfig() (int, error) { + smsConfig := new(SystemSmsConfig) + var configAllocation Config + err := orm.Eloquent.Table("config").Where("name=?", ConfigSystemSmsCount).Find(&configAllocation).Error + if err != nil { + logger.Errorf("GetSystemSmsConfig err:", err) + return 0, err + } + + err = json.Unmarshal([]byte(configAllocation.Value), smsConfig) + if err != nil { + logger.Errorf("GetSystemSmsConfig err:", err) + return int(smsConfig.MonthFreeCount), err + } + + return int(smsConfig.MonthFreeCount), nil +} diff --git a/app/admin/models/erp_order.go b/app/admin/models/erp_order.go index 2593c6e..cd252d5 100644 --- a/app/admin/models/erp_order.go +++ b/app/admin/models/erp_order.go @@ -11,6 +11,7 @@ import ( "go-admin/tools" "go-admin/tools/config" "gorm.io/gorm" + "math" "math/rand" "strconv" "strings" @@ -74,8 +75,8 @@ type ErpOrder struct { PayStatus uint32 `json:"pay_status"` // 支付状态 0-未创建 ;1-待支付; 2-已支付 IsPrint uint32 `json:"is_print"` // 是否打印小票 1-未打印 2-已打印 PrintCount uint32 `json:"print_count"` // 小票打印次数 - InvoiceCode uint32 `json:"invoice_code"` // 发票代码 - InvoiceNumber uint32 `json:"invoice_number"` // 发票编码 + InvoiceCode string `json:"invoice_code"` // 发票代码 + InvoiceNumber string `json:"invoice_number"` // 发票编码 RejectedTotalAmount float64 `json:"rejected_total_amount" gorm:"-"` // 订单总退货金额 RejectedTotalCount uint32 `json:"rejected_total_count" gorm:"-"` // 订单总退货数量 StorePer float64 `json:"store_per"` // 门店提成:订单总员工毛利X该门店设置好的提成比例,保留到小数后两位多余舍去 @@ -167,7 +168,7 @@ type ErpOrderCreateReq struct { StoreId uint32 `json:"store_id" binding:"required"` // 门店id StoreName string `json:"store_name" binding:"required"` // 门店名称 RetailType string `json:"retail_type" binding:"required"` // 销售类型:sale 零售销售; rejected 零售退货 - Tel string `json:"tel"` // 会员手机号 + Tel string `json:"tel" binding:"required"` // 会员手机号 MemberType string `json:"member_type" binding:"required"` // 会员类型:general 普通; member 会员 TotalRetailPrice float64 `json:"total_retail_price" binding:"required"` // 订单总指导零售价 TotalAmount float64 `json:"total_amount" binding:"required"` // 订单实收金额 @@ -199,9 +200,10 @@ type ErpOrderListReq struct { // ErpOrderListResp 查询零售订单列表出参 type ErpOrderListResp struct { List []ErpOrder `json:"list"` - Total int `json:"total"` // 总条数 - PageIndex int `json:"pageIndex"` // 页码 - PageSize int `json:"pageSize"` // 每页展示条数 + Total int `json:"total"` // 总条数 + PageIndex int `json:"pageIndex"` // 页码 + PageSize int `json:"pageSize"` // 每页展示条数 + ShowAll string `json:"show_all" binding:"required"` // 展示所有订单配置:ON-打开,OFF-关闭 ExportUrl string `json:"export_url"` } @@ -485,15 +487,17 @@ func (m *ErpOrderListReq) List() (*ErpOrderListResp, error) { } // 添加付款、销售员、商品信息 + erpOrderListSetCommodity(orders) erpOrderListSetCashier(orders) erpOrderListSetSalesman(orders) - erpOrderListSetCommodity(orders) + resp.List = orders //跟之前保持一致 resp.Total = int(count) resp.PageIndex = page + 1 resp.PageSize = m.PageSize + resp.ShowAll = showConfig.ShowAll return resp, nil } @@ -521,9 +525,10 @@ func QueryListByScanCode(scanCode, showConfig string) (*ErpOrderListResp, error) } // 添加付款、销售员、商品信息 + erpOrderListSetCommodity(orders) erpOrderListSetCashier(orders) erpOrderListSetSalesman(orders) - erpOrderListSetCommodity(orders) + resp.List = orders //跟之前保持一致 @@ -801,10 +806,58 @@ func (m *ErpOrder) SetCommodity() { // 添加订单的销售员信息 func erpOrderListSetSalesman(list []ErpOrder) { for i, _ := range list { - list[i].SetSalesman() + _ = list[i].SetOrderSalesman() } } +func (m *ErpOrder) SetOrderSalesman() error { + var salesProfit, staffProfit float64 + //获取销售毛利、员工毛利数据 + for _, item := range m.Commodities { + erpCommodity, err := GetCommodity(item.ErpCommodityId) + if err != nil { + logger.Error("GetCommodity err:", logger.Field("err", err)) + } + salesProfit += item.SalesProfit * erpCommodity.Brokerage1 * 0.01 + staffProfit += item.StaffProfit * erpCommodity.Brokerage2 * 0.01 + } + // 四舍五入并保留两位小数 + salesProfit = math.Round(salesProfit*100) / 100 + staffProfit = math.Round(staffProfit*100) / 100 + + var salesmanInfo []ErpOrderSales + err := orm.Eloquent.Model(&ErpOrderSales{}).Where("erp_order_id = ?", m.ID).Find(&salesmanInfo).Error + if err != nil { + return err + } + + var salesmanList []ErpOrderSales + for _, item := range salesmanInfo { + item.SalesProfitPer = salesProfit / float64(len(salesmanInfo)) + item.StaffProfitPer = staffProfit / float64(len(salesmanInfo)) + + // 获取员工毛利 + userInfo, err := GetSysUserInfoByUid(item.Uid) + if err != nil { + logger.Error("GetSysUserInfoByUid err:", logger.Field("err", err)) + } + item.Name = userInfo.NickName + item.SalesmanPer = staffProfit * userInfo.SalesCommRate / float64(len(salesmanInfo)) + + salesmanList = append(salesmanList, item) + } + + if len(salesmanList) == 0 { + m.Salesman = []ErpOrderSales{} + } else { + m.Salesman = salesmanList + } + + m.SalesmanList = "" + + return nil +} + func (m *ErpOrder) SetSalesman() { if m.SalesmanList != "" { var salesman []ErpOrderSales @@ -825,9 +878,12 @@ func (m *ErpOrderCreateReq) GetSalesmanList() (string, error) { if err != nil { logger.Error("GetCommodity err:", logger.Field("err", err)) } - salesProfit += item.SalesProfit * erpCommodity.Brokerage1 - staffProfit += item.StaffProfit * erpCommodity.Brokerage2 + salesProfit += item.SalesProfit * erpCommodity.Brokerage1 * 0.01 + staffProfit += item.StaffProfit * erpCommodity.Brokerage2 * 0.01 } + // 四舍五入并保留两位小数 + salesProfit = math.Round(salesProfit*100) / 100 + staffProfit = math.Round(staffProfit*100) / 100 var salesmanList []ErpOrderSales for _, item := range m.Salesman { @@ -898,7 +954,7 @@ func SetUserInfo(tel string) { logger.Error("user err:", logger.Field("err", err)) return } - if user.FirstRetailOrder.IsZero() { + if user.FirstRetailOrder != nil { err := orm.Eloquent.Table("user").Where("uid=?", user.Uid).Update("first_retail_order", time.Now()).Error if err != nil { logger.Error("update user err:", logger.Field("err", err)) @@ -1349,10 +1405,7 @@ func QueryStoreManageData(req *ErpOrderStoreManageDataReq) (*ErpOrderStoreManage logger.Errorf("List err:", err) showConfig.ShowAll = "ON" } - resp := &ErpOrderStoreManageDataResp{ - PageIndex: req.PageIndex, - PageSize: req.PageSize, - } + page := req.PageIndex - 1 if page < 0 { page = 0 @@ -1360,6 +1413,11 @@ func QueryStoreManageData(req *ErpOrderStoreManageDataReq) (*ErpOrderStoreManage if req.PageSize == 0 { req.PageSize = 10 } + + resp := &ErpOrderStoreManageDataResp{ + PageIndex: req.PageIndex, + PageSize: req.PageSize, + } var storeManageDataList []StoreManageData // 构建查询条件 @@ -1388,36 +1446,22 @@ func QueryStoreManageData(req *ErpOrderStoreManageDataReq) (*ErpOrderStoreManage } qs = qs.Where("maker_time IS NOT NULL") - es := qs - // 获取总条数 - err = es.Select("DATE_FORMAT(maker_time, '%Y-%m-%d') AS date, SUM(total_amount) AS total_sales_amount, " + + // 查询数据 + err = qs.Select("DATE_FORMAT(maker_time, '%Y-%m-%d') AS date, SUM(total_amount) AS total_sales_amount, " + "(SUM(total_retail_price) - SUM(total_amount)) AS promotion_fee, " + "SUM(total_sales_profit) AS sales_profit, SUM(total_staff_profit) AS staff_profit, SUM(total_count) AS count"). Group("date"). + Order("date DESC"). Find(&storeManageDataList).Error if err != nil { - logger.Error("QueryStoreManageData count err:", logger.Field("err", err)) + logger.Error("QueryStoreManageData err:", logger.Field("err", err)) return nil, err } finalStoreManageDataList := constructFinalStoreManageDataList(storeManageDataList, req) - resp.Total = len(finalStoreManageDataList) - finalStoreManageDataList = nil if req.IsExport == 1 { //导出excel - // 查询数据 - err = qs.Select("DATE_FORMAT(maker_time, '%Y-%m-%d') AS date, SUM(total_amount) AS total_sales_amount, " + - "(SUM(total_retail_price) - SUM(total_amount)) AS promotion_fee, " + - "SUM(total_sales_profit) AS sales_profit, SUM(total_staff_profit) AS staff_profit, SUM(total_count) AS count"). - Group("date"). - Order("date DESC"). - Find(&storeManageDataList).Error - if err != nil { - logger.Error("QueryStoreManageData err:", logger.Field("err", err)) - return nil, err - } - storeName := "所有门店" if req.StoreId != 0 { storeInfo, err := GetStore(req.StoreId) @@ -1437,24 +1481,15 @@ func QueryStoreManageData(req *ErpOrderStoreManageDataReq) (*ErpOrderStoreManage resp.ExportUrl = filePath } else { - // 查询数据 - err = qs.Select("DATE_FORMAT(maker_time, '%Y-%m-%d') AS date, SUM(total_amount) AS total_sales_amount, " + - "(SUM(total_retail_price) - SUM(total_amount)) AS promotion_fee, " + - "SUM(total_sales_profit) AS sales_profit, SUM(total_staff_profit) AS staff_profit, SUM(total_count) AS count"). - Group("date"). - Order("date DESC"). - Offset(page * req.PageSize). - Limit(req.PageSize). - Find(&storeManageDataList).Error - if err != nil { - logger.Error("QueryStoreManageData err:", logger.Field("err", err)) - return nil, err + // 根据页码和页面条数截取结果 + startIndex := (req.PageIndex - 1) * req.PageSize + endIndex := startIndex + req.PageSize + if endIndex > len(finalStoreManageDataList) { + endIndex = len(finalStoreManageDataList) } + resp.List = finalStoreManageDataList[startIndex:endIndex] - finalStoreManageDataList = constructFinalStoreManageDataList(storeManageDataList, req) - resp.List = finalStoreManageDataList - resp.PageIndex = req.PageIndex - resp.PageSize = req.PageSize + resp.Total = len(finalStoreManageDataList) } return resp, nil @@ -1503,20 +1538,21 @@ func constructFinalStoreManageDataList(storeManageDataList []StoreManageData, re // StoreManageDataExport 导出门店经营数据 func storeManageDataExport(list []StoreManageData, storeName string) (string, error) { file := excelize.NewFile() - streamWriter, err := file.NewStreamWriter("Sheet1") - if err != nil { - fmt.Println(err) - } + fSheet := "Sheet1" url := ExportUrl fileName := time.Now().Format(TimeFormat) + storeName + "经营数据" + ".xlsx" fmt.Println("url fileName:", url+fileName) title := []interface{}{"时间", "销售额", "推广费", "销售毛利", "员工毛利", "销售数量"} - cell, _ := excelize.CoordinatesToCellName(1, 1) - if err = streamWriter.SetRow(cell, title); err != nil { - fmt.Println(err) + for i, _ := range title { + cell, _ := excelize.CoordinatesToCellName(1+i, 1) + err := file.SetCellValue(fSheet, cell, title[i]) + if err != nil { + logger.Errorf("file set value err:", err) + } } + var row []interface{} nExcelStartRow := 0 for rowId := 0; rowId < len(list); rowId++ { @@ -1529,20 +1565,38 @@ func storeManageDataExport(list []StoreManageData, storeName string) (string, er list[rowId].Count, } - cell, _ := excelize.CoordinatesToCellName(1, nExcelStartRow+2) - if err := streamWriter.SetRow(cell, row); err != nil { - fmt.Println(err) + for j, _ := range row { + cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2) + err := file.SetCellValue(fSheet, cell, row[j]) + if err != nil { + logger.Error("file set value err:", logger.Field("err", err)) + } } nExcelStartRow++ + } + + // 设置所有单元格的样式: 居中、加边框 + style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}, + "border":[{"type":"left","color":"000000","style":1}, + {"type":"top","color":"000000","style":1}, + {"type":"right","color":"000000","style":1}, + {"type":"bottom","color":"000000","style":1}]}`) + + //设置单元格高度 + file.SetRowHeight("Sheet1", 1, 20) + + // 设置单元格大小 + file.SetColWidth("Sheet1", "A", "A", 18) + + endRow := fmt.Sprintf("F"+"%d", nExcelStartRow+1) + // 应用样式到整个表格 + _ = file.SetCellStyle("Sheet1", "A1", endRow, style) - } - if err := streamWriter.Flush(); err != nil { - fmt.Println(err) - } fmt.Println("save fileName:", config.ExportConfig.Path+fileName) if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil { fmt.Println(err) } + return url + fileName, nil } @@ -1856,12 +1910,12 @@ func retailDetailExport(list []ErpOrder, sumData RetailDetailTotalData) (string, strSalesProfitPer := "" strStaffProfitPer := "" strSalesmanPer := "" - var salesList []ErpOrderSales - err := json.Unmarshal([]byte(list[i].SalesmanList), &salesList) - if err != nil { - logger.Error("unmarshal err:", logger.Field("err", err)) - } - for j, item := range salesList { + //var salesList []ErpOrderSales + //err := json.Unmarshal([]byte(list[i].SalesmanList), &salesList) + //if err != nil { + // logger.Error("unmarshal err:", logger.Field("err", err)) + //} + for j, item := range list[i].Salesman { salesMan += item.Name // 将浮点数转换为字符串,保留两位小数 strNumber1 := strconv.FormatFloat(item.SalesProfitPer, 'f', 2, 64) @@ -1871,7 +1925,7 @@ func retailDetailExport(list []ErpOrder, sumData RetailDetailTotalData) (string, strNumber3 := strconv.FormatFloat(item.SalesmanPer, 'f', 2, 64) strSalesmanPer += strNumber3 - if j < len(salesList)-1 { + if j < len(list[i].Salesman)-1 { salesMan += "\n" strSalesProfitPer += "\n" strStaffProfitPer += "\n" @@ -1882,7 +1936,7 @@ func retailDetailExport(list []ErpOrder, sumData RetailDetailTotalData) (string, // 组合支付相关信息 var cashierData TotalCashierData var cashiers []ErpOrderCashier - err = json.Unmarshal([]byte(list[i].CashierList), &cashiers) + err := json.Unmarshal([]byte(list[i].CashierList), &cashiers) if err != nil { logger.Error("unmarshal err:", logger.Field("err", err)) } @@ -2062,10 +2116,6 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai logger.Errorf("List err:", err) showConfig.ShowAll = "ON" } - resp := &ErpOrderRetailDetailResp{ - PageIndex: req.PageIndex, - PageSize: req.PageSize, - } page := req.PageIndex - 1 if page < 0 { @@ -2075,6 +2125,11 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai req.PageSize = 10 } + resp := &ErpOrderRetailDetailResp{ + PageIndex: page + 1, + PageSize: req.PageSize, + } + qs := orm.Eloquent.Debug().Table("erp_order_commodity"). Select("erp_order_commodity.*, erp_order.*"). Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id") @@ -2133,8 +2188,8 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai "SUM(erp_order_commodity.Amount) as Amount, " + "SUM(erp_order_commodity.wholesale_price) as wholesale_price, " + "(SUM(erp_order_commodity.wholesale_price) + SUM(erp_order_commodity.staff_cost_price)) as staff_price, " + - "(SUM(erp_order_commodity.Amount) - SUM(erp_order_commodity.wholesale_price)) as sales_profit, " + - "(SUM(erp_order_commodity.Amount) - SUM(erp_order_commodity.wholesale_price) - SUM(erp_order_commodity.staff_cost_price)) as staff_profit, " + + "SUM(erp_order_commodity.sales_profit) as sales_profit, " + + "SUM(erp_order_commodity.staff_profit) as staff_profit, " + "SUM(erp_order.total_retail_price) as total_retail_price, " + "(SUM(erp_order.total_retail_price) - SUM(erp_order.total_amount)) as total_discount, " + "SUM(erp_order.total_amount) as total_amount, " + @@ -2172,14 +2227,21 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai return resp, err } - sumData.TotalSalesProfitPer = totalPerData.TotalSalesProfitPer - sumData.TotalStaffProfitPer = totalPerData.TotalStaffProfitPer - sumData.SalesmanPer = totalPerData.SalesmanPer - sumData.ScanAmount = cashier.ScanAmount - sumData.CashAmount = cashier.CashAmount - sumData.PosAmount = cashier.PosAmount - sumData.StoreVmAmount = cashier.StoreVmAmount - sumData.OtherAmount = cashier.OtherAmount + //sumData.TotalSalesProfitPer = totalPerData.TotalSalesProfitPer + //sumData.TotalStaffProfitPer = totalPerData.TotalStaffProfitPer + //sumData.SalesmanPer = totalPerData.SalesmanPer + //sumData.ScanAmount = cashier.ScanAmount + //sumData.CashAmount = cashier.CashAmount + //sumData.PosAmount = cashier.PosAmount + //sumData.StoreVmAmount = cashier.StoreVmAmount + //sumData.OtherAmount = cashier.OtherAmount + + sumData.TotalSalesProfit = 0 // 订单总销售毛利 + sumData.TotalStaffProfit = 0 // 订单总员工毛利 + sumData.TotalRetailPrice = 0 // 订单总指导零售价 + sumData.TotalDiscount = 0 // 订单总优惠 + sumData.TotalAmount = 0 // 订单实收金额 + sumData.StorePer = 0 // 门店提成 var result []RetailDetailByJoin @@ -2219,8 +2281,8 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai } orders := packData(result) - erpOrderListSetCashier(orders) - erpOrderListSetSalesman(orders) + //erpOrderListSetCashier(orders) + //erpOrderListSetSalesman(orders) resp.List = orders @@ -2266,8 +2328,8 @@ func packData(result []RetailDetailByJoin) []ErpOrder { order.TotalRetailPrice = item.TotalRetailPrice order.TotalAmount = item.TotalAmount order.TotalCount = item.TotalCount - order.TotalSalesProfit = item.TotalSalesProfit - order.TotalStaffProfit = item.TotalStaffProfit + //order.TotalSalesProfit = item.TotalSalesProfit + //order.TotalStaffProfit = item.TotalStaffProfit order.VmCount = item.VmCount order.SaleOrderId = item.SaleOrderId order.PayStatus = item.PayStatus @@ -2305,6 +2367,8 @@ func packData(result []RetailDetailByJoin) []ErpOrder { commodity.WholesalePrice = item.WholesalePrice commodity.ErpSupplierId = item.ErpSupplierId commodity.ErpSupplierName = item.ErpSupplierName + commodity.SalesProfit = item.SalesProfit + commodity.StaffProfit = item.StaffProfit order.Commodities = append(order.Commodities, commodity) orderIdMap[item.ErpOrderId] = order @@ -2324,10 +2388,6 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai logger.Errorf("List err:", err) showConfig.ShowAll = "ON" } - resp := &ErpOrderRetailDetailResp{ - PageIndex: req.PageIndex, - PageSize: req.PageSize, - } page := req.PageIndex - 1 if page < 0 { @@ -2337,6 +2397,11 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai req.PageSize = 10 } + resp := &ErpOrderRetailDetailResp{ + PageIndex: page + 1, + PageSize: req.PageSize, + } + qs := orm.Eloquent.Table("erp_order") if showConfig.ShowAll == "OFF" { qs = qs.Where("invoice_code != ?", 0) @@ -2376,6 +2441,7 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai } } qs.Where("erp_order.pay_status = ?", HavePaid) + es := qs var sumData RetailDetailTotalData orderSumQs := qs @@ -2446,6 +2512,7 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai return resp, err } erpOrderListSetCommodity(orders) + erpOrderListSetSalesman(orders) fileUrl, err := retailDetailExport(orders, sumData) if err != nil { @@ -2454,6 +2521,13 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai } resp.ExportUrl = fileUrl } else { + var count int64 + err = es.Count(&count).Error + if err != nil { + logger.Error("count err:", logger.Field("err", err)) + return resp, err + } + var orders []ErpOrder err = qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&orders).Error if err != nil && err != RecordNotFound { @@ -2461,17 +2535,11 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai return resp, err } - var count int64 - err = qs.Count(&count).Error - if err != nil { - logger.Error("count err:", logger.Field("err", err)) - return resp, err - } - // 添加付款、销售员、商品信息 + erpOrderListSetCommodity(orders) erpOrderListSetCashier(orders) erpOrderListSetSalesman(orders) - erpOrderListSetCommodity(orders) + resp.List = orders //跟之前保持一致 @@ -2499,9 +2567,9 @@ func QueryReceiptData(req *ErpOrderDeleteReq) (*ErpOrderReceiptDataResp, error) } // 添加付款、销售员、商品信息 + erpOrderListSetCommodity(orders) erpOrderListSetCashier(orders) erpOrderListSetSalesman(orders) - erpOrderListSetCommodity(orders) // 查询门店信息 storeInfo, err := GetStore(orders[0].StoreId) @@ -2562,8 +2630,32 @@ func CreateErpOrder(req *ErpOrderCreateReq, sysUser *SysUser) error { return err } - // 1-创建零售订单 begin := orm.Eloquent.Begin() + // 0-创建用户信息 + userInfo, err := GetUserInfoByTel(req.Tel) + if err != nil { + logger.Error("checkOrderData GetUserInfoByTel err:", logger.Field("err", err)) + return errors.New("操作失败:" + err.Error()) + } + + if userInfo.Uid == 0 { + user := UserInfo{ + Uid: uint32(erpOrder.Uid), + Tel: req.Tel, + StoreId: uint64(req.StoreId), + UserType: 1, // 用户 + OpenMemberLevel: 1, // 普通会员 + MemberLevel: 1, // 普通会员 + } + err = begin.Create(&user).Error + if err != nil { + begin.Rollback() + logger.Error("create user err:", logger.Field("err", err)) + return errors.New("操作失败:" + err.Error()) + } + } + + // 1-创建零售订单 err = begin.Create(erpOrder).Error if err != nil { begin.Rollback() @@ -2645,6 +2737,7 @@ func EditErpOrder(req *ErpOrderCreateReq, sysUser *SysUser) error { } erpOrder.ID = orderInfo.ID + erpOrder.BillSn = orderInfo.BillSn // 编辑的订单单据号不能改变 begin := orm.Eloquent.Begin() // 1-更新零售订单 err = begin.Model(&ErpOrder{}).Where("id = ?", orderInfo.ID).Updates(erpOrder).Error @@ -2696,10 +2789,24 @@ func checkOrderData(req *ErpOrderCreateReq, sysUser *SysUser) (*ErpOrder, error) return nil, errors.New("操作失败:" + err.Error()) } + // 通过手机号查询用户id,如果没有,则新建一个用户id + userInfo, err := GetUserInfoByTel(req.Tel) + if err != nil { + logger.Error("checkOrderData GetUserInfoByTel err:", logger.Field("err", err)) + return nil, errors.New("操作失败:" + err.Error()) + } + + var userUid uint32 + if userInfo.Uid == 0 { + userUid = CreateUid() // 没有用户则新建 + } else { + userUid = userInfo.Uid + } + erpOrder := &ErpOrder{ BillSn: NewErpBillSn(), RetailType: req.RetailType, - Uid: sysUser.UserId, // todo 待修改为用户id + Uid: int(userUid), Tel: req.Tel, StoreId: req.StoreId, StoreName: req.StoreName, @@ -2754,14 +2861,14 @@ func checkOrderData(req *ErpOrderCreateReq, sysUser *SysUser) (*ErpOrder, error) return nil, errors.New("操作失败:" + err.Error()) } - for i, _ := range commodities { // 非串码 - v, ok := commodityMap[req.ErpOrderCommodities[i].ErpCommodityId] + for _, commodity := range commodities { // 非串码 + v, ok := commodityMap[commodity.ErpCommodityId] if !ok { // 没有则直接添加 - commodityMap[commodities[i].ErpCommodityId] = commodities[i] + commodityMap[commodity.ErpCommodityId] = commodity } else { // 已有则比较非串码的入库时间,添加入库时间最早的商品 - if commodities[i].FirstStockTime.Before(v.FirstStockTime) { - commodityMap[commodities[i].ErpCommodityId] = commodities[i] + if commodity.FirstStockTime.Before(v.FirstStockTime) { + commodityMap[commodity.ErpCommodityId] = commodity } } } @@ -2811,9 +2918,11 @@ func checkOrderData(req *ErpOrderCreateReq, sysUser *SysUser) (*ErpOrder, error) return nil, errors.New("退货数量大于销售数量") } - // 更新订单表总退款金额和数量 - erpOrder.RejectedTotalAmount += req.ErpOrderCommodities[i].RejectedAmount - erpOrder.RejectedTotalCount += req.ErpOrderCommodities[i].RejectedCount + // 更新订单表总退款金额和数量 备注:2024-03-12 订单表没有退款金额的字段,默认都使用订单金额字段,根据订单类型判断是零售或退款 + //erpOrder.RejectedTotalAmount += req.ErpOrderCommodities[i].RejectedAmount + //erpOrder.RejectedTotalCount += req.ErpOrderCommodities[i].RejectedCount + erpOrder.TotalAmount += req.ErpOrderCommodities[i].ReceivedAmount + erpOrder.TotalCount += req.ErpOrderCommodities[i].Count // 销售毛利 // todo 待测试核实 salesProfit := v.ReceivedAmount - float64(v.WholesalePrice*v.Count) @@ -2855,10 +2964,12 @@ func checkOrderData(req *ErpOrderCreateReq, sysUser *SysUser) (*ErpOrder, error) } req.ErpOrderCommodities[i].ID = 0 - req.ErpOrderCommodities[i].ErpCommodityId = v.ID // 商品id + req.ErpOrderCommodities[i].ErpCommodityId = v.ErpCommodityId // 商品id req.ErpOrderCommodities[i].ErpCommodityName = v.ErpCommodityName // 商品名称 req.ErpOrderCommodities[i].ErpCategoryId = v.ErpCategoryId // 分类id req.ErpOrderCommodities[i].ErpCategoryName = v.ErpCategoryName // 分类名称 + req.ErpOrderCommodities[i].ErpSupplierId = v.ErpSupplierId // 供应商id + req.ErpOrderCommodities[i].ErpSupplierName = v.ErpSupplierName // 供应商名称 req.ErpOrderCommodities[i].RetailPrice = v.RetailPrice // 指导零售价 req.ErpOrderCommodities[i].MemberDiscount = v.MemberDiscount // 会员优惠 req.ErpOrderCommodities[i].StaffCostPrice = v.StaffCostPrice // 员工成本价加价 @@ -2951,7 +3062,7 @@ func updateCommodityData(gdb *gorm.DB, orderId uint32, req *ErpOrderCreateReq) e for _, dbCommodity := range commodities { var found bool for _, reqCommodity := range req.ErpOrderCommodities { - if reqCommodity.ID == dbCommodity.ID { + if reqCommodity.ErpCommodityId == dbCommodity.ErpCommodityId { found = true // 找到匹配的商品,加入匹配列表 matchingCommodities = append(matchingCommodities, dbCommodity) @@ -2964,10 +3075,11 @@ func updateCommodityData(gdb *gorm.DB, orderId uint32, req *ErpOrderCreateReq) e } // 2-更新商品订单信息-更新 - err = gdb.Updates(&matchingCommodities).Error - if err != nil { - logger.Error("更新商品订单信息-更新 error") - return errors.New("操作失败:" + err.Error()) + for _, commodity := range matchingCommodities { + if err = gdb.Model(&ErpOrderCommodity{}).Where("id = ?", commodity.ID).Updates(commodity).Error; err != nil { + logger.Error("更新商品订单信息-更新 error") + return errors.New("操作失败:" + err.Error()) + } } // 2-更新商品订单信息-新增 @@ -3035,10 +3147,11 @@ func updateSalesData(gdb *gorm.DB, orderId uint32, req *ErpOrderCreateReq) error } // 更新 - err = gdb.Updates(&matchingOrderSales).Error - if err != nil { - logger.Error("更新订单销售员信息-更新 error") - return errors.New("操作失败:" + err.Error()) + for _, orderSaleInfo := range matchingOrderSales { + if err = gdb.Model(&ErpOrderSales{}).Where("id = ?", orderSaleInfo.ID).Updates(orderSaleInfo).Error; err != nil { + logger.Error("更新订单销售员信息-更新 error") + return errors.New("操作失败:" + err.Error()) + } } // 新增 @@ -3112,10 +3225,11 @@ func updatePayWayData(gdb *gorm.DB, orderId uint32, req *ErpOrderCreateReq) erro } // 更新 - err = gdb.Updates(&matchingOrderPayWay).Error - if err != nil { - logger.Error("更新零售订单支付方式-更新 error") - return errors.New("操作失败:" + err.Error()) + for _, orderPayWayInfo := range matchingOrderPayWay { + if err = gdb.Model(&ErpOrderPayWay{}).Where("id = ?", orderPayWayInfo.ID).Updates(orderPayWayInfo).Error; err != nil { + logger.Error("更新零售订单支付方式-更新 error") + return errors.New("操作失败:" + err.Error()) + } } // 新增 diff --git a/app/admin/models/file.go b/app/admin/models/file.go index 4c9042e..285ebb7 100644 --- a/app/admin/models/file.go +++ b/app/admin/models/file.go @@ -2,6 +2,7 @@ package models import ( "bytes" + "database/sql" "encoding/json" "errors" "fmt" @@ -1010,27 +1011,64 @@ func getNumberOnCategory(categoryId uint32) int64 { return count } +//// GenerateSerialNumber 生成商品编号(会有重复编码) +//func GenerateSerialNumber(categoryId uint32) (string, error) { +// var category Category +// err := orm.Eloquent.Debug().Model(&Category{}). +// Where("id = ?", categoryId).First(&category).Error +// if errors.Is(err, gorm.ErrRecordNotFound) { +// return "", errors.New("未查到商品分类") +// } +// +// var count int64 +// orm.Eloquent.Debug().Model(&ErpCommodity{}). +// Where("erp_category_id = ?", category.ID). +// Count(&count) +// +// serialNumber := fmt.Sprintf("%s%04d", category.Number, count+1) +// fmt.Println("商品编号:", serialNumber) +// return serialNumber, nil +//} + // GenerateSerialNumber 生成商品编号 func GenerateSerialNumber(categoryId uint32) (string, error) { - var category Category - err := orm.Eloquent.Debug().Model(&Category{}). - Where("id = ?", categoryId).First(&category).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return "", errors.New("未查到商品分类") + // 查询商品分类 + var category ErpCategory + if err := orm.Eloquent.Debug().Model(&ErpCategory{}). + Where("id = ?", categoryId).First(&category).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return "", errors.New("未查到商品分类") + } + return "", err } - var count int64 - orm.Eloquent.Debug().Model(&ErpCommodity{}). - Where("erp_category_id = ?", category.ID). - Count(&count) + // 查询该商品分类下最大的商品编号 + var maxSerialNumber sql.NullString + if err := orm.Eloquent.Debug().Model(&ErpCommodity{}). + Where("erp_category_id = ?", categoryId). + Select("MAX(serial_number)"). + Row().Scan(&maxSerialNumber); err != nil && !errors.Is(err, sql.ErrNoRows) { + return "", err + } - serialNumber := fmt.Sprintf("%s%04d", category.Number, count+1) + // 处理 NULL 值 + var lastNumber uint64 + if maxSerialNumber.Valid { + lastSerial := maxSerialNumber.String + lastNumberStr := lastSerial[len(category.Number):] + lastNumber, _ = strconv.ParseUint(lastNumberStr, 10, 32) + } + + // 递增生成新的商品编号 + newNumber := lastNumber + 1 + + serialNumber := fmt.Sprintf("%s%04d", category.Number, newNumber) fmt.Println("商品编号:", serialNumber) return serialNumber, nil } // UpdateErpStockAmountInfo 更新库存和库存商品表的金额:指导零售价、最低零售价 -func UpdateErpStockAmountInfo(begin *gorm.DB, commodityId, retailPrice, minRetailPrice uint32) error { +func UpdateErpStockAmountInfo(begin *gorm.DB, commodityId, retailPrice, minRetailPrice uint32, barCode string) error { // 更新库存表 err := begin.Table("erp_stock").Where("erp_commodity_id=?", commodityId). Updates(map[string]interface{}{ @@ -1046,6 +1084,7 @@ func UpdateErpStockAmountInfo(begin *gorm.DB, commodityId, retailPrice, minRetai Updates(map[string]interface{}{ "retail_price": retailPrice, "min_retail_price": minRetailPrice, + "erp_barcode": barCode, }).Error if err != nil { return err diff --git a/app/admin/models/greentown_sms.go b/app/admin/models/greentown_sms.go index 29bef44..203541e 100644 --- a/app/admin/models/greentown_sms.go +++ b/app/admin/models/greentown_sms.go @@ -5,6 +5,7 @@ import ( "crypto/md5" "encoding/hex" "encoding/json" + "errors" "fmt" "go-admin/logger" "io" @@ -50,6 +51,10 @@ type GtSendMessageResp struct { } func GtSendMessage(phoneList []string, content string) error { + if len(phoneList) > GetSmsNumberRemaining() { // 待发送短信超出剩余可用数量 + return errors.New("短信剩余数量不足") + } + params := make(map[string]interface{}, 0) nowTime := time.Now() fmt.Println("nowTime.UnixMicro", nowTime.UnixMilli()) @@ -64,6 +69,14 @@ func GtSendMessage(phoneList []string, content string) error { return err } 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 + } + return nil } diff --git a/app/admin/models/order.go b/app/admin/models/order.go index 677d76a..34ce200 100644 --- a/app/admin/models/order.go +++ b/app/admin/models/order.go @@ -495,7 +495,7 @@ func OrderListExport(list []Order) (string, error) { // user有可能为空 memberExpire := "" if list[rowId].User != nil { - memberExpire = calculateRemainingDays(list[rowId].User.MemberExpire) + memberExpire = calculateRemainingDays(*list[rowId].User.MemberExpire) } for i := 0; i < len(list[rowId].OrderCards); i++ { diff --git a/app/admin/models/purchase.go b/app/admin/models/purchase.go index bc09aba..fd69586 100644 --- a/app/admin/models/purchase.go +++ b/app/admin/models/purchase.go @@ -84,6 +84,7 @@ type ErpPurchaseCommodity struct { ExecutionPrice float64 `json:"execute_price" gorm:"-"` // 平均采购单价 ExecutionEmployeePrice float64 `json:"execute_employee_price" gorm:"-"` // 平均员工成本价 ExecutionAmount float64 `json:"execute_amount" gorm:"-"` // 执行金额 + DefaultEmployeePrice float64 `json:"default_employee_price" gorm:"-"` // 默认员工成本价 } // ErpPurchaseInventory 采购入库执行信息 @@ -109,17 +110,17 @@ type ErpPurchaseInventory struct { // ErpPurchaseCreateReq 新建采购订单入参 type ErpPurchaseCreateReq struct { PurchaseType string `json:"purchase_type" binding:"required"` // 采购类型:procure-采购 reject-退货 - PurchaseOrderSn string `json:"purchase_order_sn"` // 采购退货订单号 - StoreId uint32 `json:"store_id"` // 门店id - DeliveryAddress string `json:"delivery_address"` // 交货地址 - HandlerId uint32 `json:"handler_id" gorm:"index"` // 经手人id + PurchaseOrderSn string `json:"purchase_order_sn"` // 采购退货订单号:出库必传 + StoreId uint32 `json:"store_id"` // 门店id:入库必传 + DeliveryAddress string `json:"delivery_address"` // 交货地址:入库必传 + HandlerId uint32 `json:"handler_id" binding:"required"` // 经手人id HandlerName string `json:"handler_name"` // 经手人名称 - ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id - ErpCashierId uint32 `json:"erp_cashier_id"` // 付款方式 - AccountHolder string `json:"account_holder"` // 收款人 - OpeningBank string `json:"opening_bank" ` // 开户行 - BankAccount string `json:"bank_account" ` // 银行卡号 - DeliveryTime string `json:"delivery_time" ` // 交货日期 + ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id:入库必传 + ErpCashierId uint32 `json:"erp_cashier_id" binding:"required"` // 付款方式 + AccountHolder string `json:"account_holder"` // 收款人:入库必传 + OpeningBank string `json:"opening_bank"` // 开户行:入库必传 + BankAccount string `json:"bank_account" ` // 银行卡号:入库必传 + DeliveryTime string `json:"delivery_time" ` // 交货日期:入库必传 Remark string `json:"remark"` // 备注 ErpPurchaseCommodities []ErpPurchaseCommodity `json:"erp_purchase_commodity" binding:"required"` // 采购商品信息 } @@ -128,17 +129,17 @@ type ErpPurchaseCreateReq struct { type ErpPurchaseEditReq struct { ErpPurchaseOrderId uint32 `json:"erp_purchase_order_id" binding:"required"` // 采购订单id PurchaseType string `json:"purchase_type" binding:"required"` // 采购类型:procure-采购 reject-退货 - PurchaseOrderSn string `json:"purchase_order_sn"` // 采购退货订单号 - StoreId uint32 `json:"store_id" binding:"required"` // 门店id - DeliveryAddress string `json:"delivery_address" binding:"required"` // 交货地址 - HandlerId uint32 `json:"handler_id" gorm:"index"` // 经手人id + PurchaseOrderSn string `json:"purchase_order_sn"` // 采购退货订单号:出库必传 + StoreId uint32 `json:"store_id"` // 门店id:入库必传 + DeliveryAddress string `json:"delivery_address"` // 交货地址:入库必传 + HandlerId uint32 `json:"handler_id" binding:"required"` // 经手人id HandlerName string `json:"handler_name"` // 经手人名称 - ErpSupplierId uint32 `json:"erp_supplier_id" binding:"required"` // 供应商id + ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id:入库必传 ErpCashierId uint32 `json:"erp_cashier_id" binding:"required"` // 付款方式 - AccountHolder string `json:"account_holder"` // 收款人 - OpeningBank string `json:"opening_bank" validate:"required"` // 开户行 - BankAccount string `json:"bank_account" validate:"required"` // 银行卡号 - DeliveryTime string `json:"delivery_time" binding:"required"` // 交货日期 + AccountHolder string `json:"account_holder"` // 收款人:入库必传 + OpeningBank string `json:"opening_bank"` // 开户行:入库必传 + BankAccount string `json:"bank_account" ` // 银行卡号:入库必传 + DeliveryTime string `json:"delivery_time"` // 交货日期:入库必传 Remark string `json:"remark"` // 备注 ErpPurchaseCommodities []ErpPurchaseCommodity `json:"erp_purchase_commodity" binding:"required"` // 采购商品信息 } @@ -153,6 +154,7 @@ type ErpPurchaseOrderListReq struct { AuditTimeEnd string `json:"audit_time_end"` // 审核结束时间 AuditFlag string `json:"audit_flag"` // 审核标记(默认展示所有):ON-订单只展示已审核的采购入库订单,含待入库/已终止/已完成 State uint32 `json:"state"` // 状态:1-待审核 2-待入库 3-待退货 4-已完成 5-已终止 + HandlerId uint32 `json:"handler_id"` // 经手人id PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 页面条数 } @@ -189,6 +191,11 @@ type ErpPurchaseTerminateReq struct { Remark string `json:"remark" binding:"required"` // 备注 } +// ErpPurchaseDeleteReq 删除采购单入参 +type ErpPurchaseDeleteReq struct { + SerialNumber string `json:"serial_number" binding:"required"` // 单据编号 +} + // ErpPurchaseExecuteResp 执行(入库/退货)出参 type ErpPurchaseExecuteResp struct { List []ExecuteData `json:"list"` @@ -412,19 +419,16 @@ type PurchaseData struct { // ErpPurchaseReportBySupplierReq 供应商采购汇总入参 type ErpPurchaseReportBySupplierReq struct { - PurchaseType string `json:"purchase_type"` // 采购类型:procure-采购 reject-退货 - ErpCommodityName string `json:"erp_commodity_name"` // 商品名称 - ErpCategoryID uint32 `json:"erp_category_id"` // 商品分类id - ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id - StartTime string `json:"startTime"` // 入/出库,开始时间 - EndTime string `json:"endTime"` // 入/出库,结束时间 - IsExport uint32 `json:"is_export"` // 1-导出 - PageIndex int `json:"pageIndex"` // 页码 - PageSize int `json:"pageSize"` // 页面条数 - StoreList []struct { - StoreID uint32 `json:"store_id"` // 门店id - StoreName string `json:"store_name"` // 门店名称 - } `json:"store_list"` // 门店复选 + PurchaseType string `json:"purchase_type"` // 采购类型:procure-采购 reject-退货 + ErpCommodityName []string `json:"erp_commodity_name"` // 商品名称 + ErpCategoryID []uint32 `json:"erp_category_id"` // 商品分类id + ErpSupplierId []uint32 `json:"erp_supplier_id"` // 供应商id + StartTime string `json:"start_time"` // 入/出库,开始时间 + EndTime string `json:"end_time"` // 入/出库,结束时间 + IsExport uint32 `json:"is_export"` // 1-导出 + PageIndex int `json:"pageIndex"` // 页码 + PageSize int `json:"pageSize"` // 页面条数 + StoreList []uint32 `json:"store_list"` // 门店复选 } // ErpPurchaseReportBySupplierResp 供应商采购汇总出参 @@ -556,6 +560,9 @@ func (m *ErpPurchaseOrderListReq) List() (*ErpPurchaseOrderListResp, error) { //parse = parse.AddDate(0, 0, 1) qs = qs.Where("audit_time < ?", parse) } + if m.HandlerId != 0 { + qs = qs.Where("handler_id=?", m.HandlerId) + } } var count int64 @@ -586,7 +593,7 @@ func NewErpPurchaseSn() string { logger.Error("create sn err") return "" } - random := rand.Int31n(9999) + 1000 + random := rand.Intn(9000) + 1000 sn := fmt.Sprintf("%s%d", nowTime.Format("060102"), random) exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_purchase_order WHERE serial_number='%s'", sn)) if err != nil { @@ -686,6 +693,76 @@ func GetPurchaseInventorySn() string { } } +// CheckCreateErpPurchaseOrderParam 新增采购订单-检查参数 +func CheckCreateErpPurchaseOrderParam(req *ErpPurchaseCreateReq) error { + if req.PurchaseType == ErpProcureOrder { // 采购入库订单 + if req.StoreId == 0 { + return errors.New("操作失败:门店id为空") + } + if req.DeliveryAddress == "" { + return errors.New("操作失败:交货地址为空") + } + if req.ErpSupplierId == 0 { + return errors.New("操作失败:供应商id为空") + } + if req.AccountHolder == "" { + return errors.New("操作失败:收款人为空") + } + if req.OpeningBank == "" { + return errors.New("操作失败:开户行为空") + } + if req.BankAccount == "" { + return errors.New("操作失败:银行卡号为空") + } + if req.DeliveryTime == "" { + return errors.New("操作失败:交货日期为空") + } + } else if req.PurchaseType == ErpRejectOrder { // 退货单 + if req.PurchaseOrderSn == "" { + return errors.New("操作失败:采购退货单据编号为空") + } + } else { + return errors.New("操作失败:采购类型有误") + } + + return nil +} + +// CheckEditErpPurchaseOrderParam 编辑采购订单-检查参数 +func CheckEditErpPurchaseOrderParam(req *ErpPurchaseEditReq) error { + if req.PurchaseType == ErpProcureOrder { // 采购入库订单 + if req.StoreId == 0 { + return errors.New("操作失败:门店id为空") + } + if req.DeliveryAddress == "" { + return errors.New("操作失败:交货地址为空") + } + if req.ErpSupplierId == 0 { + return errors.New("操作失败:供应商id为空") + } + if req.AccountHolder == "" { + return errors.New("操作失败:收款人为空") + } + if req.OpeningBank == "" { + return errors.New("操作失败:开户行为空") + } + if req.BankAccount == "" { + return errors.New("操作失败:银行卡号为空") + } + if req.DeliveryTime == "" { + return errors.New("操作失败:交货日期为空") + } + } else if req.PurchaseType == ErpRejectOrder { // 退货单 + if req.PurchaseOrderSn == "" { + return errors.New("操作失败:采购退货单据编号为空") + } + } else { + return errors.New("操作失败:采购类型有误") + } + + return nil +} + // CreateErpPurchaseOrder 新增采购订单 func CreateErpPurchaseOrder(req *ErpPurchaseCreateReq, sysUser *SysUser) (*ErpPurchaseOrder, error) { var err error @@ -794,6 +871,11 @@ func EditErpPurchaseOrder(req *ErpPurchaseEditReq, sysUser *SysUser) (*ErpPurcha if purchaseOrder.State != ErpPurchaseOrderUnAudit { // 只有待审核的订单才能编辑 return nil, errors.New("订单不是待审核状态") } + + if req.StoreId == 0 && req.PurchaseType == ErpProcureOrder { + return nil, errors.New("操作失败:门店id为空") + } + begin := orm.Eloquent.Begin() // 1-更新采购订单信息 purchaseOrder.StoreId = req.StoreId @@ -936,6 +1018,7 @@ func InventoryErpPurchase(req *ErpPurchaseInventoryReq) error { logger.Error("update inventory count err:", logger.Field("err", err)) return err } + v.PurchaseType = req.PurchaseType // 记录采购类型 // 新建采购入库记录 err = begin.Create(&v).Error if err != nil { @@ -1036,8 +1119,8 @@ func InventoryErpPurchaseUpdateStock(gdb *gorm.DB, req *ErpPurchaseInventoryReq, ErpSupplierName: purchaseOrder.ErpSupplierName, StaffCostPrice: uint32(v.EmployeePrice - v.ImplementationPrice), WholesalePrice: uint32(v.ImplementationPrice), - State: 1, - StorageType: 1, + State: InStock, + StorageType: PurchaseInventory, // 采购入库 FirstStockTime: nowTime, StockTime: nowTime, Count: v.Count, @@ -1142,7 +1225,10 @@ func checkPurchaseInventory(req *ErpPurchaseInventoryReq) error { } countMap := make(map[uint32]uint32) - for _, inventory := range req.Inventories { + for i, inventory := range req.Inventories { + if inventory.ErpCommodityId == 0 { + return fmt.Errorf("商品Id传参错误,不能为0") + } countMap[inventory.ErpCommodityId] += inventory.Count // 如果该商品是串码商品,判断其串码是否会重复 @@ -1152,9 +1238,24 @@ func checkPurchaseInventory(req *ErpPurchaseInventoryReq) error { logger.Error("exist sn err") } if exist { - return fmt.Errorf("串码重复[%s]", inventory.IMEI) + return fmt.Errorf("串码有重复项请修改[%s]", inventory.IMEI) } } + + // 备注:员工成本价在"库存管理-采购单入库"里面的入库操作前端是隐藏不可修改的,会默认传0 + if inventory.EmployeePrice != 0 && inventory.EmployeePrice < inventory.ImplementationPrice { + return fmt.Errorf("数据错误,员工成本价不能低于采购执行单价") + } + + if inventory.EmployeePrice == 0 { // 没有传入员工成本价,则默认按照商品资料设置的员工成本价加价金额 + erpCommodity, err := GetCommodity(inventory.ErpCommodityId) + if err != nil { + logger.Error("checkPurchaseInventory GetCommodity err:", logger.Field("err", err)) + return fmt.Errorf("查询员工成本价报错") + } + + req.Inventories[i].EmployeePrice = inventory.ImplementationPrice + float64(erpCommodity.StaffCostPrice) + } } // 入库的商品信息有误,不在之前的商品列表中 @@ -2393,12 +2494,12 @@ type Result struct { } // GetTotalsAndAveragesByCommodityID 查询执行数量之和、平均执行单价、执行金额之和和平均员工成本价 -func GetTotalsAndAveragesByCommodityID(commodityID uint32) (Result, error) { +func GetTotalsAndAveragesByCommodityID(commodityID, orderID uint32) (Result, error) { var result Result err := orm.Eloquent.Table("erp_purchase_inventory"). Select("SUM(`count`) AS total_count, AVG(`implementation_price`) AS avg_implementation_price, "+ "SUM(`amount`) AS total_amount, AVG(`employee_price`) AS avg_employee_price"). - Where("erp_commodity_id = ?", commodityID). + Where("erp_commodity_id = ? and erp_purchase_order_id = ?", commodityID, orderID). Scan(&result).Error if err != nil { return Result{}, err @@ -2637,7 +2738,7 @@ func getReportByOrderFromCommodityOrCategory(req *ErpPurchaseReportByOrderReq) ( req.PageSize = 10 } resp := &ErpPurchaseReportByOrderResp{ - PageIndex: req.PageIndex + 1, + PageIndex: page + 1, PageSize: req.PageSize, } qs := orm.Eloquent.Table("erp_purchase_inventory") @@ -2754,7 +2855,7 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq) (*ErpPurchaseR req.PageSize = 10 } resp := &ErpPurchaseReportByOrderResp{ - PageIndex: req.PageIndex + 1, + PageIndex: page + 1, PageSize: req.PageSize, } qs := orm.Eloquent.Table("erp_purchase_order") @@ -3068,7 +3169,7 @@ func getReportByCommodityFromCommodityOrCategory(req *ErpPurchaseReportByCommodi req.PageSize = 10 } resp := &ErpPurchaseReportByCommodityResp{ - PageIndex: req.PageIndex + 1, + PageIndex: page + 1, PageSize: req.PageSize, } @@ -3881,15 +3982,30 @@ func GetReportBySupplier(req *ErpPurchaseReportBySupplierReq) (*ErpPurchaseRepor if req.PurchaseType != "" { query = query.Where("erp_purchase_inventory.purchase_type = ?", req.PurchaseType) } - if req.ErpCommodityName != "" { - query = query.Where("erp_purchase_inventory.erp_commodity_name = ?", req.ErpCommodityName) + if len(req.ErpCommodityName) != 0 { + var commodityNameList []string + for _, commodityName := range req.ErpCommodityName { + commodityNameList = append(commodityNameList, commodityName) + } + query = query.Where("erp_purchase_inventory.erp_commodity_name IN (?)", commodityNameList) } - if req.ErpCategoryID != 0 { - query = query.Where("erp_purchase_inventory.erp_category_id = ?", req.ErpCategoryID) + + if len(req.ErpCategoryID) != 0 { + var erpCategoryIDs []uint32 + for _, categoryID := range req.ErpCategoryID { + erpCategoryIDs = append(erpCategoryIDs, categoryID) + } + query = query.Where("erp_purchase_inventory.erp_category_id IN (?)", erpCategoryIDs) } - if req.ErpSupplierId != 0 { - query = query.Where("erp_purchase_inventory.erp_supplier_id = ?", req.ErpSupplierId) + + if len(req.ErpSupplierId) != 0 { + var supplierIDs []uint32 + for _, supplier := range req.ErpSupplierId { + supplierIDs = append(supplierIDs, supplier) + } + query = query.Where("erp_purchase_inventory.erp_supplier_id IN (?)", supplierIDs) } + if req.StartTime != "" { // 入/出库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { @@ -3898,6 +4014,7 @@ func GetReportBySupplier(req *ErpPurchaseReportBySupplierReq) (*ErpPurchaseRepor } query = query.Where("erp_purchase_inventory.created_at >= ?", parse) } + if req.EndTime != "" { // 入/出库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { @@ -3910,7 +4027,7 @@ func GetReportBySupplier(req *ErpPurchaseReportBySupplierReq) (*ErpPurchaseRepor if len(req.StoreList) > 0 { var storeIDs []uint32 for _, store := range req.StoreList { - storeIDs = append(storeIDs, store.StoreID) + storeIDs = append(storeIDs, store) } query = query.Where("erp_purchase_order.store_id IN (?)", storeIDs) } diff --git a/app/admin/models/sms_summary.go b/app/admin/models/sms_summary.go new file mode 100644 index 0000000..0b73e39 --- /dev/null +++ b/app/admin/models/sms_summary.go @@ -0,0 +1,78 @@ +package models + +import ( + "database/sql" + orm "go-admin/common/global" + "gorm.io/gorm" + "time" +) + +const monthlyLimit = 1000 // 每月的短信限额为 1000 + +type SmsSummary struct { + Model + + Year int `json:"year"` // 年 + Month int `json:"month"` // 月 + Used int `json:"used"` // 短信已发送数量 +} + +// GetSmsNumberRemaining 查询本月短信剩余数量 +func GetSmsNumberRemaining() int { + // 获取当前时间的年份和月份 + now := time.Now() + year, month, _ := now.Date() + + var totalUsed sql.NullInt64 + + // 查询当前年份和月份的短信发送总数 + if err := orm.Eloquent.Debug().Model(&SmsSummary{}). + Where("year = ? AND month = ?", year, int(month)). + Select("SUM(used)"). + Scan(&totalUsed).Error; err != nil { + return 0 + } + + // 获取每月短信限额 + nMonthlyLimit, err := GetSystemSmsConfig() + if err != nil { + nMonthlyLimit = monthlyLimit + } + + remaining := nMonthlyLimit - int(totalUsed.Int64) + + return remaining +} + +// UpdateSmsUsedCount 更新本月已使用短信数量 +func UpdateSmsUsedCount(count int) error { + // 获取当前时间的年份和月份 + now := time.Now() + year, month, _ := now.Date() + + // 查询当前年份和月份的短信发送记录 + var smsSummary SmsSummary + if err := orm.Eloquent.Where("year = ? AND month = ?", year, int(month)).First(&smsSummary).Error; err != nil { + if err == gorm.ErrRecordNotFound { + // 如果记录不存在,则创建新记录 + smsSummary = SmsSummary{ + Year: year, + Month: int(month), + Used: count, // 使用传入的 count 初始化已使用数量 + } + if err := orm.Eloquent.Create(&smsSummary).Error; err != nil { + return err + } + } else { + return err + } + } else { + // 如果记录存在,则更新已使用的短信数量 + smsSummary.Used += count + if err := orm.Eloquent.Model(&smsSummary).Updates(&SmsSummary{Used: smsSummary.Used}).Error; err != nil { + return err + } + } + + return nil +} diff --git a/app/admin/models/user.go b/app/admin/models/user.go index e997a69..f753e93 100644 --- a/app/admin/models/user.go +++ b/app/admin/models/user.go @@ -55,9 +55,9 @@ type UserInfo struct { Model Uid uint32 `json:"uid" gorm:"column:uid;unique_index"` // - MemberLevel uint32 `json:"memberLevel"` // 会员等级 1-会员 - MemberExpire time.Time `json:"memberExpire"` // 会员到期时间 - OpenMemberTime time.Time `json:"open_member_time"` // 开通会员时间 + MemberLevel uint32 `json:"member_level"` // 当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 + MemberExpire *time.Time `json:"member_expire"` // 会员到期时间 + OpenMemberTime *time.Time `json:"open_member_time"` // 开通会员时间 Bond uint32 `json:"bond"` // 保证金 WxName string `json:"wxName"` // 昵称 WxAvatar string `json:"wxAvatar"` // 头像 @@ -75,25 +75,25 @@ type UserInfo struct { OpenMemberChannel string `json:"open_member_channel" ` // 开通会员渠道: -门店推广 -用户邀请 -兑换码 StoreId uint64 `json:"store_id"` // 门店id InviteCodeUrl string `json:"invite_code_url"` // 分享二维码 - MemberOpenTime time.Time `json:"member_open_time" gorm:"-"` // - LastLoginAt time.Time `json:"last_login_at"` // 最近登录时间 + MemberOpenTime *time.Time `json:"member_open_time" gorm:"-"` // + LastLoginAt *time.Time `json:"last_login_at"` // 最近登录时间 IP string `json:"-" gorm:"type:varchar(60)"` // ip InBlack bool `json:"in_black"` // 是否在黑名单 CooperativeBusinessId uint32 `json:"cooperative_business_id" gorm:"index"` // 合作商id CooperativeName string `json:"cooperative_name"` // 合作商名称 Version uint32 `json:"-"` // MemberStatus uint8 `json:"member_status" gorm:"-"` // - InviteTime time.Time `json:"invite_time"` // - OpenMemberLevel uint32 `json:"open_member_level"` // 开通会员级别:2-黄金会员 4-白金会员 5-黑金会员 + InviteTime *time.Time `json:"invite_time"` // + OpenMemberLevel uint32 `json:"open_member_level"` // 开通会员级别:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 ShopAssistantName string `json:"shop_assistant_name"` // 店员名称 - RenewalTime time.Time `json:"renewal_time"` // - RenewalMemberLevel uint32 `json:"renewal_member_level"` // Mark int8 `json:"mark"` // 标记 - FirstRetailOrder time.Time `json:"first_retail_order"` // 首次零售开单时间 - MemberLevelString string `json:"member_level_string" gorm:"-"` // 会员类型 + FirstRetailOrder *time.Time `json:"first_retail_order"` // 首次零售开单时间 Store *Store `json:"store" gorm:"-"` // OrderCards []OrderCard `json:"order_cards" gorm:"foreignKey:uid;references:uid"` // ForfeitPenalty int `json:"forfeit_penalty" gorm:"-"` // 滞纳金 + //RenewalTime *time.Time `json:"renewal_time"` // + //RenewalMemberLevel uint32 `json:"renewal_member_level"` // + //MemberLevelString string `json:"member_level_string" gorm:"-"` // 会员类型 } func (m *UserInfo) TableName() string { @@ -255,8 +255,8 @@ type NewUserListReq struct { Tel string `json:"tel"` // 手机号 StoreId int `json:"store_id"` // 门店id UserType int `json:"user_type"` // 用户类型 用户类型 1-普通用户 2-店员 - OpenMemberLevel int `json:"open_member_level"` // 首次开通租卡会员等级 - MemberLevel int `json:"memberLevel"` // 当前会员等级 + OpenMemberLevel []int `json:"open_member_level"` // 首次开通租卡会员等级:2-黄金会员 4-白金会员 5-黑金会员 + MemberLevel []int `json:"member_level"` // 当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 CreateStartTime string `json:"create_startTime"` // 注册小程序-开始时间 CreateEndTime string `json:"create_endTime"` // 注册小程序-结束时间 OrderStartTime string `json:"order_startTime"` // 首次零售开单-开始时间 @@ -297,22 +297,22 @@ func GetNewUserList(req *NewUserListReq) (*NewUserListResp, error) { qs := orm.Eloquent.Model(&UserInfo{}).Debug() if req.Tel != "" { - qs = qs.Where("tel", req.Tel) + qs = qs.Where("user.tel", req.Tel) } if req.Uid != 0 { - qs = qs.Where("uid", req.Uid) + qs = qs.Where("user.uid", req.Uid) } - if req.OpenMemberLevel != 0 { - qs = qs.Where("open_member_level", req.OpenMemberLevel) + if len(req.OpenMemberLevel) != 0 { + qs = qs.Where("user.open_member_level in (?)", req.OpenMemberLevel) } - if req.MemberLevel != 0 { - qs = qs.Where("member_level", req.MemberLevel) + if len(req.MemberLevel) != 0 { + qs = qs.Where("user.member_level in (?)", req.MemberLevel) } if req.StoreId != 0 { - qs = qs.Where("store_id", req.StoreId) + qs = qs.Where("user.store_id", req.StoreId) } if req.UserType != 0 { - qs = qs.Where("user_type", req.UserType) + qs = qs.Where("user.user_type", req.UserType) } if req.CreateStartTime != "" { @@ -321,7 +321,7 @@ func GetNewUserList(req *NewUserListReq) (*NewUserListResp, error) { logger.Errorf("err:", logger.Field("err", err)) return nil, err } - qs = qs.Where("created_at > ?", parse) + qs = qs.Where("user.created_at > ?", parse) } if req.CreateEndTime != "" { parse, err := time.Parse(QueryTimeFormat, req.CreateEndTime) @@ -329,7 +329,7 @@ func GetNewUserList(req *NewUserListReq) (*NewUserListResp, error) { logger.Errorf("err:", logger.Field("err", err)) return nil, err } - qs = qs.Where("created_at < ?", parse) + qs = qs.Where("user.created_at < ?", parse) } if req.OrderStartTime != "" { @@ -338,7 +338,7 @@ func GetNewUserList(req *NewUserListReq) (*NewUserListResp, error) { logger.Errorf("err:", logger.Field("err", err)) return nil, err } - qs = qs.Where("first_retail_order > ?", parse) + qs = qs.Where("user.first_retail_order > ?", parse) } if req.OrderEndTime != "" { parse, err := time.Parse(QueryTimeFormat, req.OrderEndTime) @@ -346,7 +346,7 @@ func GetNewUserList(req *NewUserListReq) (*NewUserListResp, error) { logger.Errorf("err:", logger.Field("err", err)) return nil, err } - qs = qs.Where("first_retail_order < ?", parse) + qs = qs.Where("user.first_retail_order < ?", parse) } if req.OpenStartTime != "" { @@ -355,7 +355,7 @@ func GetNewUserList(req *NewUserListReq) (*NewUserListResp, error) { logger.Errorf("err:", logger.Field("err", err)) return nil, err } - qs = qs.Where("open_member_time > ?", parse) + qs = qs.Where("user.open_member_time > ?", parse) } if req.OpenEndTime != "" { parse, err := time.Parse(QueryTimeFormat, req.OpenEndTime) @@ -363,7 +363,7 @@ func GetNewUserList(req *NewUserListReq) (*NewUserListResp, error) { logger.Errorf("err:", logger.Field("err", err)) return nil, err } - qs = qs.Where("open_member_time < ?", parse) + qs = qs.Where("user.open_member_time < ?", parse) } var count int64 @@ -382,9 +382,9 @@ func GetNewUserList(req *NewUserListReq) (*NewUserListResp, error) { GROUP BY uid HAVING COUNT(uid) > 0`) - // 查询用户数据,过期天数,消费次数,消费金额 + // 查询用户数据,过期天数,消费次数,消费金额---20240308修改:过期会员等级会自动改成1普通会员,所以这里的范围改成,1,2,3, 4, 5 qs = qs.Select("user.*, COALESCE(fr.order_count, 0) as order_count, COALESCE(fr.order_amount, 0) as "+ - "order_amount, CASE WHEN (user.member_level IN (2, 4, 5) AND user.member_expire < ?) "+ + "order_amount, CASE WHEN (user.member_level IN (1, 2, 3, 4, 5) AND user.member_expire < ?) "+ "THEN DATEDIFF(?, user.member_expire) ELSE 0 END AS member_expire_days", currentTime, currentTime). Joins(fmt.Sprintf("LEFT JOIN (%s) fr ON user.uid = fr.uid", subQuery)) @@ -443,6 +443,33 @@ func GetNewUserList(req *NewUserListReq) (*NewUserListResp, error) { //滞纳金 一个卡带一天2块钱 users[i].ForfeitPenalty = len(c) * 200 * int(users[i].MemberExpireDays) } + + // 添加门店信息 + users[i].Store, _ = setStore(u.StoreId) + + // 校验时间,如果为01-01-01 08:05,则赋值为空 + if u.MemberExpire != nil && u.MemberExpire.IsZero() { + users[i].MemberExpire = nil + } + if u.OpenMemberTime != nil && u.OpenMemberTime.IsZero() { + users[i].OpenMemberTime = nil + } + if u.MemberOpenTime != nil && u.MemberOpenTime.IsZero() { + users[i].MemberOpenTime = nil + } + if u.LastLoginAt != nil && u.LastLoginAt.IsZero() { + users[i].LastLoginAt = nil + } + if u.InviteTime != nil && u.InviteTime.IsZero() { + users[i].InviteTime = nil + } + //if u.RenewalTime != nil && u.RenewalTime.IsZero() { + // users[i].RenewalTime = nil + //} + if u.FirstRetailOrder != nil && u.FirstRetailOrder.IsZero() { + users[i].FirstRetailOrder = nil + } + } if req.IsExport == 1 { @@ -461,6 +488,16 @@ func GetNewUserList(req *NewUserListReq) (*NewUserListResp, error) { return resp, nil } +func setStore(storeId uint64) (*Store, error) { + storeInfo := new(Store) + err := orm.Eloquent.Table("store").Where("id=?", storeId).Find(storeInfo).Error + if err != nil && err != RecordNotFound { + logger.Error("set store err:", logger.Field("err", err)) + return nil, err + } + return storeInfo, nil +} + func GetUserList(page, pageSize, uid, memberLevel, storeId, userType, cooperativeBusinessId int, tel, startTime, endTime, nameKey, sortFiled, sortType string, filter bool) ([]U, uint32, uint32, error) { var ( users = make([]U, 0) @@ -624,17 +661,17 @@ func newUserListExport(list []U) (string, error) { storeMap[uint32(list[i].StoreId)], // 所属门店 list[i].OrderCount, // 消费次数 list[i].OrderAmount, // 消费金额 - tools.ConvertTimeToString(list[i].CreatedAt), // 注册小程序时间 - tools.ConvertTimeToString(list[i].FirstRetailOrder), // 首次零售开单时间 - getMemberLevelChineseDescription(list[i].OpenMemberLevel), // 首次开通租卡会员等级 - getMemberLevelChineseDescription(list[i].MemberLevel), // 当前会员等级 - tools.ConvertTimeToString(list[i].OpenMemberTime), // 首次开通租卡会员时间 - tools.ConvertTimeToString(list[i].MemberExpire), // 租卡会员到期时间 - list[i].Deposit, // 保证金 - list[i].MemberExpireDays, // 租卡会员过期天数 - list[i].ForfeitPenalty, // 滞纳金 - cardNamesResult, // 未归还卡带名称 - cardNumsResult, // 未归还卡带串码 + tools.ConvertTimeToString(list[i].CreatedAt), // 注册小程序时间 + tools.ConvertTimeToStringByPoint(list[i].FirstRetailOrder), // 首次零售开单时间 + getMemberLevelChineseDescription(list[i].OpenMemberLevel), // 首次开通租卡会员等级 + getMemberLevelChineseDescription(list[i].MemberLevel), // 当前会员等级 + tools.ConvertTimeToStringByPoint(list[i].OpenMemberTime), // 首次开通租卡会员时间 + tools.ConvertTimeToStringByPoint(list[i].MemberExpire), // 租卡会员到期时间 + float32(list[i].Deposit) / 100, // 保证金(数据库存储的是分) + list[i].MemberExpireDays, // 租卡会员过期天数 + list[i].ForfeitPenalty, // 滞纳金 + cardNamesResult, // 未归还卡带名称 + cardNumsResult, // 未归还卡带串码 } for j, _ := range row { @@ -859,9 +896,9 @@ type UserInviteListReq struct { } func (m *UserInfo) InitUserInvite(invite UserInvite) { - m.MemberOpenTime = invite.MemberOpenTime + m.MemberOpenTime = &invite.MemberOpenTime m.MemberStatus = invite.MemberStatus - m.InviteTime = invite.CreatedAt + m.InviteTime = &invite.CreatedAt m.MemberLevel = invite.MemberLevel } @@ -1224,10 +1261,10 @@ type NewUserInviteRecordReq struct { UserTel string `json:"user_tel"` // 用户手机号 CreateStartTime time.Time `json:"create_start_time"` // 注册小程序时间-开始时间 CreateEndTime time.Time `json:"create_end_time"` // 注册小程序时间-结束时间 - RecordType uint32 `json:"record_type"` // 记录类型 1-首次邀请,2-开通年费黄金,3-开通季度黄金,4-开通半年黄金, 5-开通年费白金,6-开通年费黑金,7-续费年费黄金(干预),8-续费年费白金(干预),9-续费年费黑金(干预),10-续费年费黄金(自动), 11-续费季度黄金(自动),12-续费半年黄金(自动),13-续费年费白金(自动),14-续费年费黑金(自动),15-黄金→白金(干预), 16-黄金→黑金(干预),17-白金→黑金(干预),18-黄金→白金(自动),19-黄金→黑金(自动),20-白金→黑金(自动) + RecordType []uint32 `json:"record_type"` // 记录类型 1-首次邀请,2-开通年费黄金,3-开通季度黄金,4-开通半年黄金, 5-开通年费白金,6-开通年费黑金,7-续费年费黄金(干预),8-续费年费白金(干预),9-续费年费黑金(干预),10-续费年费黄金(自动), 11-续费季度黄金(自动),12-续费半年黄金(自动),13-续费年费白金(自动),14-续费年费黑金(自动),15-黄金→白金(干预), 16-黄金→黑金(干预),17-白金→黑金(干预),18-黄金→白金(自动),19-黄金→黑金(自动),20-白金→黑金(自动) RecordStartTime time.Time `json:"record_start_time"` // 记录时间-开始时间 RecordEndTime time.Time `json:"record_end_time"` // 记录时间-结束时间 - MemberLevel uint32 `json:"member_level"` // 当前类型:1-普通 2-黄金 4-白金 5-黑金 + MemberLevel uint32 `json:"member_level"` // 当前类型:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 IsExport uint32 `json:"is_export"` // 1-导出 } @@ -1327,86 +1364,147 @@ func (m *NewUserInviteRecordReq) NewList() (*UserInviteRecordListResp, error) { qs = qs.Where("B2.created_at < ?", m.CreateEndTime) countQuery = countQuery.Where("B2.created_at < ?", m.CreateEndTime) } - if m.RecordType != 0 { - switch m.RecordType { - case 1: // 首次邀请 - qs = qs.Where("first=1").Where("spend_type=1") - countQuery = countQuery.Where("first=1").Where("spend_type=1") - case 2: // 开通年费黄金 - qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=2") - countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=2") - case 3: // 开通季度黄金 - qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=201") - countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=201") - case 4: // 开通半年黄金 - qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=202") - countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=202") - case 5: // 开通年费白金 - qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=2") - countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=2") - case 6: // 开通年费黑金 - qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=2") - countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=2") + //if len(m.RecordType) != 0 { + // for _, recordType := range m.RecordType { + // switch recordType { + // case 1: // 首次邀请 + // qs = qs.Where("first=1").Where("spend_type=1") + // countQuery = countQuery.Where("first=1").Where("spend_type=1") + // case 2: // 开通年费黄金 + // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=2") + // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=2") + // case 3: // 开通季度黄金 + // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=201") + // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=201") + // case 4: // 开通半年黄金 + // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=202") + // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=202") + // case 5: // 开通年费白金 + // qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=2") + // countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=2") + // case 6: // 开通年费黑金 + // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=2") + // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=2") + // + // case 7: // 续费年费黄金(干预) + // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=0") + // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=0") + // case 8: // 续费年费白金(干预) + // qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=0") + // countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=0") + // case 9: // 续费年费黑金(干预) + // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=0") + // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=0") + // + // case 10: // 续费年费黄金(自动) + // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1") + // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1") + // case 11: // 续费季度黄金(自动) + // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). + // Where("user_invite_record.member_genre=201") + // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). + // Where("user_invite_record.member_genre=201") + // case 12: // 续费半年黄金(自动) + // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). + // Where("user_invite_record.member_genre=202") + // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). + // Where("user_invite_record.member_genre=202") + // case 13: // 续费年费白金(自动) + // qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=1") + // countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=1") + // case 14: // 续费年费黑金(自动) + // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=1") + // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=1") + // + // case 15: //黄金→白金(干预) + // qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=0") + // countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=0") + // case 16: //黄金→黑金(干预) + // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). + // Where("user_invite_record.member_genre in (200,201,202)") + // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). + // Where("user_invite_record.member_genre in (200,201,202)") + // case 17: //白金→黑金(干预) + // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). + // Where("user_invite_record.member_genre not in (200,201,202)") + // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). + // Where("user_invite_record.member_genre not in (200,201,202)") + // + // case 18: //黄金→白金(自动) + // qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=1") + // countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=1") + // case 19: //黄金→黑金(自动) + // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). + // Where("user_invite_record.member_genre in (200,201,202)") + // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). + // Where("user_invite_record.member_genre in (200,201,202)") + // case 20: //白金→黑金(自动) + // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). + // Where("user_invite_record.member_genre not in (200,201,202)") + // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). + // Where("user_invite_record.member_genre not in (200,201,202)") + // } + // } + //} + if len(m.RecordType) != 0 { + var recordTypeConditions []string + for _, t := range m.RecordType { + switch t { + case 1: + recordTypeConditions = append(recordTypeConditions, "(first=1 AND spend_type=1)") + case 2: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=2)") + case 3: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=2 AND user_invite_record.member_genre=201)") + case 4: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=2 AND user_invite_record.member_genre=202)") + case 5: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=4 AND spend_type=2)") + case 6: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=2)") - case 7: // 续费年费黄金(干预) - qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=0") - countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=0") - case 8: // 续费年费白金(干预) - qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=0") - countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=0") - case 9: // 续费年费黑金(干预) - qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=0") - countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=0") + case 7: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=3 AND renew_hide=0)") + case 8: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=4 AND spend_type=3 AND renew_hide=0)") + case 9: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=3 AND renew_hide=0)") - case 10: // 续费年费黄金(自动) - qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1") - countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1") - case 11: // 续费季度黄金(自动) - qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). - Where("user_invite_record.member_genre=201") - countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). - Where("user_invite_record.member_genre=201") - case 12: // 续费半年黄金(自动) - qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). - Where("user_invite_record.member_genre=202") - countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). - Where("user_invite_record.member_genre=202") - case 13: // 续费年费白金(自动) - qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=1") - countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=1") - case 14: // 续费年费黑金(自动) - qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=1") - countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=1") + case 10: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=3 AND renew_hide=1)") + case 11: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=3 AND renew_hide=1 AND user_invite_record.member_genre=201)") + case 12: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=3 AND renew_hide=1 AND user_invite_record.member_genre=202)") + case 13: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=4 AND spend_type=3 AND renew_hide=1)") + case 14: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=3 AND renew_hide=1)") - case 15: //黄金→白金(干预) - qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=0") - countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=0") - case 16: //黄金→黑金(干预) - qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). - Where("user_invite_record.member_genre in (200,201,202)") - countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). - Where("user_invite_record.member_genre in (200,201,202)") - case 17: //白金→黑金(干预) - qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). - Where("user_invite_record.member_genre not in (200,201,202)") - countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). - Where("user_invite_record.member_genre not in (200,201,202)") + case 15: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=4 AND spend_type=4 AND renew_hide=0)") + case 16: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=4 AND renew_hide=0 AND user_invite_record.member_genre in (200,201,202))") + case 17: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=4 AND renew_hide=0 AND user_invite_record.member_genre not in (200,201,202))") - case 18: //黄金→白金(自动) - qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=1") - countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=1") - case 19: //黄金→黑金(自动) - qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). - Where("user_invite_record.member_genre in (200,201,202)") - countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). - Where("user_invite_record.member_genre in (200,201,202)") - case 20: //白金→黑金(自动) - qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). - Where("user_invite_record.member_genre not in (200,201,202)") - countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). - Where("user_invite_record.member_genre not in (200,201,202)") + case 18: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=4 AND spend_type=4 AND renew_hide=1)") + case 19: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=4 AND renew_hide=1 AND user_invite_record.member_genre in (200,201,202))") + case 20: + recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=4 AND renew_hide=1 AND user_invite_record.member_genre not in (200,201,202))") + } + } + + // 拼接多选条件 + if len(recordTypeConditions) > 0 { + recordTypeQuery := strings.Join(recordTypeConditions, " OR ") + qs = qs.Where(recordTypeQuery) + countQuery = countQuery.Where(recordTypeQuery) } } + if !m.RecordStartTime.IsZero() { qs = qs.Where("action_time > ?", m.RecordStartTime) countQuery = countQuery.Where("action_time > ?", m.RecordStartTime) @@ -1541,8 +1639,7 @@ func getMemberLevelChineseDescription(memberLevel uint32) string { switch memberLevel { case 1: return "普通会员" - case 2: - case 3: + case 2, 3: return "黄金会员" case 4: return "白金会员" @@ -2406,9 +2503,10 @@ type GroupSendMessageCreateTemplateListReq struct { PageSize int `json:"pageSize"` } type GroupSendMessageCreateTemplateListResp struct { - List []GroupSendMessageTemplate `json:"list"` - Count uint32 `json:"count"` - PageNum int `json:"pageIndex"` + List []GroupSendMessageTemplate `json:"list"` + SmsRemainingNumber int `json:"sms_remaining_number"` // 本月短信剩余数量 + Count uint32 `json:"count"` + PageNum int `json:"pageIndex"` } func (m *GroupSendMessageCreateTemplateListReq) List() (*GroupSendMessageCreateTemplateListResp, error) { @@ -2444,6 +2542,8 @@ func (m *GroupSendMessageCreateTemplateListReq) List() (*GroupSendMessageCreateT } resp.List = groupSends + resp.SmsRemainingNumber = GetSmsNumberRemaining() + return resp, nil } @@ -3102,7 +3202,7 @@ func SendMessageMemberRenewal() { renewalLog := &UserRenewalLog{ Uid: users[i].Uid, Action: UserRenewalLogSendMessage, - MemberExpire: users[i].MemberExpire, + MemberExpire: *users[i].MemberExpire, Type: 0, Serial: uint32(users[i].MemberExpire.Unix()), } @@ -3582,3 +3682,52 @@ func (m *TelListReq) GetTelList() (*TelListResp, error) { return resp, nil } + +// UpdateExpireMemberLevel 更新过期用户的当前会员等级 +func UpdateExpireMemberLevel() { + var users []UserInfo + err := orm.Eloquent.Table("user").Where("member_expire < ?", time.Now()). + Where("member_level in (?)", []uint32{2, 3, 4, 5}).Find(&users).Error + if err != nil { + logger.Error(err.Error()) + return + } + + if len(users) == 0 { + logger.Info("UpdateExpireMemberLevel users is null") + return + } + + for i, _ := range users { + if err = orm.Eloquent.Model(&UserInfo{}).Where("id = ?", users[i].ID).Updates(map[string]interface{}{ + "member_level": 1, + }).Error; err != nil { + logger.Errorf("UpdateExpireMemberLevel err,", err.Error()) + continue + } + } +} + +// GetUserInfoByTel 通过手机号获取用户信息 +func GetUserInfoByTel(tel string) (UserInfo, error) { + var userInfo UserInfo + err := orm.Eloquent.Table("user").Where("tel = ?", tel).Find(&userInfo).Error + if err != nil { + logger.Error("err:", logger.Field("err", err)) + return userInfo, err + } + + return userInfo, nil +} + +// CreateUid 找一个可以用的Uid +func CreateUid() uint32 { + for { + uid := utils.GenUid() + var count int64 + if err := orm.Eloquent.Table("user").Where("uid = ?", uid).Count(&count).Error; err == nil && count > 0 { + continue + } + return uid + } +} diff --git a/app/admin/models/user_vm.go b/app/admin/models/user_vm.go index 4dc2551..f3c8677 100644 --- a/app/admin/models/user_vm.go +++ b/app/admin/models/user_vm.go @@ -55,10 +55,10 @@ func UserVmUpdate(gdb *gorm.DB, uid uint32, amount int, event, describe string) return err } - flag := false + //flag := false begin := gdb if gdb == nil { - flag = true + //flag = true begin = orm.Eloquent.Begin() } @@ -79,8 +79,14 @@ func UserVmUpdate(gdb *gorm.DB, uid uint32, amount int, event, describe string) return err } } else { - sql := fmt.Sprintf("UPDATE user_vm SET vm = vm+? WHERE uid=?;") - err = begin.Exec(sql, amount, uid).Error + // 如果用户积分不够抵扣,则扣到0为止 + if userVm.Vm == 0 || int(userVm.Vm)+amount <= 0 { + sql := fmt.Sprintf("UPDATE user_vm SET vm = ? WHERE uid=?;") + err = begin.Exec(sql, 0, uid).Error + } else { + sql := fmt.Sprintf("UPDATE user_vm SET vm = vm+? WHERE uid=?;") + err = begin.Exec(sql, amount, uid).Error + } if err != nil { begin.Rollback() logger.Error("err:", logger.Field("err", err)) @@ -91,11 +97,15 @@ func UserVmUpdate(gdb *gorm.DB, uid uint32, amount int, event, describe string) vmRecord := &UserVmRecord{ Uid: uid, BeforeVm: uint32(userVm.Vm), - AfterVm: uint32(int(userVm.Vm) + amount), + AfterVm: 0, // 默认值为 0 Alter: amount, Event: event, Describe: describe, } + + if newValue := int(userVm.Vm) + amount; newValue > 0 { + vmRecord.AfterVm = uint32(newValue) + } err = begin.Create(vmRecord).Error if err != nil { begin.Rollback() @@ -103,14 +113,14 @@ func UserVmUpdate(gdb *gorm.DB, uid uint32, amount int, event, describe string) return err } - if flag { - err = begin.Commit().Error - if err != nil { - begin.Rollback() - logger.Error("err:", logger.Field("err", err)) - return err - } - } + //if flag { + // err = begin.Commit().Error + // if err != nil { + // begin.Rollback() + // logger.Error("err:", logger.Field("err", err)) + // return err + // } + //} return nil } diff --git a/app/admin/router/cooperativemanage.go b/app/admin/router/cooperativemanage.go index e29dc7f..9d56b77 100644 --- a/app/admin/router/cooperativemanage.go +++ b/app/admin/router/cooperativemanage.go @@ -12,6 +12,7 @@ func registerCooperativeManageRouter(v1 *gin.RouterGroup, authMiddleware *jwt.Gi cooperativeBusiness := v1.Group("/cooperative").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) { + cooperativeBusiness.POST("get_default_info", cooperativemanage.CooperativeGetDefaultInfo) // 获取合作商默认用户名和密码 cooperativeBusiness.POST("list", cooperativemanage.CooperativeBusinessList) // 获取合作商列表 cooperativeBusiness.POST("add", cooperativemanage.CooperativeAdd) // 获取合作商 cooperativeBusiness.POST("edit", cooperativemanage.CooperativeEdit) // 编辑供应商 diff --git a/cmd/api/server.go b/cmd/api/server.go index f23b8e2..cb0e694 100644 --- a/cmd/api/server.go +++ b/cmd/api/server.go @@ -116,26 +116,32 @@ func run() error { fmt.Println("err:", err) } - // 生效共享卡 - err = s.Every(1).Day().At("05:00").Do(models.ShareCardProfitEffectCard) - if err != nil { - fmt.Println("err:", err) - } - // 发放积分 - err = s.Every(1).Day().At("02:00").Do(models.ShareCardProvideVm) - if err != nil { - fmt.Println("err:", err) - } - // 用户积分记录 - err = s.Every(1).Day().At("03:00").Do(models.ShareCardUserVmRecord) - if err != nil { - fmt.Println("err:", err) - } + // 2024-03-11 跟产品确认共享卡功能已隐藏,暂时注释该部分代码 + //// 生效共享卡 + //err = s.Every(1).Day().At("05:00").Do(models.ShareCardProfitEffectCard) + //if err != nil { + // fmt.Println("err:", err) + //} + //// 发放积分 + //err = s.Every(1).Day().At("02:00").Do(models.ShareCardProvideVm) + //if err != nil { + // fmt.Println("err:", err) + //} + //// 用户积分记录 + //err = s.Every(1).Day().At("03:00").Do(models.ShareCardUserVmRecord) + //if err != nil { + // fmt.Println("err:", err) + //} // 用户收回卡绑定卡 err = s.Every(1).Day().At("00:00").Do(models.ShareCardRetrieveCardSetStockCardCron) if err != nil { fmt.Println("err:", err) } + // 更新过期用户的当前会员等级-20240308添加 + err = s.Every(1).Day().At("00:05").Do(models.UpdateExpireMemberLevel) + if err != nil { + fmt.Println("err:", err) + } // 用户邀请用户报表 //err = s.Every(1).Day().At("00:00").Do(models.CreateInviteMemberReport) err = s.Every(1).Day().At("00:10").Do(models.CreateInviteMemberReport) diff --git a/docs/docs.go b/docs/docs.go index 584d781..2031c34 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -886,6 +886,29 @@ const docTemplate = `{ } } }, + "/api/v1/cooperative/get_default_info": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "合作商", + "v1.2.0" + ], + "summary": "获取合作商默认用户名和密码", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.DefaultUserNameAndPasswordResp" + } + } + } + } + }, "/api/v1/cooperative/get_pay_info": { "post": { "consumes": [ @@ -2206,7 +2229,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/models.ErpPurchaseTerminateReq" + "$ref": "#/definitions/models.ErpPurchaseDeleteReq" } } ], @@ -2662,6 +2685,40 @@ const docTemplate = `{ } } }, + "/api/v1/group_send_message/template/list": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "短信群发", + "V1.2.0" + ], + "summary": "短信群发", + "parameters": [ + { + "description": "查询短信模版列表模型", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.GroupSendMessageCreateTemplateListReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.GroupSendMessageCreateTemplateListResp" + } + } + } + } + }, "/api/v1/inventory/add_remark": { "post": { "consumes": [ @@ -6181,6 +6238,19 @@ const docTemplate = `{ } } }, + "models.DefaultUserNameAndPasswordResp": { + "type": "object", + "properties": { + "password": { + "description": "密码", + "type": "string" + }, + "username": { + "description": "用户名", + "type": "string" + } + } + }, "models.DemandData": { "type": "object", "properties": { @@ -6758,11 +6828,11 @@ const docTemplate = `{ }, "invoice_code": { "description": "发票代码", - "type": "integer" + "type": "string" }, "invoice_number": { "description": "发票编码", - "type": "integer" + "type": "string" }, "is_print": { "description": "是否打印小票 1-未打印 2-已打印", @@ -7060,6 +7130,7 @@ const docTemplate = `{ "salesman", "store_id", "store_name", + "tel", "total_amount", "total_count", "total_retail_price" @@ -7203,6 +7274,9 @@ const docTemplate = `{ }, "models.ErpOrderListResp": { "type": "object", + "required": [ + "show_all" + ], "properties": { "export_url": { "type": "string" @@ -7221,6 +7295,10 @@ const docTemplate = `{ "description": "每页展示条数", "type": "integer" }, + "show_all": { + "description": "展示所有订单配置:ON-打开,OFF-关闭", + "type": "string" + }, "total": { "description": "总条数", "type": "integer" @@ -7667,6 +7745,10 @@ const docTemplate = `{ "description": "创建时间", "type": "string" }, + "default_employee_price": { + "description": "默认员工成本价", + "type": "number" + }, "erp_commodity_id": { "description": "商品id", "type": "integer" @@ -7773,8 +7855,17 @@ const docTemplate = `{ "models.ErpPurchaseCreateReq": { "type": "object", "required": [ + "account_holder", + "bank_account", + "delivery_address", + "delivery_time", + "erp_cashier_id", "erp_purchase_commodity", - "purchase_type" + "erp_supplier_id", + "handler_id", + "opening_bank", + "purchase_type", + "store_id" ], "properties": { "account_holder": { @@ -7838,6 +7929,18 @@ const docTemplate = `{ } } }, + "models.ErpPurchaseDeleteReq": { + "type": "object", + "required": [ + "serial_number" + ], + "properties": { + "serial_number": { + "description": "单据编号", + "type": "string" + } + } + }, "models.ErpPurchaseDetailReq": { "type": "object", "required": [ @@ -8446,21 +8549,30 @@ const docTemplate = `{ "models.ErpPurchaseReportBySupplierReq": { "type": "object", "properties": { - "endTime": { + "end_time": { "description": "入/出库,结束时间", "type": "string" }, "erp_category_id": { "description": "商品分类id", - "type": "integer" + "type": "array", + "items": { + "type": "integer" + } }, "erp_commodity_name": { "description": "商品名称", - "type": "string" + "type": "array", + "items": { + "type": "string" + } }, "erp_supplier_id": { "description": "供应商id", - "type": "integer" + "type": "array", + "items": { + "type": "integer" + } }, "is_export": { "description": "1-导出", @@ -8478,7 +8590,7 @@ const docTemplate = `{ "description": "采购类型:procure-采购 reject-退货", "type": "string" }, - "startTime": { + "start_time": { "description": "入/出库,开始时间", "type": "string" }, @@ -8486,17 +8598,7 @@ const docTemplate = `{ "description": "门店复选", "type": "array", "items": { - "type": "object", - "properties": { - "store_id": { - "description": "门店id", - "type": "integer" - }, - "store_name": { - "description": "门店名称", - "type": "string" - } - } + "type": "integer" } } } @@ -9056,7 +9158,7 @@ const docTemplate = `{ "type": "string" }, "state": { - "description": "库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库", + "description": "库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库(前端只看1,4)", "type": "integer" }, "stock_time_end": { @@ -9372,6 +9474,78 @@ const docTemplate = `{ } } }, + "models.GroupSendMessageCreateTemplateListReq": { + "type": "object", + "properties": { + "pageIndex": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "status": { + "description": "1-待发送 2-已发送", + "type": "integer" + }, + "title": { + "type": "string" + } + } + }, + "models.GroupSendMessageCreateTemplateListResp": { + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/models.GroupSendMessageTemplate" + } + }, + "pageIndex": { + "type": "integer" + }, + "sms_remaining_number": { + "description": "本月短信剩余数量", + "type": "integer" + } + } + }, + "models.GroupSendMessageTemplate": { + "type": "object", + "properties": { + "createdAt": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "数据库记录编号", + "type": "integer" + }, + "message": { + "type": "string" + }, + "send_time": { + "type": "string" + }, + "status": { + "description": "1-待发送 2-已发送", + "type": "integer" + }, + "tels": { + "type": "string" + }, + "title": { + "type": "string" + }, + "user_type": { + "description": "1-所有用户 2-会员 3-非会员 4-指定用户", + "type": "integer" + } + } + }, "models.InsertSysUserReq": { "type": "object", "properties": { @@ -9919,7 +10093,7 @@ const docTemplate = `{ "type": "integer" }, "member_level": { - "description": "当前类型:1-普通 2-黄金 4-白金 5-黑金", + "description": "当前类型:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", "type": "integer" }, "pageIndex": { @@ -9938,7 +10112,10 @@ const docTemplate = `{ }, "record_type": { "description": "记录类型 1-首次邀请,2-开通年费黄金,3-开通季度黄金,4-开通半年黄金, 5-开通年费白金,6-开通年费黑金,7-续费年费黄金(干预),8-续费年费白金(干预),9-续费年费黑金(干预),10-续费年费黄金(自动), 11-续费季度黄金(自动),12-续费半年黄金(自动),13-续费年费白金(自动),14-续费年费黑金(自动),15-黄金→白金(干预), 16-黄金→黑金(干预),17-白金→黑金(干预),18-黄金→白金(自动),19-黄金→黑金(自动),20-白金→黑金(自动)", - "type": "integer" + "type": "array", + "items": { + "type": "integer" + } }, "store_id": { "description": "邀请人所属门店id", @@ -9973,17 +10150,23 @@ const docTemplate = `{ "description": "1-导出", "type": "integer" }, - "memberLevel": { - "description": "当前会员等级", - "type": "integer" + "member_level": { + "description": "当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", + "type": "array", + "items": { + "type": "integer" + } }, "open_endTime": { "description": "首次开通租卡会员-结束时间", "type": "string" }, "open_member_level": { - "description": "首次开通租卡会员等级", - "type": "integer" + "description": "首次开通租卡会员等级:2-黄金会员 4-白金会员 5-黑金会员", + "type": "array", + "items": { + "type": "integer" + } }, "open_startTime": { "description": "首次开通租卡会员-开始时间", @@ -11772,21 +11955,17 @@ const docTemplate = `{ "description": "标记", "type": "integer" }, - "memberExpire": { + "member_expire": { "description": "会员到期时间", "type": "string" }, - "memberLevel": { - "description": "会员等级 1-会员", - "type": "integer" - }, "member_expire_days": { "description": "会员过期天数", "type": "integer" }, - "member_level_string": { - "description": "会员类型", - "type": "string" + "member_level": { + "description": "当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", + "type": "integer" }, "member_open_time": { "type": "string" @@ -11799,7 +11978,7 @@ const docTemplate = `{ "type": "string" }, "open_member_level": { - "description": "开通会员级别:2-黄金会员 4-白金会员 5-黑金会员", + "description": "开通会员级别:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", "type": "integer" }, "open_member_time": { @@ -11824,12 +12003,6 @@ const docTemplate = `{ "description": "省", "type": "string" }, - "renewal_member_level": { - "type": "integer" - }, - "renewal_time": { - "type": "string" - }, "shop_assistant_name": { "description": "店员名称", "type": "string" @@ -11943,18 +12116,14 @@ const docTemplate = `{ "description": "标记", "type": "integer" }, - "memberExpire": { + "member_expire": { "description": "会员到期时间", "type": "string" }, - "memberLevel": { - "description": "会员等级 1-会员", + "member_level": { + "description": "当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", "type": "integer" }, - "member_level_string": { - "description": "会员类型", - "type": "string" - }, "member_open_time": { "type": "string" }, @@ -11966,7 +12135,7 @@ const docTemplate = `{ "type": "string" }, "open_member_level": { - "description": "开通会员级别:2-黄金会员 4-白金会员 5-黑金会员", + "description": "开通会员级别:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", "type": "integer" }, "open_member_time": { @@ -11983,12 +12152,6 @@ const docTemplate = `{ "description": "省", "type": "string" }, - "renewal_member_level": { - "type": "integer" - }, - "renewal_time": { - "type": "string" - }, "shop_assistant_name": { "description": "店员名称", "type": "string" diff --git a/docs/swagger.json b/docs/swagger.json index 51b8632..2f85a33 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -875,6 +875,29 @@ } } }, + "/api/v1/cooperative/get_default_info": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "合作商", + "v1.2.0" + ], + "summary": "获取合作商默认用户名和密码", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.DefaultUserNameAndPasswordResp" + } + } + } + } + }, "/api/v1/cooperative/get_pay_info": { "post": { "consumes": [ @@ -2195,7 +2218,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/models.ErpPurchaseTerminateReq" + "$ref": "#/definitions/models.ErpPurchaseDeleteReq" } } ], @@ -2651,6 +2674,40 @@ } } }, + "/api/v1/group_send_message/template/list": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "短信群发", + "V1.2.0" + ], + "summary": "短信群发", + "parameters": [ + { + "description": "查询短信模版列表模型", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.GroupSendMessageCreateTemplateListReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.GroupSendMessageCreateTemplateListResp" + } + } + } + } + }, "/api/v1/inventory/add_remark": { "post": { "consumes": [ @@ -6170,6 +6227,19 @@ } } }, + "models.DefaultUserNameAndPasswordResp": { + "type": "object", + "properties": { + "password": { + "description": "密码", + "type": "string" + }, + "username": { + "description": "用户名", + "type": "string" + } + } + }, "models.DemandData": { "type": "object", "properties": { @@ -6747,11 +6817,11 @@ }, "invoice_code": { "description": "发票代码", - "type": "integer" + "type": "string" }, "invoice_number": { "description": "发票编码", - "type": "integer" + "type": "string" }, "is_print": { "description": "是否打印小票 1-未打印 2-已打印", @@ -7049,6 +7119,7 @@ "salesman", "store_id", "store_name", + "tel", "total_amount", "total_count", "total_retail_price" @@ -7192,6 +7263,9 @@ }, "models.ErpOrderListResp": { "type": "object", + "required": [ + "show_all" + ], "properties": { "export_url": { "type": "string" @@ -7210,6 +7284,10 @@ "description": "每页展示条数", "type": "integer" }, + "show_all": { + "description": "展示所有订单配置:ON-打开,OFF-关闭", + "type": "string" + }, "total": { "description": "总条数", "type": "integer" @@ -7656,6 +7734,10 @@ "description": "创建时间", "type": "string" }, + "default_employee_price": { + "description": "默认员工成本价", + "type": "number" + }, "erp_commodity_id": { "description": "商品id", "type": "integer" @@ -7762,8 +7844,17 @@ "models.ErpPurchaseCreateReq": { "type": "object", "required": [ + "account_holder", + "bank_account", + "delivery_address", + "delivery_time", + "erp_cashier_id", "erp_purchase_commodity", - "purchase_type" + "erp_supplier_id", + "handler_id", + "opening_bank", + "purchase_type", + "store_id" ], "properties": { "account_holder": { @@ -7827,6 +7918,18 @@ } } }, + "models.ErpPurchaseDeleteReq": { + "type": "object", + "required": [ + "serial_number" + ], + "properties": { + "serial_number": { + "description": "单据编号", + "type": "string" + } + } + }, "models.ErpPurchaseDetailReq": { "type": "object", "required": [ @@ -8435,21 +8538,30 @@ "models.ErpPurchaseReportBySupplierReq": { "type": "object", "properties": { - "endTime": { + "end_time": { "description": "入/出库,结束时间", "type": "string" }, "erp_category_id": { "description": "商品分类id", - "type": "integer" + "type": "array", + "items": { + "type": "integer" + } }, "erp_commodity_name": { "description": "商品名称", - "type": "string" + "type": "array", + "items": { + "type": "string" + } }, "erp_supplier_id": { "description": "供应商id", - "type": "integer" + "type": "array", + "items": { + "type": "integer" + } }, "is_export": { "description": "1-导出", @@ -8467,7 +8579,7 @@ "description": "采购类型:procure-采购 reject-退货", "type": "string" }, - "startTime": { + "start_time": { "description": "入/出库,开始时间", "type": "string" }, @@ -8475,17 +8587,7 @@ "description": "门店复选", "type": "array", "items": { - "type": "object", - "properties": { - "store_id": { - "description": "门店id", - "type": "integer" - }, - "store_name": { - "description": "门店名称", - "type": "string" - } - } + "type": "integer" } } } @@ -9045,7 +9147,7 @@ "type": "string" }, "state": { - "description": "库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库", + "description": "库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库(前端只看1,4)", "type": "integer" }, "stock_time_end": { @@ -9361,6 +9463,78 @@ } } }, + "models.GroupSendMessageCreateTemplateListReq": { + "type": "object", + "properties": { + "pageIndex": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "status": { + "description": "1-待发送 2-已发送", + "type": "integer" + }, + "title": { + "type": "string" + } + } + }, + "models.GroupSendMessageCreateTemplateListResp": { + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/models.GroupSendMessageTemplate" + } + }, + "pageIndex": { + "type": "integer" + }, + "sms_remaining_number": { + "description": "本月短信剩余数量", + "type": "integer" + } + } + }, + "models.GroupSendMessageTemplate": { + "type": "object", + "properties": { + "createdAt": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "数据库记录编号", + "type": "integer" + }, + "message": { + "type": "string" + }, + "send_time": { + "type": "string" + }, + "status": { + "description": "1-待发送 2-已发送", + "type": "integer" + }, + "tels": { + "type": "string" + }, + "title": { + "type": "string" + }, + "user_type": { + "description": "1-所有用户 2-会员 3-非会员 4-指定用户", + "type": "integer" + } + } + }, "models.InsertSysUserReq": { "type": "object", "properties": { @@ -9908,7 +10082,7 @@ "type": "integer" }, "member_level": { - "description": "当前类型:1-普通 2-黄金 4-白金 5-黑金", + "description": "当前类型:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", "type": "integer" }, "pageIndex": { @@ -9927,7 +10101,10 @@ }, "record_type": { "description": "记录类型 1-首次邀请,2-开通年费黄金,3-开通季度黄金,4-开通半年黄金, 5-开通年费白金,6-开通年费黑金,7-续费年费黄金(干预),8-续费年费白金(干预),9-续费年费黑金(干预),10-续费年费黄金(自动), 11-续费季度黄金(自动),12-续费半年黄金(自动),13-续费年费白金(自动),14-续费年费黑金(自动),15-黄金→白金(干预), 16-黄金→黑金(干预),17-白金→黑金(干预),18-黄金→白金(自动),19-黄金→黑金(自动),20-白金→黑金(自动)", - "type": "integer" + "type": "array", + "items": { + "type": "integer" + } }, "store_id": { "description": "邀请人所属门店id", @@ -9962,17 +10139,23 @@ "description": "1-导出", "type": "integer" }, - "memberLevel": { - "description": "当前会员等级", - "type": "integer" + "member_level": { + "description": "当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", + "type": "array", + "items": { + "type": "integer" + } }, "open_endTime": { "description": "首次开通租卡会员-结束时间", "type": "string" }, "open_member_level": { - "description": "首次开通租卡会员等级", - "type": "integer" + "description": "首次开通租卡会员等级:2-黄金会员 4-白金会员 5-黑金会员", + "type": "array", + "items": { + "type": "integer" + } }, "open_startTime": { "description": "首次开通租卡会员-开始时间", @@ -11761,21 +11944,17 @@ "description": "标记", "type": "integer" }, - "memberExpire": { + "member_expire": { "description": "会员到期时间", "type": "string" }, - "memberLevel": { - "description": "会员等级 1-会员", - "type": "integer" - }, "member_expire_days": { "description": "会员过期天数", "type": "integer" }, - "member_level_string": { - "description": "会员类型", - "type": "string" + "member_level": { + "description": "当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", + "type": "integer" }, "member_open_time": { "type": "string" @@ -11788,7 +11967,7 @@ "type": "string" }, "open_member_level": { - "description": "开通会员级别:2-黄金会员 4-白金会员 5-黑金会员", + "description": "开通会员级别:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", "type": "integer" }, "open_member_time": { @@ -11813,12 +11992,6 @@ "description": "省", "type": "string" }, - "renewal_member_level": { - "type": "integer" - }, - "renewal_time": { - "type": "string" - }, "shop_assistant_name": { "description": "店员名称", "type": "string" @@ -11932,18 +12105,14 @@ "description": "标记", "type": "integer" }, - "memberExpire": { + "member_expire": { "description": "会员到期时间", "type": "string" }, - "memberLevel": { - "description": "会员等级 1-会员", + "member_level": { + "description": "当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", "type": "integer" }, - "member_level_string": { - "description": "会员类型", - "type": "string" - }, "member_open_time": { "type": "string" }, @@ -11955,7 +12124,7 @@ "type": "string" }, "open_member_level": { - "description": "开通会员级别:2-黄金会员 4-白金会员 5-黑金会员", + "description": "开通会员级别:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员", "type": "integer" }, "open_member_time": { @@ -11972,12 +12141,6 @@ "description": "省", "type": "string" }, - "renewal_member_level": { - "type": "integer" - }, - "renewal_time": { - "type": "string" - }, "shop_assistant_name": { "description": "店员名称", "type": "string" diff --git a/docs/swagger.yaml b/docs/swagger.yaml index a402b65..198f567 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -928,6 +928,15 @@ definitions: description: 备注 type: string type: object + models.DefaultUserNameAndPasswordResp: + properties: + password: + description: 密码 + type: string + username: + description: 用户名 + type: string + type: object models.DemandData: properties: erp_category_id: @@ -1348,10 +1357,10 @@ definitions: type: integer invoice_code: description: 发票代码 - type: integer + type: string invoice_number: description: 发票编码 - type: integer + type: string is_print: description: 是否打印小票 1-未打印 2-已打印 type: integer @@ -1618,6 +1627,7 @@ definitions: - salesman - store_id - store_name + - tel - total_amount - total_count - total_retail_price @@ -1689,9 +1699,14 @@ definitions: pageSize: description: 每页展示条数 type: integer + show_all: + description: 展示所有订单配置:ON-打开,OFF-关闭 + type: string total: description: 总条数 type: integer + required: + - show_all type: object models.ErpOrderPayReq: properties: @@ -2008,6 +2023,9 @@ definitions: createdAt: description: 创建时间 type: string + default_employee_price: + description: 默认员工成本价 + type: number erp_commodity_id: description: 商品id type: integer @@ -2131,8 +2149,25 @@ definitions: description: 门店id type: integer required: + - account_holder + - bank_account + - delivery_address + - delivery_time + - erp_cashier_id - erp_purchase_commodity + - erp_supplier_id + - handler_id + - opening_bank - purchase_type + - store_id + type: object + models.ErpPurchaseDeleteReq: + properties: + serial_number: + description: 单据编号 + type: string + required: + - serial_number type: object models.ErpPurchaseDetailReq: properties: @@ -2580,18 +2615,24 @@ definitions: type: object models.ErpPurchaseReportBySupplierReq: properties: - endTime: + end_time: description: 入/出库,结束时间 type: string erp_category_id: description: 商品分类id - type: integer + items: + type: integer + type: array erp_commodity_name: description: 商品名称 - type: string + items: + type: string + type: array erp_supplier_id: description: 供应商id - type: integer + items: + type: integer + type: array is_export: description: 1-导出 type: integer @@ -2604,20 +2645,13 @@ definitions: purchase_type: description: 采购类型:procure-采购 reject-退货 type: string - startTime: + start_time: description: 入/出库,开始时间 type: string store_list: description: 门店复选 items: - properties: - store_id: - description: 门店id - type: integer - store_name: - description: 门店名称 - type: string - type: object + type: integer type: array type: object models.ErpPurchaseReportBySupplierResp: @@ -3029,7 +3063,7 @@ definitions: description: 首次入库订单编号 type: string state: - description: 库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库 + description: 库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库(前端只看1,4) type: integer stock_time_end: description: 最近入库结束时间 @@ -3257,6 +3291,55 @@ definitions: description: 数据总条数 type: integer type: object + models.GroupSendMessageCreateTemplateListReq: + properties: + pageIndex: + type: integer + pageSize: + type: integer + status: + description: 1-待发送 2-已发送 + type: integer + title: + type: string + type: object + models.GroupSendMessageCreateTemplateListResp: + properties: + count: + type: integer + list: + items: + $ref: '#/definitions/models.GroupSendMessageTemplate' + type: array + pageIndex: + type: integer + sms_remaining_number: + description: 本月短信剩余数量 + type: integer + type: object + models.GroupSendMessageTemplate: + properties: + createdAt: + description: 创建时间 + type: string + id: + description: 数据库记录编号 + type: integer + message: + type: string + send_time: + type: string + status: + description: 1-待发送 2-已发送 + type: integer + tels: + type: string + title: + type: string + user_type: + description: 1-所有用户 2-会员 3-非会员 4-指定用户 + type: integer + type: object models.InsertSysUserReq: properties: account_type: @@ -3649,7 +3732,7 @@ definitions: description: 1-导出 type: integer member_level: - description: 当前类型:1-普通 2-黄金 4-白金 5-黑金 + description: 当前类型:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 type: integer pageIndex: type: integer @@ -3664,7 +3747,9 @@ definitions: record_type: description: 记录类型 1-首次邀请,2-开通年费黄金,3-开通季度黄金,4-开通半年黄金, 5-开通年费白金,6-开通年费黑金,7-续费年费黄金(干预),8-续费年费白金(干预),9-续费年费黑金(干预),10-续费年费黄金(自动), 11-续费季度黄金(自动),12-续费半年黄金(自动),13-续费年费白金(自动),14-续费年费黑金(自动),15-黄金→白金(干预), 16-黄金→黑金(干预),17-白金→黑金(干预),18-黄金→白金(自动),19-黄金→黑金(自动),20-白金→黑金(自动) - type: integer + items: + type: integer + type: array store_id: description: 邀请人所属门店id type: integer @@ -3689,15 +3774,19 @@ definitions: is_export: description: 1-导出 type: integer - memberLevel: - description: 当前会员等级 - type: integer + member_level: + description: 当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 + items: + type: integer + type: array open_endTime: description: 首次开通租卡会员-结束时间 type: string open_member_level: - description: 首次开通租卡会员等级 - type: integer + description: 首次开通租卡会员等级:2-黄金会员 4-白金会员 5-黑金会员 + items: + type: integer + type: array open_startTime: description: 首次开通租卡会员-开始时间 type: string @@ -4988,27 +5077,24 @@ definitions: mark: description: 标记 type: integer + member_expire: + description: 会员到期时间 + type: string member_expire_days: description: 会员过期天数 type: integer - member_level_string: - description: 会员类型 - type: string + member_level: + description: 当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 + type: integer member_open_time: type: string member_status: type: integer - memberExpire: - description: 会员到期时间 - type: string - memberLevel: - description: 会员等级 1-会员 - type: integer open_member_channel: description: '开通会员渠道: -门店推广 -用户邀请 -兑换码' type: string open_member_level: - description: 开通会员级别:2-黄金会员 4-白金会员 5-黑金会员 + description: 开通会员级别:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 type: integer open_member_time: description: 开通会员时间 @@ -5026,10 +5112,6 @@ definitions: province: description: 省 type: string - renewal_member_level: - type: integer - renewal_time: - type: string shop_assistant_name: description: 店员名称 type: string @@ -5113,24 +5195,21 @@ definitions: mark: description: 标记 type: integer - member_level_string: - description: 会员类型 + member_expire: + description: 会员到期时间 type: string + member_level: + description: 当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 + type: integer member_open_time: type: string member_status: type: integer - memberExpire: - description: 会员到期时间 - type: string - memberLevel: - description: 会员等级 1-会员 - type: integer open_member_channel: description: '开通会员渠道: -门店推广 -用户邀请 -兑换码' type: string open_member_level: - description: 开通会员级别:2-黄金会员 4-白金会员 5-黑金会员 + description: 开通会员级别:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 type: integer open_member_time: description: 开通会员时间 @@ -5142,10 +5221,6 @@ definitions: province: description: 省 type: string - renewal_member_level: - type: integer - renewal_time: - type: string shop_assistant_name: description: 店员名称 type: string @@ -5964,6 +6039,21 @@ paths: tags: - 合作商 - v1.2.0 + /api/v1/cooperative/get_default_info: + post: + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.DefaultUserNameAndPasswordResp' + summary: 获取合作商默认用户名和密码 + tags: + - 合作商 + - v1.2.0 /api/v1/cooperative/get_pay_info: post: consumes: @@ -6798,7 +6888,7 @@ paths: name: request required: true schema: - $ref: '#/definitions/models.ErpPurchaseTerminateReq' + $ref: '#/definitions/models.ErpPurchaseDeleteReq' produces: - application/json responses: @@ -7096,6 +7186,28 @@ paths: tags: - 采购管理 - V1.3.0 + /api/v1/group_send_message/template/list: + post: + consumes: + - application/json + parameters: + - description: 查询短信模版列表模型 + in: body + name: request + required: true + schema: + $ref: '#/definitions/models.GroupSendMessageCreateTemplateListReq' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.GroupSendMessageCreateTemplateListResp' + summary: 短信群发 + tags: + - 短信群发 + - V1.2.0 /api/v1/inventory/add_remark: post: consumes: diff --git a/test/gen_test.go b/test/gen_test.go index c56b562..71494a9 100644 --- a/test/gen_test.go +++ b/test/gen_test.go @@ -494,3 +494,11 @@ func TestUpdateStorePassWdTest(t *testing.T) { } } } + +func TestUpdateExpireMemberLevel(t *testing.T) { + fmt.Println("test UpdateExpireMemberLevel start") + InitIODBTest() + orm.Eloquent = IODBTest + models.UpdateExpireMemberLevel() + fmt.Println("test UpdateExpireMemberLevel end") +} diff --git a/test/stock_test.go b/test/stock_test.go index 86f1774..d49021d 100644 --- a/test/stock_test.go +++ b/test/stock_test.go @@ -155,7 +155,8 @@ func InitIODBTest() { //} //driver := "mysql" - source := "mh_dev:m5h4parZsXjbeiFh@tcp(39.108.188.218:3306)/mh_dev?charset=utf8&parseTime=True&loc=Local&timeout=1000ms" + source := "mh_dev:d9qy46ONI0ZTF9eH@tcp(112.33.14.191:3306)/mh_dev?charset=utf8&parseTime=True&loc=Local&timeout=1000ms" + //source := "mh_dev:m5h4parZsXjbeiFh@tcp(39.108.188.218:3306)/mh_dev?charset=utf8&parseTime=True&loc=Local&timeout=1000ms" //global.Source = source //global.Logger.Info(tools.Green(global.Source)) db, err := sql.Open("mysql", source) diff --git a/tools/utils.go b/tools/utils.go index a520d52..71a13f9 100644 --- a/tools/utils.go +++ b/tools/utils.go @@ -98,3 +98,14 @@ func ConvertTimeToString(t time.Time) string { } return t.Format("2006-01-02 15:04:05") } + +// ConvertTimeToStringByPoint 将time类型转换为string +func ConvertTimeToStringByPoint(t *time.Time) string { + if t == nil { + return "" // 零值或 nil 返回空字符串 + } + if t.IsZero() { + return "" // 零值或 nil 返回空字符串 + } + return t.Format("2006-01-02 15:04:05") +}