feat(oa): 新增工资明细批量插入接口支持字符串格式数字- 新增 BatchInsertSalaryStringDto 和 SalaryDetailStringDto 类用于处理字符串格式的工资数据
- 在 OaSalaryMasterController 中添加新的批量插入接口 - 实现 SalaryStringConverter 工具类用于字符串数据转换 - 优化了前端数据传输格式,支持驼峰命名的字符串数字
This commit is contained in:
@@ -19,7 +19,9 @@ import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.oa.domain.vo.OaSalaryMasterVo;
|
||||
import com.ruoyi.oa.domain.bo.OaSalaryMasterBo;
|
||||
import com.ruoyi.oa.domain.dto.BatchInsertSalaryStringDto;
|
||||
import com.ruoyi.oa.service.IOaSalaryMasterService;
|
||||
import com.ruoyi.oa.utils.SalaryStringConverter;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
@@ -109,4 +111,19 @@ public class OaSalaryMasterController extends BaseController {
|
||||
return toAjax(iOaSalaryMasterService.batchInsertDetails(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量插入工资明细(处理字符串数字格式)
|
||||
* 专门用于处理前端传递的驼峰命名但数字为字符串格式的数据
|
||||
*
|
||||
* @param requestDto 字符串格式的请求DTO
|
||||
*/
|
||||
@Log(title = "批量插入工资明细", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/batchInsertDetailsWithStringConvert")
|
||||
public R<Void> batchInsertDetailsWithStringConvert(@Validated @RequestBody BatchInsertSalaryStringDto requestDto) {
|
||||
// 将字符串DTO转换为后端BO
|
||||
OaSalaryMasterBo bo = SalaryStringConverter.convertToMasterBo(requestDto);
|
||||
return toAjax(iOaSalaryMasterService.batchInsertDetails(bo));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.ruoyi.oa.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 批量插入工资明细请求DTO - 处理驼峰命名的字符串数字格式
|
||||
*
|
||||
* @author Joshi
|
||||
* @date 2025-09-08
|
||||
*/
|
||||
@Data
|
||||
public class BatchInsertSalaryStringDto {
|
||||
|
||||
/**
|
||||
* 单位名称
|
||||
*/
|
||||
@NotBlank(message = "单位名称不能为空")
|
||||
private String unitName;
|
||||
|
||||
/**
|
||||
* 工资所属期间,格式如:2025-8
|
||||
*/
|
||||
@NotBlank(message = "工资期间不能为空")
|
||||
private String salaryPeriod;
|
||||
|
||||
/**
|
||||
* 总经理审批状态或姓名
|
||||
*/
|
||||
private String gmApproval;
|
||||
|
||||
/**
|
||||
* 财务审核状态或姓名
|
||||
*/
|
||||
private String financeAudit;
|
||||
|
||||
/**
|
||||
* 出纳姓名
|
||||
*/
|
||||
private String cashier;
|
||||
|
||||
/**
|
||||
* 部门主管姓名
|
||||
*/
|
||||
private String deptManager;
|
||||
|
||||
/**
|
||||
* 经办人姓名
|
||||
*/
|
||||
private String operator;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 工资明细列表
|
||||
*/
|
||||
@Valid
|
||||
@NotEmpty(message = "明细列表不能为空")
|
||||
private List<SalaryDetailStringDto> salaryDetailList;
|
||||
}
|
||||
@@ -0,0 +1,377 @@
|
||||
package com.ruoyi.oa.domain.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 工资明细字符串DTO - 用于接收前端字符串格式的数字字段
|
||||
*
|
||||
* @author Joshi
|
||||
* @date 2025-09-08
|
||||
*/
|
||||
@Data
|
||||
public class SalaryDetailStringDto {
|
||||
|
||||
/**
|
||||
* 主键,自增
|
||||
*/
|
||||
private Long detailId;
|
||||
|
||||
/**
|
||||
* 关联主表ID
|
||||
*/
|
||||
private Long mainId;
|
||||
|
||||
/**
|
||||
* 序号(字符串格式)
|
||||
*/
|
||||
private String serialNumber;
|
||||
|
||||
/**
|
||||
* 部门
|
||||
*/
|
||||
private String dept;
|
||||
|
||||
/**
|
||||
* 员工姓名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 基本工资(字符串格式)
|
||||
*/
|
||||
private String basicSalary;
|
||||
|
||||
/**
|
||||
* 岗位工资(字符串格式)
|
||||
*/
|
||||
private String postSalary;
|
||||
|
||||
/**
|
||||
* 餐补(字符串格式)
|
||||
*/
|
||||
private String mealAllowance;
|
||||
|
||||
/**
|
||||
* 住房补贴(字符串格式)
|
||||
*/
|
||||
private String housingAllowance;
|
||||
|
||||
/**
|
||||
* 公交补贴(字符串格式)
|
||||
*/
|
||||
private String busAllowance;
|
||||
|
||||
/**
|
||||
* 出差天数(字符串格式)
|
||||
*/
|
||||
private String businessDaysOther;
|
||||
|
||||
/**
|
||||
* 出差补助(字符串格式)
|
||||
*/
|
||||
private String businessAllowance;
|
||||
|
||||
/**
|
||||
* 社保补助(字符串格式)
|
||||
*/
|
||||
private String socialSecurityAllowance;
|
||||
|
||||
/**
|
||||
* 加班时长(字符串格式)
|
||||
*/
|
||||
private String overtimeHours;
|
||||
|
||||
/**
|
||||
* 加班标准(字符串格式)
|
||||
*/
|
||||
private String overtimeRate;
|
||||
|
||||
/**
|
||||
* 加班工资总计(字符串格式)
|
||||
*/
|
||||
private String overtimeTotal;
|
||||
|
||||
/**
|
||||
* 出勤天数(字符串格式)
|
||||
*/
|
||||
private String businessDays;
|
||||
|
||||
/**
|
||||
* 请假扣款(字符串格式)
|
||||
*/
|
||||
private String leaveDeduction;
|
||||
|
||||
/**
|
||||
* 其他扣款(字符串格式)
|
||||
*/
|
||||
private String otherDeduction;
|
||||
|
||||
/**
|
||||
* 应发工资(字符串格式)
|
||||
*/
|
||||
private String grossSalary;
|
||||
|
||||
/**
|
||||
* 个人缴纳养老保险(字符串格式)
|
||||
*/
|
||||
private String personalPension;
|
||||
|
||||
/**
|
||||
* 个人缴纳医疗保险(字符串格式)
|
||||
*/
|
||||
private String personalMedical;
|
||||
|
||||
/**
|
||||
* 个人缴纳失业保险(字符串格式)
|
||||
*/
|
||||
private String personalUnemployment;
|
||||
|
||||
/**
|
||||
* 个人缴纳大病医疗(字符串格式)
|
||||
*/
|
||||
private String personalBigMedical;
|
||||
|
||||
/**
|
||||
* 个人缴纳住房公积金(字符串格式)
|
||||
*/
|
||||
private String personalHousingFund;
|
||||
|
||||
/**
|
||||
* 个人所得税(字符串格式)
|
||||
*/
|
||||
private String personalTax;
|
||||
|
||||
/**
|
||||
* 实发工资(字符串格式)
|
||||
*/
|
||||
private String netSalary;
|
||||
|
||||
/**
|
||||
* 企业缴纳养老保险(字符串格式)
|
||||
*/
|
||||
private String enterprisePension;
|
||||
|
||||
/**
|
||||
* 企业缴纳医疗保险(字符串格式)
|
||||
*/
|
||||
private String enterpriseMedical;
|
||||
|
||||
/**
|
||||
* 企业缴纳工伤保险(字符串格式)
|
||||
*/
|
||||
private String enterpriseInjury;
|
||||
|
||||
/**
|
||||
* 企业缴纳失业保险(字符串格式)
|
||||
*/
|
||||
private String enterpriseUnemployment;
|
||||
|
||||
/**
|
||||
* 企业缴纳生育保险(字符串格式)
|
||||
*/
|
||||
private String enterpriseMaternity;
|
||||
|
||||
/**
|
||||
* 企业缴纳住房公积金(字符串格式)
|
||||
*/
|
||||
private String enterpriseHousingFund;
|
||||
|
||||
/**
|
||||
* 企业缴纳大病医疗(字符串格式)
|
||||
*/
|
||||
private String enterpriseBigMedical;
|
||||
|
||||
/**
|
||||
* 单位总支出(字符串格式)
|
||||
*/
|
||||
private String unitTotalExpense;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
// 辅助方法:安全地将字符串转换为BigDecimal
|
||||
@JsonIgnore
|
||||
private BigDecimal parseDecimal(String value) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
try {
|
||||
return new BigDecimal(value.trim());
|
||||
} catch (NumberFormatException e) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助方法:安全地将字符串转换为Long
|
||||
@JsonIgnore
|
||||
private Long parseLong(String value) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
try {
|
||||
return Long.parseLong(value.trim());
|
||||
} catch (NumberFormatException e) {
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
// 转换方法,返回数值类型
|
||||
@JsonIgnore
|
||||
public Long getSerialNumberAsLong() {
|
||||
return parseLong(serialNumber);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getBasicSalaryAsDecimal() {
|
||||
return parseDecimal(basicSalary);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getPostSalaryAsDecimal() {
|
||||
return parseDecimal(postSalary);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getMealAllowanceAsDecimal() {
|
||||
return parseDecimal(mealAllowance);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getHousingAllowanceAsDecimal() {
|
||||
return parseDecimal(housingAllowance);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getBusAllowanceAsDecimal() {
|
||||
return parseDecimal(busAllowance);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public Long getBusinessDaysOtherAsLong() {
|
||||
return parseLong(businessDaysOther);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getBusinessAllowanceAsDecimal() {
|
||||
return parseDecimal(businessAllowance);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getSocialSecurityAllowanceAsDecimal() {
|
||||
return parseDecimal(socialSecurityAllowance);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getOvertimeHoursAsDecimal() {
|
||||
return parseDecimal(overtimeHours);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getOvertimeRateAsDecimal() {
|
||||
return parseDecimal(overtimeRate);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getOvertimeTotalAsDecimal() {
|
||||
return parseDecimal(overtimeTotal);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public Long getBusinessDaysAsLong() {
|
||||
return parseLong(businessDays);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getLeaveDeductionAsDecimal() {
|
||||
return parseDecimal(leaveDeduction);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getOtherDeductionAsDecimal() {
|
||||
return parseDecimal(otherDeduction);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getGrossSalaryAsDecimal() {
|
||||
return parseDecimal(grossSalary);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getPersonalPensionAsDecimal() {
|
||||
return parseDecimal(personalPension);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getPersonalMedicalAsDecimal() {
|
||||
return parseDecimal(personalMedical);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getPersonalUnemploymentAsDecimal() {
|
||||
return parseDecimal(personalUnemployment);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getPersonalBigMedicalAsDecimal() {
|
||||
return parseDecimal(personalBigMedical);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getPersonalHousingFundAsDecimal() {
|
||||
return parseDecimal(personalHousingFund);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getPersonalTaxAsDecimal() {
|
||||
return parseDecimal(personalTax);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getNetSalaryAsDecimal() {
|
||||
return parseDecimal(netSalary);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getEnterprisePensionAsDecimal() {
|
||||
return parseDecimal(enterprisePension);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getEnterpriseMedicalAsDecimal() {
|
||||
return parseDecimal(enterpriseMedical);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getEnterpriseInjuryAsDecimal() {
|
||||
return parseDecimal(enterpriseInjury);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getEnterpriseUnemploymentAsDecimal() {
|
||||
return parseDecimal(enterpriseUnemployment);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getEnterpriseMaternityAsDecimal() {
|
||||
return parseDecimal(enterpriseMaternity);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getEnterpriseHousingFundAsDecimal() {
|
||||
return parseDecimal(enterpriseHousingFund);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getEnterpriseBigMedicalAsDecimal() {
|
||||
return parseDecimal(enterpriseBigMedical);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public BigDecimal getUnitTotalExpenseAsDecimal() {
|
||||
return parseDecimal(unitTotalExpense);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.ruoyi.oa.utils;
|
||||
|
||||
import com.ruoyi.oa.domain.bo.OaSalaryDetailBo;
|
||||
import com.ruoyi.oa.domain.bo.OaSalaryMasterBo;
|
||||
import com.ruoyi.oa.domain.dto.BatchInsertSalaryStringDto;
|
||||
import com.ruoyi.oa.domain.dto.SalaryDetailStringDto;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 工资字符串数据转换工具类
|
||||
*
|
||||
* @author Joshi
|
||||
* @date 2025-09-08
|
||||
*/
|
||||
public class SalaryStringConverter {
|
||||
|
||||
/**
|
||||
* 将字符串格式的请求DTO转换为后端BO对象
|
||||
*
|
||||
* @param requestDto 字符串格式的请求DTO
|
||||
* @return 后端BO对象
|
||||
*/
|
||||
public static OaSalaryMasterBo convertToMasterBo(BatchInsertSalaryStringDto requestDto) {
|
||||
if (requestDto == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
OaSalaryMasterBo masterBo = new OaSalaryMasterBo();
|
||||
masterBo.setUnitName(requestDto.getUnitName());
|
||||
masterBo.setSalaryPeriod(requestDto.getSalaryPeriod());
|
||||
masterBo.setGmApproval(requestDto.getGmApproval());
|
||||
masterBo.setFinanceAudit(requestDto.getFinanceAudit());
|
||||
masterBo.setCashier(requestDto.getCashier());
|
||||
masterBo.setDeptManager(requestDto.getDeptManager());
|
||||
masterBo.setOperator(requestDto.getOperator());
|
||||
masterBo.setRemark(requestDto.getRemark());
|
||||
|
||||
// 转换明细列表
|
||||
if (CollUtil.isNotEmpty(requestDto.getSalaryDetailList())) {
|
||||
List<OaSalaryDetailBo> detailBoList = requestDto.getSalaryDetailList().stream()
|
||||
.map(SalaryStringConverter::convertToDetailBo)
|
||||
.collect(Collectors.toList());
|
||||
masterBo.setSalaryDetailList(detailBoList);
|
||||
}
|
||||
|
||||
return masterBo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串格式的明细DTO转换为后端明细BO对象
|
||||
*
|
||||
* @param stringDto 字符串格式的明细DTO
|
||||
* @return 后端明细BO对象
|
||||
*/
|
||||
public static OaSalaryDetailBo convertToDetailBo(SalaryDetailStringDto stringDto) {
|
||||
if (stringDto == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
OaSalaryDetailBo detailBo = new OaSalaryDetailBo();
|
||||
|
||||
// 基本信息
|
||||
detailBo.setDetailId(stringDto.getDetailId());
|
||||
detailBo.setMainId(stringDto.getMainId());
|
||||
detailBo.setSerialNumber(stringDto.getSerialNumberAsLong());
|
||||
detailBo.setDept(stringDto.getDept());
|
||||
detailBo.setName(stringDto.getName());
|
||||
detailBo.setRemark(stringDto.getRemark());
|
||||
|
||||
// 工资项目 - 使用转换方法
|
||||
detailBo.setBasicSalary(stringDto.getBasicSalaryAsDecimal());
|
||||
detailBo.setPostSalary(stringDto.getPostSalaryAsDecimal());
|
||||
detailBo.setMealAllowance(stringDto.getMealAllowanceAsDecimal());
|
||||
detailBo.setHousingAllowance(stringDto.getHousingAllowanceAsDecimal());
|
||||
detailBo.setBusAllowance(stringDto.getBusAllowanceAsDecimal());
|
||||
detailBo.setBusinessDaysOther(stringDto.getBusinessDaysOtherAsLong());
|
||||
detailBo.setBusinessAllowance(stringDto.getBusinessAllowanceAsDecimal());
|
||||
detailBo.setSocialSecurityAllowance(stringDto.getSocialSecurityAllowanceAsDecimal());
|
||||
|
||||
// 加班相关
|
||||
detailBo.setOvertimeHours(stringDto.getOvertimeHoursAsDecimal());
|
||||
detailBo.setOvertimeRate(stringDto.getOvertimeRateAsDecimal());
|
||||
detailBo.setOvertimeTotal(stringDto.getOvertimeTotalAsDecimal());
|
||||
detailBo.setBusinessDays(stringDto.getBusinessDaysAsLong());
|
||||
|
||||
// 扣款项目
|
||||
detailBo.setLeaveDeduction(stringDto.getLeaveDeductionAsDecimal());
|
||||
detailBo.setOtherDeduction(stringDto.getOtherDeductionAsDecimal());
|
||||
detailBo.setGrossSalary(stringDto.getGrossSalaryAsDecimal());
|
||||
|
||||
// 个人缴费
|
||||
detailBo.setPersonalPension(stringDto.getPersonalPensionAsDecimal());
|
||||
detailBo.setPersonalMedical(stringDto.getPersonalMedicalAsDecimal());
|
||||
detailBo.setPersonalUnemployment(stringDto.getPersonalUnemploymentAsDecimal());
|
||||
detailBo.setPersonalBigMedical(stringDto.getPersonalBigMedicalAsDecimal());
|
||||
detailBo.setPersonalHousingFund(stringDto.getPersonalHousingFundAsDecimal());
|
||||
detailBo.setPersonalTax(stringDto.getPersonalTaxAsDecimal());
|
||||
detailBo.setNetSalary(stringDto.getNetSalaryAsDecimal());
|
||||
|
||||
// 企业缴费
|
||||
detailBo.setEnterprisePension(stringDto.getEnterprisePensionAsDecimal());
|
||||
detailBo.setEnterpriseMedical(stringDto.getEnterpriseMedicalAsDecimal());
|
||||
detailBo.setEnterpriseInjury(stringDto.getEnterpriseInjuryAsDecimal());
|
||||
detailBo.setEnterpriseUnemployment(stringDto.getEnterpriseUnemploymentAsDecimal());
|
||||
detailBo.setEnterpriseMaternity(stringDto.getEnterpriseMaternityAsDecimal());
|
||||
detailBo.setEnterpriseHousingFund(stringDto.getEnterpriseHousingFundAsDecimal());
|
||||
detailBo.setEnterpriseBigMedical(stringDto.getEnterpriseBigMedicalAsDecimal());
|
||||
detailBo.setUnitTotalExpense(stringDto.getUnitTotalExpenseAsDecimal());
|
||||
|
||||
return detailBo;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user