feat(system): 增加工资条导入功能并优化相关服务- 新增工资条导入相关的错误码常量
- 修改考勤统计导出功能,增加行高设置 - 优化工资条控制器和服务实现,支持导入功能- 更新数据库实体和相关VO,增加公司名称字段 - 重构工资条导出功能,优化数据处理和样式设置
This commit is contained in:
parent
3001531471
commit
ac47a0a252
@ -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, "所选公司在当前月份的工资条已下发,不能修改!");
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,9 @@ public class PayslipCreateReqVO {
|
||||
@Schema(description = "所属公司编号")
|
||||
private Long companyDeptId;
|
||||
|
||||
@Schema(description = "所属公司名称")
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "银行开户名")
|
||||
private String bankName;
|
||||
|
||||
|
@ -28,6 +28,9 @@ public class PayslipRespVO {
|
||||
@Schema(description = "所属公司编号")
|
||||
private Long companyDeptId;
|
||||
|
||||
@Schema(description = "公司名称", example = "芋道源码")
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "银行开户名")
|
||||
private String bankName;
|
||||
|
||||
|
@ -40,6 +40,11 @@ public class PayslipDO extends BaseDO {
|
||||
*/
|
||||
private Long companyDeptId;
|
||||
|
||||
/**
|
||||
* 所属公司名称
|
||||
*/
|
||||
private String companyName;
|
||||
|
||||
/**
|
||||
* 薪资日期 YYYY-MM
|
||||
*/
|
||||
|
@ -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()));
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
* 下发工资条
|
||||
|
@ -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()));
|
||||
|
Loading…
Reference in New Issue
Block a user