package service import ( "fmt" "github.com/shopspring/decimal" "github.com/xuri/excelize/v2" "strconv" "time" "wms/constvar" "wms/models" "wms/pkg/logx" "wms/request" ) type WarehouseMonthFormsService struct{} func NewWarehouseMonthFormsService() *WarehouseMonthFormsService { return &WarehouseMonthFormsService{} } func (slf *WarehouseMonthFormsService) Query(params request.GetMonthStats) (result []*models.WarehouseMonthStats, err error) { search := slf.BuildSearch(params) search = search.SetPage(params.Page, params.PageSize) return search.FindNotTotal() } func (slf *WarehouseMonthFormsService) BuildSearch(params request.GetMonthStats) (search *models.WarehouseMonthStatsSearch) { search = models.NewWarehouseMonthStatsSearch(). SetKeyword(params.Keyword).SetDate(params.Date).SetWarehouseId(params.WarehouseID) if params.Preload { search = search.SetPreload(true) } return search } func (slf *WarehouseMonthFormsService) Count(params request.GetMonthStats) (total int64, err error) { search := slf.BuildSearch(params) return search.Count() } func (slf *WarehouseMonthFormsService) FetchAll(params request.GetMonthStats) (list []*models.WarehouseMonthStats, err error) { total, err := slf.Count(params) if err != nil { return nil, err } list = make([]*models.WarehouseMonthStats, 0, total) params.PageSize = 500 page := 1 for { params.Page = page data, err := slf.Query(params) if err != nil { return nil, err } if len(data) == 0 { break } list = append(list, data...) page++ } return } func (slf *WarehouseMonthFormsService) Export(dataList []*models.WarehouseMonthStats) (filename string, err error) { // 创建一个新的 Excel 文件 f := excelize.NewFile() if err != nil { logx.Errorf("NewSheet err:%v", err) return "", err } headers, headerLen, inputTypes, outputTypes := slf.GetHeaders() err = SetExcelHeader(headers, f) if err != nil { logx.Errorf("SetExcelHeader err:%v", err) return "", err } //表头样式 style, err := SetHeaderStyle(f) if err != nil { return "", err } f.SetCellStyle("Sheet1", "A1", getColumnAlphabet(headerLen)+"2", style) // 设置列宽 f.SetColWidth("Sheet1", "A", "F", 30) f.SetColWidth("Sheet1", "G", getColumnAlphabet(headerLen), 15) inputStart := 6 outputStart := 6 + len(inputTypes) for i, v := range dataList { column := strconv.Itoa(i + 3) f.SetCellValue("Sheet1", "A"+column, v.ProductId) f.SetCellValue("Sheet1", "B"+column, v.ProductName) f.SetCellValue("Sheet1", "C"+column, v.EndAmount) f.SetCellValue("Sheet1", "D"+column, v.BeginAmount) f.SetCellValue("Sheet1", "E"+column, v.Unit) f.SetCellValue("Sheet1", "F"+column, v.SalePrice) slf.FillDealerTypeToExcel(v.InputItems, inputStart, i+3, inputTypes, f, constvar.InputTotalHeader) slf.FillDealerTypeToExcel(v.OutputItems, outputStart, i+3, outputTypes, f, constvar.OutPutTotalHeader) } fileName := fmt.Sprintf("%s月度统计报表%s.xlsx", "仓库", time.Now().Format("2006-01-02-1504")) if err := f.SaveAs(fileName); err != nil { return fileName, err } return fileName, nil } func (slf *WarehouseMonthFormsService) GetHeaders() (headers []interface{}, headerLen int, inputTypes, outputTypes []string) { // 自定义表头 //查询入库类型 inputTypes = GetDictNameListByType(constvar.StorageType) inputTypes = append(inputTypes, constvar.InputTotalHeader) headerLen += len(inputTypes) //查询入库类型 outputTypes = GetDictNameListByType(constvar.StockoutType) outputTypes = append(outputTypes, constvar.OutPutTotalHeader) headerLen += len(inputTypes) headerLen += 6 headers = []interface{}{"物料编号", "物料编码", "月末结存", "月初结存", "单位", "单价", map[string][]string{"本月入库": inputTypes}, map[string][]string{"本月出库": outputTypes}} return headers, headerLen, inputTypes, outputTypes } func (slf *WarehouseMonthFormsService) SumItems(items []*models.WarehouseStatsItems) (sum decimal.Decimal) { for _, v := range items { sum = sum.Add(v.Amount) } return sum } func (slf *WarehouseMonthFormsService) FillDealerTypeToExcel(items []*models.WarehouseStatsItems, startIndex int, column int, dealerTypes []string, f *excelize.File, totalHeader string) { columnStr := strconv.Itoa(column) sum := slf.SumItems(items) detailMap := models.WarehouseStatsItemMap(items) for k := range detailMap { if k == "" { detailMap["其他"] = detailMap[k] delete(detailMap, k) } } for i := 0; i < len(dealerTypes); i++ { var amount decimal.Decimal if detailMap[dealerTypes[i]] != nil { amount = detailMap[dealerTypes[i]].Amount } else if dealerTypes[i] == totalHeader { amount = sum } f.SetCellValue("Sheet1", getColumnAlphabet(startIndex+i)+columnStr, amount) } return } func GetCurrentWarehouseStats(date string, warehouseId int, productIds []string, realTime bool) (statRecords []*models.WarehouseMonthStats, err error) { //本月期初数量/上月结余数量 groupSumList, err := models.NewLocationProductAmountSearch().SetProductIds(productIds).GroupSum("product_id", "amount") productIds = make([]string, 0, len(groupSumList)) for _, groupSum := range groupSumList { productIds = append(productIds, groupSum.Class) } products, err := models.NewMaterialSearch().SetFields("id, name, unit, weight, more_unit, more_unit_value").SetIDs(productIds).FindNotTotal() if err != nil { logx.Errorf("MonthStats GetCurrentStats get products err:%v", err) return } productMap := models.MaterialMap(products) //按配置取开始时间和结束时间 beginTime, endTime, err := NewSystemConfigService().GetInventoryCutOffTime() if realTime { beginTime = endTime endTime = time.Now() } if err != nil { logx.Errorf("MonthStats GetCurrentStats get GetInventoryCutOffTime err:%v", err) return } inputMap, err := GetStatsMulti(beginTime, endTime, constvar.BaseOperationTypeIncoming, warehouseId) if err != nil { logx.Errorf("MonthStats GetStatsByOperationType input err:%v", err) return } outputMap, err := GetStatsMulti(beginTime, endTime, constvar.BaseOperationTypeOutgoing, warehouseId) if err != nil { logx.Errorf("MonthStats GetStatsByOperationType output err:%v", err) return } for _, groupSum := range groupSumList { productId := groupSum.Class if productMap[productId] == nil { continue } product := productMap[productId] amount := groupSum.Sum record := models.WarehouseMonthStats{ WarehouseId: warehouseId, ProductId: productId, ProductName: product.Name, Unit: product.Unit, SalePrice: product.SalePrice, EndAmount: amount, InputAmount: SumMapAmount(inputMap[productId]), InputItems: GetDealerItems(inputMap[productId], models.MonthStatsItemsTypeInput), OutputAmount: SumMapAmount(outputMap[productId]), OutputItems: GetDealerItems(outputMap[productId], models.MonthStatsItemsTypeOutput), Date: date, } statRecords = append(statRecords, &record) } return } func GetStatsMulti(beginTime, endTime time.Time, operationType constvar.BaseOperationType, warehouseId int) (m map[string]map[string]decimal.Decimal, err error) { m = make(map[string]map[string]decimal.Decimal) operationIds, err := models.NewOperationSearch().SetBaseOperationType(operationType). SetFields("id").SetTimeBetween(beginTime, endTime). SetWarehouseId(warehouseId). FindIds() if err != nil { return } if len(operationIds) == 0 { return } groupSumList, err := models.NewOperationDetailsSearch().SetOperationIds(operationIds). SetFields("product_id, dealer_type, amount"). GroupMultiSumAmount() if err != nil { return } m = make(map[string]map[string]decimal.Decimal) for _, v := range groupSumList { if m[v.ProductID] == nil { m[v.ProductID] = make(map[string]decimal.Decimal) } m[v.ProductID][v.DealerType] = v.Sum } return } func SumMapAmount(m map[string]decimal.Decimal) (sum decimal.Decimal) { for _, v := range m { sum = sum.Add(v) } return } func GetDealerItems(m map[string]decimal.Decimal, tp models.MonthStatsItemsType) (items []*models.WarehouseStatsItems) { for k, v := range m { name := k if name == "" { name = "其他" } items = append(items, &models.WarehouseStatsItems{ Type: tp, Name: name, Amount: v, }) } return }