1、租赁订单归还增加"超期处理"的逻辑,超期处理的订单状态为7,用户信息中保证金清零,且mark=1;

2、优化租赁订单查询列表接口,解决查询慢的问题;已完成状态改为(4,7);
This commit is contained in:
chenlin 2025-07-17 11:06:49 +08:00
parent f670065965
commit 9c4e75d749
2 changed files with 286 additions and 85 deletions

View File

@ -122,6 +122,34 @@ func RevertGoods(c *gin.Context) {
return
}
if len(order.PhoneExt) != 4 {
app.Error(c, http.StatusBadRequest, errors.New("手机尾号填写有误4位数字"),
"手机尾号填写有误4位数字")
return
}
if order.OverdueFlag == 1 { // 检查用户会员是否过期
var orderInfo models.Order
err := orm.Eloquent.Table("order").Where("id", order.ID).Find(&orderInfo).Error
if err != nil {
app.Error(c, http.StatusBadRequest, err, err.Error())
return
}
userInfo, err := models.GetUserInfoByUid(uint32(orderInfo.Uid))
if err != nil {
app.Error(c, http.StatusBadRequest, err, err.Error())
return
}
if userInfo.MemberLevel == 2 || userInfo.MemberLevel == 3 || userInfo.MemberLevel == 4 ||
userInfo.MemberLevel == 5 {
app.Error(c, http.StatusBadRequest, errors.New("该用户会员还未过期,不能选择超期处理"),
"该用户会员还未过期,不能选择超期处理")
return
}
}
if order.RevertShopperCode != "" && !models.CheckCode(order.RevertShopperCode) {
app.Error(c, http.StatusBadRequest, errors.New("order revert shopper code err"), "店员码错误")
return

View File

@ -23,12 +23,13 @@ import (
)
const (
OrderCardStatusUnPick = 1 // 待取货中
OrderCardStatusPlaying = 2 // 游玩中
OrderCardStatusReturning = 3 // 归还中
OrderCardStatusCompleted = 4 // 已完成
OrderCardStatusCancel = 5 // 已取消
OrderCardStatusRefund = 6 // 已退款
OrderCardStatusUnPick = 1 // 待取货中
OrderCardStatusPlaying = 2 // 游玩中
OrderCardStatusReturning = 3 // 归还中
OrderCardStatusCompleted = 4 // 已完成
OrderCardStatusCancel = 5 // 已取消
OrderCardStatusRefund = 6 // 已退款
OrderCardStatusSystemReturn = 7 // 系统处理(超期卡)
DeliveryTypeStorePick = 1 // 门店取货
DeliveryTypeExpress = 2 // 快递取货
@ -79,9 +80,10 @@ type Order struct {
GameCardSerialNumbers []string `json:"game_card_serial_numbers" gorm:"-"`
OrderCards []OrderCard `json:"order_cards" gorm:"-"`
DeliverShopperCode string `json:"deliver_shopper_code" gorm:"-"` //发货店员码
RevertShopperCode string `json:"revert_shopper_code" gorm:"-"`
PhoneExt string `json:"phone_ext" gorm:"-"`
DeliverShopperCode string `json:"deliver_shopper_code" gorm:"-"` // 发货店员码
RevertShopperCode string `json:"revert_shopper_code" gorm:"-"` // 店员识别码
PhoneExt string `json:"phone_ext" gorm:"-"` // 用户手机号后四位
OverdueFlag uint32 `json:"overdue_flag" gorm:"-"` // 超期处理标志1
User *UserInfo `json:"user" gorm:"foreignKey:uid;references:uid"`
}
@ -229,20 +231,159 @@ func (m *OrderListReq) List(exportFlag int, c *gin.Context) ([]Order, int64, str
return orders, count, filePath, nil
}
//func (m *OrderListReq) queryListFormOrderCard(exportFlag int, c *gin.Context) ([]Order, int64, error) {
// var orderCards []OrderCard
// orders := make([]Order, 0)
//
// qs := orm.Eloquent.Table("order_card").Where("card_status=?", m.CardStatus)
//
// // 非管理员才判断所属门店
// if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
// sysUser, err := GetSysUserByCtx(c)
// if err != nil {
// return nil, 0, err
// }
//
// // 返回sysUser未过期的门店id列表
// storeList := GetValidStoreIDs(sysUser.StoreData)
// if m.StoreId != 0 {
// if !Contains(storeList, uint32(m.StoreId)) {
// return nil, 0, errors.New("您没有该门店权限")
// }
// } else {
// if len(storeList) > 0 {
// if len(storeList) == 1 {
// qs = qs.Where("store_id = ? OR revert_store_id = ?", storeList[0], storeList[0])
// } else {
// qs = qs.Where("store_id IN (?) OR revert_store_id IN (?)", storeList, storeList)
// }
// } else {
// return nil, 0, errors.New("用户未绑定门店")
// }
// }
// }
//
// if m.SerialNumber != "" {
// qs = qs.Where("serial_number=?", m.SerialNumber)
// }
//
// if m.DeliveryType != 0 { // 共有
// qs = qs.Where("delivery_type", m.DeliveryType)
// }
//
// if m.Uid != 0 { // 用户id共有
// qs = qs.Where("uid", m.Uid)
// }
// if m.GameCardId != 0 { // 游戏卡id共有
// qs = qs.Where("game_card_id", m.GameCardId)
// }
//
// if m.StoreId != 0 { // 门店id共有
// qs = qs.Where("store_id = ? OR revert_store_id = ?", m.StoreId, m.StoreId)
// }
// if !m.StartTime.IsZero() { // 共有
// fmt.Println("起始时间:", m.StartTime.Unix())
// qs = qs.Where("created_at > ?", m.StartTime)
// }
// if !m.EndTime.IsZero() { // 共有
// fmt.Println("时间:", m.StartTime.Unix())
// qs = qs.Where("created_at < ?", m.EndTime)
// }
//
// err := qs.Find(&orderCards).Error
// if err != nil {
// logger.Error("err:", logger.Field("err", err))
// return nil, 0, err
// }
//
// orderIds := make([]uint32, 0)
// for i, _ := range orderCards {
// orderIds = append(orderIds, orderCards[i].OrderId)
// }
//
// orderQs := orm.Eloquent.Table("order").Where("pay_status", 2).Where("id in (?)", orderIds)
// var count int64
// err = orderQs.Count(&count).Error
// if err != nil {
// logger.Errorf("err:", logger.Field("err", err))
// return nil, 0, err
// }
//
// page := m.Page
// pageSize := m.PageSize
// page -= 1
// if page < 0 {
// page = 0
// }
//
// if exportFlag == 1 { //一次性导出excel
// orderQs = orderQs.Preload("User").Order("created_at DESC")
// } else {
// orderQs = orderQs.Preload("User").Order("created_at DESC").Offset(page * pageSize).Limit(pageSize)
// }
// err = orderQs.Find(&orders).Error
// if err != nil {
// logger.Errorf("err:", logger.Field("err", err))
// return nil, 0, err
// }
//
// ids := make([]uint32, 0, len(orders))
// for i, _ := range orders {
// ids = append(ids, uint32(orders[i].ID))
// }
// if len(ids) == 0 {
// logger.Error("gameIds is nil")
// return nil, 0, err
// }
//
// err = orm.Eloquent.Table("order_card").Where("order_id in (?)", ids).Find(&orderCards).Error
// if err != nil {
// logger.Error("err:", logger.Field("err", err))
// return nil, 0, err
// }
// orderCards = OrderCardListSetGameInfo(orderCards)
// orderCardsMap := make(map[uint32][]OrderCard, 0)
// for i, _ := range orderCards {
// if orderCards[i].CardStatus == OrderCardStatusSystemReturn {
// orderCards[i].CardStatus = OrderCardStatusCompleted
// }
//
// if orderCards[i].CardStatus == m.CardStatus { //卡片状态相同的租卡订单才返回,方便财务导出数据
// orderCardsMap[orderCards[i].OrderId] = append(orderCardsMap[orderCards[i].OrderId], orderCards[i])
// }
// }
// for i, _ := range orders {
// //2023-12-12 跟产品讨论后确认状态按原来的5种进行展示
// //if orders[i].CardStatus == 2 || orders[i].CardStatus == 3 {
// // orders[i].CardStatus = 4
// //}
// v, ok := orderCardsMap[orders[i].ID]
// if ok {
// orders[i].OrderCards = v
// }
// }
//
// return orders, count, nil
//}
func (m *OrderListReq) queryListFormOrderCard(exportFlag int, c *gin.Context) ([]Order, int64, error) {
var orderCards []OrderCard
orders := make([]Order, 0)
var orderIds []uint32
qs := orm.Eloquent.Table("order_card").Where("card_status=?", m.CardStatus)
// 初始 card 表查询
cardQs := orm.Eloquent.Table("order_card").Select("DISTINCT order_id")
if m.CardStatus == OrderCardStatusCompleted {
cardQs = cardQs.Where("pay_status = 2 and card_status in (?)", []int{OrderCardStatusCompleted, OrderCardStatusSystemReturn})
} else {
cardQs = cardQs.Where("pay_status = 2 and card_status = ?", m.CardStatus)
}
// 非管理员才判断所属门店
// 权限控制
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
sysUser, err := GetSysUserByCtx(c)
if err != nil {
return nil, 0, err
}
// 返回sysUser未过期的门店id列表
storeList := GetValidStoreIDs(sysUser.StoreData)
if m.StoreId != 0 {
if !Contains(storeList, uint32(m.StoreId)) {
@ -251,9 +392,9 @@ func (m *OrderListReq) queryListFormOrderCard(exportFlag int, c *gin.Context) ([
} else {
if len(storeList) > 0 {
if len(storeList) == 1 {
qs = qs.Where("store_id = ? OR revert_store_id = ?", storeList[0], storeList[0])
cardQs = cardQs.Where("store_id = ? OR revert_store_id = ?", storeList[0], storeList[0])
} else {
qs = qs.Where("store_id IN (?) OR revert_store_id IN (?)", storeList, storeList)
cardQs = cardQs.Where("store_id IN (?) OR revert_store_id IN (?)", storeList, storeList)
}
} else {
return nil, 0, errors.New("用户未绑定门店")
@ -261,98 +402,106 @@ func (m *OrderListReq) queryListFormOrderCard(exportFlag int, c *gin.Context) ([
}
}
// 其他筛选条件
if m.SerialNumber != "" {
qs = qs.Where("serial_number=?", m.SerialNumber)
cardQs = cardQs.Where("serial_number = ?", m.SerialNumber)
}
if m.DeliveryType != 0 {
cardQs = cardQs.Where("delivery_type = ?", m.DeliveryType)
}
if m.Uid != 0 {
cardQs = cardQs.Where("uid = ?", m.Uid)
}
if m.GameCardId != 0 {
cardQs = cardQs.Where("game_card_id = ?", m.GameCardId)
}
if m.StoreId != 0 {
cardQs = cardQs.Where("store_id = ? OR revert_store_id = ?", m.StoreId, m.StoreId)
}
if !m.StartTime.IsZero() {
cardQs = cardQs.Where("created_at > ?", m.StartTime)
}
if !m.EndTime.IsZero() {
cardQs = cardQs.Where("created_at < ?", m.EndTime)
}
if m.DeliveryType != 0 { // 共有
qs = qs.Where("delivery_type", m.DeliveryType)
}
if m.Uid != 0 { // 用户id共有
qs = qs.Where("uid", m.Uid)
}
if m.GameCardId != 0 { // 游戏卡id共有
qs = qs.Where("game_card_id", m.GameCardId)
}
if m.StoreId != 0 { // 门店id共有
qs = qs.Where("store_id = ? OR revert_store_id = ?", m.StoreId, m.StoreId)
}
if !m.StartTime.IsZero() { // 共有
fmt.Println("起始时间:", m.StartTime.Unix())
qs = qs.Where("created_at > ?", m.StartTime)
}
if !m.EndTime.IsZero() { // 共有
fmt.Println("时间:", m.StartTime.Unix())
qs = qs.Where("created_at < ?", m.EndTime)
}
err := qs.Find(&orderCards).Error
if err != nil {
logger.Error("err:", logger.Field("err", err))
return nil, 0, err
}
orderIds := make([]uint32, 0)
for i, _ := range orderCards {
orderIds = append(orderIds, orderCards[i].OrderId)
}
orderQs := orm.Eloquent.Table("order").Where("pay_status", 2).Where("id in (?)", orderIds)
// 统计总数(订单数)
var count int64
err = orderQs.Count(&count).Error
err := cardQs.Count(&count).Error
if err != nil {
logger.Errorf("err:", logger.Field("err", err))
logger.Error("统计订单数量失败:", logger.Field("err", err))
return nil, 0, err
}
if count == 0 {
return []Order{}, 0, nil
}
// 分页参数
page := m.Page
pageSize := m.PageSize
page -= 1
if page < 0 {
page = 0
if page < 1 {
page = 1
}
offset := (page - 1) * pageSize
// 查询分页的 order_iddistinct 结果)
cardQs = cardQs.Order("order_id DESC")
if exportFlag == 0 {
cardQs = cardQs.Offset(offset).Limit(pageSize)
}
err = cardQs.Pluck("order_id", &orderIds).Error
if err != nil {
logger.Error("分页查询 order_card 失败:", logger.Field("err", err))
return nil, 0, err
}
if exportFlag == 1 { //一次性导出excel
orderQs = orderQs.Preload("User").Order("created_at DESC")
} else {
orderQs = orderQs.Preload("User").Order("created_at DESC").Offset(page * pageSize).Limit(pageSize)
if len(orderIds) == 0 {
return []Order{}, count, nil
}
// 查询订单
orderQs := orm.Eloquent.Table("order").
Where("pay_status = ?", 2).
Where("id IN (?)", orderIds).
Preload("User").
Order("created_at DESC")
err = orderQs.Find(&orders).Error
if err != nil {
logger.Errorf("err:", logger.Field("err", err))
logger.Error("查询 order 失败:", logger.Field("err", err))
return nil, 0, err
}
ids := make([]uint32, 0, len(orders))
for i, _ := range orders {
ids = append(ids, uint32(orders[i].ID))
}
if len(ids) == 0 {
logger.Error("gameIds is nil")
return nil, 0, err
// 反查关联的卡片
var orderCards []OrderCard
if m.CardStatus == OrderCardStatusCompleted {
err = orm.Eloquent.Table("order_card").
Where("order_id IN (?) AND card_status IN (?)", orderIds, []int{OrderCardStatusCompleted, OrderCardStatusSystemReturn}).
Find(&orderCards).Error
} else {
err = orm.Eloquent.Table("order_card").
Where("order_id IN (?) AND card_status = ?", orderIds, m.CardStatus).
Find(&orderCards).Error
}
err = orm.Eloquent.Table("order_card").Where("order_id in (?)", ids).Find(&orderCards).Error
if err != nil {
logger.Error("err:", logger.Field("err", err))
logger.Error("查询 order_card 失败:", logger.Field("err", err))
return nil, 0, err
}
orderCards = OrderCardListSetGameInfo(orderCards)
orderCardsMap := make(map[uint32][]OrderCard, 0)
for i, _ := range orderCards {
if orderCards[i].CardStatus == m.CardStatus { //卡片状态相同的租卡订单才返回,方便财务导出数据
orderCardsMap[orderCards[i].OrderId] = append(orderCardsMap[orderCards[i].OrderId], orderCards[i])
// 绑定卡片到订单
orderCardsMap := make(map[uint32][]OrderCard)
for _, oc := range orderCards {
if oc.CardStatus == OrderCardStatusSystemReturn {
oc.CardStatus = OrderCardStatusCompleted
}
orderCardsMap[oc.OrderId] = append(orderCardsMap[oc.OrderId], oc)
}
for i, _ := range orders {
//2023-12-12 跟产品讨论后确认状态按原来的5种进行展示
//if orders[i].CardStatus == 2 || orders[i].CardStatus == 3 {
// orders[i].CardStatus = 4
//}
v, ok := orderCardsMap[orders[i].ID]
if ok {
for i := range orders {
if v, ok := orderCardsMap[orders[i].ID]; ok {
orders[i].OrderCards = v
}
}
@ -495,6 +644,9 @@ func (m *OrderListReq) queryListFormOrder(exportFlag int, c *gin.Context) ([]Ord
orderCards = OrderCardListSetGameInfo(orderCards)
orderCardsMap := make(map[uint32][]OrderCard, 0)
for i, _ := range orderCards {
if orderCards[i].CardStatus == OrderCardStatusSystemReturn {
orderCards[i].CardStatus = OrderCardStatusCompleted
}
orderCardsMap[orderCards[i].OrderId] = append(orderCardsMap[orderCards[i].OrderId], orderCards[i])
}
for i, _ := range orders {
@ -1094,6 +1246,13 @@ func (m *Order) Revert() error {
logger.Error("order store id not game card goods store id")
return errors.New("order store id not game card goods store id")
}
// 判断是否有超期还卡标志
cardStatusFlag := OrderCardStatusCompleted
if m.OverdueFlag == 1 {
cardStatusFlag = OrderCardStatusSystemReturn
}
begin := orm.Eloquent.Begin()
var eg errgroup.Group
//eg.Go(func() error {
@ -1226,7 +1385,7 @@ func (m *Order) Revert() error {
if m.RevertExpressNo != "" { // 物流单号不为空则记录到数据库2024/2/1 产品新需求,解决用户物流归还但小程序不提交归还信息,店员要输入手机号的问题
err = begin.Table("order_card").Where("id=?", orderCard.ID).Updates(&map[string]interface{}{
//"store_id": m.StoreId,
"card_status": OrderCardStatusCompleted,
"card_status": cardStatusFlag,
"revert_store_id": m.RevertStoreId,
"revert_time": time.Now(),
"revert_shopper_code": m.RevertShopperCode,
@ -1239,7 +1398,7 @@ func (m *Order) Revert() error {
} else {
err = begin.Table("order_card").Where("id=?", orderCard.ID).Updates(&map[string]interface{}{
//"store_id": m.StoreId,
"card_status": OrderCardStatusCompleted,
"card_status": cardStatusFlag,
"revert_store_id": m.RevertStoreId,
"revert_time": time.Now(),
"revert_shopper_code": m.RevertShopperCode,
@ -1281,7 +1440,21 @@ func (m *Order) Revert() error {
}
return nil
})
//orderCard.StoreId
if m.OverdueFlag == 1 { // 押金清零
eg.Go(func() error {
sql := fmt.Sprintf(
"UPDATE user SET deposit = 0, mark = 1 WHERE uid =%d;",
orderCard.Uid)
fmt.Println("sql:", sql)
err = begin.Exec(sql).Error
if err != nil {
logger.Errorf("err:", logger.Field("err", err))
return err
}
return nil
})
}
err = eg.Wait()
if err != nil {
logger.Errorf("err:", logger.Field("err", err))