1、优化零售明细excel导出,解决导出全量数量超时报错的问题;

This commit is contained in:
chenlin 2024-11-05 20:40:49 +08:00
parent 4e47b69ef1
commit 6d801b1404
2 changed files with 341 additions and 9 deletions

View File

@ -276,3 +276,53 @@ func GetCategoryLevels(categoryID uint32) (CategoryLevels, error) {
return levels, nil
}
// GetAllCategories 查询所有分类并返回一个映射
func GetAllCategories() (map[uint32]Category, error) {
var categories []Category
err := orm.Eloquent.Model(&Category{}).Find(&categories).Error
if err != nil {
return nil, err
}
categoryMap := make(map[uint32]Category)
for _, category := range categories {
categoryMap[category.ID] = category
}
return categoryMap, nil
}
// GetCategoryLevelsFromMap 从预加载的分类信息中获取层级
func GetCategoryLevelsFromMap(categoryID uint32, categoryMap map[uint32]Category) CategoryLevels {
var levels CategoryLevels
// 维持当前分类的ID
currentID := categoryID
levelCount := 0
for currentID != 0 && levelCount < 3 {
currentCategory, exists := categoryMap[currentID]
if !exists {
break
}
// 根据分类编号的长度判断层级
numberLength := len(currentCategory.Number)
switch numberLength {
case 3:
levels.Level1 = currentCategory // 一级分类
case 6:
levels.Level2 = currentCategory // 二级分类
case 9:
levels.Level3 = currentCategory // 三级分类
default:
return levels // 超过9位返回空
}
// 移动到上级分类
currentID = currentCategory.Pid
levelCount++
}
return levels
}

View File

