1.新增接口:门店销售对比;
This commit is contained in:
parent
3751999ca1
commit
6725fc0a1f
|
@ -5,6 +5,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
model "go-admin/app/admin/models"
|
||||
"go-admin/logger"
|
||||
"go-admin/tools"
|
||||
"go-admin/tools/app"
|
||||
"net/http"
|
||||
)
|
||||
|
@ -35,3 +36,36 @@ func ErpDecisionReport(c *gin.Context) {
|
|||
app.OK(c, resp, "OK")
|
||||
return
|
||||
}
|
||||
|
||||
// ErpStoreSalesData 门店销售对比
|
||||
// @Summary 门店销售对比
|
||||
// @Tags 决策中心,V1.4.0
|
||||
// @Produce json
|
||||
// @Accept json
|
||||
// @Param request body models.ErpStoreSalesDataReq true "门店销售对比数据模型"
|
||||
// @Success 200 {object} models.ErpStoreSalesDataResp
|
||||
// @Router /api/v1/decision/store_sales_report [post]
|
||||
func ErpStoreSalesData(c *gin.Context) {
|
||||
var req = new(model.ErpStoreSalesDataReq)
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
logger.Error("ShouldBindJSON err:", logger.Field("err", err))
|
||||
app.Error(c, http.StatusBadRequest, err, "参数错误:"+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err := tools.Validate(req) //必填参数校验
|
||||
if err != nil {
|
||||
app.Error(c, http.StatusBadRequest, err, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := model.QueryStoreSalesData(req, c)
|
||||
if err != nil {
|
||||
logger.Error("QueryStoreSalesData err:", logger.Field("err", err))
|
||||
app.Error(c, http.StatusInternalServerError, err, "查询失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
app.OK(c, resp, "")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2754,3 +2754,358 @@ func reportDecisionExport(req *ErpDecisionReportResp) (string, error) {
|
|||
}
|
||||
return url + fileName, nil
|
||||
}
|
||||
|
||||
// ErpStoreSalesDataReq 门店销售对比入参
|
||||
type ErpStoreSalesDataReq struct {
|
||||
StoreId []uint32 `json:"store_id"` // 门店ID
|
||||
StartTime string `json:"start_time"` // 开始时间
|
||||
EndTime string `json:"end_time"` // 结束时间
|
||||
PageIndex int `json:"pageIndex"` // 页码
|
||||
PageSize int `json:"pageSize"` // 页面条数
|
||||
IsExport uint32 `json:"is_export"` // 1-导出
|
||||
SortType string `json:"sort_type"` // 排序类型:desc 降序、asc 升序
|
||||
}
|
||||
|
||||
// ErpStoreSalesDataResp 门店销售对比出参
|
||||
type ErpStoreSalesDataResp struct {
|
||||
List []StoreSalesData `json:"list"`
|
||||
Total int `json:"total"` // 总条数
|
||||
PageIndex int `json:"pageIndex"` // 页码
|
||||
PageSize int `json:"pageSize"` // 每页展示条数
|
||||
ExportUrl string `json:"export_url"`
|
||||
TotalSalesAmount float64 `json:"total_sales_amount"` // 总销售额
|
||||
TotalPromotionFee float64 `json:"total_promotion_fee"` // 总推广费
|
||||
TotalSalesProfit float64 `json:"total_sales_profit"` // 总销售毛利
|
||||
TotalStaffProfit float64 `json:"total_staff_profit"` // 总员工毛利
|
||||
TotalCount int64 `json:"total_count"` // 总销售数量
|
||||
}
|
||||
|
||||
// StoreSalesData 门店销售数据
|
||||
type StoreSalesData struct {
|
||||
StoreId uint32 `json:"store_id"` // 门店id
|
||||
StoreName string `json:"store_name"` // 门店名称
|
||||
TotalSalesAmount float64 `json:"total_sales_amount"` // 销售额
|
||||
PromotionFee float64 `json:"promotion_fee"` // 推广费
|
||||
SalesProfit float64 `json:"sales_profit"` // 销售毛利
|
||||
StaffProfit float64 `json:"staff_profit"` // 员工毛利
|
||||
Count int64 `json:"count"` // 销售数量
|
||||
}
|
||||
|
||||
// QueryStoreSalesData 查询门店销售对比数据
|
||||
func QueryStoreSalesData(req *ErpStoreSalesDataReq, c *gin.Context) (*ErpStoreSalesDataResp, error) {
|
||||
showConfig, err := GetErpOrderShowConfig()
|
||||
if err != nil {
|
||||
logger.Errorf("List err:", err)
|
||||
showConfig.ShowAll = "ON"
|
||||
}
|
||||
|
||||
page := req.PageIndex - 1
|
||||
if page < 0 {
|
||||
page = 0
|
||||
}
|
||||
if req.PageSize == 0 {
|
||||
req.PageSize = 10
|
||||
}
|
||||
|
||||
resp := &ErpStoreSalesDataResp{
|
||||
PageIndex: req.PageIndex,
|
||||
PageSize: req.PageSize,
|
||||
}
|
||||
var storeManageDataList []StoreSalesData
|
||||
|
||||
// 构建查询条件
|
||||
qs := orm.Eloquent.Model(&ErpOrder{})
|
||||
if len(req.StoreId) != 0 {
|
||||
qs.Where("erp_order.store_id in ?", req.StoreId)
|
||||
}
|
||||
|
||||
var storeList []uint32
|
||||
// 非管理员才判断所属门店
|
||||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||||
sysUser, err := GetSysUserByCtx(c)
|
||||
if err != nil {
|
||||
return nil, errors.New("操作失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 返回sysUser未过期的门店id列表
|
||||
storeList = GetValidStoreIDs(sysUser.StoreData)
|
||||
if len(storeList) > 0 {
|
||||
if len(storeList) == 1 {
|
||||
qs = qs.Where("store_id = ?", storeList[0])
|
||||
} else {
|
||||
qs = qs.Where("store_id IN (?)", storeList)
|
||||
}
|
||||
} else {
|
||||
return nil, errors.New("用户未绑定门店")
|
||||
}
|
||||
} else {
|
||||
var allStoreList []Store
|
||||
err = orm.Eloquent.Table("store").Where("is_online = 1 and cooperative_business_id = 1").
|
||||
Find(&allStoreList).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, v := range allStoreList {
|
||||
storeList = append(storeList, v.ID)
|
||||
}
|
||||
}
|
||||
|
||||
if showConfig.ShowAll == "OFF" {
|
||||
qs = qs.Where("is_print = ? or retail_type = ?", HavePrinted, RetailTypeRejected)
|
||||
}
|
||||
|
||||
if req.StartTime != "" && req.EndTime != "" {
|
||||
startTime, err := time.Parse(QueryTimeFormat, req.StartTime)
|
||||
if err != nil {
|
||||
logger.Error("startTime parse err")
|
||||
}
|
||||
|
||||
endTime, err := time.Parse(QueryTimeFormat, req.EndTime)
|
||||
if err != nil {
|
||||
logger.Error("endTime parse err")
|
||||
}
|
||||
|
||||
qs = qs.Where("maker_time BETWEEN ? AND ?", startTime, endTime)
|
||||
} else {
|
||||
qs = qs.Where("maker_time IS NOT NULL")
|
||||
}
|
||||
qs.Where("state = ?", ErpOrderStateAudited)
|
||||
|
||||
// 查询汇总数据
|
||||
var summary struct {
|
||||
TotalSalesAmount float64
|
||||
TotalPromotionFee float64
|
||||
TotalSalesProfit float64
|
||||
TotalStaffProfit float64
|
||||
TotalCount int64
|
||||
}
|
||||
err = qs.Select("SUM(CASE WHEN retail_type = 'sale' THEN total_amount ELSE -total_amount END) AS total_sales_amount, " +
|
||||
"SUM(CASE WHEN retail_type = 'sale' THEN total_discount ELSE -total_discount END) AS total_promotion_fee, " +
|
||||
"SUM(CASE WHEN retail_type = 'sale' THEN total_sales_profit ELSE -total_sales_profit END) AS total_sales_profit, " +
|
||||
"SUM(CASE WHEN retail_type = 'sale' THEN total_staff_profit ELSE -total_staff_profit END) AS total_staff_profit, " +
|
||||
"SUM(CASE WHEN retail_type = 'sale' THEN total_count ELSE -total_count END) AS total_count").
|
||||
Find(&summary).Error
|
||||
if err != nil {
|
||||
logger.Error("QueryStoreManageData summary err:", logger.Field("err", err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 查询分页数据 按 store_id 进行汇总
|
||||
var storeData []struct {
|
||||
StoreId uint32 `json:"store_id"`
|
||||
TotalSalesAmount float64 `json:"total_sales_amount"`
|
||||
PromotionFee float64 `json:"promotion_fee"`
|
||||
SalesProfit float64 `json:"sales_profit"`
|
||||
StaffProfit float64 `json:"staff_profit"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
err = qs.Select("store_id, " +
|
||||
"SUM(CASE WHEN retail_type = 'sale' THEN total_discount ELSE -total_discount END) AS promotion_fee, " +
|
||||
"SUM(CASE WHEN retail_type = 'sale' THEN total_amount ELSE -total_amount END) AS total_sales_amount, " +
|
||||
"SUM(CASE WHEN retail_type = 'sale' THEN total_sales_profit ELSE -total_sales_profit END) AS sales_profit, " +
|
||||
"SUM(CASE WHEN retail_type = 'sale' THEN total_staff_profit ELSE -total_staff_profit END) AS staff_profit, " +
|
||||
"SUM(CASE WHEN retail_type = 'sale' THEN total_count ELSE -total_count END) AS count").
|
||||
Group("store_id").
|
||||
Order("store_id").
|
||||
Find(&storeData).Error
|
||||
if err != nil {
|
||||
logger.Error("QueryStoreManageData err:", logger.Field("err", err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
storeMap, err := GetAllStoreData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 组合数据
|
||||
for _, storeId := range storeList {
|
||||
flag := false
|
||||
for _, v := range storeData {
|
||||
if v.StoreId == storeId {
|
||||
flag = true
|
||||
storeManageDataList = append(storeManageDataList, StoreSalesData{
|
||||
StoreId: v.StoreId,
|
||||
StoreName: storeMap[v.StoreId].Name,
|
||||
TotalSalesAmount: math.Round(v.TotalSalesAmount*100) / 100,
|
||||
PromotionFee: math.Round(v.PromotionFee*100) / 100,
|
||||
SalesProfit: math.Round(v.SalesProfit*100) / 100,
|
||||
StaffProfit: math.Round(v.StaffProfit*100) / 100,
|
||||
Count: v.Count,
|
||||
})
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !flag {
|
||||
storeManageDataList = append(storeManageDataList, StoreSalesData{
|
||||
StoreId: storeId,
|
||||
StoreName: storeMap[storeId].Name,
|
||||
TotalSalesAmount: 0,
|
||||
PromotionFee: 0,
|
||||
SalesProfit: 0,
|
||||
StaffProfit: 0,
|
||||
Count: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 汇总数据赋值给响应
|
||||
resp.TotalSalesAmount = math.Round(summary.TotalSalesAmount*100) / 100
|
||||
resp.TotalPromotionFee = math.Round(summary.TotalPromotionFee*100) / 100
|
||||
resp.TotalSalesProfit = math.Round(summary.TotalSalesProfit*100) / 100
|
||||
resp.TotalStaffProfit = math.Round(summary.TotalStaffProfit*100) / 100
|
||||
resp.TotalCount = summary.TotalCount
|
||||
|
||||
if req.IsExport == 1 { //导出excel
|
||||
filePath, err := storeSalesDataExport(storeManageDataList, summary, c)
|
||||
if err != nil {
|
||||
logger.Error("StoreManageDataExport err:", logger.Field("err", err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.ExportUrl = filePath
|
||||
} else {
|
||||
// 根据页码和页面条数截取结果
|
||||
startIndex := page * req.PageSize
|
||||
endIndex := startIndex + req.PageSize
|
||||
if endIndex > len(storeManageDataList) {
|
||||
endIndex = len(storeManageDataList)
|
||||
}
|
||||
resp.List = storeManageDataList[startIndex:endIndex]
|
||||
|
||||
resp.Total = len(storeManageDataList)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// storeSalesDataExport 导出门店经营数据
|
||||
func storeSalesDataExport(list []StoreSalesData, summary struct {
|
||||
TotalSalesAmount float64
|
||||
TotalPromotionFee float64
|
||||
TotalSalesProfit float64
|
||||
TotalStaffProfit float64
|
||||
TotalCount int64
|
||||
}, c *gin.Context) (string, error) {
|
||||
file := excelize.NewFile()
|
||||
fSheet := "Sheet1"
|
||||
|
||||
url := config.ExportConfig.Url
|
||||
fileName := time.Now().Format(TimeFormat) + "门店销售对比" + ".xlsx"
|
||||
fmt.Println("url fileName:", url+fileName)
|
||||
|
||||
// 判断是否有入销售毛利、员工毛利的权限
|
||||
flag1, _ := checkRoleMenu(c, SalesProfitMenu)
|
||||
flag2, _ := checkRoleMenu(c, StaffProfitMenu)
|
||||
fmt.Println("flag1 is:", flag1)
|
||||
fmt.Println("flag2 is:", flag2)
|
||||
logger.Info("flag1 is:", logger.Field("flag1", flag1))
|
||||
logger.Info("flag2 is:", logger.Field("flag2", flag2))
|
||||
|
||||
nEndCount := 0
|
||||
title := []interface{}{"店铺名称", "销售额", "推广费"}
|
||||
if flag1 { // 销售毛利
|
||||
title = append(title, "销售毛利")
|
||||
nEndCount += 1
|
||||
}
|
||||
if flag2 { // 员工毛利
|
||||
title = append(title, "员工毛利")
|
||||
nEndCount += 1
|
||||
}
|
||||
title = append(title, "销售数量")
|
||||
|
||||
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++ {
|
||||
row = []interface{}{
|
||||
list[rowId].StoreName,
|
||||
list[rowId].TotalSalesAmount,
|
||||
list[rowId].PromotionFee,
|
||||
}
|
||||
|
||||
// 控制是否导出
|
||||
if flag1 { // 销售毛利
|
||||
row = append(row, list[rowId].SalesProfit)
|
||||
}
|
||||
if flag2 { // 员工毛利
|
||||
row = append(row, list[rowId].StaffProfit)
|
||||
}
|
||||
row = append(row, list[rowId].Count)
|
||||
|
||||
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++
|
||||
}
|
||||
|
||||
totalData := "汇总 记录数:" + strconv.FormatInt(int64(len(list)), 10)
|
||||
end := []interface{}{totalData, summary.TotalSalesAmount, summary.TotalPromotionFee}
|
||||
|
||||
if flag1 { // 销售毛利
|
||||
end = append(end, summary.TotalSalesProfit)
|
||||
}
|
||||
if flag2 { // 员工毛利
|
||||
end = append(end, summary.TotalStaffProfit)
|
||||
}
|
||||
end = append(end, summary.TotalCount)
|
||||
|
||||
for i, _ := range end {
|
||||
cell, _ := excelize.CoordinatesToCellName(1+i, nExcelStartRow+2)
|
||||
err := file.SetCellValue(fSheet, cell, end[i])
|
||||
if err != nil {
|
||||
logger.Error("file set value err:", logger.Field("err", err))
|
||||
}
|
||||
}
|
||||
|
||||
// 设置所有单元格的样式: 居中、加边框
|
||||
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", 30)
|
||||
file.SetColWidth("Sheet1", "B", "B", 18)
|
||||
file.SetColWidth("Sheet1", "C", "C", 18)
|
||||
file.SetColWidth("Sheet1", "D", "D", 18)
|
||||
file.SetColWidth("Sheet1", "E", "E", 18)
|
||||
file.SetColWidth("Sheet1", "F", "F", 18)
|
||||
|
||||
var endRow string
|
||||
switch nEndCount {
|
||||
case 1:
|
||||
endRow = fmt.Sprintf("E"+"%d", nExcelStartRow+2)
|
||||
case 2:
|
||||
endRow = fmt.Sprintf("F"+"%d", nExcelStartRow+2)
|
||||
default:
|
||||
endRow = fmt.Sprintf("D"+"%d", nExcelStartRow+2)
|
||||
}
|
||||
// 应用样式到整个表格
|
||||
_ = 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
|
||||
}
|
||||
|
|
|
@ -10,5 +10,6 @@ import (
|
|||
func registerErpDecisionRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
||||
r := v1.Group("/decision").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
||||
|
||||
r.POST("report", decision.ErpDecisionReport) // 进销存报表
|
||||
r.POST("report", decision.ErpDecisionReport) // 进销存报表
|
||||
r.POST("store_sales_report", decision.ErpStoreSalesData) // 进销存报表
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user