From cac7321819e86249c07934d9e37ecf84acbe024c Mon Sep 17 00:00:00 2001 From: herenshan112 Date: Fri, 14 Jul 2023 10:52:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=87=91=E8=9D=B6=E5=AF=B9?= =?UTF-8?q?=E7=85=A7HR=E8=A1=8C=E6=94=BF=E7=BB=84=E7=BB=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../administrativeorganization/govcont.go | 114 ++++- .../administrativeorganization/type.go | 8 + api/version1/personnelapi/peoplestatistics.go | 470 ++++++++++++++++++ api/version1/personnelapi/staffarchives.go | 2 +- api/version1/personnelapi/type.go | 48 ++ api/version1/shiyan/shiyan.go | 13 +- apirouter/organization/organization_group.go | 2 + apirouter/personnel/people.go | 6 + models/hrmodels/educational_structure.go | 59 +++ models/hrmodels/emp_onb_arc.go | 73 +++ models/hrmodels/user_emp.go | 65 +++ overall/overallhandle/overall_handle.go | 206 +++++++- overall/overallhandle/type.go | 5 + 13 files changed, 1049 insertions(+), 22 deletions(-) create mode 100644 api/version1/personnelapi/peoplestatistics.go create mode 100644 models/hrmodels/educational_structure.go create mode 100644 models/hrmodels/emp_onb_arc.go create mode 100644 models/hrmodels/user_emp.go diff --git a/api/version1/administrativeorganization/govcont.go b/api/version1/administrativeorganization/govcont.go index 8d1e24a..6f2103e 100644 --- a/api/version1/administrativeorganization/govcont.go +++ b/api/version1/administrativeorganization/govcont.go @@ -1093,10 +1093,10 @@ func (o *OrganizationApi) BasisOrgObtainSonOrgAndMan(c *gin.Context) { idInt, _ := strconv.ParseInt(requestData.Id, 10, 64) idList = []int64{idInt} - if idInt != 309 { + if idInt != 313 { err = orgCont.GetCont(map[string]interface{}{"id": idInt}) parenAry.SunList = append(parenAry.SunList, idInt) - parenAry.GetAllParentOrg(idInt, 3) + parenAry.GetAllParentOrg(idInt, 2) } else { } @@ -1132,7 +1132,7 @@ func (o *OrganizationApi) BasisOrgObtainSonOrgAndMan(c *gin.Context) { var orgAndPeopleListCont empowerSyncDepartMan //启用协程结构体 synPro.Add(1) - go orgAndPeopleListCont.BasisOrgDirectOrg(isNotIn, idList, 3) //获取行政组织 + go orgAndPeopleListCont.BasisOrgDirectOrg(isNotIn, idList, 2) //获取行政组织 synPro.Add(1) go orgAndPeopleListCont.GetPeopleListIng(isNotIn, idList) //获取人员 synPro.Wait() @@ -1776,3 +1776,111 @@ func (o *OrganizationApi) NewEiteGovStateOrDel(c *gin.Context) { overallhandle.Result(0, err, c) } + +/* +* +@ 作者: 秦东 +@ 时间: 2023-07-01 09:13:10 +@ 功能: 获取行政组织直接下属 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (o *OrganizationApi) GetOrgChiled(c *gin.Context) { + var requestData overallhandle.PublicId[int64] + err := c.ShouldBindJSON(&requestData) + if err != nil { + overallhandle.Result(100, err, c) + return + } + if requestData.Id == 0 { + overallhandle.Result(1, err, c, "请提交行政组织ID") + return + } + var orgList []models.AdministrativeOrganization + err = overall.CONSTANT_DB_HR.Where("`state` = 1 AND `superior` = ?", requestData.Id).Find(&orgList).Error + if err != nil { + overallhandle.Result(107, err, c) + return + } + var sendList []AdminOrgSend + for _, v := range orgList { + var sendCont AdminOrgSend + sendCont.Id = v.Id // + sendCont.Number = v.Number //行政编码"` + sendCont.Name = v.Name //组织名称"` + sendCont.Superior = v.Superior //上级ID"` + sendCont.OrganizationType = v.OrganizationType //行政组织类型"` + sendCont.Abbreviation = v.Abbreviation //行政组织简称"` + sendCont.Time = v.Time //创建时间"` + sendCont.State = v.State //状态(1:启用;2:禁用;3:删除)"` + sendCont.WechatOrganizationId = v.WechatOrganizationId //20微信组织架构对照码"` + sendCont.SuperiorSun = v.SuperiorSun //级联ID"` + sendCont.Schoole = v.Schoole //原知行学院对照码"` + sendCont.KingdeeId = v.KingdeeId //金蝶对照ID"` + sendCont.IsPower = v.IsPower // 是否为实权部门"` + sendCont.Sort = v.Sort //是否为实权部门"` + sendCont.IsChild = judgeIsChild(v.Id) + sendList = append(sendList, sendCont) + } + sendOrgList := overallhandle.MapOut() + sendOrgList["list"] = sendList + userKey := c.Request.Header.Get("user-key") + myCont, myErr := overallhandle.GetCreetUserCont(userKey) + if myErr == nil { + sendOrgList["current"] = myCont.Company + } else { + sendOrgList["current"] = 309 + } + var parenAry overallhandle.AllSunList[int64] + parenAry.SunList = append(parenAry.SunList, requestData.Id) + parenAry.GetAllParentOrg(requestData.Id, 2) + fmt.Printf("父级--->%v\n", parenAry.SunList) + var orgAndPeopleListTitleCont empowerSynces //启用协程结构体 + synProes.Add(1) + go orgAndPeopleListTitleCont.BasisOrgDirectOrgIng(parenAry.SunList) //获取行政组织 + synProes.Wait() + orgTitleList := orgAndPeopleListTitleCont.readDataLock() + sort.SliceStable(orgTitleList, func(i, j int) bool { + return orgTitleList[i].Sort < orgTitleList[j].Sort + }) + var tabval []TitleDepartmentsCont + if len(parenAry.SunList) > 0 && requestData.Id != 313 { + + for _, ov := range orgTitleList { + var titleDepartCont TitleDepartmentsCont + titleDepartCont.DepartmentId = ov.Id //行政组织ID + titleDepartCont.Id = ov.Id //行政组织ID + titleDepartCont.DepartmentKey = ov.Number //行政组织编码 + titleDepartCont.DepartmentName = ov.Name //行政组织名称 + titleDepartCont.ParentId = ov.Superior //上级ID + titleDepartCont.DepartmentNames = ov.Name //行政组织别名 + tabval = append(tabval, titleDepartCont) + } + } + sendOrgList["tabval"] = tabval + + overallhandle.Result(0, sendOrgList, c) +} + +// 判断是否有子集 +func judgeIsChild(orgId int64) (isTrue bool) { + isTrue = false + var countid int64 + err := overall.CONSTANT_DB_HR.Model(&models.AdministrativeOrganization{}).Where("`state` = 1 AND `superior` = ?", orgId).Count(&countid).Error + if err != nil { + return + } + if countid > 0 { + isTrue = true + } + return +} diff --git a/api/version1/administrativeorganization/type.go b/api/version1/administrativeorganization/type.go index aec7357..97c03a2 100644 --- a/api/version1/administrativeorganization/type.go +++ b/api/version1/administrativeorganization/type.go @@ -528,3 +528,11 @@ type PublicAddPostCont struct { Superior int64 `json:"superior"` //上级岗位 Incharge string `json:"incharge"` // 1:责任岗;2:非责任岗 } + +/* +行政组织 +*/ +type AdminOrgSend struct { + models.AdministrativeOrganization + IsChild bool `json:"ischild"` +} diff --git a/api/version1/personnelapi/peoplestatistics.go b/api/version1/personnelapi/peoplestatistics.go new file mode 100644 index 0000000..40af10b --- /dev/null +++ b/api/version1/personnelapi/peoplestatistics.go @@ -0,0 +1,470 @@ +package personnelapi + +import ( + "fmt" + "hr_server/models" + "hr_server/models/hrmodels" + "hr_server/overall" + "hr_server/overall/overallhandle" + "time" + + "github.com/gin-gonic/gin" +) + +/* +* +@ 作者: 秦东 +@ 时间: 2023-06-29 15:10:35 +@ 功能: 离职率 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (s *StaffApi) DimissionRate(c *gin.Context) { + var requestData TurnoverRate + err := c.ShouldBindJSON(&requestData) + if err != nil { + requestData.Id = 313 + } + if requestData.Id == 0 { + requestData.Id = 313 + } + currentTime := time.Now().Unix() + statisticalTime := currentTime + if requestData.Time != "" { + var timeCont overallhandle.DateTimeTotimes + timeCont.BaisStrToTime(requestData.Time) + statisticalTime = timeCont.AllTime + } + //行政组织 + var orgList []models.AdministrativeOrganization + err = overall.CONSTANT_DB_HR.Model(&models.AdministrativeOrganization{}).Select("`id`,`name`").Where("`state` = 1 AND `superior` = ?", requestData.Id).Order("`sort` ASC").Find(&orgList).Error + if err != nil { + overallhandle.Result(107, err, c) + return + } + currentYear := overallhandle.ComputingTime(statisticalTime, 1) + currentMonths := overallhandle.ComputingTime(statisticalTime, 3) + // var i int64 + if currentYear != overallhandle.ComputingTime(currentTime, 1) { + currentMonths = 12 + } + var calRateCont CalTurRateContBlack + calRateCont.CurrentOrgId = requestData.Id + for _, v := range orgList { //行政组织 + calRateCont.Dfg(currentYear, currentMonths, v) + } + fmt.Printf("行政组织总数----->%v----->%v\n", len(orgList), len(calRateCont.List)) + overallhandle.Result(0, calRateCont, c) +} + +func (c *CalTurRateContBlack) Dfg(years, months int64, orgCont models.AdministrativeOrganization) { + // defer synPro.Done() + var contData SendCalTurRateCont + contData.OrgId = orgCont.Id + contData.OrgName = orgCont.Name + var sunAry overallhandle.AllSunList[int64] + sunAry.GetAllSunOrg(orgCont.Id) + + var sumPeople int64 + overall.CONSTANT_DB_HR.Model(&models.PersonArchives{}).Select("`id`").Where("admin_org IN ? AND emp_type BETWEEN ? AND ?", sunAry.SunList, 1, 10).Count(&sumPeople) + + var i int64 + for i = 1; i <= months; i++ { + var timeCont overallhandle.DateTimeTotimes + timeCont.BaisStrToTime(fmt.Sprintf("%v-%v-01 00:00:00", years, i)) + // fmt.Printf("时间--->%v\n", timeCont.Time) + hjsdk := overallhandle.UnixTimeToDay(timeCont.AllTime, 14) + startTime, endTime := overallhandle.GetAppointMonthStarAndEndTimeEs(hjsdk) + var reatCount int64 + overall.CONSTANT_DB_HR.Model(&hrmodels.UserEmp{}).Select("`id`").Where("admin_org IN ? AND leave_date BETWEEN ? AND ?", sunAry.SunList, startTime, endTime).Count(&reatCount) + beiChuShu := sumPeople + reatCount + if beiChuShu == 0 { + contData.Odds = append(contData.Odds, 0) + } else { + + reatVal := overallhandle.DecimalEs((float64(reatCount)/float64(beiChuShu))*100, 3) + contData.Odds = append(contData.Odds, reatVal) + } + } + c.List = append(c.List, contData) +} + +/* +* +@ 作者: 秦东 +@ 时间: 2023-06-29 16:10:50 +@ 功能: 根据行政组织计算时间内的离职率 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (c *CalTurRateCont) CalculateTurnoverRate(years, months int64, orgCont models.AdministrativeOrganization) { + // defer synPro.Done() + var calCont CalculateTurnoverRateCont + calCont.OrgId = orgCont.Id + calCont.OrgName = orgCont.Name + calCont.Months = months + calCont.Odds = months + c.List = append(c.List, calCont) +} + +/* +* +@ 作者: 秦东 +@ 时间: 2023-07-01 09:36:07 +@ 功能: 获取单一行政组织离职率 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (s *StaffApi) GetOenOrgDimRate(c *gin.Context) { + userKey := c.Request.Header.Get("user-key") + myCont, myErr := overallhandle.GetCreetUserCont(userKey) + var requestData TurnoverRate + err := c.ShouldBindJSON(&requestData) + if err != nil { + + if myErr != nil { + requestData.Id = 309 + } else { + requestData.Id = myCont.Company + } + } + if requestData.Id == 0 { + if myErr != nil { + requestData.Id = 309 + } else { + requestData.Id = myCont.Company + } + } + fmt.Printf("获得行政组织--->%v\n--->%v\n--->%v\n", userKey, myCont, requestData) + + currentTime := time.Now().Unix() + statisticalTime := currentTime + if requestData.Time != "" { + var timeCont overallhandle.DateTimeTotimes + timeCont.BaisStrToTime(requestData.Time) + statisticalTime = timeCont.AllTime + } + //行政组织 + var orgList []models.AdministrativeOrganization + err = overall.CONSTANT_DB_HR.Model(&models.AdministrativeOrganization{}).Select("`id`,`name`").Where("`state` = 1 AND `superior` = ?", requestData.Id).Order("`sort` ASC").Find(&orgList).Error + if err != nil { + overallhandle.Result(107, err, c) + return + } + currentYear := overallhandle.ComputingTime(statisticalTime, 1) + currentMonths := overallhandle.ComputingTime(statisticalTime, 3) + // var i int64 + if currentYear != overallhandle.ComputingTime(currentTime, 1) { + currentMonths = 12 + } + var calRateCont CalTurRateContBlack + calRateCont.CurrentOrgId = requestData.Id + for _, v := range orgList { //行政组织 + calRateCont.Dfg(currentYear, currentMonths, v) + } + fmt.Printf("行政组织总数----->%v----->%v\n", len(orgList), len(calRateCont.List)) + overallhandle.Result(0, calRateCont, c) +} + +/* +* +@ 作者: 秦东 +@ 时间: 2023-07-01 14:08:40 +@ 功能: 获取公司指定年月的离职率 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (s *StaffApi) GetOrgTimeRate(c *gin.Context) { + userKey := c.Request.Header.Get("user-key") + myCont, myErr := overallhandle.GetCreetUserCont(userKey) + var requestData TurnoverRate + err := c.ShouldBindJSON(&requestData) + if err != nil { + if myErr != nil { + requestData.Id = 309 + } else { + requestData.Id = myCont.Company + } + } + if requestData.Id == 0 { + if myErr != nil { + requestData.Id = 309 + } else { + requestData.Id = myCont.Company + } + } + //行政组织 + var orgList []models.AdministrativeOrganization + err = overall.CONSTANT_DB_HR.Model(&models.AdministrativeOrganization{}).Select("`id`,`name`").Where("`state` = 1 AND `superior` = ?", requestData.Id).Order("`sort` ASC").Find(&orgList).Error + if err != nil { + overallhandle.Result(107, err, c) + return + } + + currentTime := time.Now().Unix() + hjsdk := overallhandle.UnixTimeToDay(currentTime, 14) + startTime, endTime := overallhandle.GetAppointMonthStarAndEndTimeEs(hjsdk) + if requestData.Time != "" { + var timeCont overallhandle.DateTimeTotimes + timeCont.BaisStrToTime(requestData.Time) + fmt.Printf("时间--->%v\n--->%v\n", requestData.Time, timeCont.Time) + hjsdks := overallhandle.UnixTimeToDay(timeCont.AllTime, 14) + fmt.Printf("时间--222->%v\n", hjsdks) + startTime, endTime = overallhandle.GetAppointMonthStarAndEndTimeEs(hjsdks) + } + var calRateCont SendPicRateInfo + calRateCont.CurrentOrgId = requestData.Id + for _, v := range orgList { //行政组织 + calRateCont.MonthsRate(startTime, endTime, v) + } + overallhandle.Result(0, calRateCont, c) +} + +/* +* +@ 作者: 秦东 +@ 时间: 2023-07-01 14:17:14 +@ 功能: 计算指定月份离职率 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (c *SendPicRateInfo) MonthsRate(startTime, endTime int64, orgCont models.AdministrativeOrganization) { + var contData SendPicRateCont + contData.OrgId = orgCont.Id + contData.OrgName = orgCont.Name + var sunAry overallhandle.AllSunList[int64] + sunAry.GetAllSunOrg(orgCont.Id) + + var sumPeople int64 + overall.CONSTANT_DB_HR.Model(&models.PersonArchives{}).Select("`id`").Where("admin_org IN ? AND emp_type BETWEEN ? AND ?", sunAry.SunList, 1, 10).Count(&sumPeople) + var reatCount int64 + overall.CONSTANT_DB_HR.Model(&hrmodels.UserEmp{}).Select("`id`").Where("admin_org IN ? AND leave_date BETWEEN ? AND ?", sunAry.SunList, startTime, endTime).Count(&reatCount) + beiChuShu := sumPeople + reatCount + if beiChuShu == 0 { + contData.Odds = 0 + } else { + + reatVal := overallhandle.DecimalEs((float64(reatCount)/float64(beiChuShu))*100, 3) + contData.Odds = reatVal + } + c.List = append(c.List, contData) +} + +/* +* +@ 作者: 秦东 +@ 时间: 2023-07-01 15:49:31 +@ 功能: 获取学历结构 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (s *StaffApi) GetEducationalStructure(c *gin.Context) { + userKey := c.Request.Header.Get("user-key") + myCont, myErr := overallhandle.GetCreetUserCont(userKey) + var requestData overallhandle.PublicId[int64] + err := c.ShouldBindJSON(&requestData) + if err != nil { + if myErr != nil { + requestData.Id = 309 + } else { + requestData.Id = myCont.Company + } + } + if requestData.Id == 0 { + if myErr != nil { + requestData.Id = 309 + } else { + requestData.Id = myCont.Company + } + } + var sunAry overallhandle.AllSunList[int64] + sunAry.GetAllSunOrg(requestData.Id) + //学历列表 + var eduStruListCont []hrmodels.EducationalStructure + err = overall.CONSTANT_DB_HR.Distinct("`number`,MAX(`education`) as educationmax ").Where("admin_org IN ?", sunAry.SunList).Group("`number`").Find(&eduStruListCont).Error + if err != nil { + overallhandle.Result(0, err, c) + } + a1 := 0 + a2 := 0 + a3 := 0 + a4 := 0 + a5 := 0 + a6 := 0 + a7 := 0 + a8 := 0 + a9 := 0 + a10 := 0 + a11 := 0 + a12 := 0 + for _, v := range eduStruListCont { + switch v.EducationMax { + case 1: + a1++ + case 2: + a2++ + case 3: + a3++ + case 4: + a4++ + case 5: + a5++ + case 6: + a6++ + case 7: + a7++ + case 8: + a8++ + case 9: + a9++ + case 10: + a10++ + case 11: + a11++ + case 12: + a12++ + default: + } + } + var sendEducStruCont []EducStruCont + sumPie := a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + if a1 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a1)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "初中及以下", Percentage: proportion}) + } + if a2 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a2)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "中专", Percentage: proportion}) + } + if a3 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a3)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "高中", Percentage: proportion}) + } + if a4 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a4)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "中技", Percentage: proportion}) + } + if a5 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a5)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "高技", Percentage: proportion}) + } + if a6 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a6)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "函数专科", Percentage: proportion}) + } + if a7 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a7)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "大学专科", Percentage: proportion}) + } + if a8 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a8)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "函数本科", Percentage: proportion}) + } + if a9 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a9)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "大学本科", Percentage: proportion}) + } + if a10 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a10)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "硕士研究生", Percentage: proportion}) + } + if a11 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a11)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "博士研究生", Percentage: proportion}) + } + if a12 != 0 { + var proportion float64 + if sumPie != 0 { + proportion = overallhandle.DecimalEs((float64(a12)/float64(sumPie))*100, 3) + } + sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "专家、教授", Percentage: proportion}) + } + overallhandle.Result(0, sendEducStruCont, c) +} diff --git a/api/version1/personnelapi/staffarchives.go b/api/version1/personnelapi/staffarchives.go index 7735de9..cad6838 100644 --- a/api/version1/personnelapi/staffarchives.go +++ b/api/version1/personnelapi/staffarchives.go @@ -1873,7 +1873,7 @@ func (s *StaffApi) WeChatGiveUsCont(c *gin.Context) { myCont["planformaldate"] = userCont.Planformaldate //预计转正日期 myCont["political_outlook"] = userCont.PoliticalOutlook //政治面貌(1:群众;2:无党派;3:台盟会员;4:九三社员;5:致公党员;6:农工党员;7:民进会员;8:民建会员;9:民盟盟员;10:民革会员,11:共青团员;12:预备党员;13:中共党员) redisClient.HashMsetAdd(redisMyContKey, myCont) - + saveData["userinfo"] = myCont var sendKpiCont WriteIderCont sendKpiCont.Openid = requestData.OpenId sendKpiCont.Key = userKeyCode diff --git a/api/version1/personnelapi/type.go b/api/version1/personnelapi/type.go index 9a52c04..73449b4 100644 --- a/api/version1/personnelapi/type.go +++ b/api/version1/personnelapi/type.go @@ -581,3 +581,51 @@ type editUSerIcons struct { Id int64 `json:"id"` // IconPath string `json:"iconpath"` // } + +// 获取离职率 +type TurnoverRate struct { + overallhandle.PublicId[int64] + Time string `json:"time"` +} + +// 离职率计算 +type CalculateTurnoverRateCont struct { + OrgId int64 `json:"orgid"` + OrgName string `json:"orgname"` + Months int64 `json:"months"` + Odds int64 `json:"odds"` +} + +type CalTurRateCont struct { + List []CalculateTurnoverRateCont `json:"list"` +} + +// 输出离职率 +type SendCalTurRateCont struct { + OrgId int64 `json:"orgid"` + OrgName string `json:"orgname"` + Odds []float64 `json:"odds"` +} +type CalTurRateContBlack struct { + CurrentOrgId int64 `json:"currentorgid"` + List []SendCalTurRateCont `json:"list"` +} + +/* +输出饼型离职率 +*/ +type SendPicRateCont struct { + OrgId int64 `json:"orgid"` + OrgName string `json:"orgname"` + Odds float64 `json:"odds"` +} +type SendPicRateInfo struct { + CurrentOrgId int64 `json:"currentorgid"` + List []SendPicRateCont `json:"list"` +} + +// 学历结构 +type EducStruCont struct { + Education string `json:"education"` + Percentage float64 `json:"percentage"` +} diff --git a/api/version1/shiyan/shiyan.go b/api/version1/shiyan/shiyan.go index 9c9de5f..f308d1f 100644 --- a/api/version1/shiyan/shiyan.go +++ b/api/version1/shiyan/shiyan.go @@ -298,19 +298,20 @@ func (s *ShiYan) Shitu(c *gin.Context) { c.ShouldBindJSON(&req) out := overallhandle.MapOut() + // groupId := overallhandle.RecursionOrgLevees(103, req.Id, 4) groupId, companyId, departmentId, sunDepartId, workShopId := overallhandle.GetOrgStructure(req.Id) - sdee := overallhandle.RecursionOrgLeve(req.Id, 3) - // node, err := snowflake.NewWorker(1) - // fmt.Printf("node--------->%v\n", err) + // sdee := overallhandle.RecursionOrgLeve(req.Id, 3) + // // node, err := snowflake.NewWorker(1) + // // fmt.Printf("node--------->%v\n", err)_, companyId, departmentId, sunDepartId, _ := overallhandle.GetOrgStructure(orgMainDepart.Id) - // out["node"] = node.GetId() - // out["err "] = err + // // out["node"] = node.GetId() + // // out["err "] = err out["groupId "] = groupId out["companyId "] = companyId out["departmentId "] = departmentId out["sunDepartId "] = sunDepartId out["workShopId "] = workShopId - out["sdee "] = sdee + // out["sdee "] = sdee overallhandle.Result(0, out, c) } diff --git a/apirouter/organization/organization_group.go b/apirouter/organization/organization_group.go index 415a068..6ca3ca9 100644 --- a/apirouter/organization/organization_group.go +++ b/apirouter/organization/organization_group.go @@ -53,6 +53,8 @@ func (o *OrganizationRoute) InitRouterGroup(route *gin.RouterGroup) { apiRouter.POST("govnewthreeing", apiHandle.GovNewThreeIng) //行政组织树(新副本) + apiRouter.POST("getorgchiled", apiHandle.GetOrgChiled) //获取行政组织直接下属 + apiRouter.POST("govthreeaboutman", apiHandle.GovThreeAboutMan) //行政组织树及相关人员 apiRouter.POST("search_org_people", apiHandle.SearchOrgAndPeople) //角色组织与人员搜索列表 diff --git a/apirouter/personnel/people.go b/apirouter/personnel/people.go index bbbe28e..b304a15 100644 --- a/apirouter/personnel/people.go +++ b/apirouter/personnel/people.go @@ -74,6 +74,12 @@ func (p *PersonnelRoute) InitRouterGroup(route *gin.RouterGroup) { apiRouter.POST("addinsidehistorynew", apiHandle.AddInsideHistoryNew) //添加集团工作履历(新版) + apiRouter.POST("dimission_rate", apiHandle.DimissionRate) //离职率 + + apiRouter.POST("oneorg_dimission_rate", apiHandle.GetOenOrgDimRate) //获取单一行政组织离职率 + apiRouter.POST("getorgtimerate", apiHandle.GetOrgTimeRate) //获取公司指定年月的离职率 + apiRouter.POST("get_edu_stru", apiHandle.GetEducationalStructure) //获取学历结构 + } } diff --git a/models/hrmodels/educational_structure.go b/models/hrmodels/educational_structure.go new file mode 100644 index 0000000..ff4b22a --- /dev/null +++ b/models/hrmodels/educational_structure.go @@ -0,0 +1,59 @@ +package hrmodels + +import ( + "hr_server/overall" + "strings" +) + +// 学历结构 +type EducationalStructure struct { + Number string `json:"number" gorm:"column:number;type:varchar(30) unsigned;comment:员工工号"` + Education int `json:"education" gorm:"column:education;type:int(5) unsigned;default:1;comment:学历(1:初中及以下;2:中专;3:高中;4:中技;5:高技;6:函数专科;7:大学专科;8:函数本科;9:大学本科;10:硕士研究生;11:博士研究生;12:专家、教授)"` + AdminOrg int64 `json:"adminorg" gorm:"column:admin_org;type:bigint(20) unsigned;default:0;not null;comment:所属行政组织"` + EducationMax int `json:"educationmax" gorm:"column:educationmax;type:int(5) unsigned;default:1;comment:学历(1:初中及以下;2:中专;3:高中;4:中技;5:高技;6:函数专科;7:大学专科;8:函数本科;9:大学本科;10:硕士研究生;11:博士研究生;12:专家、教授)"` +} + +func (EducationalStructure *EducationalStructure) TableName() string { + return "educational_structure" +} + +// 编辑内容 +func (cont *EducationalStructure) EiteCont(whereMap interface{}, saveData interface{}) (err error) { + err = overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Updates(saveData).Error + return +} + +// 获取内容 +func (cont *EducationalStructure) GetCont(whereMap interface{}, field ...string) (err error) { + gormDb := overall.CONSTANT_DB_HR.Model(&cont) + if len(field) > 0 { + fieldStr := strings.Join(field, ",") + gormDb = gormDb.Select(fieldStr) + } + gormDb = gormDb.Where(whereMap) + err = gormDb.First(&cont).Error + return +} + +// 根据条件获取总数 +func (cont *EducationalStructure) CountCont(whereMap interface{}) (countId int64) { + overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Count(&countId) + return +} + +// 读取全部信息 +func (cont *EducationalStructure) ContMap(whereMap interface{}, field ...string) (countAry []EducationalStructure, err error) { + gormDb := overall.CONSTANT_DB_HR.Model(&cont) + if len(field) > 0 { + fieldStr := strings.Join(field, ",") + gormDb = gormDb.Select(fieldStr) + } + err = gormDb.Where(whereMap).Find(&countAry).Error + return +} + +// 删除内容 +func (cont *EducationalStructure) DelCont(whereMap interface{}) (err error) { + err = overall.CONSTANT_DB_HR.Where(whereMap).Delete(&cont).Error + return +} diff --git a/models/hrmodels/emp_onb_arc.go b/models/hrmodels/emp_onb_arc.go new file mode 100644 index 0000000..41359fc --- /dev/null +++ b/models/hrmodels/emp_onb_arc.go @@ -0,0 +1,73 @@ +package hrmodels + +import ( + "hr_server/overall" + "strings" +) + +/** +@ 作者: 秦东 +@ 时间: 2023-06-29 15:21:07 +@ 功能: 人员变动时间 +@ 参数 + # +@ 返回值 + # +@ 方法原型 + # +*/ +// 金蝶人员状态关键字 +type EmpOnbArc struct { + Id int64 `json:"id" gorm:"primaryKey;column:id;type:bigint(20) unsigned;not null;comment:Id;index"` + UserId int64 `json:"userid" gorm:"column:userid;type:bigint(20) unsigned;default:0;not null;comment:员工ID"` + EntryTime int64 `json:"entrytime" gorm:"column:entry_time;type:bigint(20) unsigned;default:0;not null;comment:入职时间"` + LeaveDate int64 `json:"leavedate" gorm:"column:leave_date;type:bigint(20) unsigned;default:0;not null;comment:离职日期"` + ZhuanZheng int64 `json:"zhuanzheng" gorm:"column:zhuan_zheng;type:bigint(20) unsigned;default:0;not null;comment:转正"` + Time int64 `json:"time" gorm:"column:time;type:bigint(20) unsigned;default:0;not null;comment:时间"` + AdminOrg int64 `json:"adminorg" gorm:"column:admin_org;type:bigint(20) unsigned;default:0;not null;comment:行政组织"` +} + +func (EmpOnbArc *EmpOnbArc) TableName() string { + return "emp_onb_arc" +} + +// 编辑内容 +func (cont *EmpOnbArc) EiteCont(whereMap interface{}, saveData interface{}) (err error) { + err = overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Updates(saveData).Error + return +} + +// 获取内容 +func (cont *EmpOnbArc) GetCont(whereMap interface{}, field ...string) (err error) { + gormDb := overall.CONSTANT_DB_HR.Model(&cont) + if len(field) > 0 { + fieldStr := strings.Join(field, ",") + gormDb = gormDb.Select(fieldStr) + } + gormDb = gormDb.Where(whereMap) + err = gormDb.First(&cont).Error + return +} + +// 根据条件获取总数 +func (cont *EmpOnbArc) CountCont(whereMap interface{}) (countId int64) { + overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Count(&countId) + return +} + +// 读取全部信息 +func (cont *EmpOnbArc) ContMap(whereMap interface{}, field ...string) (countAry []EmpOnbArc, err error) { + gormDb := overall.CONSTANT_DB_HR.Model(&cont) + if len(field) > 0 { + fieldStr := strings.Join(field, ",") + gormDb = gormDb.Select(fieldStr) + } + err = gormDb.Where(whereMap).Find(&countAry).Error + return +} + +// 删除内容 +func (cont *EmpOnbArc) DelCont(whereMap interface{}) (err error) { + err = overall.CONSTANT_DB_HR.Where(whereMap).Delete(&cont).Error + return +} diff --git a/models/hrmodels/user_emp.go b/models/hrmodels/user_emp.go new file mode 100644 index 0000000..81a547e --- /dev/null +++ b/models/hrmodels/user_emp.go @@ -0,0 +1,65 @@ +package hrmodels + +import ( + "hr_server/overall" + "strings" +) + +// 金蝶人员状态关键字 +type UserEmp struct { + Id int64 `json:"id" gorm:"primaryKey;column:id;type:bigint(20) unsigned;not null;comment:Id;index"` + UserId int64 `json:"userid" gorm:"column:userid;type:bigint(20) unsigned;default:0;not null;comment:员工ID"` + EntryTime int64 `json:"entrytime" gorm:"column:entry_time;type:bigint(20) unsigned;default:0;not null;comment:入职时间"` + LeaveDate int64 `json:"leavedate" gorm:"column:leave_date;type:bigint(20) unsigned;default:0;not null;comment:离职日期"` + ZhuanZheng int64 `json:"zhuanzheng" gorm:"column:zhuan_zheng;type:bigint(20) unsigned;default:0;not null;comment:转正"` + RetireTime int64 `json:"retiretime" gorm:"column:retire_time;type:bigint(20) unsigned;default:0;not null;comment:退休"` + Time int64 `json:"time" gorm:"column:time;type:bigint(20) unsigned;default:0;not null;comment:时间"` + Number string `json:"number" gorm:"column:number;type:varchar(30) unsigned;not null;comment:员工工号"` + Name string `json:"name" gorm:"column:name;type:varchar(255) unsigned;default:'';not null;comment:姓名"` + AdminOrg int64 `json:"adminorg" gorm:"column:admin_org;type:bigint(20) unsigned;default:0;not null;comment:所属行政组织"` +} + +func (UserEmp *UserEmp) TableName() string { + return "user_emp" +} + +// 编辑内容 +func (cont *UserEmp) EiteCont(whereMap interface{}, saveData interface{}) (err error) { + err = overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Updates(saveData).Error + return +} + +// 获取内容 +func (cont *UserEmp) GetCont(whereMap interface{}, field ...string) (err error) { + gormDb := overall.CONSTANT_DB_HR.Model(&cont) + if len(field) > 0 { + fieldStr := strings.Join(field, ",") + gormDb = gormDb.Select(fieldStr) + } + gormDb = gormDb.Where(whereMap) + err = gormDb.First(&cont).Error + return +} + +// 根据条件获取总数 +func (cont *UserEmp) CountCont(whereMap interface{}) (countId int64) { + overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Count(&countId) + return +} + +// 读取全部信息 +func (cont *UserEmp) ContMap(whereMap interface{}, field ...string) (countAry []UserEmp, err error) { + gormDb := overall.CONSTANT_DB_HR.Model(&cont) + if len(field) > 0 { + fieldStr := strings.Join(field, ",") + gormDb = gormDb.Select(fieldStr) + } + err = gormDb.Where(whereMap).Find(&countAry).Error + return +} + +// 删除内容 +func (cont *UserEmp) DelCont(whereMap interface{}) (err error) { + err = overall.CONSTANT_DB_HR.Where(whereMap).Delete(&cont).Error + return +} diff --git a/overall/overallhandle/overall_handle.go b/overall/overallhandle/overall_handle.go index 63ab075..d696d5c 100644 --- a/overall/overallhandle/overall_handle.go +++ b/overall/overallhandle/overall_handle.go @@ -6,7 +6,9 @@ import ( "crypto/rand" "crypto/sha1" "encoding/hex" + "errors" "fmt" + "hr_server/grocerystore" "hr_server/middleware/snowflake" "hr_server/models" "hr_server/overall" @@ -14,6 +16,7 @@ import ( "math" "math/big" "net/http" + "reflect" "strconv" "strings" "time" @@ -22,6 +25,27 @@ import ( ) // 全局函数处理 +var ( + timeLayoutMap = map[string]string{ + "y": "2006", + "m": "2006-01", + "d": "2006-01-02", + "h": "2006-01-02 15", + "i": "2006-01-02 15:04", + "s": "2006-01-02 15:04:05", + } + + weekDay = map[string]int{ + "Monday": 1, + "Tuesday": 2, + "Wednesday": 3, + "Thursday": 4, + "Friday": 5, + "Saturday": 6, + "Sunday": 7, + } +) + // 编号,纯数字 func TableNumber(class ...string) (number int64) { result, _ := rand.Int(rand.Reader, big.NewInt(8999)) @@ -723,6 +747,31 @@ func PolitiToString(emp int) string { return "群众" } } +func RecursionOrgLevees(oldId, superior int64, leve int64) (groupId int64) { + if leve == 0 { + leve = 1 + } + if superior == 0 { + return + } + var orgMap models.OrgContType + err := orgMap.GetCont(map[string]interface{}{"`id`": superior, "`state`": 1}, "`id`", "`superior`", "`level`") + if err != nil { + return + } + if orgMap.Level <= leve { + if orgMap.Level == leve { + groupId = oldId + } else { + groupId = orgMap.Id + } + + return + } else { + groupId = RecursionOrgLevees(orgMap.Superior, orgMap.Superior, leve) + } + return +} // 递归查找 func RecursionOrgLeve(superior int64, leve int64) (groupId int64) { @@ -779,6 +828,9 @@ func RecursionOrgLeveEs(oldId, superior, leve int64) (groupId int64) { // 获取集团、公司、部门、二级部门、工段 func GetOrgStructure(orgId int64) (groupId, companyId, departmentId, sunDepartId, workShopId int64) { + if orgId == 0 { + return + } var orgContTypeInfo models.OrgContType err := orgContTypeInfo.GetCont(map[string]interface{}{"`id`": orgId}) if err != nil { @@ -789,25 +841,26 @@ func GetOrgStructure(orgId int64) (groupId, companyId, departmentId, sunDepartId case 1: groupId = orgContTypeInfo.Id case 2: - groupId = RecursionOrgLeve(orgContTypeInfo.Superior, 1) + groupId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 1) workShopId = orgContTypeInfo.Id case 3: - groupId = RecursionOrgLeve(orgContTypeInfo.Superior, 2) + groupId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 2) companyId = orgContTypeInfo.Id case 4: - groupId = RecursionOrgLeve(orgContTypeInfo.Superior, 2) - companyId = RecursionOrgLeve(orgContTypeInfo.Superior, 3) + groupId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 2) + companyId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 3) departmentId = orgContTypeInfo.Id case 5: - groupId = RecursionOrgLeve(orgContTypeInfo.Superior, 2) - companyId = RecursionOrgLeve(orgContTypeInfo.Superior, 3) - departmentId = RecursionOrgLeve(orgContTypeInfo.Superior, 4) + groupId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 2) + companyId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 3) + departmentId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 4) + fmt.Printf("departmentId--->%v\norgId--->%v\n", departmentId, orgId) sunDepartId = orgContTypeInfo.Id case 6: - groupId = RecursionOrgLeve(orgContTypeInfo.Superior, 1) - companyId = RecursionOrgLeve(orgContTypeInfo.Superior, 3) - departmentId = RecursionOrgLeve(orgContTypeInfo.Superior, 4) - sunDepartId = RecursionOrgLeve(orgContTypeInfo.Superior, 5) + groupId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 2) + companyId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 3) + departmentId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 4) + sunDepartId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 5) workShopId = orgContTypeInfo.Id default: groupId = orgContTypeInfo.Id @@ -1137,8 +1190,9 @@ func (d *DateTimeTotimes) BaisStrToTime(dateTime string) { default: } - fmt.Printf("dateTime:%v---1--->%v\n", dateTime, len(dateTime)) + // fmt.Printf("dateTime:%v---1--->%v\n", dateTime, len(dateTime)) orgTime, orgTimeErr := DateToTimeStamp(fmt.Sprintf("%v-01-01 12:00:00", dateTime)) + d.Time = dateTime if orgTimeErr { d.AllTime = orgTime d.Years = strconv.FormatInt(ComputingTime(orgTime, 1), 10) @@ -1284,3 +1338,131 @@ func ComputingTime(timeStamp int64, timeType int) (timeDataInt int64) { } return } + +// 获取指定月的起止时间副本 +func GetAppointMonthStarAndEndTimeEs(dayTime string) (startTime, endTime int64) { + dataTypeAll := "2006-01-02" + firstToTime := StringToTimeIng("d", dayTime) + startTimeStr := fmt.Sprintf("%v 00:00:00", firstToTime.AddDate(0, 0, 0).Format(dataTypeAll)) + endTimeStr := fmt.Sprintf("%v 23:59:59", firstToTime.AddDate(0, 1, -1).Format(dataTypeAll)) + // startTime = dayTime + // fmt.Printf("获取指定月的起止时间副本--->%v--->%v\n", startTimeStr, endTimeStr) + startTime, _ = DateToTimeStamp(startTimeStr) + endTime, _ = DateToTimeStamp(endTimeStr) + return +} + +// 日期字符串转换成time格式 +func StringToTimeIng(unit, str string) (res time.Time) { + loc, _ := time.LoadLocation("Local") + // str := t.ToString() + layout, ok := timeLayoutMap[unit] + if !ok { + layout = timeLayoutMap["s"] + } + res, _ = time.ParseInLocation(layout, str, loc) + return +} + +/* +* +@ 作者: 秦东 +@ 时间: 2023-07-01 13:04:00 +@ 功能: 获取当前登陆人信息 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func GetCreetUserCont(userKey string) (manCont models.ManCont, err error) { + redisFileKey := fmt.Sprintf("ScanCode:Authentication:LoginApi_%v_%v", overall.CONSTANT_CONFIG.RedisPrefixStr.Alias, userKey) + redisClient := grocerystore.RunRedis(overall.CONSTANT_REDIS5) + userRedisToken, isTrue := redisClient.HashGetAll(redisFileKey) + if !isTrue { + return + } + manCont, err = GetUserRedisCont(userRedisToken["usernumber"]) + return +} + +// 获取人员Redis信息 +func GetUserRedisCont(number string) (manCont models.ManCont, err error) { + redisMyContKey := fmt.Sprintf("ScanCode:Authentication:UserCont_%v_%v", overall.CONSTANT_CONFIG.RedisPrefixStr.Alias, number) + redisClient := grocerystore.RunRedis(overall.CONSTANT_REDIS5) + useMap, isTrue := redisClient.HashGetAll(redisMyContKey) + if !isTrue { + errors.New("没有相关信息") + return + } + err = MapToStruct(useMap, &manCont, "json") + return +} + +/* +map[string]string 转 struct +*/ +func MapToStruct(mapString map[string]string, structInterface interface{}, tag string) (err error) { + strType := reflect.TypeOf(structInterface) + strValue := reflect.ValueOf(structInterface) + switch strType.Kind() { + case reflect.Ptr: + if strType.Elem().Kind() != reflect.Struct { + // fmt.Printf("1-->%v\n", strType.Elem().Kind().String()) + return errors.New("需要*struct类型,却传入*" + strType.Elem().Kind().String() + "类型") + } + default: + // fmt.Printf("2-->%v\n", strType.Kind().String()) + return errors.New("需要*struct类型,却传入" + strType.Kind().String() + "类型") + } + // fmt.Printf("strType--->%v---strValue---->%v\n", strType, strValue) + strTypeElem := strType.Elem() + strValueElem := strValue.Elem() + strTypeNum := strTypeElem.NumField() + // fmt.Printf("strTypeElem--->%v---strValueElem---->%v---------strTypeNum--------->%v\n", strTypeElem, strValueElem, strTypeNum) + for i := 0; i < strTypeNum; i++ { + fieldName := strTypeElem.Field(i).Name + if tag != "" { + fieldName = strTypeElem.Field(i).Tag.Get(tag) + } + value, ok := mapString[fieldName] + if !ok { + continue + } + // fmt.Printf("name--->%v---tag---->%v----value---->%v----ok---->%v\n", fieldName, tag, value, ok) + if strValueElem.Field(i).CanSet() { + // fmt.Printf("Type--->%v---value---->%v\n", strValueElem.Field(i).Type(), reflect.TypeOf(value)) + valType := fmt.Sprintf("%v", strValueElem.Field(i).Type()) + switch valType { + case "int": + valueInt, _ := strconv.Atoi(value) + strValueElem.Field(i).Set(reflect.ValueOf(valueInt)) + case "int32": + valueInt32, _ := strconv.ParseInt(value, 10, 32) + strValueElem.Field(i).Set(reflect.ValueOf(int32(valueInt32))) + case "int64": + valueInt64, _ := strconv.ParseInt(value, 10, 64) + strValueElem.Field(i).Set(reflect.ValueOf(valueInt64)) + case "float32": + valuefloat32, _ := strconv.ParseFloat(value, 32) + strValueElem.Field(i).Set(reflect.ValueOf(float32(valuefloat32))) + case "float64": + valuefloat64, _ := strconv.ParseFloat(value, 64) + strValueElem.Field(i).Set(reflect.ValueOf(valuefloat64)) + case "string": + strValueElem.Field(i).Set(reflect.ValueOf(value)) + default: + + } + } else { + continue + } + } + return +} diff --git a/overall/overallhandle/type.go b/overall/overallhandle/type.go index 3bc903f..5b110a7 100644 --- a/overall/overallhandle/type.go +++ b/overall/overallhandle/type.go @@ -18,6 +18,10 @@ type ConstId struct { Id string `json:"id"` } +type PublicId[T GenericityVariable] struct { + Id T `json:"id"` +} + //翻页格式化 type PageTurning struct { Page int `json:"page" form:"page"` // 页码 @@ -99,4 +103,5 @@ type DateTimeTotimes struct { Minutes string `json:"minutes"` Second string `json:"second"` AllTime int64 `json:"alltime"` + Time string `json:"time"` }