feat(system): 增加工资条导入功能并优化相关服务- 新增工资条导入相关的错误码常量

- 修改考勤统计导出功能,增加行高设置
- 优化工资条控制器和服务实现,支持导入功能- 更新数据库实体和相关VO,增加公司名称字段
- 重构工资条导出功能,优化数据处理和样式设置
This commit is contained in:
furongxin 2024-10-30 09:28:18 +08:00
parent 3001531471
commit ac47a0a252
9 changed files with 67 additions and 14 deletions

View File

@ -269,4 +269,5 @@ public interface ErrorCodeConstants {
ErrorCode PAYSLIP_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_012_002_006, "导入数据不能为空!");
ErrorCode PAYSLIP_EXISTS = new ErrorCode(1_012_002_007, "所选公司在当前月份已上传工资条!如需修改,请勾选覆盖导入。");
ErrorCode PAYSLIP_ID_CARD_ERROR = new ErrorCode(1_012_002_008, "【{}】身份证输入有误,请核对后导入!");
ErrorCode PAYSLIP_ISSUED = new ErrorCode(1_012_002_009, "所选公司在当前月份的工资条已下发,不能修改!");
}

View File

@ -23,8 +23,10 @@ import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 工资条")
@ -162,6 +164,10 @@ public class PayslipController {
public CommonResult<PageResult<PayslipRespVO>> getMyPage(@RequestBody PayslipPageReqVO pageReqVO) {
PageResult<PayslipRespVO> pageResult = BeanUtils.toBean(payslipService.getMyPage(pageReqVO), PayslipRespVO.class);
// 获取电子签名Map
Map<Long, String> signImgPathMap = fileApi.getUserSignImgPathMap(convertList(pageResult.getList(), PayslipRespVO::getUserId)).getCheckedData();
pageResult.getList().forEach(data -> {
List<PayslipDetail> details = data.getDetails();
// 设置实发工资
@ -189,7 +195,7 @@ public class PayslipController {
.setValue(data.getRemark()));
if (data.getIsConfirm() == 1) {
data.setSignURL(fileApi.getUserSignImgPath(data.getUserId()).getData());
data.setSignURL(signImgPathMap.get(data.getUserId()));
}
// 设置签名
@ -208,12 +214,14 @@ public class PayslipController {
@Parameter(name = "file", description = "Excel 文件", required = true),
@Parameter(name = "date", description = "日期", required = true),
@Parameter(name = "deptId", description = "公司编号", required = true),
@Parameter(name = "companyName", description = "公司名称", required = true),
@Parameter(name = "isUpdate", description = "是否允许覆盖", required = true)
})
@PreAuthorize("@ss.hasPermission('system:hr:payslip:import')")
public CommonResult<Boolean> importExcel(@RequestParam("file") MultipartFile file,
@RequestParam("date") String date,
@RequestParam("deptId") Long deptId,
@RequestParam("companyName") String companyName,
@RequestParam("isUpdate") Boolean isUpdate) throws Exception {
List<PayslipImportExcelVO> list = EasyExcel.read(file.getInputStream(), PayslipImportExcelVO.class, null)
@ -221,7 +229,7 @@ public class PayslipController {
.autoCloseStream(false) // 不要自动关闭交给 Servlet 自己处理
.doReadAllSync();
// 导入数据
payslipService.importPayslip(list, date, deptId, isUpdate);
payslipService.importPayslip(list, date, deptId, companyName, isUpdate);
return success(true);
}

View File

@ -25,6 +25,9 @@ public class PayslipCreateReqVO {
@Schema(description = "所属公司编号")
private Long companyDeptId;
@Schema(description = "所属公司名称")
private String companyName;
@Schema(description = "银行开户名")
private String bankName;

View File

@ -28,6 +28,9 @@ public class PayslipRespVO {
@Schema(description = "所属公司编号")
private Long companyDeptId;
@Schema(description = "公司名称", example = "芋道源码")
private String companyName;
@Schema(description = "银行开户名")
private String bankName;

View File

@ -40,6 +40,11 @@ public class PayslipDO extends BaseDO {
*/
private Long companyDeptId;
/**
* 所属公司名称
*/
private String companyName;
/**
* 薪资日期 YYYY-MM
*/

View File

@ -1252,7 +1252,7 @@ public class AttendanceServiceImpl implements AttendanceService {
.head(generateDailyHead(headTitle, detailedHead, maxSize))
.autoCloseStream(false)
.excelType(ExcelTypeEnum.XLS)
.registerWriteHandler(new CustomCellStyleHandler())
.registerWriteHandler(new CustomCellStyleHandler(null))
.sheet("考勤统计按日导出")
.doWrite(data);
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("考勤统计", StandardCharsets.UTF_8.name()));
@ -1399,7 +1399,7 @@ public class AttendanceServiceImpl implements AttendanceService {
.head(generateHead(headTitle, detailedHead))
.autoCloseStream(false)
.excelType(ExcelTypeEnum.XLS)
.registerWriteHandler(new CustomCellStyleHandler())
.registerWriteHandler(new CustomCellStyleHandler(null))
.sheet("考勤统计按月导出")
.doWrite(data);
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("考勤统计", StandardCharsets.UTF_8.name()));

View File

@ -14,6 +14,11 @@ import java.util.Map;
public class CustomCellStyleHandler implements CellWriteHandler {
private final Map<String, CellStyle> styleCache = new HashMap<>();
private final List<String> nameList;
public CustomCellStyleHandler(List<String> nameList) {
this.nameList = nameList;
}
@Override
public void afterCellDispose(
@ -32,6 +37,10 @@ public class CustomCellStyleHandler implements CellWriteHandler {
CellStyle cellStyle = getOrCreateCellStyle(workbook, isHead, relativeRowIndex, cellDataList);
cell.setCellStyle(cellStyle);
if (nameList != null && nameList.contains(cell.getStringCellValue())) {
cell.getRow().setHeightInPoints(150);
}
}
private CellStyle getOrCreateCellStyle(Workbook workbook, Boolean isHead, Integer relativeRowIndex, List<WriteCellData<?>> cellDataList) {

View File

@ -53,7 +53,7 @@ public interface PayslipService {
* 导入工资条
* @param list 导入工资条数据
*/
void importPayslip(List<PayslipImportExcelVO> list, String date, Long deptId, Boolean isUpdate);
void importPayslip(List<PayslipImportExcelVO> list, String date, Long deptId, String companyName, Boolean isUpdate);
/**
* 下发工资条

View File

@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.system.controller.admin.hr.vo.payslip.*;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.hr.PayslipDO;
@ -20,6 +21,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@ -51,6 +53,9 @@ public class PayslipServiceImpl implements PayslipService{
@Resource
private AdminUserService userService;
@Resource
private FileApi fileApi;
@Override
public void createPayslip(List<PayslipCreateReqVO> createReqVO) {
@ -87,12 +92,20 @@ public class PayslipServiceImpl implements PayslipService{
@Override
@Transactional(rollbackFor = Exception.class) // 添加事务异常则回滚所有导入
public void importPayslip(List<PayslipImportExcelVO> importList, String date, Long deptId, Boolean isUpdate) {
public void importPayslip(List<PayslipImportExcelVO> importList, String date, Long deptId, String companyName, Boolean isUpdate) {
if (CollUtil.isEmpty(importList)) {
throw exception(PAYSLIP_IMPORT_LIST_IS_EMPTY);
}
if (payslipMapper.selectCount(new LambdaQueryWrapperX<PayslipDO>()
.eq(PayslipDO::getSalaryDate, date)
.eqIfPresent(PayslipDO::getCompanyDeptId, deptId)
.eq(PayslipDO::getIsConfirm, 0)) > 0L) {
throw exception(PAYSLIP_ISSUED);
}
// 判断如果选择覆盖 则删除原有数据重新插入
if (isUpdate) {
payslipMapper.deletePayslip(date, deptId);
@ -125,6 +138,7 @@ public class PayslipServiceImpl implements PayslipService{
payslipDO.setBankName(data.getBankName());
payslipDO.setBankNo(data.getBankNo());
payslipDO.setRemark(data.getRemark());
payslipDO.setCompanyName(companyName);
/* begin 设置明细数据 */
List<PayslipDetail> details = new ArrayList<>();
@ -146,7 +160,7 @@ public class PayslipServiceImpl implements PayslipService{
// 误餐补助
detailList.add(new PayslipDetail()
.setCode("wcbz")
.setName("防暑降温费")
.setName("误餐补助")
.setValue(data.getWcbz()));
// 福利费
detailList.add(new PayslipDetail()
@ -258,11 +272,15 @@ public class PayslipServiceImpl implements PayslipService{
List<Long> userIds = convertList(list, PayslipRespVO::getUserId);
Map<Long, AdminUserDO> userMap = convertMap(userService.getUserList(userIds), AdminUserDO::getId);
List<List<String>> data = new ArrayList<>();
// 获取电子签名Map
Map<Long, String> signImgPathMap = fileApi.getUserSignImgPathMap(userIds).getCheckedData();
List<String> nameList = new ArrayList<>();
List<List<Object>> data = new ArrayList<>();
int count = 1;
for (PayslipRespVO payslipRespVO : list) {
List<String> row = new ArrayList<>();
List<Object> row = new ArrayList<>();
row.add(String.valueOf(count++));
row.add(payslipRespVO.getUserName());
row.add(userMap.get(payslipRespVO.getUserId()).getIdcard());
@ -275,14 +293,15 @@ public class PayslipServiceImpl implements PayslipService{
}else {
children.add(item);
}
return children.stream().collect(Collectors.toMap(PayslipDetail::getCode, PayslipDetail::getValue));
return children.stream().collect(Collectors.toMap(PayslipDetail::getCode,
value -> value.getValue() == null ? 0 : value.getValue()));
})
.flatMap(map -> map.entrySet().stream()) // 将每个 Map 转换为 Entry
.collect(Collectors.toMap(
Map.Entry::getKey, // 使用 Entry key
Map.Entry::getValue, // 使用 Entry value
(existing, replacement) -> existing // 处理键冲突保留现有值
));;
));
row.add(detailMap.get("jbgz").toString());
row.add(detailMap.get("fsjwf").toString());
@ -302,20 +321,25 @@ public class PayslipServiceImpl implements PayslipService{
row.add(payslipRespVO.getBankName());
row.add(payslipRespVO.getBankNo());
row.add(payslipRespVO.getRemark());
row.add(payslipRespVO.getSignURL());
if (payslipRespVO.getIsConfirm() == 1) {
row.add(new URL(signImgPathMap.get(payslipRespVO.getUserId())));
nameList.add(payslipRespVO.getUserName());
}else {
row.add("");
}
data.add(row);
}
// 获取公司信息
DeptDO deptDO = deptService.getDept(exportReqVO.getDeptId());
String headTitle = deptDO.getName() + exportReqVO.getDate() + "工资条";
EasyExcel.write(response.getOutputStream())
.head(getHead(headTitle, list.get(0)))
.autoCloseStream(false)
.excelType(ExcelTypeEnum.XLS)
.registerWriteHandler(new CustomCellStyleHandler())
.registerWriteHandler(new CustomCellStyleHandler(nameList))
.sheet("工资条")
.doWrite(data);
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("工资条", StandardCharsets.UTF_8.name()));