pg_worker_attendance_report.go 7.0 KB
package domainService

import (
	"fmt"
	"github.com/linmadan/egglib-go/core/application"
	pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/dao"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/repository"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/log"
	"time"
)

type PGWorkerAttendanceReportService struct {
	transactionContext *pgTransaction.TransactionContext
}

// 考勤汇报
func (ptr *PGWorkerAttendanceReportService) Report(cid, oid int, report *domain.DeviceZkTeco) (interface{}, error) {
	var (
		attendanceRecordDao, _        = dao.NewAttendanceRecordDao(ptr.transactionContext)
		attendanceRecordRepository, _ = repository.NewProductAttendanceRecordRepository(ptr.transactionContext)
		productGroupRepository, _     = repository.NewProductGroupRepository(ptr.transactionContext)
		productCalendarRepository, _  = repository.NewProductCalendarRepository(ptr.transactionContext)
		isSignIn                      = true
		record                        *domain.ProductAttendanceRecord
		workStation                   *domain.WorkStation
		attendanceType                int = domain.ParticipateSupport
		worker                        *domain.User
		org                           *domain.Org
	)

	if err := report.Valid(); err != nil {
		return nil, err
	}

	var (
		device    *domain.Device
		err       error
		groupId   = 0
		groupName = ""
	)
	deviceRepository, _ := dao.NewDeviceDao(ptr.transactionContext)
	if device, err = deviceRepository.FindDeviceByDeviceCode(cid, oid, report.Sn); err != nil {
		return nil, err
	}
	workStation = device.WorkStation

	var userService = NewUserService()
	org, err = userService.Organization(oid)
	if err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}

	worker, err = userService.UserByICCode(cid, oid, report.UserNo)
	if err != nil {
		return nil, err
	}

	var productCalendar *domain.ProductCalendar
	productGroup, _ := FindMemberBelongToProductGroup(productGroupRepository, cid, oid, workStation.WorkStationId, worker)
	if productGroup != nil {
		attendanceType = domain.ParticipateNormal
		groupId = productGroup.ProductGroupId
		groupName = productGroup.GroupName
		productCalendar, _ = productCalendarRepository.FindOne(map[string]interface{}{"companyId": cid, "orgId": oid, "workStationId": workStation.WorkStationId})
	}

	beginTime := report.ActionTime.Add(-time.Hour * 16)
	endTime := report.ActionTime
	_, records, _ := attendanceRecordDao.WorkerAttendanceRecords(cid, oid, worker.UserId, "", beginTime, endTime)
	for i := 0; i < len(records); i++ {
		r := records[i]
		if workStation.WorkStationId == r.WorkStation.WorkStationId {
			continue
		}
		if !utils.TimeIsZero(r.SignIn) && utils.TimeIsZero(r.SignOut) {
			if utils.TimeAfterEqual(report.ActionTime, r.SignIn) {
				r.SignOut = report.ActionTime
				r.WorkTimeBefore = r.ComputeWorkTimeBefore(productCalendar)
				log.Logger.Debug(fmt.Sprintf("【考勤汇报】 用户:%v(%v) 在其他工段打卡 下线当前工段:%v 签退 %v", worker.UserName, worker.UserId, r.WorkStation.SectionName, report))
				if _, err = attendanceRecordRepository.Save(r); err != nil {
					return nil, err
				}
			} else {
				log.Logger.Debug(fmt.Sprintf("【考勤汇报】 考勤记录不合法,操作时间小于签到时间 考勤ID:%v  用户:%v  打卡时间:%v", r.ProductAttendanceId, worker.UserId, report.ActionTime))
				return struct{}{}, nil
			}
			break
		}
	}
	for i := 0; i < len(records); i++ {
		r := records[i]
		if workStation.WorkStationId != r.WorkStation.WorkStationId {
			continue
		}
		// 操作时间 < 签到时间
		if utils.TimeAfterEqual(r.SignIn, report.ActionTime) {
			log.Logger.Debug(fmt.Sprintf("【考勤汇报】 考勤记录不合法,操作时间小于签到时间 考勤ID:%v  用户:%v  打卡时间:%v", r.ProductAttendanceId, worker.UserId, report.ActionTime))
			return struct{}{}, nil
		}
		// 存在完整打卡记录
		// 1. 如果在区间内,退出
		if !utils.TimeIsZero(r.SignIn) && !utils.TimeIsZero(r.SignOut) {
			if utils.TimeBeforeEqual(r.SignIn, report.ActionTime) && utils.TimeAfterEqual(r.SignOut, report.ActionTime) {
				log.Logger.Debug(fmt.Sprintf("【考勤汇报】 已存在同一时间段的考勤记录 考勤ID:%v  用户:%v  打卡时间:%v", r.ProductAttendanceId, worker.UserId, report.ActionTime))
				return struct{}{}, nil
			}
			if r.WorkStation.WorkStationId == workStation.WorkStationId && utils.TimeAfterEqual(r.SignOut.Add(time.Minute*5), report.ActionTime) {
				isSignIn = false
				record = r
				log.Logger.Debug(fmt.Sprintf("【考勤汇报】 已存在同一时间段的考勤记录,小于离岗时间5min 考勤ID:%v  用户:%v  打卡时间:%v", r.ProductAttendanceId, worker.UserId, report.ActionTime))
				break
			}
			continue
		}
		// 存在未结束的打卡记录
		// 1.满足条件-签退
		if !utils.TimeIsZero(r.SignIn) && utils.TimeIsZero(r.SignOut) {
			// 五分钟内重复打卡不算数
			if r.SignIn.Add(time.Minute * 5).After(report.ActionTime) {
				log.Logger.Debug(fmt.Sprintf("【考勤汇报】 打卡未满五分钟 考勤ID:%v  用户:%v  打卡时间:%v", r.ProductAttendanceId, worker.UserId, report.ActionTime))
				return struct{}{}, nil
			}
			if utils.TimeBeforeEqual(r.SignIn, report.ActionTime) {
				isSignIn = false
				record = r
				break
			}
		}
	}

	if isSignIn || record == nil {
		record = &domain.ProductAttendanceRecord{
			CompanyId:      cid,
			OrgId:          oid,
			AttendanceType: attendanceType,
			ProductWorker:  worker,
			WorkStation:    workStation,
			SignIn:         report.ActionTime,
			//SignOut:          cmd.SignOut,
			AttendanceStatus: domain.AttendanceNotApprove,
			WorkTimeBefore:   0,
			WorkTimeAfter:    0,
			CreatedAt:        time.Now(),
			UpdatedAt:        time.Now(),
			Ext: domain.NewExt(org.OrgName).WithAttendanceExt(&domain.ProductAttendanceRecordExt{
				GroupName:      groupName,
				ProductGroupId: groupId,
			}),
		}
		record.SetProductTimeByProductCalendar(productCalendar)
		log.Logger.Debug(fmt.Sprintf("【考勤汇报】 用户:%v(%v) 签到 %v", worker.UserName, worker.UserId, report))
	} else {
		record.SignOut = report.ActionTime
		record.WorkTimeBefore = record.ComputeWorkTimeBefore(productCalendar)
		log.Logger.Debug(fmt.Sprintf("【考勤汇报】 用户:%v(%v) 签退 %v", worker.UserName, worker.UserId, report))
	}

	if _, err = attendanceRecordRepository.Save(record); err != nil {
		return nil, err
	}

	return struct{}{}, nil
}

func NewPGWorkerAttendanceReportService(transactionContext *pgTransaction.TransactionContext) (*PGWorkerAttendanceReportService, error) {
	if transactionContext == nil {
		return nil, fmt.Errorf("transactionContext参数不能为nil")
	} else {
		return &PGWorkerAttendanceReportService{
			transactionContext: transactionContext,
		}, nil
	}
}