@ -17,6 +17,7 @@ import (
"sort"
"strconv"
"strings"
"sync"
"time"
)
@ -1345,6 +1346,40 @@ func NewErpBillSn() string {
}
}
// 添加零售订单的银行流水号
func erpOrderSetBankTrxNoAI(list []ErpOrder) {
if len(list) == 0 {
return // 如果列表为空,直接返回
}
// 提取所有的 BillSn
billSnList := make([]string, len(list))
for i, order := range list {
billSnList[i] = order.BillSn
}
// 批量查询
var orderPayWays []ErpOrderRecord
err := orm.Eloquent.Table("erp_order_record").
Where("bill_sn IN (?) AND status = ?", billSnList, PayOk).
Find(&orderPayWays).Error
if err != nil {
logger.Error("SetBankTrxNo query erp_order_record err:", logger.Field("err", err))
return
}
// 将银行流水号映射到订单
bankTrxNoMap := make(map[string]string)
for _, record := range orderPayWays {
bankTrxNoMap[record.BillSn] = record.BankTrxNo
}
// 设置每个订单的银行流水号
for i := range list {
list[i].BankTrxNo = bankTrxNoMap[list[i].BillSn]
}
}
// 添加零售订单的银行流水号
func erpOrderSetBankTrxNo(list []ErpOrder) {
for i, _ := range list {
@ -1467,6 +1502,171 @@ func (m *ErpOrder) SetRetailDetailCommodity() {
m.Commodities = respOrderCommodities
}
// ErpOrderRetailDetailSetCommodityAI 添加零售明细中订单的商品信息
func ErpOrderRetailDetailSetCommodityAI(list []ErpOrder) {
// 构建订单ID的切片
var orderIDs []uint32
for _, order := range list {
orderIDs = append(orderIDs, order.ID)
}
// 批量查询所有商品信息
var orderCommodities []ErpOrderCommodity
err := orm.Eloquent.Table("erp_order_commodity").Find(&orderCommodities).Error
if err != nil {
logger.Error("Batch query erp_order_commodity err:", logger.Field("err", err))
return
}
// 创建一个映射便于根据订单ID查找商品信息
commodityMap := make(map[uint32][]ErpOrderCommodity)
for _, commodity := range orderCommodities {
commodityMap[commodity.ErpOrderId] = append(commodityMap[commodity.ErpOrderId], commodity)
}
// 批量查询所有已售的非串码商品信息
var stockCommodities []ErpStockCommodity
err = orm.Eloquent.Table("erp_stock_commodity").Where("state = ? and imei = ?", SoldOut, "").Find(&stockCommodities).Error
if err != nil {
logger.Error("Batch query erp_stock_commodity err:", logger.Field("err", err))
return
}
// 创建一个映射便于根据库存商品ID查找商品信息
stockMap := make(map[uint32]ErpStockCommodity)
for _, stock := range stockCommodities {
stockMap[stock.ID] = stock
}
// 批量查询销售员信息
var salesmanInfo []ErpOrderSales
err = orm.Eloquent.Model(&ErpOrderSales{}).Find(&salesmanInfo).Error
if err != nil {
logger.Error("Batch query ErpOrderSales err:", logger.Field("err", err))
return
}
// 创建用户信息的映射,便于快速查找
salesMap := make(map[uint32][]ErpOrderSales)
for _, user := range salesmanInfo {
salesMap[user.ErpOrderId] = append(salesMap[user.ErpOrderId], user)
}
// 批量查询系统用户信息
userMap, err := GetSysUserInfoByIds()
if err != nil {
return
}
// 批量查询商品信息
var erpCommodities []ErpCommodity
err = orm.Eloquent.Table("erp_commodity").Find(&erpCommodities).Error
if err != nil {
logger.Error("Batch query erp_commodity err:", logger.Field("err", err))
return
}
erpCommodityMap := make(map[uint32]ErpCommodity)
for _, commodity := range erpCommodities {
erpCommodityMap[commodity.ID] = commodity
}
for i := range list {
list[i].SetRetailDetailCommodityAI(commodityMap[list[i].ID], stockMap)
list[i].StorePer = tools.RoundToTwoDecimalPlaces(list[i].StorePer)
if list[i].RetailType == RetailTypeRejected { // 退货订单,金额需要转换为负值
list[i].TotalRetailPrice = -math.Abs(list[i].TotalRetailPrice)
list[i].TotalAmount = -math.Abs(list[i].TotalAmount)
list[i].TotalCount = -int32(math.Abs(float64(list[i].TotalCount)))
list[i].TotalSalesProfit = -list[i].TotalSalesProfit
list[i].TotalStaffProfit = -list[i].TotalStaffProfit
list[i].TotalDiscount = -math.Abs(list[i].TotalDiscount)
list[i].VmCount = -uint32(math.Abs(float64(list[i].VmCount)))
if list[i].TotalStaffProfit > 0 {
list[i].StorePer = math.Abs(list[i].StorePer)
} else {
list[i].StorePer = -math.Abs(list[i].StorePer)
}
}
_ = list[i].SetOrderSalesmanAI(erpCommodityMap, salesMap, userMap)
}
}
func (m *ErpOrder) SetRetailDetailCommodityAI(orderCommodities []ErpOrderCommodity, stockMap map[uint32]ErpStockCommodity) {
var respOrderCommodities []ErpOrderCommodity
for _, item := range orderCommodities {
fmt.Println("orderId is:", item.ErpOrderId)
if m.RetailType == RetailTypeRejected { // 退货订单,金额需要转换为负值
item.Count = -item.Count
item.RetailPrice = -item.RetailPrice
item.SalePrice = -item.SalePrice
item.Amount = -item.Amount
item.SaleDiscount = -item.SaleDiscount
item.MemberDiscount = -item.MemberDiscount
item.VmDiscount = -item.VmDiscount
item.ReceivedAmount = -item.ReceivedAmount
item.RejectedAmount = -item.RejectedAmount
item.SalesProfit = -item.SalesProfit
item.StaffProfit = -item.StaffProfit
item.StaffCostPrice = -item.StaffCostPrice
item.WholesalePrice = -item.WholesalePrice
item.CouponDiscount = -item.CouponDiscount
}
item.StaffPrice = item.StaffCostPrice + item.WholesalePrice
if item.IMEIType == 2 || item.IMEIType == 3 || item.IMEI != "" { // 串码
respOrderCommodities = append(respOrderCommodities, item)
} else { // 非串码
idList, err := stringToIntArray(item.ErpStockCommodityID)
if err != nil {
respOrderCommodities = append(respOrderCommodities, item)
continue
}
for _, stockCommodityId := range idList {
fmt.Println("stockCommodityId is:", stockCommodityId)
var orderCommodity ErpOrderCommodity
orderCommodity = item
if m.RetailType == RetailTypeRejected { // 退货订单,数量需要转换为负值
orderCommodity.Count = -1
} else {
orderCommodity.Count = 1
}
nCount := math.Abs(float64(item.Count))
orderCommodity.SaleDiscount = item.SaleDiscount / nCount
orderCommodity.VmDiscount = item.VmDiscount / nCount
orderCommodity.ReceivedAmount = item.ReceivedAmount / nCount
orderCommodity.RejectedAmount = item.RejectedAmount / nCount
orderCommodity.SalesProfit = item.SalesProfit / nCount
orderCommodity.StaffProfit = item.StaffProfit / nCount
// 获取库存商品信息
stockCommodity, exists := stockMap[stockCommodityId]
if !exists {
respOrderCommodities = append(respOrderCommodities, item)
continue
}
orderCommodity.ErpSupplierId = stockCommodity.ErpSupplierId
orderCommodity.ErpSupplierName = stockCommodity.ErpSupplierName
orderCommodity.WholesalePrice = stockCommodity.WholesalePrice
orderCommodity.StaffCostPrice = stockCommodity.StaffCostPrice
orderCommodity.StaffPrice = orderCommodity.WholesalePrice + orderCommodity.StaffCostPrice
if m.RetailType == RetailTypeRejected { // 退货订单,数量需要转换为负值
orderCommodity.WholesalePrice = -orderCommodity.WholesalePrice
orderCommodity.StaffCostPrice = -orderCommodity.StaffCostPrice
orderCommodity.StaffPrice = -orderCommodity.StaffPrice
}
respOrderCommodities = append(respOrderCommodities, orderCommodity)
}
}
}
m.Commodities = respOrderCommodities
}
// 添加订单的商品信息
func erpOrderListSetCommodity(list []ErpOrder) {
for i, _ := range list {
@ -1631,6 +1831,69 @@ func (m *ErpOrder) SetOrderSalesmanRetailDetail(userId uint32) error {
return nil
}
// GetSysUserInfoByIds 批量获取用户信息
func GetSysUserInfoByIds() (map[uint32]SysUser, error) {
var userInfos []SysUser
err := orm.Eloquent.Debug().Table("sys_user").Find(&userInfos).Error
if err != nil {
logger.Error("Batch query sys_user err:", logger.Field("err", err))
return nil, err
}
// 创建用户信息的映射,便于快速查找
userMap := make(map[uint32]SysUser)
for _, user := range userInfos {
if countDigits(user.Uid) == 8 {
userMap[user.Uid] = user
} else {
userMap[uint32(user.UserId)] = user
}
}
return userMap, nil
}
func (m *ErpOrder) SetOrderSalesmanAI(erpCommodityMap map[uint32]ErpCommodity, salesMap map[uint32][]ErpOrderSales, userMap map[uint32]SysUser) error {
var salesProfit, staffProfit, totalStaffProfit float64
//获取销售毛利、员工毛利数据
for _, item := range m.Commodities {
erpCommodity := erpCommodityMap[item.ErpCommodityId]
salesProfit += item.SalesProfit * erpCommodity.Brokerage1 * 0.01
staffProfit += item.StaffProfit * erpCommodity.Brokerage2 * 0.01
totalStaffProfit += item.StaffProfit
}
// 四舍五入并保留两位小数
salesProfit = math.Round(salesProfit*100) / 100
staffProfit = math.Round(staffProfit*100) / 100
totalStaffProfit = math.Round(totalStaffProfit*100) / 100
var salesmanInfo []ErpOrderSales
salesmanInfo = salesMap[m.ID]
var salesmanList []ErpOrderSales
for _, item := range salesmanInfo {
item.SalesProfitPer = salesProfit / float64(len(salesmanInfo))
item.StaffProfitPer = staffProfit / float64(len(salesmanInfo))
// 获取员工毛利
userInfo := userMap[item.Uid]
item.Name = userInfo.NickName
item.SalesmanPer = totalStaffProfit * userInfo.SalesCommRate * 0.01 / float64(len(salesmanInfo))
salesmanList = append(salesmanList, item)
}
if len(salesmanList) == 0 {
m.Salesman = []ErpOrderSales{}
} else {
m.Salesman = salesmanList
}
m.SalesmanList = ""
return nil
}
// 添加订单的销售员信息
func erpOrderListSetSalesman(list []ErpOrder) {
for i, _ := range list {
@ -3600,6 +3863,12 @@ func retailDetailExport(list []ErpOrder, sumData RetailDetailTotalData, c *gin.C
}
}
categoryMap, err := GetAllCategories()
if err != nil {
// 处理错误
logger.Error("GetAllCategories err:", logger.Field("err", err))
}
var row []interface{}
nAmount := 0.0
nExcelStartRow := 0
@ -3641,7 +3910,8 @@ func retailDetailExport(list []ErpOrder, sumData RetailDetailTotalData, c *gin.C
}
// 商品分类
categoryLevels, _ := GetCategoryLevels(list[i].Commodities[rowId].ErpCategoryId)
categoryID := list[i].Commodities[rowId].ErpCategoryId
categoryLevels := GetCategoryLevelsFromMap(categoryID, categoryMap)
isIMEIType := "是"
if list[i].Commodities[rowId].IMEIType == 1 {
@ -3675,11 +3945,11 @@ func retailDetailExport(list []ErpOrder, sumData RetailDetailTotalData, c *gin.C
}
}
salesMan1 := ""
salesMan2 := ""
// 单个订单的汇总数据只记录一次
if !orderFlag {
orderFlag = true
salesMan1 := ""
salesMan2 := ""
nSalesProfitPer := 0.0
nStaffProfitPer := 0.0
nSalesmanPer := 0.0
@ -3793,8 +4063,8 @@ func retailDetailExport(list []ErpOrder, sumData RetailDetailTotalData, c *gin.C
auditTime,
list[i].StoreName,
list[i].BankTrxNo,
list[i].Salesman[0].Name, //销售员1
list[i].Salesman[1].Name, //销售员2
salesMan1, //销售员1
salesMan2, //销售员2
categoryLevels.Level1.Name, // 一级分类
categoryLevels.Level2.Name, // 二级分类
categoryLevels.Level3.Name, // 三级分类
@ -3885,7 +4155,7 @@ func retailDetailExport(list []ErpOrder, sumData RetailDetailTotalData, c *gin.C
auditTime,
list[i].StoreName,
list[i].BankTrxNo,
list[i].Salesman[0].Name, //销售员1
salesMan1, //销售员1
"", //销售员2
categoryLevels.Level1.Name, // 一级分类
categoryLevels.Level2.Name, // 二级分类
@ -4903,9 +5173,21 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq, c *gin.Context) (*Erp
logger.Error("erp commodity list err:", logger.Field("err", err))
return resp, err
}
ErpOrderRetailDetailSetCommodity(orders)
erpOrderListSetSalesman(orders)
erpOrderSetBankTrxNo(orders)
// 进行批量处理
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
ErpOrderRetailDetailSetCommodityAI(orders) // 商品信息处理
}()
go func() {
defer wg.Done()
erpOrderSetBankTrxNoAI(orders) // 银行交易号处理
}()
wg.Wait() // 等待所有处理完成
fileUrl, err := retailDetailExport(orders, sumData, c)
if err != nil {