fonchain-fiee/pkg/service/cron.go
2025-02-19 14:24:15 +08:00

517 lines
16 KiB
Go

package service
import (
"context"
"dubbo.apache.org/dubbo-go/v3/common/logger"
"dubbo.apache.org/dubbo-go/v3/config"
"errors"
"fmt"
"github.com/fonchain_enterprise/fonchain-main/api/account"
"github.com/fonchain_enterprise/fonchain-main/api/artwork"
"github.com/fonchain_enterprise/fonchain-main/api/collections"
"github.com/fonchain_enterprise/fonchain-main/api/employee"
"github.com/fonchain_enterprise/fonchain-main/api/oa"
"github.com/fonchain_enterprise/fonchain-main/api/order"
backendSeries "github.com/fonchain_enterprise/fonchain-main/api/series"
"github.com/fonchain_enterprise/fonchain-main/api/shopbrand"
config1 "github.com/fonchain_enterprise/fonchain-main/pkg/config"
"github.com/fonchain_enterprise/fonchain-main/pkg/e"
"github.com/fonchain_enterprise/fonchain-main/pkg/model"
"github.com/fonchain_enterprise/fonchain-main/pkg/model/vo/turnstile"
"github.com/fonchain_enterprise/fonchain-main/pkg/utils"
"github.com/google/uuid"
"github.com/robfig/cron/v3"
"os"
"path"
"strconv"
"strings"
"sync"
"time"
)
func Task(c *cron.Cron) {
/*if config.GetConsumerService("ArtworkClientImpl") != nil {
_, _ = c.AddFunc("@every 5m", CheckCopyright)
}*/
//发送周报短信
if config.GetConsumerService("OrderClientImpl") != nil {
_, _ = c.AddFunc("0 15 * * 0", SendAReportToBoss)
}
//重启打卡机设备
if config.GetConsumerService("AccountClientImpl") != nil {
_, _ = c.AddFunc("0 0 4 * *", RebootClockDevice)
}
//更新考勤组绑定
//if config.GetConsumerService("EmployeeClientImpl") != nil {
// _, _ = c.AddFunc("1 4 * * *", UpdateAttendanceRegularly)
//}
//更新在职状态
if config.GetConsumerService("EmployeeClientImpl") != nil {
_, _ = c.AddFunc("0 23 * * *", UpdateWorkingStatus)
}
//创建到期消息提醒
if config.GetConsumerService("EmployeeClientImpl") != nil {
_, _ = c.AddFunc("0 1 * * *", CreateAReminderMessage)
}
//创建假期余额
if config.GetConsumerService("EmployeeClientImpl") != nil {
_, _ = c.AddFunc("0 0 1 1 *", CreateLeaveBalance)
//_, _ = c.AddFunc("10 10 * * *", CreateLeaveBalance)
}
//添加补充年假
if config.GetConsumerService("EmployeeClientImpl") != nil {
_, _ = c.AddFunc("1 0 * * *", AddSupplementaryAnnualLeave)
}
/*if config.GetConsumerService("SeriesClientImpl") != nil && config.GetConsumerService("BrandClientImpl") != nil && config.GetConsumerService("CollectionsClientImpl") != nil {
_, _ = c.AddFunc("@every 5m", CheckSeries)
}*/
if err := DelayDeleteFileTask.AddTimerTask(c); err != nil {
panic("添加定时任务失败,错误:" + err.Error())
}
if config.GetConsumerService("AccountClientImpl") != nil && config.GetConsumerService("ApprovalClientImpl") != nil {
_, _ = c.AddFunc("* 9 * * *", SendPromotionMsg) // 23:50 执行
}
//更新打卡机用户状态
if config.GetConsumerService("AccountClientImpl") != nil {
_, _ = c.AddFunc("0 12 * * 1", UpdateClockUserStatus)
}
}
func UpdateClockUserStatus() {
fmt.Println("更新打卡机用户状态")
list, err := AccountProvider.ClockDeviceBatchList(context.Background(), &account.ClockBatchBindRequest{})
if err != nil {
fmt.Println("查询打卡机用户失败")
return
}
userList := []*account.ClockUserDeviceBatch{}
//整合数据
if len(list.Data) == 0 {
return
}
for _, i := range list.Data {
if i.WorkStatus == "notactive" {
continue
}
userList = append(userList, &account.ClockUserDeviceBatch{
UserId: i.UserId,
DeviceId: i.DeviceId,
JobNum: i.JobNum,
DeviceNum: i.DeviceNum,
DeviceName: i.DeviceName,
WorkStatus: i.WorkStatus,
})
}
data, clockDeviceBatchUntie := DeviceNumToJobNums(userList)
//下发数据
err = DelBatchDeviceAccount(data)
if err != nil {
fmt.Println("下发数据失败", err)
}
//删除关联
_, err = AccountProvider.ClockDeviceBatchUntie(context.Background(), clockDeviceBatchUntie)
if err != nil {
return
}
return
}
func DelBatchDeviceAccount(req map[string][]uint64) (err error) {
for deviceNum, jobNums := range req {
uuidObj := uuid.New()
stringSlice := make([]string, len(jobNums))
for i, num := range jobNums {
stringSlice[i] = strconv.FormatUint(num, 10)
}
synReq := turnstile.TurnStile{
Cmd: "to_device",
From: "Message1",
To: deviceNum,
Extra: uuidObj.String(),
Data: turnstile.TurnData{
Cmd: e.DelMultiUser,
UserIds: stringSlice,
UserType: 0,
},
}
err, _ = utils.IssueTheCardPunchData(synReq, deviceNum, uuidObj)
if err != nil {
return errors.New("下发数据失败")
}
}
return err
}
func DeviceNumToJobNums(data []*account.ClockUserDeviceBatch) (deviceNum map[string][]uint64, ClockDeviceBatchUntie *account.ClockBatchBindRequest) {
deviceNumToJobNums := make(map[string][]uint64)
ClockDeviceBatchUntie = &account.ClockBatchBindRequest{}
for _, batch := range data {
ClockDeviceBatchUntie.UserId = append(ClockDeviceBatchUntie.UserId, batch.UserId)
if _, exists := deviceNumToJobNums[batch.DeviceNum]; exists {
deviceNumToJobNums[batch.DeviceNum] = append(deviceNumToJobNums[batch.DeviceNum], batch.UserId)
} else {
deviceNumToJobNums[batch.DeviceNum] = []uint64{batch.UserId}
}
}
// 提取所有设备号并去重
deviceIdSet := make(map[uint64]bool)
for _, batch := range data {
// 检查设备 ID 是否已存在,去重
if !deviceIdSet[batch.DeviceId] {
ClockDeviceBatchUntie.DeviceId = append(ClockDeviceBatchUntie.DeviceId, batch.DeviceId)
deviceIdSet[batch.DeviceId] = true
}
}
return deviceNumToJobNums, ClockDeviceBatchUntie
}
// AddSupplementaryAnnualLeave 添加补充年假
func AddSupplementaryAnnualLeave() {
if time.Now().Month() == time.January && time.Now().Day() == 1 {
return
}
WorkingConditionId, err := GrpcEmployeeProvider.SearchDictionaryList(context.Background(), &employee.SearchDictionaryRequest{
Name: "在职",
Tag: "workingCondition",
})
if err != nil || WorkingConditionId.WorkingCondition == nil {
fmt.Println("查询工作状态失败!")
return
}
currentMonthDay := time.Now().Format("01-02")
// 根据在职状态和入职日期模糊查询员工档案
employeeFileList, err := GrpcEmployeeProvider.FindEmployeeFileList(context.Background(), &employee.FindEmployeeFileListRequest{
WorkingConditionId: WorkingConditionId.WorkingCondition[0].Id,
BlurDateOfEntry: currentMonthDay,
})
if err != nil || len(employeeFileList.EmployeeFileList) == 0 {
fmt.Println("无人员需要添加假期余额")
return
}
for _, i := range employeeFileList.EmployeeFileList {
replenishment := supplementaryLeave(i.DateOfEntry)
if replenishment == 0 {
continue
}
fmt.Printf("用户 %v 的入职日期为 %v,需要补充年假 %v 天\n", i.UserId, i.DateOfEntry, replenishment)
_, err = GrpcOAImpl.ModifyTheLeaveBalance(context.Background(), &oa.ModifyTheLeaveBalanceReq{
StaffUid: i.UserId,
LeaveType: "annualLeave",
Movement: 1,
Year: int32(time.Now().Year()),
Days: float32(replenishment),
})
if err != nil {
fmt.Printf("更新用户 %v 的假期余额失败: %v\n", i.UserId, err)
}
}
}
// CreateLeaveBalance 创建假期余额
func CreateLeaveBalance() {
WorkingConditionId, err := GrpcEmployeeProvider.SearchDictionaryList(context.Background(), &employee.SearchDictionaryRequest{
Name: "在职",
Tag: "workingCondition",
})
if err != nil || WorkingConditionId.WorkingCondition == nil {
fmt.Println("查询工作状态失败!")
return
}
employeeFileList, err := GrpcEmployeeProvider.FindEmployeeFileList(context.Background(), &employee.FindEmployeeFileListRequest{
WorkingConditionId: WorkingConditionId.WorkingCondition[0].Id,
})
if err != nil || len(employeeFileList.EmployeeFileList) == 0 {
fmt.Println("定时创建假期余额失败!")
return
}
for _, i := range employeeFileList.EmployeeFileList {
departmentPosition := []*oa.LeaveBalancePosition{}
if i.DepartmentPostList != nil {
for _, s := range i.DepartmentPostList {
departmentPosition = append(departmentPosition, &oa.LeaveBalancePosition{
DepartmentUID: strconv.FormatUint(s.DepartmentId, 10),
DepartmentName: s.DepartmentName,
PositionUID: strconv.FormatUint(s.PostId, 10),
PositionName: s.PostName,
})
}
}
annualLeave := AnnualLeaveByYearsOfService(i.DateOfEntry)
_, err = GrpcOAImpl.SaveLeaveBalance(context.Background(), &oa.LeaveBalance{
StaffUID: i.UserId,
StaffNum: i.JobNumber,
StaffName: i.Name,
Year: int32(time.Now().Year()),
Positions: departmentPosition,
AnnualLeave: float32(annualLeave),
HasParentalLeave: 1,
HasNursingLeave: 1,
EmployeeFileId: i.Id,
})
}
return
}
// 补充年假天数
func supplementaryLeave(DateOfEntry string) int {
joinDate, err := time.Parse("2006-01-02", DateOfEntry)
if err != nil {
fmt.Println("入职日期解析错误:", err)
return 0
}
currentDate := time.Now()
yearsOfService := int(currentDate.Sub(joinDate).Hours() / 24 / 365)
//if !isEligibleForSupplementaryLeave(joinDate, currentDate) {
// return 0
//}
supplementaryLeaveDays := 0
switch yearsOfService {
case 1:
supplementaryLeaveDays = 5
case 5:
supplementaryLeaveDays = 2
case 10:
supplementaryLeaveDays = 3
case 20:
supplementaryLeaveDays = 5
default:
return 0
}
// 计算补充年假
endOfYear := time.Date(currentDate.Year(), 12, 31, 0, 0, 0, 0, currentDate.Location())
daysUntilEndOfYear := endOfYear.Sub(currentDate).Hours() / 24
supplementaryLeave := (daysUntilEndOfYear / 365) * float64(supplementaryLeaveDays)
return int(supplementaryLeave)
}
// 工龄年假天数
func AnnualLeaveByYearsOfService(DateOfEntry string) int {
joinDate, err := time.Parse("2006-01-02", DateOfEntry)
if err != nil {
fmt.Println("入职日期解析错误:", err)
return 0
}
currentDate := time.Now()
yearsOfService := int(currentDate.Sub(joinDate).Hours() / 24 / 365)
switch {
case yearsOfService < 1:
return 0
case yearsOfService < 5:
return 5
case yearsOfService < 10:
return 7
case yearsOfService < 20:
return 10
default:
return 15
}
}
// 检查是否符合补充年假的条件
func isEligibleForSupplementaryLeave(joinDate, currentDate time.Time) bool {
yearsOfService := int(currentDate.Sub(joinDate).Hours() / 24 / 365)
anniversaryDate := joinDate.AddDate(yearsOfService, 0, 0)
return currentDate.Equal(anniversaryDate)
}
func UpdateAttendanceRegularly() {
_, err := GrpcEmployeeProvider.UpdateAttendanceRegularly(context.Background(), &employee.EmptyStructure{})
if err != nil {
fmt.Println("定时更新考勤组失败!")
return
}
return
}
func UpdateWorkingStatus() {
_, err := GrpcEmployeeProvider.UpdateWorkingStatus(context.Background(), &employee.EmptyStructure{})
if err != nil {
fmt.Println("定时更新员工工作状态失败!")
return
}
return
}
func CreateAReminderMessage() {
_, err := GrpcEmployeeProvider.CreateAReminderMessage(context.Background(), &employee.IdUnifiedReturn{})
if err != nil {
fmt.Println("创建到期消息提醒失败!")
return
}
fmt.Println("----------------创建到期消息提醒成功-------------------")
return
}
func RebootClockDevice() {
var batch account.ClockBatchBindRequest
devRes, err := AccountProvider.ClockDeviceBatchList(context.Background(), &batch) //获取设备列表
if err != nil {
return
}
for _, i := range devRes.Data {
uuidObj := uuid.New()
fmt.Println(uuidObj.String())
synReq := turnstile.TurnStile{
Cmd: "to_device",
From: "Message1",
To: i.DeviceNum,
Extra: uuidObj.String(),
Data: turnstile.TurnData{
Cmd: e.Reboot,
},
}
err, _ := utils.IssueTheCardPunchData(synReq, i.DeviceNum, uuidObj)
if err != nil {
return
}
}
}
func SendAReportToBoss() {
now := time.Now()
weekday := now.Weekday()
lastMonday := now.AddDate(0, 0, -int(weekday)+1-6)
lastSunday := now.AddDate(0, 0, -int(weekday)+7-6)
host := ""
if config1.Env == "prod" {
host = "https://sale.fontree.cn"
} else {
host = "https://sellertest.szjixun.cn"
}
lastStart := lastMonday.Format("2006-01-02")
lastEnd := lastSunday.Format("2006-01-02")
telList, err := OrderProvider.GetSmsConfig(context.Background(), &order.SmsConfigRequest{
Position: "boss",
})
if err != nil || len(telList.SmsConfig) == 0 {
fmt.Println("获取手机号失败!")
return
}
for _, i := range telList.SmsConfig {
infoUrl := fmt.Sprintf("%v/#/pages/examine/examine?startDate=%v&endDate=%v&uid=%v&", host, lastStart, lastEnd, i.Id)
url := lastStart + "||" + lastEnd + "||" + infoUrl
_, err1 := AccountProvider.SendExCustomMsg(context.Background(), &account.SendCustomMsgRequest{
TelNum: i.TelNum,
Url: url,
MId: 145217, //模板Id
SigNo: 159789, //签名id
})
if err1 != nil {
fmt.Println("短信发送失败!")
return
}
}
return
}
// CheckCopyright 检验版权文件
func CheckCopyright() {
logger.Error("MoveCopyrightFile start", time.Now().Format("2006-01-02 15:04:05"))
files, err := os.ReadDir(model.CopyrightDir)
if err != nil {
logger.Error("MoveCopyrightFile err", err)
return
}
//utils.CheckDirPath(model.CopyrightDir+"/old", true)
var lock sync.RWMutex
lock.Lock()
defer lock.Unlock()
for _, v := range files {
if !v.IsDir() {
if path.Ext(v.Name()) == ".psb" {
var req artwork.UpdateCrHashByTfnumRequest
var temp artwork.UpdateCrHashByTfnumRequest_Info
filePath := model.CopyrightDir + "/" + v.Name()
temp.Tfnum = strings.TrimSuffix(v.Name(), path.Ext(v.Name()))
temp.CopyrightHash, _ = utils.GenerateSHA256Hash(filePath)
if temp.Tfnum != "" && temp.CopyrightHash != "" {
req.Data = append(req.Data, &temp)
}
_, err = GrpcArtworkImpl.UpdateCrHashByTfnum(context.Background(), &req)
if err != nil {
logger.Errorf("GrpcArtworkImpl UpdateCopyrightHash err", err)
_ = os.Rename(filePath, filePath+"_err")
return
}
_ = os.Rename(filePath, filePath+"_use")
logger.Error("MoveCopyrightFile end", &temp)
}
}
}
//if len(req.Data) > 0 {
// _, err = GrpcArtworkImpl.UpdateCrHashByTfnum(context.Background(), &req)
// if err != nil {
// logger.Errorf("GrpcArtworkImpl UpdateCopyrightHash err", err)
// return
// }
//}
}
// CheckSeries 检测系列
func CheckSeries() {
var req backendSeries.CheckSeriesReq
resp, err := GrpcBackendSeriesImpl.CheckSeries(context.Background(), &req)
if err != nil {
fmt.Println(err.Error())
return
}
if len(resp.Data) > 0 {
// 请求brand
var brandReq shopbrand.BrandListreq
for _, v := range resp.Data {
brandReq.BrandUid = append(brandReq.BrandUid, v.BrandId)
}
brandList, err := GrpcShopBrandImpl.BrandList(context.Background(), &brandReq)
logger.Info("brandList CheckSeries", brandList, "ntfReq", brandList.Data)
if err != nil {
logger.Error("brandList err", err)
return
}
var brandDataMap map[string]shopbrand.BrandListres_Info = map[string]shopbrand.BrandListres_Info{}
if len(brandList.Data) > 0 {
for _, v := range brandList.Data {
brandDataMap[v.BrandUid] = shopbrand.BrandListres_Info{
BrandUid: v.BrandUid,
Address: v.Address,
}
}
}
//得到hash 请求藏品服,上链
var ntfReq collections.StoreNFTList
for _, v := range resp.Data {
var ntfInfo collections.StoreNFTInfo
ntfInfo.SeriesUID = v.SeriesUuid
ntfInfo.BrandHash = brandDataMap[v.BrandId].Address
ntfReq.NFT = append(ntfReq.NFT, &ntfInfo)
}
ntfResp, err := GrpcCollectionImpl.StoreNFT(context.Background(), &ntfReq)
logger.Info("ntfResp CheckSeries", ntfResp, "ntfReq", ntfReq.NFT)
if err != nil {
logger.Errorf("HandShelf StoreNFT err", err)
err = errors.New(e.GetMsg(e.ErrorStoreNTF))
return
}
if len(ntfResp.SeriesUID) == len(ntfReq.NFT) {
return
}
failSeriesUuid := make(map[string]struct{}, len(ntfResp.SeriesUID))
if len(ntfResp.SeriesUID) > 0 {
for _, seriesUuid := range ntfResp.SeriesUID {
failSeriesUuid[seriesUuid] = struct{}{}
}
}
for _, v := range ntfReq.NFT {
_, ok := failSeriesUuid[v.SeriesUID]
if !ok {
var seriesReq backendSeries.UpdateSeriesChainReq
seriesReq.SeriesUuid = v.SeriesUID
seriesReq.ChainStatus = 1
_, _ = GrpcBackendSeriesImpl.UpdateSeriesChain(context.Background(), &seriesReq)
}
}
}
return
}