This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package jnpf.storecertificatephoto.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.certificate.service.CertificateInstanceService;
|
||||
import jnpf.model.certificate.po.CertificateInstanceEntity;
|
||||
import jnpf.model.storecertificatephoto.po.StoreCertificatePhotoEntity;
|
||||
import jnpf.model.storecertificatephoto.req.StoreCertificatePhotoAddReq;
|
||||
import jnpf.model.storecertificatephoto.req.StoreCertificatePhotoUpdateReq;
|
||||
import jnpf.model.storecertificatephoto.vo.StoreCertificatePhotoVO;
|
||||
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
|
||||
import jnpf.permission.StoreApi;
|
||||
import jnpf.permission.V2OrganizeApi;
|
||||
import jnpf.permission.dto.store.StoreBaseInfoIdsQueryDTO;
|
||||
import jnpf.permission.vo.store.BaseStoreVO;
|
||||
import jnpf.permission.vo.v2.organzie.OrganizeGeneralDetailVO;
|
||||
import jnpf.storecertificatephoto.service.StoreCertificatePhotoService;
|
||||
import jnpf.util.UserProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* web门店自定义证件配置照控制器
|
||||
*/
|
||||
@RestController
|
||||
@Validated
|
||||
@RequestMapping("/web/store-certificate-photo")
|
||||
public class StoreCertificatePhotoController {
|
||||
|
||||
@Autowired
|
||||
private StoreCertificatePhotoService storeCertificatePhotoService;
|
||||
@Autowired
|
||||
private CertificateInstanceService certificateInstanceService;
|
||||
@Autowired
|
||||
private V2OrganizeApi v2OrganizeApi;
|
||||
@Autowired
|
||||
private StoreApi storeApi;
|
||||
|
||||
/**
|
||||
* 新增门店证件照配置
|
||||
*
|
||||
* @param req 门店证件照请求参数
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public ActionResult<Void> add(@Validated @RequestBody StoreCertificatePhotoAddReq req) {
|
||||
storeCertificatePhotoService.add(req);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑门店自定义证件配置配置
|
||||
*
|
||||
* @param req 门店证件照编辑参数
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PutMapping("/update")
|
||||
public ActionResult<Void> update(@Validated @RequestBody StoreCertificatePhotoUpdateReq req) {
|
||||
storeCertificatePhotoService.update(req);
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除门店自定义证件配置配置
|
||||
*
|
||||
* @param id 门店证照自定义配置id
|
||||
* @return 操作结果
|
||||
*/
|
||||
@DeleteMapping("/delete/{id}")
|
||||
public ActionResult<Void> delete(@PathVariable("id") String id) {
|
||||
Set<String> orgIds = certificateInstanceService.list(new LambdaQueryWrapper<CertificateInstanceEntity>()
|
||||
.eq(CertificateInstanceEntity::getTemplateId,id)
|
||||
.eq(CertificateInstanceEntity::getEnabledMark,0))
|
||||
.stream()
|
||||
.map(CertificateInstanceEntity::getSubjectId)
|
||||
.collect(Collectors.toSet());
|
||||
if(CollectionUtils.isNotEmpty(orgIds)){
|
||||
List<BaseStoreVO> baseStoreVOS = storeApi.listBaseInfoByIds(new StoreBaseInfoIdsQueryDTO(orgIds,UserProvider.getUser().getTenantId()));
|
||||
String orgNames = baseStoreVOS.stream().map(BaseStoreVO::getStoreName).collect(Collectors.joining(","));
|
||||
return ActionResult.fail(400,"已被["+orgNames+"]门店使用,不能删除!");
|
||||
}
|
||||
|
||||
boolean succ = storeCertificatePhotoService.update(new LambdaUpdateWrapper<StoreCertificatePhotoEntity>()
|
||||
.eq(StoreCertificatePhotoEntity::getId,id)
|
||||
.set(StoreCertificatePhotoEntity::getEnabledMark,1)
|
||||
.set(StoreCertificatePhotoEntity::getLastModifyUserId, UserProvider.getLoginUserId())
|
||||
.set(StoreCertificatePhotoEntity::getLastModifyTime,new Date()));
|
||||
return ActionResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询门店自定义证件配置列表
|
||||
*
|
||||
* @return 门店证件照列表
|
||||
*/
|
||||
@GetMapping("/query-list")
|
||||
public ActionResult<List<StoreCertificatePhotoVO>> queryList() {
|
||||
return ActionResult.success(storeCertificatePhotoService.queryList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询门店自定义证件配置照详情
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return 门店证件照详情
|
||||
*/
|
||||
@GetMapping("/query-info/{id}")
|
||||
public ActionResult<StoreCertificatePhotoVO> queryInfo(@PathVariable("id") @NotBlank(message = "主键ID不能为空") String id) {
|
||||
return ActionResult.success(storeCertificatePhotoService.queryInfo(id));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package jnpf.storecertificatephoto.controller;
|
||||
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.model.certificate.vo.CertificateTypeOptionVO;
|
||||
import jnpf.model.storecertificatephoto.vo.StoreCertificatePhotoIdNameVO;
|
||||
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
|
||||
import jnpf.model.warningnotice.req.WarningNoticeSaveReq;
|
||||
import jnpf.model.warningnotice.vo.WarningNoticeVO;
|
||||
import jnpf.storecertificatephoto.service.StoreCertificatePhotoService;
|
||||
import jnpf.storecertificatephoto.service.WarningNoticeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* web预警通知控制器
|
||||
*/
|
||||
@RestController
|
||||
@Validated
|
||||
@RequestMapping("/web/warning-notice")
|
||||
public class WarningNoticeController {
|
||||
|
||||
@Autowired
|
||||
private WarningNoticeService warningNoticeService;
|
||||
@Autowired
|
||||
private StoreCertificatePhotoService storeCertificatePhotoService;
|
||||
|
||||
/**
|
||||
* 保存预警通知配置
|
||||
*
|
||||
* @param req 保存请求参数
|
||||
* @return 预警通知配置
|
||||
*/
|
||||
@PostMapping("/save")
|
||||
public ActionResult<WarningNoticeVO> save(@Validated @RequestBody WarningNoticeSaveReq req) {
|
||||
return ActionResult.success("保存成功", warningNoticeService.save(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量保存预警通知配置
|
||||
*
|
||||
* @param reqList 批量保存请求参数
|
||||
* @return 预警通知配置列表
|
||||
*/
|
||||
@PostMapping("/saveList")
|
||||
public ActionResult<List<WarningNoticeVO>> saveList(
|
||||
@RequestBody @NotEmpty(message = "保存参数不能为空") List<@Valid WarningNoticeSaveReq> reqList) {
|
||||
return ActionResult.success("保存成功", warningNoticeService.saveList(reqList));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据证照类型查询预警通知配置
|
||||
*
|
||||
* @param type 证照类型
|
||||
* @return 预警通知配置
|
||||
*/
|
||||
@GetMapping("/query-by-type")
|
||||
public ActionResult<WarningNoticeVO> queryByType(@RequestParam("type") @NotBlank(message = "证照类型,或者模板id不能为空!") String type) {
|
||||
return ActionResult.success("获取成功", warningNoticeService.queryByType(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有预警通知配置
|
||||
*
|
||||
* @return 预警通知配置列表
|
||||
*/
|
||||
@GetMapping("/query-all")
|
||||
public ActionResult<List<WarningNoticeVO>> queryAll() {
|
||||
return ActionResult.success("获取成功", warningNoticeService.queryAll());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询证照类型选项。
|
||||
*
|
||||
* @return 证照类型选项
|
||||
*/
|
||||
@GetMapping("/query-certificate-type-list")
|
||||
public ActionResult<List<CertificateTypeOptionVO>> queryCertificateTypeList() {
|
||||
List<StoreCertificatePhotoIdNameVO> customerCertificateList = storeCertificatePhotoService.queryIdNameList();
|
||||
List<CertificateTypeOptionVO> result = new ArrayList<>(CertificateTypeEnum.values().length + customerCertificateList.size());
|
||||
for (CertificateTypeEnum type : CertificateTypeEnum.values()){
|
||||
CertificateTypeOptionVO option = new CertificateTypeOptionVO();
|
||||
option.setLabel(type.getLabel());
|
||||
option.setKey(type.getType());
|
||||
option.setType(type.getType());
|
||||
result.add(option);
|
||||
}
|
||||
for (StoreCertificatePhotoIdNameVO customerCertificate : customerCertificateList){
|
||||
CertificateTypeOptionVO option = new CertificateTypeOptionVO();
|
||||
option.setLabel(customerCertificate.getCertificateName());
|
||||
option.setKey(customerCertificate.getId());
|
||||
option.setType(CertificateTypeEnum.STORE_CUSTOM_CERTIFICATE.getType());
|
||||
result.add(option);
|
||||
}
|
||||
return ActionResult.success(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package jnpf.storecertificatephoto.helper;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jnpf.model.storecertificatephoto.po.StoreCertificatePhotoEntity;
|
||||
import jnpf.storecertificatephoto.mapper.StoreCertificatePhotoMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class StoreCertificatePhotoHelper {
|
||||
|
||||
@Autowired
|
||||
private StoreCertificatePhotoMapper storeCertificatePhotoMapper;
|
||||
|
||||
public Map<String,String> buildStoreCertificateIdAndNames(Collection<String> templateIds,Integer status){
|
||||
if(CollectionUtil.isEmpty(templateIds)){
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
LambdaQueryWrapper<StoreCertificatePhotoEntity> queryWrapper = new LambdaQueryWrapper<StoreCertificatePhotoEntity>()
|
||||
.select(StoreCertificatePhotoEntity::getId, StoreCertificatePhotoEntity::getCertificateName)
|
||||
.in(StoreCertificatePhotoEntity::getId, templateIds);
|
||||
if(Objects.nonNull(status)){
|
||||
queryWrapper.eq(StoreCertificatePhotoEntity::getStatus, status);
|
||||
}
|
||||
return storeCertificatePhotoMapper.selectList(queryWrapper)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(StoreCertificatePhotoEntity::getId, StoreCertificatePhotoEntity::getCertificateName));
|
||||
}
|
||||
|
||||
public Map<String,StoreCertificatePhotoEntity> buildStoreCertificateById(Collection<String> templateIds,Integer status){
|
||||
if(CollectionUtil.isEmpty(templateIds)){
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
LambdaQueryWrapper<StoreCertificatePhotoEntity> queryWrapper = new LambdaQueryWrapper<StoreCertificatePhotoEntity>()
|
||||
.in(StoreCertificatePhotoEntity::getId, templateIds);
|
||||
if(Objects.nonNull(status)){
|
||||
queryWrapper.eq(StoreCertificatePhotoEntity::getStatus, status);
|
||||
}
|
||||
return storeCertificatePhotoMapper.selectList(queryWrapper)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(StoreCertificatePhotoEntity::getId, v->v));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package jnpf.storecertificatephoto.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.model.warningnotice.po.FtbParamEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 基础参数Mapper
|
||||
*/
|
||||
public interface BaseParamMapper extends SuperMapper<FtbParamEntity> {
|
||||
|
||||
/**
|
||||
* 根据参数键查询参数
|
||||
*
|
||||
* @param key 参数键
|
||||
* @return 基础参数
|
||||
*/
|
||||
FtbParamEntity selectByKey(@Param("key") String key);
|
||||
|
||||
/**
|
||||
* 根据参数键更新参数
|
||||
*
|
||||
* @param sourceKey 原参数键
|
||||
* @param entity 基础参数
|
||||
* @return 更新条数
|
||||
*/
|
||||
int updateByKey(@Param("sourceKey") String sourceKey, @Param("entity") FtbParamEntity entity);
|
||||
|
||||
/**
|
||||
* 新增参数
|
||||
*
|
||||
* @param entity 基础参数
|
||||
* @return 新增条数
|
||||
*/
|
||||
int insertParam(@Param("entity") FtbParamEntity entity);
|
||||
|
||||
/**
|
||||
* 批量新增参数
|
||||
*
|
||||
* @param entities 参数列表
|
||||
* @return 新增条数
|
||||
*/
|
||||
int batchInsertParam(@Param("entities") List<FtbParamEntity> entities);
|
||||
|
||||
/**
|
||||
* 批量按ID更新参数
|
||||
*
|
||||
* @param entities 参数列表
|
||||
* @return 更新条数
|
||||
*/
|
||||
int batchUpdateById(@Param("entities") List<FtbParamEntity> entities);
|
||||
|
||||
/**
|
||||
* 根据key递增参数值
|
||||
*
|
||||
* @param key 参数key
|
||||
* @param number 递增值
|
||||
* @return 影响行数
|
||||
*/
|
||||
int incrementValueByKey(@Param("key") String key, @Param("number") Long number);
|
||||
|
||||
/**
|
||||
* 根据key删除参数
|
||||
*
|
||||
* @param key 参数key
|
||||
* @return 影响行数
|
||||
*/
|
||||
int deleteByKey(@Param("key") String key);
|
||||
|
||||
/**
|
||||
* 根据type删除参数。not key
|
||||
*
|
||||
* @param type 参数type
|
||||
* @param notKey 不包含的key
|
||||
* @return 影响行数
|
||||
*/
|
||||
int deleteByTypeNotKey(@Param("type") String type,@Param("notKey") String notKey);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package jnpf.storecertificatephoto.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.model.storecertificatephoto.po.StoreCertificatePhotoItemEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 门店证件照子项Mapper
|
||||
*/
|
||||
public interface StoreCertificatePhotoItemMapper extends SuperMapper<StoreCertificatePhotoItemEntity> {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package jnpf.storecertificatephoto.mapper;
|
||||
|
||||
import jnpf.base.mapper.SuperMapper;
|
||||
import jnpf.model.storecertificatephoto.po.StoreCertificatePhotoEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 门店证件照Mapper
|
||||
*/
|
||||
public interface StoreCertificatePhotoMapper extends SuperMapper<StoreCertificatePhotoEntity> {
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package jnpf.storecertificatephoto.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import jnpf.model.storecertificatephoto.po.StoreCertificatePhotoEntity;
|
||||
import jnpf.model.storecertificatephoto.req.StoreCertificatePhotoAddReq;
|
||||
import jnpf.model.storecertificatephoto.req.StoreCertificatePhotoUpdateReq;
|
||||
import jnpf.model.storecertificatephoto.vo.StoreCertificatePhotoIdNameVO;
|
||||
import jnpf.model.storecertificatephoto.vo.StoreCertificatePhotoVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 门店证件照服务
|
||||
*/
|
||||
public interface StoreCertificatePhotoService extends IService<StoreCertificatePhotoEntity> {
|
||||
|
||||
/**
|
||||
* 新增门店证件照配置
|
||||
*
|
||||
* @param req 门店证件照请求参数
|
||||
*/
|
||||
void add(StoreCertificatePhotoAddReq req);
|
||||
|
||||
/**
|
||||
* 编辑门店证件照配置
|
||||
*
|
||||
* @param req 门店证件照编辑参数
|
||||
*/
|
||||
void update(StoreCertificatePhotoUpdateReq req);
|
||||
|
||||
/**
|
||||
* 查询门店证件照列表
|
||||
*
|
||||
* @return 门店证件照列表
|
||||
*/
|
||||
List<StoreCertificatePhotoVO> queryList();
|
||||
|
||||
/**
|
||||
* 查询门店证件照ID和名称列表
|
||||
*
|
||||
* @return 门店证件照ID和名称列表
|
||||
*/
|
||||
List<StoreCertificatePhotoIdNameVO> queryIdNameList();
|
||||
|
||||
/**
|
||||
* 根据ID查询门店证件照详情
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return 门店证件照详情
|
||||
*/
|
||||
StoreCertificatePhotoVO queryInfo(String id);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package jnpf.storecertificatephoto.service;
|
||||
|
||||
import jnpf.model.warningnotice.req.WarningNoticeSaveReq;
|
||||
import jnpf.model.warningnotice.vo.WarningNoticeVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 预警通知服务
|
||||
*/
|
||||
public interface WarningNoticeService {
|
||||
|
||||
/**
|
||||
* 保存预警通知配置
|
||||
*
|
||||
* @param req 保存请求参数
|
||||
* @return 预警通知配置
|
||||
*/
|
||||
WarningNoticeVO save(WarningNoticeSaveReq req);
|
||||
|
||||
/**
|
||||
* 批量保存预警通知配置
|
||||
*
|
||||
* @param reqList 批量保存请求参数
|
||||
* @return 预警通知配置列表
|
||||
*/
|
||||
List<WarningNoticeVO> saveList(List<WarningNoticeSaveReq> reqList);
|
||||
|
||||
/**
|
||||
* 根据证照类型查询预警通知配置
|
||||
*
|
||||
* @param type 证照类型
|
||||
* @return 预警通知配置
|
||||
*/
|
||||
WarningNoticeVO queryByType(String type);
|
||||
|
||||
/**
|
||||
* 查询所有预警通知配置
|
||||
*
|
||||
* @return 预警通知配置
|
||||
*/
|
||||
List<WarningNoticeVO> queryAll();
|
||||
}
|
||||
@@ -0,0 +1,518 @@
|
||||
package jnpf.storecertificatephoto.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import jnpf.certificate.mapper.CertificateInstanceItemMapper;
|
||||
import jnpf.certificate.mapper.CertificateInstanceMapper;
|
||||
import jnpf.model.certificate.po.CertificateInstanceEntity;
|
||||
import jnpf.model.certificate.po.CertificateInstanceItemEntity;
|
||||
import jnpf.model.storecertificatephoto.po.StoreCertificatePhotoEntity;
|
||||
import jnpf.model.storecertificatephoto.po.StoreCertificatePhotoItemEntity;
|
||||
import jnpf.model.storecertificatephoto.req.StoreCertificatePhotoAddReq;
|
||||
import jnpf.model.storecertificatephoto.req.StoreCertificatePhotoItemReq;
|
||||
import jnpf.model.storecertificatephoto.req.StoreCertificatePhotoUpdateReq;
|
||||
import jnpf.model.storecertificatephoto.vo.StoreCertificatePhotoIdNameVO;
|
||||
import jnpf.model.storecertificatephoto.vo.StoreCertificatePhotoItemVO;
|
||||
import jnpf.model.storecertificatephoto.vo.StoreCertificatePhotoVO;
|
||||
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
|
||||
import jnpf.storecertificatephoto.mapper.StoreCertificatePhotoItemMapper;
|
||||
import jnpf.storecertificatephoto.mapper.StoreCertificatePhotoMapper;
|
||||
import jnpf.storecertificatephoto.service.StoreCertificatePhotoService;
|
||||
import jnpf.util.UserProvider;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 门店证件照服务实现
|
||||
*/
|
||||
@Service
|
||||
public class StoreCertificatePhotoServiceImpl extends ServiceImpl<StoreCertificatePhotoMapper, StoreCertificatePhotoEntity>
|
||||
implements StoreCertificatePhotoService {
|
||||
|
||||
private static final int ITEM_TYPE_IMAGE = 1;
|
||||
private static final int ITEM_TYPE_TEXT = 2;
|
||||
|
||||
@Autowired
|
||||
private StoreCertificatePhotoItemMapper storeCertificatePhotoItemMapper;
|
||||
@Autowired
|
||||
private CertificateInstanceItemMapper certificateInstanceItemMapper;
|
||||
@Autowired
|
||||
private CertificateInstanceMapper certificateInstanceMapper;
|
||||
@Autowired
|
||||
private RedissonClient redissonClient;
|
||||
private static final String lockPrefix = "certificate:customer:add:";
|
||||
|
||||
/**
|
||||
* 新增门店证件照配置
|
||||
*
|
||||
* @param req 门店证件照请求参数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void add(StoreCertificatePhotoAddReq req) {
|
||||
validateAddReq(req);
|
||||
String certificateName = req.getCertificateName().trim();
|
||||
|
||||
if (existsCertificateName(certificateName, null)) {
|
||||
throw new RuntimeException("证照名称已存在");
|
||||
}
|
||||
|
||||
String lockKey = buildCertificateCustomerAddLock();
|
||||
|
||||
RLock lock = redissonClient.getLock(lockKey);
|
||||
try {
|
||||
lock.lock(10, TimeUnit.SECONDS);
|
||||
Long count = baseMapper.selectCount(new LambdaQueryWrapper<StoreCertificatePhotoEntity>()
|
||||
.eq(StoreCertificatePhotoEntity::getEnabledMark,0));
|
||||
if(Objects.nonNull(count) && count >= 15){
|
||||
throw new RuntimeException("超出15个证照,无法添加!");
|
||||
}
|
||||
}finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
StoreCertificatePhotoEntity entity = req.convert();
|
||||
insertPhotoEntity(entity);
|
||||
|
||||
List<StoreCertificatePhotoItemEntity> items = new ArrayList<>();
|
||||
items.addAll(buildItems(entity.getId(), req.getImageItemList(), ITEM_TYPE_IMAGE));
|
||||
items.addAll(buildItems(entity.getId(), req.getTextItemList(), ITEM_TYPE_TEXT));
|
||||
for (StoreCertificatePhotoItemEntity item : items) {
|
||||
storeCertificatePhotoItemMapper.insert(item);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildCertificateCustomerAddLock() {
|
||||
return lockPrefix+UserProvider.getUser().getTenantId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑门店证件照配置
|
||||
*
|
||||
* @param req 门店证件照编辑参数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(StoreCertificatePhotoUpdateReq req) {
|
||||
validateAddReq(req);
|
||||
String id = req.getId().trim();
|
||||
StoreCertificatePhotoEntity dbEntity = getEntityById(id);
|
||||
// 先查询当前模板项,再与传入项对比,识别本次删除项。
|
||||
List<StoreCertificatePhotoItemEntity> originItems = queryCurrentItems(id);
|
||||
List<String> deletedItemIds = collectDeletedItemIds(originItems, req);
|
||||
// 删除前先校验是否已被证照实例使用。
|
||||
validateDeleteItemReference(deletedItemIds);
|
||||
// 未被使用的项执行逻辑删除。
|
||||
deleteItemsByIds(deletedItemIds);
|
||||
String certificateName = req.getCertificateName().trim();
|
||||
if (existsCertificateName(certificateName, id)) {
|
||||
throw new RuntimeException("证照名称已存在");
|
||||
}
|
||||
|
||||
StoreCertificatePhotoEntity entity = req.convert();
|
||||
entity.setId(dbEntity.getId());
|
||||
entity.setEnabledMark(dbEntity.getEnabledMark());
|
||||
updatePhotoEntity(entity);
|
||||
|
||||
if(!dbEntity.getStatus().equals(entity.getStatus())){
|
||||
certificateInstanceMapper.update(null,new LambdaUpdateWrapper<CertificateInstanceEntity>()
|
||||
.eq(CertificateInstanceEntity::getTemplateId, req.getId())
|
||||
.eq(CertificateInstanceEntity::getCertificateType, CertificateTypeEnum.STORE_CUSTOM_CERTIFICATE.getType())
|
||||
.eq(CertificateInstanceEntity::getEnabledMark, 0)
|
||||
.set(CertificateInstanceEntity::getTemplateStatus, req.getStatus())
|
||||
.set(CertificateInstanceEntity::getLastModifyUserId, UserProvider.getLoginUserId())
|
||||
.set(CertificateInstanceEntity::getLastModifyTime, new Date()));
|
||||
}
|
||||
|
||||
upsertItems(id, req.getImageItemList(), ITEM_TYPE_IMAGE);
|
||||
upsertItems(id, req.getTextItemList(), ITEM_TYPE_TEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询门店证件照列表
|
||||
*
|
||||
* @return 门店证件照列表
|
||||
*/
|
||||
@Override
|
||||
public List<StoreCertificatePhotoVO> queryList() {
|
||||
LambdaQueryWrapper<StoreCertificatePhotoEntity> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(StoreCertificatePhotoEntity::getEnabledMark, 0);
|
||||
queryWrapper.orderByDesc(StoreCertificatePhotoEntity::getCreatorTime);
|
||||
List<StoreCertificatePhotoEntity> entityList = baseMapper.selectList(queryWrapper);
|
||||
if (CollUtil.isEmpty(entityList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Map<String, List<StoreCertificatePhotoItemEntity>> itemMap = queryItemMap(entityList.stream()
|
||||
.map(StoreCertificatePhotoEntity::getId)
|
||||
.collect(Collectors.toList()));
|
||||
return entityList.stream().map(entity -> buildVO(entity, itemMap)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StoreCertificatePhotoIdNameVO> queryIdNameList() {
|
||||
LambdaQueryWrapper<StoreCertificatePhotoEntity> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.select(StoreCertificatePhotoEntity::getId, StoreCertificatePhotoEntity::getCertificateName);
|
||||
queryWrapper.eq(StoreCertificatePhotoEntity::getEnabledMark, 0);
|
||||
queryWrapper.orderByDesc(StoreCertificatePhotoEntity::getCreatorTime);
|
||||
return baseMapper.selectList(queryWrapper).stream()
|
||||
.map(StoreCertificatePhotoIdNameVO::convert)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询门店证件照详情
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return 门店证件照详情
|
||||
*/
|
||||
@Override
|
||||
public StoreCertificatePhotoVO queryInfo(String id) {
|
||||
String photoId = id.trim();
|
||||
StoreCertificatePhotoEntity entity = getEntityById(photoId);
|
||||
Map<String, List<StoreCertificatePhotoItemEntity>> itemMap = queryItemMap(Collections.singletonList(photoId));
|
||||
return buildVO(entity, itemMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验新增参数
|
||||
*
|
||||
* @param req 门店证件照请求参数
|
||||
*/
|
||||
private void validateAddReq(StoreCertificatePhotoAddReq req) {
|
||||
if (req.getImageCount() == null || req.getImageCount() < 0) {
|
||||
throw new RuntimeException("证照图片数量必须大于等于0");
|
||||
}
|
||||
if (req.getImageCount() != req.getImageItemList().size()) {
|
||||
throw new RuntimeException("证照图片数量必须与图片名称数量一致");
|
||||
}
|
||||
|
||||
if (Objects.nonNull(req.getExpireDateEnabled()) &&
|
||||
1== req.getExpireDateEnabled()&&
|
||||
StrUtil.isBlank(req.getExpireDateName())) {
|
||||
throw new RuntimeException("到期日期名称不能为空");
|
||||
}
|
||||
|
||||
validateItemNames(req.getImageItemList(), "图片名称");
|
||||
validateItemNames(req.getTextItemList(), "文本名称");
|
||||
validateItemIds(req.getImageItemList(), req.getTextItemList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验子项名称
|
||||
*
|
||||
* @param itemList 子项列表
|
||||
* @param label 提示文案
|
||||
*/
|
||||
private void validateItemNames(List<StoreCertificatePhotoItemReq> itemList, String label) {
|
||||
Set<String> nameSet = new LinkedHashSet<>();
|
||||
for (StoreCertificatePhotoItemReq item : itemList) {
|
||||
if (item == null || StrUtil.isBlank(item.getItemName())) {
|
||||
throw new RuntimeException(label + "不能为空");
|
||||
}
|
||||
if (!nameSet.add(item.getItemName().trim())) {
|
||||
throw new RuntimeException(label + "不能重复");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验更新请求中子项ID不能重复
|
||||
*
|
||||
* @param imageItemList 图片子项列表
|
||||
* @param textItemList 文本子项列表
|
||||
*/
|
||||
private void validateItemIds(List<StoreCertificatePhotoItemReq> imageItemList,
|
||||
List<StoreCertificatePhotoItemReq> textItemList) {
|
||||
Set<String> itemIdSet = new LinkedHashSet<>();
|
||||
List<StoreCertificatePhotoItemReq> allItems = new ArrayList<>();
|
||||
if (CollUtil.isNotEmpty(imageItemList)) {
|
||||
allItems.addAll(imageItemList);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(textItemList)) {
|
||||
allItems.addAll(textItemList);
|
||||
}
|
||||
for (StoreCertificatePhotoItemReq itemReq : allItems) {
|
||||
if (itemReq == null || StrUtil.isBlank(itemReq.getId())) {
|
||||
continue;
|
||||
}
|
||||
String itemId = StrUtil.trim(itemReq.getId());
|
||||
if (!itemIdSet.add(itemId)) {
|
||||
throw new RuntimeException("子项ID不能重复");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建门店证件照子项
|
||||
*
|
||||
* @param photoId 门店证件照ID
|
||||
* @param itemReqList 子项请求列表
|
||||
* @param itemType 子项类型
|
||||
* @return 子项实体列表
|
||||
*/
|
||||
private List<StoreCertificatePhotoItemEntity> buildItems(String photoId,
|
||||
List<StoreCertificatePhotoItemReq> itemReqList,
|
||||
Integer itemType) {
|
||||
List<StoreCertificatePhotoItemEntity> itemList = new ArrayList<>();
|
||||
for (int i = 0; i < itemReqList.size(); i++) {
|
||||
StoreCertificatePhotoItemReq itemReq = itemReqList.get(i);
|
||||
StoreCertificatePhotoItemEntity itemEntity = new StoreCertificatePhotoItemEntity();
|
||||
itemEntity.setId(StrUtil.isNotBlank(itemReq.getId()) ? StrUtil.trim(itemReq.getId()) : null);
|
||||
itemEntity.setPhotoId(photoId);
|
||||
itemEntity.setItemType(itemType);
|
||||
itemEntity.setItemName(itemReq.getItemName().trim());
|
||||
itemEntity.setTextPrompt(ITEM_TYPE_TEXT == itemType && StrUtil.isNotBlank(itemReq.getTextPrompt())
|
||||
? itemReq.getTextPrompt().trim()
|
||||
: null);
|
||||
itemEntity.setSorts((long) i + 1);
|
||||
itemEntity.setEnabledMark(0);
|
||||
itemList.add(itemEntity);
|
||||
}
|
||||
return itemList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新时按子项ID进行增改
|
||||
*
|
||||
* @param photoId 门店证件照ID
|
||||
* @param itemReqList 子项请求列表
|
||||
* @param itemType 子项类型
|
||||
*/
|
||||
private void upsertItems(String photoId, List<StoreCertificatePhotoItemReq> itemReqList, Integer itemType) {
|
||||
if (CollUtil.isEmpty(itemReqList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> itemIds = itemReqList.stream()
|
||||
.filter(item -> item != null && StrUtil.isNotBlank(item.getId()))
|
||||
.map(item -> StrUtil.trim(item.getId()))
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Map<String, StoreCertificatePhotoItemEntity> dbItemMap = new HashMap<>();
|
||||
if (CollUtil.isNotEmpty(itemIds)) {
|
||||
LambdaQueryWrapper<StoreCertificatePhotoItemEntity> itemWrapper = Wrappers.lambdaQuery();
|
||||
itemWrapper.in(StoreCertificatePhotoItemEntity::getId, itemIds);
|
||||
itemWrapper.eq(StoreCertificatePhotoItemEntity::getPhotoId, photoId);
|
||||
itemWrapper.eq(StoreCertificatePhotoItemEntity::getEnabledMark, 0);
|
||||
List<StoreCertificatePhotoItemEntity> dbItems = storeCertificatePhotoItemMapper.selectList(itemWrapper);
|
||||
dbItemMap = dbItems.stream()
|
||||
.collect(Collectors.toMap(StoreCertificatePhotoItemEntity::getId, item -> item, (a, b) -> a));
|
||||
}
|
||||
|
||||
List<StoreCertificatePhotoItemEntity> items = buildItems(photoId, itemReqList, itemType);
|
||||
for (StoreCertificatePhotoItemEntity item : items) {
|
||||
if (StrUtil.isBlank(item.getId())) {
|
||||
storeCertificatePhotoItemMapper.insert(item);
|
||||
continue;
|
||||
}
|
||||
StoreCertificatePhotoItemEntity dbItem = dbItemMap.get(item.getId());
|
||||
if (dbItem == null) {
|
||||
throw new RuntimeException("子项ID不存在或不属于当前配置");
|
||||
}
|
||||
item.setItemType(itemType);
|
||||
item.setEnabledMark(dbItem.getEnabledMark());
|
||||
storeCertificatePhotoItemMapper.updateById(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断证照名称是否已存在
|
||||
*
|
||||
* @param certificateName 证照名称
|
||||
* @param excludeId 排除的主键ID
|
||||
* @return 是否存在
|
||||
*/
|
||||
private boolean existsCertificateName(String certificateName, String excludeId) {
|
||||
LambdaQueryWrapper<StoreCertificatePhotoEntity> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(StoreCertificatePhotoEntity::getCertificateName, certificateName);
|
||||
queryWrapper.eq(StoreCertificatePhotoEntity::getEnabledMark, 0);
|
||||
queryWrapper.ne(StrUtil.isNotBlank(excludeId), StoreCertificatePhotoEntity::getId, excludeId);
|
||||
return baseMapper.selectCount(queryWrapper) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前模板下所有有效项。
|
||||
*
|
||||
* @param photoId 模板ID
|
||||
* @return 当前模板项列表
|
||||
*/
|
||||
private List<StoreCertificatePhotoItemEntity> queryCurrentItems(String photoId) {
|
||||
LambdaQueryWrapper<StoreCertificatePhotoItemEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(StoreCertificatePhotoItemEntity::getPhotoId, photoId);
|
||||
wrapper.eq(StoreCertificatePhotoItemEntity::getEnabledMark, 0);
|
||||
return storeCertificatePhotoItemMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对比原有模板项与本次请求项,得到被删除的模板项ID。
|
||||
*
|
||||
* @param originItems 原有模板项
|
||||
* @param req 编辑请求
|
||||
* @return 待删除模板项ID列表
|
||||
*/
|
||||
private List<String> collectDeletedItemIds(List<StoreCertificatePhotoItemEntity> originItems,
|
||||
StoreCertificatePhotoUpdateReq req) {
|
||||
if (CollUtil.isEmpty(originItems)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Set<String> currentItemIds = new LinkedHashSet<>();
|
||||
appendReqItemIds(currentItemIds, req.getImageItemList());
|
||||
appendReqItemIds(currentItemIds, req.getTextItemList());
|
||||
|
||||
return originItems.stream()
|
||||
.map(StoreCertificatePhotoItemEntity::getId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.map(StrUtil::trim)
|
||||
.filter(itemId -> !currentItemIds.contains(itemId))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 收集请求中的子项ID(仅收集更新场景中有值的itemId)。
|
||||
*
|
||||
* @param targetSet 目标ID集合
|
||||
* @param itemReqList 请求项列表
|
||||
*/
|
||||
private void appendReqItemIds(Set<String> targetSet, List<StoreCertificatePhotoItemReq> itemReqList) {
|
||||
if (CollUtil.isEmpty(itemReqList)) {
|
||||
return;
|
||||
}
|
||||
for (StoreCertificatePhotoItemReq itemReq : itemReqList) {
|
||||
if (itemReq == null || StrUtil.isBlank(itemReq.getId())) {
|
||||
continue;
|
||||
}
|
||||
targetSet.add(StrUtil.trim(itemReq.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验待删除模板项是否已被证照实例使用。
|
||||
*
|
||||
* @param deletedItemIds 待删除模板项ID列表
|
||||
*/
|
||||
private void validateDeleteItemReference(List<String> deletedItemIds) {
|
||||
if (CollUtil.isEmpty(deletedItemIds)) {
|
||||
return;
|
||||
}
|
||||
LambdaQueryWrapper<CertificateInstanceItemEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.in(CertificateInstanceItemEntity::getTemplateItemId, deletedItemIds);
|
||||
wrapper.eq(CertificateInstanceItemEntity::getEnabledMark, 0);
|
||||
Long count = certificateInstanceItemMapper.selectCount(wrapper);
|
||||
if (count != null && count > 0) {
|
||||
throw new RuntimeException("该字段已经被使用,无法删除");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行模板项逻辑删除。
|
||||
*
|
||||
* @param deletedItemIds 待删除模板项ID列表
|
||||
*/
|
||||
private void deleteItemsByIds(List<String> deletedItemIds) {
|
||||
if (CollUtil.isEmpty(deletedItemIds)) {
|
||||
return;
|
||||
}
|
||||
for (String itemId : deletedItemIds) {
|
||||
StoreCertificatePhotoItemEntity item = new StoreCertificatePhotoItemEntity();
|
||||
item.setId(itemId);
|
||||
item.setEnabledMark(1);
|
||||
storeCertificatePhotoItemMapper.updateById(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询有效的门店证件照配置。
|
||||
*
|
||||
* @param id 主键ID
|
||||
* @return 门店证件照实体
|
||||
*/
|
||||
private StoreCertificatePhotoEntity getEntityById(String id) {
|
||||
StoreCertificatePhotoEntity entity = baseMapper.selectById(id);
|
||||
if (entity == null || !Integer.valueOf(0).equals(entity.getEnabledMark())) {
|
||||
throw new RuntimeException("门店证件照配置不存在");
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询子项映射
|
||||
*
|
||||
* @param photoIds 门店证件照ID列表
|
||||
* @return 子项映射
|
||||
*/
|
||||
private Map<String, List<StoreCertificatePhotoItemEntity>> queryItemMap(List<String> photoIds) {
|
||||
if (CollUtil.isEmpty(photoIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
LambdaQueryWrapper<StoreCertificatePhotoItemEntity> itemWrapper = Wrappers.lambdaQuery();
|
||||
itemWrapper.in(StoreCertificatePhotoItemEntity::getPhotoId, photoIds);
|
||||
itemWrapper.eq(StoreCertificatePhotoItemEntity::getEnabledMark, 0);
|
||||
itemWrapper.orderByAsc(StoreCertificatePhotoItemEntity::getPhotoId)
|
||||
.orderByAsc(StoreCertificatePhotoItemEntity::getItemType)
|
||||
.orderByAsc(StoreCertificatePhotoItemEntity::getSorts);
|
||||
return storeCertificatePhotoItemMapper.selectList(itemWrapper).stream()
|
||||
.collect(Collectors.groupingBy(StoreCertificatePhotoItemEntity::getPhotoId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建门店证件照返回对象
|
||||
*
|
||||
* @param entity 门店证件照实体
|
||||
* @param itemMap 子项映射
|
||||
* @return 门店证件照返回对象
|
||||
*/
|
||||
private StoreCertificatePhotoVO buildVO(StoreCertificatePhotoEntity entity,
|
||||
Map<String, List<StoreCertificatePhotoItemEntity>> itemMap) {
|
||||
StoreCertificatePhotoVO vo = StoreCertificatePhotoVO.convert(entity);
|
||||
List<StoreCertificatePhotoItemEntity> currentItems = itemMap.getOrDefault(entity.getId(), Collections.emptyList());
|
||||
vo.setImageItemList(currentItems.stream()
|
||||
.filter(item -> ITEM_TYPE_IMAGE == item.getItemType())
|
||||
.map(StoreCertificatePhotoItemVO::convert)
|
||||
.collect(Collectors.toList()));
|
||||
vo.setTextItemList(currentItems.stream()
|
||||
.filter(item -> ITEM_TYPE_TEXT == item.getItemType())
|
||||
.map(StoreCertificatePhotoItemVO::convert)
|
||||
.collect(Collectors.toList()));
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增门店证件照主表数据
|
||||
*
|
||||
* @param entity 门店证件照实体
|
||||
*/
|
||||
private void insertPhotoEntity(StoreCertificatePhotoEntity entity) {
|
||||
try {
|
||||
baseMapper.insert(entity);
|
||||
} catch (DuplicateKeyException e) {
|
||||
throw new RuntimeException("证照名称已存在");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新门店证件照主表数据
|
||||
*
|
||||
* @param entity 门店证件照实体
|
||||
*/
|
||||
private void updatePhotoEntity(StoreCertificatePhotoEntity entity) {
|
||||
try {
|
||||
baseMapper.updateById(entity);
|
||||
} catch (DuplicateKeyException e) {
|
||||
throw new RuntimeException("证照名称已存在");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,641 @@
|
||||
package jnpf.storecertificatephoto.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jnpf.model.storecertificatephoto.po.StoreCertificatePhotoEntity;
|
||||
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
|
||||
import jnpf.model.warningnotice.po.FtbParamEntity;
|
||||
import jnpf.model.warningnotice.req.WarningNoticeSaveReq;
|
||||
import jnpf.model.warningnotice.req.WarningNoticeTargetReq;
|
||||
import jnpf.model.warningnotice.req.WarningNoticeUserConfigReq;
|
||||
import jnpf.model.warningnotice.vo.WarningNoticeTargetVO;
|
||||
import jnpf.model.warningnotice.vo.WarningNoticeUserConfigVO;
|
||||
import jnpf.model.warningnotice.vo.WarningNoticeVO;
|
||||
import jnpf.storecertificatephoto.helper.StoreCertificatePhotoHelper;
|
||||
import jnpf.storecertificatephoto.mapper.BaseParamMapper;
|
||||
import jnpf.storecertificatephoto.service.WarningNoticeService;
|
||||
import jnpf.util.FtbUtil;
|
||||
import jnpf.util.JsonUtil;
|
||||
import jnpf.util.ServiceException;
|
||||
import jnpf.util.StringUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 预警通知服务实现
|
||||
*/
|
||||
@Service
|
||||
public class WarningNoticeServiceImpl implements WarningNoticeService {
|
||||
|
||||
private static final String CONFIG_KEY_PREFIX = "ftbWarningNotice_";
|
||||
/**
|
||||
* 预警配置类型
|
||||
*/
|
||||
public static final String certificateWarnNoticeType = "certificateWarnNoticeType";
|
||||
private static final Long DEFAULT_SORT = 0L;
|
||||
|
||||
@Autowired
|
||||
private BaseParamMapper baseParamMapper;
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
@Autowired
|
||||
private StoreCertificatePhotoHelper storeCertificatePhotoHelper;
|
||||
|
||||
/**
|
||||
* 保存预警通知配置
|
||||
*
|
||||
* @param req 保存请求参数
|
||||
* @return 预警通知配置
|
||||
*/
|
||||
@Override
|
||||
public WarningNoticeVO save(WarningNoticeSaveReq req) {
|
||||
List<WarningNoticeVO> result = saveList(Collections.singletonList(req));
|
||||
ServiceException.isTrue(CollUtil.isNotEmpty(result), "保存预警配置失败");
|
||||
return result.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量保存预警通知配置
|
||||
*
|
||||
* @param reqList 批量保存请求参数
|
||||
* @return 预警通知配置列表
|
||||
*/
|
||||
@Override
|
||||
public List<WarningNoticeVO> saveList(List<WarningNoticeSaveReq> reqList) {
|
||||
ServiceException.isTrue(CollUtil.isNotEmpty(reqList), "保存参数不能为空");
|
||||
|
||||
List<WarningNoticePreparedData> preparedList = prepareSaveDataList(reqList);
|
||||
validateBatchUniqueness(preparedList);
|
||||
BatchParamSplit split = splitById(preparedList);
|
||||
executeBatch(split);
|
||||
|
||||
// 批量更新/插入后,按key回查最新数据,保证返回包含数据库最终ID
|
||||
List<String> keys = preparedList.stream()
|
||||
.map(item -> item.getEntity().getKey())
|
||||
.collect(Collectors.toList());
|
||||
List<WarningNoticeVO> result = queryByKeys(keys);
|
||||
ServiceException.isTrue(result.size() == keys.size(), "保存预警配置失败");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据证照类型查询预警通知配置
|
||||
*
|
||||
* @param type 证照类型
|
||||
* @return 预警通知配置
|
||||
*/
|
||||
@Override
|
||||
public WarningNoticeVO queryByType(String type) {
|
||||
String key = buildConfigKey(type);
|
||||
FtbParamEntity entity = baseParamMapper.selectByKey(key);
|
||||
if (entity == null || StrUtil.isBlank(entity.getValue())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
WarningNoticeVO warningNoticeVO = buildWarningNoticeVO(entity);
|
||||
return normalizeWarningNoticeVO(warningNoticeVO);
|
||||
}
|
||||
|
||||
private WarningNoticeVO buildWarningNoticeVO(FtbParamEntity entity) {
|
||||
WarningNoticeVO warningNoticeVO = JsonUtil.getJsonToBean(entity.getValue(), WarningNoticeVO.class);
|
||||
ServiceException.notNull(warningNoticeVO, "预警通知配置数据异常");
|
||||
warningNoticeVO.setKey(entity.getKey());
|
||||
String certificateType = buildCertificateTypeOrTemplateId(entity.getKey());
|
||||
Optional<CertificateTypeEnum> certificateTypeEnumOptional = CertificateTypeEnum.getByType(certificateType);
|
||||
ServiceException.isTrue(certificateTypeEnumOptional.isPresent(), "预警通知配置数据异常.证照类型异常");
|
||||
CertificateTypeEnum certificateTypeEnum = certificateTypeEnumOptional.get();
|
||||
warningNoticeVO.setType(certificateTypeEnum.getType());
|
||||
warningNoticeVO.setTypeOrTemplateId(certificateType);
|
||||
warningNoticeVO.setId(entity.getId());
|
||||
return warningNoticeVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WarningNoticeVO> queryAll() {
|
||||
List<FtbParamEntity> ftbParamEntities = baseParamMapper.selectList(new LambdaQueryWrapper<FtbParamEntity>().eq(FtbParamEntity::getType, certificateWarnNoticeType));
|
||||
if(CollectionUtil.isEmpty(ftbParamEntities)){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return ftbParamEntities.stream()
|
||||
.map(this::buildWarningNoticeVO)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建基础参数实体
|
||||
*
|
||||
* @param saveData 预警通知配置
|
||||
* @param reqId 请求中的ID
|
||||
* @return 基础参数实体
|
||||
*/
|
||||
private FtbParamEntity buildBaseParamEntity(WarningNoticeVO saveData, String reqId) {
|
||||
FtbParamEntity entity = new FtbParamEntity();
|
||||
entity.setId(StrUtil.isNotBlank(reqId) ? normalizeText(reqId) : FtbUtil.getId());
|
||||
entity.setKey(saveData.getKey());
|
||||
entity.setType(certificateWarnNoticeType);
|
||||
entity.setValue(JsonUtil.getObjectToString(saveData));
|
||||
entity.setSort(DEFAULT_SORT);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建保存对象
|
||||
*
|
||||
* @param req 保存请求参数
|
||||
* @param certificateType 证照类型
|
||||
* @param key 参数键
|
||||
* @return 预警通知配置
|
||||
*/
|
||||
private WarningNoticeVO buildSaveData(WarningNoticeSaveReq req, CertificateTypeEnum certificateType, String key) {
|
||||
WarningNoticeVO warningNoticeVO = new WarningNoticeVO();
|
||||
warningNoticeVO.setKey(key);
|
||||
warningNoticeVO.setType(certificateType.getType());
|
||||
warningNoticeVO.setExpiryReminderDays(req.getExpiryReminderDays());
|
||||
warningNoticeVO.setNoticeFrequencyDays(req.getNoticeFrequencyDays());
|
||||
|
||||
List<WarningNoticeUserConfigVO> noticeConfigList = new ArrayList<>();
|
||||
for (WarningNoticeUserConfigReq configReq : req.getNoticeConfigList()) {
|
||||
WarningNoticeUserConfigVO configVO = new WarningNoticeUserConfigVO();
|
||||
configVO.setNoticeUserType(normalizeText(configReq.getNoticeUserType()));
|
||||
|
||||
List<WarningNoticeTargetVO> noticeUserList = new ArrayList<>();
|
||||
for (WarningNoticeTargetReq targetReq : configReq.getNoticeUserList()) {
|
||||
WarningNoticeTargetVO targetVO = new WarningNoticeTargetVO();
|
||||
targetVO.setId(normalizeText(targetReq.getId()));
|
||||
targetVO.setName(normalizeText(targetReq.getName()));
|
||||
noticeUserList.add(targetVO);
|
||||
}
|
||||
configVO.setNoticeUserList(noticeUserList);
|
||||
noticeConfigList.add(configVO);
|
||||
}
|
||||
warningNoticeVO.setNoticeConfigList(noticeConfigList);
|
||||
return warningNoticeVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化返回对象
|
||||
*
|
||||
* @param warningNoticeVO 预警通知配置
|
||||
* @return 预警通知配置
|
||||
*/
|
||||
private WarningNoticeVO normalizeWarningNoticeVO(WarningNoticeVO warningNoticeVO) {
|
||||
warningNoticeVO.setId(normalizeText(warningNoticeVO.getId()));
|
||||
warningNoticeVO.setKey(normalizeText(warningNoticeVO.getKey()));
|
||||
warningNoticeVO.setType(normalizeText(warningNoticeVO.getType()));
|
||||
if (warningNoticeVO.getNoticeConfigList() == null) {
|
||||
warningNoticeVO.setNoticeConfigList(new ArrayList<>());
|
||||
return warningNoticeVO;
|
||||
}
|
||||
|
||||
for (WarningNoticeUserConfigVO configVO : warningNoticeVO.getNoticeConfigList()) {
|
||||
configVO.setNoticeUserType(normalizeText(configVO.getNoticeUserType()));
|
||||
if (configVO.getNoticeUserList() == null) {
|
||||
configVO.setNoticeUserList(new ArrayList<>());
|
||||
continue;
|
||||
}
|
||||
for (WarningNoticeTargetVO targetVO : configVO.getNoticeUserList()) {
|
||||
targetVO.setId(normalizeText(targetVO.getId()));
|
||||
targetVO.setName(normalizeText(targetVO.getName()));
|
||||
}
|
||||
}
|
||||
return warningNoticeVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验通知人员配置
|
||||
*
|
||||
* @param noticeConfigList 通知人员配置列表
|
||||
*/
|
||||
private void validateNoticeConfigList(List<WarningNoticeUserConfigReq> noticeConfigList) {
|
||||
ServiceException.isTrue(CollUtil.isNotEmpty(noticeConfigList), "临期通知人员不能为空");
|
||||
Set<String> noticeTypeSet = new HashSet<>();
|
||||
for (WarningNoticeUserConfigReq configReq : noticeConfigList) {
|
||||
ServiceException.notNull(configReq, "通知人员配置不能为空");
|
||||
String noticeUserType = normalizeText(configReq.getNoticeUserType());
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(noticeUserType), "通知人员类型不能为空");
|
||||
ServiceException.isTrue(noticeTypeSet.add(noticeUserType), "通知人员类型不能重复");
|
||||
validateNoticeTargetList(configReq.getNoticeUserList());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验通知对象列表
|
||||
*
|
||||
* @param noticeUserList 通知对象列表
|
||||
*/
|
||||
private void validateNoticeTargetList(List<WarningNoticeTargetReq> noticeUserList) {
|
||||
ServiceException.isTrue(CollUtil.isNotEmpty(noticeUserList), "通知对象不能为空");
|
||||
Set<String> targetIdSet = new HashSet<>();
|
||||
for (WarningNoticeTargetReq targetReq : noticeUserList) {
|
||||
ServiceException.notNull(targetReq, "通知对象不能为空");
|
||||
String id = normalizeText(targetReq.getId());
|
||||
String name = normalizeText(targetReq.getName());
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(id), "通知对象ID不能为空");
|
||||
ServiceException.isTrue(targetIdSet.add(id), "同一通知人员类型下的通知对象不能重复");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成配置键
|
||||
*
|
||||
* @param certificateType 证照类型
|
||||
* @return 配置键
|
||||
*/
|
||||
private String buildConfigKey(CertificateTypeEnum certificateType,String typeOrTemplateId) {
|
||||
if(CertificateTypeEnum.STORE_CUSTOM_CERTIFICATE.equals(certificateType)){
|
||||
return buildConfigKey(typeOrTemplateId);
|
||||
}
|
||||
return buildConfigKey(certificateType.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成配置键
|
||||
*
|
||||
* @param certificateType 证照类型
|
||||
* @return 配置键
|
||||
*/
|
||||
private String buildConfigKey(String certificateType) {
|
||||
return CONFIG_KEY_PREFIX + certificateType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置键找出证照类型,如果是自定义证照,则是模板id
|
||||
*
|
||||
* @param key 配置键
|
||||
* @return 证照类型
|
||||
*/
|
||||
private String buildCertificateTypeOrTemplateId(String key) {
|
||||
if(StringUtil.isBlank(key)){
|
||||
return null;
|
||||
}
|
||||
return key.substring(CONFIG_KEY_PREFIX.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化文本
|
||||
*
|
||||
* @param text 原始文本
|
||||
* @return 规范化后的文本
|
||||
*/
|
||||
private String normalizeText(String text) {
|
||||
return StrUtil.trim(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量执行保存。
|
||||
* 先按ID分流为更新/插入;若出现唯一键冲突,则根据type全量回查后重新分流并重试一次。
|
||||
*
|
||||
* @param split 批量分流数据
|
||||
*/
|
||||
private void executeBatch(BatchParamSplit split) {
|
||||
try {
|
||||
executeBatchOnceInTransaction(split);
|
||||
} catch (Exception e) {
|
||||
if (!isDuplicateKeyException(e)) {
|
||||
throw e;
|
||||
}
|
||||
BatchParamSplit retrySplit = rebuildSplitByTypeFromDbInNewTransaction(split.getAllEntities());
|
||||
try {
|
||||
executeBatchOnceInTransaction(retrySplit);
|
||||
} catch (Exception ex) {
|
||||
if (!isDuplicateKeyException(ex)) {
|
||||
throw ex;
|
||||
}
|
||||
throw new ServiceException("该证照类型的预警配置已存在");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单次执行批量更新+批量插入。
|
||||
*
|
||||
* @param split 分流结果
|
||||
*/
|
||||
private void executeBatchOnce(BatchParamSplit split) {
|
||||
if (split == null || CollUtil.isEmpty(split.getAllEntities())) {
|
||||
return;
|
||||
}
|
||||
if (CollUtil.isNotEmpty(split.getUpdateEntities())) {
|
||||
baseParamMapper.batchUpdateById(split.getUpdateEntities());
|
||||
}
|
||||
if (CollUtil.isNotEmpty(split.getInsertEntities())) {
|
||||
baseParamMapper.batchInsertParam(split.getInsertEntities());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在事务中执行一次批量写入。
|
||||
*
|
||||
* @param split 分流结果
|
||||
*/
|
||||
private void executeBatchOnceInTransaction(BatchParamSplit split) {
|
||||
TransactionTemplate template = buildTransactionTemplate(TransactionDefinition.PROPAGATION_REQUIRED, false);
|
||||
template.execute(status -> {
|
||||
executeBatchOnce(split);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 预处理批量请求:校验参数并构建VO/实体。
|
||||
*
|
||||
* @param reqList 请求列表
|
||||
* @return 预处理结果列表
|
||||
*/
|
||||
private List<WarningNoticePreparedData> prepareSaveDataList(List<WarningNoticeSaveReq> reqList) {
|
||||
List<WarningNoticePreparedData> result = new ArrayList<>(reqList.size());
|
||||
Map<String, StoreCertificatePhotoEntity> stringStoreCertificatePhotoEntityMap = storeCertificatePhotoHelper.buildStoreCertificateById(reqList.stream()
|
||||
.map(WarningNoticeSaveReq::getTypeOrTemplateId)
|
||||
.filter(this::isStoreCertificateType)
|
||||
.collect(Collectors.toSet()),null);
|
||||
|
||||
for (WarningNoticeSaveReq req : reqList) {
|
||||
ServiceException.notNull(req, "保存参数不能为空");
|
||||
String typeOrTemplateId = req.getTypeOrTemplateId();
|
||||
Optional<CertificateTypeEnum> certificateTypeEnumOptional= CertificateTypeEnum.getByType(typeOrTemplateId);
|
||||
ServiceException.isTrue(certificateTypeEnumOptional.isPresent(), "证照类型不能为空");
|
||||
CertificateTypeEnum certificateType = certificateTypeEnumOptional.get();
|
||||
Integer expiryReminderDays = req.getExpiryReminderDays();
|
||||
if (certificateType != CertificateTypeEnum.STORE_CUSTOM_CERTIFICATE) {
|
||||
ServiceException.notNull(expiryReminderDays, "临期提醒时间不能为空");
|
||||
ServiceException.isTrue(expiryReminderDays >= 0, "临期提醒时间必须大于等于0");
|
||||
ServiceException.isTrue(expiryReminderDays<=180, "临期提醒时间最大180");
|
||||
}else{
|
||||
StoreCertificatePhotoEntity storeCertificatePhotoEntity = stringStoreCertificatePhotoEntityMap.get(typeOrTemplateId);
|
||||
ServiceException.notNull(storeCertificatePhotoEntity, "自定义证照不存在["+typeOrTemplateId+"]");
|
||||
expiryReminderDays = storeCertificatePhotoEntity.getExpiryReminderDays();
|
||||
}
|
||||
ServiceException.notNull(req.getNoticeFrequencyDays(), "通知频率不能为空");
|
||||
if(Objects.nonNull(expiryReminderDays) && expiryReminderDays > 0){
|
||||
ServiceException.isTrue(req.getNoticeFrequencyDays() <= expiryReminderDays, "通知频率必须小于等于临期提醒");
|
||||
}
|
||||
// validateNoticeConfigList(req.getNoticeConfigList());
|
||||
|
||||
String key = buildConfigKey(certificateType,typeOrTemplateId);
|
||||
WarningNoticeVO saveData = buildSaveData(req, certificateType, key);
|
||||
String reqId = normalizeText(req.getId());
|
||||
FtbParamEntity entity = buildBaseParamEntity(saveData, reqId);
|
||||
result.add(new WarningNoticePreparedData(typeOrTemplateId, reqId, entity));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isStoreCertificateType(String typeOrTemplateId) {
|
||||
Optional<CertificateTypeEnum> certificateTypeEnumOptional= CertificateTypeEnum.getByType(typeOrTemplateId);
|
||||
ServiceException.isTrue(certificateTypeEnumOptional.isPresent(), "证照类型不能为空");
|
||||
CertificateTypeEnum certificateType = certificateTypeEnumOptional.get();
|
||||
return CertificateTypeEnum.STORE_CUSTOM_CERTIFICATE.equals(certificateType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按是否有ID进行分流:有ID走更新,无ID走插入。
|
||||
*
|
||||
* @param preparedList 预处理结果列表
|
||||
* @return 分流结果
|
||||
*/
|
||||
private BatchParamSplit splitById(List<WarningNoticePreparedData> preparedList) {
|
||||
List<FtbParamEntity> updateEntities = new ArrayList<>();
|
||||
List<FtbParamEntity> insertEntities = new ArrayList<>();
|
||||
List<FtbParamEntity> allEntities = new ArrayList<>();
|
||||
for (WarningNoticePreparedData data : preparedList) {
|
||||
FtbParamEntity entity = data.getEntity();
|
||||
String reqId = data.getReqId();
|
||||
allEntities.add(entity);
|
||||
if (StrUtil.isNotBlank(reqId)) {
|
||||
updateEntities.add(entity);
|
||||
} else {
|
||||
insertEntities.add(entity);
|
||||
}
|
||||
}
|
||||
return new BatchParamSplit(updateEntities, insertEntities, allEntities);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量参数唯一性校验。
|
||||
* 同一次请求中同一type只能出现一次,同一id只能出现一次。
|
||||
*
|
||||
* @param preparedList 预处理列表
|
||||
*/
|
||||
private void validateBatchUniqueness(List<WarningNoticePreparedData> preparedList) {
|
||||
Set<String> typeSet = new HashSet<>();
|
||||
Set<String> reqIdSet = new HashSet<>();
|
||||
for (WarningNoticePreparedData data : preparedList) {
|
||||
String type = normalizeText(data.getType());
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(type), "证照类型不能为空");
|
||||
ServiceException.isTrue(typeSet.add(type), "同一次请求中证照类型不能重复");
|
||||
|
||||
String reqId = normalizeText(data.getReqId());
|
||||
if (StrUtil.isBlank(reqId)) {
|
||||
continue;
|
||||
}
|
||||
ServiceException.isTrue(reqIdSet.add(reqId), "同一次请求中ID不能重复");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* duplicate key 后按 type 全量回查,重建更新/插入集合。
|
||||
*
|
||||
* @param entities 本次要保存的实体
|
||||
* @return 重建后的分流结果
|
||||
*/
|
||||
private BatchParamSplit rebuildSplitByTypeFromDb(List<FtbParamEntity> entities) {
|
||||
if (CollUtil.isEmpty(entities)) {
|
||||
return new BatchParamSplit(Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
|
||||
}
|
||||
List<FtbParamEntity> dbList = baseParamMapper.selectList(
|
||||
new LambdaQueryWrapper<FtbParamEntity>().eq(FtbParamEntity::getType, certificateWarnNoticeType)
|
||||
);
|
||||
Map<String, FtbParamEntity> dbByKey = dbList.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> StrUtil.isNotBlank(item.getKey()))
|
||||
.collect(Collectors.toMap(item -> StrUtil.trim(item.getKey()), item -> item, (a, b) -> a));
|
||||
|
||||
List<FtbParamEntity> updateEntities = new ArrayList<>();
|
||||
List<FtbParamEntity> insertEntities = new ArrayList<>();
|
||||
List<FtbParamEntity> allEntities = new ArrayList<>();
|
||||
for (FtbParamEntity entity : entities) {
|
||||
if (entity == null || StrUtil.isBlank(entity.getKey())) {
|
||||
continue;
|
||||
}
|
||||
FtbParamEntity saveEntity = cloneParamEntity(entity);
|
||||
FtbParamEntity dbEntity = dbByKey.get(StrUtil.trim(saveEntity.getKey()));
|
||||
if (dbEntity != null && StrUtil.isNotBlank(dbEntity.getId())) {
|
||||
saveEntity.setId(StrUtil.trim(dbEntity.getId()));
|
||||
updateEntities.add(saveEntity);
|
||||
} else {
|
||||
if (StrUtil.isBlank(saveEntity.getId())) {
|
||||
saveEntity.setId(FtbUtil.getId());
|
||||
}
|
||||
insertEntities.add(saveEntity);
|
||||
}
|
||||
allEntities.add(saveEntity);
|
||||
}
|
||||
return new BatchParamSplit(updateEntities, insertEntities, allEntities);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在新事务中按type回查并重建分流结果。
|
||||
*
|
||||
* @param entities 本次要保存的实体
|
||||
* @return 重建后的分流结果
|
||||
*/
|
||||
private BatchParamSplit rebuildSplitByTypeFromDbInNewTransaction(List<FtbParamEntity> entities) {
|
||||
TransactionTemplate template = buildTransactionTemplate(TransactionDefinition.PROPAGATION_REQUIRES_NEW, true);
|
||||
BatchParamSplit split = template.execute(status -> rebuildSplitByTypeFromDb(entities));
|
||||
return split == null
|
||||
? new BatchParamSplit(Collections.emptyList(), Collections.emptyList(), Collections.emptyList())
|
||||
: split;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建事务模板。
|
||||
*
|
||||
* @param propagationBehavior 事务传播级别
|
||||
* @param readOnly 是否只读
|
||||
* @return 事务模板
|
||||
*/
|
||||
private TransactionTemplate buildTransactionTemplate(int propagationBehavior, boolean readOnly) {
|
||||
TransactionTemplate template = new TransactionTemplate(transactionManager);
|
||||
template.setPropagationBehavior(propagationBehavior);
|
||||
template.setReadOnly(readOnly);
|
||||
return template;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按key列表查询预警配置,返回值与入参顺序一致。
|
||||
*
|
||||
* @param keys 配置key列表
|
||||
* @return 预警配置列表
|
||||
*/
|
||||
private List<WarningNoticeVO> queryByKeys(List<String> keys) {
|
||||
if (CollUtil.isEmpty(keys)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<FtbParamEntity> dbList = baseParamMapper.selectList(
|
||||
new LambdaQueryWrapper<FtbParamEntity>()
|
||||
.eq(FtbParamEntity::getType, certificateWarnNoticeType)
|
||||
.in(FtbParamEntity::getKey, keys)
|
||||
);
|
||||
Map<String, WarningNoticeVO> voByKey = dbList.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> StrUtil.isNotBlank(item.getKey()))
|
||||
.collect(Collectors.toMap(
|
||||
item -> StrUtil.trim(item.getKey()),
|
||||
item -> normalizeWarningNoticeVO(buildWarningNoticeVO(item)),
|
||||
(a, b) -> a
|
||||
));
|
||||
|
||||
List<WarningNoticeVO> result = new ArrayList<>(keys.size());
|
||||
for (String key : keys) {
|
||||
WarningNoticeVO vo = voByKey.get(StrUtil.trim(key));
|
||||
if (vo != null) {
|
||||
result.add(vo);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制参数实体,避免重试时修改原对象。
|
||||
*
|
||||
* @param source 原实体
|
||||
* @return 复制后的实体
|
||||
*/
|
||||
private FtbParamEntity cloneParamEntity(FtbParamEntity source) {
|
||||
FtbParamEntity target = new FtbParamEntity();
|
||||
target.setId(normalizeText(source.getId()));
|
||||
target.setKey(normalizeText(source.getKey()));
|
||||
target.setType(normalizeText(source.getType()));
|
||||
target.setValue(source.getValue());
|
||||
target.setSort(source.getSort());
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断异常链中是否包含唯一键冲突。
|
||||
*
|
||||
* @param throwable 异常
|
||||
* @return 是否唯一键冲突
|
||||
*/
|
||||
private boolean isDuplicateKeyException(Throwable throwable) {
|
||||
Throwable current = throwable;
|
||||
while (current != null) {
|
||||
if (current instanceof DuplicateKeyException) {
|
||||
return true;
|
||||
}
|
||||
String message = current.getMessage();
|
||||
if (StrUtil.isNotBlank(message)
|
||||
&& StrUtil.containsIgnoreCase(message, "duplicate")
|
||||
&& StrUtil.containsIgnoreCase(message, "key")) {
|
||||
return true;
|
||||
}
|
||||
current = current.getCause();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预处理数据载体。
|
||||
*/
|
||||
private static class WarningNoticePreparedData {
|
||||
private final String type;
|
||||
private final String reqId;
|
||||
private final FtbParamEntity entity;
|
||||
|
||||
private WarningNoticePreparedData(String type, String reqId, FtbParamEntity entity) {
|
||||
this.type = type;
|
||||
this.reqId = reqId;
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
private String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
private String getReqId() {
|
||||
return reqId;
|
||||
}
|
||||
|
||||
private FtbParamEntity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新/插入分流结果。
|
||||
*/
|
||||
private static class BatchParamSplit {
|
||||
private final List<FtbParamEntity> updateEntities;
|
||||
private final List<FtbParamEntity> insertEntities;
|
||||
private final List<FtbParamEntity> allEntities;
|
||||
|
||||
private BatchParamSplit(List<FtbParamEntity> updateEntities,
|
||||
List<FtbParamEntity> insertEntities,
|
||||
List<FtbParamEntity> allEntities) {
|
||||
this.updateEntities = updateEntities;
|
||||
this.insertEntities = insertEntities;
|
||||
this.allEntities = allEntities;
|
||||
}
|
||||
|
||||
private List<FtbParamEntity> getUpdateEntities() {
|
||||
return updateEntities;
|
||||
}
|
||||
|
||||
private List<FtbParamEntity> getInsertEntities() {
|
||||
return insertEntities;
|
||||
}
|
||||
|
||||
private List<FtbParamEntity> getAllEntities() {
|
||||
return allEntities;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user