WiiCITMS/process/hr/organization_ai.go
2025-11-07 14:14:34 +08:00

484 lines
14 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}