export.go 9.7 KB
package service

import (
	"fmt"
	"strings"

	"github.com/linmadan/egglib-go/core/application"
	"github.com/xuri/excelize/v2"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/factory"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/staff_assess/query"
	"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/infrastructure/dao"
)

// 员工绩效-综合管理-导出绩效-个人
func (srv *StaffAssessServeice) ExportUserAssess2V2(param *query.ExportUserAssess2Commad) (*excelize.File, error) {
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		_ = transactionContext.RollbackTransaction()
	}()
	hrbp, err := srv.getHRBP(transactionContext, param.CompanyId, param.OperatorId)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	assessDao := dao.NewStaffAssessDao(map[string]interface{}{
		"transactionContext": transactionContext,
	})
	// 按照cycleId获取项目的指标项
	evaluationItemList, err := assessDao.SearchEvaluationItemUsed2(param.CompanyId,
		param.CycleId, param.OperatorId, hrbp, param.ExportUserId)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	// 按照项目获取填写的内容
	assessContentList, err := assessDao.SearchStaffAssessContent2(param.CompanyId,
		param.CycleId, param.OperatorId, hrbp, param.ExportUserId)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	eData := newExportData3()
	eData.FormatTableHead(evaluationItemList)
	eData.FormatListValue(assessContentList)
	xlsxFile := excelize.NewFile()
	//设置默认的第一个sheet
	sheetIndex := xlsxFile.GetActiveSheetIndex()
	firstSheetName := xlsxFile.GetSheetName(sheetIndex)
	cycleName := ""
	if len(evaluationItemList) > 0 {
		cycleName = evaluationItemList[0].CycleName
	}
	for k1, val := range eData.userProjcetMap {
		for k2, val2 := range val {
			// 根据员工名称 添加一个sheet
			uname := eData.userIdName[k1]
			if len(uname) == 0 {
				continue
			}
			tableHeader, ok := eData.tableHeader[eData.tableHeaderKey(k1, val2)]
			if !ok {
				continue
			}

			newSheetName := uname + fmt.Sprintf("_%d", k2+1)
			xlsxFile.NewSheet(newSheetName)
			xlsxFile.SetCellStr(newSheetName, "B2", uname)
			xlsxFile.MergeCell(newSheetName, "B2", "B4")
			//填充第一列数据
			xlsxFile.SetCellStr(newSheetName, "A1", tableHeader.Name)
			xlsxFile.SetCellStr(newSheetName, "A2", cycleName)
			xlsxFile.MergeCell(newSheetName, "A2", "A4")
			xlsxFile.SetCellStr(newSheetName, "A5", "权重")
			xlsxFile.MergeCell(newSheetName, "A5", "B5")
			xlsxFile.SetCellStr(newSheetName, "A6", "评估标准")
			xlsxFile.MergeCell(newSheetName, "A6", "B6")
			// 日期
			dayList := eData.userDayMap[eData.userDayKey(k1, val2)]
			for ii, vv := range dayList {
				//填写在第几行
				axisNum := 7 + 3*ii
				axis := fmt.Sprintf("A%d", axisNum)
				xlsxFile.SetCellStr(newSheetName, axis, vv)
				axisEnd := fmt.Sprintf("B%d", axisNum+2)
				xlsxFile.MergeCell(newSheetName, axis, axisEnd) //单元格高度按三个单元格合并
			}
			allColNum := 0 //计算总共有多少列
			//第一行
			for _, v2 := range tableHeader.Child {

				//第二行
				for _, v3 := range v2.Child {
					//第三行
					for _, v4 := range v3.Child {
						allColNum++
						//按列填充数据
						colName, _ := excelize.ColumnNumberToName(allColNum + 2) //第3列开始
						xlsxFile.SetCellStr(newSheetName, colName+"2", v2.Name)  //分类
						xlsxFile.SetCellStr(newSheetName, colName+"3", v3.Name)  //加分项 得分项
						xlsxFile.SetCellStr(newSheetName, colName+"4", v4.Name)  // 评估项名称
						//权重 填写第5行数据
						k23 := eData.data23Key(k1, v2.Name, v3.Name, v4.Name)
						xlsxFile.SetCellStr(newSheetName, colName+"5", eData.data3[k23])
						//评估标准 填写第6行数据
						xlsxFile.SetCellStr(newSheetName, colName+"6", eData.data2[k23])
						//按日期填充评估的填写的值
						for i5, v5 := range dayList {
							k1 := eData.dataKey(k1, val2, v5, v2.Name, v3.Name, v4.Name)
							//填写在第几行
							axisNum := 7 + 3*i5
							axis := fmt.Sprintf("%s%d", colName, axisNum)
							if d, ok := eData.data[k1]; ok {
								xlsxFile.SetCellStr(newSheetName, axis, d.String())
							}
							//单元格高度按三个单元格合并
							axisEnd := fmt.Sprintf("%s%d", colName, axisNum+2)
							xlsxFile.MergeCell(newSheetName, axis, axisEnd)
						}
					}
				}
			}
			//
			colName, _ := excelize.ColumnNumberToName(allColNum + 2)
			xlsxFile.MergeCell(newSheetName, "A1", fmt.Sprintf("%s1", colName))
		}
	}
	//删除默认的第一个sheet
	xlsxFile.DeleteSheet(firstSheetName)
	return xlsxFile, nil
}

