| | |
| | | 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.ruoyi.system.domain.TbBasicData; |
| | | 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.service.TbBasicDataService; |
| | | import com.ruoyi.system.mapper.TbDeptMapper; |
| | | import com.ruoyi.system.query.ScoreQuery; |
| | | import com.ruoyi.system.service.*; |
| | | import com.ruoyi.system.vo.BasicDataReportingVO; |
| | | import com.ruoyi.system.vo.FieldReportingVO; |
| | | 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> |
| | |
| | | * @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(String deptAreaCode) throws Exception { |
| | | 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(); |
| | | if (CollUtils.isNotEmpty(list)) { |
| | | List<FieldReportingVO> fieldReportingVOS = BeanUtils.copyList(list, FieldReportingVO.class); |
| | | vo.setFields(fieldReportingVOS); |
| | | } |
| | | 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())); |
| | | vo.getFields().forEach(item -> { |
| | | TbBasicDataField tbBasicDataField = fieldMap.get(item.getId()); |
| | | if (Objects.nonNull(tbBasicDataField)) { |
| | | item.setValue(tbBasicDataField.getFieldValue()); |
| | | } |
| | | }); |
| | | return R.ok(vo); |
| | | } |
| | | } |
| | | return R.ok(vo); |
| | | } |
| | | |
| | | @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); |
| | | tbBasicDataFields.forEach(item -> item.setBasicDataId(tbBasicData.getId())); |
| | | //查询需要填写的动态字段 |
| | | List<TbField> fieldList = tbFieldService.lambdaQuery().eq(TbField::getStatus, ShowStatusEnum.SHOW).list(); |
| | | //添加固定字段 转移支付规模、当期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()); |
| | | //查询对应的基础数据配置 |
| | | List<ScoreVO> vos = tbScoreService.pageScore(query,page); |
| | | return PageDTO.of(page, vos); |
| | | } |
| | | } |