新增文书送达、文书送达记录、字典查询、文书信息等接口
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