package cn.iocoder.yudao.module.ums.service.member;
|
|
import cn.hutool.core.util.StrUtil;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.module.archive.api.document.ArchiveDocumentApi;
|
import cn.iocoder.yudao.module.archive.api.document.dto.ArchiveDocumentCreateReqDTO;
|
import cn.iocoder.yudao.module.archive.api.document.dto.ArchiveDocumentRespDTO;
|
import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi;
|
import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO;
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserCreateReqDTO;
|
import cn.iocoder.yudao.module.ums.controller.admin.member.vo.UmsMemberPageReqVO;
|
import cn.iocoder.yudao.module.ums.controller.admin.member.vo.UmsMemberSaveReqVO;
|
import cn.iocoder.yudao.module.ums.dal.dataobject.application.UmsApplicationDO;
|
import cn.iocoder.yudao.module.ums.dal.dataobject.member.UmsMemberDO;
|
import cn.iocoder.yudao.module.ums.dal.mysql.member.UmsMemberMapper;
|
import cn.iocoder.yudao.module.ums.dal.redis.UmsNoRedisDAO;
|
import jakarta.annotation.Resource;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.validation.annotation.Validated;
|
|
import java.time.LocalDate;
|
import java.util.Collections;
|
import java.util.List;
|
import java.util.Set;
|
import java.util.stream.Collectors;
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.module.ums.enums.ErrorCodeConstants.*;
|
|
@Service
|
@Validated
|
@Slf4j
|
public class UmsMemberServiceImpl implements UmsMemberService {
|
|
/**
|
* 会员系统账号默认部门 ID(system_dept 中「学会会员」)
|
*/
|
private static final Long MEMBER_DEPT_ID = 129L;
|
|
public static final String MEMBER_RECORD_TYPE = "ums_member";
|
|
/** 会员状态:正常(可归档) */
|
private static final Integer MEMBER_STATUS_NORMAL = 1;
|
|
/** 归档来源类型:3-会员(对应 archive 模块 source_type) */
|
private static final Integer ARCHIVE_SOURCE_TYPE_MEMBER = 3;
|
|
/** 归档密级:2-内部 */
|
private static final Integer ARCHIVE_SECRET_LEVEL_INTERNAL = 2;
|
|
/** 会员档案分类编码(对应 archive_category.code) */
|
private static final String ARCHIVE_CATEGORY_CODE_MEMBER = "member";
|
|
@Resource
|
private UmsMemberMapper memberMapper;
|
|
@Resource
|
private UmsNoRedisDAO noRedisDAO;
|
|
@Resource
|
private AdminUserApi adminUserApi;
|
|
@Resource
|
private StorageAttachmentApi storageAttachmentApi;
|
|
@Resource
|
private ArchiveDocumentApi archiveDocumentApi;
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public UmsMemberDO createMemberFromApplication(UmsApplicationDO application) {
|
// 1. 生成会员编号
|
String no = noRedisDAO.generate(UmsNoRedisDAO.MEMBER_NO_PREFIX);
|
if (memberMapper.selectByNo(no) != null) {
|
throw exception(MEMBER_NO_EXISTS);
|
}
|
|
// 2. 创建系统用户账号
|
Long userId = createSystemUser(application);
|
|
// 3. 创建会员记录
|
UmsMemberDO member = UmsMemberDO.builder()
|
.no(no)
|
.userId(userId)
|
.applicationId(application.getId())
|
.memberType(application.getMemberType())
|
.memberGrade(application.getMemberGrade())
|
.name(application.getApplicantName())
|
.contactPhone(application.getContactPhone())
|
.contactEmail(application.getContactEmail())
|
.legalPerson(application.getLegalPerson())
|
.organizationCode(application.getOrganizationCode())
|
.researchDirection(application.getResearchDirection())
|
.workUnit(application.getWorkUnit())
|
.title(application.getTitle())
|
.regionCode(application.getRegionCode())
|
.industry(application.getIndustry())
|
.joinDate(LocalDate.now())
|
.status(1) // 正常
|
.build();
|
memberMapper.insert(member);
|
|
return member;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Long createMember(UmsMemberSaveReqVO createReqVO) {
|
String no = noRedisDAO.generate(UmsNoRedisDAO.MEMBER_NO_PREFIX);
|
if (memberMapper.selectByNo(no) != null) {
|
throw exception(MEMBER_NO_EXISTS);
|
}
|
|
// 会员等级与类型匹配校验
|
validateMemberGrade(createReqVO.getMemberType(), createReqVO.getMemberGrade());
|
|
UmsMemberDO member = BeanUtils.toBean(createReqVO, UmsMemberDO.class, in -> in
|
.setNo(no)
|
.setStatus(createReqVO.getStatus() != null ? createReqVO.getStatus() : 1)
|
.setJoinDate(createReqVO.getJoinDate() != null ? createReqVO.getJoinDate() : LocalDate.now()));
|
memberMapper.insert(member);
|
|
storageAttachmentApi.bindAttachments("file", MEMBER_RECORD_TYPE,
|
member.getId(), createReqVO.getBlobIds());
|
|
return member.getId();
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void updateMember(UmsMemberSaveReqVO updateReqVO) {
|
validateMemberExists(updateReqVO.getId());
|
validateMemberGrade(updateReqVO.getMemberType(), updateReqVO.getMemberGrade());
|
|
UmsMemberDO updateObj = BeanUtils.toBean(updateReqVO, UmsMemberDO.class);
|
memberMapper.updateById(updateObj);
|
|
storageAttachmentApi.updateAttachments("file", MEMBER_RECORD_TYPE,
|
updateReqVO.getId(), updateReqVO.getBlobIds());
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void deleteMember(Long id) {
|
validateMemberExists(id);
|
memberMapper.deleteById(id);
|
storageAttachmentApi.deleteAttachmentsByRecord(MEMBER_RECORD_TYPE, id);
|
}
|
|
@Override
|
public UmsMemberDO getMember(Long id) {
|
return memberMapper.selectById(id);
|
}
|
|
@Override
|
public UmsMemberDO getMemberByUserId(Long userId) {
|
return memberMapper.selectByUserId(userId);
|
}
|
|
@Override
|
public PageResult<UmsMemberDO> getMemberPage(UmsMemberPageReqVO pageReqVO) {
|
return memberMapper.selectPage(pageReqVO);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public String archiveMember(Long id) {
|
// 1.1 校验会员存在
|
UmsMemberDO member = validateMemberExists(id);
|
// 1.2 只有「正常」状态的会员才能归档
|
if (!MEMBER_STATUS_NORMAL.equals(member.getStatus())) {
|
throw exception(MEMBER_ARCHIVE_FAIL_STATUS, member.getNo(), memberStatusName(member.getStatus()));
|
}
|
// 1.3 重复归档校验
|
if (member.getArchiveDocumentId() != null) {
|
throw exception(MEMBER_ALREADY_ARCHIVED, member.getNo(),
|
StrUtil.blankToDefault(archiveNo(id), "未知"));
|
}
|
|
// 2. 带入会员材料附件,按来源单据归档
|
List<Long> blobIds = storageAttachmentApi.listAttachments(MEMBER_RECORD_TYPE, id).stream()
|
.map(StorageBlobRespDTO::getId).collect(Collectors.toList());
|
Long archiveDocumentId = archiveDocumentApi.archiveBySource(new ArchiveDocumentCreateReqDTO()
|
.setSourceType(ARCHIVE_SOURCE_TYPE_MEMBER)
|
.setSourceId(id)
|
.setSourceNo(member.getNo())
|
.setSourceTitle(member.getName())
|
.setCategoryCode(ARCHIVE_CATEGORY_CODE_MEMBER)
|
.setSecretLevel(ARCHIVE_SECRET_LEVEL_INTERNAL)
|
.setSummary("会员材料归档")
|
.setBlobIds(blobIds)).getCheckedData();
|
|
// 3. 回写归档档案 ID(作为已归档硬标记)
|
memberMapper.updateById(new UmsMemberDO().setId(id).setArchiveDocumentId(archiveDocumentId));
|
return StrUtil.blankToDefault(archiveNo(id), "未知");
|
}
|
|
// =================== 内部方法 ===================
|
|
private Long createSystemUser(UmsApplicationDO application) {
|
// 手机号可作为用户名/密码(参考 HRM 员工模式)
|
String mobile = StrUtil.blankToDefault(application.getContactPhone(), "unknown");
|
String username = mobile;
|
String nickname = application.getApplicantName();
|
|
try {
|
return adminUserApi.createUser(new AdminUserCreateReqDTO()
|
.setUsername(username)
|
.setNickname(nickname)
|
.setDeptId(MEMBER_DEPT_ID)
|
.setPostIds(Collections.emptySet())
|
.setMobile(mobile)
|
.setPassword(mobile) // 默认密码为手机号
|
.setEmail(application.getContactEmail())
|
.setRemark("由入会申请自动创建:" + application.getNo()));
|
} catch (Exception e) {
|
log.error("[createSystemUser] 创建会员系统账号失败,申请单={}", application.getId(), e);
|
// 如果手机号重复,给出明确提示
|
if (e.getMessage() != null && e.getMessage().contains("手机号")) {
|
throw exception(MEMBER_USER_MOBILE_EXISTS);
|
}
|
throw exception(MEMBER_USER_CREATE_FAIL);
|
}
|
}
|
|
/**
|
* 校验会员等级与类型匹配:单位会员(type=2)不可选个人专有等级「5-理事长」
|
*/
|
private void validateMemberGrade(Integer memberType, String memberGrade) {
|
if (memberType == null || StrUtil.isBlank(memberGrade)) {
|
return;
|
}
|
if (memberType == 2 && "5".equals(memberGrade)) {
|
throw exception(MEMBER_GRADE_NOT_MATCH_TYPE);
|
}
|
}
|
|
private UmsMemberDO validateMemberExists(Long id) {
|
UmsMemberDO member = memberMapper.selectById(id);
|
if (member == null) {
|
throw exception(MEMBER_NOT_EXISTS);
|
}
|
return member;
|
}
|
|
/** 会员状态中文名:1-正常 0-暂停(用于归档失败提示) */
|
private String memberStatusName(Integer status) {
|
if (status == null) {
|
return "未知";
|
}
|
return MEMBER_STATUS_NORMAL.equals(status) ? "正常" : "暂停";
|
}
|
|
/** 查询来源单据已生成的档案编号(未归档时返回 null) */
|
private String archiveNo(Long memberId) {
|
ArchiveDocumentRespDTO archive = archiveDocumentApi
|
.getBySource(ARCHIVE_SOURCE_TYPE_MEMBER, memberId).getCheckedData();
|
return archive != null ? archive.getNo() : null;
|
}
|
|
}
|