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

505 lines
16 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"
)
// 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)
}