新增文书送达、文书送达记录、字典查询、文书信息等接口
This commit is contained in:
parent
8383232e5c
commit
a7420da684
|
|
@ -0,0 +1,139 @@
|
||||||
|
package com.aisino.iles.lawenforcement.service;
|
||||||
|
|
||||||
|
import com.aisino.iles.common.util.PageableHelper;
|
||||||
|
import com.aisino.iles.lawenforcement.model.DeliveryMethod;
|
||||||
|
import com.aisino.iles.lawenforcement.model.query.DeliveryQuery;
|
||||||
|
import com.aisino.iles.lawenforcement.repository.DeliveryMethodRepository;
|
||||||
|
import com.smartlx.sso.client.model.RemoteUserInfo;
|
||||||
|
import jakarta.persistence.criteria.Predicate;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 送达方式服务类
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class DeliveryMethodService {
|
||||||
|
private final DeliveryMethodRepository deliveryMethodRepo;
|
||||||
|
|
||||||
|
public DeliveryMethodService(DeliveryMethodRepository deliveryMethodRepo) {
|
||||||
|
this.deliveryMethodRepo = deliveryMethodRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存送达方式信息
|
||||||
|
*
|
||||||
|
* @param deliveryMethod 送达方式信息
|
||||||
|
* @return 保存后的送达方式信息
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public DeliveryMethod saveDeliveryMethod(DeliveryMethod deliveryMethod, RemoteUserInfo user, String type) {
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
if ("add".equals(type)) {
|
||||||
|
deliveryMethod.setIsDeleted(false);
|
||||||
|
deliveryMethod.setCreateTime(now);
|
||||||
|
if (null != user) {
|
||||||
|
deliveryMethod.setCreatedBy(user.getXm());
|
||||||
|
deliveryMethod.setCreatedAccountBy(user.getYhwybs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deliveryMethod.setUpdateTime(now);
|
||||||
|
return deliveryMethodRepo.save(deliveryMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询送达方式信息
|
||||||
|
*
|
||||||
|
* @param deliveryMethodId 送达方式ID
|
||||||
|
* @return 送达方式信息
|
||||||
|
*/
|
||||||
|
public Optional<DeliveryMethod> findDeliveryMethodById(String deliveryMethodId) {
|
||||||
|
return deliveryMethodRepo.findById(deliveryMethodId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据查询条件分页查询送达方式信息
|
||||||
|
*
|
||||||
|
* @param query 查询条件
|
||||||
|
* @return 分页送达方式信息
|
||||||
|
*/
|
||||||
|
public Page<DeliveryMethod> findDeliveryMethodPage(DeliveryQuery query) {
|
||||||
|
return deliveryMethodRepo.findAll(build(query),
|
||||||
|
PageableHelper.buildPageRequest(query.page(), query.pageSize(), "updateTime", "desc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建查询条件
|
||||||
|
*
|
||||||
|
* @param query 查询条件
|
||||||
|
* @return 规格
|
||||||
|
*/
|
||||||
|
private Specification<DeliveryMethod> build(DeliveryQuery query) {
|
||||||
|
return (root, criteriaQuery, criteriaBuilder) -> {
|
||||||
|
List<Predicate> predicates = new ArrayList<>();
|
||||||
|
Optional.ofNullable(query.getIsDeleted()).ifPresent(o -> predicates.add(criteriaBuilder.equal(root.get("isDeleted"), o)));
|
||||||
|
Optional.ofNullable(query.getMethodName()).filter(StringUtils::hasText).ifPresent(o -> predicates.add(criteriaBuilder.like(root.get("methodName"), "%" + o + "%")));
|
||||||
|
Optional.ofNullable(query.getDescription()).filter(StringUtils::hasText).ifPresent(o -> predicates.add(criteriaBuilder.like(root.get("description"), "%" + o + "%")));
|
||||||
|
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID删除送达方式信息
|
||||||
|
*
|
||||||
|
* @param deliveryMethodId 送达方式ID
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void deleteDeliveryMethodById(String deliveryMethodId) {
|
||||||
|
deliveryMethodRepo.findById(deliveryMethodId).ifPresent(deliveryMethod -> {
|
||||||
|
deliveryMethod.setIsDeleted(true);
|
||||||
|
deliveryMethod.setUpdateTime(LocalDateTime.now());
|
||||||
|
deliveryMethodRepo.save(deliveryMethod);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 送达方式是否存在
|
||||||
|
*
|
||||||
|
* @param deliveryMethodId 送达方式ID
|
||||||
|
* @return 是否存在
|
||||||
|
*/
|
||||||
|
public boolean existsDeliveryMethodById(String deliveryMethodId) {
|
||||||
|
return deliveryMethodRepo.existsById(deliveryMethodId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除送达方式
|
||||||
|
*
|
||||||
|
* @param itemIds 送达方式ID列表
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void deleteDeliveryMethodByIds(List<String> itemIds) {
|
||||||
|
deliveryMethodRepo.findAllById(itemIds).forEach(deliveryMethod -> {
|
||||||
|
deliveryMethod.setIsDeleted(true);
|
||||||
|
deliveryMethod.setUpdateTime(LocalDateTime.now());
|
||||||
|
deliveryMethodRepo.save(deliveryMethod);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据查询条件获取送达方式列表
|
||||||
|
*
|
||||||
|
* @param query 查询条件
|
||||||
|
* @return 送达方式集合
|
||||||
|
*/
|
||||||
|
public List<DeliveryMethod> getDeliveryMethodList(DeliveryQuery query) {
|
||||||
|
return deliveryMethodRepo.findAll(build(query));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,769 @@
|
||||||
|
package com.aisino.iles.lawenforcement.service;
|
||||||
|
|
||||||
|
import com.aisino.iles.common.model.enums.IndustryCategoryForFile;
|
||||||
|
import com.aisino.iles.common.service.FtpService;
|
||||||
|
import com.aisino.iles.common.util.BeanUtils;
|
||||||
|
import com.aisino.iles.common.util.KmsServer;
|
||||||
|
import com.aisino.iles.common.util.PageableHelper;
|
||||||
|
import com.aisino.iles.core.exception.BusinessError;
|
||||||
|
import com.aisino.iles.lawenforcement.model.*;
|
||||||
|
import com.aisino.iles.lawenforcement.model.dto.DeliveryRecordStatisticsDto;
|
||||||
|
import com.aisino.iles.lawenforcement.model.dto.DeliveryScenePicDto;
|
||||||
|
import com.aisino.iles.lawenforcement.model.query.DeliveryQuery;
|
||||||
|
import com.aisino.iles.lawenforcement.repository.AgencyRepository;
|
||||||
|
import com.aisino.iles.lawenforcement.repository.DeliveryRecordRepository;
|
||||||
|
import com.aisino.iles.lawenforcement.repository.MaterialsRepository;
|
||||||
|
import com.aisino.iles.lawenforcement.repository.SmsSendRecordRepository;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.smartlx.sso.client.model.RemoteUserInfo;
|
||||||
|
import jakarta.persistence.criteria.Predicate;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.http.*;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文书送达记录服务类
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class DeliveryRecordService {
|
||||||
|
private final DeliveryRecordRepository deliveryRecordRepo;
|
||||||
|
private final DeliveryMethodService deliveryMethodService;
|
||||||
|
private final AgencyRepository agencyRepo;
|
||||||
|
private final SmsSendRecordRepository smsSendRecordRepo;
|
||||||
|
private final MaterialsRepository materialsRepo;
|
||||||
|
private final RestTemplate restTemplate;
|
||||||
|
private final FtpService ftpService;
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
private final String deliveryUsername;
|
||||||
|
private final String deliveryPassword;
|
||||||
|
private final String publishSmsCallUrl;
|
||||||
|
private final String publishVoiceCallUrl;
|
||||||
|
|
||||||
|
public DeliveryRecordService(DeliveryRecordRepository deliveryRecordRepo,
|
||||||
|
DeliveryMethodService deliveryMethodService,
|
||||||
|
AgencyRepository agencyRepo,
|
||||||
|
SmsSendRecordRepository smsSendRecordRepo,
|
||||||
|
MaterialsRepository materialsRepo,
|
||||||
|
RestTemplate restTemplate,
|
||||||
|
FtpService ftpService,
|
||||||
|
ObjectMapper objectMapper,
|
||||||
|
@Value("${third-party.delivery.username}") String deliveryUsername,
|
||||||
|
@Value("${third-party.delivery.password}") String deliveryPassword,
|
||||||
|
@Value("${third-party.delivery.publish-sms-call-url}") String publishSmsCallUrl,
|
||||||
|
@Value("${third-party.delivery.publish-voice-call-url}") String publishVoiceCallUrl) {
|
||||||
|
this.deliveryRecordRepo = deliveryRecordRepo;
|
||||||
|
this.deliveryMethodService = deliveryMethodService;
|
||||||
|
this.agencyRepo = agencyRepo;
|
||||||
|
this.smsSendRecordRepo = smsSendRecordRepo;
|
||||||
|
this.materialsRepo = materialsRepo;
|
||||||
|
this.restTemplate = restTemplate;
|
||||||
|
this.ftpService = ftpService;
|
||||||
|
this.objectMapper = objectMapper;
|
||||||
|
this.deliveryUsername = deliveryUsername;
|
||||||
|
this.deliveryPassword = deliveryPassword;
|
||||||
|
this.publishSmsCallUrl = publishSmsCallUrl;
|
||||||
|
this.publishVoiceCallUrl = publishVoiceCallUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存文书送达记录信息
|
||||||
|
*
|
||||||
|
* @param deliveryRecord 文书送达记录信息
|
||||||
|
* @return 保存后的文书送达记录信息
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public DeliveryRecord saveDeliveryRecord(DeliveryRecord deliveryRecord, RemoteUserInfo user, String type) {
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
if ("add".equals(type)) {
|
||||||
|
deliveryRecord.setCreateTime(now);
|
||||||
|
deliveryRecord.setDeliveryStatus((short) 0);
|
||||||
|
if (null != user) {
|
||||||
|
deliveryRecord.setCreatedBy(user.getXm());
|
||||||
|
deliveryRecord.setCreatedAccountBy(user.getYhwybs());
|
||||||
|
}
|
||||||
|
} else if ("send".equals(type)) {
|
||||||
|
deliveryRecord.setDeliveryStatus((short) 1);
|
||||||
|
deliveryRecord.setSendTime(now);
|
||||||
|
}
|
||||||
|
deliveryRecord.setUpdateTime(now);
|
||||||
|
DeliveryRecord save = deliveryRecordRepo.save(deliveryRecord);
|
||||||
|
if ("add".equals(type) || "up".equals(type)) {
|
||||||
|
List<Materials> materialsList = deliveryRecord.getMaterials();
|
||||||
|
if (null != materialsList && !materialsList.isEmpty()) {
|
||||||
|
List<Materials> list = materialsRepo.findByLinkId(deliveryRecord.getDeliveryId());
|
||||||
|
List<String> newPics = list.stream().map(Materials::getSavePath).toList();
|
||||||
|
materialsList.stream().filter(o -> !newPics.contains(o.getSavePath()))
|
||||||
|
.forEach(materials -> {
|
||||||
|
materials.setLrsj(now);
|
||||||
|
String name = materials.getName();
|
||||||
|
materials.setFileType(StringUtils.hasText(name) ? name.split("\\.")[1] : null);
|
||||||
|
materials.setIsOriginal("1");
|
||||||
|
materials.setMaterialsTypeCode("3");
|
||||||
|
materials.setMaterialsTypeName("文书送达现场图片");
|
||||||
|
materials.setLinkId(save.getDeliveryId());
|
||||||
|
materials.setMaterialsId(null);
|
||||||
|
materialsRepo.save(materials);
|
||||||
|
});
|
||||||
|
List<String> paths = materialsList.stream().map(Materials::getSavePath).toList();
|
||||||
|
list.stream().filter(o -> !paths.contains(o.getSavePath())).forEach(o -> {
|
||||||
|
if (StringUtils.hasText(o.getSavePath()))
|
||||||
|
ftpService.deletePathFile(o.getSavePath());
|
||||||
|
materialsRepo.delete(o);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return save;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询文书送达记录信息
|
||||||
|
*
|
||||||
|
* @param deliveryRecordId 文书送达记录ID
|
||||||
|
* @return 文书送达记录信息
|
||||||
|
*/
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public Optional<DeliveryRecord> findDeliveryRecordById(String deliveryRecordId) {
|
||||||
|
return deliveryRecordRepo.findById(deliveryRecordId).map(this::itemDeliveryRecord).map(deliveryRecord -> {
|
||||||
|
deliveryRecord.setMaterials(materialsRepo.findByLinkId(deliveryRecord.getDeliveryId()).stream().peek(scene -> {
|
||||||
|
String url = scene.getSavePath();
|
||||||
|
if (StringUtils.hasText(url)) {
|
||||||
|
scene.setUrl(ftpService.getFileUrl(url));
|
||||||
|
scene.setDownloadUrl(ftpService.getFileDownloadUrl(url));
|
||||||
|
}
|
||||||
|
}).collect(Collectors.toList()));
|
||||||
|
return deliveryRecord;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public List<DeliveryRecord> findDeliveryRecordByIds(List<String> deliveryIds) {
|
||||||
|
return deliveryRecordRepo.findAllById(deliveryIds).stream().map(this::itemDeliveryRecord).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据查询条件分页查询文书送达记录信息
|
||||||
|
*
|
||||||
|
* @param query 查询条件
|
||||||
|
* @return 分页文书送达记录信息
|
||||||
|
*/
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public Page<DeliveryRecord> findDeliveryRecordPage(DeliveryQuery query) {
|
||||||
|
return deliveryRecordRepo.findAll(build(query), PageableHelper.buildPageRequest(query.page(), query.pageSize(), "updateTime", "desc"), "delivery_record-all").map(this::itemDeliveryRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeliveryRecord itemDeliveryRecord(DeliveryRecord deliveryRecord) {
|
||||||
|
if (null != deliveryRecord.getSendTime() && deliveryRecord.getDeliveryStatus() != 2) {
|
||||||
|
// 计算两个时间之间的小时差
|
||||||
|
Duration duration = Duration.between(deliveryRecord.getSendTime(), LocalDateTime.now());
|
||||||
|
long hours = duration.toHours();
|
||||||
|
deliveryRecord.setNeedCll(hours > 24);
|
||||||
|
}
|
||||||
|
return deliveryRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建查询条件
|
||||||
|
*
|
||||||
|
* @param query 查询条件
|
||||||
|
* @return 规格
|
||||||
|
*/
|
||||||
|
private Specification<DeliveryRecord> build(DeliveryQuery query) {
|
||||||
|
return (root, criteriaQuery, criteriaBuilder) -> {
|
||||||
|
List<Predicate> predicates = new ArrayList<>();
|
||||||
|
Optional.ofNullable(query.getAgencyCode()).filter(StringUtils::hasText)
|
||||||
|
.ifPresent(o -> predicates.add(criteriaBuilder.like(root.get(DeliveryRecord_.caseInfo).get(Case_.enforcementInfo).get(EnforcementInfo_.agency).get(Agency_.agencyCode),
|
||||||
|
com.aisino.iles.common.util.StringUtils.trimEven0(o) + "%")));
|
||||||
|
Optional.ofNullable(query.getCaseId()).filter(StringUtils::hasText).ifPresent(o -> predicates.add(criteriaBuilder.equal(root.get(DeliveryRecord_.caseId), o)));
|
||||||
|
Optional.ofNullable(query.getRecipientId()).filter(StringUtils::hasText).ifPresent(o -> predicates.add(criteriaBuilder.equal(root.get(DeliveryRecord_.recipientId), o)));
|
||||||
|
Optional.ofNullable(query.getDeliveryMethodId()).filter(StringUtils::hasText).ifPresent(o -> predicates.add(criteriaBuilder.equal(root.get(DeliveryRecord_.deliveryMethodId), o)));
|
||||||
|
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID删除文书送达记录信息
|
||||||
|
*
|
||||||
|
* @param deliveryRecordId 文书送达记录ID
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void deleteDeliveryRecordById(String deliveryRecordId) {
|
||||||
|
deliveryRecordRepo.deleteById(deliveryRecordId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文书送达记录是否存在
|
||||||
|
*
|
||||||
|
* @param deliveryRecordId 文书送达记录ID
|
||||||
|
* @return 是否存在
|
||||||
|
*/
|
||||||
|
public Boolean existsDeliveryRecordById(String deliveryRecordId) {
|
||||||
|
return deliveryRecordRepo.existsById(deliveryRecordId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除文书送达记录
|
||||||
|
*
|
||||||
|
* @param itemIds 文书送达记录ID列表
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void deleteDeliveryRecordByIds(List<String> itemIds) {
|
||||||
|
deliveryRecordRepo.deleteAllById(itemIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计
|
||||||
|
*
|
||||||
|
* @param query 查询参数
|
||||||
|
* @param user 用户
|
||||||
|
* @return 统计结果
|
||||||
|
*/
|
||||||
|
public List<Map<String, Object>> statistics(DeliveryQuery query, RemoteUserInfo user) {
|
||||||
|
String agencyCode = query.getAgencyCode();
|
||||||
|
if (!StringUtils.hasText(agencyCode)) agencyCode = user.getGajgjgdm();
|
||||||
|
Integer agencyLevel = query.getAgencyLevel();
|
||||||
|
if (null == agencyLevel)
|
||||||
|
agencyLevel = agencyRepo.findByAgencyCode(agencyCode).map(Agency::getAgencyLevel).orElseThrow(() -> new BusinessError("当前用户没有匹配到有效的机构信息"));
|
||||||
|
String code = com.aisino.iles.common.util.StringUtils.trimEven0(agencyCode) + "%";
|
||||||
|
List<Agency> agencyList = agencyRepo.findLikeAgencyCode(code, agencyLevel).stream().filter(o -> !"01610100000000001".equals(o.getAgencyCode())).toList();
|
||||||
|
List<DeliveryRecordStatisticsDto> list = deliveryRecordRepo.statistics(code);
|
||||||
|
Map<String, List<DeliveryRecordStatisticsDto>> listMap = list.stream().collect(Collectors.groupingBy(DeliveryRecordStatisticsDto::getAgencyCode));
|
||||||
|
Map<String, Map<String, Object>> mm = new HashMap<>();
|
||||||
|
Set<String> map = categories();
|
||||||
|
listMap.forEach((key, val) -> {
|
||||||
|
Map<String, Object> resMap = new HashMap<>();
|
||||||
|
map.forEach(k -> {
|
||||||
|
val.stream()
|
||||||
|
.filter(dto -> k.equals(dto.getDeliveryMethodId()))
|
||||||
|
.findFirst()
|
||||||
|
.ifPresentOrElse(
|
||||||
|
dto -> resMap.put(k, dto.getNum()),
|
||||||
|
() -> resMap.put(k, 0L)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
long sum = resMap.values().stream()
|
||||||
|
.mapToLong(o -> Long.parseLong(String.valueOf(o)))
|
||||||
|
.sum();
|
||||||
|
resMap.put("total", sum);
|
||||||
|
mm.put(key, resMap);
|
||||||
|
});
|
||||||
|
return agencyList.stream().map(o -> {
|
||||||
|
Map<String, Object> resMap = new HashMap<>();
|
||||||
|
resMap.put("agencyCode", o.getAgencyCode());
|
||||||
|
resMap.put("agencyName", o.getAgencyName());
|
||||||
|
resMap.put("agencyLevel", o.getAgencyLevel());
|
||||||
|
resMap.put("hasChildren", o.getLeaf() ? 0 : 1);
|
||||||
|
Set<String> set = mm.keySet().stream().filter(v -> v.length() >= o.getAgencySimpleCode().length())
|
||||||
|
.filter(v -> Objects.equals(v.substring(0, o.getAgencySimpleCode().length()), o.getAgencySimpleCode()))//过滤掉截取后不相同的数据
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
// 累加相同属性的值
|
||||||
|
Map<String, Object> mapSum = set.stream()
|
||||||
|
.flatMap(str -> mm.get(str).entrySet().stream())
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
Map.Entry::getKey,
|
||||||
|
Map.Entry::getValue,
|
||||||
|
(v1, v2) -> (Long) v1 + (Long) v2
|
||||||
|
));
|
||||||
|
if (mapSum.isEmpty()) {
|
||||||
|
map.forEach(k -> resMap.put(k, 0L));
|
||||||
|
resMap.put("total", 0L);
|
||||||
|
} else {
|
||||||
|
resMap.putAll(mapSum);
|
||||||
|
}
|
||||||
|
return resMap;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> categories() {
|
||||||
|
DeliveryQuery deliveryQuery = new DeliveryQuery();
|
||||||
|
deliveryQuery.setIsDeleted(false);
|
||||||
|
deliveryQuery.setEnabled(true);
|
||||||
|
return deliveryMethodService.getDeliveryMethodList(deliveryQuery).stream().map(DeliveryMethod::getDeliveryMethodId).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下发机器人语音叫应
|
||||||
|
* 请求示例:
|
||||||
|
* {
|
||||||
|
* "JYBT": "日常叫应",
|
||||||
|
* "JYNR": "请立即应答",
|
||||||
|
* "YPDZ": "https://ip:port/static/audio_1.mp3",
|
||||||
|
* "TZRY": [ ... ],
|
||||||
|
* "TZDC": { ... },
|
||||||
|
* "JZSJ": { ... },
|
||||||
|
* "LYZH": "test001"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @param deliveryIds 送达记录ID列表
|
||||||
|
* @param user 当前用户
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void publishSmsCall(List<String> deliveryIds, RemoteUserInfo user) {
|
||||||
|
String auth = deliveryUsername + ":" + deliveryPassword;
|
||||||
|
String authHeader = "Basic " + Base64.getEncoder().encodeToString(auth.getBytes(US_ASCII));
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.set("Authorization", authHeader);
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
List<DeliveryRecord> list = findDeliveryRecordByIds(deliveryIds);
|
||||||
|
if (list.isEmpty())
|
||||||
|
throw new BusinessError("送达记录不存在");
|
||||||
|
list.stream().collect(Collectors.groupingBy(DeliveryRecord::getRecipientId)).forEach((recipientId, l) -> {
|
||||||
|
l.stream().collect(Collectors.groupingBy(DeliveryRecord::getCaseId)).forEach((caseid, ll) -> {
|
||||||
|
PublishSmsCallRequest smsRequest = new PublishSmsCallRequest();
|
||||||
|
Case caseInfo = ll.stream().map(DeliveryRecord::getCaseInfo).findFirst().get();
|
||||||
|
String jybt = "《" + caseInfo.getCaseName() + "》";
|
||||||
|
String jynr = "《" + caseInfo.getCaseName() + "》的文书已通过短信送达,具体内容请查看附件.";
|
||||||
|
smsRequest.setJybt(jybt);
|
||||||
|
smsRequest.setJynr(jynr);
|
||||||
|
List<Attachment> attachments = new ArrayList<>();
|
||||||
|
ll.stream().map(DeliveryRecord::getDocumentInfo).filter(documentInfo -> StringUtils.hasText(documentInfo.getFilePath()))
|
||||||
|
.forEach(documentInfo -> {
|
||||||
|
Attachment attachment = new Attachment();
|
||||||
|
attachment.setWjbh(documentInfo.getDocumentId());
|
||||||
|
String url = ftpService.getFileUrl(documentInfo.getFilePath(), DateUtils.addDays(new Date(), 2));
|
||||||
|
attachment.setWjdz(url);
|
||||||
|
attachment.setWjlx("4");
|
||||||
|
attachments.add(attachment);
|
||||||
|
});
|
||||||
|
if (!attachments.isEmpty()) smsRequest.setFjzl(attachments);
|
||||||
|
RecipientInfo recipientInfo = l.stream().map(DeliveryRecord::getRecipientInfo).findFirst().get();
|
||||||
|
NotifyPerson notifyPerson = new NotifyPerson();
|
||||||
|
notifyPerson.setRybh(recipientInfo.getRecipientId());
|
||||||
|
notifyPerson.setRyxm(recipientInfo.getName());
|
||||||
|
notifyPerson.setYddh(recipientInfo.getPhone());
|
||||||
|
smsRequest.setTzry(List.of(notifyPerson));
|
||||||
|
NotifySupervision tzdc = new NotifySupervision();//通知督促
|
||||||
|
tzdc.setSjjg(60);
|
||||||
|
tzdc.setDccs(1);
|
||||||
|
smsRequest.setTzdc(tzdc);
|
||||||
|
smsRequest.setDcfs("1");
|
||||||
|
Deadline deadline = new Deadline();//截止时间
|
||||||
|
deadline.setSjjg(24);
|
||||||
|
deadline.setSjdw("3");
|
||||||
|
smsRequest.setJzsj(deadline);
|
||||||
|
smsRequest.setLyzh(deliveryUsername);
|
||||||
|
HttpEntity<PublishSmsCallRequest> requestEntity = new HttpEntity<>(smsRequest, headers);
|
||||||
|
String smsUrl = publishSmsCallUrl;
|
||||||
|
try {
|
||||||
|
log.info("Publishing SMS to URL: {} with request: {}", smsUrl, objectMapper.writeValueAsString(smsRequest));
|
||||||
|
ResponseEntity<String> response = restTemplate.exchange(smsUrl, HttpMethod.POST, requestEntity, String.class);
|
||||||
|
log.info("status:{}", response.getStatusCode());
|
||||||
|
if (response.getStatusCode() == HttpStatus.OK) {
|
||||||
|
String body = response.getBody();
|
||||||
|
// String body = "{\"code\":0,\"msg\":\"请求成功\",\"data\":{\"JYBH\":\"460779fbe1d74eea90c9bac61dfe4b63\"}}";
|
||||||
|
log.info("SMS publish response: {}", body);
|
||||||
|
PublishVoiceCallResponse callResponse = objectMapper.readValue(body, PublishVoiceCallResponse.class);
|
||||||
|
if (0 == callResponse.getCode()) {
|
||||||
|
ll.forEach(deliveryRecord -> {
|
||||||
|
String jybh = callResponse.getData().getJybh();
|
||||||
|
saveDeliveryRecord(deliveryRecord, user, "send");
|
||||||
|
SmsSendRecord smsSendRecord = new SmsSendRecord();
|
||||||
|
smsSendRecord.setJybt(jybt);
|
||||||
|
smsSendRecord.setJynr(jynr);
|
||||||
|
smsSendRecord.setJybh(jybh);
|
||||||
|
smsSendRecord.setYddh(recipientInfo.getPhone());
|
||||||
|
smsSendRecord.setDeliveryId(deliveryRecord.getDeliveryId());
|
||||||
|
smsSendRecord.setOperator(user.getXm());
|
||||||
|
smsSendRecord.setOperatorAccount(user.getYhwybs());
|
||||||
|
smsSendRecord.setSendTime(LocalDateTime.now());
|
||||||
|
// 检验加密签名保存
|
||||||
|
Optional.ofNullable(smsSendRecord.getYddh()).filter(StringUtils::hasText).ifPresent(s -> smsSendRecord.setSginData(KmsServer.kmsSign(s)));
|
||||||
|
smsSendRecordRepo.save(smsSendRecord);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("SMS publish completed");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error publishing SMS: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下发机器人语音叫应
|
||||||
|
* 请求示例:
|
||||||
|
* {
|
||||||
|
* "JYBT": "日常叫应",
|
||||||
|
* "JYNR": "请立即应答",
|
||||||
|
* "YPDZ": "https://ip:port/static/audio_1.mp3",
|
||||||
|
* "TZRY": [ ... ],
|
||||||
|
* "TZDC": { ... },
|
||||||
|
* "JZSJ": { ... },
|
||||||
|
* "LYZH": "test001"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @param deliveryRecord 送达记录
|
||||||
|
* @param user 当前用户
|
||||||
|
* 外部接口返回的调用结果
|
||||||
|
*/
|
||||||
|
public void publishVoiceCall(DeliveryRecord deliveryRecord, RemoteUserInfo user) {
|
||||||
|
PublishVoiceCallRequest voiceRequest = new PublishVoiceCallRequest();
|
||||||
|
String auth = deliveryUsername + ":" + deliveryPassword;
|
||||||
|
String authHeader = "Basic " + Base64.getEncoder().encodeToString(auth.getBytes(US_ASCII));
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.set("Authorization", authHeader);
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
String jybt = deliveryRecord.getCaseInfo().getCaseName();
|
||||||
|
RecipientInfo recipientInfo = deliveryRecord.getRecipientInfo();
|
||||||
|
String jynr = jybt + "的文书已通过短信送达,请尽快处理";
|
||||||
|
voiceRequest.setJybt(jybt);
|
||||||
|
voiceRequest.setJynr(jynr);
|
||||||
|
NotifyPerson notifyPerson = new NotifyPerson();
|
||||||
|
notifyPerson.setRybh(recipientInfo.getRecipientId());
|
||||||
|
notifyPerson.setRyxm(recipientInfo.getName());
|
||||||
|
notifyPerson.setYddh(recipientInfo.getPhone());
|
||||||
|
voiceRequest.setTzry(List.of(notifyPerson));
|
||||||
|
voiceRequest.setLyzh(deliveryUsername);
|
||||||
|
HttpEntity<PublishVoiceCallRequest> requestEntity = new HttpEntity<>(voiceRequest, headers);
|
||||||
|
try {
|
||||||
|
log.info("Publishing Voice call to URL: {} with request: {}", publishVoiceCallUrl, objectMapper.writeValueAsString(voiceRequest));
|
||||||
|
ResponseEntity<String> response = restTemplate.exchange(publishVoiceCallUrl, HttpMethod.POST, requestEntity, String.class);
|
||||||
|
log.info("Voice call publish response: {}", response.getBody());
|
||||||
|
if (response.getStatusCode() == HttpStatus.OK) {
|
||||||
|
String body = response.getBody();
|
||||||
|
log.info("Voice call response: {}", body);
|
||||||
|
PublishVoiceCallResponse callResponse = objectMapper.readValue(body, PublishVoiceCallResponse.class);
|
||||||
|
if (0 == callResponse.getCode()) {
|
||||||
|
String jybh = callResponse.getData().getJybh();
|
||||||
|
SmsSendRecord smsSendRecord = new SmsSendRecord();
|
||||||
|
smsSendRecord.setJybt(jybt);
|
||||||
|
smsSendRecord.setJynr(jynr);
|
||||||
|
smsSendRecord.setJybh(jybh);
|
||||||
|
smsSendRecord.setYddh(recipientInfo.getPhone());
|
||||||
|
smsSendRecord.setDeliveryId(deliveryRecord.getDeliveryId());
|
||||||
|
smsSendRecord.setOperator(user.getXm());
|
||||||
|
smsSendRecord.setOperatorAccount(user.getYhwybs());
|
||||||
|
smsSendRecord.setSendTime(LocalDateTime.now());
|
||||||
|
// 检验加密签名保存
|
||||||
|
Optional.ofNullable(smsSendRecord.getYddh()).filter(StringUtils::hasText).ifPresent(s -> smsSendRecord.setSginData(KmsServer.kmsSign(s)));
|
||||||
|
smsSendRecordRepo.save(smsSendRecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error publishing voice call: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信状态回调
|
||||||
|
*
|
||||||
|
* @param smsSendRecord 短信发送记录
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void smsStatusCallback(SmsSendRecord smsSendRecord) {
|
||||||
|
smsSendRecordRepo.findByJybh(smsSendRecord.getJybh()).forEach(o -> {
|
||||||
|
BeanUtils.copyNoNullProperties(smsSendRecord, o);
|
||||||
|
// 检验加密签名保存
|
||||||
|
Optional.ofNullable(smsSendRecord.getYddh()).filter(StringUtils::hasText).ifPresent(s -> o.setSginData(KmsServer.kmsSign(s)));
|
||||||
|
smsSendRecordRepo.save(o);
|
||||||
|
if ("0401".equals(smsSendRecord.getTzztCode())) {
|
||||||
|
deliveryRecordRepo.findById(o.getDeliveryId()).ifPresent(deliveryRecord -> {
|
||||||
|
deliveryRecord.setDeliveryStatus((short) 2);
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
deliveryRecord.setUpdateTime(now);
|
||||||
|
deliveryRecord.setFinishTime(now);
|
||||||
|
deliveryRecordRepo.save(deliveryRecord);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// DTO用于下发短信叫应
|
||||||
|
@Data
|
||||||
|
public static class PublishSmsCallRequest {
|
||||||
|
/**
|
||||||
|
* 叫应标题, 必填, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("JYBT")
|
||||||
|
private String jybt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 叫应内容, 必填, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("JYNR")
|
||||||
|
private String jynr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应答方式, 可选, 默认为0 (0:按键应答, 1:视频应答)
|
||||||
|
*/
|
||||||
|
@JsonProperty("YDFS")
|
||||||
|
private String ydfs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 叫应地点, 可选, Object 类型
|
||||||
|
*/
|
||||||
|
@JsonProperty("JYDD")
|
||||||
|
private Location jydd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 附件资料, 可选, List<Attachment>
|
||||||
|
*/
|
||||||
|
@JsonProperty("FJZL")
|
||||||
|
private List<Attachment> fjzl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通知人员, 必填, List<NotifyPerson>
|
||||||
|
*/
|
||||||
|
@JsonProperty("TZRY")
|
||||||
|
private List<NotifyPerson> tzry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通知督促, 可选, Object 类型
|
||||||
|
*/
|
||||||
|
@JsonProperty("TZDC")
|
||||||
|
private NotifySupervision tzdc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 督促方式, 可选, 默认0(0:普通,1:语音,2:视频)
|
||||||
|
*/
|
||||||
|
@JsonProperty("DCFS")
|
||||||
|
private String dcfs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 截止时间, 可选, Object 类型
|
||||||
|
*/
|
||||||
|
@JsonProperty("JZSJ")
|
||||||
|
private Deadline jzsj;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超时提醒, 可选, List<TimeoutRemind>
|
||||||
|
*/
|
||||||
|
@JsonProperty("CSTX")
|
||||||
|
private List<TimeoutRemind> cstx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 来源帐号, 必填, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("LYZH")
|
||||||
|
private String lyzh;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DTO用于下发机器人语音叫应
|
||||||
|
@Data
|
||||||
|
public static class PublishVoiceCallRequest {
|
||||||
|
/**
|
||||||
|
* 叫应标题, 必填, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("JYBT")
|
||||||
|
private String jybt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 叫应内容, 可选, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("JYNR")
|
||||||
|
private String jynr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频地址, 可选, String (url 地址)
|
||||||
|
*/
|
||||||
|
@JsonProperty("YPDZ")
|
||||||
|
private String ypdz;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通知人员, 必填, List<NotifyPerson>
|
||||||
|
*/
|
||||||
|
@JsonProperty("TZRY")
|
||||||
|
private List<NotifyPerson> tzry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通知督促, 可选, Object 类型
|
||||||
|
*/
|
||||||
|
@JsonProperty("TZDC")
|
||||||
|
private NotifySupervision tzdc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 截止时间, 可选, Object 类型
|
||||||
|
*/
|
||||||
|
@JsonProperty("JZSJ")
|
||||||
|
private Deadline jzsj;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 来源帐号, 必填, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("LYZH")
|
||||||
|
private String lyzh;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class PublishVoiceCallResponse {
|
||||||
|
/**
|
||||||
|
* 状态码 0 表示成功
|
||||||
|
*/
|
||||||
|
private Integer code;
|
||||||
|
private String msg;
|
||||||
|
private PublishVoiceCallData data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class PublishVoiceCallData {
|
||||||
|
@JsonProperty("JYBH")
|
||||||
|
private String jybh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 内部实体类定义
|
||||||
|
@Data
|
||||||
|
public static class Location {
|
||||||
|
/**
|
||||||
|
* 地点名称, 可选, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("WZMC")
|
||||||
|
private String wzmc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 经度, 可选, Double
|
||||||
|
*/
|
||||||
|
@JsonProperty("WZJD")
|
||||||
|
private Double wzjd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 纬度, 可选, Double
|
||||||
|
*/
|
||||||
|
@JsonProperty("WZWD")
|
||||||
|
private Double wzwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Attachment {
|
||||||
|
/**
|
||||||
|
* 文件编号, 必填, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("WJBH")
|
||||||
|
private String wjbh;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件地址 (url 链接), 必填, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("WJDZ")
|
||||||
|
private String wjdz;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缩略图地址, 可选, String (url 链接)
|
||||||
|
*/
|
||||||
|
@JsonProperty("SLTP")
|
||||||
|
private String sltp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件类型, 必填, String (1:视频,2:音频,3:图片,4:文档,9:其他)
|
||||||
|
*/
|
||||||
|
@JsonProperty("WJLX")
|
||||||
|
private String wjlx;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class NotifyPerson {
|
||||||
|
/**
|
||||||
|
* 人员编号, 可选, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("RYBH")
|
||||||
|
private String rybh;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人员姓名, 可选, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("RYXM")
|
||||||
|
private String ryxm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移动电话, 必填, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("YDDH")
|
||||||
|
private String yddh;
|
||||||
|
// 注:可根据需要增加人员工号(RYGH)、固定电话(GDDH)、所属单位(SSDW)、所属辖区(SSXQ)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class NotifySupervision {
|
||||||
|
/**
|
||||||
|
* 通知督促的数值, 可选, Integer
|
||||||
|
*/
|
||||||
|
@JsonProperty("SJJG")
|
||||||
|
private Integer sjjg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 督促次数, 可选, Integer
|
||||||
|
*/
|
||||||
|
@JsonProperty("DCCS")
|
||||||
|
private Integer dccs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Deadline {
|
||||||
|
/**
|
||||||
|
* 截止时间数值, 可选, Integer
|
||||||
|
*/
|
||||||
|
@JsonProperty("SJJG")
|
||||||
|
private Integer sjjg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 截止时间单位, 时间单位(1:秒,2:分钟,3:小时) 可选, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("SJDW")
|
||||||
|
private String sjdw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class TimeoutRemind {
|
||||||
|
/**
|
||||||
|
* 截止时间数值, 可选, Integer
|
||||||
|
*/
|
||||||
|
@JsonProperty("SJJG")
|
||||||
|
private Integer sjjg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 截止时间单位, 时间单位(1:秒,2:分钟,3:小时) 可选, String
|
||||||
|
*/
|
||||||
|
@JsonProperty("SJDW")
|
||||||
|
private String sjdw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加场景图片
|
||||||
|
*
|
||||||
|
* @param scenePicDto 图片信息
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void addScenePic(DeliveryScenePicDto scenePicDto) {
|
||||||
|
DeliveryRecord deliveryRecord = deliveryRecordRepo.findById(scenePicDto.getDeliveryRecordId()).orElseThrow(() -> new BusinessError("送达记录不存在"));
|
||||||
|
Materials materials = new Materials();
|
||||||
|
materials.setLrsj(LocalDateTime.now());
|
||||||
|
MultipartFile pic = scenePicDto.getPic();
|
||||||
|
String name = pic.getName();
|
||||||
|
materials.setFileType(StringUtils.hasText(name) ? name.split("\\.")[1] : null);
|
||||||
|
materials.setName(name);
|
||||||
|
try {
|
||||||
|
String url = ftpService.uploadTempFile(IndustryCategoryForFile.pub, name, pic.getInputStream());
|
||||||
|
if (!StringUtils.hasText(url)) {
|
||||||
|
throw new BusinessError("文书送达现场图片接口返回失败:上传时异常");
|
||||||
|
}
|
||||||
|
materials.setSavePath(url);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BusinessError("文书送达现场图片接口上传失败:" + e);
|
||||||
|
}
|
||||||
|
materials.setIsOriginal("3");
|
||||||
|
materials.setMaterialsTypeCode("3");
|
||||||
|
materials.setMaterialsTypeName("文书送达现场图片");
|
||||||
|
materials.setLinkId(deliveryRecord.getDeliveryId());
|
||||||
|
materialsRepo.save(materials);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
package com.aisino.iles.lawenforcement.service;
|
||||||
|
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
|
import com.aisino.iles.lawenforcement.model.dto.DictItemDto;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.smartlx.sso.client.model.RemoteUserInfo;
|
||||||
|
import com.smartlx.sso.client.properties.SsoClientProperties;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DictInterfaceService {
|
||||||
|
private final String dictUrl;
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
private final SsoClientProperties ssoClientProperties;
|
||||||
|
private List<DictItemDto> dictItemDtos = new ArrayList<>();
|
||||||
|
|
||||||
|
public DictInterfaceService(@Value("${third-party.dict:}") String dictUrl,
|
||||||
|
ObjectMapper objectMapper,
|
||||||
|
SsoClientProperties ssoClientProperties) {
|
||||||
|
this.dictUrl = dictUrl;
|
||||||
|
this.objectMapper = objectMapper;
|
||||||
|
this.ssoClientProperties = ssoClientProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void getDictItemByUser(String dictCode, RemoteUserInfo user) {
|
||||||
|
String accessToken = user.getAccessToken().getAccess_token();
|
||||||
|
String tokenType = user.getAccessToken().getToken_type();
|
||||||
|
getDictItem(dictCode, tokenType, accessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getDictItem(String dictCode, String tokenType, String accessToken) {
|
||||||
|
String body = HttpUtil.createPost(dictUrl + dictCode)
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.header("Authorization", tokenType + " " + accessToken)
|
||||||
|
.header("appId", ssoClientProperties.getClientId())
|
||||||
|
.execute()
|
||||||
|
.body();
|
||||||
|
log.info("字典查询结果--------------");
|
||||||
|
try {
|
||||||
|
JsonNode jsonNode = objectMapper.readValue(body, JsonNode.class);
|
||||||
|
if (jsonNode.has("code") && 200 == jsonNode.get("code").asInt() && jsonNode.has("data")) {
|
||||||
|
JsonNode dataNode = objectMapper.readValue(jsonNode.get("data").toString(), JsonNode.class);
|
||||||
|
dictItemDtos = objectMapper.readValue(
|
||||||
|
dataNode.traverse(),
|
||||||
|
objectMapper.getTypeFactory().constructCollectionType(List.class, DictItemDto.class)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析字典结果失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFjdm(String xxdm) {
|
||||||
|
if (!StringUtils.hasText(xxdm))
|
||||||
|
return null;
|
||||||
|
DictItemDto item = findItemByXxdm(dictItemDtos, xxdm);
|
||||||
|
return item != null ? item.getFjdm() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据xxdm递归查找DictItemDto对象
|
||||||
|
*
|
||||||
|
* @param dtos 字典项列表
|
||||||
|
* @param xxdm 需要查找的代码
|
||||||
|
* @return 找到的DictItemDto对象,未找到返回null
|
||||||
|
*/
|
||||||
|
private DictItemDto findItemByXxdm(List<DictItemDto> dtos, String xxdm) {
|
||||||
|
if (dtos == null || dtos.isEmpty() || !StringUtils.hasText(xxdm))
|
||||||
|
return null;
|
||||||
|
for (DictItemDto dto : dtos) {
|
||||||
|
// 如果当前节点匹配
|
||||||
|
if (xxdm.equals(dto.getXxdm()))
|
||||||
|
return dto;
|
||||||
|
// 递归查找子节点
|
||||||
|
if (dto.getChildren() != null && !dto.getChildren().isEmpty()) {
|
||||||
|
DictItemDto found = findItemByXxdm(dto.getChildren(), xxdm);
|
||||||
|
if (found != null) {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTopXxdm(String xxdm) {
|
||||||
|
// 构建从当前节点到顶级节点的路径
|
||||||
|
StringBuilder path = new StringBuilder();
|
||||||
|
buildPath(dictItemDtos, xxdm, path);
|
||||||
|
return path.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean buildPath(List<DictItemDto> dtos, String xxdm, StringBuilder path) {
|
||||||
|
for (DictItemDto dto : dtos) {
|
||||||
|
if (dto.getXxdm().equals(xxdm)) {
|
||||||
|
// 找到当前节点
|
||||||
|
if (dto.getChildren() == null || dto.getChildren().isEmpty()) {
|
||||||
|
// 如果是叶子节点,则开始构建路径
|
||||||
|
path.insert(0, dto.getXxdm());
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// 如果不是叶子节点,继续向下查找子节点
|
||||||
|
for (DictItemDto child : dto.getChildren()) {
|
||||||
|
if (buildPath(List.of(child), xxdm, path)) {
|
||||||
|
// 在子树中找到目标节点,拼接当前节点的xxdm
|
||||||
|
path.insert(0, dto.getXxdm() + "/");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 当前节点不匹配,检查其子节点
|
||||||
|
if (dto.getChildren() != null && !dto.getChildren().isEmpty()) {
|
||||||
|
if (buildPath(dto.getChildren(), xxdm, path)) {
|
||||||
|
// 子节点中找到了目标节点,拼接当前节点的xxdm
|
||||||
|
path.insert(0, dto.getXxdm() + "/");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false; // 没有找到目标节点
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
package com.aisino.iles.lawenforcement.service;
|
||||||
|
|
||||||
|
import com.aisino.iles.common.model.enums.IndustryCategoryForFile;
|
||||||
|
import com.aisino.iles.common.service.FtpService;
|
||||||
|
import com.aisino.iles.common.util.PageableHelper;
|
||||||
|
import com.aisino.iles.core.exception.BusinessError;
|
||||||
|
import com.aisino.iles.lawenforcement.event.DataChangeAction;
|
||||||
|
import com.aisino.iles.lawenforcement.event.aop.PublishDataChange;
|
||||||
|
import com.aisino.iles.lawenforcement.model.Case;
|
||||||
|
import com.aisino.iles.lawenforcement.model.Case_;
|
||||||
|
import com.aisino.iles.lawenforcement.model.Document;
|
||||||
|
import com.aisino.iles.lawenforcement.model.Document_;
|
||||||
|
import com.aisino.iles.lawenforcement.model.dto.FormDataDto;
|
||||||
|
import com.aisino.iles.lawenforcement.model.query.DocumentQuery;
|
||||||
|
import com.aisino.iles.lawenforcement.repository.DocumentRepository;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import jakarta.persistence.criteria.Join;
|
||||||
|
import jakarta.persistence.criteria.JoinType;
|
||||||
|
import jakarta.persistence.criteria.Predicate;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class DocumentService {
|
||||||
|
private final DocumentRepository documentRepository;
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
private final FtpService ftpService;
|
||||||
|
|
||||||
|
public DocumentService(DocumentRepository documentRepository,
|
||||||
|
ObjectMapper objectMapper,
|
||||||
|
FtpService ftpService) {
|
||||||
|
this.objectMapper = objectMapper;
|
||||||
|
this.ftpService = ftpService;
|
||||||
|
this.documentRepository = documentRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文书信息
|
||||||
|
*
|
||||||
|
* @param query@return 分页查询文书信息
|
||||||
|
*/
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public Page<Document> findDocumentsPage(DocumentQuery query) {
|
||||||
|
return documentRepository.findAll(buildSpec(query), PageableHelper.buildPageRequest(query.page(), query.pageSize(), query.sort(), query.dir())).map(this::handleResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Document handleResult(Document document) {
|
||||||
|
Optional.ofNullable(document.getCaseInfo()).ifPresent(caseInfo -> caseInfo.getCaseName());
|
||||||
|
Optional.ofNullable(document.getFilePath()).ifPresent(filePath -> document.setDownloadUrl(ftpService.getFileUrl(filePath)));
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Document> listDocuments(DocumentQuery query) {
|
||||||
|
Sort sort = Sort.by(Sort.Direction.ASC, "documentNo");
|
||||||
|
return documentRepository.findAll(buildSpec(query), sort, "").stream().map(document -> {
|
||||||
|
Optional.ofNullable(document.getFilePath()).ifPresent(filePath -> document.setDownloadUrl(ftpService.getFileUrl(filePath)));
|
||||||
|
return document;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Specification<Document> buildSpec(DocumentQuery query) {
|
||||||
|
return Specification.where((root, q, criteriaBuilder) -> {
|
||||||
|
List<Predicate> predicates = new ArrayList<>();
|
||||||
|
Join<Document, Case> caseDocumentRoot = root.join("caseInfo", JoinType.LEFT);
|
||||||
|
if (StringUtils.hasText(query.getCaseNum()))
|
||||||
|
predicates.add(criteriaBuilder.equal(caseDocumentRoot.get(Case_.caseNum), query.getCaseNum()));
|
||||||
|
if (StringUtils.hasText(query.getCaseName()))
|
||||||
|
predicates.add(criteriaBuilder.like(caseDocumentRoot.get(Case_.caseName), "%"+query.getCaseName()+"%"));
|
||||||
|
Optional.ofNullable(query.getCaseId()).ifPresent(o -> predicates.add(criteriaBuilder.equal(root.get(Document_.caseInfo).get(Case_.caseId), o)));
|
||||||
|
Optional.ofNullable(query.getDocumentNo()).ifPresent(o -> predicates.add(criteriaBuilder.equal(root.get(Document_.documentNo), o)));
|
||||||
|
Optional.ofNullable(query.getDocumentCode()).ifPresent(o -> predicates.add(criteriaBuilder.equal(root.get(Document_.documentCode), o)));
|
||||||
|
Optional.ofNullable(query.getStatus()).filter("done"::equals).ifPresent(o -> {
|
||||||
|
predicates.add(criteriaBuilder.equal(root.get(Document_.status), Document.DocumentStatus.done));
|
||||||
|
});
|
||||||
|
Optional.ofNullable(query.getDocumentName()).ifPresent(o -> predicates.add(criteriaBuilder.like(root.get(Document_.documentName), "%" + o + "%")));
|
||||||
|
Optional.ofNullable(query.getDocumentDate()).filter(f -> f.length == 2).map(f -> {
|
||||||
|
List<Predicate> timePredicates = new ArrayList<>();
|
||||||
|
Optional.ofNullable(f[0]).map(from -> criteriaBuilder.greaterThanOrEqualTo(root.get(Document_.documentDate), from)).ifPresent(timePredicates::add);
|
||||||
|
Optional.ofNullable(f[1]).map(to -> criteriaBuilder.lessThanOrEqualTo(root.get(Document_.documentDate), to)).ifPresent(timePredicates::add);
|
||||||
|
return timePredicates;
|
||||||
|
}).ifPresent(predicates::addAll);
|
||||||
|
Optional.ofNullable(query.getConditionlike()).filter(StringUtils::hasText).ifPresent(o -> {
|
||||||
|
List<Predicate> orPredicates = new ArrayList<>();
|
||||||
|
Predicate p1 = criteriaBuilder.like(root.get(Document_.documentCode), "%" + o + "%");
|
||||||
|
orPredicates.add(criteriaBuilder.or(p1));
|
||||||
|
Predicate p2 = criteriaBuilder.like(root.get(Document_.documentName), "%" + o + "%");
|
||||||
|
orPredicates.add(criteriaBuilder.or(p2));
|
||||||
|
Predicate p = criteriaBuilder.or(orPredicates.toArray(new Predicate[0]));
|
||||||
|
predicates.add(p);
|
||||||
|
});
|
||||||
|
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存文书
|
||||||
|
*
|
||||||
|
* @param document 文书信息
|
||||||
|
* @return 保存后的文书信息
|
||||||
|
*/
|
||||||
|
@PublishDataChange(action = DataChangeAction.SAVE)
|
||||||
|
@Transactional
|
||||||
|
public Document saveDocument(Document document) {
|
||||||
|
document.setDocumentDate(LocalDateTime.now());
|
||||||
|
return documentRepository.save(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID删除文书信息
|
||||||
|
*
|
||||||
|
* @param documentId 文书ID
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void deleteDocumentById(String documentId) {
|
||||||
|
documentRepository.deleteById(documentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除文书信息
|
||||||
|
*
|
||||||
|
* @param documentIds 文书ID列表
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void deleteDocumentsByIds(List<String> documentIds) {
|
||||||
|
documentRepository.deleteAllById(documentIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PublishDataChange(action = DataChangeAction.SAVE)
|
||||||
|
@Transactional
|
||||||
|
public Document addDocumentFile(FormDataDto formData) {
|
||||||
|
MultipartFile file = formData.getFile1();
|
||||||
|
Document document = new Document();
|
||||||
|
try {
|
||||||
|
document = objectMapper.readValue(formData.getFormDataJson(), Document.class);
|
||||||
|
if (null != file) {
|
||||||
|
String url;
|
||||||
|
try {
|
||||||
|
url = ftpService.uploadTempFile(IndustryCategoryForFile.pub, file.getOriginalFilename(), file.getInputStream());
|
||||||
|
if (!StringUtils.hasText(url)) {
|
||||||
|
throw new BusinessError(document.getDocumentName() + "返回失败:上传时异常");
|
||||||
|
}
|
||||||
|
document.setFilePath(url);
|
||||||
|
document.setStatus(Document.DocumentStatus.done);
|
||||||
|
document.setDocumentDate(LocalDateTime.now());
|
||||||
|
documentRepository.save(document);
|
||||||
|
document.setDownloadUrl(ftpService.getFileUrl(url));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BusinessError(document.getDocumentName()+ "上传失败:" + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public Optional<Document> findByCaseIdAndDocumentName(String caseId,String documentName) {
|
||||||
|
return documentRepository.findByCaseIdAndDocumentName( caseId, documentName);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue