package models import ( "context" "encoding/json" "errors" "fmt" "github.com/gin-gonic/gin" "github.com/wechatpay-apiv3/wechatpay-go/core" "github.com/wechatpay-apiv3/wechatpay-go/core/option" "github.com/wechatpay-apiv3/wechatpay-go/services/certificates" "github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi" wechatpayutils "github.com/wechatpay-apiv3/wechatpay-go/utils" "github.com/xuri/excelize/v2" "go-admin/app/admin/models/kuaidi" orm "go-admin/common/global" "go-admin/logger" "go-admin/tools" "go-admin/tools/config" "golang.org/x/sync/errgroup" "strconv" "time" ) const ( OrderCardStatusUnPick = 1 // 待取货中 OrderCardStatusPlaying = 2 // 游玩中 OrderCardStatusReturning = 3 // 归还中 OrderCardStatusCompleted = 4 // 已完成 OrderCardStatusCancel = 5 // 已取消 OrderCardStatusRefund = 6 // 已退款 DeliveryTypeStorePick = 1 // 门店取货 DeliveryTypeExpress = 2 // 快递取货 ExpressFeeProvince = 10 * 100 // 省内 ExpressFeeOutsideProvince = 15 * 100 // 省外 PayStatusUnPay = 1 // 未支付 PayStatusPaid = 2 // 已支付 ) // gen:qs // //go:generate goqueryset -in order.go type Order struct { Model Uid uint64 `json:"uid" gorm:"index"` GameCardId uint64 `json:"game_card_id" gorm:"index"` // 游戏id GameCardGoodsId uint64 `json:"game_card_goods_id" gorm:"index"` // 游戏卡id GameCardSerialNumber string `json:"game_card_serial_number" gorm:"index"` // 游戏卡编号 StoreId uint64 `json:"store_id" gorm:"index"` // 门店id UserAddressId uint64 `json:"user_address_id"` // 地址id DeliveryType uint8 `json:"delivery_type"` // 取货类型 1-门店自取 2-快递 Count uint32 `json:"count"` // 数量 PickupCode string `json:"pickup_code"` // 取货码 CardStatus uint8 `json:"card_status"` // 1-待取货中 2-游玩中 3-归还中 4-已完成 5-已取消 DeliveryTime time.Time `json:"delivery_time"` // 发货时间 ReceiptTime time.Time `json:"receipt_time"` // 收货时间 签收时间 PayTime time.Time `json:"pay_time"` // 支付时间 PayStatus uint8 `json:"pay_status"` // 支付状态 1-未支付 2-已支付 OrderSn string `json:"order_sn" gorm:"type:varchar(255);not null;COMMENT:'订单编号'"` // 订单编号 PayPrice uint32 `json:"pay_price"` // 实际付款金额(包含运费) Postage uint32 `json:"postage"` // 邮费 ExpressCompany string `json:"express_company"` // 物流公司 ExpressCompanyNo string `json:"express_company_no"` // 物流公司编号 ExpressNo string `json:"express_no"` // 物流单号 ExpressDuration uint64 `json:"express_duration"` // 物流时长 RevertStoreId uint64 `json:"revert_store_id"` // 归还门店id RevertTime time.Time `json:"revert_time"` // 归还时间 RevertExpressCompany string `json:"revert_express_company"` // 归还物流公司 RevertExpressCompanyNo string `json:"revert_express_company_no"` // 归还物流公司编号 RevertExpressNo string `json:"revert_express_no"` // 归还物流单号 RevertExpressDuration uint64 `json:"revert_express_duration"` // 归还物流时长 CooperativeBusinessId uint32 `json:"cooperative_business_id"` // 合作商id CooperativeName string `json:"cooperative_name"` // 合作商名称 //收货店员码 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:"-"` User *UserInfo `json:"user" gorm:"foreignKey:uid;references:uid"` } func (*Order) TableName() string { return "order" } // gen:qs type OrderCard struct { Model OrderId uint32 `json:"order_id" gorm:"index"` Uid uint32 `json:"uid" gorm:"index"` GameCardId uint32 `json:"game_card_id" gorm:"index"` // 游戏id GameCardGoodsId uint32 `json:"game_card_goods_id" gorm:"index"` // 游戏卡id StoreId uint32 `json:"store_id" gorm:"index"` // 门店id CardStatus uint8 `json:"card_status"` // 1-待取货中 2-游玩中 3-归还中 4-已完成 5-已取消 DeliveryTime time.Time `json:"delivery_time"` // 发货时间 ReceiptTime time.Time `json:"receipt_time"` // 收货时间 签收时间 DeliveryType uint8 `json:"delivery_type"` // 取货类型 1-门店自取 2-快递 SerialNumber string `json:"serial_number" gorm:"index"` // 编号 PayStatus uint8 `json:"pay_status"` // 支付状态 1-未支付 2-已支付 RevertStoreId uint64 `json:"revert_store_id"` // 归还门店id RevertTime time.Time `json:"revert_time"` // 归还时间 RevertExpressCompany string `json:"revert_express_company"` // 归还物流公司 RevertExpressCompanyNo string `json:"revert_express_company_no"` // 归还物流公司编号 RevertExpressNo string `json:"revert_express_no"` // 归还物流单号 RevertExpressDuration uint64 `json:"revert_express_duration"` // 归还物流时长 IssueType uint32 `json:"issue_type"` // 问题类型: 1-问题反馈 2-正常 Postage uint32 `json:"postage" gorm:"-"` // 邮费 ExpressCompany string `json:"express_company" gorm:"-"` // 物流公司 ExpressCompanyNo string `json:"express_company_no" gorm:"-"` // 物流公司编号 ExpressNo string `json:"express_no" gorm:"-"` // 物流单号 CooperativeBusinessId uint32 `json:"cooperative_business_id"` // 合作商id CooperativeName string `json:"cooperative_name"` // 合作商名称 GameName string `json:"name" gorm:"-"` // 名称 GamePrice uint32 `json:"price" gorm:"-"` // 价格 GameCoverImg string `json:"cover_img" gorm:"-"` // 封面 Order *Order `json:"order" gorm:"-"` // 订单 RevertStore *Store `json:"revert_store" gorm:"-"` // 归还门店 DeliverShopperCode string `json:"deliver_shopper_code"` //发货店员码 RevertShopperCode string `json:"revert_shopper_code"` //收货识别码 DeliverShopper *ShopperPromotionCode `json:"deliver_shopper" gorm:"foreignKey:deliver_shopper_code;references:code"` //发货店员 RevertShopper *ShopperPromotionCode `json:"revert_shopper" gorm:"foreignKey:revert_shopper_code;references:code"` //收货店员 GameCard *GameCard `json:"game_card" gorm:"foreignKey:game_card_id;references:id"` //卡带信息 } func (*OrderCard) TableName() string { return "order_card" } func (m *Order) ToInfo(card *GameCard) OrderInfo { return OrderInfo{ Order: *m, GameName: card.Name, GamePrice: card.Price, GameCoverImg: card.CoverImg, } } type OrderInfo struct { Order GameName string `json:"name" gorm:"index"` // 名称 GamePrice uint32 `json:"price" gorm:"index"` // 价格 GameCoverImg string `json:"cover_img"` // 封面 } const ( LogCorrelationOrderId = "order_id" LogCorrelationOrderCard = "order_card_id" LogCorrelationRecycleCardOrderId = "recycle_card_order_id" ) const ( OperationTypeRevertRentCard = "revert_rent_card" // 归还租卡 OperationTypeUserShareCard = "user_share_card" // 用户共享卡 OperationTypeIssueCard = "issue_card" // 问题卡反馈 OperationTypeRecycleCardOrderImageUpdate = "recycle_card_order_image_update" // 回收卡上传图片 ) type ExpressNoInfo struct { ExpressCompany string `json:"express_company" gorm:"-"` // 物流公司 ExpressCompanyNo string `json:"express_company_no" gorm:"-"` // 物流公司编号 ExpressNo string `json:"express_no" gorm:"-"` // 物流单号 StoreId uint32 `json:"store_id" gorm:"-"` OperationType string `json:"operation_type" gorm:"-"` CorrelationId uint32 `json:"correlation_id" gorm:"-"` Store *Store `json:"store" gorm:"-"` } // gen:qs type ExpressCompany struct { Model CompanyName string `json:"company_name"` CompanyCode string `json:"company_code"` } func (*ExpressCompany) TableName() string { return "express_company" } type OrderListReq struct { Uid uint64 `json:"uid" ` OrderId uint64 `json:"order_id"` GameCardId uint64 `json:"game_card_id" ` StoreId uint64 `json:"store_id" ` // 门店id// 游戏id CardStatus uint8 `json:"card_status"` // 1-待取货中 2-游玩中 3-归还中 4-已完成 5-已取消 PayStatus uint8 `json:"pay_status"` // 支付状态 1-未支付 2-已支付 DeliveryType uint8 `json:"delivery_type"` // 取货类型 1-门店自取 2-快递 SerialNumber string `json:"serial_number" ` // 编号 PickupCode string `json:"pickup_code"` // 取货码 StartTime time.Time `json:"start_time"` // 开始时间 EndTime time.Time `json:"end_time"` // 结束时间 Page int `json:"pageIndex"` PageSize int `json:"pageSize"` } func (m *OrderListReq) List(exportFlag int, c *gin.Context) ([]Order, int64, string, error) { orders := make([]Order, 0) if m.PageSize == 0 { m.PageSize = 10 } var count int64 var err error // 如果卡片类型不为空,则优先查询order_card表 if m.CardStatus != 0 { orders, count, err = m.queryListFormOrderCard(exportFlag, c) } else { orders, count, err = m.queryListFormOrder(exportFlag, c) } filePath := "" if exportFlag == 1 { filePath, err = OrderListExport(orders) if err != nil { logger.Error("OrderListExport err:", logger.Field("err", err)) return orders, 0, "", err } } 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 == 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) queryListFormOrder(exportFlag int, c *gin.Context) ([]Order, int64, error) { var orderCards []OrderCard orders := make([]Order, 0) if m.PageSize == 0 { m.PageSize = 10 } qs := orm.Eloquent.Table("order").Select("DISTINCT `order`.*").Joins("JOIN order_card ON order.id = order_card.order_id"). Where("order.pay_status = ?", 2) orderQs := orm.Eloquent.Table("(?) as unique_orders", qs).Order("unique_orders.created_at DESC") //qs = orm.Eloquent.Table("order").Where("pay_status", 2) // 非管理员才判断所属门店 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("order.store_id = ? OR order_card.revert_store_id = ?", storeList[0], storeList[0]) } else { qs = qs.Where("order.store_id IN (?) OR order_card.revert_store_id IN (?)", storeList, storeList) } } else { return nil, 0, errors.New("用户未绑定门店") } } } isDeliver := true if m.SerialNumber != "" { isDeliver = false err := orm.Eloquent.Table("order_card").Where("serial_number=?", m.SerialNumber). Order("id DESC").Order("card_status ASC").Find(&orderCards).Error //Where("card_status in (?)", []uint32{2, 3}).Order("id DESC").Order("card_status DESC").Limit(30).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) } qs = qs.Where("order.id in (?)", orderIds) } if m.PickupCode != "" { isDeliver = false qs = qs.Where("order.pickup_code", m.PickupCode) } if m.PayStatus != 0 { qs = qs.Where("order.pay_status", m.PayStatus) } if m.DeliveryType != 0 { qs = qs.Where("order.delivery_type", m.DeliveryType) } if m.OrderId != 0 { isDeliver = false qs = qs.Where("order.id", m.OrderId) } if isDeliver { if m.Uid != 0 { qs = qs.Where("order.uid", m.Uid) } if m.GameCardId != 0 { qs = qs.Where("order.game_card_id", m.GameCardId) } if m.StoreId != 0 { qs = qs.Where("order.store_id = ? OR order_card.revert_store_id = ?", m.StoreId, m.StoreId) } if !m.StartTime.IsZero() { fmt.Println("起始时间:", m.StartTime.Unix()) qs = qs.Where("order.created_at > ?", m.StartTime) } if !m.EndTime.IsZero() { fmt.Println("时间:", m.StartTime.Unix()) qs = qs.Where("order.created_at < ?", m.EndTime) } } 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") } else { orderQs = orderQs.Preload("User").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 { 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 } // OrderListExport 导出订单列表 func OrderListExport(list []Order) (string, error) { file := excelize.NewFile() streamWriter, err := file.NewStreamWriter("Sheet1") if err != nil { fmt.Println(err) } url := config.ExportConfig.Url fileName := time.Now().Format(TimeFormat) + "租赁订单" + ".xlsx" fmt.Println("url fileName:", url+fileName) title := []interface{}{"租赁ID", "用户ID", "会员剩余时长", "取货方式", "状态", "取货码", "实付款", "下单时间", "游戏卡ID", "游戏名称", "游戏卡状态", "商品串码"} cell, _ := excelize.CoordinatesToCellName(1, 1) if err = streamWriter.SetRow(cell, title); err != nil { fmt.Println(err) } var row []interface{} nExcelStartRow := 0 for rowId := 0; rowId < len(list); rowId++ { state := "待取货" switch list[rowId].CardStatus { case 2: state = "游玩中" case 3: state = "归还中" case 4: state = "已完成" case 5: state = "已取消" } deliveryType := "门店自提" switch list[rowId].DeliveryType { case 1: deliveryType = "门店自提" case 2: deliveryType = "物流配送" } // user有可能为空 memberExpire := "" if list[rowId].User != nil { memberExpire = calculateRemainingDays(*list[rowId].User.MemberExpire) } for i := 0; i < len(list[rowId].OrderCards); i++ { cardState := "待取货" switch list[rowId].OrderCards[i].CardStatus { case 2: cardState = "游玩中" case 3: cardState = "归还中" case 4: cardState = "已完成" case 5: cardState = "已取消" } row = []interface{}{ list[rowId].ID, list[rowId].Uid, memberExpire, deliveryType, state, list[rowId].PickupCode, list[rowId].PayPrice, list[rowId].PayTime, //list[rowId].OrderCards[i].ID, // 租赁卡ID不导出 list[rowId].OrderCards[i].GameCardId, list[rowId].OrderCards[i].GameName, cardState, list[rowId].OrderCards[i].SerialNumber, } cell, _ := excelize.CoordinatesToCellName(1, nExcelStartRow+2) if err := streamWriter.SetRow(cell, row); err != nil { fmt.Println(err) } nExcelStartRow++ } } 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 } // 计算剩余时长 func calculateRemainingDays(expirationTime time.Time) string { currentTime := time.Now() remainingTime := expirationTime.Sub(currentTime) // 如果过期时间在当前时间之前,返回0天 if remainingTime < 0 { return "0天" } remainingDays := int(remainingTime.Hours() / 24) return fmt.Sprintf("%d天", remainingDays) } func (m *Order) Info() (map[string]interface{}, error) { ret := make(map[string]interface{}, 0) err := orm.Eloquent.Table("order").Where("id", m.ID).Find(m).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return ret, err } var orderCards []OrderCard err = orm.Eloquent.Table("order_card"). Preload("DeliverShopper"). Preload("DeliverShopper.User"). Preload("RevertShopper"). Preload("RevertShopper.User"). Where("order_id=?", m.ID). Find(&orderCards). Error if err != nil { logger.Error("err:", logger.Field("err", err)) return ret, err } var ( eg errgroup.Group storeCh = make(chan Store, 1) //revertStoreCh = make(chan Store, 1) userAddressCh = make(chan UserAddress, 1) userInfoCh = make(chan UserInfo, 1) ) eg.Go(func() error { var store Store err := orm.Eloquent.Table("store").Where("id", m.StoreId).Find(&store).Error if err != nil && err != RecordNotFound { storeCh <- store logger.Errorf("err:", logger.Field("err", err)) return err } storeCh <- store return nil }) //eg.Go(func() error { // var revertStore Store // err := orm.Eloquent.Table("store").Where("id", m.RevertStoreId).Find(&revertStore).Error // if err != nil && err != RecordNotFound { // storeCh <- revertStore // logger.Errorf("err:",logger.Field("err",err)) // return err // } // revertStoreCh <- revertStore // return nil //}) eg.Go(func() error { var userAddress UserAddress err := orm.Eloquent.Table("user_address").Where("id", m.UserAddressId).Find(&userAddress).Error if err != nil && err != RecordNotFound { userAddressCh <- userAddress logger.Errorf("err:", logger.Field("err", err)) return err } userAddressCh <- userAddress return nil }) eg.Go(func() error { var userInfo UserInfo err := orm.Eloquent.Table("user").Where("id", m.Uid).Find(&userInfo).Error if err != nil && err != RecordNotFound { userInfoCh <- userInfo logger.Errorf("err:", logger.Field("err", err)) return err } userInfoCh <- userInfo return nil }) err = eg.Wait() if err != nil { logger.Errorf("err:", logger.Field("err", err)) return ret, err } m.OrderCards = OrderCardListSetGameInfo(orderCards) if m.CardStatus == 2 || m.CardStatus == 3 { m.CardStatus = 4 } ret["order"] = *m ret["store"] = <-storeCh //ret["revert_store"] = <-revertStoreCh ret["userAddress"] = <-userAddressCh ret["user"] = <-userInfoCh return ret, nil } func (m *Order) Deliver() (error, string) { paraMap := make(map[string]interface{}, 0) // TODO 减库存 // TODO 更新卡的状态 var order Order err := orm.Eloquent.Table("order").Where("id", m.ID).Find(&order).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return err, "" } fmt.Println("Order:", m) cards, err := m.GetOrderCardGameCardIdList() if err != nil { logger.Error("err:", logger.Field("err", err)) return err, "" } if len(m.GameCardSerialNumbers) != len(cards) { logger.Errorf("发货卡的数量与订单游戏卡数量不一致") return errors.New("发货卡的数量与订单游戏卡数量不一致"), "发货卡的数量与订单游戏卡数量不一致" } var user UserInfo err = orm.Eloquent.Table("user").Where("uid", order.Uid).Find(&user).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return err, "" } if user.MemberExpire.Before(time.Now()) { logger.Errorf("会员已过期,不能发货") return errors.New("会员已过期,不能发货"), "会员已过期,不能发货" } fmt.Println("m.GameCardSerialNumbers:", m.GameCardSerialNumbers) orderCardMaps := make(map[uint32]OrderCard, 0) for i, _ := range cards { orderCardMaps[cards[i].ID] = cards[i] } receiptTime := time.Time{} if order.DeliveryType == 1 { receiptTime = time.Now() } isUpdateOrder := false begin := orm.Eloquent.Begin() for _, serialNumber := range m.GameCardSerialNumbers { //cards, err = m.GetOrderCardGameCardIdList() //if err != nil { // logger.Error("err:",logger.Field("err",err)) // return err, "" //} var ( gameCardGoods GameCardGoods orderCard *OrderCard ) if serialNumber != "" { paraMap["game_card_serial_number"] = serialNumber //var count int64 err := orm.Eloquent.Table("game_card_goods").Where("serial_number", serialNumber).Find(&gameCardGoods).Error if err != nil && err != RecordNotFound { begin.Rollback() logger.Errorf("err:", logger.Field("err", err)) return err, "" } if err == RecordNotFound { begin.Rollback() logger.Errorf("游戏编号卡未找到:%s", serialNumber) return errors.New("游戏卡未找到"), "编号的游戏卡不存在" } if gameCardGoods.Status == GameCardGoodsStatusCannibalize { begin.Rollback() return errors.New("card goods status err"), "该卡在调拨中,不能发货" } if gameCardGoods.Status != GameCardGoodsStatusStock { begin.Rollback() return errors.New("card goods status err"), "该卡状态,不能发货" } //err = orm.Eloquent.Table("order").Where("id", m.ID).Find(&order).Error //if err != nil && err != RecordNotFound { // begin.Rollback() // logger.Errorf("err:",logger.Field("err",err)) // return err, "" //} if order.CardStatus != OrderCardStatusUnPick { begin.Rollback() logger.Errorf("order not unpick") return errors.New("order not unpick"), "订单不是待取货状态" } if order.PayStatus != PayStatusPaid { begin.Rollback() logger.Errorf("order not pay") return errors.New("order not pay"), "订单未支付" } //if order.GameCardId != gameCardGoods.GameCardId { // logger.Errorf("游戏id卡未找到") // return errors.New("游戏卡与订单游戏不一致"), "编号的游戏卡不存在" //} orderCard = GetOrderCardMapSerialNumberUnset(orderCardMaps, uint32(gameCardGoods.GameCardId)) //orderCard, ok := cardMap[uint32(gameCardGoods.GameCardId)] if orderCard == nil { begin.Rollback() //logger.Errorf("订单游戏卡已发货") //return errors.New("订单游戏卡已发货"), "订单游戏卡已发货" logger.Errorf("发货游戏卡错误") return errors.New("发货游戏卡错误"), "发货游戏卡错误" } //orderCard, ok := orderCardMaps[uint32(gameCardGoods.GameCardId)] //if !ok { // logger.Errorf("发货游戏卡错误") // return errors.New("发货游戏卡错误"), "发货游戏卡错误" //} if m.StoreId != gameCardGoods.StoreId { begin.Rollback() logger.Errorf("游戏编号卡不是该门店") return errors.New("游戏编号卡不是该门店"), "该门店没有该游戏卡" } //fmt.Println("m.StoreId", m.StoreId) //fmt.Println("m.RevertStoreId", m.RevertStoreId) //fmt.Printf("m:%#v \n", m) //fmt.Println("orderCard.StoreId", orderCard.StoreId) if uint32(m.StoreId) != orderCard.StoreId { begin.Rollback() // 订单锁库存 logger.Errorf("订单门店与发货门店不一致") return errors.New("订单门店与发货门店不一致"), "订单门店与发货门店不一致,请取消订单后重新下单" } } if !isUpdateOrder { if m.StoreId != 0 { paraMap["store_id"] = m.StoreId paraMap["pickup_code"] = "已取货" paraMap["card_status"] = 4 paraMap["store_id"] = m.StoreId paraMap["delivery_time"] = time.Now() } if m.ExpressCompany != "" { paraMap["express_company"] = m.ExpressCompany } if m.ExpressCompanyNo != "" { paraMap["express_company_no"] = m.ExpressCompanyNo } if m.ExpressNo != "" { paraMap["express_no"] = m.ExpressNo } err := begin.Table("order").Where("id", m.ID).Updates(paraMap).Error if err != nil { begin.Rollback() logger.Errorf("err:", logger.Field("err", err)) return err, "" } isUpdateOrder = true } //goodsStatus := GameCardGoodsStatusInWay //if m.DeliveryType == 1 { goodsStatus := GameCardGoodsStatusCustomerHold //} var eg errgroup.Group eg.Go(func() error { err := begin.Table("game_card_goods").Where("serial_number", serialNumber). Update("status", goodsStatus).Error if err != nil { begin.Rollback() logger.Errorf("err:", logger.Field("err", err)) return err } return nil }) eg.Go(func() error { sql := fmt.Sprintf("UPDATE game_card_goods_stock SET user_hold_stock= user_hold_stock+1 WHERE store_id=%d AND game_card_id=%d;", m.StoreId, gameCardGoods.GameCardId) fmt.Println("sql:", sql) err := begin.Exec(sql).Error if err != nil { begin.Rollback() logger.Errorf("err:%s", err.Error()) return err } return nil }) // 归还加库存 //eg.Go(func() error { // if order.GameCardId != 0 { // sql := fmt.Sprintf("UPDATE game_card SET order_count = order_count+1 WHERE id = %d", order.GameCardId) // err := orm.Eloquent.Exec(sql).Error // if err != nil { // logger.Errorf("err:",logger.Field("err",err)) // return err // } // } // // return nil //}) eg.Go(func() error { var userInfo UserInfo err := orm.Eloquent.Table("user").Where("uid=?", order.Uid).Find(&userInfo).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } if userInfo.StoreId == 0 { sql := fmt.Sprintf("UPDATE `user` SET store_id = %d WHERE uid =%d", order.StoreId, order.Uid) err := begin.Exec(sql).Error if err != nil { begin.Rollback() logger.Errorf("err:", logger.Field("err", err)) return err } } //var userInvite UserInvite //err = orm.Eloquent.Table("user_11invite").Where("uid=?", order.Uid).Find(&userInvite).Error //if err == RecordNotFound { // invite := &UserInvite{ // FromUid: 0, // UserType: 0, // StoreId: order.StoreId, // MemberOpenTime: userInfo.MemberExpire.AddDate(-1, 0, 0), // MemberType: 2, // MemberStatus: 2, // ToUid: uint32(order.Uid), // StoreType: 1, // } // err := orm.Eloquent.Create(invite).Error // if err != nil { // logger.Errorf("err:",logger.Field("err",err)) // return err // } //} return nil }) eg.Go(func() error { //var orderCard OrderCard //err := orm.Eloquent.Table("order_card").Where("order_id=?", m.ID).Where("uid=?", order.Uid). // Where("game_card_id=?", gameCardGoods.GameCardId).Where("serial_number=''").Limit(1).Find(&orderCard).Error //if err != nil { // logger.Errorf("err:",logger.Field("err",err)) // return err //} //err = begin.Table("order_card").Where("id=?", orderCard.ID).Updates(&map[string]interface{}{ // "game_card_goods_id": gameCardGoods.ID, // "serial_number": gameCardGoods.SerialNumber, // "card_status": 2, //}).Error err = begin.Table("order_card").Where("id=?", orderCard.ID).Updates(&map[string]interface{}{ "store_id": m.StoreId, "delivery_time": time.Now(), "game_card_goods_id": gameCardGoods.ID, "serial_number": gameCardGoods.SerialNumber, "card_status": 2, "receipt_time": receiptTime, "deliver_shopper_code": m.DeliverShopperCode, }).Error if err != nil { begin.Rollback() logger.Errorf("err:", logger.Field("err", err)) return err } delete(orderCardMaps, orderCard.ID) return nil }) err = eg.Wait() if err != nil { begin.Rollback() logger.Errorf("err:", logger.Field("err", err)) return err, "" } } err = begin.Table("order_card").Where("order_id=?", m.ID).Where("uid=?", order.Uid). Where("serial_number=''").Updates(&map[string]interface{}{ "card_status": 5, }).Error err = begin.Commit().Error if err != nil { begin.Rollback() logger.Error("err:", logger.Field("err", err)) return err, "" } if m.ExpressCompanyNo != "" && m.ExpressNo != "" { _, err = kuaidi.SubscribeExpressState(m.ExpressCompanyNo, m.ExpressNo) if err != nil { logger.Error("subscribe express state err:", logger.Field("err", err)) } } //DeliverTask{} //err := orm.Eloquent.Table("order").Where("id", m.ID).Find(&order).Error UpdateDeliverTaskSubState(order.ID) if user.OpenMemberChannel == OpenMemberChannelStorePromotion { go func() { var orders []Order err = orm.Eloquent.Table("order").Where("uid=?", user.Uid). Where("card_status!=?", OrderCardStatusCancel).Where("pay_status=?", 2).Find(&orders).Error if err != nil { logger.Error("order err:", logger.Field("err", err)) return } if len(orders) == 1 && orders[0].CardStatus == 4 { err = orm.Eloquent.Table("user").Where("uid=?", user.Uid). Update("store_id", orders[0].StoreId).Error if err != nil { logger.Error("update store err:", logger.Field("err", err)) } } //if !exist && user.OpenMemberTime.Format(DateTimeFormat) == time.Now().Format(DateTimeFormat) { // //_, err = NewUserQuerySet(model.DB).UidEq(uc.Uid).GetUpdater().SetStoreId(uint64(req.StoreId)).UpdateNum() // if err != nil { // logger.Error("update user err:",logger.Field("err",err)) // } //} }() } return nil, "" } func (m *Order) Revert() error { OrderJson, _ := json.Marshal(m) fmt.Println("归还订单:", string(OrderJson)) var order Order err := orm.Eloquent.Table("order").Preload("User").Where("id", m.ID).Find(&order).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } if m.PhoneExt != "" && !order.User.CheckPhoneExt(m.PhoneExt, 4) { return errors.New("手机尾号校验不正确") } cardMap, err := order.GetOrderCardMap() if err != nil { logger.Error("err:", logger.Field("err", err)) return err } orderCardIds := make([]uint32, 0, len(cardMap)) for _, card := range cardMap { orderCardIds = append(orderCardIds, card.ID) } //CardIssueFeedback{} var issueCount int64 err = orm.Eloquent.Table("card_issue_feedback").Where("relevance_id in (?)", orderCardIds). Where("state=?", CardIssueStateFollowing).Count(&issueCount).Error if err != nil { logger.Errorf("err:%#v", logger.Field("err", err)) return err } if issueCount > 0 { logger.Error("untreated_issue_feedback") return errors.New("请先检测用户反馈问题卡") } //for _, serialNumber := range m.GameCardSerialNumbers { serialNumber := m.GameCardSerialNumber orderCard, ok := cardMap[serialNumber] if !ok { logger.Error("order card is not revert card") return errors.New("order card is not revert card") } if m.RevertStoreId == 0 { logger.Error("revert store id null") return errors.New("revert store id null") } if orderCard.CardStatus != OrderCardStatusReturning && orderCard.CardStatus != OrderCardStatusPlaying { logger.Error("order card status not returning playing ") return errors.New("order card status not returning playing ") } var gameCardGoods GameCardGoods //err := orm.Eloquent.Table("order").Where("game_card_serial_number", m.GameCardSerialNumber).Find(&gameCardGoods).Error err = orm.Eloquent.Table("game_card_goods").Where("serial_number", serialNumber).Find(&gameCardGoods).Error if err != nil { logger.Errorf("err:%#v", logger.Field("err", err)) return err } if order.StoreId != gameCardGoods.StoreId { logger.Error("order store id not game card goods store id") return errors.New("order store id not game card goods store id") } begin := orm.Eloquent.Begin() var eg errgroup.Group //eg.Go(func() error { // fmt.Println("GameCardSerialNumber", serialNumber) // fmt.Println("GameCardSerialNumber 更新订单信息:") // // TODO // err := orm.Eloquent.Table("order").Where("game_card_serial_number", serialNumber).Where("card_status in (?)", []int{OrderCardStatusReturning, OrderCardStatusPlaying}). // Updates(map[string]interface{}{ // "card_status": OrderCardStatusCompleted, // "revert_store_id": m.RevertStoreId, // "revert_time": time.Now(), // }).Error // if err != nil { // logger.Errorf("err:",logger.Field("err",err)) // return err // } // return nil //}) eg.Go(func() error { //err := orm.Eloquent.Table("game_card_goods").Where("serial_number", m.GameCardSerialNumber). // Update("status", GameCardGoodsStatusStock,).Error goodsStatus := GameCardGoodsStatusStock if gameCardGoods.Status == 7 { goodsStatus = GameCardGoodsStatusUnusual } err := orm.Eloquent.Table("game_card_goods").Where("serial_number", serialNumber). Updates(map[string]interface{}{ "status": goodsStatus, "store_id": m.RevertStoreId, "stock_time": time.Now(), }).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } return nil }) eg.Go(func() error { if gameCardGoods.StoreId != m.RevertStoreId { sqlStore := fmt.Sprintf( "UPDATE game_card_goods_stock SET user_hold_stock= user_hold_stock-1,order_count=order_count+1,total_stock=total_stock-1 WHERE store_id=%d AND game_card_id=%d;", order.StoreId, gameCardGoods.GameCardId) fmt.Println("sqlStore:", sqlStore) err = orm.Eloquent.Exec(sqlStore).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } var count int64 err := orm.Eloquent.Table("game_card_goods_stock").Where("store_id", m.RevertStoreId). Where("game_card_id", gameCardGoods.GameCardId).Count(&count).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } if count == 0 && (gameCardGoods.Status != 7 || gameCardGoods.FunctionState != 1) { goodsStock := &GameCardGoodsStock{ StoreId: m.RevertStoreId, GameCardId: gameCardGoods.GameCardId, StoreStock: 0, RentStock: 1, UserHoldStock: 0, OrderCount: 0, TotalStock: 1, } err := orm.Eloquent.Create(goodsStock).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } return nil } else { if gameCardGoods.Status != 7 || gameCardGoods.FunctionState != 1 { sql := fmt.Sprintf( "UPDATE game_card_goods_stock SET rent_stock= rent_stock+1,total_stock=total_stock+1 WHERE store_id=%d AND game_card_id=%d;", m.RevertStoreId, gameCardGoods.GameCardId) fmt.Println("sql:", sql) err = orm.Eloquent.Exec(sql).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } } } } else { //sqlStore := fmt.Sprintf("UPDATE game_card_goods_stock SET user_hold_stock= user_hold_stock-1,order_count=order_count+1,order_count=order_count+1 WHERE store_id=%d AND game_card_id=%d;", order.StoreId, gameCardGoods.GameCardId) sqlStore := fmt.Sprintf( "UPDATE game_card_goods_stock SET user_hold_stock= user_hold_stock-1,order_count=order_count+1 WHERE store_id=%d AND game_card_id=%d;", order.StoreId, gameCardGoods.GameCardId) fmt.Println("sqlStore:", sqlStore) err = orm.Eloquent.Exec(sqlStore).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } if gameCardGoods.Status != 7 || gameCardGoods.FunctionState != 1 { //sql := fmt.Sprintf("UPDATE game_card_goods_stock SET rent_stock= rent_stock+1,user_hold_stock= user_hold_stock-1 WHERE store_id=%d AND game_card_id=%d;", m.RevertStoreId, gameCardGoods.GameCardId) sql := fmt.Sprintf( "UPDATE game_card_goods_stock SET rent_stock= rent_stock+1 WHERE store_id=%d AND game_card_id=%d;", m.RevertStoreId, gameCardGoods.GameCardId) fmt.Println("sql:", sql) err = orm.Eloquent.Exec(sql).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } } } return nil }) eg.Go(func() error { if order.GameCardId != 0 { sql := fmt.Sprintf("UPDATE game_card SET order_count = order_count+1 WHERE id = %d", order.GameCardId) err := orm.Eloquent.Exec(sql).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } } return nil }) eg.Go(func() 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, "revert_store_id": m.RevertStoreId, "revert_time": time.Now(), "revert_shopper_code": m.RevertShopperCode, "revert_express_no": m.RevertExpressNo, }).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } } else { err = begin.Table("order_card").Where("id=?", orderCard.ID).Updates(&map[string]interface{}{ //"store_id": m.StoreId, "card_status": OrderCardStatusCompleted, "revert_store_id": m.RevertStoreId, "revert_time": time.Now(), "revert_shopper_code": m.RevertShopperCode, }).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } } var count int64 err = orm.Eloquent.Table("order_card").Where("order_id=?", orderCard.OrderId). Where("card_status in (?)", []uint32{1, 2, 3}).Count(&count).Error //NewOrderCardQuerySet(DB).OrderIdEq(order.ID).CardStatusIn(1, 2, 3).Total() if err != nil { logger.Error("err:", logger.Field("err", err)) return err } if count == 0 { err := begin.Table("order").Where("id=?", orderCard.OrderId).Updates(&map[string]interface{}{ "card_status": OrderCardStatusCompleted, }).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return err } } return nil }) eg.Go(func() error { sql := fmt.Sprintf( "UPDATE user_rent_card SET have_rent_count = have_rent_count-1,can_rent_count=can_rent_count+1 WHERE uid =%d;", orderCard.Uid) //sql := fmt.Sprintf("UPDATE user_rent_card SET have_rent_count = have_rent_count-1,can_rent_count=can_rent_count+1 WHERE uid =%d;", m.Uid) fmt.Println("sql:", sql) err = begin.Exec(sql).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } return nil }) //orderCard.StoreId err = eg.Wait() if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } err = begin.Commit().Error if err != nil { begin.Rollback() logger.Error("err:", logger.Field("err", err)) return err } return nil } func (*ExpressCompany) List() ([]ExpressCompany, error) { companys := make([]ExpressCompany, 0) err := orm.Eloquent.Table("express_company").Order("id desc").Find(&companys).Error if err != nil && err != RecordNotFound { logger.Error("err:", logger.Field("err", err)) return companys, err } return companys, nil } func (m *Order) Del() error { err := orm.Eloquent.Table("order").Where("id", m.ID).Delete(m).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } return nil } func (m *Order) Refund() error { var order Order err := orm.Eloquent.Table("order").Where("id", m.ID).Find(&order).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } if order.CardStatus != OrderCardStatusCancel || order.PayStatus != PayStatusPaid { logger.Error("order card status not cancel paid") return errors.New("order card status not cancel paid ") } err = orm.Eloquent.Table("order").Where("id", m.ID).Update("card_status", OrderCardStatusRefund).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } return nil } func WxPayTransactionOrderClose(outTradeNo string) error { var ( mchID string = "1609877389" // 商户号 mchCertificateSerialNumber string = "7540301D8FD52CCF7D6267DCF7CD2BC0AB467EFF" // 商户证书序列号 mchAPIv3Key string = "DeovoMingHuiRengTianTang45675123" // 商户APIv3密钥 ) // 微信商户 // 商户ID:1609877389 // 操作密码:456755 // 密钥API:DeovoMingHuiRengTianTang45675456 // 密钥APIv3: DeovoMingHuiRengTianTang45675123 // 证书序列号:7540301D8FD52CCF7D6267DCF7CD2BC0AB467EFF // 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名 //privatePath := "/www/wwwroot/dev.admin.deovo.com/admin_server/go-admin/config/merchant/apiclient_key.pem" // TODO 测试 privatePath := "/www/wwwroot/admin.deovo.com/admin_server/go-admin/config/merchant/apiclient_key.pem" // TODO 正式 mchPrivateKey, err := wechatpayutils.LoadPrivateKeyWithPath(privatePath) if err != nil { //log.Fatal("load merchant private key error") logger.Errorf("err:", logger.Field("err", err)) } ctx := context.Background() // 使用商户私钥等初始化 client,并使它具有自动定时获取微信支付平台证书的能力 opts := []core.ClientOption{ option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key), } client, err := core.NewClient(ctx, opts...) if err != nil { //log.Fatalf("new wechat pay client err:%s",logger.Field("err",err)) logger.Errorf("err:", logger.Field("err", err)) } // 发送请求,以下载微信支付平台证书为例 // https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay5_1.shtml svc := certificates.CertificatesApiService{Client: client} resp, result, err := svc.DownloadCertificates(context.Background()) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return err } //log.Printf("status=%d resp=%s", result.Response.StatusCode, resp) logger.Info("WxPayTransactionOrderClose", logger.Field("status", result.Response.StatusCode), logger.Field("resp", resp)) svcClient := jsapi.JsapiApiService{Client: client} apiResult, err := svcClient.CloseOrder(ctx, jsapi.CloseOrderRequest{ OutTradeNo: &outTradeNo, Mchid: &mchID, }) if err != nil { fmt.Println("err:", logger.Field("err", err)) logger.Error(err.Error()) return err } fmt.Println("StatusCode:", (*apiResult).Response.StatusCode) //bodyCloseOrder,_ := ioutil.ReadAll((*apiResult.Response.Body)) fmt.Println("apiResult:", (*apiResult).Response.StatusCode) return nil } func IsUserHaveUnreturnedOrders(uid uint32) (bool, error) { fmt.Println("uid", uid) sql := fmt.Sprintf("SELECT COUNT(*) AS count FROM order_card WHERE uid = %d AND pay_status=2 AND card_status IN (1,2,3) ;", uid) //sql := fmt.Sprintf("SELECT COUNT(*) AS count FROM order_card WHERE uid = %d AND pay_status IN (1,2) AND card_status IN (1,2,3) ;", uid) //count, err := NewOrderQuerySet(DB).UidEq(uint64(uid)).PayStatusEq(PayStatusPaid).CardStatusIn(1, 2, 3).Total() //if err != nil { // logger.Error("err:",logger.Field("err",err)) // return false, err //} unreturned := &struct { Count int `json:"count"` }{} orm.Eloquent.Raw(sql).Scan(unreturned) fmt.Println("订单数量count:", unreturned.Count) return unreturned.Count != 0, nil } func (m *Order) GetOrderCardMap() (map[string]OrderCard, error) { cardMap := make(map[string]OrderCard, 0) var orderCards []OrderCard err := orm.Eloquent.Table("order_card"). Where("order_id=?", m.ID). //Where("uid=?", m.Uid). Find(&orderCards).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return cardMap, err } for i, _ := range orderCards { cardMap[orderCards[i].SerialNumber] = orderCards[i] } return cardMap, nil } func (m *Order) GetOrderCardGameCardIdList() ([]OrderCard, error) { var orderCards []OrderCard err := orm.Eloquent.Table("order_card"). Where("order_id=?", m.ID). Where("card_status=?", OrderCardStatusUnPick). //Where("serial_number=''"). Find(&orderCards).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return orderCards, err } return orderCards, nil } //func GetOrderCardSerialNumberUnset(list []OrderCard, gameCardId uint32) *OrderCard { // for i, _ := range list { // if list[i].GameCardId == gameCardId && list[i].SerialNumber == "" { // return &list[i] // } // } // return nil //} func GetOrderCardMapSerialNumberUnset(list map[uint32]OrderCard, gameCardId uint32) *OrderCard { for _, v := range list { if v.GameCardId == gameCardId && v.SerialNumber == "" { return &v } } return nil } func OrderCardListSetGameInfo(list []OrderCard) []OrderCard { ids := make([]uint32, 0, len(list)) revertStoreIds := make([]uint32, 0, len(list)) for i, _ := range list { ids = append(ids, list[i].GameCardId) revertStoreIds = append(revertStoreIds, uint32(list[i].RevertStoreId)) } if len(ids) == 0 { return list } fmt.Println("ids:", ids) cardMap, err := GameCardMap(ids) if err != nil { logger.Error("err:", logger.Field("err", err)) return list } storeMap, err := RevertStoreMap(revertStoreIds) if err != nil { logger.Error("err:", logger.Field("err", err)) return list } //fmt.Println("cardMap:", cardMap) //fmt.Println("cardMap:", storeMap) for i, _ := range list { gameCard, ok1 := cardMap[list[i].GameCardId] store, ok2 := storeMap[uint32(list[i].RevertStoreId)] if ok1 { list[i].GameName = gameCard.Name list[i].GameCoverImg = gameCard.CoverImg list[i].GamePrice = gameCard.Price if ok2 { list[i].RevertStore = &store } } } return list } func GameCardMap(ids []uint32) (map[uint32]GameCard, error) { cardMap := make(map[uint32]GameCard, 0) if len(ids) == 0 { return cardMap, nil } var cards []GameCard err := orm.Eloquent.Table("game_card").Where("id in (?)", ids).Find(&cards).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return cardMap, err } if len(cards) == 0 { return cardMap, nil } for i, _ := range cards { cardMap[cards[i].ID] = cards[i] } return cardMap, nil } func RevertStoreMap(ids []uint32) (map[uint32]Store, error) { storeMap := make(map[uint32]Store, 0) if len(ids) == 0 { return storeMap, nil } var stores []Store err := orm.Eloquent.Table("store").Where("id in (?)", ids).Find(&stores).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return storeMap, err } if len(stores) == 0 { return storeMap, nil } for i, _ := range stores { storeMap[stores[i].ID] = stores[i] } return storeMap, nil } func (m *ExpressNoInfo) SetStore() { err := orm.Eloquent.Table("store").Where("id=?", m.StoreId).Find(m.Store).Error if err != nil { logger.Error("err:%s", logger.Field("err", err)) return } } // FundRecordListReq 财务统计入参 type FundRecordListReq struct { Uid uint64 `json:"uid" ` FundType string `json:"fund_type"` TransactionId string `json:"transaction_id"` // 支付单号 OutTradeNo string `json:"out_trade_no"` RefundId string `json:"refund_id"` PaymentNo string `json:"payment_no"` StartTime time.Time `json:"start_time"` // 开始时间 EndTime time.Time `json:"end_time"` // 结束时间 Page int `json:"pageIndex"` PageSize int `json:"pageSize"` IsExport uint32 `json:"is_export"` // 1-导出 } type FundRecordListResp struct { List []FundRecord `json:"list"` Total int64 `json:"total"` // 总条数 PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 每页展示条数 ExportUrl string `json:"export_url"` } func (m *FundRecordListReq) List() ([]FundRecord, int64, string, error) { var fundRecords []FundRecord qs := orm.Eloquent.Table("fund_record") // 默认剔除"尊享会员费",只有传参有才展示 if m.FundType != "" { qs = qs.Where("fund_type=?", m.FundType) } else { qs = qs.Where("fund_type != ?", "privilege_member_fee") } if m.TransactionId != "" { qs = qs.Where("transaction_id=?", m.TransactionId) } if m.OutTradeNo != "" { qs = qs.Where("out_trade_no=?", m.OutTradeNo) } if m.RefundId != "" { qs = qs.Where("refund_id=?", m.RefundId) } if m.PaymentNo != "" { qs = qs.Where("payment_no=?", m.PaymentNo) } if m.Uid != 0 { qs = qs.Where("uid=?", m.Uid) } 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) } var count int64 err := qs.Count(&count).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return fundRecords, 0, "", err } if m.PageSize == 0 { m.PageSize = 10 } page := m.Page pageSize := m.PageSize page -= 1 if page < 0 { page = 0 } if m.IsExport == 1 { // 导出excel err = qs.Order("created_at DESC").Find(&fundRecords).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return fundRecords, 0, "", err } exportUrl, err := fundRecordListExport(fundRecords) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return fundRecords, 0, "", err } return nil, 0, exportUrl, nil } else { err = qs.Order("created_at DESC").Offset(page * pageSize).Limit(pageSize).Find(&fundRecords).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return fundRecords, 0, "", err } } return fundRecords, count, "", nil } // TranslateFundType 将fund_type转换为对应的字符 func TranslateFundType(fundType string) string { fundTypeMap := map[string]string{ "member_fee": "会员费", "buy_goods_refund": "商品退货", "buy_goods": "商品购买", "buy_goods_cancel": "商品取消", "recycle_card": "回收卡带", "postage_package_fee": "购买运费包", "member_deposit": "押金", "upgrade_member": "升级会员", "member_expire_delay": "滞纳金", "express_fee": "邮费", "deposit_refund": "退押金", "express_fee_refund": "退邮费", "downgrade_renewal": "降级续费", } if val, ok := fundTypeMap[fundType]; ok { return val } return "未知类型" } // ConvertAmount 将Amount转换为格式化字符串 func ConvertAmount(amount int64) string { // 转换为以分为单位的小数,保留两位小数 convertedAmount := float64(amount) / 100.0 sign := "+" if convertedAmount < 0 { sign = "-" convertedAmount = -convertedAmount } return sign + strconv.FormatFloat(convertedAmount, 'f', 2, 64) } // fundRecordListExport 导出财务统计数据 func fundRecordListExport(list []FundRecord) (string, error) { file := excelize.NewFile() fSheet := "Sheet1" url := config.ExportConfig.Url fileName := time.Now().Format(TimeFormat) + "财务统计" + ".xlsx" fmt.Println("url fileName:", url+fileName) title := []interface{}{"用户ID", "类型", "金额", "商户单号", "交易单号", "退款单号", "付款单号", "创建时间", "备注"} 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++ { formattedTime := list[rowId].CreatedAt.Format(QueryTimeFormat) row = []interface{}{ list[rowId].Uid, TranslateFundType(list[rowId].FundType), ConvertAmount(list[rowId].Amount), list[rowId].OutTradeNo, list[rowId].TransactionId, list[rowId].RefundId, list[rowId].PaymentNo, formattedTime, list[rowId].Remark, } 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", 10) file.SetColWidth("Sheet1", "B", "B", 13) file.SetColWidth("Sheet1", "C", "C", 10) file.SetColWidth("Sheet1", "D", "D", 16) file.SetColWidth("Sheet1", "E", "E", 30) file.SetColWidth("Sheet1", "F", "F", 30) file.SetColWidth("Sheet1", "G", "G", 30) file.SetColWidth("Sheet1", "H", "H", 25) file.SetColWidth("Sheet1", "I", "I", 13) var endRow string endRow = fmt.Sprintf("I"+"%d", nExcelStartRow+1) // 应用样式到整个表格 _ = file.SetCellStyle("Sheet1", "A1", endRow, style) 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 } type CooperativeOrderReq struct { CooperativeBusinessId uint32 `json:"cooperative_business_id"` Uid uint64 `json:"uid" ` OrderId uint64 `json:"order_id"` GameCardId uint64 `json:"game_card_id" ` StoreId uint64 `json:"store_id" ` // 门店id// 游戏id CardStatus uint8 `json:"card_status"` // 1-待取货中 2-游玩中 3-归还中 4-已完成 PayStatus uint8 `json:"pay_status"` DeliveryType uint8 `json:"delivery_type"` SerialNumber string `json:"serial_number" ` // 编号 PickupCode string `json:"pickup_code"` // 取货码 StartTime time.Time `json:"start_time"` // 开始时间 EndTime time.Time `json:"end_time"` // 结束时间 Page int `json:"pageIndex"` PageSize int `json:"pageSize"` } func (m *CooperativeOrderReq) List() ([]Order, int64, error) { var orderCards []OrderCard orders := make([]Order, 0) if m.PageSize == 0 { m.PageSize = 10 } qs := orm.Eloquent.Table("order").Where("pay_status", 2). Where("cooperative_business_id=?", m.CooperativeBusinessId) isDeliver := true if m.SerialNumber != "" { isDeliver = false err := orm.Eloquent.Table("order_card").Where("serial_number=?", m.SerialNumber). Order("id DESC").Order("card_status ASC").Find(&orderCards).Error //Where("card_status in (?)", []uint32{2, 3}).Order("id DESC").Order("card_status DESC").Limit(30).Find(&orderCards).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return orders, 0, err } orderIds := make([]uint32, 0) for i, _ := range orderCards { orderIds = append(orderIds, orderCards[i].OrderId) } qs = qs.Where("id in (?)", orderIds) } if m.PickupCode != "" { isDeliver = false qs = qs.Where("pickup_code", m.PickupCode) } if m.PayStatus != 0 { qs = qs.Where("pay_status", m.PayStatus) } if m.DeliveryType != 0 { qs = qs.Where("delivery_type", m.DeliveryType) } if m.OrderId != 0 { isDeliver = false qs = qs.Where("id", m.OrderId) } if isDeliver { if m.Uid != 0 { qs = qs.Where("uid", m.Uid) } if m.GameCardId != 0 { qs = qs.Where("game_card_id", m.GameCardId) } if m.CardStatus != 0 { qs = qs.Where("card_status", m.CardStatus) } if m.StoreId != 0 { qs = qs.Where("store_id", 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) } } var count int64 err := qs.Count(&count).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return orders, 0, err } page := m.Page pageSize := m.PageSize page -= 1 if page < 0 { page = 0 } err = qs.Order("created_at DESC").Offset(page * pageSize).Limit(pageSize).Find(&orders).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return orders, 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 orders, 0, err } //var orderCards []OrderCard 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 orders, 0, err } orderCards = OrderCardListSetGameInfo(orderCards) orderCardsMap := make(map[uint32][]OrderCard, 0) for i, _ := range orderCards { orderCardsMap[orderCards[i].OrderId] = append(orderCardsMap[orderCards[i].OrderId], orderCards[i]) } for i, _ := range orders { 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 GetUserExpiredCards(userId []uint32) (map[uint32][]OrderCard, error) { var m = make(map[uint32][]OrderCard) var oc []OrderCard err := orm.Eloquent.Table("order_card"). Preload("GameCard"). Where("uid in (?)", userId). Where("pay_status = ?", HavePaid).Where("card_status in ?", []int{1, 2, 3}). Find(&oc).Error if err != nil { return m, err } for _, card := range oc { l, ok := m[card.Uid] if ok { m[card.Uid] = append(l, card) } else { m[card.Uid] = []OrderCard{card} } } return m, nil }