From 6d801b140490ba995b768c0f3802326a821ec78c Mon Sep 17 00:00:00 2001 From: chenlin Date: Tue, 5 Nov 2024 20:40:49 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E9=9B=B6=E5=94=AE?= =?UTF-8?q?=E6=98=8E=E7=BB=86excel=E5=AF=BC=E5=87=BA=EF=BC=8C=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E5=AF=BC=E5=87=BA=E5=85=A8=E9=87=8F=E6=95=B0=E9=87=8F?= =?UTF-8?q?=E8=B6=85=E6=97=B6=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/models/category.go | 50 ++++++ app/admin/models/erp_order.go | 300 +++++++++++++++++++++++++++++++++- 2 files changed, 341 insertions(+), 9 deletions(-) diff --git a/app/admin/models/category.go b/app/admin/models/category.go index 6cbf2ff..2c08073 100644 --- a/app/admin/models/category.go +++ b/app/admin/models/category.go @@ -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 +} diff --git a/app/admin/models/erp_order.go b/app/admin/models/erp_order.go index 7801f86..4dc5e46 100644 --- a/app/admin/models/erp_order.go +++ b/app/admin/models/erp_order.go @@ -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 {