1、历史汇总查询新增24小时退订数和退订率,对应excel调整;
2、订单表新增状态4-24小时退订查询;
This commit is contained in:
parent
2863174547
commit
2eb326eb0a
|
@ -1,16 +1,13 @@
|
||||||
package migumanage
|
package migumanage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-admin-team/go-admin-core/logger"
|
"github.com/go-admin-team/go-admin-core/logger"
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
"github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
||||||
"go-admin/app/admin/models"
|
"go-admin/app/admin/models"
|
||||||
"go-admin/tools"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -336,6 +333,10 @@ func (e MiGuDeployService) OrderList(c *gin.Context) {
|
||||||
if req.State != 0 {
|
if req.State != 0 {
|
||||||
if req.State == 3 { // 1小时内退订
|
if req.State == 3 { // 1小时内退订
|
||||||
qs = qs.Where("is_one_hour_cancel = ?", 1)
|
qs = qs.Where("is_one_hour_cancel = ?", 1)
|
||||||
|
} else if req.State == 4 {
|
||||||
|
// 查询退订状态为2,且退订时间与订购时间在24小时内
|
||||||
|
qs = qs.Where("state = ?", 2)
|
||||||
|
qs = qs.Where("TIMESTAMPDIFF(HOUR, subscribe_time, unsubscribe_time) <= 24")
|
||||||
} else {
|
} else {
|
||||||
state := 1 // 订阅
|
state := 1 // 订阅
|
||||||
if req.State == 1 {
|
if req.State == 1 {
|
||||||
|
@ -508,10 +509,12 @@ func (e MiGuDeployService) HistoricalSummaryListOld(c *gin.Context) {
|
||||||
IFNULL(submission_count.submission_count, 0) AS submission_count,
|
IFNULL(submission_count.submission_count, 0) AS submission_count,
|
||||||
COUNT(CASE WHEN mg_order.is_one_hour_cancel = 1 THEN 1 END) AS new_user_unsub_within_hour,
|
COUNT(CASE WHEN mg_order.is_one_hour_cancel = 1 THEN 1 END) AS new_user_unsub_within_hour,
|
||||||
COUNT(CASE WHEN mg_order.state = 2 AND DATE(mg_order.unsubscribe_time) = DATE(mg_order.subscribe_time) THEN 1 END) AS new_user_unsub_on_day,
|
COUNT(CASE WHEN mg_order.state = 2 AND DATE(mg_order.unsubscribe_time) = DATE(mg_order.subscribe_time) THEN 1 END) AS new_user_unsub_on_day,
|
||||||
|
COUNT(CASE WHEN mg_order.state = 2 AND TIMESTAMPDIFF(HOUR, mg_order.subscribe_time, mg_order.unsubscribe_time) <= 24 THEN 1 END) AS new_user_unsub_within_24h,
|
||||||
COUNT(*) AS new_user_count,
|
COUNT(*) AS new_user_count,
|
||||||
SUM(CASE WHEN mg_order.state = 2 THEN 1 ELSE 0 END) AS total_new_user_unsub,
|
SUM(CASE WHEN mg_order.state = 2 THEN 1 ELSE 0 END) AS total_new_user_unsub,
|
||||||
CONCAT(ROUND(COUNT(CASE WHEN mg_order.is_one_hour_cancel = 1 THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 2), '%') AS new_user_unsub_within_hour_rate,
|
CONCAT(ROUND(COUNT(CASE WHEN mg_order.is_one_hour_cancel = 1 THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 2), '%') AS new_user_unsub_within_hour_rate,
|
||||||
CONCAT(ROUND(COUNT(CASE WHEN mg_order.state = 2 AND DATE(mg_order.unsubscribe_time) = DATE(mg_order.subscribe_time) THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 2), '%') AS new_user_unsub_on_day_rate,
|
CONCAT(ROUND(COUNT(CASE WHEN mg_order.state = 2 AND DATE(mg_order.unsubscribe_time) = DATE(mg_order.subscribe_time) THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 2), '%') AS new_user_unsub_on_day_rate,
|
||||||
|
CONCAT(ROUND(COUNT(CASE WHEN mg_order.state = 2 AND TIMESTAMPDIFF(HOUR, mg_order.subscribe_time, mg_order.unsubscribe_time) <= 24 THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 2), '%') AS new_user_unsub_within_24h_rate,
|
||||||
CONCAT(ROUND(SUM(CASE WHEN mg_order.state = 2 THEN 1 ELSE 0 END) * 100.0 / NULLIF(COUNT(*), 0), 2), '%') AS total_new_user_unsub_rate,
|
CONCAT(ROUND(SUM(CASE WHEN mg_order.state = 2 THEN 1 ELSE 0 END) * 100.0 / NULLIF(COUNT(*), 0), 2), '%') AS total_new_user_unsub_rate,
|
||||||
IFNULL(
|
IFNULL(
|
||||||
CONCAT(
|
CONCAT(
|
||||||
|
@ -2667,215 +2670,215 @@ func (e MiGuDeployService) AddProduct(c *gin.Context) {
|
||||||
// e.OK("", "删除成功")
|
// e.OK("", "删除成功")
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// ImportExcelToMgOrderHandler 处理Excel文件导入请求
|
//// ImportExcelToMgOrderHandler 处理Excel文件导入请求
|
||||||
// @Summary 导入订单Excel文件
|
//// @Summary 导入订单Excel文件
|
||||||
// @Tags 2024-咪咕-管理后台
|
//// @Tags 2024-咪咕-管理后台
|
||||||
// @Accept multipart/form-data
|
//// @Accept multipart/form-data
|
||||||
// @Produce json
|
//// @Produce json
|
||||||
// @Param file formData file true "Excel文件"
|
//// @Param file formData file true "Excel文件"
|
||||||
// @Success 200 {object} map[string]string{"message": "导入成功"}
|
//// @Success 200 {object} map[string]string{"message": "导入成功"}
|
||||||
// @Router /api/v1/admin/order/import [post]
|
//// @Router /api/v1/admin/order/import [post]
|
||||||
func (e MiGuDeployService) ImportExcelToMgOrderHandler(c *gin.Context) {
|
//func (e MiGuDeployService) ImportExcelToMgOrderHandler(c *gin.Context) {
|
||||||
err := e.MakeContext(c).MakeOrm().Errors
|
// err := e.MakeContext(c).MakeOrm().Errors
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
e.Logger.Error(err)
|
// e.Logger.Error(err)
|
||||||
response.Error(c, http.StatusInternalServerError, err, "创建上下文失败")
|
// response.Error(c, http.StatusInternalServerError, err, "创建上下文失败")
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// 从请求中获取文件
|
// // 从请求中获取文件
|
||||||
file, err := c.FormFile("file")
|
// file, err := c.FormFile("file")
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "无法读取文件"})
|
// c.JSON(http.StatusBadRequest, gin.H{"error": "无法读取文件"})
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// 打开上传的文件
|
// // 打开上传的文件
|
||||||
fileStream, err := file.Open()
|
// fileStream, err := file.Open()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "无法打开文件"})
|
// c.JSON(http.StatusInternalServerError, gin.H{"error": "无法打开文件"})
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
defer fileStream.Close()
|
// defer fileStream.Close()
|
||||||
|
//
|
||||||
// 创建 CSV 阅读器
|
// // 创建 CSV 阅读器
|
||||||
reader := csv.NewReader(fileStream)
|
// reader := csv.NewReader(fileStream)
|
||||||
reader.LazyQuotes = true
|
// reader.LazyQuotes = true
|
||||||
|
//
|
||||||
// 跳过 CSV 文件的标题行
|
// // 跳过 CSV 文件的标题行
|
||||||
if _, err := reader.Read(); err != nil {
|
// if _, err := reader.Read(); err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "无法读取CSV标题行"})
|
// c.JSON(http.StatusInternalServerError, gin.H{"error": "无法读取CSV标题行"})
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
//nRow := 0
|
// //nRow := 0
|
||||||
// 逐行读取 CSV 并插入数据库
|
// // 逐行读取 CSV 并插入数据库
|
||||||
for {
|
// for {
|
||||||
//nRow++
|
// //nRow++
|
||||||
row, err := reader.Read()
|
// row, err := reader.Read()
|
||||||
if err == io.EOF {
|
// if err == io.EOF {
|
||||||
break
|
// break
|
||||||
}
|
// }
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "读取CSV文件失败"})
|
// c.JSON(http.StatusInternalServerError, gin.H{"error": "读取CSV文件失败"})
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// 检查数据是否齐全
|
// // 检查数据是否齐全
|
||||||
if len(row) < 3 {
|
// if len(row) < 3 {
|
||||||
continue // 跳过数据不全的行
|
// continue // 跳过数据不全的行
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// 解析订阅时间
|
// // 解析订阅时间
|
||||||
subscribeTime, err := time.Parse("2006-01-02 15:04:05", row[1])
|
// subscribeTime, err := time.Parse("2006-01-02 15:04:05", row[1])
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
fmt.Printf("解析时间错误: %v\n", err)
|
// fmt.Printf("解析时间错误: %v\n", err)
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//const cutoffTimeStr = "2024-10-18 18:58:00"
|
|
||||||
//cutoffTime, _ := time.Parse("2006-01-02 15:04:05", cutoffTimeStr)
|
|
||||||
//// 判断是否超过截止时间
|
|
||||||
//if subscribeTime.After(cutoffTime) {
|
|
||||||
// fmt.Printf("跳过超过截止时间的记录: %v\n", subscribeTime)
|
|
||||||
// continue
|
// continue
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
// 将时间转换为 UTC+08:00
|
// //const cutoffTimeStr = "2024-10-18 18:58:00"
|
||||||
// 将时间往前推8小时
|
// //cutoffTime, _ := time.Parse("2006-01-02 15:04:05", cutoffTimeStr)
|
||||||
localTime := subscribeTime.Add(-8 * time.Hour)
|
// //// 判断是否超过截止时间
|
||||||
|
// //if subscribeTime.After(cutoffTime) {
|
||||||
tempOrderNo := models.GetExcelOrderSerial(e.Orm, subscribeTime)
|
// // fmt.Printf("跳过超过截止时间的记录: %v\n", subscribeTime)
|
||||||
|
// // continue
|
||||||
// 创建MgOrder对象
|
// //}
|
||||||
order := models.MgOrderCopy{
|
//
|
||||||
ProductID: 2,
|
// // 将时间转换为 UTC+08:00
|
||||||
ChannelCode: "00211NV",
|
// // 将时间往前推8小时
|
||||||
OrderSerial: tempOrderNo,
|
|
||||||
SubscribeTime: &localTime,
|
|
||||||
PhoneNumber: row[0],
|
|
||||||
ChannelTradeNo: tempOrderNo,
|
|
||||||
ExternalOrderID: tempOrderNo,
|
|
||||||
State: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
if row[2] == "未包月" { // 1小时内退订
|
|
||||||
order.IsOneHourCancel = 1
|
|
||||||
order.State = 2
|
|
||||||
unsubscribeTime := localTime.Add(30 * time.Minute)
|
|
||||||
order.UnsubscribeTime = &unsubscribeTime
|
|
||||||
}
|
|
||||||
|
|
||||||
order.CreatedAt = localTime
|
|
||||||
order.UpdatedAt = localTime
|
|
||||||
order.SM4PhoneNumber, _ = tools.SM4Encrypt(models.SM4KEy, order.PhoneNumber)
|
|
||||||
|
|
||||||
// 插入到数据库
|
|
||||||
if err := e.Orm.Create(&order).Error; err != nil {
|
|
||||||
fmt.Printf("插入订单数据失败: %v\n", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("order is:", order)
|
|
||||||
//if nRow > 4 {
|
|
||||||
// break
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 返回成功消息
|
|
||||||
c.JSON(http.StatusOK, gin.H{"message": "导入成功"})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImportExcelToMgOrderHandlerUpdate 处理Excel文件导入请求
|
|
||||||
// @Summary 导入订单Excel退订文件
|
|
||||||
// @Tags 2024-咪咕-管理后台
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Produce json
|
|
||||||
// @Param file formData file true "Excel文件"
|
|
||||||
// @Success 200 {object} map[string]string{"message": "导入成功"}
|
|
||||||
// @Router /api/v1/admin/order/import_update [post]
|
|
||||||
func (e MiGuDeployService) ImportExcelToMgOrderHandlerUpdate(c *gin.Context) {
|
|
||||||
err := e.MakeContext(c).MakeOrm().Errors
|
|
||||||
if err != nil {
|
|
||||||
e.Logger.Error(err)
|
|
||||||
response.Error(c, http.StatusInternalServerError, err, "创建上下文失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从请求中获取文件
|
|
||||||
file, err := c.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "无法读取文件"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打开上传的文件
|
|
||||||
fileStream, err := file.Open()
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "无法打开文件"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer fileStream.Close()
|
|
||||||
|
|
||||||
// 创建 CSV 阅读器
|
|
||||||
reader := csv.NewReader(fileStream)
|
|
||||||
reader.LazyQuotes = true
|
|
||||||
|
|
||||||
// 跳过 CSV 文件的标题行
|
|
||||||
if _, err := reader.Read(); err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "无法读取CSV标题行"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//nRow := 0
|
|
||||||
// 逐行读取 CSV 并插入数据库
|
|
||||||
for {
|
|
||||||
//nRow++
|
|
||||||
row, err := reader.Read()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "读取CSV文件失败"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查数据是否齐全
|
|
||||||
if len(row) < 3 {
|
|
||||||
continue // 跳过数据不全的行
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将时间往前推8小时
|
|
||||||
// localTime := subscribeTime.Add(-8 * time.Hour)
|
// localTime := subscribeTime.Add(-8 * time.Hour)
|
||||||
|
//
|
||||||
if !(row[0] != "" && len(row[0]) == 11) {
|
// tempOrderNo := models.GetExcelOrderSerial(e.Orm, subscribeTime)
|
||||||
continue
|
//
|
||||||
}
|
// // 创建MgOrder对象
|
||||||
|
// order := models.MgOrderCopy{
|
||||||
if row[0] == "15812800163" {
|
// ProductID: 2,
|
||||||
fmt.Println("found phone number: 15812800163")
|
// ChannelCode: "00211NV",
|
||||||
break
|
// OrderSerial: tempOrderNo,
|
||||||
}
|
// SubscribeTime: &localTime,
|
||||||
|
// PhoneNumber: row[0],
|
||||||
unsubscribeTime, _ := models.ConvertStringToTime(row[2])
|
// ChannelTradeNo: tempOrderNo,
|
||||||
|
// ExternalOrderID: tempOrderNo,
|
||||||
err = e.Orm.Table("mg_order_copy").Where("phone_number = ?", row[0]).Updates(map[string]interface{}{
|
// State: 1,
|
||||||
"state": models.UnsubscribeOK,
|
// }
|
||||||
"unsubscribe_time": unsubscribeTime,
|
//
|
||||||
"updated_at": unsubscribeTime,
|
// if row[2] == "未包月" { // 1小时内退订
|
||||||
}).Error
|
// order.IsOneHourCancel = 1
|
||||||
if err != nil {
|
// order.State = 2
|
||||||
fmt.Println("CheckOrderState update mg_order err:", err.Error())
|
// unsubscribeTime := localTime.Add(30 * time.Minute)
|
||||||
continue
|
// order.UnsubscribeTime = &unsubscribeTime
|
||||||
}
|
// }
|
||||||
//if nRow > 4 {
|
//
|
||||||
|
// order.CreatedAt = localTime
|
||||||
|
// order.UpdatedAt = localTime
|
||||||
|
// order.SM4PhoneNumber, _ = tools.SM4Encrypt(models.SM4KEy, order.PhoneNumber)
|
||||||
|
//
|
||||||
|
// // 插入到数据库
|
||||||
|
// if err := e.Orm.Create(&order).Error; err != nil {
|
||||||
|
// fmt.Printf("插入订单数据失败: %v\n", err)
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fmt.Println("order is:", order)
|
||||||
|
// //if nRow > 4 {
|
||||||
|
// // break
|
||||||
|
// //}
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 返回成功消息
|
||||||
|
// c.JSON(http.StatusOK, gin.H{"message": "导入成功"})
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//// ImportExcelToMgOrderHandlerUpdate 处理Excel文件导入请求
|
||||||
|
//// @Summary 导入订单Excel退订文件
|
||||||
|
//// @Tags 2024-咪咕-管理后台
|
||||||
|
//// @Accept multipart/form-data
|
||||||
|
//// @Produce json
|
||||||
|
//// @Param file formData file true "Excel文件"
|
||||||
|
//// @Success 200 {object} map[string]string{"message": "导入成功"}
|
||||||
|
//// @Router /api/v1/admin/order/import_update [post]
|
||||||
|
//func (e MiGuDeployService) ImportExcelToMgOrderHandlerUpdate(c *gin.Context) {
|
||||||
|
// err := e.MakeContext(c).MakeOrm().Errors
|
||||||
|
// if err != nil {
|
||||||
|
// e.Logger.Error(err)
|
||||||
|
// response.Error(c, http.StatusInternalServerError, err, "创建上下文失败")
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 从请求中获取文件
|
||||||
|
// file, err := c.FormFile("file")
|
||||||
|
// if err != nil {
|
||||||
|
// c.JSON(http.StatusBadRequest, gin.H{"error": "无法读取文件"})
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 打开上传的文件
|
||||||
|
// fileStream, err := file.Open()
|
||||||
|
// if err != nil {
|
||||||
|
// c.JSON(http.StatusInternalServerError, gin.H{"error": "无法打开文件"})
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// defer fileStream.Close()
|
||||||
|
//
|
||||||
|
// // 创建 CSV 阅读器
|
||||||
|
// reader := csv.NewReader(fileStream)
|
||||||
|
// reader.LazyQuotes = true
|
||||||
|
//
|
||||||
|
// // 跳过 CSV 文件的标题行
|
||||||
|
// if _, err := reader.Read(); err != nil {
|
||||||
|
// c.JSON(http.StatusInternalServerError, gin.H{"error": "无法读取CSV标题行"})
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //nRow := 0
|
||||||
|
// // 逐行读取 CSV 并插入数据库
|
||||||
|
// for {
|
||||||
|
// //nRow++
|
||||||
|
// row, err := reader.Read()
|
||||||
|
// if err == io.EOF {
|
||||||
// break
|
// break
|
||||||
// }
|
// }
|
||||||
}
|
// if err != nil {
|
||||||
|
// c.JSON(http.StatusInternalServerError, gin.H{"error": "读取CSV文件失败"})
|
||||||
// 返回成功消息
|
// return
|
||||||
c.JSON(http.StatusOK, gin.H{"message": "导入成功"})
|
// }
|
||||||
}
|
//
|
||||||
|
// // 检查数据是否齐全
|
||||||
|
// if len(row) < 3 {
|
||||||
|
// continue // 跳过数据不全的行
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 将时间往前推8小时
|
||||||
|
// //localTime := subscribeTime.Add(-8 * time.Hour)
|
||||||
|
//
|
||||||
|
// if !(row[0] != "" && len(row[0]) == 11) {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if row[0] == "15812800163" {
|
||||||
|
// fmt.Println("found phone number: 15812800163")
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// unsubscribeTime, _ := models.ConvertStringToTime(row[2])
|
||||||
|
//
|
||||||
|
// err = e.Orm.Table("mg_order_copy").Where("phone_number = ?", row[0]).Updates(map[string]interface{}{
|
||||||
|
// "state": models.UnsubscribeOK,
|
||||||
|
// "unsubscribe_time": unsubscribeTime,
|
||||||
|
// "updated_at": unsubscribeTime,
|
||||||
|
// }).Error
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Println("CheckOrderState update mg_order err:", err.Error())
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// //if nRow > 4 {
|
||||||
|
// // break
|
||||||
|
// //}
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 返回成功消息
|
||||||
|
// c.JSON(http.StatusOK, gin.H{"message": "导入成功"})
|
||||||
|
//}
|
||||||
|
|
||||||
// HourSummaryList 历史汇总(按小时)
|
// HourSummaryList 历史汇总(按小时)
|
||||||
// @Summary 历史汇总(按小时)
|
// @Summary 历史汇总(按小时)
|
||||||
|
@ -3086,15 +3089,33 @@ func (e MiGuDeployService) queryHistoricalDataByHour(startTime, endTime string,
|
||||||
|
|
||||||
// 拆分小时数据与汇总数据
|
// 拆分小时数据与汇总数据
|
||||||
var filteredData []models.MgHourSummary
|
var filteredData []models.MgHourSummary
|
||||||
var summaryData *models.MgHourSummary
|
summaryData := &models.MgHourSummary{}
|
||||||
for _, item := range data {
|
for _, item := range data {
|
||||||
if item.Hour == "Total" {
|
if item.Hour == "Total" {
|
||||||
summaryData = &item
|
// 累积汇总数据
|
||||||
|
summaryData.SubmissionCount += item.SubmissionCount
|
||||||
|
summaryData.NewUserCount += item.NewUserCount
|
||||||
|
summaryData.NewUserUnsubWithinHour += item.NewUserUnsubWithinHour
|
||||||
|
summaryData.NewUserUnsubOnDay += item.NewUserUnsubOnDay
|
||||||
|
summaryData.TotalNewUserUnsub += item.TotalNewUserUnsub
|
||||||
} else {
|
} else {
|
||||||
filteredData = append(filteredData, item)
|
filteredData = append(filteredData, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 汇总数据比率重新计算
|
||||||
|
if summaryData.NewUserCount > 0 {
|
||||||
|
summaryData.SubmissionSuccessRate = fmt.Sprintf("%.2f%%", float64(summaryData.NewUserCount)*100/float64(summaryData.SubmissionCount))
|
||||||
|
summaryData.NewUserUnsubWithinHourRate = fmt.Sprintf("%.2f%%", float64(summaryData.NewUserUnsubWithinHour)*100/float64(summaryData.NewUserCount))
|
||||||
|
summaryData.NewUserUnsubOnDayRate = fmt.Sprintf("%.2f%%", float64(summaryData.NewUserUnsubOnDay)*100/float64(summaryData.NewUserCount))
|
||||||
|
summaryData.TotalNewUserUnsubRate = fmt.Sprintf("%.2f%%", float64(summaryData.TotalNewUserUnsub)*100/float64(summaryData.NewUserCount))
|
||||||
|
} else {
|
||||||
|
summaryData.SubmissionSuccessRate = "0.00%"
|
||||||
|
summaryData.NewUserUnsubWithinHourRate = "0.00%"
|
||||||
|
summaryData.NewUserUnsubOnDayRate = "0.00%"
|
||||||
|
summaryData.TotalNewUserUnsubRate = "0.00%"
|
||||||
|
}
|
||||||
|
|
||||||
// 按小时降序排序
|
// 按小时降序排序
|
||||||
sort.Slice(filteredData, func(i, j int) bool {
|
sort.Slice(filteredData, func(i, j int) bool {
|
||||||
hourI, errI := strconv.Atoi(filteredData[i].Hour)
|
hourI, errI := strconv.Atoi(filteredData[i].Hour)
|
||||||
|
|
|
@ -149,6 +149,8 @@ type MgHistoricalSummary struct {
|
||||||
NewUserUnsubWithinHourRate string `json:"new_user_unsub_within_hour_rate"` // 当日新用户退订率(1小时以内)
|
NewUserUnsubWithinHourRate string `json:"new_user_unsub_within_hour_rate"` // 当日新用户退订率(1小时以内)
|
||||||
NewUserUnsubOnDay int `json:"new_user_unsub_on_day"` // 当日新用户退订数
|
NewUserUnsubOnDay int `json:"new_user_unsub_on_day"` // 当日新用户退订数
|
||||||
NewUserUnsubOnDayRate string `json:"new_user_unsub_on_day_rate"` // 当日新用户退订率
|
NewUserUnsubOnDayRate string `json:"new_user_unsub_on_day_rate"` // 当日新用户退订率
|
||||||
|
NewUserUnsubWithin24H int `gorm:"column:new_user_unsub_within_24h" json:"new_user_unsub_within_24h"` // 当日新用户24小时退订数
|
||||||
|
NewUserUnsubWithin24HRate string `gorm:"column:new_user_unsub_within_24h_rate" json:"new_user_unsub_within_24h_rate"` // 当日新用户24小时退订率
|
||||||
TotalNewUserUnsub int `json:"total_new_user_unsub"` // 累计新用户退订数
|
TotalNewUserUnsub int `json:"total_new_user_unsub"` // 累计新用户退订数
|
||||||
TotalNewUserUnsubRate string `json:"total_new_user_unsub_rate"` // 累计新用户退订率
|
TotalNewUserUnsubRate string `json:"total_new_user_unsub_rate"` // 累计新用户退订率
|
||||||
//Province string `gorm:"size:255" json:"province"` // 省份
|
//Province string `gorm:"size:255" json:"province"` // 省份
|
||||||
|
@ -398,7 +400,7 @@ type OrderListReq struct {
|
||||||
ChannelTradeNo string `json:"channelTradeNo"` // 渠道订单号
|
ChannelTradeNo string `json:"channelTradeNo"` // 渠道订单号
|
||||||
Phone string `json:"phone"` // 手机号码
|
Phone string `json:"phone"` // 手机号码
|
||||||
SM4PhoneNumber string `json:"sm4_phone_number"` // SM4加密手机号
|
SM4PhoneNumber string `json:"sm4_phone_number"` // SM4加密手机号
|
||||||
State int `json:"state"` // 退订状态 0-查所有 1-未退订 2-已退订 3-1小时内退订
|
State int `json:"state"` // 退订状态 0-查所有 1-已退订 2-未退订 3-1小时内退订 4-24小时退订
|
||||||
PageNum int `json:"page_num"` // 页码
|
PageNum int `json:"page_num"` // 页码
|
||||||
PageSize int `json:"page_size"` // 每页条数
|
PageSize int `json:"page_size"` // 每页条数
|
||||||
IsExport uint32 `json:"is_export"` // 1-导出
|
IsExport uint32 `json:"is_export"` // 1-导出
|
||||||
|
@ -1397,7 +1399,7 @@ func ExportHistoricalSummaryToExcel(data []MgHistoricalSummary, db *gorm.DB) (st
|
||||||
|
|
||||||
// 设置标题栏
|
// 设置标题栏
|
||||||
titles := []string{"日期", "产品ID", "渠道编码", "提交数", "新用户数", "提交成功率", "1小时退订数", "1小时退订率",
|
titles := []string{"日期", "产品ID", "渠道编码", "提交数", "新用户数", "提交成功率", "1小时退订数", "1小时退订率",
|
||||||
"当日退订数", "当日退订率", "累计退订数", "累计退订率"}
|
"当日退订数", "当日退订率", "24小时退订数", "24小时退订率", "累计退订数", "累计退订率"}
|
||||||
for i, title := range titles {
|
for i, title := range titles {
|
||||||
cell, _ := excelize.CoordinatesToCellName(i+1, 1)
|
cell, _ := excelize.CoordinatesToCellName(i+1, 1)
|
||||||
file.SetCellValue(sheet, cell, title)
|
file.SetCellValue(sheet, cell, title)
|
||||||
|
@ -1424,6 +1426,8 @@ func ExportHistoricalSummaryToExcel(data []MgHistoricalSummary, db *gorm.DB) (st
|
||||||
file.SetColWidth(sheet, "J", "J", 15)
|
file.SetColWidth(sheet, "J", "J", 15)
|
||||||
file.SetColWidth(sheet, "K", "K", 15)
|
file.SetColWidth(sheet, "K", "K", 15)
|
||||||
file.SetColWidth(sheet, "L", "L", 15)
|
file.SetColWidth(sheet, "L", "L", 15)
|
||||||
|
file.SetColWidth(sheet, "M", "M", 15)
|
||||||
|
file.SetColWidth(sheet, "N", "N", 15)
|
||||||
|
|
||||||
// 创建一个产品ID到名称的映射
|
// 创建一个产品ID到名称的映射
|
||||||
productMap := make(map[int64]string)
|
productMap := make(map[int64]string)
|
||||||
|
@ -1453,11 +1457,13 @@ func ExportHistoricalSummaryToExcel(data []MgHistoricalSummary, db *gorm.DB) (st
|
||||||
file.SetCellValue(sheet, "H"+strconv.Itoa(row), record.NewUserUnsubWithinHourRate)
|
file.SetCellValue(sheet, "H"+strconv.Itoa(row), record.NewUserUnsubWithinHourRate)
|
||||||
file.SetCellValue(sheet, "I"+strconv.Itoa(row), record.NewUserUnsubOnDay)
|
file.SetCellValue(sheet, "I"+strconv.Itoa(row), record.NewUserUnsubOnDay)
|
||||||
file.SetCellValue(sheet, "J"+strconv.Itoa(row), record.NewUserUnsubOnDayRate)
|
file.SetCellValue(sheet, "J"+strconv.Itoa(row), record.NewUserUnsubOnDayRate)
|
||||||
file.SetCellValue(sheet, "K"+strconv.Itoa(row), record.TotalNewUserUnsub)
|
file.SetCellValue(sheet, "K"+strconv.Itoa(row), record.NewUserUnsubWithin24H)
|
||||||
file.SetCellValue(sheet, "L"+strconv.Itoa(row), record.TotalNewUserUnsubRate)
|
file.SetCellValue(sheet, "L"+strconv.Itoa(row), record.NewUserUnsubWithin24HRate)
|
||||||
|
file.SetCellValue(sheet, "M"+strconv.Itoa(row), record.TotalNewUserUnsub)
|
||||||
|
file.SetCellValue(sheet, "N"+strconv.Itoa(row), record.TotalNewUserUnsubRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
endRow := fmt.Sprintf("L%d", len(data)+1)
|
endRow := fmt.Sprintf("N%d", len(data)+1)
|
||||||
// 应用样式到整个表格
|
// 应用样式到整个表格
|
||||||
_ = file.SetCellStyle(sheet, "A1", endRow, style)
|
_ = file.SetCellStyle(sheet, "A1", endRow, style)
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ func registerMiGuControlManageRouter(v1 *gin.RouterGroup, authMiddleware *jwt.Gi
|
||||||
api.POST("home/revenue_analysis", apiMiGu.CalculateRevenueAnalysis) // 营收分析
|
api.POST("home/revenue_analysis", apiMiGu.CalculateRevenueAnalysis) // 营收分析
|
||||||
|
|
||||||
api.POST("historical_summary/list", apiMiGu.HistoricalSummaryListOld) // 历史汇总查询
|
api.POST("historical_summary/list", apiMiGu.HistoricalSummaryListOld) // 历史汇总查询
|
||||||
api.POST("order/import", apiMiGu.ImportExcelToMgOrderHandler) // 通过excel导入订单数据
|
//api.POST("order/import", apiMiGu.ImportExcelToMgOrderHandler) // 通过excel导入订单数据
|
||||||
//api.POST("order/import_update", apiMiGu.ImportExcelToMgOrderHandlerUpdate) // 通过excel导入订单退订数据
|
//api.POST("order/import_update", apiMiGu.ImportExcelToMgOrderHandlerUpdate) // 通过excel导入订单退订数据
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5046,6 +5046,14 @@ const docTemplateadmin = `{
|
||||||
"description": "当日新用户退订率",
|
"description": "当日新用户退订率",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"new_user_unsub_within_24h": {
|
||||||
|
"description": "当日新用户24小时退订数",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"new_user_unsub_within_24h_rate": {
|
||||||
|
"description": "当日新用户24小时退订率",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"new_user_unsub_within_hour": {
|
"new_user_unsub_within_hour": {
|
||||||
"description": "当日新用户退订数(1小时以内)",
|
"description": "当日新用户退订数(1小时以内)",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
@ -5677,6 +5685,10 @@ const docTemplateadmin = `{
|
||||||
"description": "查询结束时间",
|
"description": "查询结束时间",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"is_export": {
|
||||||
|
"description": "1-导出",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"product_id": {
|
"product_id": {
|
||||||
"description": "产品ID",
|
"description": "产品ID",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
@ -5919,6 +5931,10 @@ const docTemplateadmin = `{
|
||||||
"description": "结束时间",
|
"description": "结束时间",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"is_export": {
|
||||||
|
"description": "1-导出",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"page_num": {
|
"page_num": {
|
||||||
"description": "页码",
|
"description": "页码",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
|
|
@ -5038,6 +5038,14 @@
|
||||||
"description": "当日新用户退订率",
|
"description": "当日新用户退订率",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"new_user_unsub_within_24h": {
|
||||||
|
"description": "当日新用户24小时退订数",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"new_user_unsub_within_24h_rate": {
|
||||||
|
"description": "当日新用户24小时退订率",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"new_user_unsub_within_hour": {
|
"new_user_unsub_within_hour": {
|
||||||
"description": "当日新用户退订数(1小时以内)",
|
"description": "当日新用户退订数(1小时以内)",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
@ -5669,6 +5677,10 @@
|
||||||
"description": "查询结束时间",
|
"description": "查询结束时间",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"is_export": {
|
||||||
|
"description": "1-导出",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"product_id": {
|
"product_id": {
|
||||||
"description": "产品ID",
|
"description": "产品ID",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
@ -5911,6 +5923,10 @@
|
||||||
"description": "结束时间",
|
"description": "结束时间",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"is_export": {
|
||||||
|
"description": "1-导出",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"page_num": {
|
"page_num": {
|
||||||
"description": "页码",
|
"description": "页码",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
|
|
@ -1138,6 +1138,12 @@ definitions:
|
||||||
new_user_unsub_on_day_rate:
|
new_user_unsub_on_day_rate:
|
||||||
description: 当日新用户退订率
|
description: 当日新用户退订率
|
||||||
type: string
|
type: string
|
||||||
|
new_user_unsub_within_24h:
|
||||||
|
description: 当日新用户24小时退订数
|
||||||
|
type: integer
|
||||||
|
new_user_unsub_within_24h_rate:
|
||||||
|
description: 当日新用户24小时退订率
|
||||||
|
type: string
|
||||||
new_user_unsub_within_hour:
|
new_user_unsub_within_hour:
|
||||||
description: 当日新用户退订数(1小时以内)
|
description: 当日新用户退订数(1小时以内)
|
||||||
type: integer
|
type: integer
|
||||||
|
@ -1589,6 +1595,9 @@ definitions:
|
||||||
end_time:
|
end_time:
|
||||||
description: 查询结束时间
|
description: 查询结束时间
|
||||||
type: string
|
type: string
|
||||||
|
is_export:
|
||||||
|
description: 1-导出
|
||||||
|
type: integer
|
||||||
product_id:
|
product_id:
|
||||||
description: 产品ID
|
description: 产品ID
|
||||||
type: integer
|
type: integer
|
||||||
|
@ -1758,6 +1767,9 @@ definitions:
|
||||||
end_time:
|
end_time:
|
||||||
description: 结束时间
|
description: 结束时间
|
||||||
type: string
|
type: string
|
||||||
|
is_export:
|
||||||
|
description: 1-导出
|
||||||
|
type: integer
|
||||||
page_num:
|
page_num:
|
||||||
description: 页码
|
description: 页码
|
||||||
type: integer
|
type: integer
|
||||||
|
|
Loading…
Reference in New Issue
Block a user