WiiCITMS/process/hr/organization_ai.go

484 lines
14 KiB
Go
Raw Normal View History

2025-11-07 14:14:34 +08:00
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
}