WiiCITMS/process/hr/staff_position.go

505 lines
16 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"
)
// AssignPositionRequest 为员工分配岗位的请求参数
type AssignPositionRequest struct {
StaffGuid string `json:"staffGuid"` // 员工GUID
OrganizationGuid string `json:"organizationGuid"` // 组织GUID
PositionGuid string `json:"positionGuid"` // 岗位GUID可选如果为空则只绑定组织
IsLeader bool `json:"isLeader"` // 是否是组织负责人
RecordType int `json:"recordType"` // 关系类型0-主部门/岗位1-兼职部门/岗位
}
// UpdateStaffPositionRequest 更新员工岗位的请求参数
type UpdateStaffPositionRequest struct {
RecordGuid string `json:"recordGuid"` // 员工组织关系记录GUID
PositionGuid string `json:"positionGuid"` // 岗位GUID
IsLeader bool `json:"isLeader"` // 是否是组织负责人
RecordType int `json:"recordType"` // 关系类型0-主部门/岗位1-兼职部门/岗位
}
// RemoveStaffPositionRequest 移除员工岗位的请求参数
type RemoveStaffPositionRequest struct {
StaffGuid string `json:"staffGuid"` // 员工GUID
OrganizationGuid string `json:"organizationGuid"` // 组织GUID
}
// StaffPositionRelDetail 员工岗位关系详情
type StaffPositionRelDetail struct {
RecordGuid unique.UUID `json:"recordGuid"` // 关系记录GUID
StaffGuid unique.UUID `json:"staffGuid"` // 员工GUID
StaffName string `json:"staffName"` // 员工姓名
OrganizationGuid unique.UUID `json:"organizationGuid"` // 组织GUID
OrganizationName string `json:"organizationName"` // 组织名称
PositionGuid unique.UUID `json:"positionGuid"` // 岗位GUID
PositionName string `json:"positionName"` // 岗位名称
IsLeader bool `json:"isLeader"` // 是否是组织负责人
RecordType int `json:"recordType"` // 关系类型0-主部门/岗位1-兼职部门/岗位
}
// AssignPosition 为员工分配岗位和组织
func AssignPosition(params AssignPositionRequest) (*StaffPositionRelDetail, *process.Process) {
// 验证员工ID
staffGuid, err := unique.FromString(params.StaffGuid)
if err != nil {
return nil, process.FailError(types.InvalidParamError, err)
}
// 验证组织ID
orgGuid, err := unique.FromString(params.OrganizationGuid)
if err != nil {
return nil, process.FailError(types.InvalidParamError, err)
}
// 开始事务
tx := dblib.DBIns.DB.Begin()
// 查询员工是否存在
staff := &hr.StaffModel{}
r := tx.Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", staffGuid).First(staff)
if r.Error != nil {
tx.Rollback()
return nil, process.FailError(types.StaffNotFoundError, r.Error)
}
// 查询组织是否存在
org := &hr.OrganizationModel{}
r = tx.Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", orgGuid).First(org)
if r.Error != nil {
tx.Rollback()
return nil, process.FailError(types.OrgNotFoundError, r.Error)
}
// 如果提供了岗位ID则验证岗位是否存在且属于该组织
var position *hr.PositionModel
if params.PositionGuid != "" {
posGuid, err := unique.FromString(params.PositionGuid)
if err != nil {
tx.Rollback()
return nil, process.FailError(types.InvalidParamError, err)
}
position = &hr.PositionModel{}
r = tx.Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", posGuid).First(position)
if r.Error != nil {
tx.Rollback()
return nil, process.FailError(types.PositionNotFoundError, r.Error)
}
// 检查岗位是否与组织关联
var count int64
r = tx.Model(&hr.OrgPositionRelModel{}).Where(
"OrganizationGuid = ? AND PositionGuid = ? AND (RecordStatus & 524288) = 0",
orgGuid, posGuid,
).Count(&count)
if r.Error != nil || count == 0 {
tx.Rollback()
return nil, process.FailError(types.InvalidPositionError, fmt.Errorf("岗位不属于指定组织"))
}
}
// 检查是否已经存在员工与组织的关联
var existingRel hr.Staff2OrganizationModel
relQuery := tx.Where(
"ObjectGuid = ? AND TargetGuid = ? AND (RecordStatus & 524288) = 0",
staffGuid, orgGuid,
).First(&existingRel)
// 查找当前员工是否已有主部门关系
var currentMain hr.Staff2OrganizationModel
hasMain := tx.Where("ObjectGuid = ? AND RecordType = 0 AND (RecordStatus & 524288) = 0", staffGuid).First(&currentMain).Error == nil
if params.RecordType == 0 { // 分配主部门/岗位
if relQuery.Error == nil {
// 已存在该组织的关联:将其设为主并更新信息
if params.PositionGuid != "" {
posGuid, _ := unique.FromString(params.PositionGuid)
existingRel.PositionGuid = posGuid
}
existingRel.IsLeader = params.IsLeader
existingRel.RecordType = 0
if err := tx.Save(&existingRel).Error; err != nil {
tx.Rollback()
return nil, process.FailError(types.UpdateStaffError, err)
}
// 如果存在其他主部门,则降级
if hasMain && currentMain.RecordGuid != existingRel.RecordGuid {
if err := tx.Model(&hr.Staff2OrganizationModel{}).
Where("RecordGuid = ?", currentMain.RecordGuid).
Update("RecordType", 1).Error; err != nil {
tx.Rollback()
return nil, process.FailError(types.UpdateStaffError, err)
}
}
} else {
if hasMain {
// 已有主部门:若同组织,更新;否则切换主部门到新组织(不新增记录)
if currentMain.TargetGuid == orgGuid {
if params.PositionGuid != "" {
posGuid, _ := unique.FromString(params.PositionGuid)
currentMain.PositionGuid = posGuid
}
currentMain.IsLeader = params.IsLeader
// 保持为主部门
if err := tx.Save(&currentMain).Error; err != nil {
tx.Rollback()
return nil, process.FailError(types.UpdateStaffError, err)
}
} else {
// 切换主部门到新的组织
currentMain.TargetGuid = orgGuid
if params.PositionGuid != "" {
posGuid, _ := unique.FromString(params.PositionGuid)
currentMain.PositionGuid = posGuid
} else {
currentMain.PositionGuid = unique.NilUUID
}
currentMain.IsLeader = params.IsLeader
currentMain.RecordType = 0
if err := tx.Save(&currentMain).Error; err != nil {
tx.Rollback()
return nil, process.FailError(types.UpdateStaffError, err)
}
}
existingRel = currentMain
} else {
// 不存在主部门:创建一条主部门关联
newRel := hr.Staff2OrganizationInstance()
newRel.ObjectGuid = staffGuid
newRel.TargetGuid = orgGuid
newRel.RecordType = 0
newRel.IsLeader = params.IsLeader
if params.PositionGuid != "" {
posGuid, _ := unique.FromString(params.PositionGuid)
newRel.PositionGuid = posGuid
}
if err := tx.Create(newRel).Error; err != nil {
tx.Rollback()
return nil, process.FailError(types.CreateStaffError, err)
}
existingRel = *newRel
}
}
} else { // 分配兼职部门/岗位
if relQuery.Error == nil {
// 已存在关联,更新为兼职
if params.PositionGuid != "" {
posGuid, _ := unique.FromString(params.PositionGuid)
existingRel.PositionGuid = posGuid
}
existingRel.IsLeader = params.IsLeader
existingRel.RecordType = int16(params.RecordType)
if err := tx.Save(&existingRel).Error; err != nil {
tx.Rollback()
return nil, process.FailError(types.UpdateStaffError, err)
}
} else {
// 不存在关联,创建兼职记录
newRel := hr.Staff2OrganizationInstance()
newRel.ObjectGuid = staffGuid
newRel.TargetGuid = orgGuid
if params.RecordType == 0 {
newRel.RecordType = 1
} else {
newRel.RecordType = int16(params.RecordType)
}
newRel.IsLeader = params.IsLeader
if params.PositionGuid != "" {
posGuid, _ := unique.FromString(params.PositionGuid)
newRel.PositionGuid = posGuid
}
if err := tx.Create(newRel).Error; err != nil {
tx.Rollback()
return nil, process.FailError(types.CreateStaffError, err)
}
existingRel = *newRel
}
}
// 提交事务
tx.Commit()
// 构建返回结果
result := &StaffPositionRelDetail{
RecordGuid: existingRel.RecordGuid,
StaffGuid: staff.RecordGuid,
StaffName: staff.StaffName,
OrganizationGuid: org.RecordGuid,
OrganizationName: org.OrganizationName,
IsLeader: existingRel.IsLeader,
RecordType: int(existingRel.RecordType),
}
if params.PositionGuid != "" && position != nil {
result.PositionGuid = position.RecordGuid
result.PositionName = position.PositionName
}
return result, process.Success(200)
}
// UpdateStaffPosition 更新员工岗位关系
func UpdateStaffPosition(params UpdateStaffPositionRequest) (*StaffPositionRelDetail, *process.Process) {
// 验证关系记录ID
relGuid, err := unique.FromString(params.RecordGuid)
if err != nil {
return nil, process.FailError(types.InvalidParamError, err)
}
// 开始事务
tx := dblib.DBIns.DB.Begin()
// 查询关系记录是否存在
rel := &hr.Staff2OrganizationModel{}
r := tx.Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", relGuid).First(rel)
if r.Error != nil {
tx.Rollback()
return nil, process.FailError(types.OrgStaffRelNotFoundError, r.Error)
}
// 如果提供了岗位ID则验证岗位是否存在
var position *hr.PositionModel
if params.PositionGuid != "" {
posGuid, err := unique.FromString(params.PositionGuid)
if err != nil {
tx.Rollback()
return nil, process.FailError(types.InvalidParamError, err)
}
position = &hr.PositionModel{}
r = tx.Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", posGuid).First(position)
if r.Error != nil {
tx.Rollback()
return nil, process.FailError(types.PositionNotFoundError, r.Error)
}
// 检查岗位是否与组织关联
var count int64
r = tx.Model(&hr.OrgPositionRelModel{}).Where(
"OrganizationGuid = ? AND PositionGuid = ? AND (RecordStatus & 524288) = 0",
rel.TargetGuid, posGuid,
).Count(&count)
if r.Error != nil || count == 0 {
tx.Rollback()
return nil, process.FailError(types.InvalidPositionError, fmt.Errorf("岗位不属于指定组织"))
}
rel.PositionGuid = posGuid
}
// 更新其他字段
rel.IsLeader = params.IsLeader
rel.RecordType = int16(params.RecordType)
// 更新记录
r = tx.Save(rel)
if r.Error != nil {
tx.Rollback()
return nil, process.FailError(types.UpdateStaffError, r.Error)
}
// 如果这是主部门/岗位,则将其他关系更新为非主部门/岗位
if params.RecordType == 0 {
r = tx.Model(&hr.Staff2OrganizationModel{}).
Where("ObjectGuid = ? AND RecordGuid != ? AND RecordType = 0 AND (RecordStatus & 524288) = 0",
rel.ObjectGuid, rel.RecordGuid).
Update("RecordType", 1)
if r.Error != nil {
tx.Rollback()
return nil, process.FailError(types.UpdateStaffError, r.Error)
}
}
// 提交事务
tx.Commit()
// 查询员工和组织信息以构建返回结果
staff := &hr.StaffModel{}
dblib.DBIns.DB.Where("RecordGuid = ?", rel.ObjectGuid).First(staff)
org := &hr.OrganizationModel{}
dblib.DBIns.DB.Where("RecordGuid = ?", rel.TargetGuid).First(org)
// 构建返回结果
result := &StaffPositionRelDetail{
RecordGuid: rel.RecordGuid,
StaffGuid: staff.RecordGuid,
StaffName: staff.StaffName,
OrganizationGuid: org.RecordGuid,
OrganizationName: org.OrganizationName,
IsLeader: rel.IsLeader,
RecordType: int(rel.RecordType),
}
if position != nil {
result.PositionGuid = position.RecordGuid
result.PositionName = position.PositionName
} else if rel.PositionGuid != unique.NilUUID {
pos := &hr.PositionModel{}
dblib.DBIns.DB.Where("RecordGuid = ?", rel.PositionGuid).First(pos)
result.PositionGuid = pos.RecordGuid
result.PositionName = pos.PositionName
}
return result, process.Success(200)
}
// RemoveStaffPosition 移除员工的组织和岗位关联
func RemoveStaffPosition(params RemoveStaffPositionRequest) *process.Process {
// 验证员工ID
staffGuid, err := unique.FromString(params.StaffGuid)
if err != nil {
return process.FailError(types.InvalidParamError, err)
}
// 验证组织ID
orgGuid, err := unique.FromString(params.OrganizationGuid)
if err != nil {
return process.FailError(types.InvalidParamError, err)
}
// 查询关系记录是否存在
var rel hr.Staff2OrganizationModel
r := dblib.DBIns.DB.Where(
"ObjectGuid = ? AND TargetGuid = ? AND (RecordStatus & 524288) = 0",
staffGuid, orgGuid,
).First(&rel)
if r.Error != nil {
return process.FailError(types.OrgStaffRelNotFoundError, r.Error)
}
// 检查是否是员工的最后一个组织关联
var count int64
r = dblib.DBIns.DB.Model(&hr.Staff2OrganizationModel{}).
Where("ObjectGuid = ? AND (RecordStatus & 524288) = 0", staffGuid).
Count(&count)
if r.Error != nil {
return process.FailError(types.QueryStaffError, r.Error)
}
if count <= 1 {
return process.FailError(types.LastOrgRelError, fmt.Errorf("无法移除员工的最后一个组织关联"))
}
// 如果是主部门/岗位,需要将另一个关系设为主部门/岗位
if rel.RecordType == 0 {
// 查找一个非主部门/岗位关系
var otherRel hr.Staff2OrganizationModel
r = dblib.DBIns.DB.Where(
"ObjectGuid = ? AND RecordGuid != ? AND (RecordStatus & 524288) = 0",
staffGuid, rel.RecordGuid,
).First(&otherRel)
if r.Error == nil {
// 将此关系设为主部门/岗位
otherRel.RecordType = 0
dblib.DBIns.DB.Save(&otherRel)
}
}
// 软删除关系记录 - 直接使用SQL操作
r = dblib.DBIns.DB.Exec("UPDATE "+hr.Staff2OrganizationTable+" SET RecordStatus = RecordStatus | 524288 WHERE RecordGuid = ?", rel.RecordGuid)
if r.Error != nil {
return process.FailError(types.DeleteStaffError, r.Error)
}
return process.Success(200)
}
// GetStaffPositions 获取员工的所有组织和岗位关联
func GetStaffPositions(staffGuid string) ([]StaffPositionRelDetail, *process.Process) {
// 验证员工ID
guid, err := unique.FromString(staffGuid)
if err != nil {
return nil, process.FailError(types.InvalidParamError, err)
}
// 查询员工是否存在
staff := &hr.StaffModel{}
r := dblib.DBIns.DB.Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", guid).First(staff)
if r.Error != nil {
return nil, process.FailError(types.StaffNotFoundError, r.Error)
}
// 查询员工的所有组织和岗位关联
result := make([]StaffPositionRelDetail, 0)
rows, err := dblib.DBIns.DB.Raw(`
SELECT
so.RecordGuid,
o.RecordGuid as OrgGuid,
o.OrganizationName,
p.RecordGuid as PosGuid,
p.PositionName,
so.IsLeader,
so.RecordType
FROM
`+hr.Staff2OrganizationTable+` so
JOIN
`+hr.OrganizationTable+` o ON so.TargetGuid = o.RecordGuid
LEFT JOIN
`+hr.PositionTable+` p ON so.PositionGuid = p.RecordGuid
WHERE
so.ObjectGuid = ?
AND (so.RecordStatus & 524288) = 0
AND (o.RecordStatus & 524288) = 0
ORDER BY
so.RecordType ASC
`, guid).Rows()
if err != nil {
return nil, process.FailError(types.QueryStaffError, err)
}
defer rows.Close()
for rows.Next() {
var rel StaffPositionRelDetail
var relGuid, orgGuid, posGuid unique.UUID
var recordType int16
var isLeader bool
err := rows.Scan(
&relGuid,
&orgGuid,
&rel.OrganizationName,
&posGuid,
&rel.PositionName,
&isLeader,
&recordType,
)
if err != nil {
continue
}
rel.RecordGuid = relGuid
rel.StaffGuid, _ = unique.FromString(staffGuid)
rel.StaffName = staff.StaffName
rel.OrganizationGuid = orgGuid
rel.IsLeader = isLeader
rel.RecordType = int(recordType)
if posGuid != unique.NilUUID {
rel.PositionGuid = posGuid
}
result = append(result, rel)
}
return result, process.Success(200)
}