diff --git a/app/admin/apis/ordermanage/order.go b/app/admin/apis/ordermanage/order.go index 6fece4d..e51474c 100644 --- a/app/admin/apis/ordermanage/order.go +++ b/app/admin/apis/ordermanage/order.go @@ -35,7 +35,7 @@ func OrderList(c *gin.Context) { // //} - list, count, err := req.List() + list, count, _, err := req.List(0) if err != nil { logger.Errorf("err:", logger.Field("err", err)) app.Error(c, http.StatusInternalServerError, err, "查询失败") @@ -264,3 +264,35 @@ func FundRecordList(c *gin.Context) { } app.OK(c, ret, "") } + +// OrderListExport 导出订单列表 +// @Summary 导出订单列表 +// @Tags 订单管理 +// @Produce json +// @Accept json +// @Param request body models.OrderListReq true "导出订单列表模型" +// @Success 200 {object} app.Response "{"code": 200, "data": { "export_url": "" }}" +// @Router /api/v1/order/list_export [post] +func OrderListExport(c *gin.Context) { + req := &models.OrderListReq{} + if c.ShouldBindJSON(req) != nil { + logger.Errorf("para err") + app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误") + return + } + reqJson, _ := json.Marshal(req) + fmt.Println("reqJson:", string(reqJson)) + + _, _, filePath, err := req.List(1) + if err != nil { + logger.Errorf("OrderListExport err:", logger.Field("err", err)) + app.Error(c, http.StatusInternalServerError, err, "导出失败") + return + } + + ret := map[string]interface{}{ + "export_url": filePath, + } + + app.OK(c, ret, "") +} diff --git a/app/admin/models/commodity.go b/app/admin/models/commodity.go index fc04c20..ba3dc88 100644 --- a/app/admin/models/commodity.go +++ b/app/admin/models/commodity.go @@ -9,6 +9,7 @@ import ( "go-admin/tools/config" "golang.org/x/sync/errgroup" "gorm.io/gorm" + "math/rand" "strconv" "strings" "sync" @@ -547,7 +548,18 @@ func (m *StockImporter) ImportStockData(colsMap []map[string]interface{}) error } _, ok2 := erpCommodityMap[list[i].Name] if !ok2 { + if list[i].Name == "" { + //如果商品名称为空,则需要补全 + commodityName, err := getCommodityNameBySerialNum(list[i].SerialNum) + if err != nil { + logger.Errorf("getCommodityNameBySerialNum err:", logger.Field("err", err)) + return err + } + + list[i].Name = commodityName + } erpCommodityNames = append(erpCommodityNames, list[i].Name) + } _, ok3 := erpSupplierNameMap[list[i].SupplierName] if !ok3 { @@ -644,19 +656,30 @@ func (m *StockImporter) ImportStockData(colsMap []map[string]interface{}) error StockTime: nowTime, Count: 1, IMEIType: v2.IMEIType, - IMEI: v2.IMEI, + IMEI: "", Remark: "", } if list[i].StockTime != "" { //导入时间不为空 - parsedTime, _ := time.Parse("2006/1/2", list[i].StockTime) + local, _ := time.LoadLocation("Local") + parsedTime, _ := time.ParseInLocation("2006/1/2", list[i].StockTime, local) + //parsedTime, _ := time.Parse("2006/1/2", list[i].StockTime) stockCommodity.FirstStockTime = parsedTime + stockCommodity.StockTime = parsedTime } - if list[i].SysGenerate != "" { //导入串码不为空,则默认为3手动添加 + if list[i].SysGenerate != "" && v2.IMEIType == 3 { //导入串码不为空,则默认为3手动添加 stockCommodity.IMEIType = 3 stockCommodity.IMEI = list[i].SysGenerate + } else if v2.IMEIType == 2 { // 如果该商品串码类型是:2-串码(系统生成),则系统自动生成 + stockCommodity.IMEIType = 2 + serialCode, err := generateSerialCode(v2.ErpCategoryId) + if err != nil { + return err + } + stockCommodity.IMEI = serialCode } + erpStockCommodity = append(erpStockCommodity, stockCommodity) _, ok4 := m.CensusMap[stockCommodity.StoreId] @@ -675,6 +698,54 @@ func (m *StockImporter) ImportStockData(colsMap []map[string]interface{}) error return nil } +// 获取商品名称 +func getCommodityNameBySerialNum(serialNumber string) (string, error) { + var commodity ErpCommodity + err := orm.Eloquent.Table("erp_commodity").Where("serial_number=?", serialNumber).Find(&commodity).Error + if err != nil { + return "", err + } + + return commodity.Name, nil +} + +// generateSerialCode 生成商品串码 +func generateSerialCode(categoryID uint32) (string, error) { + // 生成年月日6位数 + dateStr := time.Now().Format("060102") + + // 生成四位随机数 + rand.Seed(time.Now().UnixNano()) + randomNumber := rand.Intn(10000) + randomStr := fmt.Sprintf("%04d", randomNumber) + + // 获取商品分类编号前3位 + categoryStr, err := getCategoryCode(categoryID) + if err != nil { + logger.Errorf("getCategoryCode err:", logger.Field("err", err)) + return "", err + } + + // 拼接串码 + serialCode := categoryStr + dateStr + randomStr + + return serialCode, nil +} + +// getCategoryCode 根据商品分类ID查询分类编号前3位 +func getCategoryCode(categoryID uint32) (string, error) { + // 这里模拟查询数据库,实际中你需要连接数据库进行查询 + // 假设这里的数据是从数据库中查询得到的 + categoryInfo, err := GetCategoryById(categoryID) + if err != nil { + logger.Errorf("GetCategoryById err:", logger.Field("err", err)) + return "", err + } + + // 取前3位字符串 + return categoryInfo.Number[:3], nil +} + func (m *StockImporter) processErpStocks(erpStocks []ErpStockCommodity) error { begin := orm.Eloquent.Begin() total := len(erpStocks) @@ -718,7 +789,7 @@ func (m *StockImporter) processErpStocks(erpStocks []ErpStockCommodity) error { } func createStockList(begin *gorm.DB, stockList []ErpStockCommodity) error { - err := begin.Create(&stockList).Error + err := begin.Debug().Create(&stockList).Error if err != nil { begin.Rollback() return err @@ -918,7 +989,7 @@ func ErpCommodityListExport(list []ErpCommodity) (string, error) { fmt.Println(err) } - url := "http://39.108.188.218:8000/img/export/" + url := ExportUrl fileName := time.Now().Format(TimeFormat) + "商品" + ".xlsx" //title := []interface{}{"供应商编号", "供应商名称", "联系人", "手机号", "地址", "开户银行", "银行账号", "付款周期/天"} @@ -962,7 +1033,7 @@ func InventoryDetailListExport(list []ErpStockCommodity) (string, error) { fmt.Println(err) } - url := config.ExportConfig.Url + url := ExportUrl fileName := time.Now().Format(TimeFormat) + "商品" + ".xlsx" fmt.Println("url fileName:", url+fileName) @@ -1037,7 +1108,7 @@ func ErpCategoryListExport(list []ErpCategory) (string, error) { fmt.Println(err) } - url := "http://39.108.188.218:8000/img/export/" + url := ExportUrl fileName := time.Now().Format(TimeFormat) + "分类列表数据" + ".xlsx" //title := []interface{}{"门店", "用户ID", "订单编号", "下单时间", "卡带", "说明", "回收价", "闲麦价", "审核时间", "审核人", "操作", "复核时间", "复核状态"} diff --git a/app/admin/models/file.go b/app/admin/models/file.go index 64b3fd7..65efa4a 100644 --- a/app/admin/models/file.go +++ b/app/admin/models/file.go @@ -372,62 +372,90 @@ func checkStockExcel(sheetCols [][]string) error { } } - for i := 1; i < nLow; i++ { // todo - if !isExistingProduct(sheetCols[0][i]) { - return errors.New("第" + strconv.Itoa(i+1) + "行商品不存在,请新建商品") - } - - // 商品编号必须为纯数字 - if sheetCols[1][i] != "" { - if _, err := strconv.Atoi(sheetCols[1][i]); err != nil { - return errors.New("第" + strconv.Itoa(i+1) + "行商品编号必须为纯数字") + for i := 1; i < nMax; i++ { // todo + if i < len(sheetCols[0]) { + if !isExistingProduct(sheetCols[0][i]) { + return errors.New("第" + strconv.Itoa(i+1) + "行商品不存在,请新建商品") } } - if !isExistingProductCode(sheetCols[1][i]) { - return errors.New("第" + strconv.Itoa(i+1) + "行商品编号不存在") + if i < len(sheetCols[1]) { + // 商品编号必须为纯数字 + if sheetCols[1][i] != "" { + if _, err := strconv.Atoi(sheetCols[1][i]); err != nil { + return errors.New("第" + strconv.Itoa(i+1) + "行商品编号必须为纯数字") + } + } + + if !isExistingProductCode(sheetCols[1][i]) { + return errors.New("第" + strconv.Itoa(i+1) + "行商品编号不存在") + } } // 所属门店不能为空 - if sheetCols[2][i] == "" { - return errors.New("第" + strconv.Itoa(i+1) + "行所属门店不能为空") - } - if !isExistingStore(sheetCols[2][i]) { - return errors.New("第" + strconv.Itoa(i+1) + "行门店不存在,请新建门店") + if i < len(sheetCols[2]) { + if sheetCols[2][i] == "" { + return errors.New("第" + strconv.Itoa(i+1) + "行所属门店不能为空") + } + if !isExistingStore(sheetCols[2][i]) { + return errors.New("第" + strconv.Itoa(i+1) + "行门店不存在,请新建门店") + } } // 商品串码规则校验 当串码行数跟其他一致时正常遍历,如果小于其他行,则最后一行不遍历 todo // 如串码在商品库存表已经存在,则报错提示 - if len(sheetCols[3]) <= nLow && i+1 < nLow { - if err := checkSerialCode(sheetCols[0][i], sheetCols[1][i], sheetCols[3][i], i); err != nil { + //if len(sheetCols[3]) <= nLow && i+1 < nLow { + if i < len(sheetCols[3]) { + productName := "" + if i < len(sheetCols[0]) { + productName = sheetCols[0][i] + } + + productCode := "" + if i < len(sheetCols[1]) { + productCode = sheetCols[1][i] + } + + count := "" + if i < len(sheetCols[8]) { + count = sheetCols[8][i] + } + + if err := checkSerialCode(productName, productCode, sheetCols[3][i], i); err != nil { return err } // 串码类商品数量只能为1 - if sheetCols[3][i] != "" && sheetCols[8][i] != "1" { + if sheetCols[3][i] != "" && count != "1" { return errors.New("第" + strconv.Itoa(i+1) + "行串码类商品数量只能为1") } } // 采购价、员工成本价必须大于0 - if purchasePrice, err := strconv.Atoi(sheetCols[4][i]); err != nil || purchasePrice <= 0 { - return errors.New("第" + strconv.Itoa(i+1) + "行采购价必须是大于0的数字") + if i < len(sheetCols[4]) { + if purchasePrice, err := strconv.Atoi(sheetCols[4][i]); err != nil || purchasePrice <= 0 { + return errors.New("第" + strconv.Itoa(i+1) + "行采购价必须是大于0的数字") + } } - if employeeCost, err := strconv.Atoi(sheetCols[5][i]); err != nil || employeeCost <= 0 { - return errors.New("第" + strconv.Itoa(i+1) + "行员工成本价必须是大于0的数字") + if i < len(sheetCols[5]) { + if employeeCost, err := strconv.Atoi(sheetCols[5][i]); err != nil || employeeCost <= 0 { + return errors.New("第" + strconv.Itoa(i+1) + "行员工成本价必须是大于0的数字") + } } // 供应商不能为空 - if sheetCols[6][i] == "" { - return errors.New("第" + strconv.Itoa(i+1) + "行供应商不能为空") - } - if !isExistingSupplier(sheetCols[6][i]) { - return errors.New("第" + strconv.Itoa(i+1) + "行供应商不存在,请新建供应商") + if i < len(sheetCols[6]) { + if sheetCols[6][i] == "" { + return errors.New("第" + strconv.Itoa(i+1) + "行供应商不能为空") + } + if !isExistingSupplier(sheetCols[6][i]) { + return errors.New("第" + strconv.Itoa(i+1) + "行供应商不存在,请新建供应商") + } } // 入库时间格式校验 //if len(sheetCols[7]) < nLow && i+1 < nLow { - if i+1 <= len(sheetCols[7]) { + if i < len(sheetCols[7]) { if sheetCols[7][i] != "" { parsedTime, err := time.Parse("2006/1/2", sheetCols[7][i]) if err != nil { @@ -435,7 +463,7 @@ func checkStockExcel(sheetCols [][]string) error { } // 格式化时间为指定格式 formattedTime := parsedTime.Format(DateTimeFormat) - sheetCols[7][i] = formattedTime + "00-00-00" + //sheetCols[7][i] = formattedTime + "00-00-00" // 需小于当前时间 nFlag, _ := isInputTimeBeforeOrEqualNow(formattedTime) @@ -447,8 +475,10 @@ func checkStockExcel(sheetCols [][]string) error { } // 数量必须为正整数 - if quantity, err := strconv.Atoi(sheetCols[8][i]); err != nil || quantity < 1 { - return errors.New("第" + strconv.Itoa(i+1) + "行数量必须是大于等于1的整数") + if i < len(sheetCols[8]) { + if quantity, err := strconv.Atoi(sheetCols[8][i]); err != nil || quantity < 1 { + return errors.New("第" + strconv.Itoa(i+1) + "行数量必须是大于等于1的整数") + } } } diff --git a/app/admin/models/order.go b/app/admin/models/order.go index b7628e0..bf09940 100644 --- a/app/admin/models/order.go +++ b/app/admin/models/order.go @@ -10,10 +10,13 @@ import ( "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/config" "golang.org/x/sync/errgroup" + "gorm.io/gorm" "time" ) @@ -185,10 +188,10 @@ 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-已完成 - PayStatus uint8 `json:"pay_status"` - DeliveryType uint8 `json:"delivery_type"` + 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"` // 开始时间 @@ -197,47 +200,157 @@ type OrderListReq struct { PageSize int `json:"pageSize"` } -//type OrderListResp struct { -//} +func (m *OrderListReq) List(exportFlag int) ([]Order, int64, string, error) { + orders := make([]Order, 0) + if m.PageSize == 0 { + m.PageSize = 10 + } -func (m *OrderListReq) List() ([]Order, int64, error) { - //orderInfos := make([]OrderInfo, 0) + var count int64 + var err error + // 如果卡片类型不为空,则优先查询order_card表 + if m.CardStatus != 0 { + orders, count, err = m.queryListFormOrderCard(exportFlag) + } else { + orders, count, err = m.queryListFormOrder(exportFlag) + } + + 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) ([]Order, int64, error) { + var orderCards []OrderCard + orders := make([]Order, 0) + qs := orm.Eloquent.Table("order_card").Where("card_status=?", m.CardStatus) + + 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", 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 + } + + //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 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) ([]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) + var qs *gorm.DB + qs = orm.Eloquent.Table("order").Where("pay_status", 2) isDeliver := true if m.SerialNumber != "" { isDeliver = false - ////qs = qs.Where("game_card_serial_number", m.SerialNumber) - //err := orm.Eloquent.Table("order_card").Where("serial_number=?", m.SerialNumber). - // Order("id DESC").Order("card_status ASC").Limit(30).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 - //} - //order := Order{} - //if len(orderCards) > 0 { - // err := orm.Eloquent.Table("order").Where("id=?", orderCards[0].OrderId).Find(&order).Error - // if err != nil { - // logger.Error("err:",logger.Field("err",err)) - // return orders, 0, err - // } - //} - //orders = append(orders, order) - //orders[0].OrderCards = OrderCardListSetGameInfo(orderCards) - //return orders, 1, nil 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 + return nil, 0, err } orderIds := make([]uint32, 0) for i, _ := range orderCards { @@ -246,6 +359,7 @@ func (m *OrderListReq) List() ([]Order, int64, error) { qs = qs.Where("id in (?)", orderIds) } + if m.PickupCode != "" { isDeliver = false qs = qs.Where("pickup_code", m.PickupCode) @@ -267,9 +381,7 @@ func (m *OrderListReq) List() ([]Order, int64, error) { 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) } @@ -287,7 +399,7 @@ func (m *OrderListReq) List() ([]Order, int64, error) { err := qs.Count(&count).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) - return orders, 0, err + return nil, 0, err } page := m.Page pageSize := m.PageSize @@ -295,10 +407,16 @@ func (m *OrderListReq) List() ([]Order, int64, error) { if page < 0 { page = 0 } - err = qs.Preload("User").Order("created_at DESC").Offset(page * pageSize).Limit(pageSize).Find(&orders).Error + + if exportFlag == 1 { //一次性导出excel + qs = qs.Preload("User").Order("created_at DESC") + } else { + qs = qs.Preload("User").Order("created_at DESC").Offset(page * pageSize).Limit(pageSize) + } + err = qs.Find(&orders).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) - return orders, 0, err + return nil, 0, err } ids := make([]uint32, 0, len(orders)) @@ -307,14 +425,13 @@ func (m *OrderListReq) List() ([]Order, int64, error) { } if len(ids) == 0 { logger.Error("gameIds is nil") - return orders, 0, err + return nil, 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 + return nil, 0, err } orderCards = OrderCardListSetGameInfo(orderCards) orderCardsMap := make(map[uint32][]OrderCard, 0) @@ -322,37 +439,125 @@ func (m *OrderListReq) List() ([]Order, int64, error) { 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 - } + //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 } } - //fmt.Println("orders:", orders) - //fmt.Println("gameIds:", gameIds) - //games := make([]GameCard, 0) - //err = orm.Eloquent.Table("game_card").Where("id IN (?)", gameIds).Find(&games).Error - //if err != nil { - // logger.Errorf("err:",logger.Field("err",err)) - // return orders, 0, err - //} - //fmt.Println("games:", games) - //gameMap := make(map[uint32]GameCard, 0) - //for i, _ := range games { - // gameMap[games[i].ID] = games[i] - //} - //for i, _ := range orders { - // game, ok := gameMap[uint32(orders[i].GameCardId)] - // if ok { - // orders = append(orders, orders[i].ToInfo(&game)) - // } - //} 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 := ExportUrl + fileName := time.Now().Format(TimeFormat) + "订单" + ".xlsx" + fmt.Println("url fileName:", url+fileName) + + title := []interface{}{"租赁ID", "用户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, + list[rowId].OrderCards[i].GameCardId, + list[rowId].OrderCards[i].GameName, + cardState} + + 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 diff --git a/app/admin/router/ordermanage.go b/app/admin/router/ordermanage.go index 77ea789..8830dd9 100644 --- a/app/admin/router/ordermanage.go +++ b/app/admin/router/ordermanage.go @@ -11,7 +11,8 @@ import ( func registerOrderManageRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { order := v1.Group("/order") { - order.POST("/list", ordermanage.OrderList) // 订单列表 + order.POST("/list", ordermanage.OrderList) // 订单列表 + order.POST("/list_export", ordermanage.OrderListExport) // 订单列表导出 } } diff --git a/config/settings.yml b/config/settings.yml index 3bf5c48..a70476c 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -41,7 +41,7 @@ settings: driver: mysql # 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms source: mh_dev:d9qy46ONI0ZTF9eH@tcp(39.108.188.218:3306)/mh_dev?charset=utf8&parseTime=True&loc=Local&timeout=1000ms -# source: mh_pro:fLeytnBFCRB553ab@tcp(39.108.188.218:3306)/mh_pro?charset=utf8&parseTime=True&loc=Local&timeout=1000ms +# source: mh_pro:c5JBW3X6EEVQluYM@tcp(39.108.188.218:3306)/mh_pro?charset=utf8&parseTime=True&loc=Local&timeout=1000ms gen: # 代码生成读取的数据库名称 @@ -50,7 +50,7 @@ settings: frontpath: ../go-admin-ui/src export: - path: D:\\ + path: /Users/max/Documents/ url: http://39.108.188.218:8000/img/export/ # path: /www/server/images/export/ -# url: http://39.108.188.218:8000/img/export/ +# url: https://dev.admin.deovo.com/load/export/ diff --git a/docs/docs.go b/docs/docs.go index 9cd1ea1..4944d7b 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -2278,6 +2278,39 @@ const docTemplate = `{ } } }, + "/api/v1/order/list_export": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "订单管理" + ], + "summary": "导出订单列表", + "parameters": [ + { + "description": "导出订单列表模型", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.OrderListReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": { \"export_url\": \"\" }}", + "schema": { + "$ref": "#/definitions/app.Response" + } + } + } + } + }, "/api/v1/post": { "get": { "security": [ @@ -5326,6 +5359,58 @@ const docTemplate = `{ } } }, + "models.OrderListReq": { + "type": "object", + "properties": { + "card_status": { + "description": "1-待取货中 2-游玩中 3-归还中 4-已完成 5-已取消", + "type": "integer" + }, + "delivery_type": { + "description": "取货类型 1-门店自取 2-快递", + "type": "integer" + }, + "end_time": { + "description": "结束时间", + "type": "string" + }, + "game_card_id": { + "type": "integer" + }, + "order_id": { + "type": "integer" + }, + "pageIndex": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "pay_status": { + "description": "支付状态 1-未支付 2-已支付", + "type": "integer" + }, + "pickup_code": { + "description": "取货码", + "type": "string" + }, + "serial_number": { + "description": "编号", + "type": "string" + }, + "start_time": { + "description": "开始时间", + "type": "string" + }, + "store_id": { + "description": "门店id// 游戏id", + "type": "integer" + }, + "uid": { + "type": "integer" + } + } + }, "models.Post": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index 02b74c8..48b4adf 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -2267,6 +2267,39 @@ } } }, + "/api/v1/order/list_export": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "订单管理" + ], + "summary": "导出订单列表", + "parameters": [ + { + "description": "导出订单列表模型", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.OrderListReq" + } + } + ], + "responses": { + "200": { + "description": "{\"code\": 200, \"data\": { \"export_url\": \"\" }}", + "schema": { + "$ref": "#/definitions/app.Response" + } + } + } + } + }, "/api/v1/post": { "get": { "security": [ @@ -5315,6 +5348,58 @@ } } }, + "models.OrderListReq": { + "type": "object", + "properties": { + "card_status": { + "description": "1-待取货中 2-游玩中 3-归还中 4-已完成 5-已取消", + "type": "integer" + }, + "delivery_type": { + "description": "取货类型 1-门店自取 2-快递", + "type": "integer" + }, + "end_time": { + "description": "结束时间", + "type": "string" + }, + "game_card_id": { + "type": "integer" + }, + "order_id": { + "type": "integer" + }, + "pageIndex": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "pay_status": { + "description": "支付状态 1-未支付 2-已支付", + "type": "integer" + }, + "pickup_code": { + "description": "取货码", + "type": "string" + }, + "serial_number": { + "description": "编号", + "type": "string" + }, + "start_time": { + "description": "开始时间", + "type": "string" + }, + "store_id": { + "description": "门店id// 游戏id", + "type": "integer" + }, + "uid": { + "type": "integer" + } + } + }, "models.Post": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 9be2ca5..dcee793 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1325,6 +1325,43 @@ definitions: visible: type: string type: object + models.OrderListReq: + properties: + card_status: + description: 1-待取货中 2-游玩中 3-归还中 4-已完成 5-已取消 + type: integer + delivery_type: + description: 取货类型 1-门店自取 2-快递 + type: integer + end_time: + description: 结束时间 + type: string + game_card_id: + type: integer + order_id: + type: integer + pageIndex: + type: integer + pageSize: + type: integer + pay_status: + description: 支付状态 1-未支付 2-已支付 + type: integer + pickup_code: + description: 取货码 + type: string + serial_number: + description: 编号 + type: string + start_time: + description: 开始时间 + type: string + store_id: + description: 门店id// 游戏id + type: integer + uid: + type: integer + type: object models.Post: properties: createBy: @@ -3528,6 +3565,27 @@ paths: summary: 操作日志列表(update) tags: - system/日志 + /api/v1/order/list_export: + post: + consumes: + - application/json + parameters: + - description: 导出订单列表模型 + in: body + name: request + required: true + schema: + $ref: '#/definitions/models.OrderListReq' + produces: + - application/json + responses: + "200": + description: '{"code": 200, "data": { "export_url": "" }}' + schema: + $ref: '#/definitions/app.Response' + summary: 导出订单列表 + tags: + - 订单管理 /api/v1/post: get: description: 获取JSON