This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
package jnpf.certificate.service;
|
||||
|
||||
import jnpf.model.certificate.req.app.CertificateAppBatchRemindReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppSingleRemindReq;
|
||||
|
||||
/**
|
||||
* App端证照提醒服务。
|
||||
*/
|
||||
public interface CertificateAppReminderService {
|
||||
|
||||
/**
|
||||
* 一键提醒。
|
||||
*
|
||||
* @param req 提醒参数
|
||||
*/
|
||||
void batchRemind(CertificateAppBatchRemindReq req);
|
||||
|
||||
/**
|
||||
* 单个提醒。
|
||||
*
|
||||
* @param req 提醒参数
|
||||
*/
|
||||
void singleRemind(CertificateAppSingleRemindReq req);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package jnpf.certificate.service;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.model.certificate.req.app.CertificateAppEmployeeRiskQueryReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppRiskChartReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppStoreRiskQueryReq;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppEmployeeRiskVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppRiskChartVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppRiskReminderCountVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppStoreRiskVO;
|
||||
|
||||
/**
|
||||
* App 端证照风险服务。
|
||||
*/
|
||||
public interface CertificateAppRiskService {
|
||||
|
||||
/**
|
||||
* 查询证照风险图表统计。
|
||||
*
|
||||
* @param req 查询参数(组织门店、证照类型)
|
||||
* @return 图表统计结果
|
||||
*/
|
||||
CertificateAppRiskChartVO queryChart(CertificateAppRiskChartReq req);
|
||||
|
||||
/**
|
||||
* 分页查询员工证照风险列表(缺失、临期、过期)。
|
||||
*
|
||||
* @param req 查询参数(组织门店、分页)
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageInfo<CertificateAppEmployeeRiskVO> queryEmployeePage(CertificateAppEmployeeRiskQueryReq req);
|
||||
|
||||
/**
|
||||
* 分页查询门店证照风险列表(缺失、临期、过期)。
|
||||
*
|
||||
* @param req 查询参数(组织门店、证照类型、状态、分页)
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageInfo<CertificateAppStoreRiskVO> queryStorePage(CertificateAppStoreRiskQueryReq req);
|
||||
|
||||
/**
|
||||
* 查询风险提醒总数量(员工+组织)。
|
||||
*
|
||||
* @return 风险提醒数量统计
|
||||
*/
|
||||
CertificateAppRiskReminderCountVO queryRiskReminderCount(String orgId);
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package jnpf.certificate.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.model.certificate.po.CertificateInstanceEntity;
|
||||
import jnpf.model.certificate.req.CertificateInstanceAddReq;
|
||||
import jnpf.model.certificate.req.CertificateHealthManageQueryReq;
|
||||
import jnpf.model.certificate.req.CertificateInstanceQueryReq;
|
||||
import jnpf.model.certificate.req.CertificateStoreManageQueryReq;
|
||||
import jnpf.model.certificate.req.CertificateStoreDashboardReq;
|
||||
import jnpf.model.certificate.req.CertificateSyncHealthReq;
|
||||
import jnpf.model.certificate.req.CertificateInstanceUpdateReq;
|
||||
import jnpf.model.certificate.vo.CertificateHealthManageVO;
|
||||
import jnpf.model.certificate.vo.CertificateInstanceVO;
|
||||
import jnpf.model.certificate.vo.CertificateTypeOptionVO;
|
||||
import jnpf.model.certificate.vo.CertificateStoreManageVO;
|
||||
import jnpf.model.certificate.vo.CertificateStoreDashboardVO;
|
||||
import jnpf.model.certificate.vo.CertificateStoreCustomStatusTableVO;
|
||||
import jnpf.model.certificate.vo.app.HealthCertificateDetailVO;
|
||||
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 证照实例服务。
|
||||
*/
|
||||
public interface CertificateInstanceService extends IService<CertificateInstanceEntity> {
|
||||
|
||||
/**
|
||||
* 新增证照实例。
|
||||
*
|
||||
* @param req 请求参数
|
||||
*/
|
||||
void add(CertificateInstanceAddReq req);
|
||||
|
||||
/**
|
||||
* 更新证照实例。
|
||||
*
|
||||
* @param req 请求参数
|
||||
*/
|
||||
void update(CertificateInstanceUpdateReq req);
|
||||
|
||||
/**
|
||||
* 按ID查询详情。
|
||||
*
|
||||
* @param id 实例ID
|
||||
* @return 详情
|
||||
*/
|
||||
CertificateInstanceVO queryInfo(String id);
|
||||
|
||||
/**
|
||||
* 分页查询列表。
|
||||
*
|
||||
* @param req 查询参数
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageInfo<CertificateInstanceVO> queryPage(CertificateInstanceQueryReq req);
|
||||
|
||||
/**
|
||||
* 健康证管理分页查询。
|
||||
*
|
||||
* @param req 查询参数
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageInfo<CertificateHealthManageVO> queryHealthPage(CertificateHealthManageQueryReq req);
|
||||
|
||||
/**
|
||||
* 门店证照分页查询。
|
||||
*
|
||||
* @param req 查询参数
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageInfo<CertificateStoreManageVO> queryStorePage(CertificateStoreManageQueryReq req);
|
||||
|
||||
/**
|
||||
* 逻辑删除。
|
||||
*
|
||||
* @param id 实例ID
|
||||
*/
|
||||
void delete(String id);
|
||||
|
||||
/**
|
||||
* 保存用户的健康证信息
|
||||
* @param userId
|
||||
* @param healthCertificate
|
||||
* @param startHealthDate
|
||||
* @param endHealthDate
|
||||
*/
|
||||
void saveHealthCertificate(String userId, String healthCertificate, String startHealthDate, String endHealthDate);
|
||||
|
||||
/**
|
||||
* 删除员工健康证
|
||||
* @param userId
|
||||
*/
|
||||
void deleteHealthCertificate(String userId);
|
||||
|
||||
/**
|
||||
* 根据用户id查询健康证
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
Optional<HealthCertificateDetailVO> getHealthCertificateDetail(String userId);
|
||||
|
||||
/**
|
||||
* 根据用户id查询健康证
|
||||
* @param userIds
|
||||
* @return
|
||||
*/
|
||||
List<HealthCertificateDetailVO> getHealthCertificateDetails(Collection<String> userIds);
|
||||
|
||||
/**
|
||||
* 根据用户id查询健康证
|
||||
* @param userIds
|
||||
* @return
|
||||
*/
|
||||
default Map<String, HealthCertificateDetailVO> getHealthCertificateDetailMap(Collection<String> userIds){
|
||||
return getHealthCertificateDetails(userIds)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(HealthCertificateDetailVO::getUserId, v -> v));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据状态,证照类型 查询用户id列表
|
||||
* @param status
|
||||
* @return
|
||||
*/
|
||||
List<String> getUserIdsByStatus(Integer status,String certificateType);
|
||||
|
||||
/**
|
||||
* 查询健康证用户id列表
|
||||
* @param status
|
||||
* @return
|
||||
*/
|
||||
default List<String> getHealthCertificateUserIdsByStatus(Integer status){
|
||||
return getUserIdsByStatus(status, CertificateTypeEnum.HEALTH_CERTIFICATE.getType());
|
||||
}
|
||||
/**
|
||||
* 门店自定义证照看板统计。
|
||||
*
|
||||
* @param req 查询参数
|
||||
* @return 看板统计结果
|
||||
*/
|
||||
CertificateStoreDashboardVO storeCertificateDashboard(CertificateStoreDashboardReq req);
|
||||
|
||||
/**
|
||||
* 门店证照看板表格分页查询。
|
||||
*
|
||||
* @param req 查询参数
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageInfo<CertificateStoreCustomStatusTableVO> storeCertificateDashboardTablePage(CertificateStoreDashboardReq req);
|
||||
|
||||
/**
|
||||
* 查询证照类型下拉选项。
|
||||
*
|
||||
* @return 证照类型选项
|
||||
*/
|
||||
List<CertificateTypeOptionVO> queryCertificateTypeList();
|
||||
|
||||
/**
|
||||
* 批量初始化员工健康证实例(缺失状态)。
|
||||
*
|
||||
* @param userIds 员工用户ID集合
|
||||
* @return 初始化条数
|
||||
*/
|
||||
int batchInitHealthCertificate(Collection<String> userIds);
|
||||
|
||||
/**
|
||||
* 初始化员工健康证实例(缺失状态)。
|
||||
*
|
||||
* @param userId 员工用户ID
|
||||
* @return 是否成功
|
||||
*/
|
||||
default boolean initHealthCertificate(String userId){
|
||||
return batchInitHealthCertificate(List.of(userId)) > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package jnpf.certificate.service;
|
||||
|
||||
import jnpf.model.certificate.vo.CertificateOrganizeBusinessLicenseVO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 组织营业执照开放接口服务。
|
||||
*/
|
||||
public interface CertificateManageApiService {
|
||||
|
||||
/**
|
||||
* 根据组织ID查询营业执照信息。
|
||||
*
|
||||
* @param organizeId 组织ID
|
||||
* @return 营业执照信息
|
||||
*/
|
||||
CertificateOrganizeBusinessLicenseVO queryBusinessLicense(String organizeId);
|
||||
|
||||
/**
|
||||
* 根据组织ID列表批量查询营业执照信息。
|
||||
*
|
||||
* @param organizeIds 组织ID列表
|
||||
* @return 营业执照信息列表
|
||||
*/
|
||||
List<CertificateOrganizeBusinessLicenseVO> queryBusinessLicenseBatch(Collection<String> organizeIds);
|
||||
|
||||
/**
|
||||
* 保存营业执照信息。
|
||||
*
|
||||
* @param req 营业执照参数
|
||||
*/
|
||||
void saveBusinessLicense(CertificateOrganizeBusinessLicenseVO req);
|
||||
|
||||
/**
|
||||
* 初始化门店默认缺失证照(营业执照、食品经营许可证)。
|
||||
*
|
||||
* @param storeId 门店ID
|
||||
*/
|
||||
void initStoreDefaultCertificates(String storeId);
|
||||
|
||||
/**
|
||||
* 根据组织ID删除该主体下全部证照信息。
|
||||
*
|
||||
* @param organizeId 组织ID
|
||||
* @param loginUserId 当前登录用户ID
|
||||
*/
|
||||
void deleteBusinessLicense(String organizeId, String loginUserId);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package jnpf.certificate.service;
|
||||
|
||||
import jnpf.model.certificate.req.app.CertificateAppBusinessLicenseUpdateReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppHealthCertificateUpdateReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppHygieneLicenseUpdateReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppStoreCustomUpdateReq;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppCertificateDetailVO;
|
||||
|
||||
/**
|
||||
* 端证照管理服务。
|
||||
*/
|
||||
public interface CertificateManageService {
|
||||
|
||||
/**
|
||||
* 根据证照实例ID查询详情。
|
||||
*
|
||||
* @param certificateInstanceId 证照实例ID
|
||||
* @return 证照详情
|
||||
*/
|
||||
CertificateAppCertificateDetailVO queryInfo(String certificateInstanceId);
|
||||
|
||||
/**
|
||||
* 更新健康证。
|
||||
*
|
||||
* @param req 更新参数
|
||||
*/
|
||||
void updateHealthCertificate(CertificateAppHealthCertificateUpdateReq req);
|
||||
|
||||
/**
|
||||
* 更新营业执照。
|
||||
*
|
||||
* @param req 更新参数
|
||||
*/
|
||||
void updateBusinessLicense(CertificateAppBusinessLicenseUpdateReq req);
|
||||
|
||||
/**
|
||||
* 更新食品经营许可证。
|
||||
*
|
||||
* @param req 更新参数
|
||||
*/
|
||||
void updateHygieneLicense(CertificateAppHygieneLicenseUpdateReq req);
|
||||
|
||||
/**
|
||||
* 更新门店自定义证照。
|
||||
*
|
||||
* @param req 更新参数
|
||||
*/
|
||||
void updateStoreCustomCertificate(CertificateAppStoreCustomUpdateReq req);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package jnpf.certificate.service;
|
||||
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.certificate.req.CertificateStoreSaveReq;
|
||||
import jnpf.model.certificate.vo.CertificateStoreAndCertificatesVO;
|
||||
import jnpf.model.certificate.vo.CertificateStoreTabVO;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 门店证照服务。
|
||||
*/
|
||||
public interface CertificateStoreService {
|
||||
|
||||
/**
|
||||
* 保存门店及证照数据。
|
||||
*
|
||||
* @param req 保存参数
|
||||
*/
|
||||
String saveStoreAndCertificates(CertificateStoreSaveReq req);
|
||||
|
||||
/**
|
||||
* 删除门店。
|
||||
*
|
||||
* @param id 门店ID
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean deleteStore(@PathVariable("id") String id) throws HandleException;
|
||||
|
||||
/**
|
||||
* 根据门店ID查询门店及门店证照详情。
|
||||
*
|
||||
* @param storeId 门店ID
|
||||
* @return 门店及门店证照详情
|
||||
*/
|
||||
CertificateStoreAndCertificatesVO getStoreAndCertificates(String storeId);
|
||||
|
||||
/**
|
||||
* 查询门店证照Tab列表。
|
||||
*
|
||||
* @return 门店证照Tab列表
|
||||
*/
|
||||
List<CertificateStoreTabVO> queryStoreCertificateTabList();
|
||||
}
|
||||
@@ -0,0 +1,628 @@
|
||||
package jnpf.certificate.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import jnpf.authority.utils.PermissionsApplicableEnums;
|
||||
import jnpf.authority.utils.PermissionsApplicableObject;
|
||||
import jnpf.authority.utils.PermissionsUtils;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.certificate.helper.NoticeHelper;
|
||||
import jnpf.certificate.helper.OrganizationHelper;
|
||||
import jnpf.certificate.mapper.CertificateInstanceMapper;
|
||||
import jnpf.certificate.model.CertificateAppReminderRecord;
|
||||
import jnpf.certificate.service.CertificateAppReminderService;
|
||||
import jnpf.certificate.util.SubjectNameUtils;
|
||||
import jnpf.model.certificate.po.CertificateInstanceEntity;
|
||||
import jnpf.model.certificate.req.app.CertificateAppBatchRemindReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppSingleRemindReq;
|
||||
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
|
||||
import jnpf.permission.V2UserApi;
|
||||
import jnpf.permission.vo.v2.organzie.OrganizeBaseInfoVO;
|
||||
import jnpf.permission.vo.v2.organzie.OrganizeGeneralDetailVO;
|
||||
import jnpf.permission.vo.v2.user.UserBoundInfoVO;
|
||||
import jnpf.storecertificatephoto.helper.StoreCertificatePhotoHelper;
|
||||
import jnpf.util.ServiceException;
|
||||
import jnpf.util.StringUtil;
|
||||
import jnpf.util.UserProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutableTriple;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static jnpf.certificate.helper.NoticeHelper.URL_CERTIFICATE;
|
||||
|
||||
/**
|
||||
* App端证照提醒服务实现。
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class CertificateAppReminderServiceImpl implements CertificateAppReminderService {
|
||||
|
||||
private static final int STATUS_MISSING = 1;
|
||||
private static final int STATUS_EXPIRED = 2;
|
||||
private static final int STATUS_NEAR_EXPIRE = 3;
|
||||
private static final int STATUS_NORMAL = 4;
|
||||
|
||||
private static final int SUBJECT_TYPE_EMPLOYEE = 1;
|
||||
private static final int SUBJECT_TYPE_ORGANIZATION = 2;
|
||||
private static final int SUBJECT_TYPE_STORE = 3;
|
||||
|
||||
@Autowired
|
||||
private CertificateInstanceMapper certificateInstanceMapper;
|
||||
@Autowired
|
||||
private V2UserApi v2UserApi;
|
||||
@Autowired
|
||||
private OrganizationHelper organizationHelper;
|
||||
@Autowired
|
||||
private PermissionsUtils permissionsUtils;
|
||||
@Autowired
|
||||
private NoticeHelper noticeHelper;
|
||||
@Autowired
|
||||
private StoreCertificatePhotoHelper storeCertificatePhotoHelper;
|
||||
@Autowired
|
||||
private ThreadPoolTaskExecutor commonExecutor;
|
||||
|
||||
/**
|
||||
* 一键提醒。
|
||||
* 健康证提醒员工本人,非健康证提醒组织负责人。
|
||||
*/
|
||||
@Override
|
||||
public void batchRemind(CertificateAppBatchRemindReq req) {
|
||||
log.error("batchRemind req:{}",req);
|
||||
ServiceException.notNull(req, "请求参数不能为空");
|
||||
Integer subjectType = req.getSubjectType();
|
||||
ServiceException.isTrue(subjectType != null && subjectType >= SUBJECT_TYPE_EMPLOYEE && subjectType <= SUBJECT_TYPE_STORE,
|
||||
"主体类型不合法");
|
||||
|
||||
// 构建查询的subjectType列表,subjectType=2时同时查3
|
||||
List<Integer> subjectTypes = new ArrayList<>();
|
||||
subjectTypes.add(subjectType);
|
||||
if (Integer.valueOf(SUBJECT_TYPE_ORGANIZATION).equals(subjectType)) {
|
||||
subjectTypes.add(SUBJECT_TYPE_STORE);
|
||||
}
|
||||
// 查询非正常状态的证照实例
|
||||
List<Integer> statuses = Arrays.asList(STATUS_MISSING, STATUS_EXPIRED, STATUS_NEAR_EXPIRE);
|
||||
|
||||
List<CertificateInstanceEntity> records= null;
|
||||
List<String> userIds = buildQueryUserIds(req.getOrgId());
|
||||
if(Objects.nonNull(userIds) && userIds.isEmpty()){//没查到数据,返回
|
||||
return;
|
||||
}
|
||||
if(req.getSubjectType() == SUBJECT_TYPE_EMPLOYEE){
|
||||
records = certificateInstanceMapper.selectBySubjectTypesAndStatusesFilterUser(subjectTypes, statuses,userIds);
|
||||
}else{
|
||||
records = certificateInstanceMapper.selectBySubjectTypesAndStatusesFilterOrganization(subjectTypes, statuses,req.getOrgId());
|
||||
}
|
||||
|
||||
if (CollUtil.isEmpty(records)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String tenantId = UserProvider.getUser().getTenantId();
|
||||
String remindUserName = StrUtil.blankToDefault(StrUtil.trim(UserProvider.getUser().getUserName()), "系统");
|
||||
|
||||
// 按是否健康证分组,批量解析接收人
|
||||
Map<Boolean, List<CertificateInstanceEntity>> grouped = records.stream()
|
||||
.collect(Collectors.partitioningBy(r -> isHealthCertificate(r.getCertificateType())));
|
||||
|
||||
// 健康证:接收人就是员工本人(subjectId)
|
||||
Map<String, String> healthReceiverMap = resolveHealthReceivers(grouped.getOrDefault(true, Collections.emptyList()));
|
||||
// 非健康证:接收人是组织负责人
|
||||
MutableTriple<Map<String,String>,Map<String,String>,Map<String,String>>
|
||||
orgReceiversAndOrgNamesAndTemplateNames = buildOrgReceiversAndOrgNamesAndTemplateNames(grouped.getOrDefault(false, Collections.emptyList()));
|
||||
|
||||
Map<String,String> orgReceivers = orgReceiversAndOrgNamesAndTemplateNames.getLeft();
|
||||
Map<String,String> orgNames = orgReceiversAndOrgNamesAndTemplateNames.getMiddle();
|
||||
Map<String,String> templateNames = orgReceiversAndOrgNamesAndTemplateNames.getRight();
|
||||
|
||||
List<CertificateInstanceEntity> finalRecords = records;
|
||||
commonExecutor.execute(() -> sendNotices(finalRecords, healthReceiverMap, orgReceivers, orgNames, templateNames, tenantId, remindUserName));
|
||||
}
|
||||
|
||||
private List<String> buildQueryUserIds(String orgId) {
|
||||
if(StringUtil.isBlank(orgId)){
|
||||
return null;
|
||||
}
|
||||
Map<String,List<String>> userIdsByOrgIds = organizationHelper.buildUserIdsByOrgIds(List.of(orgId),false,null);
|
||||
if(CollUtil.isEmpty(userIdsByOrgIds)){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<String> userIds = userIdsByOrgIds.get(orgId);
|
||||
if(CollectionUtil.isEmpty(userIds)){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return userIds;
|
||||
}
|
||||
|
||||
private void sendNotices(List<CertificateInstanceEntity> records,
|
||||
Map<String, String> healthReceiverMap,
|
||||
Map<String,String> orgReceivers,
|
||||
Map<String,String> orgNames,
|
||||
Map<String,String> templateNames,
|
||||
String tenantId,
|
||||
String remindUserName){
|
||||
for (CertificateInstanceEntity record : records) {
|
||||
String receiverUserId = isHealthCertificate(record.getCertificateType())
|
||||
? healthReceiverMap.get(StrUtil.trim(record.getSubjectId()))
|
||||
: orgReceivers.get(StrUtil.trim(record.getSubjectId()));
|
||||
if (StrUtil.isBlank(receiverUserId)) {
|
||||
continue;
|
||||
}
|
||||
String subjectId = record.getSubjectId();
|
||||
String orgName = orgNames.get(subjectId);
|
||||
String templateName = null;
|
||||
|
||||
String templateId = record.getTemplateId();
|
||||
if(StringUtil.isNotBlank(templateId)){
|
||||
templateName = templateNames.get(templateId);
|
||||
}
|
||||
sendNotice(record, receiverUserId, tenantId, remindUserName,templateName,orgName);
|
||||
}
|
||||
}
|
||||
|
||||
// 批量解析健康证接收人:subjectId -> userId
|
||||
private Map<String, String> resolveHealthReceivers(List<CertificateInstanceEntity> records) {
|
||||
if (CollUtil.isEmpty(records)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Set<String> subjectIds = records.stream()
|
||||
.map(r -> StrUtil.trim(r.getSubjectId()))
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
if (CollUtil.isEmpty(subjectIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
// 健康证subjectId就是userId,直接映射
|
||||
Map<String, String> result = new HashMap<>(subjectIds.size());
|
||||
subjectIds.forEach(id -> result.put(id, id));
|
||||
return result;
|
||||
}
|
||||
|
||||
// 批量解析非健康证接收人:subjectId(组织/门店) -> leaderId
|
||||
private Map<String, String> resolveOrgReceivers(List<CertificateInstanceEntity> records) {
|
||||
if (CollUtil.isEmpty(records)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Set<String> subjectIds = records.stream()
|
||||
.map(r -> StrUtil.trim(r.getSubjectId()))
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
if (CollUtil.isEmpty(subjectIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, OrganizeGeneralDetailVO> organizeMap = organizationHelper.buildOrganizeGenerals(subjectIds);
|
||||
Map<String, String> result = new HashMap<>(subjectIds.size());
|
||||
for (String subjectId : subjectIds) {
|
||||
OrganizeGeneralDetailVO org = organizeMap.get(subjectId);
|
||||
if (org != null && StrUtil.isNotBlank(org.getLeaderId())) {
|
||||
result.put(subjectId, StrUtil.trim(org.getLeaderId()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 左边是 组织接收人。key为subjectId,value为组织负责人id
|
||||
* 中间是 组织名称,key为组织id,value为组织名称
|
||||
* 右边是 模板名称,key为模板id,value为模板名称
|
||||
* @param records
|
||||
* @return
|
||||
*/
|
||||
private MutableTriple<Map<String,String>,Map<String,String>,Map<String,String>>
|
||||
buildOrgReceiversAndOrgNamesAndTemplateNames(List<CertificateInstanceEntity> records) {
|
||||
if (CollUtil.isEmpty(records)) {
|
||||
return MutableTriple.of(Collections.emptyMap(),Collections.emptyMap(),Collections.emptyMap());
|
||||
}
|
||||
|
||||
Set<String> templateIds = new HashSet<>();
|
||||
Set<String> orgIds = new HashSet<>();
|
||||
for (CertificateInstanceEntity record:records){
|
||||
String templateId = record.getTemplateId();
|
||||
if(StringUtil.isNotBlank(templateId)){
|
||||
templateIds.add(templateId);
|
||||
}
|
||||
orgIds.add(record.getSubjectId());
|
||||
}
|
||||
|
||||
Map<String,String> orgReceivers = new HashMap<>();
|
||||
Map<String,String> orgNames = new HashMap<>();
|
||||
|
||||
Map<String, OrganizeGeneralDetailVO> organizeMap = organizationHelper.buildOrganizeGenerals(orgIds);
|
||||
Map<String,String> templateNames = storeCertificatePhotoHelper.buildStoreCertificateIdAndNames(templateIds,null);
|
||||
for (String orgId : orgIds) {
|
||||
OrganizeGeneralDetailVO org = organizeMap.get(orgId);
|
||||
if(Objects.isNull(org)){
|
||||
continue;
|
||||
}
|
||||
if (StrUtil.isNotBlank(org.getLeaderId())) {
|
||||
orgReceivers.put(orgId, StrUtil.trim(org.getLeaderId()));
|
||||
}
|
||||
orgNames.put(orgId,org.getName());
|
||||
}
|
||||
return MutableTriple.of(orgReceivers,orgNames,templateNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个提醒。
|
||||
* 根据证照实例ID查询后,按证照类型解析接收人并发送提醒。
|
||||
*/
|
||||
@Override
|
||||
public void singleRemind(CertificateAppSingleRemindReq req) {
|
||||
ServiceException.notNull(req, "请求参数不能为空");
|
||||
List<String> certificateInstanceIds = req.getCertificateInstanceIds();
|
||||
ServiceException.isTrue(CollUtil.isNotEmpty(certificateInstanceIds), "证照实例ID不能为空");
|
||||
|
||||
// 查询证照实例
|
||||
List<CertificateInstanceEntity> certificateInstanceEntities = certificateInstanceMapper.selectBatchIds(certificateInstanceIds);
|
||||
if(CollUtil.isEmpty(certificateInstanceEntities)){
|
||||
log.warn("证照实例不存在,certificateInstanceId={}", certificateInstanceIds);
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> templateIds = new HashSet<>();
|
||||
Set<String> orgIds = new HashSet<>();
|
||||
for (CertificateInstanceEntity record:certificateInstanceEntities) {
|
||||
if (record.getStatus() == null || Integer.valueOf(STATUS_NORMAL).equals(record.getStatus())) {
|
||||
log.warn("证照状态无需提醒,certificateInstanceId={}, status={}", record.getId(), record.getStatus());
|
||||
continue;
|
||||
}
|
||||
String templateId = record.getTemplateId();
|
||||
Integer subjectType = record.getSubjectType();
|
||||
String subjectId = record.getSubjectId();
|
||||
if(StringUtil.isNotBlank(templateId)){
|
||||
templateIds.add(templateId);
|
||||
}
|
||||
if(Objects.nonNull(subjectType) && subjectType != SUBJECT_TYPE_EMPLOYEE){
|
||||
orgIds.add(subjectId);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String,String> templateIdAndNames = storeCertificatePhotoHelper.buildStoreCertificateIdAndNames(templateIds,null);
|
||||
Map<String, OrganizeBaseInfoVO> organizeBaseInfoById = organizationHelper.buildBaseOrganizeVO(orgIds,UserProvider.getUser().getTenantId());
|
||||
|
||||
for (CertificateInstanceEntity record:certificateInstanceEntities){
|
||||
if (record.getStatus() == null || Integer.valueOf(STATUS_NORMAL).equals(record.getStatus())) {
|
||||
log.warn("证照状态无需提醒,certificateInstanceId={}, status={}", record.getId(), record.getStatus());
|
||||
continue;
|
||||
}
|
||||
|
||||
// 解析接收人
|
||||
String receiverUserId = resolveSingleReceiverUserId(record,organizeBaseInfoById);
|
||||
if (StrUtil.isBlank(receiverUserId)) {
|
||||
log.warn("未找到提醒接收人,certificateInstanceId={}, subjectType={}, subjectId={}",
|
||||
record.getId(), record.getSubjectType(), record.getSubjectId());
|
||||
continue;
|
||||
}
|
||||
|
||||
String tenantId = UserProvider.getUser().getTenantId();
|
||||
String remindUserName = StrUtil.blankToDefault(StrUtil.trim(UserProvider.getUser().getUserName()), "系统");
|
||||
|
||||
String templateName = templateIdAndNames.get(record.getTemplateId());
|
||||
String orgName = null;
|
||||
OrganizeBaseInfoVO organizeBaseInfoVO = organizeBaseInfoById.get(record.getSubjectId());
|
||||
if(Objects.nonNull(organizeBaseInfoVO)){
|
||||
orgName = organizeBaseInfoVO.getName();
|
||||
}
|
||||
|
||||
sendNotice(record, receiverUserId, tenantId, remindUserName,templateName,orgName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析单条提醒的接收人用户ID。
|
||||
* 健康证:通过V2UserApi#getUsersBound查询员工本人信息。
|
||||
* 非健康证:通过OrganizationHelper#buildOrganizeGenerals查询组织负责人。
|
||||
*/
|
||||
private String resolveSingleReceiverUserId(CertificateInstanceEntity record,Map<String, OrganizeBaseInfoVO> organizeBaseInfoById) {
|
||||
String subjectId = StrUtil.trim(record.getSubjectId());
|
||||
if (StrUtil.isBlank(subjectId)) {
|
||||
return null;
|
||||
}
|
||||
if (isHealthCertificate(record.getCertificateType())) {
|
||||
return subjectId;
|
||||
}
|
||||
OrganizeBaseInfoVO organize = organizeBaseInfoById.get(subjectId);
|
||||
if (organize == null) {
|
||||
log.error("组织信息不存在,subjectId={}", subjectId);
|
||||
return null;
|
||||
}
|
||||
return StrUtil.trim(organize.getLeaderId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送单条提醒消息。
|
||||
*/
|
||||
private void sendNotice(CertificateInstanceEntity record,
|
||||
String receiverUserId,
|
||||
String tenantId,
|
||||
String remindUserName,
|
||||
String templateName,
|
||||
String orgName) {
|
||||
if (record == null) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isBlank(receiverUserId)) {
|
||||
return;
|
||||
}
|
||||
NoticeMessage noticeMessage = buildNoticeMessage(record, remindUserName,templateName,orgName);
|
||||
|
||||
if(isHealthCertificate(record.getCertificateType())){
|
||||
noticeHelper.sendMessage(
|
||||
Collections.singletonList(receiverUserId),
|
||||
tenantId,
|
||||
noticeMessage.getTitle(),
|
||||
noticeMessage.getContent(),
|
||||
NoticeHelper.BUTTON_NAME_HANDLER,
|
||||
buildJumpHealthCertificateUrl(record),
|
||||
NoticeHelper.MP_ID_CERTIFICATE
|
||||
);
|
||||
return;
|
||||
}
|
||||
noticeHelper.sendMessage(
|
||||
Collections.singletonList(receiverUserId),
|
||||
tenantId,
|
||||
noticeMessage.getTitle(),
|
||||
noticeMessage.getContent(),
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
private String buildJumpHealthCertificateUrl(CertificateInstanceEntity record) {
|
||||
if(Objects.isNull(record)){
|
||||
return null;
|
||||
}
|
||||
String subjectId = record.getSubjectId();
|
||||
if(StringUtil.isBlank(subjectId)){
|
||||
return null;
|
||||
}
|
||||
return String.format(URL_CERTIFICATE,record.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建提醒文案。
|
||||
* 文案依据原型:标题“存在风险,请及时处理”,正文按缺失/临期/过期区分。
|
||||
*/
|
||||
private NoticeMessage buildNoticeMessage(CertificateInstanceEntity record,
|
||||
String remindUserName,
|
||||
String templateName,
|
||||
String orgName) {
|
||||
String certificateType = StrUtil.trim(record.getCertificateType());
|
||||
Integer status = record.getStatus();
|
||||
String certificateName = resolveCertificateTypeName(certificateType,templateName);
|
||||
int remainDays = calculateRemainDays(record.getExpireDate());
|
||||
String subjectName = StrUtil.blankToDefault(orgName,StrUtil.blankToDefault(SubjectNameUtils.getSubjectName(record.getSubjectType()), "该主体"));
|
||||
|
||||
if (isHealthCertificate(certificateType)) {
|
||||
String title = "您的健康证存在风险,请及时处理!";
|
||||
if (Integer.valueOf(STATUS_NEAR_EXPIRE).equals(status)) {
|
||||
return new NoticeMessage(title, buildHealthCertificateNearExpireContent(remainDays,remindUserName));
|
||||
}
|
||||
if (Integer.valueOf(STATUS_EXPIRED).equals(status)) {
|
||||
return new NoticeMessage(title, String.format("您的健康证已过期,%s提醒您及时更新健康证。", remindUserName));
|
||||
}
|
||||
return new NoticeMessage(title, String.format("您的健康证缺失,%s提醒您及时更新健康证。", remindUserName));
|
||||
}
|
||||
|
||||
String title = subjectName + certificateName + "存在风险,请及时处理!";
|
||||
if (Integer.valueOf(STATUS_NEAR_EXPIRE).equals(status)) {
|
||||
return new NoticeMessage(title, buildCertificateNearExpireContent(subjectName,certificateName,remainDays));
|
||||
}
|
||||
if (Integer.valueOf(STATUS_EXPIRED).equals(status)) {
|
||||
return new NoticeMessage(title, String.format("%s%s已过期,请及时更新%s。", subjectName, certificateName, certificateName));
|
||||
}
|
||||
return new NoticeMessage(title, String.format("%s%s缺失,请及时上传%s。", subjectName, certificateName, certificateName));
|
||||
}
|
||||
|
||||
private String buildCertificateNearExpireContent(String subjectName, String certificateName, int remainDays) {
|
||||
if(remainDays <= 0){
|
||||
return String.format("%s%s今天过期,请及时更新%s。", subjectName, certificateName, certificateName);
|
||||
}
|
||||
return String.format("%s%s离到期时间还有%s天,请及时更新%s。", subjectName, certificateName, remainDays, certificateName);
|
||||
}
|
||||
|
||||
private String buildHealthCertificateNearExpireContent(int remainDays,String remindUserName) {
|
||||
if(remainDays <= 0){
|
||||
return String.format("您的健康证今天过期,%s提醒您请及时更新健康证。", remindUserName);
|
||||
}
|
||||
return String.format("您的健康证离到期时间还有%s天,%s提醒您请及时更新健康证。", remainDays,remindUserName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单条提醒权限校验。
|
||||
*/
|
||||
private void validateSinglePermission(CertificateAppReminderRecord record, String userId, String moduleId) {
|
||||
Integer subjectType = record.getSubjectType();
|
||||
if (Integer.valueOf(SUBJECT_TYPE_EMPLOYEE).equals(subjectType)) {
|
||||
PermissionUserScope userScope = resolvePermissionUserScope(userId, moduleId);
|
||||
if (Boolean.TRUE.equals(userScope.getAllDataPermission())) {
|
||||
return;
|
||||
}
|
||||
ServiceException.isTrue(CollUtil.isNotEmpty(userScope.getUserIds()), "暂无数据权限");
|
||||
ServiceException.isTrue(userScope.getUserIds().contains(StrUtil.trim(record.getReceiverUserId())), "暂无当前证照数据权限");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Integer.valueOf(SUBJECT_TYPE_ORGANIZATION).equals(subjectType) || Integer.valueOf(SUBJECT_TYPE_STORE).equals(subjectType)) {
|
||||
PermissionOrgScope orgScope = resolvePermissionOrgScope(userId, moduleId,UserProvider.getUser().getTenantId());
|
||||
if (Boolean.TRUE.equals(orgScope.getAllDataPermission())) {
|
||||
return;
|
||||
}
|
||||
String orgPermissionId = StrUtil.trim(record.getOrgPermissionId());
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(orgPermissionId), "组织数据不存在,无法提醒");
|
||||
ServiceException.isTrue(CollUtil.isNotEmpty(orgScope.getOrgIds()), "暂无数据权限");
|
||||
ServiceException.isTrue(orgScope.getOrgIds().contains(orgPermissionId), "暂无当前证照数据权限");
|
||||
return;
|
||||
}
|
||||
throw new ServiceException("主体类型不支持提醒");
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析员工维度权限范围。
|
||||
* allDataPermission=true 代表全量权限,false 时使用 userIds 过滤。
|
||||
*/
|
||||
private PermissionUserScope resolvePermissionUserScope(String userId, String moduleId) {
|
||||
List<String> permissionUserIds = permissionsUtils.obtainPersonnelUserIdDataPermissions(userId, moduleId);
|
||||
if (permissionUserIds == null) {
|
||||
return new PermissionUserScope(true, Collections.emptyList());
|
||||
}
|
||||
return new PermissionUserScope(false, normalizeIdList(permissionUserIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析组织维度权限范围。
|
||||
* allDataPermission=true 代表全量权限,false 时使用 orgIds 过滤。
|
||||
*/
|
||||
private PermissionOrgScope resolvePermissionOrgScope(String userId, String moduleId,String tenantId) {
|
||||
if (Boolean.TRUE.equals(UserProvider.getUser().getIsAdministrator())) {
|
||||
return new PermissionOrgScope(true, Collections.emptyList());
|
||||
}
|
||||
|
||||
PermissionsApplicableObject applicableObject = permissionsUtils.obtainTheScopeOfUserPermissionsEnums(userId, moduleId,tenantId);
|
||||
PermissionsApplicableEnums applicableEnums = applicableObject == null ? null : applicableObject.getPermissionsApplicableEnums();
|
||||
if (PermissionsApplicableEnums.ALL.equals(applicableEnums)) {
|
||||
return new PermissionOrgScope(true, Collections.emptyList());
|
||||
}
|
||||
|
||||
List<String> orgIds = normalizeIdList(applicableObject == null ? Collections.emptyList() : applicableObject.getOrgIds());
|
||||
if (CollUtil.isEmpty(orgIds)) {
|
||||
try {
|
||||
List<String> fallbackOrgIds = permissionsUtils.obtainPersonnelOrganizationIdDataPermissions(userId);
|
||||
if (fallbackOrgIds == null) {
|
||||
return new PermissionOrgScope(true, Collections.emptyList());
|
||||
}
|
||||
orgIds = normalizeIdList(fallbackOrgIds);
|
||||
} catch (Exception e) {
|
||||
return new PermissionOrgScope(false, Collections.emptyList());
|
||||
}
|
||||
}
|
||||
return new PermissionOrgScope(false, orgIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 规整ID集合:去空、去重、去首尾空格。
|
||||
*/
|
||||
private List<String> normalizeIdList(Collection<String> idList) {
|
||||
if (CollUtil.isEmpty(idList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return idList.stream()
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.map(StrUtil::trim)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否健康证类型。
|
||||
*/
|
||||
private boolean isHealthCertificate(String certificateType) {
|
||||
return StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.HEALTH_CERTIFICATE.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 证照类型转中文名称。
|
||||
*/
|
||||
private String resolveCertificateTypeName(String certificateType,String templateName) {
|
||||
if (StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.HEALTH_CERTIFICATE.getType())) {
|
||||
return "健康证";
|
||||
}
|
||||
if (StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.BUSINESS_LICENSE.getType())) {
|
||||
return "营业执照";
|
||||
}
|
||||
if (StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.HYGIENE_LICENSE.getType())) {
|
||||
return "食品经营许可证";
|
||||
}
|
||||
if (StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.STORE_CUSTOM_CERTIFICATE.getType())) {
|
||||
return templateName;
|
||||
}
|
||||
return "证照";
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算距离到期的剩余天数。
|
||||
*/
|
||||
private int calculateRemainDays(Date expireDate) {
|
||||
if (expireDate == null) {
|
||||
return 0;
|
||||
}
|
||||
Date today = DateUtil.beginOfDay(DateUtil.date());
|
||||
Date target = DateUtil.beginOfDay(expireDate);
|
||||
long days = DateUtil.betweenDay(today, target, false);
|
||||
return (int) Math.max(days, 0L);
|
||||
}
|
||||
|
||||
/**
|
||||
* 员工权限范围。
|
||||
*/
|
||||
private static class PermissionUserScope {
|
||||
private final Boolean allDataPermission;
|
||||
private final List<String> userIds;
|
||||
|
||||
private PermissionUserScope(Boolean allDataPermission, List<String> userIds) {
|
||||
this.allDataPermission = allDataPermission;
|
||||
this.userIds = userIds;
|
||||
}
|
||||
|
||||
public Boolean getAllDataPermission() {
|
||||
return allDataPermission;
|
||||
}
|
||||
|
||||
public List<String> getUserIds() {
|
||||
return userIds;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 组织权限范围。
|
||||
*/
|
||||
private static class PermissionOrgScope {
|
||||
private final Boolean allDataPermission;
|
||||
private final List<String> orgIds;
|
||||
|
||||
private PermissionOrgScope(Boolean allDataPermission, List<String> orgIds) {
|
||||
this.allDataPermission = allDataPermission;
|
||||
this.orgIds = orgIds;
|
||||
}
|
||||
|
||||
public Boolean getAllDataPermission() {
|
||||
return allDataPermission;
|
||||
}
|
||||
|
||||
public List<String> getOrgIds() {
|
||||
return orgIds;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提醒文案对象。
|
||||
*/
|
||||
private static class NoticeMessage {
|
||||
private final String title;
|
||||
private final String content;
|
||||
|
||||
private NoticeMessage(String title, String content) {
|
||||
this.title = title;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,514 @@
|
||||
package jnpf.certificate.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jnpf.authority.utils.PermissionsApplicableEnums;
|
||||
import jnpf.authority.utils.PermissionsApplicableObject;
|
||||
import jnpf.authority.utils.PermissionsUtils;
|
||||
import jnpf.certificate.helper.OrganizationHelper;
|
||||
import jnpf.certificate.mapper.CertificateAppRiskMapper;
|
||||
import jnpf.certificate.service.CertificateAppRiskService;
|
||||
import jnpf.model.certificate.req.app.CertificateAppEmployeeRiskQueryReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppRiskChartReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppStoreRiskQueryReq;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppEmployeeRiskVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppRiskChartVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppRiskReminderCountVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppStatusCountVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppStoreRiskItemVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppStoreRiskVO;
|
||||
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
|
||||
import jnpf.permission.eum.v2.FtbStoreTagEnum;
|
||||
import jnpf.permission.vo.v2.organzie.OrganizeBaseInfoVO;
|
||||
import jnpf.permission.vo.v2.organzie.OrganizeGeneralDetailVO;
|
||||
import jnpf.permission.vo.v2.position.PositionBaseInfoVO;
|
||||
import jnpf.permission.vo.v2.user.UserBaseRelationSimpleVO;
|
||||
import jnpf.permission.vo.v2.user.UserBoundVO;
|
||||
import jnpf.storecertificatephoto.helper.StoreCertificatePhotoHelper;
|
||||
import jnpf.util.StringUtil;
|
||||
import jnpf.util.UserProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* App 端证照风险服务实现。
|
||||
*/
|
||||
@Service
|
||||
public class CertificateAppRiskServiceImpl implements CertificateAppRiskService {
|
||||
|
||||
private static final int STATUS_MISSING = 1;
|
||||
private static final int STATUS_EXPIRED = 2;
|
||||
private static final int STATUS_NEAR_EXPIRE = 3;
|
||||
private static final int STATUS_NORMAL = 4;
|
||||
|
||||
/**
|
||||
* 证照风险查询 Mapper。
|
||||
*/
|
||||
@Autowired
|
||||
private CertificateAppRiskMapper certificateAppRiskMapper;
|
||||
|
||||
/**
|
||||
* 数据权限工具。
|
||||
*/
|
||||
@Autowired
|
||||
private PermissionsUtils permissionsUtils;
|
||||
@Autowired
|
||||
private OrganizationHelper organizationHelper;
|
||||
@Autowired
|
||||
private StoreCertificatePhotoHelper storeCertificatePhotoHelper;
|
||||
|
||||
|
||||
/**
|
||||
* 查询证照风险图表统计。
|
||||
* 健康证按用户数据权限统计,非健康证按组织数据权限统计。
|
||||
*/
|
||||
@Override
|
||||
public CertificateAppRiskChartVO queryChart(CertificateAppRiskChartReq req) {
|
||||
CertificateAppRiskChartReq queryReq = req == null ? new CertificateAppRiskChartReq() : req;
|
||||
queryReq.setOrgId(StrUtil.trim(queryReq.getOrgId()));
|
||||
queryReq.setCertificateType(StrUtil.blankToDefault(
|
||||
StrUtil.trim(queryReq.getCertificateType()),
|
||||
CertificateTypeEnum.HEALTH_CERTIFICATE.getType()
|
||||
));
|
||||
|
||||
String orgId = queryReq.getOrgId();
|
||||
boolean healthCertificateQuery = isHealthCertificate(queryReq.getCertificateType());
|
||||
buildQueryUserIds(queryReq,healthCertificateQuery);
|
||||
//如果查询组织id,但是没有查询到该组织的用户id列表,则返回空
|
||||
if(healthCertificateQuery && StringUtil.isNotBlank(orgId) && CollectionUtil.isEmpty(queryReq.getUserIds())){
|
||||
return buildChart(null);
|
||||
}
|
||||
List<CertificateAppStatusCountVO> statusCountList;
|
||||
if (healthCertificateQuery) {
|
||||
statusCountList = certificateAppRiskMapper.queryHealthRiskStatusCount(queryReq);
|
||||
} else {
|
||||
statusCountList = certificateAppRiskMapper.queryStoreRiskStatusCount(queryReq);
|
||||
}
|
||||
return buildChart(statusCountList);
|
||||
}
|
||||
|
||||
private void buildQueryUserIds(CertificateAppRiskChartReq queryReq,boolean healthCertificateQuery) {
|
||||
if(!healthCertificateQuery){
|
||||
return;
|
||||
}
|
||||
String queryReqOrgId = queryReq.getOrgId();
|
||||
if(StringUtil.isBlank(queryReqOrgId)){
|
||||
return;
|
||||
}
|
||||
List<String> userIdsByOrgId = organizationHelper.getUserIdsByOrgId(queryReqOrgId);
|
||||
queryReq.setUserIds(userIdsByOrgId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询员工证照风险数据。
|
||||
*/
|
||||
@Override
|
||||
public PageInfo<CertificateAppEmployeeRiskVO> queryEmployeePage(CertificateAppEmployeeRiskQueryReq req) {
|
||||
CertificateAppEmployeeRiskQueryReq queryReq = req == null ? new CertificateAppEmployeeRiskQueryReq() : req;
|
||||
queryReq.setOrgId(StrUtil.trim(queryReq.getOrgId()));
|
||||
long current = queryReq.getCurrentPage() == null || queryReq.getCurrentPage() <= 0 ? 1L : queryReq.getCurrentPage();
|
||||
long pageSize = queryReq.getPageSize() == null || queryReq.getPageSize() <= 0 ? 10L : queryReq.getPageSize();
|
||||
String orgId = queryReq.getOrgId();
|
||||
Collection<String> queryUserIds;
|
||||
Map<String, UserBaseRelationSimpleVO> relationMap;
|
||||
if (StringUtil.isNotBlank(orgId)) {
|
||||
relationMap = organizationHelper.getUserBaseRelationMapByOrgId(orgId);
|
||||
queryUserIds = relationMap.keySet();
|
||||
} else {
|
||||
relationMap = Collections.emptyMap();
|
||||
queryUserIds = null;
|
||||
}
|
||||
if (StringUtil.isNotBlank(orgId) && CollectionUtil.isEmpty(queryUserIds)) {
|
||||
return buildEmptyEmployeePage(current, pageSize);
|
||||
}
|
||||
|
||||
Page<CertificateAppEmployeeRiskVO> page = new Page<>(current, pageSize);
|
||||
Page<CertificateAppEmployeeRiskVO> queryPage = certificateAppRiskMapper.queryEmployeeRiskPageByUserIds(page, queryUserIds);
|
||||
List<CertificateAppEmployeeRiskVO> records = queryPage.getRecords() == null ? new ArrayList<>() : queryPage.getRecords();
|
||||
if (CollectionUtil.isEmpty(records)) {
|
||||
return buildEmptyEmployeePage(current, pageSize);
|
||||
}
|
||||
|
||||
Set<String> pageUserIds = records.stream()
|
||||
.map(CertificateAppEmployeeRiskVO::getUserId)
|
||||
.filter(StringUtil::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
if (CollectionUtil.isEmpty(pageUserIds)) {
|
||||
return buildEmptyEmployeePage(current, pageSize);
|
||||
}
|
||||
if (StringUtil.isBlank(orgId)) {
|
||||
relationMap = organizationHelper.getUserBaseRelationMapByUserIds(pageUserIds);
|
||||
}
|
||||
|
||||
for (CertificateAppEmployeeRiskVO item : records){
|
||||
UserBaseRelationSimpleVO relation = relationMap.get(item.getUserId());
|
||||
if(Objects.isNull(relation)){
|
||||
continue;
|
||||
}
|
||||
item.setWorkerName(StrUtil.blankToDefault(StrUtil.trim(relation.getUserName()), "-"));
|
||||
item.setPhone(StrUtil.blankToDefault(StrUtil.trim(relation.getMobilePhone()), "-"));
|
||||
item.setOrgId(relation.getOrganizeId());
|
||||
item.setPositionId(relation.getPositionId());
|
||||
item.setOrgName(relation.getOrganizeName());
|
||||
item.setPositionName(relation.getPositionName());
|
||||
item.setPhone(relation.getMobilePhone());
|
||||
}
|
||||
|
||||
PageInfo<CertificateAppEmployeeRiskVO> pageInfo = new PageInfo<>();
|
||||
pageInfo.setList(records);
|
||||
pageInfo.setPageNum((int) queryPage.getCurrent());
|
||||
pageInfo.setPageSize((int) queryPage.getSize());
|
||||
pageInfo.setTotal(queryPage.getTotal());
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询门店证照风险数据。
|
||||
*/
|
||||
@Override
|
||||
public PageInfo<CertificateAppStoreRiskVO> queryStorePage(CertificateAppStoreRiskQueryReq req) {
|
||||
CertificateAppStoreRiskQueryReq queryReq = req == null ? new CertificateAppStoreRiskQueryReq() : req;
|
||||
queryReq.setOrgId(StrUtil.trim(queryReq.getOrgId()));
|
||||
queryReq.setCertificateType(StrUtil.trim(queryReq.getCertificateType()));
|
||||
long current = queryReq.getCurrentPage() == null || queryReq.getCurrentPage() <= 0 ? 1L : queryReq.getCurrentPage();
|
||||
long pageSize = queryReq.getPageSize() == null || queryReq.getPageSize() <= 0 ? 10L : queryReq.getPageSize();
|
||||
|
||||
PageInfo<CertificateAppStoreRiskVO> emptyPage = buildEmptyStorePage(current, pageSize);
|
||||
|
||||
Page<CertificateAppStoreRiskVO> page = new Page<>(current, pageSize);
|
||||
Page<CertificateAppStoreRiskVO> queryPage = certificateAppRiskMapper.queryStoreRiskPage(page, queryReq);
|
||||
|
||||
List<CertificateAppStoreRiskVO> records = queryPage.getRecords() == null ? Collections.emptyList() : queryPage.getRecords();
|
||||
if (CollectionUtil.isEmpty(records)) {
|
||||
return emptyPage;
|
||||
}
|
||||
|
||||
Set<String> orgIds = new HashSet<>();
|
||||
records.forEach(vo -> {
|
||||
orgIds.add(vo.getSubjectId());
|
||||
});
|
||||
List<CertificateAppStoreRiskItemVO> detailList = certificateAppRiskMapper.queryStoreRiskDetailList(orgIds);
|
||||
|
||||
Set<String> templateIds = detailList.stream()
|
||||
.map(CertificateAppStoreRiskItemVO::getTemplateId)
|
||||
.filter(StringUtil::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
Map<String,String> templateIdAndNames = null;
|
||||
if(CollUtil.isNotEmpty(templateIds)){
|
||||
templateIdAndNames = storeCertificatePhotoHelper.buildStoreCertificateIdAndNames(templateIds,1);
|
||||
}else {
|
||||
templateIdAndNames = new HashMap<>();
|
||||
}
|
||||
Map<String, String> finalTemplateIdAndNames = templateIdAndNames;
|
||||
Map<String, List<CertificateAppStoreRiskItemVO>> detailMap = CollectionUtil.emptyIfNull(detailList).stream()
|
||||
.peek(item -> item.setCertificateTypeName(resolveCertificateTypeName(item.getCertificateType(),item.getTemplateId(), finalTemplateIdAndNames)))
|
||||
.filter(item -> StringUtil.isNotBlank(item.getCertificateTypeName()))//过滤掉被禁用的证照
|
||||
.collect(Collectors.groupingBy(CertificateAppStoreRiskItemVO::getSubjectId, LinkedHashMap::new, Collectors.toList()));
|
||||
for (CertificateAppStoreRiskVO record : records) {
|
||||
List<CertificateAppStoreRiskItemVO> certificateList = detailMap.getOrDefault(record.getSubjectId(), Collections.emptyList());
|
||||
record.setCertificateList(certificateList);
|
||||
}
|
||||
Map<String, OrganizeBaseInfoVO> organizeBaseInfoVOMap = organizationHelper.buildBaseOrganizeVO(orgIds,UserProvider.getUser().getTenantId());
|
||||
|
||||
fillStoreRiskItem(records,organizeBaseInfoVOMap);
|
||||
|
||||
PageInfo<CertificateAppStoreRiskVO> pageInfo = new PageInfo<>();
|
||||
pageInfo.setList(records);
|
||||
pageInfo.setPageNum((int) queryPage.getCurrent());
|
||||
pageInfo.setPageSize((int) queryPage.getSize());
|
||||
pageInfo.setTotal(queryPage.getTotal());
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询有风险的员工、组织、总数量
|
||||
*/
|
||||
@Override
|
||||
public CertificateAppRiskReminderCountVO queryRiskReminderCount(String orgId) {
|
||||
|
||||
List<String> orgIds = new ArrayList<>(1);
|
||||
Map<String,List<String>> userIdsByOrgId = null;
|
||||
if(StringUtil.isNotBlank(orgId)){
|
||||
userIdsByOrgId = organizationHelper.buildUserIdsByOrgIds(List.of(orgId),true,"");
|
||||
orgIds.add(orgId);
|
||||
}else{
|
||||
userIdsByOrgId = organizationHelper.buildUserIdsByOrgIds(null,true,"");
|
||||
}
|
||||
|
||||
Set<String> userIds = userIdsByOrgId.values()
|
||||
.stream()
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toSet());
|
||||
long employeeCount = 0L;
|
||||
if(!CollUtil.isEmpty(userIds)){
|
||||
employeeCount = certificateAppRiskMapper.queryEmployeeRiskTotalCount(userIds);
|
||||
}
|
||||
|
||||
Long organizationCount = certificateAppRiskMapper.queryOrganizationRiskTotalCount(orgIds);
|
||||
if(Objects.isNull(organizationCount)){
|
||||
organizationCount = 0L;
|
||||
}
|
||||
|
||||
CertificateAppRiskReminderCountVO vo = new CertificateAppRiskReminderCountVO();
|
||||
vo.setEmployeeCount(employeeCount);
|
||||
vo.setOrganizationCount(organizationCount);
|
||||
vo.setTotalCount(employeeCount + organizationCount);
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析员工数据权限范围。
|
||||
* 通过 allDataPermission 标识是否全量权限,userIds 为受限时可访问用户。
|
||||
*/
|
||||
private PermissionUserScope resolvePermissionUserScope(String userId, String moduleId) {
|
||||
List<String> permissionUserIds = permissionsUtils.obtainPersonnelUserIdDataPermissions(userId, moduleId);
|
||||
if (permissionUserIds == null) {
|
||||
return new PermissionUserScope(true, Collections.emptyList());
|
||||
}
|
||||
return new PermissionUserScope(false, normalizeIdList(permissionUserIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析组织数据权限范围。
|
||||
* 通过 allDataPermission 标识是否全量权限,orgIds 为受限时可访问组织。
|
||||
*/
|
||||
private PermissionOrgScope resolvePermissionOrgScope(String userId, String moduleId,String tenantId) {
|
||||
if (Boolean.TRUE.equals(UserProvider.getUser().getIsAdministrator())) {
|
||||
return new PermissionOrgScope(true, Collections.emptyList());
|
||||
}
|
||||
|
||||
PermissionsApplicableObject applicableObject = permissionsUtils.obtainTheScopeOfUserPermissionsEnums(userId, moduleId,tenantId);
|
||||
PermissionsApplicableEnums applicableEnums = applicableObject == null ? null : applicableObject.getPermissionsApplicableEnums();
|
||||
if (PermissionsApplicableEnums.ALL.equals(applicableEnums)) {
|
||||
return new PermissionOrgScope(true, Collections.emptyList());
|
||||
}
|
||||
|
||||
List<String> orgIds = normalizeIdList(applicableObject == null ? Collections.emptyList() : applicableObject.getOrgIds());
|
||||
if (CollUtil.isEmpty(orgIds)) {
|
||||
try {
|
||||
List<String> fallbackOrgIds = permissionsUtils.obtainPersonnelOrganizationIdDataPermissions(userId);
|
||||
if (fallbackOrgIds == null) {
|
||||
return new PermissionOrgScope(true, Collections.emptyList());
|
||||
}
|
||||
orgIds = normalizeIdList(fallbackOrgIds);
|
||||
} catch (Exception e) {
|
||||
return new PermissionOrgScope(false, Collections.emptyList());
|
||||
}
|
||||
}
|
||||
return new PermissionOrgScope(false, orgIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 规整 ID 列表:去空、去重、去前后空格。
|
||||
*/
|
||||
private List<String> normalizeIdList(List<String> idList) {
|
||||
if (CollUtil.isEmpty(idList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return idList.stream()
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.map(StrUtil::trim)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为健康证类型。
|
||||
*/
|
||||
private boolean isHealthCertificate(String certificateType) {
|
||||
return StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.HEALTH_CERTIFICATE.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建图表统计结果对象。
|
||||
*/
|
||||
private CertificateAppRiskChartVO buildChart(List<CertificateAppStatusCountVO> statusCountList) {
|
||||
Map<Integer, Integer> countMap = CollUtil.emptyIfNull(statusCountList)
|
||||
.stream()
|
||||
.filter(item -> item != null && item.getStatus() != null)
|
||||
.collect(Collectors.toMap(
|
||||
CertificateAppStatusCountVO::getStatus,
|
||||
item -> item.getCount() == null ? 0 : item.getCount(),
|
||||
Integer::sum
|
||||
));
|
||||
|
||||
int missingCount = countMap.getOrDefault(STATUS_MISSING, 0);
|
||||
int nearExpireCount = countMap.getOrDefault(STATUS_NEAR_EXPIRE, 0);
|
||||
int expiredCount = countMap.getOrDefault(STATUS_EXPIRED, 0);
|
||||
int normalCount = countMap.getOrDefault(STATUS_NORMAL, 0);
|
||||
int totalCount = missingCount + nearExpireCount + expiredCount + normalCount;
|
||||
|
||||
CertificateAppRiskChartVO chartVO = new CertificateAppRiskChartVO();
|
||||
chartVO.setMissingCount(missingCount);
|
||||
chartVO.setNearExpireCount(nearExpireCount);
|
||||
chartVO.setExpiredCount(expiredCount);
|
||||
chartVO.setNormalCount(normalCount);
|
||||
chartVO.setTotalCount(totalCount);
|
||||
|
||||
chartVO.setStatusList(Arrays.asList(
|
||||
buildStatusCount(STATUS_MISSING, missingCount),
|
||||
buildStatusCount(STATUS_NEAR_EXPIRE, nearExpireCount),
|
||||
buildStatusCount(STATUS_EXPIRED, expiredCount),
|
||||
buildStatusCount(STATUS_NORMAL, normalCount)
|
||||
));
|
||||
return chartVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建单个状态统计项。
|
||||
*/
|
||||
private CertificateAppStatusCountVO buildStatusCount(Integer status, Integer count) {
|
||||
CertificateAppStatusCountVO item = new CertificateAppStatusCountVO();
|
||||
item.setStatus(status);
|
||||
item.setStatusName(resolveStatusName(status));
|
||||
item.setCount(count == null ? 0 : count);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建空图表结果。
|
||||
*/
|
||||
private CertificateAppRiskChartVO buildEmptyChart() {
|
||||
return buildChart(Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建员工风险空分页。
|
||||
*/
|
||||
private PageInfo<CertificateAppEmployeeRiskVO> buildEmptyEmployeePage(long current, long pageSize) {
|
||||
PageInfo<CertificateAppEmployeeRiskVO> pageInfo = new PageInfo<>();
|
||||
pageInfo.setList(Collections.emptyList());
|
||||
pageInfo.setPageNum((int) current);
|
||||
pageInfo.setPageSize((int) pageSize);
|
||||
pageInfo.setTotal(0);
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建门店风险空分页。
|
||||
*/
|
||||
private PageInfo<CertificateAppStoreRiskVO> buildEmptyStorePage(long current, long pageSize) {
|
||||
PageInfo<CertificateAppStoreRiskVO> pageInfo = new PageInfo<>();
|
||||
pageInfo.setList(Collections.emptyList());
|
||||
pageInfo.setPageNum((int) current);
|
||||
pageInfo.setPageSize((int) pageSize);
|
||||
pageInfo.setTotal(0);
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充门店风险返回项的展示字段。
|
||||
*/
|
||||
private void fillStoreRiskItem(List<CertificateAppStoreRiskVO> records,Map<String, OrganizeBaseInfoVO> organizeBaseInfoVOMap) {
|
||||
if (CollectionUtil.isEmpty(records)) {
|
||||
return;
|
||||
}
|
||||
for (CertificateAppStoreRiskVO item : records){
|
||||
OrganizeBaseInfoVO organizeBaseInfoVO = organizeBaseInfoVOMap.get(item.getSubjectId());
|
||||
if(Objects.isNull(organizeBaseInfoVO)){
|
||||
continue;
|
||||
}
|
||||
item.setOrganizeId(organizeBaseInfoVO.getId());
|
||||
item.setOrganizeName(organizeBaseInfoVO.getName());
|
||||
String storeTag = organizeBaseInfoVO.getStoreTag();
|
||||
item.setStoreTag(storeTag);
|
||||
item.setOrganizeLeaderName(organizeBaseInfoVO.getLeaderName());
|
||||
item.setOrganizeLeaderId(organizeBaseInfoVO.getLeaderId());
|
||||
FtbStoreTagEnum storeTagEnum = FtbStoreTagEnum.fromName(storeTag);
|
||||
if(Objects.nonNull(storeTagEnum)){
|
||||
item.setStoreTagName(storeTagEnum.getLabel());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态编码转中文名称。
|
||||
*/
|
||||
private String resolveStatusName(Integer status) {
|
||||
if (Integer.valueOf(STATUS_MISSING).equals(status)) {
|
||||
return "缺失";
|
||||
}
|
||||
if (Integer.valueOf(STATUS_EXPIRED).equals(status)) {
|
||||
return "过期";
|
||||
}
|
||||
if (Integer.valueOf(STATUS_NEAR_EXPIRE).equals(status)) {
|
||||
return "临期";
|
||||
}
|
||||
if (Integer.valueOf(STATUS_NORMAL).equals(status)) {
|
||||
return "正常";
|
||||
}
|
||||
return "-";
|
||||
}
|
||||
|
||||
/**
|
||||
* 证照类型编码转中文名称。
|
||||
*/
|
||||
private String resolveCertificateTypeName(String certificateType,String templateId,Map<String,String> templateIdAndNames) {
|
||||
if (StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.HEALTH_CERTIFICATE.getType())) {
|
||||
return "健康证";
|
||||
}
|
||||
if (StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.BUSINESS_LICENSE.getType())) {
|
||||
return "营业执照";
|
||||
}
|
||||
if (StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.HYGIENE_LICENSE.getType())) {
|
||||
return "食品经营许可证";
|
||||
}
|
||||
if (StrUtil.isBlank(certificateType)) {
|
||||
return "证照";
|
||||
}
|
||||
String templateName = templateIdAndNames.get(templateId);
|
||||
if(StringUtil.isNotBlank(templateName)){
|
||||
return templateName;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户维度权限范围。
|
||||
*/
|
||||
private static class PermissionUserScope {
|
||||
private final Boolean allDataPermission;
|
||||
private final List<String> userIds;
|
||||
|
||||
private PermissionUserScope(Boolean allDataPermission, List<String> userIds) {
|
||||
this.allDataPermission = allDataPermission;
|
||||
this.userIds = userIds;
|
||||
}
|
||||
|
||||
public Boolean getAllDataPermission() {
|
||||
return allDataPermission;
|
||||
}
|
||||
|
||||
public List<String> getUserIds() {
|
||||
return userIds;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 组织维度权限范围。
|
||||
*/
|
||||
private static class PermissionOrgScope {
|
||||
private final Boolean allDataPermission;
|
||||
private final List<String> orgIds;
|
||||
|
||||
private PermissionOrgScope(Boolean allDataPermission, List<String> orgIds) {
|
||||
this.allDataPermission = allDataPermission;
|
||||
this.orgIds = orgIds;
|
||||
}
|
||||
|
||||
public Boolean getAllDataPermission() {
|
||||
return allDataPermission;
|
||||
}
|
||||
|
||||
public List<String> getOrgIds() {
|
||||
return orgIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,574 @@
|
||||
package jnpf.certificate.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
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 io.seata.spring.annotation.GlobalTransactional;
|
||||
import jnpf.certificate.mapper.CertificateBusinessLicenseExtMapper;
|
||||
import jnpf.certificate.mapper.CertificateHygieneLicenseExtMapper;
|
||||
import jnpf.certificate.mapper.CertificateInstanceItemMapper;
|
||||
import jnpf.certificate.mapper.CertificateInstanceMapper;
|
||||
import jnpf.certificate.service.CertificateManageApiService;
|
||||
import jnpf.model.certificate.po.CertificateBusinessLicenseExtEntity;
|
||||
import jnpf.model.certificate.po.CertificateHygieneLicenseExtEntity;
|
||||
import jnpf.model.certificate.po.CertificateInstanceEntity;
|
||||
import jnpf.model.certificate.po.CertificateInstanceItemEntity;
|
||||
import jnpf.model.certificate.vo.CertificateOrganizeBusinessLicenseVO;
|
||||
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
|
||||
import jnpf.util.FtbUtil;
|
||||
import jnpf.util.ServiceException;
|
||||
import jnpf.util.StringUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 组织营业执照开放接口服务实现。
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class CertificateManageApiServiceImpl implements CertificateManageApiService {
|
||||
|
||||
private static final int STATUS_MISSING = 1;
|
||||
private static final int STATUS_EXPIRED = 2;
|
||||
private static final int STATUS_NEAR_EXPIRE = 3;
|
||||
private static final int STATUS_NORMAL = 4;
|
||||
private static final int SUBJECT_TYPE_ORGANIZE = 2;
|
||||
private static final int SUBJECT_TYPE_STORE = 3;
|
||||
private static final int IS_LONG_TERM_NO = 0;
|
||||
private static final int NEAR_EXPIRE_DAYS = 30;
|
||||
|
||||
@Autowired
|
||||
private CertificateInstanceMapper certificateInstanceMapper;
|
||||
@Autowired
|
||||
private CertificateBusinessLicenseExtMapper certificateBusinessLicenseExtMapper;
|
||||
@Autowired
|
||||
private CertificateHygieneLicenseExtMapper certificateHygieneLicenseExtMapper;
|
||||
@Autowired
|
||||
private CertificateInstanceItemMapper certificateInstanceItemMapper;
|
||||
|
||||
/**
|
||||
* 根据组织ID查询营业执照信息。
|
||||
*/
|
||||
@Override
|
||||
public CertificateOrganizeBusinessLicenseVO queryBusinessLicense(String organizeId) {
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(organizeId), "组织ID不能为空");
|
||||
return buildOrganizeBusinessLicenseVO(StrUtil.trim(organizeId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据组织ID列表批量查询营业执照信息。
|
||||
*/
|
||||
@Override
|
||||
public List<CertificateOrganizeBusinessLicenseVO> queryBusinessLicenseBatch(Collection<String> organizeIds) {
|
||||
if (CollUtil.isEmpty(organizeIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<String> targetIds = organizeIds.stream()
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.map(StrUtil::trim)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isEmpty(targetIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Map<String, CertificateInstanceEntity> instanceMap = queryBusinessInstanceMap(targetIds);
|
||||
Map<String, CertificateBusinessLicenseExtEntity> extMap = queryBusinessExtMap(instanceMap.values());
|
||||
|
||||
List<CertificateOrganizeBusinessLicenseVO> result = new ArrayList<>(targetIds.size());
|
||||
for (String organizeId : targetIds) {
|
||||
CertificateInstanceEntity instance = instanceMap.get(organizeId);
|
||||
CertificateBusinessLicenseExtEntity ext = instance == null ? null : extMap.get(instance.getId());
|
||||
result.add(convertToVO(organizeId, instance, ext));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存组织营业执照信息。
|
||||
*/
|
||||
@Override
|
||||
@GlobalTransactional
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveBusinessLicense(CertificateOrganizeBusinessLicenseVO req) {
|
||||
ServiceException.notNull(req, "请求参数不能为空");
|
||||
String organizeId = StrUtil.trim(req.getOrganizeId());
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(organizeId), "组织ID不能为空");
|
||||
|
||||
Date establishDate = parseDate(req.getEstablishDate(), "成立时间");
|
||||
Date issueDate = parseDate(req.getIssueDate(), "发证日期");
|
||||
Date expireDate = parseDate(req.getExpireDate(), "到期日期");
|
||||
Integer isLongTerm = req.getIsLongTerm() == null ? 0 : req.getIsLongTerm();
|
||||
if (Integer.valueOf(1).equals(isLongTerm)) {
|
||||
expireDate = null;
|
||||
}
|
||||
|
||||
String certificateType = CertificateTypeEnum.BUSINESS_LICENSE.getType();
|
||||
String certificateImage = trimToNull(req.getCertificateImage());
|
||||
int status = calculateStatus(isLongTerm, expireDate);
|
||||
|
||||
String instanceId = upsertBusinessInstance(
|
||||
organizeId,
|
||||
certificateType,
|
||||
certificateImage,
|
||||
issueDate,
|
||||
expireDate,
|
||||
isLongTerm,
|
||||
status
|
||||
);
|
||||
if(Objects.isNull(instanceId)){
|
||||
return;
|
||||
}
|
||||
upsertBusinessExt(instanceId, req, establishDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化门店默认缺失证照(营业执照、食品经营许可证)。
|
||||
*/
|
||||
@Override
|
||||
@GlobalTransactional
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void initStoreDefaultCertificates(String storeId) {
|
||||
String targetStoreId = StrUtil.trim(storeId);
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(targetStoreId), "门店ID不能为空");
|
||||
|
||||
List<String> defaultTypes = Arrays.asList(
|
||||
CertificateTypeEnum.BUSINESS_LICENSE.getType(),
|
||||
CertificateTypeEnum.HYGIENE_LICENSE.getType()
|
||||
);
|
||||
for (String certificateType : defaultTypes) {
|
||||
initStoreDefaultCertificate(targetStoreId, certificateType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据组织ID删除该主体下全部证照信息。
|
||||
*/
|
||||
@Override
|
||||
@GlobalTransactional
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteBusinessLicense(String organizeId, String loginUserId) {
|
||||
String targetOrganizeId = StrUtil.trim(organizeId);
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(targetOrganizeId), "组织ID不能为空");
|
||||
|
||||
Date now = new Date();
|
||||
LambdaUpdateWrapper<CertificateInstanceEntity> instanceUpdateWrapper = Wrappers.lambdaUpdate();
|
||||
instanceUpdateWrapper.eq(CertificateInstanceEntity::getEnabledMark, 0);
|
||||
instanceUpdateWrapper.eq(CertificateInstanceEntity::getSubjectId, targetOrganizeId);
|
||||
instanceUpdateWrapper.set(CertificateInstanceEntity::getEnabledMark, 1);
|
||||
instanceUpdateWrapper.set(CertificateInstanceEntity::getLastModifyTime, now);
|
||||
if(StringUtil.isNotBlank(loginUserId)){
|
||||
instanceUpdateWrapper.set(CertificateInstanceEntity::getLastModifyUserId, loginUserId);
|
||||
}
|
||||
certificateInstanceMapper.update(null, instanceUpdateWrapper);
|
||||
|
||||
LambdaQueryWrapper<CertificateInstanceEntity> instanceQueryWrapper = Wrappers.lambdaQuery();
|
||||
instanceQueryWrapper.eq(CertificateInstanceEntity::getSubjectType, SUBJECT_TYPE_ORGANIZE);
|
||||
instanceQueryWrapper.eq(CertificateInstanceEntity::getSubjectId, targetOrganizeId);
|
||||
List<CertificateInstanceEntity> allBusinessInstances = certificateInstanceMapper.selectList(instanceQueryWrapper);
|
||||
if (CollUtil.isEmpty(allBusinessInstances)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> instanceIds = allBusinessInstances.stream()
|
||||
.map(CertificateInstanceEntity::getId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.map(StrUtil::trim)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isEmpty(instanceIds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LambdaUpdateWrapper<CertificateBusinessLicenseExtEntity> extUpdateWrapper = Wrappers.lambdaUpdate();
|
||||
extUpdateWrapper.eq(CertificateBusinessLicenseExtEntity::getEnabledMark, 0);
|
||||
extUpdateWrapper.in(CertificateBusinessLicenseExtEntity::getInstanceId, instanceIds);
|
||||
extUpdateWrapper.set(CertificateBusinessLicenseExtEntity::getEnabledMark, 1);
|
||||
extUpdateWrapper.set(CertificateBusinessLicenseExtEntity::getLastModifyTime, now);
|
||||
extUpdateWrapper.set(CertificateBusinessLicenseExtEntity::getLastModifyUserId, loginUserId);
|
||||
certificateBusinessLicenseExtMapper.update(null, extUpdateWrapper);
|
||||
|
||||
LambdaUpdateWrapper<CertificateHygieneLicenseExtEntity> hygieneExtUpdateWrapper = Wrappers.lambdaUpdate();
|
||||
hygieneExtUpdateWrapper.eq(CertificateHygieneLicenseExtEntity::getEnabledMark, 0);
|
||||
hygieneExtUpdateWrapper.in(CertificateHygieneLicenseExtEntity::getInstanceId, instanceIds);
|
||||
hygieneExtUpdateWrapper.set(CertificateHygieneLicenseExtEntity::getEnabledMark, 1);
|
||||
hygieneExtUpdateWrapper.set(CertificateHygieneLicenseExtEntity::getLastModifyTime, now);
|
||||
hygieneExtUpdateWrapper.set(CertificateHygieneLicenseExtEntity::getLastModifyUserId, loginUserId);
|
||||
certificateHygieneLicenseExtMapper.update(null, hygieneExtUpdateWrapper);
|
||||
|
||||
LambdaUpdateWrapper<CertificateInstanceItemEntity> itemUpdateWrapper = Wrappers.lambdaUpdate();
|
||||
itemUpdateWrapper.eq(CertificateInstanceItemEntity::getEnabledMark, 0);
|
||||
itemUpdateWrapper.in(CertificateInstanceItemEntity::getInstanceId, instanceIds);
|
||||
itemUpdateWrapper.set(CertificateInstanceItemEntity::getEnabledMark, 1);
|
||||
itemUpdateWrapper.set(CertificateInstanceItemEntity::getLastModifyTime, now);
|
||||
itemUpdateWrapper.set(CertificateInstanceItemEntity::getLastModifyUserId, loginUserId);
|
||||
certificateInstanceItemMapper.update(null, itemUpdateWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询并组装组织营业执照返回对象。
|
||||
*/
|
||||
private CertificateOrganizeBusinessLicenseVO buildOrganizeBusinessLicenseVO(String organizeId) {
|
||||
CertificateInstanceEntity instance = queryLatestBusinessInstance(organizeId);
|
||||
CertificateBusinessLicenseExtEntity ext = instance == null ? null : queryLatestBusinessExt(instance.getId());
|
||||
return convertToVO(organizeId, instance, ext);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询营业执照主表数据映射。
|
||||
*/
|
||||
private Map<String, CertificateInstanceEntity> queryBusinessInstanceMap(List<String> organizeIds) {
|
||||
LambdaQueryWrapper<CertificateInstanceEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(CertificateInstanceEntity::getEnabledMark, 0);
|
||||
wrapper.eq(CertificateInstanceEntity::getSubjectType, SUBJECT_TYPE_ORGANIZE);
|
||||
wrapper.eq(CertificateInstanceEntity::getCertificateType, CertificateTypeEnum.BUSINESS_LICENSE.getType());
|
||||
wrapper.in(CertificateInstanceEntity::getSubjectId, organizeIds);
|
||||
wrapper.orderByDesc(CertificateInstanceEntity::getLastModifyTime);
|
||||
wrapper.orderByDesc(CertificateInstanceEntity::getCreatorTime);
|
||||
List<CertificateInstanceEntity> instanceList = certificateInstanceMapper.selectList(wrapper);
|
||||
if (CollUtil.isEmpty(instanceList)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, CertificateInstanceEntity> result = new LinkedHashMap<>();
|
||||
for (CertificateInstanceEntity entity : instanceList) {
|
||||
if (entity == null || StrUtil.isBlank(entity.getSubjectId())) {
|
||||
continue;
|
||||
}
|
||||
String subjectId = StrUtil.trim(entity.getSubjectId());
|
||||
result.putIfAbsent(subjectId, entity);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询营业执照扩展表数据映射。
|
||||
*/
|
||||
private Map<String, CertificateBusinessLicenseExtEntity> queryBusinessExtMap(Iterable<CertificateInstanceEntity> instances) {
|
||||
List<String> instanceIds = new ArrayList<>();
|
||||
for (CertificateInstanceEntity entity : instances) {
|
||||
if (entity != null && StrUtil.isNotBlank(entity.getId())) {
|
||||
instanceIds.add(StrUtil.trim(entity.getId()));
|
||||
}
|
||||
}
|
||||
if (CollUtil.isEmpty(instanceIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
LambdaQueryWrapper<CertificateBusinessLicenseExtEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(CertificateBusinessLicenseExtEntity::getEnabledMark, 0);
|
||||
wrapper.in(CertificateBusinessLicenseExtEntity::getInstanceId, instanceIds);
|
||||
wrapper.orderByDesc(CertificateBusinessLicenseExtEntity::getLastModifyTime);
|
||||
wrapper.orderByDesc(CertificateBusinessLicenseExtEntity::getCreatorTime);
|
||||
List<CertificateBusinessLicenseExtEntity> extList = certificateBusinessLicenseExtMapper.selectList(wrapper);
|
||||
if (CollUtil.isEmpty(extList)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, CertificateBusinessLicenseExtEntity> result = new LinkedHashMap<>();
|
||||
for (CertificateBusinessLicenseExtEntity ext : extList) {
|
||||
if (ext == null || StrUtil.isBlank(ext.getInstanceId())) {
|
||||
continue;
|
||||
}
|
||||
result.putIfAbsent(StrUtil.trim(ext.getInstanceId()), ext);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询组织最新营业执照主表记录。
|
||||
*/
|
||||
private CertificateInstanceEntity queryLatestBusinessInstance(String organizeId) {
|
||||
LambdaQueryWrapper<CertificateInstanceEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(CertificateInstanceEntity::getEnabledMark, 0);
|
||||
wrapper.eq(CertificateInstanceEntity::getSubjectType, SUBJECT_TYPE_ORGANIZE);
|
||||
wrapper.eq(CertificateInstanceEntity::getSubjectId, organizeId);
|
||||
wrapper.eq(CertificateInstanceEntity::getCertificateType, CertificateTypeEnum.BUSINESS_LICENSE.getType());
|
||||
wrapper.orderByDesc(CertificateInstanceEntity::getLastModifyTime);
|
||||
wrapper.orderByDesc(CertificateInstanceEntity::getCreatorTime);
|
||||
List<CertificateInstanceEntity> list = certificateInstanceMapper.selectList(wrapper);
|
||||
return CollUtil.isEmpty(list) ? null : list.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询实例最新营业执照扩展记录。
|
||||
*/
|
||||
private CertificateBusinessLicenseExtEntity queryLatestBusinessExt(String instanceId) {
|
||||
LambdaQueryWrapper<CertificateBusinessLicenseExtEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(CertificateBusinessLicenseExtEntity::getEnabledMark, 0);
|
||||
wrapper.eq(CertificateBusinessLicenseExtEntity::getInstanceId, instanceId);
|
||||
wrapper.orderByDesc(CertificateBusinessLicenseExtEntity::getLastModifyTime);
|
||||
wrapper.orderByDesc(CertificateBusinessLicenseExtEntity::getCreatorTime);
|
||||
List<CertificateBusinessLicenseExtEntity> list = certificateBusinessLicenseExtMapper.selectList(wrapper);
|
||||
return CollUtil.isEmpty(list) ? null : list.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存或更新营业执照主表信息。
|
||||
*/
|
||||
private String upsertBusinessInstance(String organizeId,
|
||||
String certificateType,
|
||||
String certificateImage,
|
||||
Date issueDate,
|
||||
Date expireDate,
|
||||
Integer isLongTerm,
|
||||
Integer status) {
|
||||
LambdaUpdateWrapper<CertificateInstanceEntity> updateWrapper = buildBusinessInstanceUpdateWrapper(
|
||||
organizeId, certificateType, certificateImage, issueDate, expireDate, isLongTerm, status
|
||||
);
|
||||
int updateRows = certificateInstanceMapper.update(null, updateWrapper);
|
||||
if (updateRows > 0) {
|
||||
CertificateInstanceEntity latest = queryLatestBusinessInstance(organizeId);
|
||||
ServiceException.notNull(latest, "营业执照实例更新成功但未查询到数据");
|
||||
return latest.getId();
|
||||
}
|
||||
|
||||
CertificateInstanceEntity insertEntity = new CertificateInstanceEntity();
|
||||
insertEntity.setId(FtbUtil.getId());
|
||||
insertEntity.setCertificateType(certificateType);
|
||||
insertEntity.setSubjectType(SUBJECT_TYPE_ORGANIZE);
|
||||
insertEntity.setSubjectId(organizeId);
|
||||
insertEntity.setCertificateImage(certificateImage);
|
||||
insertEntity.setIssueDate(issueDate);
|
||||
insertEntity.setExpireDate(expireDate);
|
||||
if(Objects.nonNull(expireDate)){
|
||||
insertEntity.setExpireTimestamp(expireDate.getTime());
|
||||
}
|
||||
insertEntity.setIsLongTerm(isLongTerm);
|
||||
insertEntity.setStatus(status);
|
||||
insertEntity.setEnabledMark(0);
|
||||
try {
|
||||
certificateInstanceMapper.insert(insertEntity);
|
||||
return insertEntity.getId();
|
||||
} catch (DuplicateKeyException e) {
|
||||
log.warn("营业执照实例插入出现重复键,执行重试更新。organizeId={}, certificateType={}", organizeId, certificateType, e);
|
||||
LambdaUpdateWrapper<CertificateInstanceEntity> retryWrapper = buildBusinessInstanceUpdateWrapper(
|
||||
organizeId, certificateType, certificateImage, issueDate, expireDate, isLongTerm, status
|
||||
);
|
||||
int retryRows = certificateInstanceMapper.update(null, retryWrapper);
|
||||
if(retryRows <= 0){
|
||||
log.error("upsertBusinessInstance fail.insertEntity:{}",insertEntity);
|
||||
return null;
|
||||
}
|
||||
CertificateInstanceEntity latest = queryLatestBusinessInstance(organizeId);
|
||||
ServiceException.notNull(latest, "营业执照实例重试更新成功但未查询到数据");
|
||||
return latest.getId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化单个门店默认证照记录。
|
||||
*/
|
||||
private void initStoreDefaultCertificate(String storeId, String certificateType) {
|
||||
LambdaQueryWrapper<CertificateInstanceEntity> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(CertificateInstanceEntity::getEnabledMark, 0);
|
||||
queryWrapper.eq(CertificateInstanceEntity::getSubjectType, SUBJECT_TYPE_STORE);
|
||||
queryWrapper.eq(CertificateInstanceEntity::getSubjectId, storeId);
|
||||
queryWrapper.eq(CertificateInstanceEntity::getCertificateType, certificateType);
|
||||
queryWrapper.last("limit 1");
|
||||
CertificateInstanceEntity existed = certificateInstanceMapper.selectOne(queryWrapper);
|
||||
if (existed != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
CertificateInstanceEntity insertEntity = new CertificateInstanceEntity();
|
||||
insertEntity.setId(FtbUtil.getId());
|
||||
insertEntity.setCertificateType(certificateType);
|
||||
insertEntity.setSubjectType(SUBJECT_TYPE_STORE);
|
||||
insertEntity.setSubjectId(storeId);
|
||||
insertEntity.setIsLongTerm(IS_LONG_TERM_NO);
|
||||
insertEntity.setStatus(STATUS_MISSING);
|
||||
insertEntity.setEnabledMark(0);
|
||||
try {
|
||||
certificateInstanceMapper.insert(insertEntity);
|
||||
} catch (DuplicateKeyException e) {
|
||||
log.warn("初始化门店默认证照出现重复键,忽略。storeId={}, certificateType={}", storeId, certificateType, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存或更新营业执照扩展表信息。
|
||||
*/
|
||||
private void upsertBusinessExt(String instanceId, CertificateOrganizeBusinessLicenseVO req, Date establishDate) {
|
||||
String companyName = trimToNull(req.getCompanyName());
|
||||
String companyAddress = trimToNull(req.getCompanyAddress());
|
||||
String legalRepresentative = trimToNull(req.getLegalRepresentative());
|
||||
|
||||
LambdaUpdateWrapper<CertificateBusinessLicenseExtEntity> updateWrapper = buildBusinessExtUpdateWrapper(
|
||||
instanceId, companyName, companyAddress, legalRepresentative, establishDate
|
||||
);
|
||||
int updateRows = certificateBusinessLicenseExtMapper.update(null, updateWrapper);
|
||||
if (updateRows > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
CertificateBusinessLicenseExtEntity insertEntity = new CertificateBusinessLicenseExtEntity();
|
||||
insertEntity.setId(FtbUtil.getId());
|
||||
insertEntity.setInstanceId(instanceId);
|
||||
insertEntity.setCompanyName(companyName);
|
||||
insertEntity.setCompanyAddress(companyAddress);
|
||||
insertEntity.setLegalRepresentative(legalRepresentative);
|
||||
insertEntity.setEstablishDate(establishDate);
|
||||
insertEntity.setEnabledMark(0);
|
||||
try {
|
||||
certificateBusinessLicenseExtMapper.insert(insertEntity);
|
||||
} catch (DuplicateKeyException e) {
|
||||
log.warn("营业执照扩展插入出现重复键,执行重试更新。instanceId={}", instanceId, e);
|
||||
LambdaUpdateWrapper<CertificateBusinessLicenseExtEntity> retryWrapper = buildBusinessExtUpdateWrapper(
|
||||
instanceId, companyName, companyAddress, legalRepresentative, establishDate
|
||||
);
|
||||
int retryRows = certificateBusinessLicenseExtMapper.update(null, retryWrapper);
|
||||
ServiceException.isTrue(retryRows > 0, "营业执照扩展保存失败,请稍后重试");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装营业执照返回对象。
|
||||
*/
|
||||
private CertificateOrganizeBusinessLicenseVO convertToVO(String organizeId,
|
||||
CertificateInstanceEntity instance,
|
||||
CertificateBusinessLicenseExtEntity ext) {
|
||||
CertificateOrganizeBusinessLicenseVO vo = new CertificateOrganizeBusinessLicenseVO();
|
||||
vo.setOrganizeId(organizeId);
|
||||
vo.setIsLongTerm(instance == null || instance.getIsLongTerm() == null ? 0 : instance.getIsLongTerm());
|
||||
if (instance != null) {
|
||||
vo.setCertificateImage(instance.getCertificateImage());
|
||||
vo.setIssueDate(formatDate(instance.getIssueDate()));
|
||||
vo.setExpireDate(formatDate(instance.getExpireDate()));
|
||||
vo.setBusinessTerm(buildBusinessTerm(instance.getIssueDate(), instance.getExpireDate(), vo.getIsLongTerm()));
|
||||
} else {
|
||||
vo.setBusinessTerm("[]");
|
||||
}
|
||||
if (ext != null) {
|
||||
vo.setCompanyName(ext.getCompanyName());
|
||||
vo.setLegalRepresentative(ext.getLegalRepresentative());
|
||||
vo.setCompanyAddress(ext.getCompanyAddress());
|
||||
vo.setEstablishDate(formatDate(ext.getEstablishDate()));
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算证照状态。
|
||||
*/
|
||||
private Integer calculateStatus(Integer isLongTerm, Date expireDate) {
|
||||
if (Integer.valueOf(1).equals(isLongTerm)) {
|
||||
return STATUS_NORMAL;
|
||||
}
|
||||
if (expireDate == null) {
|
||||
return STATUS_MISSING;
|
||||
}
|
||||
Date today = DateUtil.beginOfDay(DateUtil.date());
|
||||
Date target = DateUtil.beginOfDay(expireDate);
|
||||
if (target.before(today)) {
|
||||
return STATUS_EXPIRED;
|
||||
}
|
||||
long daysDiff = DateUtil.betweenDay(today, target, false);
|
||||
if (daysDiff <= NEAR_EXPIRE_DAYS) {
|
||||
return STATUS_NEAR_EXPIRE;
|
||||
}
|
||||
return STATUS_NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析日期字符串。
|
||||
*/
|
||||
private Date parseDate(String dateText, String fieldName) {
|
||||
if (StrUtil.isBlank(dateText)) {
|
||||
return null;
|
||||
}
|
||||
int strLen = dateText.length();
|
||||
if(StringUtil.isNumeric(dateText) && (strLen == 10 || strLen == 13)){
|
||||
long date = Long.parseLong(dateText);
|
||||
if(dateText.length() == 10){
|
||||
date = date * 1000;
|
||||
}
|
||||
return new Date(date);
|
||||
}
|
||||
try {
|
||||
return DateUtil.parseDate(StrUtil.trim(dateText));
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException(fieldName + "格式不正确,正确格式为yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期。
|
||||
*/
|
||||
private String formatDate(Date date) {
|
||||
return date == null ? null : DateUtil.formatDate(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装营业期限展示文案。
|
||||
*/
|
||||
private String buildBusinessTerm(Date issueDate, Date expireDate, Integer isLongTerm) {
|
||||
if (Integer.valueOf(1).equals(isLongTerm)) {
|
||||
return "[]";
|
||||
}
|
||||
if (expireDate == null) {
|
||||
return "[]";
|
||||
}
|
||||
String issueText = issueDate == null ? "" : DateUtil.formatDate(issueDate);
|
||||
return "[\""+issueText + "\",\"" + DateUtil.formatDate(expireDate)+"\"]";
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建营业执照主表更新条件。
|
||||
*/
|
||||
private LambdaUpdateWrapper<CertificateInstanceEntity> buildBusinessInstanceUpdateWrapper(String organizeId,
|
||||
String certificateType,
|
||||
String certificateImage,
|
||||
Date issueDate,
|
||||
Date expireDate,
|
||||
Integer isLongTerm,
|
||||
Integer status) {
|
||||
LambdaUpdateWrapper<CertificateInstanceEntity> updateWrapper = Wrappers.lambdaUpdate();
|
||||
updateWrapper.eq(CertificateInstanceEntity::getSubjectId, organizeId);
|
||||
updateWrapper.eq(CertificateInstanceEntity::getCertificateType, certificateType);
|
||||
updateWrapper.set(CertificateInstanceEntity::getSubjectType, SUBJECT_TYPE_ORGANIZE);
|
||||
updateWrapper.set(CertificateInstanceEntity::getEnabledMark, 0);
|
||||
updateWrapper.set(CertificateInstanceEntity::getCertificateImage, certificateImage);
|
||||
updateWrapper.set(CertificateInstanceEntity::getIssueDate, issueDate);
|
||||
updateWrapper.set(CertificateInstanceEntity::getExpireDate, expireDate);
|
||||
if(Objects.nonNull(expireDate)){
|
||||
updateWrapper.set(CertificateInstanceEntity::getExpireTimestamp, expireDate.getTime());
|
||||
}
|
||||
updateWrapper.set(CertificateInstanceEntity::getIsLongTerm, isLongTerm);
|
||||
updateWrapper.set(CertificateInstanceEntity::getStatus, status);
|
||||
return updateWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建营业执照扩展表更新条件。
|
||||
*/
|
||||
private LambdaUpdateWrapper<CertificateBusinessLicenseExtEntity> buildBusinessExtUpdateWrapper(String instanceId,
|
||||
String companyName,
|
||||
String companyAddress,
|
||||
String legalRepresentative,
|
||||
Date establishDate) {
|
||||
LambdaUpdateWrapper<CertificateBusinessLicenseExtEntity> updateWrapper = Wrappers.lambdaUpdate();
|
||||
updateWrapper.eq(CertificateBusinessLicenseExtEntity::getEnabledMark, 0);
|
||||
updateWrapper.eq(CertificateBusinessLicenseExtEntity::getInstanceId, instanceId);
|
||||
updateWrapper.set(CertificateBusinessLicenseExtEntity::getCompanyName, companyName);
|
||||
updateWrapper.set(CertificateBusinessLicenseExtEntity::getCompanyAddress, companyAddress);
|
||||
updateWrapper.set(CertificateBusinessLicenseExtEntity::getLegalRepresentative, legalRepresentative);
|
||||
updateWrapper.set(CertificateBusinessLicenseExtEntity::getEstablishDate, establishDate);
|
||||
return updateWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 去首尾空格,空串返回 null。
|
||||
*/
|
||||
private String trimToNull(String text) {
|
||||
String value = StrUtil.trim(text);
|
||||
return StrUtil.isBlank(value) ? null : value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,481 @@
|
||||
package jnpf.certificate.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
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.Assert;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import jnpf.certificate.mapper.CertificateBusinessLicenseExtMapper;
|
||||
import jnpf.certificate.mapper.CertificateHygieneLicenseExtMapper;
|
||||
import jnpf.certificate.mapper.CertificateInstanceItemMapper;
|
||||
import jnpf.certificate.mapper.CertificateInstanceMapper;
|
||||
import jnpf.certificate.service.CertificateManageService;
|
||||
import jnpf.model.certificate.po.CertificateBusinessLicenseExtEntity;
|
||||
import jnpf.model.certificate.po.CertificateHygieneLicenseExtEntity;
|
||||
import jnpf.model.certificate.po.CertificateInstanceEntity;
|
||||
import jnpf.model.certificate.po.CertificateInstanceItemEntity;
|
||||
import jnpf.model.certificate.req.CertificateInstanceItemReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppBusinessLicenseUpdateReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppHealthCertificateUpdateReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppHygieneLicenseUpdateReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppStoreCustomUpdateReq;
|
||||
import jnpf.model.certificate.vo.CertificateInstanceItemVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppBusinessLicenseDetailVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppCertificateDetailVO;
|
||||
import jnpf.model.certificate.vo.app.HealthCertificateDetailVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppHygieneLicenseDetailVO;
|
||||
import jnpf.model.certificate.vo.app.CertificateAppStoreCustomDetailVO;
|
||||
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
|
||||
import jnpf.util.FtbUtil;
|
||||
import jnpf.util.ServiceException;
|
||||
import jnpf.util.UserProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* App端证照管理服务实现。
|
||||
*/
|
||||
@Service
|
||||
public class CertificateManageServiceImpl implements CertificateManageService {
|
||||
|
||||
private static final int STATUS_MISSING = 1;
|
||||
private static final int STATUS_EXPIRED = 2;
|
||||
private static final int STATUS_NEAR_EXPIRE = 3;
|
||||
private static final int STATUS_NORMAL = 4;
|
||||
private static final int NEAR_EXPIRE_DAYS = 30;
|
||||
|
||||
@Autowired
|
||||
private CertificateInstanceMapper certificateInstanceMapper;
|
||||
@Autowired
|
||||
private CertificateBusinessLicenseExtMapper certificateBusinessLicenseExtMapper;
|
||||
@Autowired
|
||||
private CertificateHygieneLicenseExtMapper certificateHygieneLicenseExtMapper;
|
||||
@Autowired
|
||||
private CertificateInstanceItemMapper certificateInstanceItemMapper;
|
||||
|
||||
/**
|
||||
* 根据证照实例ID查询详情,按证照类型返回不同明细对象。
|
||||
*/
|
||||
@Override
|
||||
public CertificateAppCertificateDetailVO queryInfo(String certificateInstanceId) {
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(certificateInstanceId), "证照实例ID不能为空");
|
||||
CertificateInstanceEntity entity = queryActiveEntity(StrUtil.trim(certificateInstanceId));
|
||||
Optional<CertificateTypeEnum> certificateTypeEnumOptional = CertificateTypeEnum.getByType(entity.getCertificateType());
|
||||
ServiceException.isTrue(certificateTypeEnumOptional.isPresent(), "不支持的证照类型");
|
||||
CertificateTypeEnum certificateTypeEnum = certificateTypeEnumOptional.get();
|
||||
|
||||
Integer status = calculateStatus(entity.getIsLongTerm(), entity.getExpireDate());
|
||||
CertificateAppCertificateDetailVO result = new CertificateAppCertificateDetailVO();
|
||||
result.setCertificateInstanceId(entity.getId());
|
||||
result.setCertificateType(certificateTypeEnum.getType());
|
||||
result.setStatus(status);
|
||||
result.setStatusName(resolveStatusName(status));
|
||||
|
||||
if (CertificateTypeEnum.HEALTH_CERTIFICATE.equals(certificateTypeEnum)) {
|
||||
result.setDetail(buildHealthDetail(entity));
|
||||
return result;
|
||||
}
|
||||
if (CertificateTypeEnum.BUSINESS_LICENSE.equals(certificateTypeEnum)) {
|
||||
result.setDetail(buildBusinessLicenseDetail(entity));
|
||||
return result;
|
||||
}
|
||||
if (CertificateTypeEnum.HYGIENE_LICENSE.equals(certificateTypeEnum)) {
|
||||
result.setDetail(buildHygieneLicenseDetail(entity));
|
||||
return result;
|
||||
}
|
||||
result.setDetail(buildStoreCustomDetail(entity));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新健康证数据。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateHealthCertificate(CertificateAppHealthCertificateUpdateReq req) {
|
||||
ServiceException.notNull(req, "请求参数不能为空");
|
||||
CertificateInstanceEntity entity = queryAndAssertType(req.getCertificateInstanceId(), CertificateTypeEnum.HEALTH_CERTIFICATE, "健康证");
|
||||
|
||||
Date issueDate = parseDate(req.getIssueDate(), "发证日期");
|
||||
Date expireDate = parseDate(req.getExpireDate(), "到期日期");
|
||||
|
||||
//原生app增量更新,可能不传值,则使用数据库值
|
||||
if(Objects.isNull(issueDate)){
|
||||
issueDate = entity.getIssueDate();
|
||||
}
|
||||
if(Objects.isNull(expireDate)){
|
||||
expireDate = entity.getExpireDate();
|
||||
}
|
||||
if(Objects.nonNull(issueDate) && Objects.nonNull(expireDate) && issueDate.after(expireDate)){
|
||||
throw new ServiceException("发证日期不能大于到期日期");
|
||||
}
|
||||
|
||||
entity.setCertificateImage(trimToNull(req.getCertificateImage()));
|
||||
entity.setIssueDate(issueDate);
|
||||
entity.setExpireDate(expireDate);
|
||||
entity.setIsLongTerm(0);
|
||||
entity.setStatus(calculateStatus(entity.getIsLongTerm(), entity.getExpireDate()));
|
||||
int r = certificateInstanceMapper.updateById(entity);
|
||||
if(r <= 0){
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新营业执照数据,并同步营业执照扩展表。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateBusinessLicense(CertificateAppBusinessLicenseUpdateReq req) {
|
||||
ServiceException.notNull(req, "请求参数不能为空");
|
||||
CertificateInstanceEntity entity = queryAndAssertType(req.getCertificateInstanceId(), CertificateTypeEnum.BUSINESS_LICENSE, "营业执照");
|
||||
|
||||
Date establishDate = parseDate(req.getEstablishDate(), "成立时间");
|
||||
Date issueDate = parseDate(req.getIssueDate(), "发证日期");
|
||||
Date expireDate = parseDate(req.getExpireDate(), "到期日期");
|
||||
Integer isLongTerm = req.getIsLongTerm() == null ? 0 : req.getIsLongTerm();
|
||||
if (Integer.valueOf(1).equals(isLongTerm)) {
|
||||
expireDate = null;
|
||||
}
|
||||
|
||||
entity.setCertificateImage(trimToNull(req.getCertificateImage()));
|
||||
entity.setCertificateNo(trimToNull(req.getCertificateNo()));
|
||||
entity.setIssueDate(issueDate);
|
||||
entity.setExpireDate(expireDate);
|
||||
entity.setIsLongTerm(isLongTerm);
|
||||
entity.setStatus(calculateStatus(entity.getIsLongTerm(), entity.getExpireDate()));
|
||||
certificateInstanceMapper.updateById(entity);
|
||||
|
||||
saveBusinessLicenseExt(entity.getId(), req, establishDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新食品经营许可证数据,并同步食品许可扩展表。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateHygieneLicense(CertificateAppHygieneLicenseUpdateReq req) {
|
||||
ServiceException.notNull(req, "请求参数不能为空");
|
||||
CertificateInstanceEntity entity = queryAndAssertType(req.getCertificateInstanceId(), CertificateTypeEnum.HYGIENE_LICENSE, "食品经营许可证");
|
||||
|
||||
Date issueDate = parseDate(req.getIssueDate(), "发证日期");
|
||||
Date expireDate = parseDate(req.getExpireDate(), "到期日期");
|
||||
|
||||
entity.setCertificateImage(trimToNull(req.getCertificateImage()));
|
||||
entity.setIssueDate(issueDate);
|
||||
entity.setExpireDate(expireDate);
|
||||
entity.setIsLongTerm(0);
|
||||
entity.setStatus(calculateStatus(entity.getIsLongTerm(), entity.getExpireDate()));
|
||||
certificateInstanceMapper.updateById(entity);
|
||||
|
||||
saveHygieneLicenseExt(entity.getId(), req);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新门店自定义证照数据,并重写自定义字段明细。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateStoreCustomCertificate(CertificateAppStoreCustomUpdateReq req) {
|
||||
ServiceException.notNull(req, "请求参数不能为空");
|
||||
CertificateInstanceEntity entity = queryAndAssertType(req.getCertificateInstanceId(), CertificateTypeEnum.STORE_CUSTOM_CERTIFICATE, "门店自定义证照");
|
||||
|
||||
Date expireDate = parseDate(req.getExpireDate(), "到期日期");
|
||||
entity.setCertificateImage("");
|
||||
entity.setIssueDate(null);
|
||||
entity.setExpireDate(expireDate);
|
||||
entity.setIsLongTerm(0);
|
||||
entity.setStatus(calculateStatus(entity.getIsLongTerm(), entity.getExpireDate()));
|
||||
certificateInstanceMapper.updateById(entity);
|
||||
|
||||
deleteAndSaveStoreCustomItems(entity.getId(), req.getItemList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建健康证明细返回对象。
|
||||
*/
|
||||
private HealthCertificateDetailVO buildHealthDetail(CertificateInstanceEntity entity) {
|
||||
HealthCertificateDetailVO detailVO = new HealthCertificateDetailVO();
|
||||
detailVO.setCertificateImage(entity.getCertificateImage());
|
||||
detailVO.setIssueDate(entity.getIssueDate());
|
||||
detailVO.setExpireDate(entity.getExpireDate());
|
||||
detailVO.setStatus(entity.getStatus());
|
||||
return detailVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建营业执照明细返回对象。
|
||||
*/
|
||||
private CertificateAppBusinessLicenseDetailVO buildBusinessLicenseDetail(CertificateInstanceEntity entity) {
|
||||
CertificateBusinessLicenseExtEntity extEntity = queryBusinessLicenseExt(entity.getId());
|
||||
CertificateAppBusinessLicenseDetailVO detailVO = new CertificateAppBusinessLicenseDetailVO();
|
||||
detailVO.setCertificateImage(entity.getCertificateImage());
|
||||
detailVO.setCertificateNo(entity.getCertificateNo());
|
||||
detailVO.setIssueDate(entity.getIssueDate());
|
||||
detailVO.setExpireDate(entity.getExpireDate());
|
||||
detailVO.setIsLongTerm(entity.getIsLongTerm());
|
||||
detailVO.setStatus(entity.getStatus());
|
||||
if (extEntity != null) {
|
||||
detailVO.setCompanyName(extEntity.getCompanyName());
|
||||
detailVO.setLegalRepresentative(extEntity.getLegalRepresentative());
|
||||
detailVO.setEstablishDate(extEntity.getEstablishDate());
|
||||
detailVO.setBusinessScope(extEntity.getBusinessScope());
|
||||
detailVO.setAddress(extEntity.getCompanyAddress());
|
||||
}
|
||||
return detailVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建食品经营许可证明细返回对象。
|
||||
*/
|
||||
private CertificateAppHygieneLicenseDetailVO buildHygieneLicenseDetail(CertificateInstanceEntity entity) {
|
||||
CertificateHygieneLicenseExtEntity extEntity = queryHygieneLicenseExt(entity.getId());
|
||||
CertificateAppHygieneLicenseDetailVO detailVO = new CertificateAppHygieneLicenseDetailVO();
|
||||
detailVO.setCertificateImage(entity.getCertificateImage());
|
||||
detailVO.setIssueDate(entity.getIssueDate());
|
||||
detailVO.setExpireDate(entity.getExpireDate());
|
||||
detailVO.setStatus(entity.getStatus());
|
||||
if (extEntity != null) {
|
||||
detailVO.setBusinessProject(extEntity.getBusinessProject());
|
||||
}
|
||||
return detailVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建门店自定义证照明细返回对象。
|
||||
*/
|
||||
private CertificateAppStoreCustomDetailVO buildStoreCustomDetail(CertificateInstanceEntity entity) {
|
||||
CertificateAppStoreCustomDetailVO detailVO = new CertificateAppStoreCustomDetailVO();
|
||||
detailVO.setCertificateImage(entity.getCertificateImage());
|
||||
detailVO.setExpireDate(entity.getExpireDate());
|
||||
|
||||
LambdaQueryWrapper<CertificateInstanceItemEntity> itemWrapper = Wrappers.lambdaQuery();
|
||||
itemWrapper.eq(CertificateInstanceItemEntity::getInstanceId, entity.getId());
|
||||
itemWrapper.eq(CertificateInstanceItemEntity::getEnabledMark, 0);
|
||||
itemWrapper.orderByAsc(CertificateInstanceItemEntity::getSorts);
|
||||
List<CertificateInstanceItemEntity> itemList = certificateInstanceItemMapper.selectList(itemWrapper);
|
||||
if (CollUtil.isNotEmpty(itemList)) {
|
||||
detailVO.setItemList(itemList.stream().map(CertificateInstanceItemVO::convert).collect(Collectors.toList()));
|
||||
}
|
||||
return detailVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存营业执照扩展信息,不存在则新增,存在则更新。
|
||||
*/
|
||||
private void saveBusinessLicenseExt(String instanceId, CertificateAppBusinessLicenseUpdateReq req, Date establishDate) {
|
||||
CertificateBusinessLicenseExtEntity extEntity = queryBusinessLicenseExt(instanceId);
|
||||
if (extEntity == null) {
|
||||
extEntity = new CertificateBusinessLicenseExtEntity();
|
||||
extEntity.setId(FtbUtil.getId());
|
||||
extEntity.setInstanceId(instanceId);
|
||||
extEntity.setEnabledMark(0);
|
||||
fillBusinessLicenseExt(extEntity, req, establishDate);
|
||||
certificateBusinessLicenseExtMapper.insert(extEntity);
|
||||
return;
|
||||
}
|
||||
fillBusinessLicenseExt(extEntity, req, establishDate);
|
||||
certificateBusinessLicenseExtMapper.update(null,new LambdaUpdateWrapper<CertificateBusinessLicenseExtEntity>()
|
||||
.eq(CertificateBusinessLicenseExtEntity::getId, extEntity.getId())
|
||||
.set(CertificateBusinessLicenseExtEntity::getCompanyName,extEntity.getCompanyName())
|
||||
.set(CertificateBusinessLicenseExtEntity::getCompanyAddress,extEntity.getCompanyAddress())
|
||||
.set(CertificateBusinessLicenseExtEntity::getBusinessScope,extEntity.getBusinessScope())
|
||||
.set(CertificateBusinessLicenseExtEntity::getEstablishDate,extEntity.getEstablishDate())
|
||||
.set(CertificateBusinessLicenseExtEntity::getLegalRepresentative,extEntity.getLegalRepresentative())
|
||||
.set(CertificateBusinessLicenseExtEntity::getLastModifyUserId, UserProvider.getLoginUserId())
|
||||
.set(CertificateBusinessLicenseExtEntity::getLastModifyTime,new Date()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充营业执照扩展字段。
|
||||
*/
|
||||
private void fillBusinessLicenseExt(CertificateBusinessLicenseExtEntity extEntity, CertificateAppBusinessLicenseUpdateReq req, Date establishDate) {
|
||||
extEntity.setCompanyName(trimToNull(req.getCompanyName()));
|
||||
extEntity.setLegalRepresentative(trimToNull(req.getLegalRepresentative()));
|
||||
extEntity.setEstablishDate(establishDate);
|
||||
extEntity.setBusinessScope(trimToNull(req.getBusinessScope()));
|
||||
extEntity.setCompanyAddress(req.getAddress());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存食品经营许可扩展信息,不存在则新增,存在则更新。
|
||||
*/
|
||||
private void saveHygieneLicenseExt(String instanceId, CertificateAppHygieneLicenseUpdateReq req) {
|
||||
CertificateHygieneLicenseExtEntity extEntity = queryHygieneLicenseExt(instanceId);
|
||||
if (extEntity == null) {
|
||||
extEntity = new CertificateHygieneLicenseExtEntity();
|
||||
extEntity.setId(FtbUtil.getId());
|
||||
extEntity.setInstanceId(instanceId);
|
||||
extEntity.setEnabledMark(0);
|
||||
extEntity.setBusinessProject(trimToNull(req.getBusinessProject()));
|
||||
certificateHygieneLicenseExtMapper.insert(extEntity);
|
||||
return;
|
||||
}
|
||||
extEntity.setBusinessProject(trimToNull(req.getBusinessProject()));
|
||||
certificateHygieneLicenseExtMapper.update(null,new LambdaUpdateWrapper<CertificateHygieneLicenseExtEntity>()
|
||||
.eq(CertificateHygieneLicenseExtEntity::getId, extEntity.getId())
|
||||
.set(CertificateHygieneLicenseExtEntity::getBusinessProject,extEntity.getBusinessProject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除旧的门店自定义明细并保存新的明细列表。
|
||||
*/
|
||||
private void deleteAndSaveStoreCustomItems(String instanceId, List<CertificateInstanceItemReq> itemList) {
|
||||
LambdaQueryWrapper<CertificateInstanceItemEntity> deleteWrapper = Wrappers.lambdaQuery();
|
||||
deleteWrapper.eq(CertificateInstanceItemEntity::getInstanceId, instanceId);
|
||||
certificateInstanceItemMapper.delete(deleteWrapper);
|
||||
|
||||
List<CertificateInstanceItemReq> safeList = itemList == null ? Collections.emptyList() : itemList;
|
||||
long defaultSort = 1L;
|
||||
for (CertificateInstanceItemReq itemReq : safeList) {
|
||||
if (itemReq == null || StrUtil.isBlank(itemReq.getItemName())) {
|
||||
continue;
|
||||
}
|
||||
CertificateInstanceItemEntity itemEntity = new CertificateInstanceItemEntity();
|
||||
itemEntity.setId(FtbUtil.getId());
|
||||
itemEntity.setInstanceId(instanceId);
|
||||
itemEntity.setTemplateItemId(trimToNull(itemReq.getTemplateItemId()));
|
||||
itemEntity.setItemName(trimToNull(itemReq.getItemName()));
|
||||
itemEntity.setItemType(itemReq.getItemType());
|
||||
itemEntity.setItemValue(trimToNull(itemReq.getItemValue()));
|
||||
itemEntity.setSorts(itemReq.getSorts() == null ? defaultSort : itemReq.getSorts());
|
||||
itemEntity.setEnabledMark(0);
|
||||
certificateInstanceItemMapper.insert(itemEntity);
|
||||
defaultSort++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据实例ID查询营业执照扩展信息。
|
||||
*/
|
||||
private CertificateBusinessLicenseExtEntity queryBusinessLicenseExt(String instanceId) {
|
||||
LambdaQueryWrapper<CertificateBusinessLicenseExtEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(CertificateBusinessLicenseExtEntity::getInstanceId, instanceId);
|
||||
wrapper.eq(CertificateBusinessLicenseExtEntity::getEnabledMark, 0);
|
||||
wrapper.orderByDesc(CertificateBusinessLicenseExtEntity::getLastModifyTime);
|
||||
wrapper.orderByDesc(CertificateBusinessLicenseExtEntity::getCreatorTime);
|
||||
List<CertificateBusinessLicenseExtEntity> extList = certificateBusinessLicenseExtMapper.selectList(wrapper);
|
||||
return CollUtil.isEmpty(extList) ? null : extList.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据实例ID查询食品许可扩展信息。
|
||||
*/
|
||||
private CertificateHygieneLicenseExtEntity queryHygieneLicenseExt(String instanceId) {
|
||||
LambdaQueryWrapper<CertificateHygieneLicenseExtEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(CertificateHygieneLicenseExtEntity::getInstanceId, instanceId);
|
||||
wrapper.eq(CertificateHygieneLicenseExtEntity::getEnabledMark, 0);
|
||||
wrapper.orderByDesc(CertificateHygieneLicenseExtEntity::getLastModifyTime);
|
||||
wrapper.orderByDesc(CertificateHygieneLicenseExtEntity::getCreatorTime);
|
||||
List<CertificateHygieneLicenseExtEntity> extList = certificateHygieneLicenseExtMapper.selectList(wrapper);
|
||||
return CollUtil.isEmpty(extList) ? null : extList.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询有效证照实例。
|
||||
*/
|
||||
private CertificateInstanceEntity queryActiveEntity(String id) {
|
||||
CertificateInstanceEntity entity = certificateInstanceMapper.selectById(id);
|
||||
ServiceException.notNull(entity, "证照数据不存在");
|
||||
ServiceException.isTrue(Integer.valueOf(0).equals(entity.getEnabledMark()), "证照数据不存在");
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询实例并校验证照类型。
|
||||
*/
|
||||
private CertificateInstanceEntity queryAndAssertType(String certificateInstanceId, CertificateTypeEnum expectType, String typeName) {
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(certificateInstanceId), "证照实例ID不能为空");
|
||||
CertificateInstanceEntity entity = queryActiveEntity(StrUtil.trim(certificateInstanceId));
|
||||
ServiceException.isTrue(StrUtil.equalsIgnoreCase(StrUtil.trim(entity.getCertificateType()), expectType.getType()),
|
||||
"当前证照不是" + typeName);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析日期字符串。
|
||||
*/
|
||||
private Date parseDate(String dateText, String fieldName) {
|
||||
if (StrUtil.isBlank(dateText)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return DateUtil.parseDate(StrUtil.trim(dateText));
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException(fieldName + "格式不正确,正确格式为yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析日期时间戳
|
||||
*/
|
||||
private Date parseDate(Long dateTimestamp, String fieldName) {
|
||||
if (Objects.isNull(dateTimestamp) || dateTimestamp <= 0L) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return new Date(dateTimestamp);
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException(fieldName + "格式不正确,正确格式为yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算证照状态。
|
||||
*/
|
||||
private Integer calculateStatus(Integer isLongTerm, Date expireDate) {
|
||||
if (Integer.valueOf(1).equals(isLongTerm)) {
|
||||
return STATUS_NORMAL;
|
||||
}
|
||||
if (expireDate == null) {
|
||||
return STATUS_MISSING;
|
||||
}
|
||||
Date today = DateUtil.beginOfDay(DateUtil.date());
|
||||
Date target = DateUtil.beginOfDay(expireDate);
|
||||
if (target.before(today)) {
|
||||
return STATUS_EXPIRED;
|
||||
}
|
||||
long daysDiff = DateUtil.betweenDay(today, target, false);
|
||||
if (daysDiff <= NEAR_EXPIRE_DAYS) {
|
||||
return STATUS_NEAR_EXPIRE;
|
||||
}
|
||||
return STATUS_NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态转中文名称。
|
||||
*/
|
||||
private String resolveStatusName(Integer status) {
|
||||
if (Integer.valueOf(STATUS_MISSING).equals(status)) {
|
||||
return "缺失";
|
||||
}
|
||||
if (Integer.valueOf(STATUS_EXPIRED).equals(status)) {
|
||||
return "过期";
|
||||
}
|
||||
if (Integer.valueOf(STATUS_NEAR_EXPIRE).equals(status)) {
|
||||
return "临期";
|
||||
}
|
||||
if (Integer.valueOf(STATUS_NORMAL).equals(status)) {
|
||||
return "正常";
|
||||
}
|
||||
return "-";
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串去空格,空串按null处理。
|
||||
*/
|
||||
private String trimToNull(String value) {
|
||||
String trimValue = StrUtil.trim(value);
|
||||
return StrUtil.isBlank(trimValue) ? null : trimValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,906 @@
|
||||
package jnpf.certificate.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
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 io.seata.spring.annotation.GlobalTransactional;
|
||||
import jnpf.base.ActionResult;
|
||||
import jnpf.certificate.mapper.CertificateBusinessLicenseExtMapper;
|
||||
import jnpf.certificate.mapper.CertificateHygieneLicenseExtMapper;
|
||||
import jnpf.certificate.mapper.CertificateInstanceItemMapper;
|
||||
import jnpf.certificate.mapper.CertificateInstanceMapper;
|
||||
import jnpf.certificate.service.CertificateStoreService;
|
||||
import jnpf.exception.HandleException;
|
||||
import jnpf.model.certificate.po.CertificateBusinessLicenseExtEntity;
|
||||
import jnpf.model.certificate.po.CertificateHygieneLicenseExtEntity;
|
||||
import jnpf.model.certificate.po.CertificateInstanceEntity;
|
||||
import jnpf.model.certificate.po.CertificateInstanceItemEntity;
|
||||
import jnpf.model.certificate.req.CertificateInstanceItemReq;
|
||||
import jnpf.model.certificate.req.CertificateStoreSaveReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppBusinessLicenseUpdateReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppHygieneLicenseUpdateReq;
|
||||
import jnpf.model.certificate.req.app.CertificateAppStoreCustomUpdateReq;
|
||||
import jnpf.model.certificate.vo.CertificateStoreAndCertificatesVO;
|
||||
import jnpf.model.certificate.vo.CertificateStoreTabVO;
|
||||
import jnpf.model.storecertificatephoto.po.StoreCertificatePhotoEntity;
|
||||
import jnpf.model.storecertificatephoto.po.StoreCertificatePhotoItemEntity;
|
||||
import jnpf.model.storecertificatephoto.vo.StoreCertificatePhotoItemVO;
|
||||
import jnpf.model.storecertificatephoto.vo.StoreCertificatePhotoVO;
|
||||
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
|
||||
import jnpf.permission.OrganizeApi;
|
||||
import jnpf.permission.dto.v2.organzie.SaveStoreDTO;
|
||||
import jnpf.storecertificatephoto.helper.StoreCertificatePhotoHelper;
|
||||
import jnpf.storecertificatephoto.mapper.StoreCertificatePhotoItemMapper;
|
||||
import jnpf.storecertificatephoto.mapper.StoreCertificatePhotoMapper;
|
||||
import jnpf.util.FtbUtil;
|
||||
import jnpf.util.ServiceException;
|
||||
import jnpf.util.UserProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.sql.SQLIntegrityConstraintViolationException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 门店证照服务实现。
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class CertificateStoreServiceImpl implements CertificateStoreService {
|
||||
|
||||
private static final int STATUS_MISSING = 1;
|
||||
private static final int STATUS_EXPIRED = 2;
|
||||
private static final int STATUS_NEAR_EXPIRE = 3;
|
||||
private static final int STATUS_NORMAL = 4;
|
||||
private static final int SUBJECT_TYPE_STORE = 3;
|
||||
private static final int NEAR_EXPIRE_DAYS = 30;
|
||||
|
||||
@Autowired
|
||||
private OrganizeApi organizeApi;
|
||||
@Autowired
|
||||
private CertificateInstanceMapper certificateInstanceMapper;
|
||||
@Autowired
|
||||
private CertificateBusinessLicenseExtMapper certificateBusinessLicenseExtMapper;
|
||||
@Autowired
|
||||
private CertificateHygieneLicenseExtMapper certificateHygieneLicenseExtMapper;
|
||||
@Autowired
|
||||
private CertificateInstanceItemMapper certificateInstanceItemMapper;
|
||||
@Autowired
|
||||
private StoreCertificatePhotoMapper storeCertificatePhotoMapper;
|
||||
@Autowired
|
||||
private StoreCertificatePhotoItemMapper storeCertificatePhotoItemMapper;
|
||||
@Autowired
|
||||
private StoreCertificatePhotoHelper storeCertificatePhotoHelper;
|
||||
|
||||
/**
|
||||
* 保存门店及门店证照。
|
||||
* 先调用组织服务保存门店,再保存证照实例及扩展表。
|
||||
*/
|
||||
@Override
|
||||
public String saveStoreAndCertificates(CertificateStoreSaveReq req) {
|
||||
ServiceException.notNull(req, "请求参数不能为空");
|
||||
SaveStoreDTO store = req.getStore();
|
||||
ServiceException.notNull(store, "门店信息不能为空");
|
||||
validCustomerCertificates(req.getStoreCustomCertificates());
|
||||
|
||||
String storeId = saveStore(store);
|
||||
saveBusinessLicense(storeId,store.getDisabled(), req.getBusinessLicense());
|
||||
saveHygieneLicense(storeId,store.getDisabled(), req.getHygieneLicense());
|
||||
saveStoreCustomCertificates(storeId, store.getDisabled(),req.getStoreCustomCertificates());
|
||||
return storeId;
|
||||
}
|
||||
|
||||
private void validCustomerCertificates(Collection<CertificateAppStoreCustomUpdateReq> storeCustomCertificates) {
|
||||
if(CollectionUtil.isEmpty(storeCustomCertificates)){
|
||||
return;
|
||||
}
|
||||
for (CertificateAppStoreCustomUpdateReq req : storeCustomCertificates){
|
||||
ServiceException.notNull(req.getTemplateId(), "门店自定义证照模板id不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteStore(String id) throws HandleException {
|
||||
ActionResult<Boolean> actionResult = organizeApi.deleteStore(id);
|
||||
if(Objects.isNull(actionResult) || actionResult.getCode() != 200){
|
||||
log.error("deleteStore fail.id:{},actionResult:{}",id,actionResult);
|
||||
throw new HandleException("组织服务异常");
|
||||
}
|
||||
if(!actionResult.getData()){
|
||||
log.error("deleteStore organize fail.id:{}",id);
|
||||
throw new HandleException("删除失败!");
|
||||
}
|
||||
certificateInstanceMapper.update(new CertificateInstanceEntity(),new LambdaUpdateWrapper<CertificateInstanceEntity>()
|
||||
.eq(CertificateInstanceEntity::getSubjectId, id)
|
||||
.set(CertificateInstanceEntity::getEnabledMark,1));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据门店ID查询门店及门店证照详情。
|
||||
*/
|
||||
@Override
|
||||
public CertificateStoreAndCertificatesVO getStoreAndCertificates(String storeId) {
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(storeId), "门店ID不能为空");
|
||||
String targetStoreId = StrUtil.trim(storeId);
|
||||
|
||||
CertificateStoreAndCertificatesVO result = new CertificateStoreAndCertificatesVO();
|
||||
result.setBusinessLicense(queryBusinessLicense(targetStoreId));
|
||||
result.setHygieneLicense(queryHygieneLicense(targetStoreId));
|
||||
result.setStoreCustomCertificates(queryStoreCustomCertificates(targetStoreId));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CertificateStoreTabVO> queryStoreCertificateTabList() {
|
||||
List<CertificateStoreTabVO> result = new ArrayList<>();
|
||||
List<CertificateTypeEnum> defaultTypeList = Arrays.asList(
|
||||
CertificateTypeEnum.BUSINESS_LICENSE,
|
||||
CertificateTypeEnum.HYGIENE_LICENSE
|
||||
);
|
||||
for (CertificateTypeEnum certificateType : defaultTypeList) {
|
||||
CertificateStoreTabVO tabVO = new CertificateStoreTabVO();
|
||||
tabVO.setLabel(certificateType.getLabel());
|
||||
tabVO.setKey(certificateType.getType());
|
||||
tabVO.setType(certificateType.getType());
|
||||
result.add(tabVO);
|
||||
}
|
||||
|
||||
List<StoreCertificatePhotoVO> templateList = queryStoreCustomTemplateList(1);
|
||||
if (CollUtil.isEmpty(templateList)) {
|
||||
return result;
|
||||
}
|
||||
for (StoreCertificatePhotoVO template : templateList) {
|
||||
if (template == null || StrUtil.isBlank(template.getId()) || StrUtil.isBlank(template.getCertificateName())) {
|
||||
continue;
|
||||
}
|
||||
CertificateStoreTabVO tabVO = new CertificateStoreTabVO();
|
||||
tabVO.setLabel(StrUtil.trim(template.getCertificateName()));
|
||||
tabVO.setKey(StrUtil.trim(template.getId()));
|
||||
tabVO.setType(CertificateTypeEnum.STORE_CUSTOM_CERTIFICATE.getType());
|
||||
tabVO.setStoreCustomConfig(template);
|
||||
result.add(tabVO);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用组织服务保存门店并返回门店ID。
|
||||
*/
|
||||
private String saveStore(SaveStoreDTO storeDTO) {
|
||||
ActionResult<String> actionResult;
|
||||
try {
|
||||
actionResult = organizeApi.saveStore(storeDTO);
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("保存门店失败: " + e.getMessage());
|
||||
}
|
||||
ServiceException.notNull(actionResult, "保存门店失败");
|
||||
ServiceException.isTrue(ActionResult.success().getCode().equals(actionResult.getCode()),
|
||||
StrUtil.blankToDefault(actionResult.getMsg(), "保存门店失败"));
|
||||
String storeId = StrUtil.trim(actionResult.getData());
|
||||
if (StrUtil.isBlank(storeId)) {
|
||||
storeId = StrUtil.trim(storeDTO.getId());
|
||||
}
|
||||
ServiceException.isTrue(StrUtil.isNotBlank(storeId), "保存门店成功但未返回门店ID");
|
||||
return storeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询启用中的门店自定义证照模板及明细。
|
||||
*/
|
||||
private List<StoreCertificatePhotoVO> queryStoreCustomTemplateList(Integer status) {
|
||||
LambdaQueryWrapper<StoreCertificatePhotoEntity> templateWrapper = Wrappers.lambdaQuery();
|
||||
templateWrapper.eq(StoreCertificatePhotoEntity::getEnabledMark, 0);
|
||||
if(Objects.nonNull(status)){
|
||||
templateWrapper.eq(StoreCertificatePhotoEntity::getStatus, status);
|
||||
}
|
||||
templateWrapper.orderByDesc(StoreCertificatePhotoEntity::getCreatorTime);
|
||||
List<StoreCertificatePhotoEntity> templateEntities = storeCertificatePhotoMapper.selectList(templateWrapper);
|
||||
if (CollUtil.isEmpty(templateEntities)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<String> templateIds = templateEntities.stream()
|
||||
.map(StoreCertificatePhotoEntity::getId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.map(StrUtil::trim)
|
||||
.collect(Collectors.toList());
|
||||
Map<String, List<StoreCertificatePhotoItemEntity>> itemMap = queryStoreCustomTemplateItemMap(templateIds);
|
||||
return templateEntities.stream()
|
||||
.map(entity -> buildStoreCustomTemplateVO(entity, itemMap))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按模板ID列表查询模板明细并按模板分组。
|
||||
*/
|
||||
private Map<String, List<StoreCertificatePhotoItemEntity>> queryStoreCustomTemplateItemMap(List<String> templateIds) {
|
||||
if (CollUtil.isEmpty(templateIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
LambdaQueryWrapper<StoreCertificatePhotoItemEntity> itemWrapper = Wrappers.lambdaQuery();
|
||||
itemWrapper.in(StoreCertificatePhotoItemEntity::getPhotoId, templateIds);
|
||||
itemWrapper.eq(StoreCertificatePhotoItemEntity::getEnabledMark, 0);
|
||||
itemWrapper.orderByAsc(StoreCertificatePhotoItemEntity::getPhotoId)
|
||||
.orderByAsc(StoreCertificatePhotoItemEntity::getItemType)
|
||||
.orderByAsc(StoreCertificatePhotoItemEntity::getSorts);
|
||||
List<StoreCertificatePhotoItemEntity> itemEntities = storeCertificatePhotoItemMapper.selectList(itemWrapper);
|
||||
if (CollUtil.isEmpty(itemEntities)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return itemEntities.stream().collect(Collectors.groupingBy(StoreCertificatePhotoItemEntity::getPhotoId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建门店自定义证照模板返回对象。
|
||||
*/
|
||||
private StoreCertificatePhotoVO buildStoreCustomTemplateVO(StoreCertificatePhotoEntity entity,
|
||||
Map<String, List<StoreCertificatePhotoItemEntity>> itemMap) {
|
||||
if (entity == null || StrUtil.isBlank(entity.getId())) {
|
||||
return null;
|
||||
}
|
||||
StoreCertificatePhotoVO vo = StoreCertificatePhotoVO.convert(entity);
|
||||
List<StoreCertificatePhotoItemEntity> itemEntities = itemMap.getOrDefault(entity.getId(), Collections.emptyList());
|
||||
List<StoreCertificatePhotoItemVO> imageItemList = new ArrayList<>();
|
||||
List<StoreCertificatePhotoItemVO> textItemList = new ArrayList<>();
|
||||
for (StoreCertificatePhotoItemEntity itemEntity : itemEntities) {
|
||||
StoreCertificatePhotoItemVO itemVO = StoreCertificatePhotoItemVO.convert(itemEntity);
|
||||
if (itemVO == null) {
|
||||
continue;
|
||||
}
|
||||
if (Integer.valueOf(1).equals(itemEntity.getItemType())) {
|
||||
imageItemList.add(itemVO);
|
||||
continue;
|
||||
}
|
||||
if (Integer.valueOf(2).equals(itemEntity.getItemType())) {
|
||||
textItemList.add(itemVO);
|
||||
}
|
||||
}
|
||||
imageItemList.sort(Comparator.comparing(item -> item.getSorts() == null ? Long.MAX_VALUE : item.getSorts()));
|
||||
textItemList.sort(Comparator.comparing(item -> item.getSorts() == null ? Long.MAX_VALUE : item.getSorts()));
|
||||
vo.setImageItemList(imageItemList);
|
||||
vo.setTextItemList(textItemList);
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存营业执照实例和扩展数据。
|
||||
*/
|
||||
private void saveBusinessLicense(String storeId,Integer disable, CertificateAppBusinessLicenseUpdateReq req) {
|
||||
if (req == null) {
|
||||
req = new CertificateAppBusinessLicenseUpdateReq();
|
||||
}
|
||||
CertificateInstanceEntity instance = findOrCreateSingleInstance(
|
||||
storeId,
|
||||
req.getCertificateInstanceId(),
|
||||
CertificateTypeEnum.BUSINESS_LICENSE.getType()
|
||||
);
|
||||
Date issueDate = parseDate(req.getIssueDate(), "营业执照发证日期");
|
||||
Date expireDate = parseDate(req.getExpireDate(), "营业执照到期日期");
|
||||
Date establishDate = parseDate(req.getEstablishDate(), "营业执照成立时间");
|
||||
Integer isLongTerm = req.getIsLongTerm() == null ? 0 : req.getIsLongTerm();
|
||||
if (Integer.valueOf(1).equals(isLongTerm)) {
|
||||
expireDate = null;
|
||||
}
|
||||
|
||||
instance.setIssueDate(issueDate);
|
||||
instance.setExpireDate(expireDate);
|
||||
if(Objects.nonNull(expireDate)){
|
||||
instance.setExpireTimestamp(expireDate.getTime());
|
||||
}else{
|
||||
instance.setExpireTimestamp(0);
|
||||
}
|
||||
instance.setIsLongTerm(isLongTerm);
|
||||
instance.setCertificateNo(trimToNull(req.getCertificateNo()));
|
||||
instance.setCertificateImage(trimToNull(req.getCertificateImage()));
|
||||
instance.setStatus(calculateStatus(instance.getIsLongTerm(), instance.getExpireDate()));
|
||||
instance.setStoreDisable(buildStoreDisable(disable));
|
||||
saveOrUpdateInstance(instance);
|
||||
|
||||
upsertBusinessLicenseExt(instance.getId(), req, establishDate);
|
||||
}
|
||||
|
||||
private Integer buildStoreDisable(Integer disable) {
|
||||
if(Objects.isNull(disable)){
|
||||
return 0;
|
||||
}
|
||||
return disable == 1?1:0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询门店营业执照详情。
|
||||
*/
|
||||
private CertificateAppBusinessLicenseUpdateReq queryBusinessLicense(String storeId) {
|
||||
CertificateInstanceEntity instance = findLatestByStoreAndType(storeId, CertificateTypeEnum.BUSINESS_LICENSE.getType(),null);
|
||||
if (instance == null) {
|
||||
return null;
|
||||
}
|
||||
CertificateBusinessLicenseExtEntity extEntity = findBusinessExt(instance.getId());
|
||||
CertificateAppBusinessLicenseUpdateReq result = new CertificateAppBusinessLicenseUpdateReq();
|
||||
result.setCertificateInstanceId(instance.getId());
|
||||
result.setCertificateImage(instance.getCertificateImage());
|
||||
result.setCertificateNo(instance.getCertificateNo());
|
||||
result.setIssueDate(formatDate(instance.getIssueDate()));
|
||||
result.setExpireDate(formatDate(instance.getExpireDate()));
|
||||
result.setIsLongTerm(instance.getIsLongTerm() == null ? 0 : instance.getIsLongTerm());
|
||||
if (extEntity != null) {
|
||||
result.setCompanyName(extEntity.getCompanyName());
|
||||
result.setLegalRepresentative(extEntity.getLegalRepresentative());
|
||||
result.setEstablishDate(formatDate(extEntity.getEstablishDate()));
|
||||
result.setBusinessScope(extEntity.getBusinessScope());
|
||||
result.setAddress(extEntity.getCompanyAddress());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存食品经营许可证实例和扩展数据。
|
||||
*/
|
||||
private void saveHygieneLicense(String storeId, Integer storeDisable,CertificateAppHygieneLicenseUpdateReq req) {
|
||||
if (req == null) {
|
||||
req = new CertificateAppHygieneLicenseUpdateReq();
|
||||
}
|
||||
CertificateInstanceEntity instance = findOrCreateSingleInstance(
|
||||
storeId,
|
||||
req.getCertificateInstanceId(),
|
||||
CertificateTypeEnum.HYGIENE_LICENSE.getType()
|
||||
);
|
||||
Date issueDate = parseDate(req.getIssueDate(), "食品经营许可证发证日期");
|
||||
Date expireDate = parseDate(req.getExpireDate(), "食品经营许可证到期日期");
|
||||
|
||||
instance.setIssueDate(issueDate);
|
||||
instance.setExpireDate(expireDate);
|
||||
if(Objects.nonNull(expireDate)){
|
||||
instance.setExpireTimestamp(expireDate.getTime());
|
||||
}
|
||||
instance.setIsLongTerm(0);
|
||||
instance.setCertificateImage(trimToNull(req.getCertificateImage()));
|
||||
instance.setStatus(calculateStatus(instance.getIsLongTerm(), instance.getExpireDate()));
|
||||
instance.setStoreDisable(buildStoreDisable(storeDisable));
|
||||
saveOrUpdateInstance(instance);
|
||||
|
||||
upsertHygieneLicenseExt(instance.getId(), req);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询门店食品经营许可证详情。
|
||||
*/
|
||||
private CertificateAppHygieneLicenseUpdateReq queryHygieneLicense(String storeId) {
|
||||
CertificateInstanceEntity instance = findLatestByStoreAndType(storeId, CertificateTypeEnum.HYGIENE_LICENSE.getType(),null);
|
||||
if (instance == null) {
|
||||
return null;
|
||||
}
|
||||
CertificateHygieneLicenseExtEntity extEntity = findHygieneExt(instance.getId());
|
||||
CertificateAppHygieneLicenseUpdateReq result = new CertificateAppHygieneLicenseUpdateReq();
|
||||
result.setCertificateInstanceId(instance.getId());
|
||||
result.setCertificateImage(instance.getCertificateImage());
|
||||
result.setIssueDate(formatDate(instance.getIssueDate()));
|
||||
result.setExpireDate(formatDate(instance.getExpireDate()));
|
||||
if (extEntity != null) {
|
||||
result.setBusinessProject(extEntity.getBusinessProject());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存门店自定义证照实例和明细数据。
|
||||
*/
|
||||
private void saveStoreCustomCertificates(String storeId,Integer disabled, Collection<CertificateAppStoreCustomUpdateReq> reqList) {
|
||||
if (CollUtil.isEmpty(reqList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String,String> templateNameById = storeCertificatePhotoHelper.buildStoreCertificateIdAndNames(reqList.stream()
|
||||
.map(CertificateAppStoreCustomUpdateReq::getTemplateId)
|
||||
.collect(Collectors.toSet()),1);
|
||||
for (CertificateAppStoreCustomUpdateReq req : reqList) {
|
||||
if (req == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//如果是禁用状态,则跳过
|
||||
String templateId = req.getTemplateId();
|
||||
int templateStatus = 1;
|
||||
if(!templateNameById.containsKey(templateId)){
|
||||
templateStatus = 0;
|
||||
continue;
|
||||
}
|
||||
CertificateInstanceEntity instance = findOrCreateCustomInstance(storeId, req.getCertificateInstanceId(), templateId);
|
||||
|
||||
Date expireDate = parseDate(req.getExpireDate(), "门店自定义证照到期日期");
|
||||
|
||||
instance.setCertificateImage(buildCustomCertificateImage(req.getItemList()));
|
||||
instance.setIssueDate(null);
|
||||
instance.setExpireDate(expireDate);
|
||||
if(Objects.nonNull(expireDate)){
|
||||
instance.setExpireTimestamp(expireDate.getTime());
|
||||
}
|
||||
instance.setIsLongTerm(0);
|
||||
instance.setStatus(calculateStatus(instance.getIsLongTerm(), instance.getExpireDate()));
|
||||
|
||||
instance.setTemplateStatus(templateStatus);
|
||||
instance.setStoreDisable(buildStoreDisable(disabled));
|
||||
saveOrUpdateInstance(instance);
|
||||
|
||||
rewriteCustomItems(instance.getId(), req.getItemList());
|
||||
}
|
||||
}
|
||||
|
||||
private String buildCustomCertificateImage(List<CertificateInstanceItemReq> itemList) {
|
||||
if(CollectionUtil.isEmpty(itemList)){
|
||||
return "";
|
||||
}
|
||||
for (CertificateInstanceItemReq item : itemList) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
if (item.getItemType() == 1) {
|
||||
return item.getItemValue();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询门店自定义证照详情集合。
|
||||
*/
|
||||
private List<CertificateAppStoreCustomUpdateReq> queryStoreCustomCertificates(String storeId) {
|
||||
LambdaQueryWrapper<CertificateInstanceEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(CertificateInstanceEntity::getEnabledMark, 0);
|
||||
wrapper.eq(CertificateInstanceEntity::getSubjectType, SUBJECT_TYPE_STORE);
|
||||
wrapper.eq(CertificateInstanceEntity::getSubjectId, storeId);
|
||||
wrapper.eq(CertificateInstanceEntity::getCertificateType, CertificateTypeEnum.STORE_CUSTOM_CERTIFICATE.getType());
|
||||
wrapper.orderByDesc(CertificateInstanceEntity::getLastModifyTime);
|
||||
wrapper.orderByDesc(CertificateInstanceEntity::getCreatorTime);
|
||||
List<CertificateInstanceEntity> instanceList = certificateInstanceMapper.selectList(wrapper);
|
||||
if (CollUtil.isEmpty(instanceList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Set<String> enabledTemplateIds = storeCertificatePhotoMapper.selectList(new LambdaQueryWrapper<StoreCertificatePhotoEntity>()
|
||||
.select(StoreCertificatePhotoEntity::getId)
|
||||
.in(StoreCertificatePhotoEntity::getId,instanceList.stream()
|
||||
.map(CertificateInstanceEntity::getTemplateId)
|
||||
.collect(Collectors.toSet()))
|
||||
.eq(StoreCertificatePhotoEntity::getEnabledMark,0)
|
||||
.eq(StoreCertificatePhotoEntity::getStatus,1))
|
||||
.stream()
|
||||
.map(StoreCertificatePhotoEntity::getId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Map<String, List<CertificateInstanceItemEntity>> itemMap = queryStoreCustomItemMap(instanceList.stream()
|
||||
.filter(instance->{
|
||||
String templateId = instance.getTemplateId();
|
||||
if(StringUtils.isBlank(templateId)){
|
||||
return true;
|
||||
}
|
||||
return enabledTemplateIds.contains(templateId);
|
||||
})
|
||||
.map(CertificateInstanceEntity::getId)
|
||||
.collect(Collectors.toSet()));
|
||||
return instanceList.stream()
|
||||
.filter(instance->{
|
||||
String templateId = instance.getTemplateId();
|
||||
if(StringUtils.isBlank(templateId)){
|
||||
return true;
|
||||
}
|
||||
return enabledTemplateIds.contains(templateId);
|
||||
})
|
||||
.map(instance -> convertStoreCustomCertificate(instance, itemMap))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按证照实例ID批量查询自定义证照明细并分组。
|
||||
*/
|
||||
private Map<String, List<CertificateInstanceItemEntity>> queryStoreCustomItemMap(Collection<String> instanceIds) {
|
||||
if (CollUtil.isEmpty(instanceIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
LambdaQueryWrapper<CertificateInstanceItemEntity> itemWrapper = Wrappers.lambdaQuery();
|
||||
itemWrapper.in(CertificateInstanceItemEntity::getInstanceId, instanceIds);
|
||||
itemWrapper.eq(CertificateInstanceItemEntity::getEnabledMark, 0);
|
||||
itemWrapper.orderByAsc(CertificateInstanceItemEntity::getInstanceId);
|
||||
itemWrapper.orderByAsc(CertificateInstanceItemEntity::getSorts);
|
||||
List<CertificateInstanceItemEntity> itemEntities = certificateInstanceItemMapper.selectList(itemWrapper);
|
||||
if (CollUtil.isEmpty(itemEntities)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
return itemEntities.stream()
|
||||
.collect(Collectors.groupingBy(CertificateInstanceItemEntity::getInstanceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据证照实例ID或门店+证照类型查询单条实例,不存在则创建。
|
||||
*/
|
||||
private CertificateInstanceEntity findOrCreateSingleInstance(String storeId, String certificateInstanceId, String certificateType) {
|
||||
CertificateInstanceEntity instance = findByInstanceId(certificateInstanceId, certificateType);
|
||||
if (instance == null) {
|
||||
instance = findLatestByStoreAndType(storeId, certificateType,null);
|
||||
}
|
||||
if (instance == null) {
|
||||
instance = createNewInstance(storeId, certificateType);
|
||||
}
|
||||
normalizeStoreInstance(instance, storeId, certificateType);
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据证照实例ID查询自定义证照实例,不存在则创建新实例。
|
||||
*/
|
||||
private CertificateInstanceEntity findOrCreateCustomInstance(String storeId, String certificateInstanceId, String templateId) {
|
||||
String certificateType = CertificateTypeEnum.STORE_CUSTOM_CERTIFICATE.getType();
|
||||
CertificateInstanceEntity instance = findByInstanceId(certificateInstanceId, certificateType);
|
||||
if (instance == null) {
|
||||
instance = createNewInstance(storeId, certificateType);
|
||||
instance.setTemplateId(templateId);
|
||||
}
|
||||
normalizeStoreInstance(instance, storeId, certificateType);
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按证照实例ID查询。
|
||||
*/
|
||||
private CertificateInstanceEntity findByInstanceId(String certificateInstanceId, String certificateType) {
|
||||
if (StrUtil.isBlank(certificateInstanceId)) {
|
||||
return null;
|
||||
}
|
||||
String instanceId = StrUtil.trim(certificateInstanceId);
|
||||
CertificateInstanceEntity instance = certificateInstanceMapper.selectById(instanceId);
|
||||
ServiceException.isTrue(instance != null && Integer.valueOf(0).equals(instance.getEnabledMark()), "证照实例不存在");
|
||||
ServiceException.isTrue(StrUtil.equalsIgnoreCase(StrUtil.trim(instance.getCertificateType()), certificateType), "证照类型不匹配");
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按门店和证照类型查询最新实例。
|
||||
*/
|
||||
private CertificateInstanceEntity findLatestByStoreAndType(String storeId, String certificateType,String templateId) {
|
||||
LambdaQueryWrapper<CertificateInstanceEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(CertificateInstanceEntity::getEnabledMark, 0);
|
||||
wrapper.eq(CertificateInstanceEntity::getSubjectType, SUBJECT_TYPE_STORE);
|
||||
wrapper.eq(CertificateInstanceEntity::getSubjectId, storeId);
|
||||
wrapper.eq(CertificateInstanceEntity::getCertificateType, certificateType);
|
||||
if(StringUtils.isNotBlank(templateId)){
|
||||
wrapper.eq(CertificateInstanceEntity::getTemplateId, templateId);
|
||||
}
|
||||
wrapper.orderByDesc(CertificateInstanceEntity::getLastModifyTime);
|
||||
wrapper.orderByDesc(CertificateInstanceEntity::getCreatorTime);
|
||||
List<CertificateInstanceEntity> list = certificateInstanceMapper.selectList(wrapper);
|
||||
return CollUtil.isEmpty(list) ? null : list.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建新证照实例。
|
||||
*/
|
||||
private CertificateInstanceEntity createNewInstance(String storeId, String certificateType) {
|
||||
CertificateInstanceEntity instance = new CertificateInstanceEntity();
|
||||
instance.setSubjectType(SUBJECT_TYPE_STORE);
|
||||
instance.setSubjectId(storeId);
|
||||
instance.setCertificateType(certificateType);
|
||||
instance.setEnabledMark(0);
|
||||
instance.setTemplateId("");
|
||||
instance.setCreatorUserId(UserProvider.getLoginUserId());
|
||||
instance.setCreatorTime(new Date());
|
||||
instance.setLastModifyUserId(UserProvider.getLoginUserId());
|
||||
instance.setLastModifyTime(new Date());
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化门店证照实例字段。
|
||||
*/
|
||||
private void normalizeStoreInstance(CertificateInstanceEntity instance, String storeId, String certificateType) {
|
||||
instance.setSubjectType(SUBJECT_TYPE_STORE);
|
||||
instance.setSubjectId(storeId);
|
||||
instance.setCertificateType(certificateType);
|
||||
if (instance.getEnabledMark() == null) {
|
||||
instance.setEnabledMark(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存或更新证照实例。
|
||||
*/
|
||||
private void saveOrUpdateInstance(CertificateInstanceEntity instance) {
|
||||
if(StringUtils.isNotBlank(instance.getId())){
|
||||
updateInstanceByWrapper(instance);
|
||||
return;
|
||||
}
|
||||
instance.setId(FtbUtil.getId());
|
||||
try {
|
||||
certificateInstanceMapper.insert(instance);
|
||||
} catch (DuplicateKeyException e) {
|
||||
updateInstance(instance);
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
if (isDuplicateKeyException(e)) {
|
||||
updateInstance(instance);
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
if (isDuplicateKeyException(e)) {
|
||||
updateInstance(instance);
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
// catch (SQLIntegrityConstraintViolationException e){
|
||||
// String msg = e.getMessage();
|
||||
// if (msg.contains("Duplicate entry")){
|
||||
// updateInstance(instance);
|
||||
// return;
|
||||
// }
|
||||
// throw e;
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断异常链中是否包含唯一键冲突。
|
||||
* 兼容 Seata/MyBatis 对 JDBC 异常的包装场景。
|
||||
*/
|
||||
private boolean isDuplicateKeyException(Throwable throwable) {
|
||||
Throwable current = throwable;
|
||||
while (current != null) {
|
||||
if (current instanceof DuplicateKeyException || current instanceof SQLIntegrityConstraintViolationException) {
|
||||
return true;
|
||||
}
|
||||
String message = current.getMessage();
|
||||
if (StringUtils.isNotBlank(message)
|
||||
&& StringUtils.containsIgnoreCase(message, "Duplicate entry")
|
||||
&& StringUtils.containsIgnoreCase(message, "for key")) {
|
||||
return true;
|
||||
}
|
||||
current = current.getCause();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateInstance(CertificateInstanceEntity instance) {
|
||||
if(Objects.isNull(instance)){
|
||||
return;
|
||||
}
|
||||
CertificateInstanceEntity dbInstance = findLatestByStoreAndType(instance.getSubjectId(), instance.getCertificateType(),instance.getTemplateId());
|
||||
if(Objects.isNull(dbInstance)){
|
||||
log.error("updateInstance fail.findLatestByStoreAndType null.instance:{}",instance);
|
||||
return;
|
||||
}
|
||||
instance.setId(dbInstance.getId());
|
||||
updateInstanceByWrapper(instance);
|
||||
}
|
||||
|
||||
private void updateInstanceByWrapper(CertificateInstanceEntity instance) {
|
||||
LambdaUpdateWrapper<CertificateInstanceEntity> updateWrapper = new LambdaUpdateWrapper<CertificateInstanceEntity>().eq(CertificateInstanceEntity::getId,instance.getId())
|
||||
.set(CertificateInstanceEntity::getCertificateImage, instance.getCertificateImage())
|
||||
.set(CertificateInstanceEntity::getIssueDate, instance.getIssueDate())
|
||||
.set(CertificateInstanceEntity::getExpireDate, instance.getExpireDate())
|
||||
.set(CertificateInstanceEntity::getExpireTimestamp, instance.getExpireTimestamp())
|
||||
.set(CertificateInstanceEntity::getStatus, instance.getStatus())
|
||||
.set(CertificateInstanceEntity::getLastModifyTime, instance.getLastModifyTime())
|
||||
.set(CertificateInstanceEntity::getLastModifyUserId, instance.getLastModifyUserId())
|
||||
.set(CertificateInstanceEntity::getEnabledMark, instance.getEnabledMark())
|
||||
.set(CertificateInstanceEntity::getCreatorTime, instance.getCreatorTime())
|
||||
.set(CertificateInstanceEntity::getCreatorUserId, instance.getCreatorUserId())
|
||||
.set(CertificateInstanceEntity::getStoreDisable,instance.getStoreDisable());
|
||||
Integer templateStatus = instance.getTemplateStatus();
|
||||
if(Objects.nonNull(templateStatus)){
|
||||
updateWrapper.set(CertificateInstanceEntity::getTemplateStatus,templateStatus);
|
||||
}
|
||||
int r = certificateInstanceMapper.update(null,updateWrapper);
|
||||
if(r<=0){
|
||||
log.error("saveOrUpdateInstance insert fail.update also fail.instance:{}",instance);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存营业执照扩展表。
|
||||
*/
|
||||
private void upsertBusinessLicenseExt(String instanceId, CertificateAppBusinessLicenseUpdateReq req, Date establishDate) {
|
||||
CertificateBusinessLicenseExtEntity extEntity = new CertificateBusinessLicenseExtEntity();
|
||||
extEntity.setId(FtbUtil.getId());
|
||||
extEntity.setInstanceId(instanceId);
|
||||
extEntity.setEnabledMark(0);
|
||||
fillBusinessExt(extEntity, req, establishDate);
|
||||
try {
|
||||
certificateBusinessLicenseExtMapper.insert(extEntity);
|
||||
}catch (DuplicateKeyException e){
|
||||
int r = certificateBusinessLicenseExtMapper.update(null,new LambdaUpdateWrapper<CertificateBusinessLicenseExtEntity>()
|
||||
.eq(CertificateBusinessLicenseExtEntity::getInstanceId,instanceId)
|
||||
.eq(CertificateBusinessLicenseExtEntity::getEnabledMark,0)
|
||||
.set(CertificateBusinessLicenseExtEntity::getCompanyName,extEntity.getCompanyName())
|
||||
.set(CertificateBusinessLicenseExtEntity::getCompanyAddress,extEntity.getCompanyAddress())
|
||||
.set(CertificateBusinessLicenseExtEntity::getLegalRepresentative,extEntity.getLegalRepresentative())
|
||||
.set(CertificateBusinessLicenseExtEntity::getEstablishDate,extEntity.getEstablishDate())
|
||||
.set(CertificateBusinessLicenseExtEntity::getBusinessScope,extEntity.getBusinessScope())
|
||||
.set(CertificateBusinessLicenseExtEntity::getCreatorTime,extEntity.getCreatorTime())
|
||||
.set(CertificateBusinessLicenseExtEntity::getCreatorUserId,extEntity.getCreatorUserId())
|
||||
.set(CertificateBusinessLicenseExtEntity::getLastModifyTime,extEntity.getLastModifyTime())
|
||||
.set(CertificateBusinessLicenseExtEntity::getLastModifyUserId,extEntity.getLastModifyUserId())
|
||||
);
|
||||
if(r <= 0){
|
||||
log.error("upsertBusinessLicenseExt insert fail.update row count is:{}.instanceId:{},extEntity:{}",r,instanceId,extEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存食品经营许可证扩展表。
|
||||
*/
|
||||
private void upsertHygieneLicenseExt(String instanceId, CertificateAppHygieneLicenseUpdateReq req) {
|
||||
CertificateHygieneLicenseExtEntity extEntity = findHygieneExt(instanceId);
|
||||
if (extEntity == null) {
|
||||
extEntity = new CertificateHygieneLicenseExtEntity();
|
||||
extEntity.setId(FtbUtil.getId());
|
||||
extEntity.setInstanceId(instanceId);
|
||||
extEntity.setEnabledMark(0);
|
||||
extEntity.setBusinessProject(trimToNull(req.getBusinessProject()));
|
||||
certificateHygieneLicenseExtMapper.insert(extEntity);
|
||||
return;
|
||||
}
|
||||
extEntity.setBusinessProject(trimToNull(req.getBusinessProject()));
|
||||
certificateHygieneLicenseExtMapper.updateById(extEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写门店自定义证照明细。
|
||||
*/
|
||||
private void rewriteCustomItems(String instanceId, List<CertificateInstanceItemReq> itemList) {
|
||||
LambdaQueryWrapper<CertificateInstanceItemEntity> deleteWrapper = Wrappers.lambdaQuery();
|
||||
deleteWrapper.eq(CertificateInstanceItemEntity::getInstanceId, instanceId);
|
||||
certificateInstanceItemMapper.delete(deleteWrapper);
|
||||
|
||||
List<CertificateInstanceItemReq> safeItemList = itemList == null ? Collections.emptyList() : itemList;
|
||||
long sort = 1L;
|
||||
for (CertificateInstanceItemReq itemReq : safeItemList) {
|
||||
if (itemReq == null || StrUtil.isBlank(itemReq.getItemName())) {
|
||||
continue;
|
||||
}
|
||||
CertificateInstanceItemEntity itemEntity = new CertificateInstanceItemEntity();
|
||||
itemEntity.setId(FtbUtil.getId());
|
||||
itemEntity.setInstanceId(instanceId);
|
||||
itemEntity.setTemplateItemId(trimToNull(itemReq.getTemplateItemId()));
|
||||
itemEntity.setItemName(trimToNull(itemReq.getItemName()));
|
||||
itemEntity.setItemType(itemReq.getItemType());
|
||||
itemEntity.setItemValue(trimToNull(itemReq.getItemValue()));
|
||||
itemEntity.setSorts(itemReq.getSorts() == null ? sort : itemReq.getSorts());
|
||||
itemEntity.setEnabledMark(0);
|
||||
certificateInstanceItemMapper.insert(itemEntity);
|
||||
sort++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询营业执照扩展数据。
|
||||
*/
|
||||
private CertificateBusinessLicenseExtEntity findBusinessExt(String instanceId) {
|
||||
LambdaQueryWrapper<CertificateBusinessLicenseExtEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(CertificateBusinessLicenseExtEntity::getInstanceId, instanceId);
|
||||
wrapper.eq(CertificateBusinessLicenseExtEntity::getEnabledMark, 0);
|
||||
wrapper.orderByDesc(CertificateBusinessLicenseExtEntity::getLastModifyTime);
|
||||
wrapper.orderByDesc(CertificateBusinessLicenseExtEntity::getCreatorTime);
|
||||
List<CertificateBusinessLicenseExtEntity> extList = certificateBusinessLicenseExtMapper.selectList(wrapper);
|
||||
return CollUtil.isEmpty(extList) ? null : extList.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询食品经营许可证扩展数据。
|
||||
*/
|
||||
private CertificateHygieneLicenseExtEntity findHygieneExt(String instanceId) {
|
||||
LambdaQueryWrapper<CertificateHygieneLicenseExtEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(CertificateHygieneLicenseExtEntity::getInstanceId, instanceId);
|
||||
wrapper.eq(CertificateHygieneLicenseExtEntity::getEnabledMark, 0);
|
||||
wrapper.orderByDesc(CertificateHygieneLicenseExtEntity::getLastModifyTime);
|
||||
wrapper.orderByDesc(CertificateHygieneLicenseExtEntity::getCreatorTime);
|
||||
List<CertificateHygieneLicenseExtEntity> extList = certificateHygieneLicenseExtMapper.selectList(wrapper);
|
||||
return CollUtil.isEmpty(extList) ? null : extList.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将自定义证照实例转换为查询返回对象。
|
||||
*/
|
||||
private CertificateAppStoreCustomUpdateReq convertStoreCustomCertificate(
|
||||
CertificateInstanceEntity instance,
|
||||
Map<String, List<CertificateInstanceItemEntity>> itemMap) {
|
||||
CertificateAppStoreCustomUpdateReq result = new CertificateAppStoreCustomUpdateReq();
|
||||
result.setCertificateInstanceId(instance.getId());
|
||||
result.setExpireDate(formatDate(instance.getExpireDate()));
|
||||
result.setTemplateId(instance.getTemplateId());
|
||||
|
||||
List<CertificateInstanceItemEntity> itemEntities = itemMap.getOrDefault(instance.getId(), Collections.emptyList());
|
||||
if (CollUtil.isEmpty(itemEntities)) {
|
||||
return result;
|
||||
}
|
||||
result.setItemList(itemEntities.stream().map(entity -> {
|
||||
CertificateInstanceItemReq itemReq = new CertificateInstanceItemReq();
|
||||
itemReq.setTemplateItemId(entity.getTemplateItemId());
|
||||
itemReq.setItemName(entity.getItemName());
|
||||
itemReq.setItemType(entity.getItemType());
|
||||
itemReq.setItemValue(entity.getItemValue());
|
||||
itemReq.setSorts(entity.getSorts());
|
||||
return itemReq;
|
||||
}).filter(Objects::nonNull).collect(Collectors.toList()));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充营业执照扩展字段。
|
||||
*/
|
||||
private void fillBusinessExt(CertificateBusinessLicenseExtEntity extEntity, CertificateAppBusinessLicenseUpdateReq req, Date establishDate) {
|
||||
extEntity.setCompanyName(trimToNull(req.getCompanyName()));
|
||||
extEntity.setLegalRepresentative(trimToNull(req.getLegalRepresentative()));
|
||||
extEntity.setEstablishDate(establishDate);
|
||||
extEntity.setBusinessScope(trimToNull(req.getBusinessScope()));
|
||||
extEntity.setCompanyAddress(req.getAddress());
|
||||
extEntity.setCreatorTime(new Date());
|
||||
extEntity.setCreatorUserId(UserProvider.getLoginUserId());
|
||||
extEntity.setLastModifyTime(new Date());
|
||||
extEntity.setLastModifyUserId(UserProvider.getLoginUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析日期文本,格式为 yyyy-MM-dd。
|
||||
*/
|
||||
private Date parseDate(String dateText, String fieldName) {
|
||||
if (StrUtil.isBlank(dateText)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return DateUtil.parseDate(StrUtil.trim(dateText));
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException(fieldName + "格式不正确,正确格式为yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期格式化为 yyyy-MM-dd 字符串。
|
||||
*/
|
||||
private String formatDate(Date date) {
|
||||
if (date == null) {
|
||||
return null;
|
||||
}
|
||||
return DateUtil.formatDate(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据结束时间计算证照状态。
|
||||
*/
|
||||
private Integer calculateStatus(Integer isLongTerm, Date expireDate) {
|
||||
if (Integer.valueOf(1).equals(isLongTerm)) {
|
||||
return STATUS_NORMAL;
|
||||
}
|
||||
if (expireDate == null) {
|
||||
return STATUS_MISSING;
|
||||
}
|
||||
Date today = DateUtil.beginOfDay(DateUtil.date());
|
||||
Date target = DateUtil.beginOfDay(expireDate);
|
||||
if (target.before(today)) {
|
||||
return STATUS_EXPIRED;
|
||||
}
|
||||
long daysDiff = DateUtil.betweenDay(today, target, false);
|
||||
if (daysDiff <= NEAR_EXPIRE_DAYS) {
|
||||
return STATUS_NEAR_EXPIRE;
|
||||
}
|
||||
return STATUS_NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串去首尾空格,空串转为null。
|
||||
*/
|
||||
private String trimToNull(String value) {
|
||||
String trimValue = StrUtil.trim(value);
|
||||
return StrUtil.isBlank(trimValue) ? null : trimValue;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user