484 lines
14 KiB
Go
484 lines
14 KiB
Go
package hr
|
||
|
||
import (
|
||
"WiiCITMS/models/hr"
|
||
"WiiGenerates/WiiCITMS/generates/v1/go/types"
|
||
"WiiGoLibrary/apply/middle/process/v1"
|
||
"WiiGoLibrary/framework/db/v1/utils/mssql/unique"
|
||
"WiiGoLibrary/framework/hub/v1/dblib"
|
||
"fmt"
|
||
)
|
||
|
||
// AIOrganizationInfo 为AI提供的组织信息结构
|
||
type AIOrganizationInfo struct {
|
||
OrgGuid string `json:"orgGuid"` // 组织ID
|
||
OrgID int64 `json:"orgId"` // 组织编号
|
||
Name string `json:"name"` // 组织名称
|
||
Type int `json:"type"` // 组织类型
|
||
ParentGuid string `json:"parentGuid"` // 父组织ID
|
||
ParentName string `json:"parentName"` // 父组织名称
|
||
Level int `json:"level"` // 组织层级(从顶级开始计算)
|
||
Path string `json:"path"` // 组织路径(如:公司/部门/团队)
|
||
HeadCount int `json:"headCount"` // 编制人数
|
||
ActualCount int `json:"actualCount"` // 实际人数
|
||
ChildrenCount int `json:"childrenCount"` // 子组织数量
|
||
Children []AIOrganizationInfo `json:"children"` // 子组织(仅在需要完整树结构时使用)
|
||
Positions []PositionBrief `json:"positions"` // 组织下的岗位信息(简要)
|
||
}
|
||
|
||
// PositionBrief 岗位简要信息
|
||
type PositionBrief struct {
|
||
PositionGuid string `json:"positionGuid"` // 岗位ID
|
||
PositionName string `json:"positionName"` // 岗位名称
|
||
PositionCode string `json:"positionCode"` // 岗位代码
|
||
HeadCount int `json:"headCount"` // 编制人数
|
||
Level int `json:"level"` // 岗位级别
|
||
IsManagement bool `json:"isManagement"` // 是否管理岗位
|
||
}
|
||
|
||
// StaffBrief 员工简要信息
|
||
type StaffBrief struct {
|
||
StaffGuid string `json:"staffGuid"` // 员工ID
|
||
StaffName string `json:"staffName"` // 员工姓名
|
||
StaffID string `json:"staffId"` // 员工工号
|
||
PositionGuid string `json:"positionGuid"` // 岗位ID
|
||
PositionName string `json:"positionName"` // 岗位名称
|
||
IsLeader bool `json:"isLeader"` // 是否是组织负责人
|
||
}
|
||
|
||
// AIOrganizationTreeRequest 组织树请求参数
|
||
type AIOrganizationTreeRequest struct {
|
||
RootOrgGuid string `json:"rootOrgGuid"` // 根组织ID,不指定则获取所有顶级组织
|
||
IncludeStaff bool `json:"includeStaff"` // 是否包含员工信息
|
||
IncludeDetails bool `json:"includeDetails"` // 是否包含详细信息
|
||
MaxDepth int `json:"maxDepth"` // 最大深度,0表示不限制
|
||
}
|
||
|
||
// GetOrganizationForAI 获取组织信息(AI专用)
|
||
func GetOrganizationForAI(orgGuid string, includePositions bool) (*AIOrganizationInfo, *process.Process) {
|
||
// 验证组织ID
|
||
guid, err := unique.FromString(orgGuid)
|
||
if err != nil {
|
||
return nil, process.FailError(types.InvalidParamError, err)
|
||
}
|
||
|
||
// 查询组织
|
||
org := &hr.OrganizationModel{}
|
||
r := dblib.DBIns.DB.Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", guid).First(org)
|
||
if r.Error != nil {
|
||
return nil, process.FailError(types.OrgNotFoundError, r.Error)
|
||
}
|
||
|
||
// 构建AI组织信息
|
||
result := &AIOrganizationInfo{
|
||
OrgGuid: org.RecordGuid.String(),
|
||
OrgID: org.DepartmentID,
|
||
Name: org.OrganizationName,
|
||
Type: int(org.RecordType),
|
||
ParentGuid: org.ParentGuid.String(),
|
||
Level: 0, // 后面会计算
|
||
}
|
||
|
||
// 获取父组织名称和构建路径
|
||
if org.ParentGuid != unique.NilUUID {
|
||
parentOrg := &hr.OrganizationModel{}
|
||
r := dblib.DBIns.DB.Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", org.ParentGuid).First(parentOrg)
|
||
if r.Error == nil {
|
||
result.ParentName = parentOrg.OrganizationName
|
||
result.Path = parentOrg.OrganizationName + "/" + org.OrganizationName
|
||
|
||
// 计算层级
|
||
result.Level = calcOrganizationLevel(org.ParentGuid)
|
||
} else {
|
||
result.Path = org.OrganizationName
|
||
}
|
||
} else {
|
||
result.Path = org.OrganizationName
|
||
}
|
||
|
||
// 查询子组织数量
|
||
var childCount int64
|
||
dblib.DBIns.DB.Model(&hr.OrganizationModel{}).
|
||
Where("ParentGuid = ? AND (RecordStatus & 524288) = 0", org.RecordGuid).
|
||
Count(&childCount)
|
||
result.ChildrenCount = int(childCount)
|
||
|
||
// 查询组织下的实际人数
|
||
var actualCount int64
|
||
dblib.DBIns.DB.Model(&hr.Staff2OrganizationModel{}).
|
||
Where("TargetGuid = ? AND (RecordStatus & 524288) = 0", org.RecordGuid).
|
||
Count(&actualCount)
|
||
result.ActualCount = int(actualCount)
|
||
|
||
// 计算岗位编制总人数
|
||
var totalHeadCount int64
|
||
dblib.DBIns.DB.Model(&hr.OrgPositionRelModel{}).
|
||
Where("OrganizationGuid = ? AND (RecordStatus & 524288) = 0", org.RecordGuid).
|
||
Select("SUM(HeadCount)").
|
||
Row().
|
||
Scan(&totalHeadCount)
|
||
result.HeadCount = int(totalHeadCount)
|
||
|
||
// 如果需要,获取组织下的岗位信息
|
||
if includePositions {
|
||
result.Positions = getPositionsForOrg(org.RecordGuid)
|
||
}
|
||
|
||
return result, process.Success(200)
|
||
}
|
||
|
||
// GetOrganizationTreeForAI 获取组织树(AI专用)
|
||
func GetOrganizationTreeForAI(params AIOrganizationTreeRequest) ([]AIOrganizationInfo, *process.Process) {
|
||
var rootGuid unique.UUID
|
||
var err error
|
||
|
||
// 处理根组织ID
|
||
if params.RootOrgGuid != "" {
|
||
rootGuid, err = unique.FromString(params.RootOrgGuid)
|
||
if err != nil {
|
||
return nil, process.FailError(types.InvalidParamError, err)
|
||
}
|
||
} else {
|
||
// 不指定则查询顶级组织
|
||
rootGuid = unique.NilUUID
|
||
}
|
||
|
||
// 查询根组织列表
|
||
var rootOrgs []*hr.OrganizationModel
|
||
var query = dblib.DBIns.DB.Where("(RecordStatus & 524288) = 0")
|
||
|
||
if rootGuid == unique.NilUUID {
|
||
// 查询所有顶级组织
|
||
query = query.Where("ParentGuid = ?", rootGuid)
|
||
} else {
|
||
// 查询指定组织
|
||
query = query.Where("RecordGuid = ?", rootGuid)
|
||
}
|
||
|
||
r := query.Find(&rootOrgs)
|
||
if r.Error != nil {
|
||
return nil, process.FailError(types.QueryOrganizationError, r.Error)
|
||
}
|
||
|
||
// 构建组织树
|
||
result := buildAIOrganizationTree(rootOrgs, params, 0)
|
||
return result, process.Success(200)
|
||
}
|
||
|
||
// GetOrganizationMembers 获取组织成员(AI专用)
|
||
func GetOrganizationMembers(orgGuid string) ([]StaffBrief, *process.Process) {
|
||
// 验证组织ID
|
||
guid, err := unique.FromString(orgGuid)
|
||
if err != nil {
|
||
return nil, process.FailError(types.InvalidParamError, err)
|
||
}
|
||
|
||
// 查询组织是否存在
|
||
var count int64
|
||
r := dblib.DBIns.DB.Model(&hr.OrganizationModel{}).
|
||
Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", guid).
|
||
Count(&count)
|
||
if r.Error != nil || count == 0 {
|
||
return nil, process.FailError(types.OrgNotFoundError, r.Error)
|
||
}
|
||
|
||
// 查询组织成员
|
||
members := make([]StaffBrief, 0)
|
||
|
||
rows, err := dblib.DBIns.DB.Raw(`
|
||
SELECT
|
||
s.RecordGuid as StaffGuid,
|
||
s.UserName as StaffName,
|
||
s.JobID as StaffID,
|
||
'' as PositionGuid,
|
||
'' as PositionName,
|
||
0 as IsLeader
|
||
FROM
|
||
`+hr.Staff2OrganizationTable+` so
|
||
JOIN
|
||
`+hr.StaffTable+` s ON so.ObjectGuid = s.RecordGuid
|
||
WHERE
|
||
so.TargetGuid = ?
|
||
AND (so.RecordStatus & 524288) = 0
|
||
AND (s.RecordStatus & 524288) = 0
|
||
`, guid).Rows()
|
||
|
||
if err != nil {
|
||
return nil, process.FailError(types.QueryOrganizationError, err)
|
||
}
|
||
defer rows.Close()
|
||
|
||
// 处理查询结果
|
||
for rows.Next() {
|
||
var member StaffBrief
|
||
var staffGuid, posGuid string
|
||
var staffID int64
|
||
var isLeader int
|
||
|
||
err := rows.Scan(
|
||
&staffGuid,
|
||
&member.StaffName,
|
||
&staffID,
|
||
&posGuid,
|
||
&member.PositionName,
|
||
&isLeader,
|
||
)
|
||
|
||
if err != nil {
|
||
continue
|
||
}
|
||
|
||
member.StaffID = fmt.Sprintf("%d", staffID)
|
||
member.IsLeader = isLeader != 0
|
||
|
||
member.StaffGuid = staffGuid
|
||
member.PositionGuid = posGuid
|
||
members = append(members, member)
|
||
}
|
||
|
||
return members, process.Success(200)
|
||
}
|
||
|
||
// GetFullOrganizationPath 获取组织的完整路径(AI专用)
|
||
func GetFullOrganizationPath(orgGuid string) (string, *process.Process) {
|
||
// 验证组织ID
|
||
guid, err := unique.FromString(orgGuid)
|
||
if err != nil {
|
||
return "", process.FailError(types.InvalidParamError, err)
|
||
}
|
||
|
||
// 递归获取组织路径
|
||
path := ""
|
||
currentGuid := guid
|
||
for {
|
||
org := &hr.OrganizationModel{}
|
||
r := dblib.DBIns.DB.Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", currentGuid).First(org)
|
||
if r.Error != nil {
|
||
break
|
||
}
|
||
|
||
// 添加当前组织名称到路径前
|
||
if path == "" {
|
||
path = org.OrganizationName
|
||
} else {
|
||
path = org.OrganizationName + "/" + path
|
||
}
|
||
|
||
// 如果已经到达顶级组织,则退出循环
|
||
if org.ParentGuid == unique.NilUUID {
|
||
break
|
||
}
|
||
|
||
// 继续向上查找父组织
|
||
currentGuid = org.ParentGuid
|
||
}
|
||
|
||
return path, process.Success(200)
|
||
}
|
||
|
||
// GetAllOrganizations 获取所有组织的扁平列表(AI专用)
|
||
func GetAllOrganizations() ([]AIOrganizationInfo, *process.Process) {
|
||
// 查询所有非删除状态的组织
|
||
orgs := make([]*hr.OrganizationModel, 0)
|
||
r := dblib.DBIns.DB.Where("(RecordStatus & 524288) = 0").Find(&orgs)
|
||
if r.Error != nil {
|
||
return nil, process.FailError(types.QueryOrganizationError, r.Error)
|
||
}
|
||
|
||
// 转换为AI组织信息
|
||
result := make([]AIOrganizationInfo, 0, len(orgs))
|
||
for _, org := range orgs {
|
||
// 构建基本信息
|
||
aiOrg := AIOrganizationInfo{
|
||
OrgGuid: org.RecordGuid.String(),
|
||
OrgID: org.DepartmentID,
|
||
Name: org.OrganizationName,
|
||
Type: int(org.RecordType),
|
||
ParentGuid: org.ParentGuid.String(),
|
||
}
|
||
|
||
// 获取父组织名称
|
||
if org.ParentGuid != unique.NilUUID {
|
||
parentOrg := &hr.OrganizationModel{}
|
||
r := dblib.DBIns.DB.Where("RecordGuid = ?", org.ParentGuid).First(parentOrg)
|
||
if r.Error == nil {
|
||
aiOrg.ParentName = parentOrg.OrganizationName
|
||
}
|
||
}
|
||
|
||
// 获取子组织数量
|
||
var childCount int64
|
||
dblib.DBIns.DB.Model(&hr.OrganizationModel{}).
|
||
Where("ParentGuid = ? AND (RecordStatus & 524288) = 0", org.RecordGuid).
|
||
Count(&childCount)
|
||
aiOrg.ChildrenCount = int(childCount)
|
||
|
||
// 查询实际人数
|
||
var actualCount int64
|
||
dblib.DBIns.DB.Model(&hr.Staff2OrganizationModel{}).
|
||
Where("TargetGuid = ? AND (RecordStatus & 524288) = 0", org.RecordGuid).
|
||
Count(&actualCount)
|
||
aiOrg.ActualCount = int(actualCount)
|
||
|
||
result = append(result, aiOrg)
|
||
}
|
||
|
||
return result, process.Success(200)
|
||
}
|
||
|
||
// 辅助函数:计算组织层级(从0开始,顶级组织为0)
|
||
func calcOrganizationLevel(orgGuid unique.UUID) int {
|
||
level := 0
|
||
currentGuid := orgGuid
|
||
|
||
for {
|
||
if currentGuid == unique.NilUUID {
|
||
break
|
||
}
|
||
|
||
org := &hr.OrganizationModel{}
|
||
r := dblib.DBIns.DB.Where("RecordGuid = ?", currentGuid).First(org)
|
||
if r.Error != nil {
|
||
break
|
||
}
|
||
|
||
level++
|
||
currentGuid = org.ParentGuid
|
||
}
|
||
|
||
return level
|
||
}
|
||
|
||
// 辅助函数:获取组织下的岗位列表
|
||
func getPositionsForOrg(orgGuid unique.UUID) []PositionBrief {
|
||
result := make([]PositionBrief, 0)
|
||
|
||
rows, err := dblib.DBIns.DB.Raw(`
|
||
SELECT
|
||
p.RecordGuid as PositionGuid,
|
||
p.PositionName,
|
||
p.PositionCode,
|
||
op.HeadCount,
|
||
p.Level,
|
||
p.IsManagement
|
||
FROM
|
||
`+hr.OrgPositionRelTable+` op
|
||
JOIN
|
||
`+hr.PositionTable+` p ON op.PositionGuid = p.RecordGuid
|
||
WHERE
|
||
op.OrganizationGuid = ?
|
||
AND (op.RecordStatus & 524288) = 0
|
||
AND (p.RecordStatus & 524288) = 0
|
||
`, orgGuid).Rows()
|
||
|
||
if err != nil {
|
||
return result
|
||
}
|
||
defer rows.Close()
|
||
|
||
// 处理查询结果
|
||
for rows.Next() {
|
||
var position PositionBrief
|
||
var posGuid string
|
||
|
||
err := rows.Scan(
|
||
&posGuid,
|
||
&position.PositionName,
|
||
&position.PositionCode,
|
||
&position.HeadCount,
|
||
&position.Level,
|
||
&position.IsManagement,
|
||
)
|
||
|
||
if err != nil {
|
||
continue
|
||
}
|
||
|
||
position.PositionGuid = posGuid
|
||
result = append(result, position)
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
// 辅助函数:递归构建AI组织树
|
||
func buildAIOrganizationTree(orgs []*hr.OrganizationModel, params AIOrganizationTreeRequest, currentDepth int) []AIOrganizationInfo {
|
||
if len(orgs) == 0 {
|
||
return []AIOrganizationInfo{}
|
||
}
|
||
|
||
// 检查是否超过最大深度
|
||
if params.MaxDepth > 0 && currentDepth >= params.MaxDepth {
|
||
return []AIOrganizationInfo{}
|
||
}
|
||
|
||
result := make([]AIOrganizationInfo, 0, len(orgs))
|
||
|
||
for _, org := range orgs {
|
||
// 构建当前节点
|
||
aiOrg := AIOrganizationInfo{
|
||
OrgGuid: org.RecordGuid.String(),
|
||
OrgID: org.DepartmentID,
|
||
Name: org.OrganizationName,
|
||
Type: int(org.RecordType),
|
||
ParentGuid: org.ParentGuid.String(),
|
||
Level: calcOrganizationLevel(org.ParentGuid),
|
||
}
|
||
|
||
// 获取父组织名称
|
||
if org.ParentGuid != unique.NilUUID {
|
||
parentOrg := &hr.OrganizationModel{}
|
||
r := dblib.DBIns.DB.Where("RecordGuid = ?", org.ParentGuid).First(parentOrg)
|
||
if r.Error == nil {
|
||
aiOrg.ParentName = parentOrg.OrganizationName
|
||
}
|
||
}
|
||
|
||
// 获取子组织数量
|
||
var childCount int64
|
||
dblib.DBIns.DB.Model(&hr.OrganizationModel{}).
|
||
Where("ParentGuid = ? AND (RecordStatus & 524288) = 0", org.RecordGuid).
|
||
Count(&childCount)
|
||
aiOrg.ChildrenCount = int(childCount)
|
||
|
||
// 如果需要包含详细信息,获取员工数和岗位信息
|
||
if params.IncludeDetails {
|
||
// 查询实际人数
|
||
var actualCount int64
|
||
dblib.DBIns.DB.Model(&hr.Staff2OrganizationModel{}).
|
||
Where("TargetGuid = ? AND (RecordStatus & 524288) = 0", org.RecordGuid).
|
||
Count(&actualCount)
|
||
aiOrg.ActualCount = int(actualCount)
|
||
|
||
// 计算岗位编制总人数
|
||
var totalHeadCount int64
|
||
dblib.DBIns.DB.Model(&hr.OrgPositionRelModel{}).
|
||
Where("OrganizationGuid = ? AND (RecordStatus & 524288) = 0", org.RecordGuid).
|
||
Select("SUM(HeadCount)").
|
||
Row().
|
||
Scan(&totalHeadCount)
|
||
aiOrg.HeadCount = int(totalHeadCount)
|
||
|
||
// 获取岗位信息
|
||
aiOrg.Positions = getPositionsForOrg(org.RecordGuid)
|
||
|
||
// 生成完整路径
|
||
path, _ := GetFullOrganizationPath(org.RecordGuid.String())
|
||
aiOrg.Path = path
|
||
}
|
||
|
||
// 递归查询子组织
|
||
if aiOrg.ChildrenCount > 0 {
|
||
childOrgs := make([]*hr.OrganizationModel, 0)
|
||
dblib.DBIns.DB.Where("ParentGuid = ? AND (RecordStatus & 524288) = 0", org.RecordGuid).Find(&childOrgs)
|
||
aiOrg.Children = buildAIOrganizationTree(childOrgs, params, currentDepth+1)
|
||
} else {
|
||
aiOrg.Children = []AIOrganizationInfo{}
|
||
}
|
||
|
||
result = append(result, aiOrg)
|
||
}
|
||
|
||
return result
|
||
}
|