// 处理原始数据,方便进行 excel导出
type exportData3 struct {
	userIdName     map[string]string           //员工id对应的名字 id=>员工名称
	userProjcetMap map[string][]string         //员工的项目 员工id=>项目id
	tableHeader    map[string]*HeaderLevel     //表头数据 key=员工id+项目id
	userDayMap     map[string][]string         //每个员工对应的日期列表  key=员工id+项目id value= 日期列表
	data           map[string]*strings.Builder //每个员工表头对应的评估填写的数据 key=员工id+项目id+日期+表头
	data2          map[string]string           //每个员工评估项的标准描述  key=员工id+项目id+表头
	data3          map[string]string           //每个员工评估项的标准权重  key=员工id+项目id+表头
}

func newExportData3() *exportData3 {
	return &exportData3{
		userIdName:     map[string]string{},
		userProjcetMap: map[string][]string{},
		tableHeader:    map[string]*HeaderLevel{},
		userDayMap:     map[string][]string{},
		data:           map[string]*strings.Builder{},
		data2:          map[string]string{}, data3: map[string]string{}}
}

func (e *exportData3) FormatTableHead(param []dao.DataEvaluationItemUsed2) {
	userNameMap := map[string]struct{}{}  //员工名字过滤
	projectIdMap := map[string]struct{}{} //项目id过滤
	for _, val := range param {
		//
		if _, ok := e.userProjcetMap[val.TargetUserId]; !ok {
			e.userProjcetMap[val.TargetUserId] = []string{}
		}
		//处理一个员工多项目的情况
		if _, ok := projectIdMap[val.EvaluationProjectId]; !ok {
			e.userProjcetMap[val.TargetUserId] = append(e.userProjcetMap[val.TargetUserId], val.EvaluationProjectId)
			projectIdMap[val.EvaluationProjectId] = struct{}{}
		}
		//处理员工的名称
		if _, ok := e.userIdName[val.TargetUserId]; !ok {
			if _, ok := userNameMap[val.TargetUserName]; ok {
				//员工重名
				uname := fmt.Sprintf("%s(%d)", val.TargetUserName, len(userNameMap))
				e.userIdName[val.TargetUserId] = uname
				userNameMap[uname] = struct{}{}
			} else {
				e.userIdName[val.TargetUserId] = val.TargetUserName
				userNameMap[val.TargetUserName] = struct{}{}
			}
		}
		//每个员工对应的日期列表
		key1 := e.tableHeaderKey(val.TargetUserId, val.EvaluationProjectId)
		if _, ok := e.tableHeader[key1]; !ok {
			e.tableHeader[key1] = &HeaderLevel{
				Name:   "个人绩效评估等级统计表",
				Filter: map[string]int{},
				Child:  []HeaderLevel{},
			}
		}
		child := e.tableHeader[key1].addChild(val.Category) //第一级,"分类"
		weight := e.weightDesc(val.Weight)
		child = child.addChild(weight)  //第二级 '得分项' '加分项'
		child.addChild(val.ContentName) //第三级 评估项名称
	}
}

func (e *exportData3) FormatListValue(param []dao.DataStaffAssessContent2) {
	userDay := map[string]struct{}{}
	for _, val := range param {
		weight := e.weightDesc(val.Weight)
		key := e.dataKey(val.TargetUserId, val.EvaluationProjectId, val.BeginDay, val.Category, weight, val.ContentName)
		e.data[key] = &strings.Builder{}
		e.data[key].WriteString(val.Value + "\n") //填写的等级
		for _, vv := range val.Remark {
			vv.Title = strings.TrimSpace(vv.Title)
			if vv.Title != "填写自评反馈" {
				e.data[key].WriteString(vv.Title + "\n")
			}
			e.data[key].WriteString(vv.RemarkText + "\n")
		}
		dayKey := val.TargetUserId + val.EvaluationProjectId + val.BeginDay
		if _, ok := userDay[dayKey]; !ok {
			userDay[dayKey] = struct{}{}
			k := e.userDayKey(val.TargetUserId, val.EvaluationProjectId)
			e.userDayMap[k] = append(e.userDayMap[k], val.BeginDay)
		}
		key23 := e.data23Key(val.TargetUserId, val.Category, weight, val.ContentName)
		e.data2[key23] = val.PromptText
		if val.Weight == 0 {
			e.data3[key23] = ""
		} else {
			e.data3[key23] = fmt.Sprintf("%.2f%%", val.Weight)
		}
	}
}

func (e *exportData3) weightDesc(weight float64) string {
	if weight == 0 {
		return "加分项"
	} else {
		return "得分项"
	}
}

func (e *exportData3) dataKey(userId string, projectId string, beginDay string, category string, weight string, contentName string) string {
	key := fmt.Sprintf("%s-%s-%s-%s-%s-%s", userId, projectId, weight, beginDay, category, contentName)
	return key
}

func (e *exportData3) data23Key(userId string, category string, weight string, contentName string) string {
	key := fmt.Sprintf("%s-%s-%s-%s", userId, weight, category, contentName)
	return key
}

func (e *exportData3) userDayKey(userId string, projectId string) string {
	return fmt.Sprintf("%s-%s", userId, projectId)
}

func (e *exportData3) tableHeaderKey(targetUserId, evaluationProjectId string) string {
	return targetUserId + "-" + evaluationProjectId
}