diff --git a/app/admin/models/commodity.go b/app/admin/models/commodity.go index c62697d..66294bb 100644 --- a/app/admin/models/commodity.go +++ b/app/admin/models/commodity.go @@ -521,6 +521,44 @@ func (m *ErpCommodityListReq) List() (*ErpCommodityListResp, error) { return resp, nil } +// SortByErpSupplierId 对商品数组进行排序,先按供应商ID排序,如果相同则按商品编号排序(升序) +func SortByErpSupplierId(commodities []ErpCommodity, supplierIDDesc bool) { + // 定义排序函数 + less := func(i, j int) bool { + // 按照供应商ID排序 + if commodities[i].ErpSupplierId != commodities[j].ErpSupplierId { + if supplierIDDesc { // 降序 DESC + return commodities[i].ErpSupplierId > commodities[j].ErpSupplierId + } + return commodities[i].ErpSupplierId < commodities[j].ErpSupplierId // 升序 ASC + } + + // 解析商品编号,提取分类编号和商品编号的数字部分 + catNumI, subCatNumI, threeSubCatNumI, itemNumI := parseSerialNumber(commodities[i].SerialNumber) + catNumJ, subCatNumJ, threeSubCatNumJ, itemNumJ := parseSerialNumber(commodities[j].SerialNumber) + + // 按照分类编号从小到大排序 + if catNumI != catNumJ { + return catNumI < catNumJ + } + + // 如果分类编号相同,按照具体分类下的商品编号递增排序 + if subCatNumI != subCatNumJ { + return subCatNumI < subCatNumJ + } + + if threeSubCatNumI != threeSubCatNumJ { + return threeSubCatNumI < threeSubCatNumJ + } + + // 如果具体分类编号也相同,按照商品编号递增排序 + return itemNumI < itemNumJ + } + + // 调用排序函数进行排序 + sort.SliceStable(commodities, less) +} + // SortStockCommodities 对库存商品数组进行排序 func SortStockCommodities(commodities []ErpStock) { // 定义排序函数 diff --git a/app/admin/models/coupon.go b/app/admin/models/coupon.go index bdf19f0..48d0133 100644 --- a/app/admin/models/coupon.go +++ b/app/admin/models/coupon.go @@ -12,18 +12,19 @@ const ( type Coupon struct { Model - Name string `json:"name"` - Describe string `json:"describe" gorm:"type:text;"` // 描述 - CouponType string `json:"coupon_type"` - ActivityType uint32 `json:"activity_type"` // 活动类型 1-会员续费 - ActivityId uint32 `json:"activity_id" gorm:"index"` - Value uint32 `json:"value"` - OutCount uint32 `json:"out_count"` // 用户已领取数量 - UsedCount uint32 `json:"used_count"` // 用户已使用数量 - ActiveStart time.Time `json:"active_start"` // 有效期开始 - ActiveEnd time.Time `json:"active_end"` // 有效期结束 零值永不结束 - MemberLevel uint32 `json:"member_level"` // 会员等级 1-用户 2-会员 - IsDraw bool `json:"is_draw" gorm:"-"` + Name string `json:"name"` // 优惠券名称 + Describe string `json:"describe" gorm:"type:text"` // 优惠券简介 + Rule string `json:"rule" gorm:"type:text"` // 优惠券使用规则 + CouponType string `json:"coupon_type"` // + ActivityType uint32 `json:"activity_type"` // 活动类型 1-会员续费 + ActivityId uint32 `json:"activity_id" gorm:"index"` // + Value uint32 `json:"value"` // + OutCount uint32 `json:"out_count"` // 用户已领取数量 + UsedCount uint32 `json:"used_count"` // 用户已使用数量 + ActiveStart time.Time `json:"active_start"` // 有效期开始 + ActiveEnd time.Time `json:"active_end"` // 有效期结束 零值永不结束 + MemberLevel uint32 `json:"member_level"` // 会员等级 1-用户 2-会员 + IsDraw bool `json:"is_draw" gorm:"-"` // } // gen:qs diff --git a/app/admin/models/purchase.go b/app/admin/models/purchase.go index ea96f9c..d6e428e 100644 --- a/app/admin/models/purchase.go +++ b/app/admin/models/purchase.go @@ -2500,25 +2500,17 @@ func getErpPurchaseDemandAll(req *GetErpPurchaseDemandReq, c *gin.Context) (*Get switch req.SortType { case "desc": // 排序规则:主供应商id大 - sort.Slice(commodities, func(i, j int) bool { - return commodities[i].ErpSupplierId > commodities[j].ErpSupplierId - }) + SortByErpSupplierId(commodities, true) case "asc": // 排序规则:主供应商id小 - sort.Slice(commodities, func(i, j int) bool { - return commodities[i].ErpSupplierId < commodities[j].ErpSupplierId - }) + SortByErpSupplierId(commodities, false) default: // 排序规则:主供应商id小 - sort.Slice(commodities, func(i, j int) bool { - return commodities[i].ErpSupplierId < commodities[j].ErpSupplierId - }) + SortByErpSupplierId(commodities, false) } - } else if req.SortField == "" { + } else { // 排序规则:主供应商id小 - sort.Slice(commodities, func(i, j int) bool { - return commodities[i].ErpSupplierId < commodities[j].ErpSupplierId - }) + SortByErpSupplierId(commodities, false) } } @@ -2549,7 +2541,7 @@ func getErpPurchaseDemandAll(req *GetErpPurchaseDemandReq, c *gin.Context) (*Get wg.Add(1) go func(index int, commodity ErpCommodity) { defer wg.Done() - demandData, err := convertToDemandData(commodity, stores) + demandData, err := convertToDemandDataAll(commodity, stores) if err != nil { // Handle error return @@ -2588,230 +2580,8 @@ func getErpPurchaseDemandAll(req *GetErpPurchaseDemandReq, c *gin.Context) (*Get return resp, nil } -// 隐藏无采购需求的商品 -func getErpPurchaseDemandHide(req *GetErpPurchaseDemandReq, c *gin.Context) (*GetErpPurchaseDemandResp, error) { - page := req.PageIndex - 1 - if page < 0 { - page = 0 - } - if req.PageSize == 0 { - req.PageSize = 10 - } - - resp := &GetErpPurchaseDemandResp{ - PageIndex: page + 1, - PageSize: req.PageSize, - } - - // 查询采购需求单信息,筛选出有采购需求的商品id - var demand []ErpPurchaseDemand - demandQs := orm.Eloquent.Table("erp_purchase_demand"). - Where("state = 1") - - // 非管理员才判断所属门店 - 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) > 0 { - if len(storeList) == 1 { - demandQs = demandQs.Where("store_id = ?", storeList[0]) - } else { - demandQs = demandQs.Where("store_id IN (?)", storeList) - } - } - } else { - return nil, errors.New("用户未绑定门店") - } - } - - err := demandQs.Find(&demand).Error - if err != nil { - return nil, err - } - // 用 map 存储已经出现过的 ErpCommodityId - commodityIds := make(map[uint32]bool) - var uniqueCommodityIds []uint32 - - for _, d := range demand { - if _, ok := commodityIds[d.ErpCommodityId]; !ok { - commodityIds[d.ErpCommodityId] = true - uniqueCommodityIds = append(uniqueCommodityIds, d.ErpCommodityId) - } - } - - // 查询商品信息 - qs := orm.Eloquent.Debug().Table("erp_commodity") - if req.ErpCategoryId != 0 { - //qs = qs.Where("erp_category_id=?", req.ErpCategoryId) - categoryInfo, err := GetErpCategory(req.ErpCategoryId) - if err != nil { - return nil, err - } - qs = qs.Where("serial_number like ?", categoryInfo.Number+"%") - } - if req.ErpCommoditySerialNumber != "" { - qs = qs.Where("serial_number=?", req.ErpCommoditySerialNumber) - } - if req.ErpCommodityName != "" { - qs = qs.Where("name=?", req.ErpCommodityName) - } - if req.ErpSupplierId != 0 { - qs = qs.Where("erp_supplier_id=?", req.ErpSupplierId) - } - - var count int64 - if err := qs.Count(&count).Error; err != nil { - logger.Error("count err:", logger.Field("err", err)) - return resp, err - } - - var commodities []ErpCommodity - //if req.IsExport == 1 { // 导出excel - // err := qs.Order("id DESC").Find(&commodities).Error - // if err != nil && err != RecordNotFound { - // return resp, err - // } - //} else { - // err := qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&commodities).Error - // if err != nil && err != RecordNotFound { - // return resp, err - // } - //} - err = qs.Order("id DESC").Find(&commodities).Error - if err != nil && err != RecordNotFound { - return resp, err - } - - // 匹配商品id,有则继续查询返回数据,没有则不返回 - var matchedCommodities []ErpCommodity - for _, c := range commodities { - for _, uniqueID := range uniqueCommodityIds { - if c.ID == uniqueID { - matchedCommodities = append(matchedCommodities, c) - break // 找到匹配的商品后跳出内层循环,继续下一个商品 - } - } - } - - if len(matchedCommodities) == 0 { - resp.List = nil - } else { - // 排序 - if req.SortField == "erp_commodity_serial_number" { - switch req.SortType { - case "desc": - SortCommoditiesDesc(matchedCommodities) - case "asc": - SortCommoditiesAsc(matchedCommodities) - default: - SortCommoditiesAsc(matchedCommodities) - } - } else { - // 商品编号排序 - SortCommoditiesAsc(matchedCommodities) - } - - if req.CallType != 2 { - if req.SortField == "erp_supplier_id" { - switch req.SortType { - case "desc": - // 排序规则:主供应商id大 - sort.Slice(matchedCommodities, func(i, j int) bool { - return matchedCommodities[i].ErpSupplierId > matchedCommodities[j].ErpSupplierId - }) - case "asc": - // 排序规则:主供应商id小 - sort.Slice(matchedCommodities, func(i, j int) bool { - return matchedCommodities[i].ErpSupplierId < matchedCommodities[j].ErpSupplierId - }) - default: - // 排序规则:主供应商id小 - sort.Slice(matchedCommodities, func(i, j int) bool { - return matchedCommodities[i].ErpSupplierId < matchedCommodities[j].ErpSupplierId - }) - } - } else { - // 排序规则:主供应商id小 - sort.Slice(matchedCommodities, func(i, j int) bool { - return matchedCommodities[i].ErpSupplierId < matchedCommodities[j].ErpSupplierId - }) - } - } - - // 批量查询门店信息 - stores, err := GetOnlineStores(c) - if err != nil { - return nil, err - } - - // 并行查询需求数据 - var wg sync.WaitGroup - var tempCommodities []ErpCommodity - if req.IsExport == 1 { - tempCommodities = matchedCommodities - } else { - // 计算分页 - startIndex := page * req.PageSize - endIndex := (page + 1) * req.PageSize - if endIndex > len(matchedCommodities) { - endIndex = len(matchedCommodities) - } - tempCommodities = matchedCommodities[startIndex:endIndex] - } - demandDataList := make([]DemandData, len(tempCommodities)) - - for i, v := range tempCommodities { - wg.Add(1) - go func(index int, commodity ErpCommodity) { - defer wg.Done() - demandData, err := convertToDemandData(commodity, stores) - if err != nil { - // Handle error - return - } - demandDataList[index] = demandData - }(i, v) - } - - wg.Wait() - - if req.IsExport == 1 { // 导出excel - if len(demandDataList) == 0 { - return nil, errors.New("未查询到数据") - } - if req.CallType == 2 { // 店员视角 - resp.ExportUrl, err = demandDataExportOnShopAssistant(demandDataList) - } else { // 采购视角 - resp.ExportUrl, err = demandDataExport(demandDataList) - } - if err != nil { - return nil, err - } - } else { - // 计算分页所需的切片索引 - //startIndex := page * req.PageSize - //endIndex := (page + 1) * req.PageSize - //if endIndex > len(demandDataList) { - // endIndex = len(demandDataList) - //} - //resp.List = demandDataList[startIndex:endIndex] - - resp.List = demandDataList - resp.Total = int64(len(matchedCommodities)) - } - } - - return resp, nil -} - -// convertToDemandData 将商品转换为采购需求数据 -func convertToDemandData(commodity ErpCommodity, stores []Store) (DemandData, error) { +// convertToDemandDataAll 将商品转换为采购需求数据 +func convertToDemandDataAll(commodity ErpCommodity, stores []Store) (DemandData, error) { // 查询采购商品的备注信息 var demandRemarkInfo ErpPurchaseDemandRemark err := orm.Eloquent.Table("erp_purchase_demand_remark").Where("erp_commodity_id = ? and state = 1", @@ -2858,12 +2628,12 @@ func convertToDemandData(commodity ErpCommodity, stores []Store) (DemandData, er go func() { defer wg.Done() - stockCounts, err = GetCommodityStocksByStoreID(commodity.ID, stores) + stockCounts, err = GetCommodityStocksByStoreIDAll(commodity.ID, stores) }() go func() { defer wg.Done() - lastMonthSales, err = GetCommodityLastMonthSales(commodity.ID, stores) + lastMonthSales, err = GetCommodityLastMonthSalesAll(commodity.ID, stores) }() wg.Wait() @@ -2908,6 +2678,291 @@ func convertToDemandData(commodity ErpCommodity, stores []Store) (DemandData, er return demandData, nil } +// 隐藏无采购需求的商品 +func getErpPurchaseDemandHide(req *GetErpPurchaseDemandReq, c *gin.Context) (*GetErpPurchaseDemandResp, error) { + page := req.PageIndex - 1 + if page < 0 { + page = 0 + } + if req.PageSize == 0 { + req.PageSize = 10 + } + + resp := &GetErpPurchaseDemandResp{ + PageIndex: page + 1, + PageSize: req.PageSize, + } + + // 查询采购需求单信息,筛选出有采购需求的商品id + var demand []ErpPurchaseDemand + var demandRemarkInfo []ErpPurchaseDemandRemark + demandQs := orm.Eloquent.Table("erp_purchase_demand"). + Where("state = 1").Where("count <> 0") + demandRemarkQs := orm.Eloquent.Table("erp_purchase_demand_remark"). + Where("state = 1"). + Where("remark IS NOT NULL"). + Where("remark <> ''") + + // 非管理员才判断所属门店 + 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 { + demandQs = demandQs.Where("store_id = ?", storeList[0]) + demandRemarkQs = demandRemarkQs.Where("store_id = ?", storeList[0]) + } else { + demandQs = demandQs.Where("store_id IN (?)", storeList) + demandRemarkQs = demandRemarkQs.Where("store_id IN (?)", storeList) + } + } else { + return nil, errors.New("用户未绑定门店") + } + } + + err := demandQs.Find(&demand).Error + if err != nil { + return nil, err + } + + err = demandRemarkQs.Find(&demandRemarkInfo).Error + if err != nil { + return nil, err + } + + demandsMap := make(map[string]ErpPurchaseDemand) + storesMap := make(map[uint32][]uint32) + demandRemarksMap := make(map[uint32]ErpPurchaseDemandRemark) + + // 用 sync.Map 存储已经出现过的 ErpCommodityId + commodityIds := sync.Map{} + var uniqueCommodityIds []uint32 + + for _, d := range demand { + if _, ok := commodityIds.Load(d.ErpCommodityId); !ok { + commodityIds.Store(d.ErpCommodityId, true) + uniqueCommodityIds = append(uniqueCommodityIds, d.ErpCommodityId) + } + key := fmt.Sprintf("%d-%d", d.ErpCommodityId, d.StoreId) + demandsMap[key] = d + + // 更新 storesMap + if _, exists := storesMap[d.ErpCommodityId]; !exists { + storesMap[d.ErpCommodityId] = []uint32{d.StoreId} + } else { + storesMap[d.ErpCommodityId] = append(storesMap[d.ErpCommodityId], d.StoreId) + } + } + + for _, r := range demandRemarkInfo { + demandRemarksMap[r.ErpCommodityId] = r + } + + // 查询商品信息 + qs := orm.Eloquent.Debug().Table("erp_commodity") + if req.ErpCategoryId != 0 { + categoryInfo, err := GetErpCategory(req.ErpCategoryId) + if err != nil { + return nil, err + } + qs = qs.Where("serial_number like ?", categoryInfo.Number+"%") + } + if req.ErpCommoditySerialNumber != "" { + qs = qs.Where("serial_number=?", req.ErpCommoditySerialNumber) + } + if req.ErpCommodityName != "" { + qs = qs.Where("name=?", req.ErpCommodityName) + } + if req.ErpSupplierId != 0 { + qs = qs.Where("erp_supplier_id=?", req.ErpSupplierId) + } + + var count int64 + if err := qs.Count(&count).Error; err != nil { + logger.Error("count err:", logger.Field("err", err)) + return resp, err + } + + var commodities []ErpCommodity + err = qs.Order("id DESC").Find(&commodities).Error + if err != nil && err != RecordNotFound { + return resp, err + } + + // 匹配商品id,有则继续查询返回数据,没有则不返回 + var matchedCommodities []ErpCommodity + for _, item := range commodities { + if _, ok := commodityIds.Load(item.ID); ok { + matchedCommodities = append(matchedCommodities, item) + } + } + + if len(matchedCommodities) == 0 { + resp.List = nil + } else { + // 排序 + if req.SortField == "erp_commodity_serial_number" { + switch req.SortType { + case "desc": + SortCommoditiesDesc(matchedCommodities) + case "asc": + SortCommoditiesAsc(matchedCommodities) + default: + SortCommoditiesAsc(matchedCommodities) + } + } else { + // 商品编号排序 + SortCommoditiesAsc(matchedCommodities) + } + + if req.CallType != 2 { + if req.SortField == "erp_supplier_id" { + switch req.SortType { + case "desc": + // 排序规则:主供应商id大 + SortByErpSupplierId(matchedCommodities, true) + case "asc": + // 排序规则:主供应商id小 + SortByErpSupplierId(matchedCommodities, false) + default: + // 排序规则:主供应商id小 + SortByErpSupplierId(matchedCommodities, false) + } + } else { + // 排序规则:主供应商id小 + SortByErpSupplierId(matchedCommodities, false) + } + } + + // 批量查询门店信息 + stores, err := GetOnlineStores(c) + if err != nil { + return nil, err + } + + // 并行查询需求数据 + var wg sync.WaitGroup + var tempCommodities []ErpCommodity + if req.IsExport == 1 { + tempCommodities = matchedCommodities + } else { + // 计算分页 + startIndex := page * req.PageSize + endIndex := (page + 1) * req.PageSize + if endIndex > len(matchedCommodities) { + endIndex = len(matchedCommodities) + } + tempCommodities = matchedCommodities[startIndex:endIndex] + } + demandDataList := make([]DemandData, len(tempCommodities)) + + for i, v := range tempCommodities { + wg.Add(1) + go func(index int, commodity ErpCommodity) { + defer wg.Done() + demandData, err := convertToDemandData(commodity, storesMap[commodity.ID], stores, demandRemarksMap, demandsMap) + if err != nil { + // Handle error + return + } + demandDataList[index] = demandData + }(i, v) + } + + wg.Wait() + + if req.IsExport == 1 { // 导出excel + if len(demandDataList) == 0 { + return nil, errors.New("未查询到数据") + } + if req.CallType == 2 { // 店员视角 + resp.ExportUrl, err = demandDataExportOnShopAssistant(demandDataList) + } else { // 采购视角 + resp.ExportUrl, err = demandDataExport(demandDataList) + } + if err != nil { + return nil, err + } + } else { + resp.List = demandDataList + resp.Total = int64(len(matchedCommodities)) + } + } + + return resp, nil +} + +// convertToDemandData 将商品转换为采购需求数据 +func convertToDemandData(commodity ErpCommodity, usedStore []uint32, stores []Store, demandRemarksMap map[uint32]ErpPurchaseDemandRemark, demandMap map[string]ErpPurchaseDemand) (DemandData, error) { + demandData := DemandData{ + ErpSupplierId: commodity.ErpSupplierId, + ErpSupplierName: commodity.ErpSupplierName, + ErpCommodityID: commodity.ID, + ErpCommoditySerialNumber: commodity.SerialNumber, + ErpCommodityName: commodity.Name, + ErpCategoryID: commodity.ErpCategoryId, + ErpCategoryName: commodity.ErpCategoryName, + RetailPrice: commodity.RetailPrice, + Remark: demandRemarksMap[commodity.ID].Remark, + } + + var demands []ErpPurchaseDemand + for _, store := range usedStore { + key := fmt.Sprintf("%d-%d", commodity.ID, store) + v, ok := demandMap[key] + if !ok { + continue + } + + demands = append(demands, v) + } + + var lastWholesalePrices map[uint32]float64 + var stockCounts map[uint32]uint32 + var lastMonthSales map[uint32]uint32 + + lastWholesalePrices, _ = GetCommodityLastWholesalePrices(commodity.ID) + stockCounts, _ = GetCommodityStocksByStoreID(commodity.ID, usedStore) + lastMonthSales, _ = GetCommodityLastMonthSales(commodity.ID, usedStore) + + var totalCount uint32 + demandData.StoreList = make([]struct { + StoreID uint32 `json:"store_id"` + StoreName string `json:"store_name"` + LastMonthSales uint32 `json:"last_month_sales"` + StockCount uint32 `json:"stock_count"` + NeedCount uint32 `json:"need_count"` + }, len(stores)) + + for i, store := range stores { + demandData.StoreList[i].StoreID = store.ID + demandData.StoreList[i].StoreName = store.Name + + demandData.StoreList[i].StockCount = stockCounts[store.ID] + demandData.StoreList[i].LastMonthSales = lastMonthSales[store.ID] + + demandData.LastWholesalePrice = lastWholesalePrices[commodity.ID] + + for _, demand := range demands { + if demand.StoreId == store.ID { + demandData.StoreList[i].NeedCount = demand.Count + totalCount += demand.Count + break + } + } + } + + demandData.TotalCount = totalCount + demandData.TotalAmount = float64(totalCount) * demandData.LastWholesalePrice + + return demandData, nil +} + // GetCommodityPurchaseDemands 查询商品的采购需求单 func GetCommodityPurchaseDemands(commodityID uint32, stores []Store) ([]ErpPurchaseDemand, error) { var wg sync.WaitGroup @@ -2915,6 +2970,24 @@ func GetCommodityPurchaseDemands(commodityID uint32, stores []Store) ([]ErpPurch var demands []ErpPurchaseDemand wg.Add(len(stores)) + //for _, store := range stores { + // go func(storeID uint32) { + // defer wg.Done() + // var demand ErpPurchaseDemand + // err := orm.Eloquent.Table("erp_purchase_demand"). + // Where("erp_commodity_id = ? AND state = 1 AND store_id = ?", commodityID, storeID). + // First(&demand).Error + // if err != nil { + // // Handle error + // return + // } + // + // mu.Lock() + // defer mu.Unlock() + // demands = append(demands, demand) + // }(store.ID) + //} + for _, store := range stores { go func(storeID uint32) { defer wg.Done() @@ -2922,14 +2995,18 @@ func GetCommodityPurchaseDemands(commodityID uint32, stores []Store) ([]ErpPurch err := orm.Eloquent.Table("erp_purchase_demand"). Where("erp_commodity_id = ? AND state = 1 AND store_id = ?", commodityID, storeID). First(&demand).Error - if err != nil { - // Handle error + if err != nil && err != gorm.ErrRecordNotFound { + // Log the error but do not return it, to ensure other goroutines complete + logger.Error("query erp_purchase_demand err:", logger.Field("err", err)) return } - mu.Lock() - defer mu.Unlock() - demands = append(demands, demand) + // If no record is found, err == gorm.ErrRecordNotFound, we ignore it and not append to demands + if err == nil { + mu.Lock() + demands = append(demands, demand) + mu.Unlock() + } }(store.ID) } @@ -2964,7 +3041,85 @@ func GetCommodityLastWholesalePrices(commodityID uint32) (map[uint32]float64, er } // GetCommodityStocksByStoreID 批量查询商品的库存情况 -func GetCommodityStocksByStoreID(commodityID uint32, stores []Store) (map[uint32]uint32, error) { +func GetCommodityStocksByStoreID(commodityID uint32, stores []uint32) (map[uint32]uint32, error) { + // 并行查询库存情况 + var wg sync.WaitGroup + wg.Add(len(stores)) + + result := make(map[uint32]uint32) + + for _, store := range stores { + go func(storeID uint32) { + defer wg.Done() + // 查询库存情况 + var stockCount int64 + err := orm.Eloquent.Table("erp_stock_commodity"). + Where("erp_commodity_id = ? AND store_id = ? AND state = 1", commodityID, storeID). + Count(&stockCount).Error + if err != nil { + // Handle error + return + } + result[storeID] = uint32(stockCount) + }(store) + } + + wg.Wait() + + return result, nil +} + +// GetCommodityStockByPurchaseId 查询入库商品实际库存详情处剩余有效数,不包含已出库的数量 +func GetCommodityStockByPurchaseId(serialNumber string, orderId uint32) (uint32, error) { + var count int64 + err := orm.Eloquent.Table("erp_stock_commodity").Where("original_sn = ? and erp_commodity_id = ? and state = ?", + serialNumber, orderId, InStock).Count(&count).Error + if err != nil { + return 0, err + } + + return uint32(count), nil +} + +// GetCommodityLastMonthSales 批量查询商品的上月销售数量 +func GetCommodityLastMonthSales(commodityID uint32, stores []uint32) (map[uint32]uint32, error) { + // 获取上个月的时间范围 + firstDay, lastDay := GetLastMonthRange() + + // 并行查询上月销售数量 + var wg sync.WaitGroup + wg.Add(len(stores)) + + result := make(map[uint32]uint32) + var mu sync.Mutex // 用于保护 totalSales 的并发访问 + + for _, store := range stores { + go func(storeID uint32) { + defer wg.Done() + // 查询上月销售数量 + var sales int64 + err := orm.Eloquent.Table("erp_stock_commodity"). + Where("state = ? AND erp_commodity_id = ? AND store_id = ? AND updated_at BETWEEN ? AND ?", + SoldOut, commodityID, storeID, firstDay, lastDay).Count(&sales).Error + if err != nil { + // Handle error + return + } + + // 保护 totalSales 的并发访问 + mu.Lock() + defer mu.Unlock() + result[storeID] = uint32(sales) + }(store) + } + + wg.Wait() + + return result, nil +} + +// GetCommodityStocksByStoreIDAll 批量查询商品的库存情况 +func GetCommodityStocksByStoreIDAll(commodityID uint32, stores []Store) (map[uint32]uint32, error) { // 并行查询库存情况 var wg sync.WaitGroup wg.Add(len(stores)) @@ -2992,20 +3147,8 @@ func GetCommodityStocksByStoreID(commodityID uint32, stores []Store) (map[uint32 return result, nil } -// GetCommodityStockByPurchaseId 查询入库商品实际库存详情处剩余有效数,不包含已出库的数量 -func GetCommodityStockByPurchaseId(serialNumber string, orderId uint32) (uint32, error) { - var count int64 - err := orm.Eloquent.Table("erp_stock_commodity").Where("original_sn = ? and erp_commodity_id = ? and state = ?", - serialNumber, orderId, InStock).Count(&count).Error - if err != nil { - return 0, err - } - - return uint32(count), nil -} - -// GetCommodityLastMonthSales 批量查询商品的上月销售数量 -func GetCommodityLastMonthSales(commodityID uint32, stores []Store) (map[uint32]uint32, error) { +// GetCommodityLastMonthSalesAll 批量查询商品的上月销售数量 +func GetCommodityLastMonthSalesAll(commodityID uint32, stores []Store) (map[uint32]uint32, error) { // 获取上个月的时间范围 firstDay, lastDay := GetLastMonthRange()