作者 tangxvhui

更新

... ... @@ -432,6 +432,3 @@ func (attendanceService *AttendanceService) SearchWorkshopWorkTimeStatics(operat
}
return count, result, nil
}
//ImportDataAttendance 工时管理,导入工时数据
func (attendanceService *AttendanceService) ImportDataAttendance() {}
... ...
package service
import (
"errors"
"strconv"
"strings"
"time"
"github.com/linmadan/egglib-go/core/application"
"github.com/linmadan/egglib-go/utils/excel"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/ecelData/command"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/factory"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils/converter"
)
type importAttendance struct {
ProductDate string `json:"productDate"` //日期
WorkshopName string `json:"workshopName"` //车间名称
LineName string `json:"lineName"` //线别名称
SectionName string `json:"sectionName"` //工位名称
WorkerName string `json:"workerName"` //工人姓名
AttendanceType string `json:"attendanceType"` //考勤类型 正常 支援
SignIn string `json:"signIn"` //上岗时间
SignOut string `json:"signOut"` //离岗时间
BreakTime string `json:"breakTime"` //休息时间
FailReason string `json:"failReason"` //数据校验失败的理由
}
func (data *importAttendance) validField() error {
if len(data.ProductDate) == 0 {
return errors.New("日期未填写。")
}
if len(data.WorkerName) == 0 {
return errors.New("车间名称未填写。")
}
if len(data.LineName) == 0 {
return errors.New("线别名称未填写。")
}
if len(data.SectionName) == 0 {
return errors.New("工位名称未填写。")
}
if len(data.WorkerName) == 0 {
return errors.New("工人姓名未填写。")
}
if len(data.AttendanceType) == 0 {
return errors.New("类型未填写。")
}
if len(data.SignIn) == 0 {
return errors.New("上岗时间未填写。")
}
if len(data.SignOut) == 0 {
return errors.New("下岗时间未填写。")
}
if len(data.BreakTime) == 0 {
return errors.New("休息时间未填写。")
}
return nil
}
func (srv ExcelDataService) ImportDataAttendance(importDataCommand *command.ImportDataCommand) (interface{}, error) {
excelImport := excel.NewExcelImport()
excelImport.RowBegin = 2 //第二行开始读取
excelImport.DataFields = []excel.DataField{
{EnName: "ProductDate", CnName: "日期"},
{EnName: "WorkshopName", CnName: "车间"},
{EnName: "LineName", CnName: "线别"},
{EnName: "SectionName", CnName: "工段"},
{EnName: "WorkerName", CnName: "姓名"},
{EnName: "AttendanceType", CnName: "类别"},
{EnName: "SignIn", CnName: "上岗时间"},
{EnName: "SignOut", CnName: "离岗时间"},
{EnName: "BreakTime", CnName: "休息时长(小时)"},
}
excelData, err := converter.OpenImportFileFromIoReader(excelImport, importDataCommand.Reader, importDataCommand.FileExt) //excelImport.OpenExcelFromIoReader(importDataCommand.Reader)
if err != nil {
return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
}
items := make([]importAttendance, 0)
for _, v := range excelData {
item := importAttendance{
ProductDate: strings.TrimSpace(v["ProductDate"]),
WorkshopName: strings.TrimSpace(v["WorkshopName"]),
LineName: strings.TrimSpace(v["LineName"]),
SectionName: strings.TrimSpace(v["SectionName"]),
WorkerName: strings.TrimSpace(v["WorkerName"]),
AttendanceType: strings.TrimSpace(v["AttendanceType"]),
SignIn: strings.TrimSpace(v["SignIn"]),
SignOut: strings.TrimSpace(v["SignOut"]),
BreakTime: strings.TrimSpace(v["BreakTime"]),
FailReason: "",
}
items = append(items, item)
}
failRows, err := srv.BatchAddAttendance(*importDataCommand.Operator, items)
if err != nil {
return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
}
return srv.importResultWithHeader(excelImport.DataFields, failRows, len(items)), nil
}
// BatchAddAttendance 工时管理,导入工时数据
func (srv ExcelDataService) BatchAddAttendance(operate domain.OperateInfo, param []importAttendance) (
failRows []interface{}, err 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()
}()
//车间数据
//生产班组 数据
productGroupRepo, _ := factory.CreateProductGroupRepository(map[string]interface{}{
"transactionContext": transactionContext,
})
_, productGroupList, err := productGroupRepo.Find(map[string]interface{}{
"companyId": operate.CompanyId,
"orgId": operate.OrgId,
})
if err != nil {
return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
}
//车间名称+/+线别名称+/+工段名称 作为键名
workStationMap := map[string]*domain.WorkStation{}
//车间名称+/+工人名 作为键名
workerMap := map[string][]*domain.User{}
for _, v := range productGroupList {
workStationName := strings.Join([]string{
v.WorkStation.WorkshopName, v.WorkStation.LineName, v.WorkStation.SectionName,
}, "/")
workStationMap[workStationName] = v.WorkStation
for _, vv := range v.GroupMembers {
k := v.WorkStation.WorkshopName + "/" + vv.UserName
isIn := false
for _, vvv := range workerMap[k] {
if vvv.UserId == vv.UserId {
isIn = true
break
}
}
if !isIn {
workerMap[k] = append(workerMap[k], vv)
}
}
}
var attendanceList []*domain.ProductAttendanceRecord
nowTime := time.Now()
//检查导入的数据
for i := range param {
//检查字段值
err := param[i].validField()
if err != nil {
param[i].FailReason = err.Error()
failRows = append(failRows, param[i])
continue
}
//检查日期格式
productDate, err := time.ParseInLocation("2006-01-02", param[i].ProductDate, time.Local)
if err != nil {
param[i].FailReason = "日期格式错误,例 2006-01-02。"
failRows = append(failRows, param[i])
continue
}
//检查类型
attendanceType := 0
// 考勤类型 1.正常 2.支援
if param[i].AttendanceType == "支援" {
attendanceType = 1
} else if param[i].AttendanceType == "正常" {
attendanceType = 2
} else {
param[i].FailReason = "类型内容异常。"
failRows = append(failRows, param[i])
continue
}
//检查上岗时间格式
signIn, err := time.ParseInLocation("15:04:05", param[i].SignIn, time.Local)
if err != nil {
param[i].FailReason = "上岗时间格式错误,例 15:04:05。"
failRows = append(failRows, param[i])
continue
}
signIn = productDate.Add(time.Duration(signIn.Second()) * time.Second)
//检查离岗时间格式
signOut, err := time.ParseInLocation("15:04:05", param[i].SignOut, time.Local)
if err != nil {
param[i].FailReason = "离岗时间格式错误,例 15:04:05。"
failRows = append(failRows, param[i])
continue
}
signOut = productDate.Add(time.Duration(signOut.Second()) * time.Second)
//检查员工姓名
var worker *domain.User
workKey := param[i].WorkshopName + "/" + param[i].WorkerName
if u, ok := workerMap[workKey]; ok {
if len(u) > 1 {
param[i].FailReason = "当前车间存在重复的用户名"
failRows = append(failRows, param[i])
continue
}
worker = u[0]
} else {
param[i].FailReason = "当前车间不存在用户" + param[i].WorkerName
failRows = append(failRows, param[i])
continue
}
//检查工位
var workStation *domain.WorkStation
workStationName := param[i].WorkerName + "/" + param[i].LineName + "/" + param[i].SectionName
if v, ok := workStationMap[workStationName]; ok {
workStation = v
} else {
param[i].FailReason = "车间、线别、工段不存在"
failRows = append(failRows, param[i])
continue
}
//休息时间(小时)
beakTime, err := strconv.ParseFloat(param[i].BreakTime, 64)
if err != nil {
param[i].FailReason = "休息时长填写错误"
failRows = append(failRows, param[i])
continue
}
tempItem := &domain.ProductAttendanceRecord{
ProductAttendanceId: 0,
CompanyId: operate.CompanyId,
OrgId: operate.OrgId,
AttendanceType: attendanceType,
ProductWorker: worker,
WorkStation: workStation,
SignIn: signIn,
SignOut: signOut,
AttendanceStatus: domain.AttendanceAutoApproved, //自动审核
WorkTimeBefore: 0.0,
WorkTimeAfter: 0.0,
CreatedAt: nowTime,
UpdatedAt: nowTime,
DeletedAt: time.Time{},
ProductDate: productDate,
}
//计算工时
workTime := tempItem.ComputeWorkTime(beakTime)
tempItem.WorkTimeAfter = workTime
tempItem.WorkTimeBefore = workTime
attendanceList = append(attendanceList, tempItem)
}
if len(failRows) > 0 {
return failRows, nil
}
attendanceRepo, _ := factory.CreateProductAttendanceRecordRepository(map[string]interface{}{
"transactionContext": transactionContext,
})
for i := range attendanceList {
_, err = attendanceRepo.Save(attendanceList[i])
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return nil, err
}
... ...
... ... @@ -3,10 +3,11 @@ package domain
import (
"errors"
"fmt"
"time"
"github.com/linmadan/egglib-go/utils/xtime"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"time"
)
const (
... ... @@ -230,3 +231,12 @@ func (productAttendanceRecord *ProductAttendanceRecord) AttendanceBreakTime(prod
}
return bt
}
//计算上岗到 离岗之间的工作时间,
//breakTime 休息时间(小时)
func (productAttendanceRecord *ProductAttendanceRecord) ComputeWorkTime(breakTime float64) float64 {
signIn := roundTime(productAttendanceRecord.SignIn)
signOut := roundTime(productAttendanceRecord.SignOut)
wt := utils.Round(signOut.Sub(signIn).Hours()-breakTime, 2)
return roundWorkTime(wt)
}
... ...
... ... @@ -2,14 +2,15 @@ package controllers
import (
"fmt"
"io"
"path/filepath"
"github.com/beego/beego/v2/server/web/context"
"github.com/linmadan/egglib-go/utils/excel"
"github.com/linmadan/egglib-go/web/beego"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/ecelData/command"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/application/ecelData/service"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
"io"
"path/filepath"
)
type ExcelDataController struct {
... ... @@ -36,7 +37,7 @@ func (controller *ExcelDataController) FileImport() {
r io.Reader
ext string
)
//excelService := service.NewExcelDataService(nil)
excelService := service.NewExcelDataService(nil)
r, ext, err = controller.GetFileWithExt()
if err != nil {
controller.Response(nil, err)
... ... @@ -54,6 +55,8 @@ func (controller *ExcelDataController) FileImport() {
// data, err = excelService.ImportCooperationUser(cmd)
//case domain.ImportOrganization:
// data, err = excelService.ImportOrganization(cmd)
case "ImportAttendance":
data, err = excelService.ImportDataAttendance(cmd)
default:
err = fmt.Errorf("导入不存在 Code:%v", cmd.Code)
}
... ...