feat: 搭建后端多租户名片服务
- 初始化 Spring Boot 多模块工程与通用基础能力 - 增加租户、组织、用户、名片、文件、统计等业务模块 - 补充数据库迁移脚本与基础测试
This commit is contained in:
30
backend/easycard-module-org/pom.xml
Normal file
30
backend/easycard-module-org/pom.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.easycard</groupId>
|
||||
<artifactId>easycard-parent</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>easycard-module-org</artifactId>
|
||||
<name>easycard-module-org</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.easycard</groupId>
|
||||
<artifactId>easycard-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.easycard.module.org.controller;
|
||||
|
||||
import com.easycard.common.api.ApiResponse;
|
||||
import com.easycard.module.org.service.TenantOrgService;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/tenant")
|
||||
public class TenantOrgController {
|
||||
|
||||
private final TenantOrgService tenantOrgService;
|
||||
|
||||
public TenantOrgController(TenantOrgService tenantOrgService) {
|
||||
this.tenantOrgService = tenantOrgService;
|
||||
}
|
||||
|
||||
@GetMapping("/firm-profile")
|
||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN','TENANT_USER','PLATFORM_SUPER_ADMIN')")
|
||||
public ApiResponse<TenantOrgService.FirmProfileView> getFirmProfile() {
|
||||
return ApiResponse.success(tenantOrgService.getFirmProfile());
|
||||
}
|
||||
|
||||
@PutMapping("/firm-profile")
|
||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN','PLATFORM_SUPER_ADMIN')")
|
||||
public ApiResponse<TenantOrgService.FirmProfileView> saveFirmProfile(@Valid @RequestBody UpsertFirmProfileCommand request) {
|
||||
return ApiResponse.success(tenantOrgService.saveFirmProfile(request.toServiceRequest()));
|
||||
}
|
||||
|
||||
@GetMapping("/practice-areas")
|
||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN','TENANT_USER','PLATFORM_SUPER_ADMIN')")
|
||||
public ApiResponse<List<TenantOrgService.PracticeAreaView>> listPracticeAreas() {
|
||||
return ApiResponse.success(tenantOrgService.listPracticeAreas());
|
||||
}
|
||||
|
||||
@PostMapping("/practice-areas")
|
||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN','PLATFORM_SUPER_ADMIN')")
|
||||
public ApiResponse<TenantOrgService.PracticeAreaView> createPracticeArea(@Valid @RequestBody UpsertPracticeAreaCommand request) {
|
||||
return ApiResponse.success(tenantOrgService.createPracticeArea(request.toServiceRequest()));
|
||||
}
|
||||
|
||||
@PutMapping("/practice-areas/{areaId}")
|
||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN','PLATFORM_SUPER_ADMIN')")
|
||||
public ApiResponse<TenantOrgService.PracticeAreaView> updatePracticeArea(@PathVariable Long areaId, @Valid @RequestBody UpsertPracticeAreaCommand request) {
|
||||
return ApiResponse.success(tenantOrgService.updatePracticeArea(areaId, request.toServiceRequest()));
|
||||
}
|
||||
|
||||
@GetMapping("/departments")
|
||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN','TENANT_USER','PLATFORM_SUPER_ADMIN')")
|
||||
public ApiResponse<List<TenantOrgService.DepartmentView>> listDepartments() {
|
||||
return ApiResponse.success(tenantOrgService.listDepartments());
|
||||
}
|
||||
|
||||
@PostMapping("/departments")
|
||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN','PLATFORM_SUPER_ADMIN')")
|
||||
public ApiResponse<TenantOrgService.DepartmentView> createDepartment(@Valid @RequestBody UpsertDepartmentCommand request) {
|
||||
return ApiResponse.success(tenantOrgService.createDepartment(request.toServiceRequest()));
|
||||
}
|
||||
|
||||
@PutMapping("/departments/{deptId}")
|
||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN','PLATFORM_SUPER_ADMIN')")
|
||||
public ApiResponse<TenantOrgService.DepartmentView> updateDepartment(@PathVariable Long deptId, @Valid @RequestBody UpsertDepartmentCommand request) {
|
||||
return ApiResponse.success(tenantOrgService.updateDepartment(deptId, request.toServiceRequest()));
|
||||
}
|
||||
}
|
||||
|
||||
record UpsertFirmProfileCommand(
|
||||
@NotBlank(message = "事务所名称不能为空") String firmName,
|
||||
String firmShortName,
|
||||
String englishName,
|
||||
Long logoAssetId,
|
||||
Long heroAssetId,
|
||||
String intro,
|
||||
String hotlinePhone,
|
||||
String websiteUrl,
|
||||
String wechatOfficialAccount,
|
||||
String hqAddress,
|
||||
String hqLatitude,
|
||||
String hqLongitude
|
||||
) {
|
||||
TenantOrgService.UpsertFirmProfileRequest toServiceRequest() {
|
||||
return new TenantOrgService.UpsertFirmProfileRequest(
|
||||
firmName, firmShortName, englishName, logoAssetId, heroAssetId, intro, hotlinePhone,
|
||||
websiteUrl, wechatOfficialAccount, hqAddress, hqLatitude, hqLongitude
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
record UpsertPracticeAreaCommand(
|
||||
@NotBlank(message = "专业编码不能为空") String areaCode,
|
||||
@NotBlank(message = "专业名称不能为空") String areaName,
|
||||
Integer displayOrder,
|
||||
@NotBlank(message = "状态不能为空") String areaStatus
|
||||
) {
|
||||
TenantOrgService.UpsertPracticeAreaRequest toServiceRequest() {
|
||||
return new TenantOrgService.UpsertPracticeAreaRequest(areaCode, areaName, displayOrder == null ? 0 : displayOrder, areaStatus);
|
||||
}
|
||||
}
|
||||
|
||||
record UpsertDepartmentCommand(
|
||||
Long parentId,
|
||||
@NotBlank(message = "组织编码不能为空") String deptCode,
|
||||
@NotBlank(message = "组织名称不能为空") String deptName,
|
||||
@NotBlank(message = "组织类型不能为空") String deptType,
|
||||
String contactPhone,
|
||||
String address,
|
||||
Integer displayOrder,
|
||||
@NotBlank(message = "状态不能为空") String deptStatus
|
||||
) {
|
||||
TenantOrgService.UpsertDepartmentRequest toServiceRequest() {
|
||||
return new TenantOrgService.UpsertDepartmentRequest(parentId, deptCode, deptName, deptType, contactPhone, address, displayOrder == null ? 0 : displayOrder, deptStatus);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.easycard.module.org.dal.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@TableName("file_asset")
|
||||
public class FileAssetLiteDO {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
private String bucketName;
|
||||
private String objectKey;
|
||||
private String accessUrl;
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.easycard.module.org.dal.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("org_department")
|
||||
public class OrgDepartmentDO {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
private Long tenantId;
|
||||
private Long parentId;
|
||||
private String deptCode;
|
||||
private String deptName;
|
||||
private String deptType;
|
||||
private Long leaderUserId;
|
||||
private String contactPhone;
|
||||
private String address;
|
||||
private Integer displayOrder;
|
||||
private String deptStatus;
|
||||
private Long createdBy;
|
||||
private LocalDateTime createdTime;
|
||||
private Long updatedBy;
|
||||
private LocalDateTime updatedTime;
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.easycard.module.org.dal.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("org_firm_practice_area")
|
||||
public class OrgFirmPracticeAreaDO {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
private Long tenantId;
|
||||
private String areaCode;
|
||||
private String areaName;
|
||||
private Integer displayOrder;
|
||||
private String areaStatus;
|
||||
private Long createdBy;
|
||||
private LocalDateTime createdTime;
|
||||
private Long updatedBy;
|
||||
private LocalDateTime updatedTime;
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.easycard.module.org.dal.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("org_firm_profile")
|
||||
public class OrgFirmProfileDO {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
private Long tenantId;
|
||||
private String firmName;
|
||||
private String firmShortName;
|
||||
private String englishName;
|
||||
private Long logoAssetId;
|
||||
private Long heroAssetId;
|
||||
private String intro;
|
||||
private String hotlinePhone;
|
||||
private String websiteUrl;
|
||||
private String wechatOfficialAccount;
|
||||
private String hqAddress;
|
||||
private BigDecimal hqLatitude;
|
||||
private BigDecimal hqLongitude;
|
||||
private Long createdBy;
|
||||
private LocalDateTime createdTime;
|
||||
private Long updatedBy;
|
||||
private LocalDateTime updatedTime;
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.easycard.module.org.dal.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.easycard.module.org.dal.entity.FileAssetLiteDO;
|
||||
|
||||
public interface FileAssetLiteMapper extends BaseMapper<FileAssetLiteDO> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.easycard.module.org.dal.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.easycard.module.org.dal.entity.OrgDepartmentDO;
|
||||
|
||||
public interface OrgDepartmentMapper extends BaseMapper<OrgDepartmentDO> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.easycard.module.org.dal.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.easycard.module.org.dal.entity.OrgFirmPracticeAreaDO;
|
||||
|
||||
public interface OrgFirmPracticeAreaMapper extends BaseMapper<OrgFirmPracticeAreaDO> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.easycard.module.org.dal.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.easycard.module.org.dal.entity.OrgFirmProfileDO;
|
||||
|
||||
public interface OrgFirmProfileMapper extends BaseMapper<OrgFirmProfileDO> {
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
package com.easycard.module.org.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.easycard.common.auth.LoginUser;
|
||||
import com.easycard.common.auth.SecurityUtils;
|
||||
import com.easycard.common.exception.BusinessException;
|
||||
import com.easycard.common.storage.StorageUrlUtils;
|
||||
import com.easycard.module.org.dal.entity.FileAssetLiteDO;
|
||||
import com.easycard.module.org.dal.mapper.FileAssetLiteMapper;
|
||||
import com.easycard.module.org.dal.entity.OrgDepartmentDO;
|
||||
import com.easycard.module.org.dal.entity.OrgFirmPracticeAreaDO;
|
||||
import com.easycard.module.org.dal.entity.OrgFirmProfileDO;
|
||||
import com.easycard.module.org.dal.mapper.OrgDepartmentMapper;
|
||||
import com.easycard.module.org.dal.mapper.OrgFirmPracticeAreaMapper;
|
||||
import com.easycard.module.org.dal.mapper.OrgFirmProfileMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TenantOrgService {
|
||||
|
||||
@Value("${easycard.storage.public-endpoint:${easycard.storage.endpoint}}")
|
||||
private String publicEndpoint;
|
||||
|
||||
private final OrgFirmProfileMapper orgFirmProfileMapper;
|
||||
private final OrgFirmPracticeAreaMapper orgFirmPracticeAreaMapper;
|
||||
private final OrgDepartmentMapper orgDepartmentMapper;
|
||||
private final FileAssetLiteMapper fileAssetLiteMapper;
|
||||
|
||||
public FirmProfileView getFirmProfile() {
|
||||
LoginUser loginUser = SecurityUtils.getRequiredLoginUser();
|
||||
OrgFirmProfileDO profile = orgFirmProfileMapper.selectOne(Wrappers.<OrgFirmProfileDO>lambdaQuery()
|
||||
.eq(OrgFirmProfileDO::getTenantId, loginUser.tenantId())
|
||||
.eq(OrgFirmProfileDO::getDeleted, 0)
|
||||
.last("LIMIT 1"));
|
||||
if (profile == null) {
|
||||
return new FirmProfileView(null, "", "", "", null, "", null, "", "", "", "", "", "", null, null);
|
||||
}
|
||||
return toView(profile);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public FirmProfileView saveFirmProfile(UpsertFirmProfileRequest request) {
|
||||
LoginUser loginUser = SecurityUtils.getRequiredLoginUser();
|
||||
OrgFirmProfileDO profile = orgFirmProfileMapper.selectOne(Wrappers.<OrgFirmProfileDO>lambdaQuery()
|
||||
.eq(OrgFirmProfileDO::getTenantId, loginUser.tenantId())
|
||||
.eq(OrgFirmProfileDO::getDeleted, 0)
|
||||
.last("LIMIT 1"));
|
||||
if (profile == null) {
|
||||
profile = new OrgFirmProfileDO();
|
||||
profile.setTenantId(loginUser.tenantId());
|
||||
profile.setCreatedBy(loginUser.userId());
|
||||
profile.setDeleted(0);
|
||||
}
|
||||
profile.setFirmName(request.firmName());
|
||||
profile.setFirmShortName(request.firmShortName());
|
||||
profile.setEnglishName(request.englishName());
|
||||
profile.setLogoAssetId(request.logoAssetId());
|
||||
profile.setHeroAssetId(request.heroAssetId());
|
||||
profile.setIntro(request.intro());
|
||||
profile.setHotlinePhone(request.hotlinePhone());
|
||||
profile.setWebsiteUrl(request.websiteUrl());
|
||||
profile.setWechatOfficialAccount(request.wechatOfficialAccount());
|
||||
profile.setHqAddress(request.hqAddress());
|
||||
profile.setHqLatitude(toBigDecimal(request.hqLatitude()));
|
||||
profile.setHqLongitude(toBigDecimal(request.hqLongitude()));
|
||||
profile.setUpdatedBy(loginUser.userId());
|
||||
if (profile.getId() == null) {
|
||||
orgFirmProfileMapper.insert(profile);
|
||||
} else {
|
||||
orgFirmProfileMapper.updateById(profile);
|
||||
}
|
||||
return toView(profile);
|
||||
}
|
||||
|
||||
public List<PracticeAreaView> listPracticeAreas() {
|
||||
LoginUser loginUser = SecurityUtils.getRequiredLoginUser();
|
||||
return orgFirmPracticeAreaMapper.selectList(Wrappers.<OrgFirmPracticeAreaDO>lambdaQuery()
|
||||
.eq(OrgFirmPracticeAreaDO::getTenantId, loginUser.tenantId())
|
||||
.eq(OrgFirmPracticeAreaDO::getDeleted, 0)
|
||||
.orderByAsc(OrgFirmPracticeAreaDO::getDisplayOrder, OrgFirmPracticeAreaDO::getId))
|
||||
.stream()
|
||||
.map(item -> new PracticeAreaView(item.getId(), item.getAreaCode(), item.getAreaName(), item.getDisplayOrder(), item.getAreaStatus()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public PracticeAreaView createPracticeArea(UpsertPracticeAreaRequest request) {
|
||||
LoginUser loginUser = SecurityUtils.getRequiredLoginUser();
|
||||
OrgFirmPracticeAreaDO existed = orgFirmPracticeAreaMapper.selectOne(Wrappers.<OrgFirmPracticeAreaDO>lambdaQuery()
|
||||
.eq(OrgFirmPracticeAreaDO::getTenantId, loginUser.tenantId())
|
||||
.eq(OrgFirmPracticeAreaDO::getAreaCode, request.areaCode())
|
||||
.eq(OrgFirmPracticeAreaDO::getDeleted, 0)
|
||||
.last("LIMIT 1"));
|
||||
if (existed != null) {
|
||||
throw new BusinessException("AREA_CODE_DUPLICATED", "专业领域编码已存在");
|
||||
}
|
||||
OrgFirmPracticeAreaDO area = new OrgFirmPracticeAreaDO();
|
||||
area.setTenantId(loginUser.tenantId());
|
||||
area.setAreaCode(request.areaCode());
|
||||
area.setAreaName(request.areaName());
|
||||
area.setDisplayOrder(request.displayOrder());
|
||||
area.setAreaStatus(request.areaStatus());
|
||||
area.setCreatedBy(loginUser.userId());
|
||||
area.setUpdatedBy(loginUser.userId());
|
||||
area.setDeleted(0);
|
||||
orgFirmPracticeAreaMapper.insert(area);
|
||||
return new PracticeAreaView(area.getId(), area.getAreaCode(), area.getAreaName(), area.getDisplayOrder(), area.getAreaStatus());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public PracticeAreaView updatePracticeArea(Long areaId, UpsertPracticeAreaRequest request) {
|
||||
LoginUser loginUser = SecurityUtils.getRequiredLoginUser();
|
||||
OrgFirmPracticeAreaDO area = getPracticeArea(areaId, loginUser.tenantId());
|
||||
area.setAreaName(request.areaName());
|
||||
area.setDisplayOrder(request.displayOrder());
|
||||
area.setAreaStatus(request.areaStatus());
|
||||
area.setUpdatedBy(loginUser.userId());
|
||||
orgFirmPracticeAreaMapper.updateById(area);
|
||||
return new PracticeAreaView(area.getId(), area.getAreaCode(), area.getAreaName(), area.getDisplayOrder(), area.getAreaStatus());
|
||||
}
|
||||
|
||||
public List<DepartmentView> listDepartments() {
|
||||
LoginUser loginUser = SecurityUtils.getRequiredLoginUser();
|
||||
return orgDepartmentMapper.selectList(Wrappers.<OrgDepartmentDO>lambdaQuery()
|
||||
.eq(OrgDepartmentDO::getTenantId, loginUser.tenantId())
|
||||
.eq(OrgDepartmentDO::getDeleted, 0)
|
||||
.orderByAsc(OrgDepartmentDO::getDisplayOrder, OrgDepartmentDO::getId))
|
||||
.stream()
|
||||
.map(item -> new DepartmentView(item.getId(), item.getParentId(), item.getDeptCode(), item.getDeptName(), item.getDeptType(), item.getContactPhone(), item.getAddress(), item.getDisplayOrder(), item.getDeptStatus()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public DepartmentView createDepartment(UpsertDepartmentRequest request) {
|
||||
LoginUser loginUser = SecurityUtils.getRequiredLoginUser();
|
||||
OrgDepartmentDO existed = orgDepartmentMapper.selectOne(Wrappers.<OrgDepartmentDO>lambdaQuery()
|
||||
.eq(OrgDepartmentDO::getTenantId, loginUser.tenantId())
|
||||
.eq(OrgDepartmentDO::getDeptCode, request.deptCode())
|
||||
.eq(OrgDepartmentDO::getDeleted, 0)
|
||||
.last("LIMIT 1"));
|
||||
if (existed != null) {
|
||||
throw new BusinessException("DEPT_CODE_DUPLICATED", "组织编码已存在");
|
||||
}
|
||||
OrgDepartmentDO department = new OrgDepartmentDO();
|
||||
department.setTenantId(loginUser.tenantId());
|
||||
department.setParentId(request.parentId() == null ? 0L : request.parentId());
|
||||
department.setDeptCode(request.deptCode());
|
||||
department.setDeptName(request.deptName());
|
||||
department.setDeptType(request.deptType());
|
||||
department.setContactPhone(request.contactPhone());
|
||||
department.setAddress(request.address());
|
||||
department.setDisplayOrder(request.displayOrder());
|
||||
department.setDeptStatus(request.deptStatus());
|
||||
department.setCreatedBy(loginUser.userId());
|
||||
department.setUpdatedBy(loginUser.userId());
|
||||
department.setDeleted(0);
|
||||
orgDepartmentMapper.insert(department);
|
||||
return new DepartmentView(department.getId(), department.getParentId(), department.getDeptCode(), department.getDeptName(), department.getDeptType(), department.getContactPhone(), department.getAddress(), department.getDisplayOrder(), department.getDeptStatus());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public DepartmentView updateDepartment(Long deptId, UpsertDepartmentRequest request) {
|
||||
LoginUser loginUser = SecurityUtils.getRequiredLoginUser();
|
||||
OrgDepartmentDO department = getDepartment(deptId, loginUser.tenantId());
|
||||
department.setParentId(request.parentId() == null ? 0L : request.parentId());
|
||||
department.setDeptName(request.deptName());
|
||||
department.setDeptType(request.deptType());
|
||||
department.setContactPhone(request.contactPhone());
|
||||
department.setAddress(request.address());
|
||||
department.setDisplayOrder(request.displayOrder());
|
||||
department.setDeptStatus(request.deptStatus());
|
||||
department.setUpdatedBy(loginUser.userId());
|
||||
orgDepartmentMapper.updateById(department);
|
||||
return new DepartmentView(department.getId(), department.getParentId(), department.getDeptCode(), department.getDeptName(), department.getDeptType(), department.getContactPhone(), department.getAddress(), department.getDisplayOrder(), department.getDeptStatus());
|
||||
}
|
||||
|
||||
private OrgDepartmentDO getDepartment(Long deptId, Long tenantId) {
|
||||
OrgDepartmentDO department = orgDepartmentMapper.selectById(deptId);
|
||||
if (department == null || Integer.valueOf(1).equals(department.getDeleted()) || !tenantId.equals(department.getTenantId())) {
|
||||
throw new BusinessException("DEPARTMENT_NOT_FOUND", "组织不存在");
|
||||
}
|
||||
return department;
|
||||
}
|
||||
|
||||
private OrgFirmPracticeAreaDO getPracticeArea(Long areaId, Long tenantId) {
|
||||
OrgFirmPracticeAreaDO area = orgFirmPracticeAreaMapper.selectById(areaId);
|
||||
if (area == null || Integer.valueOf(1).equals(area.getDeleted()) || !tenantId.equals(area.getTenantId())) {
|
||||
throw new BusinessException("PRACTICE_AREA_NOT_FOUND", "专业领域不存在");
|
||||
}
|
||||
return area;
|
||||
}
|
||||
|
||||
private FirmProfileView toView(OrgFirmProfileDO profile) {
|
||||
return new FirmProfileView(
|
||||
profile.getId(),
|
||||
profile.getFirmName(),
|
||||
profile.getFirmShortName(),
|
||||
profile.getEnglishName(),
|
||||
profile.getLogoAssetId(),
|
||||
resolveAssetUrl(profile.getLogoAssetId()),
|
||||
profile.getHeroAssetId(),
|
||||
resolveAssetUrl(profile.getHeroAssetId()),
|
||||
profile.getIntro(),
|
||||
profile.getHotlinePhone(),
|
||||
profile.getWebsiteUrl(),
|
||||
profile.getWechatOfficialAccount(),
|
||||
profile.getHqAddress(),
|
||||
profile.getHqLatitude(),
|
||||
profile.getHqLongitude()
|
||||
);
|
||||
}
|
||||
|
||||
private BigDecimal toBigDecimal(String value) {
|
||||
if (value == null || value.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
return new BigDecimal(value);
|
||||
}
|
||||
|
||||
private String resolveAssetUrl(Long assetId) {
|
||||
if (assetId == null) {
|
||||
return "";
|
||||
}
|
||||
FileAssetLiteDO asset = fileAssetLiteMapper.selectById(assetId);
|
||||
if (asset == null || Integer.valueOf(1).equals(asset.getDeleted())) {
|
||||
return "";
|
||||
}
|
||||
return StorageUrlUtils.buildPublicUrl(publicEndpoint, asset.getBucketName(), asset.getObjectKey(), asset.getAccessUrl());
|
||||
}
|
||||
|
||||
public record FirmProfileView(
|
||||
Long id,
|
||||
String firmName,
|
||||
String firmShortName,
|
||||
String englishName,
|
||||
Long logoAssetId,
|
||||
String logoUrl,
|
||||
Long heroAssetId,
|
||||
String heroUrl,
|
||||
String intro,
|
||||
String hotlinePhone,
|
||||
String websiteUrl,
|
||||
String wechatOfficialAccount,
|
||||
String hqAddress,
|
||||
BigDecimal hqLatitude,
|
||||
BigDecimal hqLongitude
|
||||
) {
|
||||
}
|
||||
|
||||
public record UpsertFirmProfileRequest(
|
||||
String firmName,
|
||||
String firmShortName,
|
||||
String englishName,
|
||||
Long logoAssetId,
|
||||
Long heroAssetId,
|
||||
String intro,
|
||||
String hotlinePhone,
|
||||
String websiteUrl,
|
||||
String wechatOfficialAccount,
|
||||
String hqAddress,
|
||||
String hqLatitude,
|
||||
String hqLongitude
|
||||
) {
|
||||
}
|
||||
|
||||
public record PracticeAreaView(Long id, String areaCode, String areaName, Integer displayOrder, String areaStatus) {
|
||||
}
|
||||
|
||||
public record UpsertPracticeAreaRequest(String areaCode, String areaName, Integer displayOrder, String areaStatus) {
|
||||
}
|
||||
|
||||
public record DepartmentView(
|
||||
Long id,
|
||||
Long parentId,
|
||||
String deptCode,
|
||||
String deptName,
|
||||
String deptType,
|
||||
String contactPhone,
|
||||
String address,
|
||||
Integer displayOrder,
|
||||
String deptStatus
|
||||
) {
|
||||
}
|
||||
|
||||
public record UpsertDepartmentRequest(
|
||||
Long parentId,
|
||||
String deptCode,
|
||||
String deptName,
|
||||
String deptType,
|
||||
String contactPhone,
|
||||
String address,
|
||||
Integer displayOrder,
|
||||
String deptStatus
|
||||
) {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user