package models import ( "errors" "fmt" "github.com/gin-gonic/gin" "github.com/xuri/excelize/v2" orm "go-admin/common/global" "go-admin/logger" "go-admin/tools" "go-admin/tools/config" "math" "sort" "strconv" "sync" "time" ) // ErpDecisionReportReq 进销存报表入参 type ErpDecisionReportReq struct { StoreId []uint32 `json:"store_id"` // 门店id CommodityName []string `json:"commodity_name"` // 商品名称 CategoryID []uint32 `json:"category_id"` // 商品分类id StartTime string `json:"start_time"` // 开始时间 EndTime string `json:"end_time"` // 结束时间 IsExport uint32 `json:"is_export"` // 1-导出 PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 页面条数 } // ErpDecisionReportResp 进销存报表出参 type ErpDecisionReportResp struct { Total int `json:"total"` // 总条数/记录数 PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 页面条数 ExportUrl string `json:"export_url"` // 导出excel路径 SumData DecisionSumData `json:"sum_data"` // 汇总数据 List []DecisionReportData `json:"list"` // 明细数据 } // DecisionSumData 进销存汇总数据 type DecisionSumData struct { TotalBeginStock uint32 `json:"total_begin_stock"` // 期初库存 TotalBeginAmount float64 `json:"total_begin_amount"` // 期初金额 TotalPurchaseStock uint32 `json:"total_purchase_stock"` // 采购进货 TotalPurchaseReturn uint32 `json:"total_purchase_return"` // 采购退货 TotalOrderSale uint32 `json:"total_order_sale"` // 零售销售 TotalOrderReject uint32 `json:"total_order_reject"` // 零售退货 TotalAllotIn uint32 `json:"total_allot_in"` // 调拨入库 TotalAllotWaitIn uint32 `json:"total_allot_wait_in"` // 在途库存(入库) TotalAllotOut uint32 `json:"total_allot_out"` // 调拨出库 TotalAllotWaitOut uint32 `json:"total_allot_wait_out"` // 在途库存(出库) TotalProductIn uint32 `json:"total_product_in"` // 产品入库 TotalSystemOut uint32 `json:"total_system_out"` // 系统出库 TotalCheckIn uint32 `json:"total_check_in"` // 盘点入库 TotalCheckOut uint32 `json:"total_check_out"` // 盘点出库 TotalEndStock uint32 `json:"total_end_stock"` // 期末数量 TotalEndAmount float64 `json:"total_end_amount"` // 期末金额 } // DecisionReportData 进销存报表数据 type DecisionReportData struct { CommodityId uint32 `json:"commodity_id"` // 商品id CommodityName string `json:"commodity_name"` // 商品名称 CategoryID uint32 `json:"category_id"` // 商品分类id CategoryName string `json:"category_name"` // 商品分类名称 BeginStock uint32 `json:"begin_stock"` // 期初库存 BeginAmount float64 `json:"begin_amount"` // 期初金额 PurchaseStock uint32 `json:"purchase_stock"` // 采购进货 PurchaseReturn uint32 `json:"purchase_return"` // 采购退货 OrderSale uint32 `json:"order_sale"` // 零售销售 OrderReject uint32 `json:"order_reject"` // 零售退货 AllotIn uint32 `json:"allot_in"` // 调拨入库 AllotWaitIn uint32 `json:"allot_wait_in"` // 在途库存(入库) AllotOut uint32 `json:"allot_out"` // 调拨出库 AllotWaitOut uint32 `json:"allot_wait_out"` // 在途库存(出库) ProductIn uint32 `json:"product_in"` // 产品入库 SystemOut uint32 `json:"system_out"` // 系统出库 CheckIn uint32 `json:"check_in"` // 盘点入库 CheckOut uint32 `json:"check_out"` // 盘点出库 EndStock uint32 `json:"end_stock"` // 期末数量 EndAmount float64 `json:"end_amount"` // 期末金额 } // DecisionReportList 进销存报表 func (m *ErpDecisionReportReq) DecisionReportList(c *gin.Context) (*ErpDecisionReportResp, error) { // 非管理员才判断所属门店 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 { m.StoreId = CompareLists(storeList, m.StoreId) if len(m.StoreId) == 0 { // 没有匹配的数据,表示入参门店不是用户有权限的门店 return &ErpDecisionReportResp{}, nil } } else { return nil, errors.New("用户未绑定门店") } } resp := &ErpDecisionReportResp{ PageIndex: m.PageIndex, PageSize: m.PageSize, } page := m.PageIndex - 1 if page < 0 { page = 0 } if m.PageSize == 0 { m.PageSize = 10 } qs := orm.Eloquent.Debug().Table("erp_stock") if len(m.StoreId) > 0 { // 门店复选 var storeIDs []uint32 for _, store := range m.StoreId { storeIDs = append(storeIDs, store) } qs = qs.Where("store_id IN (?)", storeIDs) } if len(m.CommodityName) > 0 { // 商品名称 var commodityNames []string for _, commodityName := range m.CommodityName { commodityNames = append(commodityNames, commodityName) } qs = qs.Where("erp_commodity_name IN (?)", commodityNames) } if len(m.CategoryID) > 0 { // 商品分类id var categoryIDs []uint32 for _, category := range m.CategoryID { categoryIDs = append(categoryIDs, category) } qs = qs.Where("erp_category_id IN (?)", categoryIDs) } var count int64 err := qs.Count(&count).Error if err != nil { logger.Error("查询无库存列表数量失败", logger.Field("err", err)) return nil, err } var commodities []ErpStock err = qs.Order("erp_commodity_id, store_id desc").Find(&commodities).Error //if m.IsExport == 1 { // 导出excel // err = qs.Order("erp_commodity_id, store_id desc").Find(&commodities).Error //} else { // err = qs.Order("erp_commodity_id, store_id desc").Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error //} if err != nil && err != RecordNotFound { logger.Error("查询无库存列表失败", logger.Field("err", err)) return nil, err } var reportList []DecisionReportData var wg sync.WaitGroup ch := make(chan DecisionReportData, len(commodities)) for _, item := range commodities { wg.Add(1) go func(item ErpStock) { defer wg.Done() var reportData DecisionReportData reportData.CommodityId = item.ErpCommodityId reportData.CommodityName = item.ErpCommodityName reportData.CategoryID = item.ErpCategoryId reportData.CategoryName = item.ErpCategoryName // 查询各项数据 systemStartData, _ := getSystemStartCount(m, item) reportData.BeginStock = systemStartData.BeginStock reportData.BeginAmount = systemStartData.BeginAmount purchaseStockData, _ := getPurchaseStockCount(m, item) reportData.PurchaseStock = purchaseStockData.PurchaseStock purchaseReturnData, _ := getPurchaseReturnCount(m, item) reportData.PurchaseReturn = purchaseReturnData.PurchaseReturn saleOutData, _ := getSaleOutCount(m, item) reportData.OrderSale = saleOutData.OrderSale saleReturnData, _ := getSaleReturnCount(m, item) reportData.OrderReject = saleReturnData.OrderReject allotInData, _ := getAllotInCount(m, item) reportData.AllotIn = allotInData.AllotIn allotWaitInData, _ := getAllotWaitInCount(m, item) reportData.AllotWaitIn = allotWaitInData.AllotWaitIn allotOutData, _ := getAllotOutCount(m, item) reportData.AllotOut = allotOutData.AllotOut allotWaitOutData, _ := getAllotWaitOutCount(m, item) reportData.AllotWaitOut = allotWaitOutData.AllotWaitOut productData, _ := getProductCount(m, item) reportData.ProductIn = productData.ProductIn systemOutData, _ := getSystemOutCount(m, item) reportData.SystemOut = systemOutData.SystemOut changeAddData, _ := getChangeAddCount(m, item) reportData.CheckIn = changeAddData.CheckIn changeReduceData, _ := getChangeReduceCount(m, item) reportData.CheckOut = changeReduceData.CheckOut systemEndData, _ := getSystemEndCount(m, item) reportData.EndStock = systemEndData.EndStock reportData.EndAmount = systemEndData.EndAmount // 发送结果到通道 ch <- reportData }(item) } go func() { wg.Wait() close(ch) }() // 从通道中接收结果 var sumData DecisionSumData commodityMap := make(map[uint32]DecisionReportData) for data := range ch { if existing, found := commodityMap[data.CommodityId]; found { // Merge data if the commodity already exists in the map existing.BeginStock += data.BeginStock existing.BeginAmount += data.BeginAmount existing.PurchaseStock += data.PurchaseStock existing.PurchaseReturn += data.PurchaseReturn existing.OrderSale += data.OrderSale existing.OrderReject += data.OrderReject existing.AllotIn += data.AllotIn existing.AllotWaitIn += data.AllotWaitIn existing.AllotOut += data.AllotOut existing.AllotWaitOut += data.AllotWaitOut existing.ProductIn += data.ProductIn existing.SystemOut += data.SystemOut existing.CheckIn += data.CheckIn existing.CheckOut += data.CheckOut existing.EndStock += data.EndStock existing.EndAmount += data.EndAmount commodityMap[data.CommodityId] = existing } else { // If not found, add new entry to the map commodityMap[data.CommodityId] = data } } for _, data := range commodityMap { sumData.TotalBeginStock += data.BeginStock sumData.TotalBeginAmount += data.BeginAmount sumData.TotalPurchaseStock += data.PurchaseStock sumData.TotalPurchaseReturn += data.PurchaseReturn sumData.TotalOrderSale += data.OrderSale sumData.TotalOrderReject += data.OrderReject sumData.TotalAllotIn += data.AllotIn sumData.TotalAllotWaitIn += data.AllotWaitIn sumData.TotalAllotOut += data.AllotOut sumData.TotalAllotWaitOut += data.AllotWaitOut sumData.TotalProductIn += data.ProductIn sumData.TotalSystemOut += data.SystemOut sumData.TotalCheckIn += data.CheckIn sumData.TotalCheckOut += data.CheckOut sumData.TotalEndStock += data.EndStock sumData.TotalEndAmount += data.EndAmount sumData.TotalBeginAmount = math.Round(sumData.TotalBeginAmount*100) / 100 sumData.TotalEndAmount = math.Round(sumData.TotalEndAmount*100) / 100 reportList = append(reportList, data) } // 排序规则:商品编号小 sort.Slice(reportList, func(i, j int) bool { if reportList[i].CommodityId != reportList[j].CommodityId { return reportList[i].CommodityId < reportList[j].CommodityId } return true }) resp.SumData = sumData resp.Total = len(reportList) if m.IsExport == 1 { resp.List = reportList resp.ExportUrl, err = reportDecisionExport(resp) if err != nil { return nil, err } resp.Total = 0 resp.List = nil resp.SumData = DecisionSumData{} } else { // 分页处理 startIdx := (resp.PageIndex - 1) * resp.PageSize endIdx := resp.PageIndex * resp.PageSize // 确保不超出索引范围 if startIdx >= len(reportList) { resp.List = []DecisionReportData{} } else if endIdx > len(reportList) { resp.List = reportList[startIdx:] } else { resp.List = reportList[startIdx:endIdx] } } return resp, nil } // 查询期初库存、期初金额 func getSystemStartCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_stock_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } err := qs.Select("SUM(count) as begin_stock, SUM(wholesale_price) as begin_amount"). Where("storage_type = ? and store_id = ? and erp_commodity_id = ?", SystemInventory, stock.StoreId, stock.ErpCommodityId).Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询采购进货数量 func getPurchaseStockCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_purchase_inventory") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getPurchaseCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getPurchaseCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } err := qs.Select("SUM(erp_purchase_inventory.count) AS purchase_stock"). Joins("JOIN erp_purchase_order ON erp_purchase_order.id = erp_purchase_inventory.erp_purchase_order_id"). Where("erp_purchase_order.store_id = ? and erp_purchase_inventory.erp_commodity_id = ? and "+ "erp_purchase_inventory.purchase_type = ?", stock.StoreId, stock.ErpCommodityId, ErpProcureOrder). Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询采购退货数量 func getPurchaseReturnCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_stock_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } err := qs.Select("SUM(count) as purchase_return").Where("state = ? and store_id = ? and "+ "erp_commodity_id = ?", PurchaseReturn, stock.StoreId, stock.ErpCommodityId).Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询零售销售数量 func getSaleOutCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_order_commodity"). Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id") if req.StartTime != "" { // 审核开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("err:", err) } qs = qs.Where("erp_order.audit_time > ?", parse) } if req.EndTime != "" { // 审核结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("err:", err) } qs = qs.Where("erp_order.audit_time < ?", parse) } err := qs.Select("count(*) as order_sale").Where("erp_order.retail_type = ? and erp_order.state = ? "+ "and erp_order.store_id = ? and erp_order.pay_status = ? "+ "and erp_order_commodity.erp_commodity_id = ?", RetailTypeSale, ErpOrderStateAudited, stock.StoreId, HavePaid, stock.ErpCommodityId).Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询零售退货数量 func getSaleReturnCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_order_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getPurchaseCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_order.audit_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getPurchaseCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_order.audit_time > ?", parse) } err := qs.Select("SUM(erp_order_commodity.count) AS order_reject"). Joins("JOIN erp_order ON erp_order.id = erp_order_commodity.erp_order_id"). Where("erp_order.retail_type = ? and erp_order.store_id = ? and erp_order.state = ? "+ "and erp_order_commodity.erp_commodity_id = ?", RetailTypeRejected, stock.StoreId, ErpOrderStateAudited, stock.ErpCommodityId). Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询产品入库数量:产品入库 func getProductCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_stock_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } err := qs.Select("SUM(count) as product_in").Where("storage_type = ? and store_id = ? "+ "and erp_commodity_id = ?", ProductInventory, stock.StoreId, stock.ErpCommodityId).Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询盘点入库数量 func getChangeAddCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_inventory_change_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_inventory_change_order.audit_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_inventory_change_order.audit_time > ?", parse) } err := qs.Select("SUM(erp_inventory_change_commodity.count) AS check_in"). Joins("JOIN erp_inventory_change_order "+ "ON erp_inventory_change_order.id = erp_inventory_change_commodity.change_order_id"). Where("erp_inventory_change_order.change_type = ? and erp_inventory_change_order.store_id = ? "+ "and erp_inventory_change_order.state = ? "+"and erp_inventory_change_commodity.commodity_id = ?", AddChangeOrder, stock.StoreId, ErpInventoryChangeOrderFinished, stock.ErpCommodityId). Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询盘点出库数量 func getChangeReduceCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_inventory_change_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_inventory_change_order.audit_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_inventory_change_order.audit_time > ?", parse) } err := qs.Select("SUM(erp_inventory_change_commodity.count) AS check_in"). Joins("JOIN erp_inventory_change_order "+ "ON erp_inventory_change_order.id = erp_inventory_change_commodity.change_order_id"). Where("erp_inventory_change_order.change_type = ? and erp_inventory_change_order.store_id = ? "+ "and erp_inventory_change_order.state = ? and erp_inventory_change_commodity.commodity_id = ?", ReduceChangeOrder, stock.StoreId, ErpInventoryChangeOrderFinished, stock.ErpCommodityId). Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询系统出库数据:系统出库 func getSystemOutCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_stock_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } err := qs.Select("SUM(count) as system_out").Where("state = ? and store_id = ? "+ "and erp_commodity_id = ?", SystemOut, stock.StoreId, stock.ErpCommodityId).Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询在途库存(入库)数量 func getAllotWaitInCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_stock_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("updated_at > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("updated_at > ?", parse) } err := qs.Select("SUM(count) as allot_wait_in").Where("state = ? and store_id = ? "+ "and erp_commodity_id = ?", InAllot, stock.StoreId, stock.ErpCommodityId).Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询在途库存(出库)数量 func getAllotWaitOutCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_inventory_allot_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getAllotOutCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getAllotOutCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) } err := qs.Select("SUM(erp_inventory_allot_commodity.count) AS allot_out"). Joins("JOIN erp_inventory_allot_order "+ "ON erp_inventory_allot_order.id = erp_inventory_allot_commodity.allot_order_id"). Where("erp_inventory_allot_order.deliver_store_id = ? and erp_inventory_allot_order.state != ? "+ "and erp_inventory_allot_commodity.commodity_id = ?", stock.StoreId, ErpInventoryAllotOrderUnAudit, stock.ErpCommodityId). Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询调拨入库数量 func getAllotInCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_inventory_allot_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) } err := qs.Select("SUM(erp_inventory_allot_commodity.count) AS allot_in"). Joins("JOIN erp_inventory_allot_order "+ "ON erp_inventory_allot_order.id = erp_inventory_allot_commodity.allot_order_id"). Where("erp_inventory_allot_order.receive_store_id = ? and erp_inventory_allot_order.state = ? "+ "and erp_inventory_allot_commodity.commodity_id = ?", stock.StoreId, ErpInventoryAllotOrderFinished, stock.ErpCommodityId). Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询调拨出库数量 func getAllotOutCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_inventory_allot_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getAllotOutCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getAllotOutCount err:", err) return DecisionReportData{}, err } qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) } err := qs.Select("SUM(erp_inventory_allot_commodity.count) AS allot_out"). Joins("JOIN erp_inventory_allot_order "+ "ON erp_inventory_allot_order.id = erp_inventory_allot_commodity.allot_order_id"). Where("erp_inventory_allot_order.deliver_store_id = ? and erp_inventory_allot_order.state = ? "+ "and erp_inventory_allot_commodity.commodity_id = ?", stock.StoreId, ErpInventoryAllotOrderFinished, stock.ErpCommodityId). Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // 查询期末库存、期末金额 func getSystemEndCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportData, error) { var reportData DecisionReportData qs := orm.Eloquent.Debug().Table("erp_stock_commodity") // 进行条件查询 if req.StartTime != "" { // 出入库开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } if req.EndTime != "" { // 出入库结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) if err != nil { logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } qs = qs.Where("first_stock_time > ?", parse) } err := qs.Select("SUM(count) as end_stock, SUM(wholesale_price) as end_amount"). Where("state = ? and store_id = ? and erp_commodity_id = ?", InStock, stock.StoreId, stock.ErpCommodityId).Find(&reportData).Error if err != nil { return DecisionReportData{}, err } return reportData, nil } // reportDecisionExport 进销存报表导出excel func reportDecisionExport(req *ErpDecisionReportResp) (string, error) { file := excelize.NewFile() fSheet := "Sheet1" url := ExportUrl fileName := time.Now().Format(TimeFormat) + "进销存报表" + ".xlsx" fmt.Println("url fileName:", url+fileName) // 组合标题栏数据 title := []interface{}{"商品名称", "商品分类", "期初库存", "期初金额", "采购进货", "采购退货", "零售销售", "零售退货", "调拨入库", "在途库存(入库)", "调拨出库", "在途库存(出库)", "产品入库", "系统出库", "盘点入库", "盘点出库", "期末数量", "期末金额"} for i, _ := range title { cell, _ := excelize.CoordinatesToCellName(1+i, 1) err := file.SetCellValue(fSheet, cell, title[i]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } var row1 []interface{} nExcelStartRow := 0 for _, reportData := range req.List { row1 = []interface{}{ reportData.CommodityName, // 商品名称 reportData.CategoryName, // 商品分类 reportData.BeginStock, reportData.BeginAmount, reportData.PurchaseStock, reportData.PurchaseReturn, reportData.OrderSale, reportData.OrderReject, reportData.AllotIn, reportData.AllotWaitIn, reportData.AllotOut, reportData.AllotWaitOut, reportData.ProductIn, reportData.SystemOut, reportData.CheckIn, reportData.CheckOut, reportData.EndStock, reportData.EndAmount, } for j, _ := range row1 { cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2) err := file.SetCellValue(fSheet, cell, row1[j]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } nExcelStartRow++ } totalData := "汇总 记录数:" + strconv.FormatInt(int64(req.Total), 10) end := []interface{}{totalData, "", req.SumData.TotalBeginStock, req.SumData.TotalBeginAmount, req.SumData.TotalPurchaseStock, req.SumData.TotalPurchaseReturn, req.SumData.TotalOrderSale, req.SumData.TotalOrderReject, req.SumData.TotalAllotIn, req.SumData.TotalAllotWaitIn, req.SumData.TotalAllotOut, req.SumData.TotalAllotWaitOut, req.SumData.TotalProductIn, req.SumData.TotalSystemOut, req.SumData.TotalCheckIn, req.SumData.TotalCheckOut, req.SumData.TotalEndStock, req.SumData.TotalEndAmount} 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", 15) endRow := fmt.Sprintf("R"+"%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 }