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.CurrentFieldsQuery;
import com.ruoyi.system.query.ScoreCalculateQuery;
import com.ruoyi.system.query.ScoreQuery;
import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.FieldBuildUtil;
import com.ruoyi.system.vo.*;
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;
/**
*
* 基础数据表 服务实现类
*
*
* @author mitao
* @since 2024-03-13
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class TbBasicDataServiceImpl extends ServiceImpl 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;
private final ISysUserService sysUserService;
public static void setFieldValues(List fields, Map fieldMap) {
for (FieldsTreeVO field : fields) {
TbBasicDataField tbBasicDataField = fieldMap.get(field.getId());
if (tbBasicDataField != null) {
field.setValue(FieldBuildUtil.formatNumberWithCommas(tbBasicDataField.getFieldValue()));
}
if (field.getChildren() != null && !field.getChildren().isEmpty()) {
setFieldValues(field.getChildren(), fieldMap);
}
}
}
@Override
public R getBasicFields() throws Exception {
SysUser user = SecurityUtils.getLoginUser().getUser();
String deptAreaCode = user.getAreaCode();
BasicDataReportingVO vo = new BasicDataReportingVO();
//校验区划代码
TbDept dept = tbDeptMapper.selectOne(Wrappers.lambdaQuery().eq(TbDept::getAreaCode, deptAreaCode));
if (Objects.isNull(dept)) {
throw new ServiceException(String.format("区划代码%s不存在", deptAreaCode));
}
Date date = new Date();
Map 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(DateUtils.getNowQuarter());
vo.setStatus(ReportingStatusEnum.UNFILLED);
//如果当前时间不在规定范围内:季度初1-15号
if (now.isBefore(quarterStartLocalDate) || now.isAfter(fifteenDaysLimit)) {
return R.ok(vo, "请于季度初1-15号上传季度数据。");
}
//查询是否有当前季度的填报记录
TbBasicData basicData = this.getOne(Wrappers.lambdaQuery()
.eq(TbBasicData::getDeptAreaCode, dept.getAreaCode())
.between(TbBasicData::getCreateTime, quarterStart, quarterEnd));
//查询需要填写的字段
List list = tbFieldService.lambdaQuery().eq(TbField::getStatus, ShowStatusEnum.SHOW).list();
List 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);
FieldsTreeVO remark = new FieldsTreeVO();
remark.setId(-3L);
remark.setName("备注");
roots.add(remark);
vo.setFields(roots);
}
if (Objects.isNull(basicData)) {
vo.setQuarter(DateUtils.getNowQuarter());
vo.setStatus(ReportingStatusEnum.UNFILLED);
return R.ok(vo);
} else {
vo.setStatus(basicData.getStatus());
//查询已填报数据 包含数据缺失和已填报
List basicDataFields = tbBasicDataFieldService.lambdaQuery()
.eq(TbBasicDataField::getBasicDataId, basicData.getId()).list();
if (CollUtils.isNotEmpty(basicDataFields)) {
Map fieldMap = basicDataFields.stream()
.collect(Collectors.toMap(TbBasicDataField::getFieldId, Function.identity()));
setFieldValues(vo.getFields(), fieldMap);
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 tbBasicDataFields = BeanUtils.copyList(dto.getFields(), TbBasicDataField.class);
//查询需要填写的动态字段
List fieldList = tbFieldService.lambdaQuery().eq(TbField::getStatus, ShowStatusEnum.SHOW).list();
Map 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();
currentGdp.setBasicDataId(tbBasicData.getId());
currentGdp.setFieldId(-2L);
currentGdp.setFieldValue(tbBasicData.getCurrentGdp());
tbBasicDataFields.add(currentGdp);
TbBasicDataField remark = new TbBasicDataField();
remark.setBasicDataId(tbBasicData.getId());
remark.setFieldId(-3L);
remark.setFieldValue(tbBasicData.getRemark());
tbBasicDataFields.add(remark);
//将该基础数据的动态字段数据全部删除
tbBasicDataFieldService.remove(Wrappers.lambdaQuery().eq(TbBasicDataField::getBasicDataId, tbBasicData.getId()));
tbBasicDataFieldService.saveBatch(tbBasicDataFields);
//需要填写的动态字段
Set fieldIds = fieldList.stream().map(TbField::getId).collect(Collectors.toSet());
//用户填写的动态字段
Set 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 list = tbFieldService.lambdaQuery().eq(TbField::getStatus, ShowStatusEnum.SHOW).list();
List> head = head(list);
List collect = list.stream()
.filter(item -> FieldTypeEnum.TEXT.equals(item.getFieldType()))
.filter(item -> FieldInputTypeEnum.FIXED_CONTENT.equals(item.getTextInputType()))
.collect(Collectors.toList());
Map 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 value) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).contains(value)) {
return i;
}
}
return -1; // 返回-1表示未找到
}
private List> dataList(List list) throws Exception {
LoginUser loginUser = SecurityUtils.getLoginUser();
String areaName = loginUser.getUser().getAreaName();
List> excellist = new ArrayList>();
List> head = head(list);
List