package com.ruoyi.system.service.impl;
|
|
import com.alibaba.excel.EasyExcel;
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.google.common.collect.Lists;
|
import com.ruoyi.common.basic.PageDTO;
|
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.enums.*;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.utils.*;
|
import com.ruoyi.system.domain.*;
|
import com.ruoyi.system.dto.BasicDataDTO;
|
import com.ruoyi.system.handler.CustomerHandler;
|
import com.ruoyi.system.handler.SelectedSheetWriteHandler;
|
import com.ruoyi.system.listener.BasicDataListener;
|
import com.ruoyi.system.mapper.TbBasicDataMapper;
|
import com.ruoyi.system.mapper.TbDeptMapper;
|
import com.ruoyi.system.query.ScoreQuery;
|
import com.ruoyi.system.service.*;
|
import com.ruoyi.system.utils.FieldBuildUtil;
|
import com.ruoyi.system.vo.BasicDataReportingVO;
|
import com.ruoyi.system.vo.FieldsTreeVO;
|
import com.ruoyi.system.vo.ScoreVO;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.web.multipart.MultipartFile;
|
|
import javax.servlet.http.HttpServletResponse;
|
import java.net.URLEncoder;
|
import java.time.Instant;
|
import java.time.LocalDate;
|
import java.time.ZoneId;
|
import java.util.*;
|
import java.util.function.Function;
|
import java.util.stream.Collectors;
|
|
/**
|
* <p>
|
* 基础数据表 服务实现类
|
* </p>
|
*
|
* @author mitao
|
* @since 2024-03-13
|
*/
|
@Slf4j
|
@Service
|
@RequiredArgsConstructor
|
public class TbBasicDataServiceImpl extends ServiceImpl<TbBasicDataMapper, TbBasicData> implements TbBasicDataService {
|
|
private final TbDeptMapper tbDeptMapper;
|
private final HttpServletResponse response;
|
private final TbFieldService tbFieldService;
|
private final TbBasicDataFieldService tbBasicDataFieldService;
|
private final TbBasicDataConfigService tbBasicDataConfigService;
|
private final TbBasicDataConfigDetailService tbBasicDataConfigDetailService;
|
private final TbScoreService tbScoreService;
|
|
@Override
|
public R<BasicDataReportingVO> getBasicFields() throws Exception {
|
SysUser user = SecurityUtils.getLoginUser().getUser();
|
String deptAreaCode = user.getAreaCode();
|
BasicDataReportingVO vo = new BasicDataReportingVO();
|
//校验区划代码
|
TbDept dept = tbDeptMapper.selectOne(Wrappers.<TbDept>lambdaQuery().eq(TbDept::getAreaCode, deptAreaCode));
|
if (Objects.isNull(dept)) {
|
throw new ServiceException(String.format("区划代码%s不存在", deptAreaCode));
|
}
|
Date date = new Date();
|
//当前所在季度
|
int quarterOfYear = DateUtils.getQuarterOfYear(date);
|
String quarterOfYearStr = NumberDisplaceChineseUtil.numberToChinese(quarterOfYear);
|
Map<String, Date> quarterDate = DateUtils.getQuarterDate(date);
|
//当前季度开始
|
Date quarterStart = quarterDate.get("first");
|
//当前季度结束
|
Date quarterEnd = quarterDate.get("last");
|
//判断当前时间是否在季度初1-15号
|
Instant instant = quarterStart.toInstant();
|
LocalDate quarterStartLocalDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();
|
LocalDate fifteenDaysLimit = quarterStartLocalDate.plusDays(15);
|
LocalDate now = LocalDate.now();
|
vo.setQuarter(String.format("%s年%s季度",now.getYear(),quarterOfYearStr));
|
vo.setStatus(ReportingStatusEnum.UNFILLED);
|
//如果当前时间不在规定范围内:季度初1-15号
|
if (now.isBefore(quarterStartLocalDate) || now.isAfter(fifteenDaysLimit)) {
|
return R.ok(vo,"请于季度初1-15号上传季度数据。");
|
}
|
//查询是否有当前季度的填报记录
|
TbBasicData basicData = this.getOne(Wrappers.<TbBasicData>lambdaQuery()
|
.eq(TbBasicData::getDeptAreaCode, dept.getAreaCode())
|
.between(TbBasicData::getCreateTime, quarterStart,quarterEnd));
|
//查询需要填写的字段
|
List<TbField> list = tbFieldService.lambdaQuery().eq(TbField::getStatus, ShowStatusEnum.SHOW).list();
|
List<FieldsTreeVO> roots = new ArrayList<>();
|
FieldsTreeVO fieldsTreeVO = new FieldsTreeVO();
|
fieldsTreeVO.setId(-1L);
|
fieldsTreeVO.setName("转移支付规模");
|
fieldsTreeVO.setCategory(Boolean.FALSE);
|
FieldsTreeVO fieldsTreeVO2 = new FieldsTreeVO();
|
fieldsTreeVO2.setId(-2L);
|
fieldsTreeVO2.setName("当期GDP");
|
fieldsTreeVO2.setCategory(Boolean.FALSE);
|
roots.add(fieldsTreeVO);
|
roots.add(fieldsTreeVO2);
|
if (CollUtils.isNotEmpty(list)) {
|
FieldBuildUtil.buildTreeFromTbFieldList(list,roots);
|
vo.setFields(roots);
|
}
|
if (Objects.isNull(basicData)) {
|
vo.setQuarter(String.format("%s年%s季度",now.getYear(),quarterOfYearStr));
|
vo.setStatus(ReportingStatusEnum.UNFILLED);
|
return R.ok(vo);
|
}else {
|
vo.setStatus(basicData.getStatus());
|
//查询已填报数据 包含数据缺失和已填报
|
List<TbBasicDataField> basicDataFields = tbBasicDataFieldService.lambdaQuery()
|
.eq(TbBasicDataField::getBasicDataId, basicData.getId()).list();
|
|
if (CollUtils.isNotEmpty(basicDataFields)) {
|
Map<Long, TbBasicDataField> fieldMap = basicDataFields.stream()
|
.collect(Collectors.toMap(TbBasicDataField::getFieldId, Function.identity()));
|
setFieldValues(vo.getFields(), fieldMap);
|
return R.ok(vo);
|
}
|
}
|
return R.ok(vo);
|
}
|
public static void setFieldValues(List<FieldsTreeVO> fields, Map<Long, TbBasicDataField> fieldMap) {
|
for (FieldsTreeVO field : fields) {
|
TbBasicDataField tbBasicDataField = fieldMap.get(field.getId());
|
if (tbBasicDataField != null) {
|
field.setValue(tbBasicDataField.getFieldValue());
|
}
|
if (field.getChildren() != null && !field.getChildren().isEmpty()) {
|
setFieldValues(field.getChildren(), fieldMap);
|
}
|
}
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void saveBasicData(BasicDataDTO dto) {
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
String areaCode = loginUser.getUser().getAreaCode();
|
//数据校验
|
if (Objects.isNull(dto) || CollUtils.isEmpty(dto.getFields())) {
|
return;
|
}
|
TbBasicData tbBasicData = BeanUtils.copyBean(dto, TbBasicData.class);
|
tbBasicData.setDeptAreaCode(areaCode);
|
tbBasicData.setStatus(ReportingStatusEnum.MISSING_DATA);
|
this.saveOrUpdate(tbBasicData);
|
//保存基础数据动态字段数据
|
List<TbBasicDataField> tbBasicDataFields = BeanUtils.copyList(dto.getFields(), TbBasicDataField.class);
|
//查询需要填写的动态字段
|
List<TbField> fieldList = tbFieldService.lambdaQuery().eq(TbField::getStatus, ShowStatusEnum.SHOW).list();
|
Map<Long, TbField> fieldMap = fieldList.stream().collect(Collectors.toMap(TbField::getId, e -> e));
|
tbBasicDataFields.forEach(item -> {
|
item.setBasicDataId(tbBasicData.getId());
|
TbField tbField = fieldMap.get(item.getFieldId());
|
if (Objects.nonNull(tbField)) {
|
item.setFieldName(tbField.getFieldName());
|
}
|
});
|
//添加固定字段 转移支付规模、当期GDP
|
TbBasicDataField transferPaymentScale = new TbBasicDataField();
|
transferPaymentScale.setBasicDataId(tbBasicData.getId());
|
transferPaymentScale.setFieldId(-1L);
|
transferPaymentScale.setFieldValue(tbBasicData.getTransferPaymentScale());
|
tbBasicDataFields.add(transferPaymentScale);
|
TbBasicDataField currentGdp = new TbBasicDataField();
|
transferPaymentScale.setBasicDataId(tbBasicData.getId());
|
transferPaymentScale.setFieldId(-2L);
|
transferPaymentScale.setFieldValue(tbBasicData.getCurrentGdp());
|
tbBasicDataFields.add(currentGdp);
|
//将该基础数据的动态字段数据全部删除
|
tbBasicDataFieldService.remove(Wrappers.<TbBasicDataField>lambdaQuery().eq(TbBasicDataField::getBasicDataId, tbBasicData.getId()));
|
tbBasicDataFieldService.saveBatch(tbBasicDataFields);
|
//需要填写的动态字段
|
Set<Long> fieldIds = fieldList.stream().map(TbField::getId).collect(Collectors.toSet());
|
//用户填写的动态字段
|
Set<Long> deptFieldIds = tbBasicDataFields.stream().map(TbBasicDataField::getFieldId).collect(Collectors.toSet());
|
boolean flag = deptFieldIds.containsAll(fieldIds) && (StringUtils.isNotEmpty(dto.getTransferPaymentScale())&& StringUtils.isNotEmpty(dto.getCurrentGdp()));
|
if (flag) {
|
tbBasicData.setStatus(ReportingStatusEnum.FILLED);
|
this.updateById(tbBasicData);
|
}
|
if (ReportingStatusEnum.FILLED.equals(tbBasicData.getStatus())) {
|
calculateScore(tbBasicData);
|
}
|
}
|
|
@Override
|
public void downloadImportTemplate() throws Exception {
|
response.setContentType("application/vnd.ms-excel");
|
response.setCharacterEncoding("utf-8");
|
String fileName = "地方财政运行及“三保”情况统计表";
|
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
|
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
|
//查询需要填写的动态字段
|
List<TbField> list = tbFieldService.lambdaQuery().eq(TbField::getStatus, ShowStatusEnum.SHOW).list();
|
List<List<String>> head = head(list);
|
List<TbField> collect = list.stream()
|
.filter(item -> FieldTypeEnum.TEXT.equals(item.getFieldType()))
|
.filter(item -> FieldInputTypeEnum.FIXED_CONTENT.equals(item.getTextInputType()))
|
.collect(Collectors.toList());
|
Map<Integer, String[]> selectedMap = new HashMap<>();
|
if (CollUtils.isNotEmpty(collect)) {
|
selectedMap = new HashMap<>();
|
for (TbField tbField : collect) {
|
int outerListIndex = getOuterListIndex(head, tbField.getFieldName());
|
String[] selectStr = tbField.getTextContent().split(",");
|
selectedMap.put(outerListIndex, selectStr);
|
}
|
}
|
// 这里需要设置不关闭流
|
EasyExcel.write(response.getOutputStream()).head(head)
|
.autoCloseStream(Boolean.TRUE).sheet("模板")
|
.registerWriteHandler(new SelectedSheetWriteHandler(selectedMap))
|
.registerWriteHandler(new CustomerHandler())
|
.registerWriteHandler(EasyExcelUtil.getStyleStrategy())
|
.doWrite(dataList(list));
|
}
|
|
/**
|
* 根据字段名获取该字段下标
|
* @param list 表头
|
* @param value 字段名
|
* @return 下标
|
*/
|
public int getOuterListIndex(List<List<String>> list, String value) {
|
for (int i = 0; i < list.size(); i++) {
|
if (list.get(i).contains(value)) {
|
return i;
|
}
|
}
|
return -1; // 返回-1表示未找到
|
}
|
|
private List<List<Object>> dataList(List<TbField> list) throws Exception {
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
String areaName = loginUser.getUser().getAreaName();
|
|
//当前所在季度
|
int quarterOfYear = DateUtils.getQuarterOfYear(new Date());
|
String quarterOfYearStr = NumberDisplaceChineseUtil.numberToChinese(quarterOfYear);
|
List<List<Object>> excellist = new ArrayList<List<Object>>();
|
List<List<String>> head = head(list);
|
List<Object> columnNo = Lists.newArrayList("栏号");
|
for (int i = 1; i < head.size(); i++) {
|
columnNo.add(String.valueOf(i));
|
}
|
excellist.add(columnNo);
|
excellist.add(Lists.newArrayList(areaName, String.format("%s季度",quarterOfYearStr)));
|
return excellist;
|
}
|
|
private List<List<String>> head(List<TbField> list) {
|
List<List<String>> headTitles = Lists.newArrayList();
|
//固定字段
|
headTitles.add(Lists.newArrayList("地区"));
|
headTitles.add(Lists.newArrayList("填报季度"));
|
headTitles.add(Lists.newArrayList("转移支付规模"));
|
headTitles.add(Lists.newArrayList("当期GDP"));
|
list.forEach(item ->{
|
String levelOneCategory = item.getLevelOneCategory();
|
String levelTwoCategory = item.getLevelTwoCategory();
|
String levelThreeCategory = item.getLevelThreeCategory();
|
String fieldName = item.getFieldName();
|
headTitles.add(Lists.newArrayList(levelOneCategory,StringUtils.isBlank(levelTwoCategory) ? fieldName : levelTwoCategory, StringUtils.isBlank(levelThreeCategory) ? fieldName : levelThreeCategory, fieldName));
|
});
|
headTitles.add(Lists.newArrayList("备注"));
|
return headTitles;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void importBasicData(MultipartFile file) throws Exception {
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
String areaCode = loginUser.getUser().getAreaCode();
|
//查询需要填写的动态字段
|
List<TbField> fieldList = tbFieldService.lambdaQuery().eq(TbField::getStatus, ShowStatusEnum.SHOW).list();
|
EasyExcel.read(file.getInputStream(), new BasicDataListener(this,fieldList,
|
tbFieldService,areaCode,tbBasicDataFieldService,tbBasicDataConfigService,
|
tbBasicDataConfigDetailService,tbScoreService)).sheet().doRead();
|
}
|
|
private void calculateScore(TbBasicData tbBasicData) {
|
//计算得分
|
List<TbBasicDataConfig> list = tbBasicDataConfigService.lambdaQuery().eq(TbBasicDataConfig::getStatus, ShowStatusEnum.SHOW).list();
|
if (CollectionUtils.isEmpty(list)) {
|
throw new ServiceException("计算得分失败,平台未配置得分计算规则");
|
}
|
List<TbBasicDataConfig> numCalculates = list.stream()
|
.filter(item -> CalculateTypeEnum.NUMBER.equals(item.getCalculateType()))
|
.collect(Collectors.toList());
|
List<TbBasicDataConfig> textAndPercentages = list.stream()
|
.filter(item -> !CalculateTypeEnum.NUMBER.equals(item.getCalculateType()))
|
.collect(Collectors.toList());
|
if (CollectionUtils.isNotEmpty(numCalculates)) {
|
numCalculates.forEach(item -> {
|
Map<String, Object> valueMap = new HashMap<>();
|
String numberCalculateFormula = item.getNumberCalculateFormula();
|
Map<String, Integer> fieldsAndValue = CalculateUtil.getFieldsAndValue(numberCalculateFormula);
|
for (Map.Entry<String, Integer> stringIntegerEntry : fieldsAndValue.entrySet()) {
|
Optional<TbBasicDataField> tbBasicDataField = tbBasicDataFieldService.lambdaQuery()
|
.eq(TbBasicDataField::getBasicDataId, tbBasicData.getId())
|
.eq(TbBasicDataField::getFieldId, stringIntegerEntry.getValue())
|
.oneOpt();
|
tbBasicDataField.ifPresent(basicDataField -> valueMap.put(stringIntegerEntry.getKey(), basicDataField.getFieldValue()));
|
}
|
double score = CalculateUtil.calculate(numberCalculateFormula, valueMap);
|
TbScore tbScore = new TbScore();
|
tbScore.setBasicDataId(tbBasicData.getId());
|
tbScore.setScore(score);
|
tbScore.setBasicDataConfigId(item.getId());
|
tbScoreService.save(tbScore);
|
});
|
}
|
if (CollectionUtils.isNotEmpty(textAndPercentages)) {
|
for (TbBasicDataConfig textAndPercentage : textAndPercentages) {
|
TbScore tbScore = new TbScore();
|
List<TbBasicDataConfigDetail> details = tbBasicDataConfigDetailService.lambdaQuery()
|
.eq(TbBasicDataConfigDetail::getBasicDataConfigId, textAndPercentage.getId())
|
.list();
|
Map<String, String> scoreMap = details.stream().collect(Collectors.toMap(TbBasicDataConfigDetail::getKey, TbBasicDataConfigDetail::getValue));
|
if (CollectionUtils.isNotEmpty(details)) {
|
Optional<TbBasicDataField> tbBasicDataFieldOptional = tbBasicDataFieldService.lambdaQuery()
|
.eq(TbBasicDataField::getBasicDataId, tbBasicData.getId())
|
.eq(TbBasicDataField::getFieldId, textAndPercentage.getFieldIdStr())
|
.oneOpt();
|
if (tbBasicDataFieldOptional.isPresent()) {
|
TbBasicDataField tbBasicDataField = tbBasicDataFieldOptional.get();
|
if (CalculateTypeEnum.TEXT.equals(textAndPercentage.getCalculateType())) {
|
String score = scoreMap.get(tbBasicDataField.getFieldValue());
|
tbScore.setBasicDataId(tbBasicData.getId());
|
tbScore.setScore(Double.parseDouble(score));
|
tbScore.setBasicDataConfigId(textAndPercentage.getId());
|
tbScoreService.save(tbScore);
|
}
|
if (CalculateTypeEnum.PERCENTAGE.equals(textAndPercentage.getCalculateType())) {
|
for (Map.Entry<String, String> stringStringEntry : scoreMap.entrySet()) {
|
String[] split = stringStringEntry.getKey().split("-");
|
double v = Double.parseDouble(tbBasicDataField.getFieldValue());
|
double min = Double.parseDouble(split[0]);
|
double max = Double.parseDouble(split[1]);
|
if (v >= min && v <= max) {
|
tbScore.setScore(Double.parseDouble(stringStringEntry.getValue()));
|
}
|
}
|
tbScore.setBasicDataId(tbBasicData.getId());
|
tbScore.setBasicDataConfigId(textAndPercentage.getId());
|
tbScoreService.save(tbScore);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
@Override
|
public PageDTO<ScoreVO> pageScore(ScoreQuery query) {
|
Page<ScoreVO> page = new Page<>(query.getPageNum(), query.getPageSize());
|
SysUser user = SecurityUtils.getLoginUser().getUser();
|
String areaCode = user.getAreaCode();
|
Map<String, Date> quarterDate = DateUtils.getQuarterDate(new Date());
|
//当前季度开始
|
Date quarterStart = quarterDate.get("first");
|
//当前季度结束
|
Date quarterEnd = quarterDate.get("last");
|
//查询是否有当前季度的填报记录
|
TbBasicData basicData = this.getOne(Wrappers.<TbBasicData>lambdaQuery()
|
.eq(TbBasicData::getDeptAreaCode, areaCode)
|
.between(TbBasicData::getCreateTime, quarterStart,quarterEnd));
|
if (Objects.isNull(basicData)) {
|
return PageDTO.empty(page);
|
}
|
query.setBasicDataId(basicData.getId());
|
//查询对应的基础数据配置
|
Page<ScoreVO> pageVO = tbScoreService.pageScore(query,page);
|
return PageDTO.of(pageVO);
|
}
|
}
|