1、薪资核算新增环比上月数据

2、核算归档后依旧可查看上月环比数据界面
3、个税申报表批量多选申报【现阶段仅能选择一个个税扣缴义务人来生成申报表】
4、个税申报表增加一个 批量撤回按钮 【跳出一个界面选择 与申报界面一致,可批量选择个税扣缴义务人与薪资所属月来进行批量撤回】
5、薪资核算界面内增加搜索个税扣缴义务人。以及搜索归档与未归档的核算。(按状态筛选)
6、薪资核算时,二级部门需与员工的一级部门进行对应【现阶段员工二级部门由导入与sql自动带出两个方式,若为员工手动导入,则需审核】图2为对应表
This commit is contained in:
鱼不吐泡泡 2026-02-11 11:43:22 +08:00
parent 8911d28822
commit 2ac0498073
28 changed files with 1108 additions and 172 deletions

View File

@ -19,6 +19,7 @@ import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import weaver.hrm.User;
import java.util.*;
import java.util.stream.Collectors;
@ -50,7 +51,7 @@ public class SalaryAcctRecordBO {
List<TaxAgentPO> taxAgentPOS,
List<Long> needApprovalSalarySobIds,
boolean approvalCanFile,
boolean approvalCanReCalc) {
boolean approvalCanReCalc, User user) {
if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
return Collections.emptyList();
}
@ -66,10 +67,11 @@ public class SalaryAcctRecordBO {
// 只有未归档时可以"核算""删除""归档"
// 归档后工资单全部发放以后可以"查看""重新核算""回算"
// 归档后申报后可以"查看""重新核算"
// 2025-12-18 薪资核算删除重新核算隐藏这两个按钮只有系统管理员可见可使用
List<WeaTableOperate> btnList = new ArrayList<>();
if (SalaryAcctRecordStatusEnum.NOT_ARCHIVED == salaryAcctRecordStatusEnum) {
btnList.add(new WeaTableOperate("核算", null, "0"));
if(!Objects.equals(salaryAcctRecordPO.getBackCalcStatus(),NumberUtils.INTEGER_ONE)){
if(!Objects.equals(salaryAcctRecordPO.getBackCalcStatus(),NumberUtils.INTEGER_ONE) && user.getUID() == 1){
btnList.add(new WeaTableOperate("删除", null, "1"));
}
if (approvalCanFile || !needApprovalSalarySobIds.contains(salaryAcctRecordPO.getSalarySobId())) {
@ -77,7 +79,7 @@ public class SalaryAcctRecordBO {
}
} else if (SalaryAcctRecordStatusEnum.ARCHIVED == salaryAcctRecordStatusEnum && ( salarySendMap.get(salaryAcctRecordPO.getId()) ==Boolean.TRUE ) ){
btnList.add(new WeaTableOperate("查看", null, "3"));
if (approvalCanReCalc || !needApprovalSalarySobIds.contains(salaryAcctRecordPO.getSalarySobId())) {
if ((approvalCanReCalc || !needApprovalSalarySobIds.contains(salaryAcctRecordPO.getSalarySobId())) && user.getUID() == 1) {
btnList.add(new WeaTableOperate("重新核算", null, "4"));
}
if(salaryAcctRecordPO.getBackCalcStatus() == null || salaryAcctRecordPO.getBackCalcStatus() == NumberUtils.INTEGER_ZERO) {
@ -85,7 +87,7 @@ public class SalaryAcctRecordBO {
}
} else {
btnList.add(new WeaTableOperate("查看", null, "3"));
if (approvalCanReCalc || !needApprovalSalarySobIds.contains(salaryAcctRecordPO.getSalarySobId())) {
if ((approvalCanReCalc || !needApprovalSalarySobIds.contains(salaryAcctRecordPO.getSalarySobId())) && user.getUID() == 1) {
btnList.add(new WeaTableOperate("重新核算", null, "4"));
}
}

View File

@ -0,0 +1,36 @@
package com.engine.salary.entity.salaryacct.dto;
import com.engine.salary.annotation.TableTitle;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 2025-12-11 环比上月实发工资差额列表
*
* @author ydh
* @version 1.0
* @date 2025/12/11 10:05
**/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SalaryAccGzceListDTO {
//主键id
private Long id;
//人员id
private Long employeeId;
//姓名
@TableTitle(title = "姓名", dataIndex = "employeeName", key = "employeeName")
private String employeeName;
// 实发工资差额
@TableTitle(title = "实发工资差额", dataIndex = "sfgzce", key = "sfgzce")
private double sfgzce;
}

View File

@ -39,4 +39,6 @@ public class SalaryAcctRecordQueryParam extends BaseQueryParam {
private String startMonthStr;
private String endMonthStr;
// 状态 0 1 未归档 2 已归档 3 已申报
private String status;
}

View File

@ -36,6 +36,8 @@ public class SalaryAcctResultQueryParam extends BaseQueryParam {
//个税扣缴义务人
private Long taxAgentId;
//个税扣缴义务人(多选)
private List<Long> taxAgentIds;
//分部
private Collection<Long> subcompanyIds;

View File

@ -152,7 +152,7 @@ public class SalarySobItemAggregateBO {
.canEdit(openFormulaForcedEditing || Objects.equals(salaryItemPO.getCanEdit(), 1))
.canDelete(openFormulaForcedEditing || salaryItemPO.getCanDelete() == null || Objects.equals(salaryItemPO.getCanDelete(), 1))
.width(salaryItemPO.getWidth())
.defaultValue(salarySobItemPO.getDefaultValue())
.defaultValue(salaryItemPO.getDefaultValue())
.build());
}
}

View File

@ -12,6 +12,7 @@ import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationDetailListDTO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationListDTO;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParamNew;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationDetailPO;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO;
import com.engine.salary.enums.salaryaccounting.EmployeeTypeEnum;
@ -137,7 +138,7 @@ public class TaxDeclarationBO {
page.setList(dtos);
}
public static Result handle(TaxDeclarationSaveParam saveParam,
public static Result handle(TaxDeclarationSaveParamNew saveParam,
Date taxCycle,
User user,
List<SalaryItemPO> salaryItems,
@ -653,7 +654,7 @@ public class TaxDeclarationBO {
// });
// }
private static TaxDeclarationPO convert2PO(TaxDeclarationSaveParam saveParam, User user, Date taxCycle, Long taxAgentId, Integer incomeCategory) {
private static TaxDeclarationPO convert2PO(TaxDeclarationSaveParamNew saveParam, User user, Date taxCycle, Long taxAgentId, Integer incomeCategory) {
LocalDateTime now = LocalDateTime.now();
if (saveParam.getDescription() == null) {
saveParam.setDescription("");
@ -723,7 +724,6 @@ public class TaxDeclarationBO {
private static String findStringValue(String fieldCode, Map<Long, List<SalaryAcctResultPO>> resultMap, Map<String, Long> salaryItemMap) {
return resultMap.getOrDefault(salaryItemMap.getOrDefault(fieldCode, 0L), Collections.emptyList()).stream()
.map(SalaryAcctResultPO::getResultValue)
.filter(Objects::nonNull)
.findFirst().orElse("");
}

View File

@ -1,5 +1,6 @@
package com.engine.salary.entity.taxdeclaration.bo;
import com.alibaba.fastjson.JSONObject;
import com.engine.salary.constant.TaxDeclarationDataIndexConstant;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationAnnualListDTO;
@ -13,7 +14,11 @@ import com.engine.salary.util.SalaryI18nUtil;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.User;
import weaver.hrm.company.DepartmentComInfo;
import weaver.soa.hrm.Department;
import java.util.*;
@ -40,6 +45,8 @@ public class TaxDeclarationDetailBO {
if (CollectionUtils.isEmpty(taxDeclarationDetailPOS)) {
return Collections.emptyList();
}
new BaseBean().writeLog("INFO","转换成个税申报表详情列表(正常工资薪金所得)==>");
DepartmentComInfo departmentComInfo = new DepartmentComInfo();
List<TaxDeclarationWageListDTO> taxDeclarationWageListDTOS = Lists.newArrayListWithExpectedSize(taxDeclarationEmployeeDTOS.size());
Map<String, List<TaxDeclarationDetailPO>> employeeIdKeyTaxDeclarationDetailPOMap = SalaryEntityUtil.group2Map(taxDeclarationDetailPOS,
taxDeclarationDetailPO -> EmployeeTypeEnum.ORGANIZATION.getValue() + "_" + taxDeclarationDetailPO.getEmployeeId());
@ -72,10 +79,15 @@ public class TaxDeclarationDetailBO {
.description(fieldCodeKeyFieldValueMap.get(TaxDeclarationDataIndexConstant.DESCRIPTION)).build();
if (dto.getEmployeeType() == null || Objects.equals(dto.getEmployeeType(), EmployeeTypeEnum.ORGANIZATION.getValue())) {
DataCollectionEmployee simpleEmployee = simpleEmployeeMap.get(dto.getEmployeeId());
int userId = Math.toIntExact(dto.getEmployeeId());
User user = new User(userId);
String deptName = departmentComInfo.getDepartmentname(String.valueOf(user.getUserDepartment()));
new BaseBean().writeLog("INFO","姓名==>"+simpleEmployee.getUsername()+",部门==>"+deptName);
taxDeclarationWageListDTO.setId(simpleEmployee.getEmployeeId())
.setEmployeeId(simpleEmployee.getEmployeeId())
.setJobNum(simpleEmployee.getWorkcode())
.setUsername(simpleEmployee.getUsername())
.setXmmc(deptName)
.setCardNum(Optional.ofNullable(simpleEmployee).map(DataCollectionEmployee::getIdNo).orElse(StringUtils.EMPTY));
} else {
// ExtEmployeePO extEmployeePO = extEmployeePOMap.get(dto.getEmployeeId());
@ -87,6 +99,7 @@ public class TaxDeclarationDetailBO {
}
taxDeclarationWageListDTOS.add(taxDeclarationWageListDTO);
}
new BaseBean().writeLog("INFO","taxDeclarationWageListDTOS输出==>"+ JSONObject.toJSONString(taxDeclarationWageListDTOS));
return taxDeclarationWageListDTOS;
}
@ -127,6 +140,7 @@ public class TaxDeclarationDetailBO {
DataCollectionEmployee simpleEmployee = simpleEmployeeMap.get(dto.getEmployeeId());
taxDeclarationLaborListDTO.setJobNum(simpleEmployee.getWorkcode())
.setUsername(simpleEmployee.getUsername())
.setXmmc(simpleEmployee.getDepartmentName())
.setCardNum(Optional.ofNullable(simpleEmployee).map(DataCollectionEmployee::getIdNo).orElse(StringUtils.EMPTY));
} else {
@ -170,6 +184,7 @@ public class TaxDeclarationDetailBO {
DataCollectionEmployee simpleEmployee = simpleEmployeeMap.getOrDefault(dto.getEmployeeId(),new DataCollectionEmployee());
taxDeclarationLaborListDTO.setJobNum(Util.null2String(simpleEmployee.getWorkcode()))
.setUsername(Util.null2String(simpleEmployee.getUsername()))
.setXmmc(Util.null2String(simpleEmployee.getDepartmentName()))
.setCardNum(Optional.ofNullable(simpleEmployee).map(DataCollectionEmployee::getIdNo).orElse(StringUtils.EMPTY));
} else {

View File

@ -42,6 +42,11 @@ public class TaxDeclarationAnnualListDTO {
@ExcelHead(title ="姓名",dataIndex = "username")
private String username;
@SalaryTableColumn(text = "项目名称", width = "10%", column = "xmmc")
@TableTitle(title = "项目名称", dataIndex = "xmmc", key = "xmmc")
@ExcelHead(title = "项目名称", dataIndex = "xmmc")
private String xmmc;
@SalaryTableColumn(
text = "证件类型", width = "10%", column = "cardType"
)

View File

@ -42,6 +42,11 @@ public class TaxDeclarationLaborListDTO {
@ExcelHead(title = "姓名", dataIndex = "username")
private String username;
@SalaryTableColumn(text = "项目名称", width = "10%", column = "xmmc")
@TableTitle(title = "项目名称", dataIndex = "xmmc", key = "xmmc")
@ExcelHead(title = "项目名称", dataIndex = "xmmc")
private String xmmc;
@SalaryTableColumn(
text = "证件类型", width = "10%", column = "cardType"
)

View File

@ -44,6 +44,11 @@ public class TaxDeclarationWageListDTO {
@ExcelHead(title = "姓名", dataIndex = "username")
private String username;
@SalaryTableColumn(text = "项目名称", width = "10%", column = "xmmc")
@TableTitle(title = "项目名称", dataIndex = "xmmc", key = "xmmc")
@ExcelHead(title = "项目名称", dataIndex = "xmmc")
private String xmmc;
@SalaryTableColumn(text = "证件类型", width = "10%", column = "cardType")
@TableTitle(title = "证件类型", dataIndex = "cardType", key = "cardType")
@ExcelHead(title = "证件类型", dataIndex = "cardType")

View File

@ -0,0 +1,54 @@
package com.engine.salary.entity.taxdeclaration.param;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.YearMonth;
import java.util.Date;
/**
* 生成个税申报表参数
* <p>Copyright: Copyright (c) 2022</p>
* <p>Company: 泛微软件</p>
*
* @author ydh
* @version 1.0
* @version 1.1 支持多个个税扣缴义务人
**/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TaxDeclarationSaveParamNew {
/**
* 个税申报id
*/
private Long taxDeclarationId;
/**
* 薪资所属月
*/
private YearMonth salaryMonth;
/**
* 个税扣缴义务人 多个
*/
private String taxAgentId;
/**
* 备注
*/
private String description;
private String salaryMonthStr;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date taxCycle;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date salaryDate;
}

View File

@ -3,6 +3,7 @@ package com.engine.salary.maintainer.datacollection;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParamNew;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO;
import com.engine.salary.mapper.taxdeclaration.TaxDeclarationMapper;
import com.engine.salary.service.TaxDeclarationService;
@ -54,7 +55,7 @@ public class AddUpSituationManager extends Service {
// 调用生成申报单接口
YearMonth yearMonth = YearMonth.of(localDate.getYear(), localDate.getMonth());
try {
getTaxDeclarationService().save(TaxDeclarationSaveParam.builder().salaryMonth(yearMonth).salaryDate(po.getSalaryMonth()).taxCycle(po.getTaxCycle()).taxAgentId(po.getTaxAgentId()).build());
getTaxDeclarationService().save(TaxDeclarationSaveParamNew.builder().salaryMonth(yearMonth).salaryDate(po.getSalaryMonth()).taxCycle(po.getTaxCycle()).taxAgentId(po.getTaxAgentId().toString()).build());
} catch (Exception e) {
bb.writeLog("错误:" + e);
result = false;

View File

@ -119,6 +119,9 @@
<if test="tenantKey != null">
AND t.tenant_key = #{tenantKey}
</if>
<if test="status != null">
AND t.status = #{status}
</if>
<if test="ids != null and ids.size()>0">
AND t.id IN
<foreach collection="ids" open="(" item="id" separator="," close=")">

View File

@ -1,9 +1,11 @@
package com.engine.salary.mapper.taxdeclaration;
import com.engine.salary.common.LocalDateRange;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.Date;
import java.util.List;

View File

@ -152,5 +152,4 @@
#{id}
</foreach>
</update>
</mapper>

View File

@ -1,5 +1,6 @@
package com.engine.salary.service;
import com.engine.salary.entity.salaryacct.dto.SalaryAccGzceListDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctEmployeeCountDTO;
import com.engine.salary.entity.salaryacct.param.*;
import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO;
@ -156,6 +157,15 @@ public interface SalaryAcctEmployeeService {
*/
PageInfo<SalaryAcctEmployeePO> listPageByParam4Add(SalaryAcctEmployeeQueryParam queryParam);
/**
* 2025-12-11 新增环比上月实发工资差额列表
* 根据列表查询条件查询环比上月实发工资差额列表分页
*
* @param queryParam 列表查询条件
* @return
*/
PageInfo<SalaryAccGzceListDTO> listPageByParam4Gzce(SalaryAcctEmployeeQueryParam queryParam);
/**
* 根据列表查询条件查询同比减少的薪资核算人员
*
@ -171,6 +181,13 @@ public interface SalaryAcctEmployeeService {
* @return
*/
List<SalaryAcctEmployeePO> listByParam4Add(SalaryAcctEmployeeQueryParam queryParam);
/**
* 根据列表查询条件查询同比增加的薪资核算人员
*
* @param queryParam 列表查询条件
* @return
*/
List<SalaryAccGzceListDTO> listByParam4Gzce(SalaryAcctEmployeeQueryParam queryParam);
/**
* 根据列表查询条件查询合并计税的薪资核算人员分页

View File

@ -4,6 +4,7 @@ import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationListQueryParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParamNew;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO;
import com.engine.salary.util.page.PageInfo;
@ -28,7 +29,7 @@ public interface TaxDeclarationService {
TaxDeclarationPO getById(Long id);
void save(TaxDeclarationSaveParam saveParam);
void save(TaxDeclarationSaveParamNew saveParam);
/**
* 删除个税申报表
@ -50,4 +51,9 @@ public interface TaxDeclarationService {
* @param taxDeclarationId
*/
void withDrawTaxDeclaration(Long taxDeclarationId);
/**
* 批量撤回个税申报单
* @param param
*/
void batchDeleteTaxDeclaration(TaxDeclarationSaveParamNew param);
}

View File

@ -194,11 +194,7 @@ public class AddUpDeductionServiceImpl extends Service implements AddUpDeduction
String imageId = Util.null2String(importParam.getImageId());
Validate.notBlank(imageId, "imageId为空");
// 获取所有个税扣缴义务人
// 获取所有个税扣缴义务人
TaxAgentQueryParam param = TaxAgentQueryParam.builder().build();
param.setFilterType(AuthFilterTypeEnum.ADMIN_DATA);
Collection<TaxAgentPO> taxAgentList = getTaxAgentService(user).listAuth(param);
// Collection<TaxAgentManageRangeEmployeeDTO> taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree(currentEmployeeId);
Collection<TaxAgentManageRangeEmployeeDTO> taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree(currentEmployeeId);
//个税扣缴义务人
String taxAgentId = Util.null2String(importParam.getTaxAgentId());
// 获取租户下所有的人员
@ -306,18 +302,18 @@ public class AddUpDeductionServiceImpl extends Service implements AddUpDeduction
errorData.add(errorMessageMap);
errorSum += 1;
} else {
Optional<TaxAgentPO> optionalTemp = taxAgentList.stream().filter(m -> m.getName().equals(taxAgentName)).findFirst();
Optional<TaxAgentManageRangeEmployeeDTO> optionalTemp = taxAgentList.stream().filter(m -> m.getTaxAgentName().equals(taxAgentName)).findFirst();
if (optionalTemp.isPresent()) {
// 2025-10-09 个税扣缴义务人选择全部时不校验
if (StringUtils.isNotEmpty(taxAgentId) && !"-999".equals(taxAgentId)&& !optionalTemp.get().getId().equals(Long.valueOf(taxAgentId))) {
if (StringUtils.isNotEmpty(taxAgentId) && !"-999".equals(taxAgentId)&& !optionalTemp.get().getTaxAgentId().equals(Long.valueOf(taxAgentId))) {
//个税扣缴义务人与导入时选择的不一致
Map<String, String> errorMessageMap = Maps.newHashMap();
errorMessageMap.put("message", rowIndex + "个税扣缴义务人与导入时选择的不一致");
errorData.add(errorMessageMap);
errorSum += 1;
} else {
addUpDeduction.setTaxAgentId(optionalTemp.get().getId());
// taxAgentEmployees = optionalTemp.get().getEmployeeList();
addUpDeduction.setTaxAgentId(optionalTemp.get().getTaxAgentId());
taxAgentEmployees = optionalTemp.get().getEmployeeList();
}
} else {
//个税扣缴义务人不存在

View File

@ -10,6 +10,7 @@ import com.engine.salary.config.SalaryElogConfig;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctConfig;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctEmployeeBO;
import com.engine.salary.entity.salaryacct.dto.SalaryAccGzceListDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctEmployeeCountDTO;
import com.engine.salary.entity.salaryacct.param.*;
import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO;
@ -47,12 +48,17 @@ import com.engine.salary.util.page.SalaryPageUtil;
import com.engine.salary.util.valid.ValidUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.ydh.ldkj.utils.CommonUtils;
import com.ydh.ldkj.utils.HrsaSalaryUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.User;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@ -302,7 +308,23 @@ public class SalaryAcctEmployeeServiceImpl extends Service implements SalaryAcct
salaryAcctEmployeePOPageInfo.setList(SalaryPageUtil.subList(queryParam.getCurrent(), queryParam.getPageSize(), salaryAcctEmployeePOS));
return salaryAcctEmployeePOPageInfo;
}
/**
* 2025-12-11 新增环比上月实发工资差额列表
* 根据列表查询条件查询环比上月实发工资差额列表分页
*
* @param queryParam 列表查询条件
* @return
*/
@Override
public PageInfo<SalaryAccGzceListDTO> listPageByParam4Gzce(SalaryAcctEmployeeQueryParam queryParam) {
// 查询环比上月实发工资差额数据
List<SalaryAccGzceListDTO> salaryGzcePOS = listByParam4Gzce(queryParam);
PageInfo<SalaryAccGzceListDTO> salaryAcctGzceListPOPageInfo = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), SalaryAccGzceListDTO.class);
// 分页参数
salaryAcctGzceListPOPageInfo.setTotal(salaryGzcePOS.size());
salaryAcctGzceListPOPageInfo.setList(SalaryPageUtil.subList(queryParam.getCurrent(), queryParam.getPageSize(), salaryGzcePOS));
return salaryAcctGzceListPOPageInfo;
}
@Override
public List<SalaryAcctEmployeePO> listByParam4Reduce(SalaryAcctEmployeeQueryParam queryParam) {
@ -356,7 +378,91 @@ public class SalaryAcctEmployeeServiceImpl extends Service implements SalaryAcct
return resultList;
}
/**
* 查询环比上月实发工资差额数据
* @param queryParam
* @return
*/
@Override
public List<SalaryAccGzceListDTO> listByParam4Gzce(SalaryAcctEmployeeQueryParam queryParam) {
// 查询上个月的薪资核算记录同一个薪资账套
List<SalaryAcctRecordPO> salaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4LastSalaryMonth(queryParam.getSalaryAcctRecordId());
if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
return Collections.emptyList();
}
Long salaryAcctRecordId = queryParam.getSalaryAcctRecordId();
// 所有薪资项目
Map<String, String> salaryItems = HrsaSalaryUtils.getSalaryItems();
// 薪资帐套表id
Map<String,String> salarySobInfo = HrsaSalaryUtils.getSalarySobInfoByRecordId(String.valueOf(salaryAcctRecordId));
String salarySobId = Util.null2String(salarySobInfo.get("salarySobId"));
String salaryMonth = Util.null2String(salarySobInfo.get("salaryMonth"));
String lastMonth = CommonUtils.getLastMonth(salaryMonth,-1);
// 获取上月薪资核算记录表id
String lastMonthSalaryAcctRecordId = HrsaSalaryUtils.getSalarySobInfoByRecordId(salarySobId,lastMonth);
// 薪资核算人员
List<Map<String,String>> employeeInfos = HrsaSalaryUtils.getSalaryAcctEmps(salarySobId, String.valueOf(salaryAcctRecordId),queryParam);
// 上月薪资核算结果
Map<String,Map<String,String>> lastMonthSalaryAcctResults = HrsaSalaryUtils.getSalaryAcctResultNew(salarySobId , lastMonthSalaryAcctRecordId);
// 本月薪资核算结果
Map<String,Map<String,String>> salaryAcctResults = HrsaSalaryUtils.getSalaryAcctResultNew(salarySobId , String.valueOf(salaryAcctRecordId));
List<SalaryAccGzceListDTO> resultList = Lists.newArrayList();
for (int i = 0; i < employeeInfos.size(); i++) {
Map<String, String> employeeInfo = employeeInfos.get(i);
new BaseBean().writeLog("INFO","处理单条数据==>"+employeeInfo);
SalaryAccGzceListDTO salaryAccGzceListDTO = new SalaryAccGzceListDTO();
String salary_acct_emp_id = Util.null2String(employeeInfo.get("salary_acct_emp_id"));
String employeeId = Util.null2String(employeeInfo.get("employeeId"));
User employee = new User(Integer.valueOf(employeeId));
Map<String,String> lastMonthSalaryAcctResult = new HashMap<>();
if (lastMonthSalaryAcctResults.containsKey(salary_acct_emp_id)){
lastMonthSalaryAcctResult = lastMonthSalaryAcctResults.get(salary_acct_emp_id);
}
// 上月实发工资
double lastMonthSfgz = 0.00;
// 遍历
for (Map.Entry<String, String> entry : lastMonthSalaryAcctResult.entrySet()) {
String key = Util.null2String(entry.getKey());
String value = Util.null2String(entry.getValue());
// 项目名称
String salaryItemName = Util.null2String(salaryItems.get(key));
if ("实发工资".equals(salaryItemName)){
lastMonthSfgz = Util.getDoubleValue(value,0.00);
}
}
new BaseBean().writeLog("INFO","上月实发工资==>"+lastMonthSfgz);
Map<String,String> salaryAcctResult = new HashMap<>();
if (salaryAcctResults.containsKey(salary_acct_emp_id)){
salaryAcctResult = salaryAcctResults.get(salary_acct_emp_id);
}
// 实发工资
double sfgz = 0.00;
// 遍历
for (Map.Entry<String, String> entry : salaryAcctResult.entrySet()) {
String key = Util.null2String(entry.getKey());
String value = Util.null2String(entry.getValue());
// 项目名称
String salaryItemName = Util.null2String(salaryItems.get(key));
if ("实发工资".equals(salaryItemName)){
sfgz = Util.getDoubleValue(value,0.00);
}
}
new BaseBean().writeLog("INFO","当月实发工资==>"+sfgz);
BigDecimal lastMonthSfgzBigDecimal = new BigDecimal(lastMonthSfgz+"");
BigDecimal sfgzBigDecimal = new BigDecimal(sfgz+"");
BigDecimal sfgzce = sfgzBigDecimal.subtract(lastMonthSfgzBigDecimal);
new BaseBean().writeLog("INFO","实发工资差额==>"+sfgzce);
if (sfgzce.doubleValue() != 0){
salaryAccGzceListDTO.setEmployeeId((long) employee.getUID());
salaryAccGzceListDTO.setId((long) employee.getUID());
salaryAccGzceListDTO.setEmployeeName(employee.getUsername());
salaryAccGzceListDTO.setSfgzce(sfgzce.doubleValue());
resultList.add(salaryAccGzceListDTO);
}
}
new BaseBean().writeLog("INFO","查询环比上月实发工资差额数据==>"+resultList);
return resultList;
}
@Override
public PageInfo<SalaryAcctEmployeePO> listPageByParam4ConsolidatedTax(SalaryAcctEmployeeQueryParam queryParam) {
//排序配置
@ -847,8 +953,6 @@ public class SalaryAcctEmployeeServiceImpl extends Service implements SalaryAcct
if (updateParam.getLockStatus() == LockStatusEnum.LOCK) {
SalaryAcctConfig salaryAcctSobConfig = getSalaryAcctSobConfigService(user).getSalaryAcctConfig(updateParam.getSalaryAcctRecordId());
List<SalarySobItemPO> salarySobItems = salaryAcctSobConfig.getSalarySobItems();
// 2025-11-18 只锁定显示的项目隐藏的项目不锁定
salarySobItems = salarySobItems.stream().filter(item -> item.getItemHide() == 0L).collect(Collectors.toList());
List<Long> itemIds = SalaryEntityUtil.properties(salarySobItems, SalarySobItemPO::getSalaryItemId, Collectors.toList());
salaryAcctEmployees.forEach(salaryAcctEmployeePO -> {

View File

@ -17,10 +17,7 @@ import com.engine.salary.entity.salaryacct.bo.SalaryAcctConfig;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctEmployeeBO;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctResultBO;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctResultLogBO;
import com.engine.salary.entity.salaryacct.dto.SalaryAccEmployeeListDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctImportFieldDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctResultTemplateDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryComparisonResultListDTO;
import com.engine.salary.entity.salaryacct.dto.*;
import com.engine.salary.entity.salaryacct.param.*;
import com.engine.salary.entity.salaryacct.po.*;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
@ -70,7 +67,10 @@ import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StopWatch;
import weaver.conn.RecordSet;
import weaver.file.ImageFileManager;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.User;
import java.io.InputStream;
@ -1162,6 +1162,9 @@ public class SalaryAcctExcelServiceImpl extends Service implements SalaryAcctExc
throw new RuntimeException("无数据");
}
stopWatch.start("解析数据");
// 所有二级部门
Map<String,String> ejbmDatas = getEjbmIds();
new BaseBean().writeLog("INFO","导入校验二级部门==>"+ejbmDatas);
for (int i = 0; i < data.size(); i++) {
String row = "" + (i + 3) + "";
@ -1182,6 +1185,28 @@ public class SalaryAcctExcelServiceImpl extends Service implements SalaryAcctExc
}
String dataValue = (String) map.getOrDefault(dataKey.toString(), "");
String deparmentName = (String) map.getOrDefault("部门", "");
new BaseBean().writeLog("INFO","部门==>"+deparmentName);
// 2026-01-27 需要在导入的时候校验二级部门和一级部门是否对应
// 二级部门
String ejbm = (String) map.getOrDefault("二级部门", "");
new BaseBean().writeLog("INFO","二级部门==>"+ejbm);
boolean mark = true;
if (!StringUtils.isEmpty(ejbm)){
if (ejbmDatas.containsKey(deparmentName+"_"+ejbm)){
String ejbmId = Util.null2String(ejbmDatas.get(deparmentName+"_"+ejbm));
if (StringUtils.isEmpty(ejbmId)){
mark = false;
}
} else {
mark = false;
}
}
new BaseBean().writeLog("INFO","导入校验二级部门==>"+mark);
if (!mark){
Map<String, String> errorMessageMap = Maps.newHashMap();
errorMessageMap.put("message", row + "二级部门【"+ejbm+"】不属于部门【"+deparmentName+"");
excelComments.add(errorMessageMap);
}
String mobile = (String) map.getOrDefault("手机号", "");
String workcode = (String) map.getOrDefault("工号", "");
String idNo = (String) map.getOrDefault("证件号码", "");
@ -1688,4 +1713,72 @@ public class SalaryAcctExcelServiceImpl extends Service implements SalaryAcctExc
// }
// return excelSheetData;
// }
@Override
public XSSFWorkbook exportGzceList(SalaryAcctEmployeeQueryParam queryParam) {
ValidUtil.doValidator(queryParam);
// 1.工作簿名称
String sheetName = SalaryI18nUtil.getI18nLabel(85368, "环比上月实发工资差额");
// 2.表头
String[] header = {
SalaryI18nUtil.getI18nLabel(85429, "姓名"),
SalaryI18nUtil.getI18nLabel(86184, "实发工资差额")
};
List<Object> headerList = new ArrayList<>(Arrays.asList(header));
List<SalaryAccGzceListDTO> salaryAccGzce = getSalaryAcctEmployeeService(user).listByParam4Gzce(queryParam);
// 组装数据
List<List<Object>> rows = new ArrayList<>();
rows.add(headerList);
// 3.表数据
List<List<Object>> lists = convert2ExcelRow4Gzce(salaryAccGzce);
rows.addAll(lists);
// 记录日志
SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(queryParam.getSalaryAcctRecordId());
SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryAcctRecordPO.getSalarySobId());
String targetName = salarySobPO.getName() + ":" + SalaryDateUtil.localDate2YearMonth(salaryAcctRecordPO.getSalaryMonth());
LoggerContext loggerContext = new LoggerContext<>();
loggerContext.setUser(user);
loggerContext.setTargetId("" + salaryAcctRecordPO.getId());
loggerContext.setTargetName(targetName);
loggerContext.setOperateType(OperateTypeEnum.ADD.getValue());
loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "环比上月实发工资差额"));
loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "环比上月实发工资差额") + ":" + targetName);
SalaryElogConfig.salaryAcctRecordLoggerTemplate.write(loggerContext);
return ExcelUtilPlus.genWorkbookV2(rows, sheetName);
}
private List<List<Object>> convert2ExcelRow4Gzce(List<SalaryAccGzceListDTO> salaryAccGzce) {
if (CollectionUtils.isEmpty(salaryAccGzce)) {
return Collections.emptyList();
}
List<List<Object>> rows = Lists.newArrayListWithExpectedSize(salaryAccGzce.size());
for (SalaryAccGzceListDTO dto : salaryAccGzce) {
List<Object> row = Lists.newArrayListWithExpectedSize(3);
row.add(dto.getEmployeeName());
row.add(dto.getSfgzce());
rows.add(row);
}
return rows;
}
/**
* 获取二级部门ids
* @return
*/
private static Map<String,String> getEjbmIds() {
RecordSet rs = new RecordSet();
Map<String,String> data = new HashMap<>();
String sql = "select t1.id,t1.ejbm,t2.departmentname from uf_ejbm t1 left join HrmDepartment t2 on t1.yjdw = t2.id ";
rs.executeQuery(sql);
while (rs.next()) {
String ejbmId = Util.null2String(rs.getString("id"));
String ejbm = Util.null2String(rs.getString("ejbm"));
String departmentname = Util.null2String(rs.getString("departmentname"));
data.put(departmentname+"_"+ejbm,ejbmId);
}
return data;
}
}

View File

@ -42,6 +42,7 @@ import com.engine.salary.util.valid.ValidUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import weaver.general.Util;
import weaver.hrm.User;
import java.time.YearMonth;
@ -213,7 +214,13 @@ public class SalaryAcctRecordServiceImpl extends Service implements SalaryAcctRe
localDateRange.setEndDate(SalaryDateUtil.localDateToDate(queryParam.getEndMonth().atEndOfMonth()));
}
po.setSalaryMonths(localDateRange);
// 2026-01-27 添加状态查询条件
if (StringUtils.isNotEmpty(queryParam.getStatus())) {
String status = Util.null2String(queryParam.getStatus());
if (!"0".equals(status)){
po.setStatus(new Integer(status));
}
}
// 查询薪资核算记录
List<SalaryAcctRecordPO> salaryAcctRecordPOS = getSalaryAcctRecordMapper().listSome(po);
salaryAcctRecordPOS = getAuthService(user).auth(salaryAcctRecordPOS, AuthFilterTypeEnum.DATA_OPT, SalaryAcctRecordPO.class);

View File

@ -15,6 +15,7 @@ import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.entity.taxdeclaration.bo.TaxDeclarationBO;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationListQueryParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParamNew;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO;
import com.engine.salary.enums.OperateTypeEnum;
import com.engine.salary.enums.auth.AuthFilterTypeEnum;
@ -40,7 +41,10 @@ import org.apache.commons.collections4.CollectionUtils;
import weaver.general.BaseBean;
import weaver.hrm.User;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
@ -159,161 +163,170 @@ public class TaxDeclarationServiceImpl extends Service implements TaxDeclaration
}
@Override
public void save(TaxDeclarationSaveParam saveParam) {
Long taxAgentId = saveParam.getTaxAgentId();
if (taxAgentId == null) {
public void save(TaxDeclarationSaveParamNew saveParam) {
// 2026-01-21 by ydh 扣缴义务人支持多选
String taxAgentIdStr = saveParam.getTaxAgentId();
if (taxAgentIdStr == null) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "请选择要申报的扣缴义务人!"));
}
// 个税扣缴义务人id
Set<Long> taxAgentIds = Collections.singleton(taxAgentId);
// 查询个税扣缴义务人
List<TaxAgentPO> taxAgentPOS = getTaxAgentService(user).listByIds(taxAgentIds);
Map<Long, String> taxAgentNameMap = SalaryEntityUtil.convert2Map(taxAgentPOS, TaxAgentPO::getId, TaxAgentPO::getName);
List<SalaryAcctRecordPO> salaryAcctRecordPOS;
Date taxCycle;
//根据税款所属期申报
if (isTaxDeclarationByTaxCycle) {
taxCycle = saveParam.getTaxCycle();
if (Objects.isNull(taxCycle)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "税款所属期参数错误"));
List<String> taxAgentIdList = Arrays.asList(taxAgentIdStr.split(","));
if (taxAgentIdList.size() == 0) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "请选择要申报的扣缴义务人!"));
}
for (String taxAgentid : taxAgentIdList) {
if (taxAgentid == null || "".equals(taxAgentid)){
continue;
}
Long taxAgentId = Long.parseLong(taxAgentid);
// 个税扣缴义务人id
Set<Long> taxAgentIds = Collections.singleton(taxAgentId);
// 查询税款所属期个税扣缴义务人已经生成过的个税申报表
List<TaxDeclarationPO> taxDeclarationPOS = listByTaxCycle(TaxDeclarationPO.builder().taxCycle(taxCycle).taxAgentIds(taxAgentNameMap.keySet()).build());
// 已经生成过个税申报表不允许再次生成个税申报表
if (CollectionUtils.isNotEmpty(taxDeclarationPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(107986, "{0}在{1}已经生成过个税申报表,不允许再次生成")
.replace("{0}", taxAgentNameMap.get(taxDeclarationPOS.get(0).getTaxAgentId()))
.replace("{1}", SalaryDateUtil.getFormatYearMonth(taxCycle)));
}
// 查询薪资所属月的薪资核算记录
salaryAcctRecordPOS = listByTaxCycle(SalaryAcctRecordPO.builder().taxCycle(taxCycle).build());
} else {
//根据薪资所属月申报
// 薪资所属月的日期范围
LocalDateRange salaryMonthDateRange = SalaryDateUtil.localDate2Range(SalaryDateUtil.localDateToDate(saveParam.getSalaryMonth().atDay(1)));
if (Objects.isNull(salaryMonthDateRange)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "薪资所属月参数错误"));
}
// 查询个税扣缴义务人
List<TaxAgentPO> taxAgentPOS = getTaxAgentService(user).listByIds(taxAgentIds);
Map<Long, String> taxAgentNameMap = SalaryEntityUtil.convert2Map(taxAgentPOS, TaxAgentPO::getId, TaxAgentPO::getName);
List<SalaryAcctRecordPO> salaryAcctRecordPOS;
Date taxCycle;
//根据税款所属期申报
if (isTaxDeclarationByTaxCycle) {
taxCycle = saveParam.getTaxCycle();
if (Objects.isNull(taxCycle)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "税款所属期参数错误"));
}
// 查询薪资所属月个税扣缴义务人已经生成过的个税申报表
List<TaxDeclarationPO> taxDeclarationPOS = listBySalaryMonthTax(TaxDeclarationPO.builder().salaryMonths(salaryMonthDateRange).taxAgentIds(taxAgentNameMap.keySet()).build());
// 已经生成过个税申报表不允许再次生成个税申报表
if (CollectionUtils.isNotEmpty(taxDeclarationPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(107986, "{0}在{1}已经生成过个税申报表,不允许再次生成")
.replace("{0}", taxAgentNameMap.get(taxDeclarationPOS.get(0).getTaxAgentId()))
.replace("{1}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
// 查询薪资所属月的薪资核算记录
salaryAcctRecordPOS = listBySalaryMonth(SalaryAcctRecordPO.builder().salaryMonths(salaryMonthDateRange).build());
List<SalarySobPO> salarySobPOS = getSalarySobService(user).listByTaxAgentId(saveParam.getTaxAgentId());
if (CollectionUtils.isEmpty(salarySobPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98874, "{0}该义务人下无账套数据").replace("{0}", saveParam.getSalaryMonth().toString()));
}
List<Long> salarySobIds = salarySobPOS.stream().map(SalarySobPO::getId).collect(Collectors.toList());
// 查询税款所属期个税扣缴义务人已经生成过的个税申报表
List<TaxDeclarationPO> taxDeclarationPOS = listByTaxCycle(TaxDeclarationPO.builder().taxCycle(taxCycle).taxAgentIds(taxAgentNameMap.keySet()).build());
// 已经生成过个税申报表不允许再次生成个税申报表
if (CollectionUtils.isNotEmpty(taxDeclarationPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(107986, "{0}在{1}已经生成过个税申报表,不允许再次生成")
.replace("{0}", taxAgentNameMap.get(taxDeclarationPOS.get(0).getTaxAgentId()))
.replace("{1}", SalaryDateUtil.getFormatYearMonth(taxCycle)));
}
// 查询薪资所属月的薪资核算记录
salaryAcctRecordPOS = listByTaxCycle(SalaryAcctRecordPO.builder().taxCycle(taxCycle).build());
salaryAcctRecordPOS.stream().filter(record -> salarySobIds.contains(record.getSalarySobId())).collect(Collectors.toList());
} else {
//根据薪资所属月申报
// 薪资所属月的日期范围
LocalDateRange salaryMonthDateRange = SalaryDateUtil.localDate2Range(SalaryDateUtil.localDateToDate(saveParam.getSalaryMonth().atDay(1)));
if (Objects.isNull(salaryMonthDateRange)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "薪资所属月参数错误"));
}
// 查询薪资所属月个税扣缴义务人已经生成过的个税申报表
List<TaxDeclarationPO> taxDeclarationPOS = listBySalaryMonthTax(TaxDeclarationPO.builder().salaryMonths(salaryMonthDateRange).taxAgentIds(taxAgentNameMap.keySet()).build());
// 已经生成过个税申报表不允许再次生成个税申报表
if (CollectionUtils.isNotEmpty(taxDeclarationPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(107986, "{0}在{1}已经生成过个税申报表,不允许再次生成")
.replace("{0}", taxAgentNameMap.get(taxDeclarationPOS.get(0).getTaxAgentId()))
.replace("{1}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
// 查询薪资所属月的薪资核算记录
salaryAcctRecordPOS = listBySalaryMonth(SalaryAcctRecordPO.builder().salaryMonths(salaryMonthDateRange).build());
List<SalarySobPO> salarySobPOS = getSalarySobService(user).listByTaxAgentId(taxAgentId);
if (CollectionUtils.isEmpty(salarySobPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98874, "{0}该义务人下无账套数据").replace("{0}", saveParam.getSalaryMonth().toString()));
}
List<Long> salarySobIds = salarySobPOS.stream().map(SalarySobPO::getId).collect(Collectors.toList());
salaryAcctRecordPOS.stream().filter(record -> salarySobIds.contains(record.getSalarySobId())).collect(Collectors.toList());
// 无薪资核算记录不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98874, "{0}无申报数据").replace("{0}", saveParam.getSalaryMonth().toString()));
}
// 如果当前薪资所属月下存在不同的税款所属期属于异常业务场景不允许生成个税申报表
taxCycle = salaryAcctRecordPOS.get(0).getTaxCycle();
boolean differentTaxCycle = salaryAcctRecordPOS.stream().anyMatch(salaryAcctRecordPO -> salaryAcctRecordPO.getTaxCycle().compareTo(taxCycle) != 0);
if (differentTaxCycle) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98876, "{0}存在不同的税款所属期,无法正常生成个税申报表,请调整账套设置,重新核算后再生成个税申报表")
.replace("{0}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
}
// 无薪资核算记录不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98874, "{0}无申报数据").replace("{0}", saveParam.getSalaryMonth().toString()));
}
// 如果当前薪资所属月下存在不同的税款所属期属于异常业务场景不允许生成个税申报表
taxCycle = salaryAcctRecordPOS.get(0).getTaxCycle();
boolean differentTaxCycle = salaryAcctRecordPOS.stream().anyMatch(salaryAcctRecordPO -> salaryAcctRecordPO.getTaxCycle().compareTo(taxCycle) != 0);
if (differentTaxCycle) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98876, "{0}存在不同的税款所属期,无法正常生成个税申报表,请调整账套设置,重新核算后再生成个税申报表")
// 查询薪资核算结果
List<SalaryAcctResultPO> salaryAcctResultPOS = getSalaryAcctResultService(user)
.listBySalaryAcctRecordIdsAndTaxAgentIds(SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getId), taxAgentIds);
// 无薪资核算结果不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctResultPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(110093, "{0}无可申报数据")
.replace("{0}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
}
// 无薪资核算记录不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98874, "{0}无申报数据").replace("{0}", saveParam.getSalaryMonth().toString()));
}
// 查询薪资账套
Set<Long> salarySobIds = SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getSalarySobId);
List<SalarySobPO> salarySobPOS = getSalarySobService(user).listByIds(salarySobIds);
Map<Long, String> salarySobNameMap = SalaryEntityUtil.convert2Map(salarySobPOS, SalarySobPO::getId, SalarySobPO::getName);
Set<Long> salaryAcctRecordIds = SalaryEntityUtil.properties(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryAcctRecordId);
salaryAcctRecordPOS = salaryAcctRecordPOS.stream().filter(salaryAcctRecordPO -> salaryAcctRecordIds.contains(salaryAcctRecordPO.getId())).collect(Collectors.toList());
// 如果存在未归档的也不允许生成个税申报表
salaryAcctRecordPOS.forEach(salaryAcctRecordPO -> {
if (Objects.equals(salaryAcctRecordPO.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue())){
throw new SalaryRunTimeException(
String.format("%s%s账套有未归档数据请全部归档后再申报"
,SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())
,salarySobNameMap.getOrDefault(salaryAcctRecordPO.getSalarySobId(),"")
)
);
}
});
// 查询薪资核算结果
List<SalaryAcctResultPO> salaryAcctResultPOS = getSalaryAcctResultService(user)
.listBySalaryAcctRecordIdsAndTaxAgentIds(SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getId), taxAgentIds);
// 查询所有薪资项目
List<SalaryItemPO> salaryItemPOS = getSalaryItemService(user).listAll();
// 无薪资核算结果不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctResultPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(110093, "{0}无可申报数据")
.replace("{0}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
// 查询薪资账套
Set<Long> salarySobIds = SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getSalarySobId);
List<SalarySobPO> salarySobPOS = getSalarySobService(user).listByIds(salarySobIds);
Map<Long, String> salarySobNameMap = SalaryEntityUtil.convert2Map(salarySobPOS, SalarySobPO::getId, SalarySobPO::getName);
Set<Long> salaryAcctRecordIds = SalaryEntityUtil.properties(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryAcctRecordId);
salaryAcctRecordPOS = salaryAcctRecordPOS.stream().filter(salaryAcctRecordPO -> salaryAcctRecordIds.contains(salaryAcctRecordPO.getId())).collect(Collectors.toList());
// 如果存在未归档的也不允许生成个税申报表
salaryAcctRecordPOS.forEach(salaryAcctRecordPO -> {
if (Objects.equals(salaryAcctRecordPO.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue())){
throw new SalaryRunTimeException(
String.format("%s%s账套有未归档数据请全部归档后再申报"
,SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())
,salarySobNameMap.getOrDefault(salaryAcctRecordPO.getSalarySobId(),"")
)
);
// 处理要保存的数据
TaxDeclarationBO.Result result = TaxDeclarationBO.handle(saveParam, taxCycle, user, salaryItemPOS, salarySobPOS, salaryAcctResultPOS);
// 保存个税申报表
if (CollectionUtils.isNotEmpty(result.getNeedInsertTaxDeclarations())) {
if (isLog) {
log.info("salary TaxDeclaration step1 save {}", result.getNeedInsertTaxDeclarations().size());
}
getTaxDeclarationMapper().batchInsert(result.getNeedInsertTaxDeclarations());
}
});
// 查询所有薪资项目
List<SalaryItemPO> salaryItemPOS = getSalaryItemService(user).listAll();
// 处理要保存的数据
TaxDeclarationBO.Result result = TaxDeclarationBO.handle(saveParam, taxCycle, user, salaryItemPOS, salarySobPOS, salaryAcctResultPOS);
// 保存个税申报表
if (CollectionUtils.isNotEmpty(result.getNeedInsertTaxDeclarations())) {
// 保存个税申报表明细
if (CollectionUtils.isNotEmpty(result.getNeedInsertTaxDeclarationDetails())) {
if (isLog) {
log.info("salary TaxDeclaration step2 detail save {}", result.getNeedInsertTaxDeclarationDetails().size());
}
getTaxDeclarationDetailService(user).batchSave(result.getNeedInsertTaxDeclarationDetails());
}
// 保存累计情况
if (CollectionUtils.isNotEmpty(result.getNeedInsertAddUpSituations())) {
if (isLog) {
log.info("salary TaxDeclaration step3 AddUpSituations save {}", result.getNeedInsertAddUpSituations().size());
}
getAddUpSituationService(user).deleteByTaxYearMonthAndTaxAgentIds(SalaryDateUtil.localDate2YearMonth(taxCycle), taxAgentIds);
getAddUpSituationService(user).batchSave((List) result.getNeedInsertAddUpSituations());
}
// 更新薪资核算记录的状态
if (isLog) {
log.info("salary TaxDeclaration step1 save {}", result.getNeedInsertTaxDeclarations().size());
log.info("salary TaxDeclaration step4 AcctRecordStatus save {}", salaryAcctRecordIds.size());
}
getTaxDeclarationMapper().batchInsert(result.getNeedInsertTaxDeclarations());
}
// 保存个税申报表明细
if (CollectionUtils.isNotEmpty(result.getNeedInsertTaxDeclarationDetails())) {
if (isLog) {
log.info("salary TaxDeclaration step2 detail save {}", result.getNeedInsertTaxDeclarationDetails().size());
}
getTaxDeclarationDetailService(user).batchSave(result.getNeedInsertTaxDeclarationDetails());
}
// 保存累计情况
if (CollectionUtils.isNotEmpty(result.getNeedInsertAddUpSituations())) {
if (isLog) {
log.info("salary TaxDeclaration step3 AddUpSituations save {}", result.getNeedInsertAddUpSituations().size());
}
getAddUpSituationService(user).deleteByTaxYearMonthAndTaxAgentIds(SalaryDateUtil.localDate2YearMonth(taxCycle), taxAgentIds);
getAddUpSituationService(user).batchSave((List) result.getNeedInsertAddUpSituations());
}
// 更新薪资核算记录的状态
if (isLog) {
log.info("salary TaxDeclaration step4 AcctRecordStatus save {}", salaryAcctRecordIds.size());
}
getSalaryAcctRecordService(user).updateStatusByIds(salaryAcctRecordIds, SalaryAcctRecordStatusEnum.DECLARED);
getSalaryAcctRecordService(user).updateStatusByIds(salaryAcctRecordIds, SalaryAcctRecordStatusEnum.DECLARED);
// 记录日志
result.getNeedInsertTaxDeclarations().stream().forEach(declare -> {
String taxAgentName = taxAgentNameMap.getOrDefault(declare.getTaxAgentId(), "");
String targetName = SalaryDateUtil.getFormatYearMonth(declare.getSalaryMonth()) + " " + taxAgentName + " " + IncomeCategoryEnum.parseByValue(declare.getIncomeCategory()).getDefaultLabel();
LoggerContext<TaxDeclarationPO> loggerContext = new LoggerContext<>();
loggerContext.setUser(user);
loggerContext.setTargetId(declare.getId().toString());
loggerContext.setTargetName(targetName);
loggerContext.setOperateType(OperateTypeEnum.ADD.getValue());
loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "生成个税申报表"));
loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "生成个税申报表"));
loggerContext.setNewValues(declare);
SalaryElogConfig.taxDeclarationLoggerTemplate.write(loggerContext);
});
// 记录日志
result.getNeedInsertTaxDeclarations().stream().forEach(declare -> {
String taxAgentName = taxAgentNameMap.getOrDefault(declare.getTaxAgentId(), "");
String targetName = SalaryDateUtil.getFormatYearMonth(declare.getSalaryMonth()) + " " + taxAgentName + " " + IncomeCategoryEnum.parseByValue(declare.getIncomeCategory()).getDefaultLabel();
LoggerContext<TaxDeclarationPO> loggerContext = new LoggerContext<>();
loggerContext.setUser(user);
loggerContext.setTargetId(declare.getId().toString());
loggerContext.setTargetName(targetName);
loggerContext.setOperateType(OperateTypeEnum.ADD.getValue());
loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "生成个税申报表"));
loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "生成个税申报表"));
loggerContext.setNewValues(declare);
SalaryElogConfig.taxDeclarationLoggerTemplate.write(loggerContext);
});
}
}
@Override
@ -408,4 +421,67 @@ public class TaxDeclarationServiceImpl extends Service implements TaxDeclaration
loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "撤回个税申报表"));
SalaryElogConfig.taxDeclarationLoggerTemplate.write(loggerContext);
}
/**
* 批量撤回个税申报
* @param param
*/
@Override
public void batchDeleteTaxDeclaration(TaxDeclarationSaveParamNew param) {
String taxAgentIdStr = param.getTaxAgentId();
new BaseBean().writeLog("INFO","批量撤回个税申报,个税扣缴义务人==>"+taxAgentIdStr+",月份==>"+param.getSalaryMonthStr());
if (taxAgentIdStr == null) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "请选择要申报的扣缴义务人!"));
}
if (param.getSalaryMonthStr() == null) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "请选择要申报的薪资所属月!"));
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
YearMonth yearMonth = YearMonth.parse(param.getSalaryMonthStr(), formatter);
param.setSalaryMonth(yearMonth);
List<String> taxAgentIdList = Arrays.asList(taxAgentIdStr.split(","));
for (String taxAgentId : taxAgentIdList) {
if (null == taxAgentId && "".equals(taxAgentId)){
continue;
}
// 薪资所属月的日期范围
LocalDateRange salaryMonthDateRange = SalaryDateUtil.localDate2Range(SalaryDateUtil.localDateToDate(param.getSalaryMonth().atDay(1)));
new BaseBean().writeLog("INFO","薪资所属月的日期范围,开始日期==>"+salaryMonthDateRange.getFromDate()+",结束日期==>"+salaryMonthDateRange.getEndDate());
TaxDeclarationPO taxDeclarationPO = TaxDeclarationPO.builder().taxAgentId(Long.valueOf(taxAgentId)).salaryMonths(salaryMonthDateRange).build();
List<TaxDeclarationPO> taxDeclarationPOS = getTaxDeclarationMapper().listSome(taxDeclarationPO);
new BaseBean().writeLog("INFO","查询个税申报记录数量==>"+taxDeclarationPOS.size());
for (TaxDeclarationPO po : taxDeclarationPOS) {
Long taxDeclarationId = po.getId();
// 获取当前个税扣缴义务人下的薪资账套
List<SalarySobPO> salarySobPOS = getSalarySobService(user).listByTaxAgentId(po.getTaxAgentId());
List<Long> salarySobIds = salarySobPOS.stream().map(SalarySobPO::getId).collect(Collectors.toList());
// 获取记录
LocalDateRange dateRange = new LocalDateRange(po.getSalaryMonth(), po.getSalaryMonth());
List<SalaryAcctRecordPO> salaryAcctRecords = getSalaryAcctRecordService(user).listBySalarySobIdsAndSalaryMonth(salarySobIds, dateRange);
List<Long> salaryAcctRecordIds = salaryAcctRecords.stream().map(SalaryAcctRecordPO::getId).collect(Collectors.toList());
// 删除个税申报表
getTaxDeclarationMapper().deleteByIdZj(po.getId());
// 修改薪资核算记录状态为已归档
if (CollectionUtils.isNotEmpty(salaryAcctRecordIds)) {
getSalaryAcctRecordService(user).updateStatusByIds(salaryAcctRecordIds, SalaryAcctRecordStatusEnum.ARCHIVED);
}
// 查询个税扣缴义务人名称
String bar = "_";
TaxAgentPO taxAgentPO = getTaxAgentService(user).getById(po.getTaxAgentId());
String targetName = SalaryDateUtil.getFormatYearMonth(po.getSalaryMonth()) + bar + taxAgentPO.getName() + bar + IncomeCategoryEnum.parseByValue(po.getIncomeCategory()).getDefaultLabel();
// 记录日志
LoggerContext<TaxDeclarationPO> loggerContext = new LoggerContext<>();
loggerContext.setUser(user);
loggerContext.setTargetId(taxDeclarationId.toString());
loggerContext.setTargetName(targetName);
loggerContext.setOperateType(OperateTypeEnum.DELETE.getValue());
loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "撤回个税申报表"));
loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "撤回个税申报表"));
SalaryElogConfig.taxDeclarationLoggerTemplate.write(loggerContext);
}
}
}
}

View File

@ -256,6 +256,19 @@ public class SalaryAcctController {
return new ResponseResult<SalaryAcctEmployeeQueryParam, PageInfo<SalaryAccEmployeeListDTO>>(user).run(getSalaryAcctEmployeeWrapper(user)::listPage4Add, param);
}
/**
* 2025-12-11 薪资核算环比上月实发工资差额列表
* 根据列表查询条件查询环比上月实发工资差额列表分页
*
* @return
*/
@POST
@Path("/getGzceList/list")
@Produces(MediaType.APPLICATION_JSON)
public String listGzce(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctEmployeeQueryParam param) {
User user = HrmUserVarify.getUser(request, response);
return new ResponseResult<SalaryAcctEmployeeQueryParam, PageInfo<SalaryAccGzceListDTO>>(user).run(getSalaryAcctEmployeeWrapper(user)::listPage4Gzce, param);
}
//添加薪资核算人员
@POST
@ -433,7 +446,39 @@ public class SalaryAcctController {
}
}
/**
* 2025-12-11 导出薪资核算环比上月实发工资差额列表
* 根据列表查询条件查询环比上月实发工资差额列表分页
*
* @return
*/
@GET
@Path("/gzceList/export")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response exportGzceList(@Context HttpServletRequest request, @Context HttpServletResponse response) {
try {
log.info("导出薪资核算环比上月实发工资差额列表==>");
SalaryAcctEmployeeQueryParam param = buildSalaryAcctEmployeeQueryParam(request);
User user = HrmUserVarify.getUser(request, response);
XSSFWorkbook workbook = getSalaryAcctExcelWrapper(user).exportGzceList(param);
String time = LocalDate.now().toString();
String fileName = "环比上月实发工资差额" + time;
try {
fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
StreamingOutput output = outputStream -> {
workbook.write(outputStream);
outputStream.flush();
};
response.setContentType("application/octet-stream");
return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build();
} catch (Exception e) {
log.error("环比上月增加人员导出异常", e);
throw e;
}
}
// **********************************薪资核算人员相关 end*********************************/
// **********************************薪资核算结果 start*********************************/

View File

@ -4,10 +4,7 @@ import com.engine.common.util.ServiceUtil;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationFormDTO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationInfoDTO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationListDTO;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationBatParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationDetailListQueryParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationListQueryParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParam;
import com.engine.salary.entity.taxdeclaration.param.*;
import com.engine.salary.service.TaxDeclarationExcelService;
import com.engine.salary.service.TaxDeclarationService;
import com.engine.salary.service.impl.TaxDeclarationExcelServiceImpl;
@ -94,10 +91,10 @@ public class TaxDeclarationController {
@POST
@Path("/save")
@Produces(MediaType.APPLICATION_JSON)
public String save(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody TaxDeclarationSaveParam param) {
public String save(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody TaxDeclarationSaveParamNew param) {
User user = HrmUserVarify.getUser(request, response);
param.setSalaryMonth(SalaryDateUtil.String2YearMonth(param.getSalaryMonthStr()));
return new ResponseResult<TaxDeclarationSaveParam, Long>(user).run(getTaxDeclarationWrapper(user)::save, param);
return new ResponseResult<TaxDeclarationSaveParamNew, Long>(user).run(getTaxDeclarationWrapper(user)::save, param);
}
@POST
@ -146,4 +143,19 @@ public class TaxDeclarationController {
throw e;
}
}
/**
* 批量撤回个税申报
* @param request
* @param response
* @param param
* @return
*/
@POST
@Path("/batchDeleteTaxDeclaration")
@Produces(MediaType.APPLICATION_JSON)
public String batchDeleteTaxDeclaration(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody TaxDeclarationSaveParamNew param) {
User user = HrmUserVarify.getUser(request, response);
return new ResponseResult<TaxDeclarationSaveParamNew, String>(user).run(getTaxDeclarationWrapper(user)::batchDeleteTaxDeclaration,param);
}
}

View File

@ -5,6 +5,7 @@ import com.engine.core.impl.Service;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctEmployeeBO;
import com.engine.salary.entity.salaryacct.dto.SalaryAccEmployeeListDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAccGzceListDTO;
import com.engine.salary.entity.salaryacct.param.*;
import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
@ -91,6 +92,18 @@ public class SalaryAcctEmployeeWrapper extends Service {
return dtoPage;
}
/**
* 2025-12-11 新增环比上月实发工资差额列表
* 根据列表查询条件查询环比上月实发工资差额列表分页
*
* @param queryParam 列表查询条件
* @return
*/
public PageInfo<SalaryAccGzceListDTO> listPage4Gzce(SalaryAcctEmployeeQueryParam queryParam) {
// 查询同比减少的薪资核算人员分页
PageInfo<SalaryAccGzceListDTO> page = getSalaryAcctEmployeeService(user).listPageByParam4Gzce(queryParam);
return page;
}
/**
* 转换成列表dto
*

View File

@ -152,7 +152,7 @@ public class SalaryAcctRecordWrapper extends Service implements SalaryAcctRecord
List<TaxAgentPO> taxAgentPOS = getTaxAgentService(user).listAll();
// 转换成列表dto
List<SalaryAcctRecordListDTO> salaryAcctRecordListDTOS = SalaryAcctRecordBO.convert2ListDTO(list, salarySobPOS, employeeComInfos, salaryAcctEmployeeCountDTOS, salarySendCheckResult, taxAgentPOS, needApprovalSalarySobIds, approvalCanFile, approvalCanReCalc);
List<SalaryAcctRecordListDTO> salaryAcctRecordListDTOS = SalaryAcctRecordBO.convert2ListDTO(list, salarySobPOS, employeeComInfos, salaryAcctEmployeeCountDTOS, salarySendCheckResult, taxAgentPOS, needApprovalSalarySobIds, approvalCanFile, approvalCanReCalc, user);
dtoPage.setList(salaryAcctRecordListDTOS);
// 规则设置中是否开启审批功能默认关闭
if (CollectionUtils.isEmpty(needApprovalSalarySobIds)) {

View File

@ -12,6 +12,7 @@ import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationListDTO;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationBatParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationListQueryParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParamNew;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.service.SalaryEmployeeService;
@ -148,7 +149,7 @@ public class TaxDeclarationWrapper extends Service {
*
* @param saveParam 保存参数
*/
public void save(TaxDeclarationSaveParam saveParam) {
public void save(TaxDeclarationSaveParamNew saveParam) {
getTaxDeclarationService(user).save(saveParam);
}
@ -164,9 +165,9 @@ public class TaxDeclarationWrapper extends Service {
List<Long> taxAgentIds = param.getTaxAgentIds();
for (int i = 0; i < taxAgentIds.size(); i++) {
Long taxAgentId = taxAgentIds.get(i);
TaxDeclarationSaveParam saveParam = TaxDeclarationSaveParam.builder()
TaxDeclarationSaveParamNew saveParam = TaxDeclarationSaveParamNew.builder()
.salaryMonth(param.getSalaryMonth())
.taxAgentId(taxAgentId)
.taxAgentId(String.valueOf(taxAgentId))
.description(param.getDescription())
.taxCycle(param.getTaxCycle())
.salaryDate(param.getSalaryDate())
@ -175,4 +176,12 @@ public class TaxDeclarationWrapper extends Service {
}
}
/**
* 批量撤回个税申报
* @param param
*/
public void batchDeleteTaxDeclaration(TaxDeclarationSaveParamNew param) {
getTaxDeclarationService(user).batchDeleteTaxDeclaration(param);
}
}

View File

@ -0,0 +1,427 @@
package com.ydh.ldkj.utils;
import com.alibaba.fastjson.JSONObject;
import com.engine.common.util.ServiceUtil;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctConfig;
import com.engine.salary.entity.salaryacct.param.SalaryAcctEmployeeQueryParam;
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctSobConfigPO;
import com.engine.salary.entity.salarysob.po.*;
import com.engine.salary.service.SalaryAcctRecordService;
import com.engine.salary.service.SalaryAcctSobConfigService;
import com.engine.salary.service.impl.SalaryAcctRecordServiceImpl;
import com.engine.salary.service.impl.SalaryAcctSobConfigServiceImpl;
import com.engine.salary.util.valid.ValidUtil;
import weaver.conn.RecordSet;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.User;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 薪资核算工具类
*
* @author yuandonghui
* @date 2025-06-09
* @description TODO
*/
public class HrsaSalaryUtils {
private static final BaseBean log = new BaseBean();
private static SalaryAcctRecordService getSalaryAcctRecordService(User user) {
return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user);
}
private static SalaryAcctSobConfigService getSalaryAcctSobConfigService(User user) {
return ServiceUtil.getService(SalaryAcctSobConfigServiceImpl.class, user);
}
/**
* 根据薪资帐套id获取薪资帐套名称
*
* @param id 薪资帐套id
* @return
*/
public static String getSalarySobInfoById(String id) {
new BaseBean().writeLog("INFO", "根据薪资帐套id获取薪资帐套名称,薪资核算记录表id-->" + id);
RecordSet rs = new RecordSet();
String sql = "select name from hrsa_salary_sob where id = ?";
rs.executeQuery(sql, id);
rs.next();
String name = Util.null2String(rs.getString("name"));
new BaseBean().writeLog("INFO", "根据薪资帐套id获取薪资帐套名称-->" + name);
return name;
}
/**
* 根据薪资核算记录表id获取薪资帐套信息
*
* @param salaryAcctRecordId 薪资核算记录表id
* @return
*/
public static Map<String,String> getSalarySobInfoByRecordId(String salaryAcctRecordId) {
new BaseBean().writeLog("INFO", "根据薪资核算记录表id获取薪资帐套信息,薪资核算记录表id-->" + salaryAcctRecordId);
RecordSet rs = new RecordSet();
Map<String,String> salarySobInfo = new HashMap<>();
String sql = "select salary_month,salary_sob_id from hrsa_salary_acct_record where id = ?";
rs.executeQuery(sql, salaryAcctRecordId);
rs.next();
String salarySobId = Util.null2String(rs.getString("salary_sob_id"));
String salaryMonthDate = Util.null2String(rs.getString("salary_month"));
String salaryMonth = "";
if (!CommonUtils.isBlank(salaryMonthDate)){
String pattern1= "yyyy-MM-dd HH:mm:ss.SSS";
String pattern2= "yyyy-MM";
salaryMonth = CommonUtils.dateFormart(salaryMonthDate,pattern1,pattern2);
}
salarySobInfo.put("salarySobId",salarySobId);
salarySobInfo.put("salaryMonth",salaryMonth);
new BaseBean().writeLog("INFO", "根据薪资核算记录表id获取薪资帐套信息-->" + salarySobInfo);
return salarySobInfo;
}
/**
* 根据薪资帐套id获取薪资核算记录表id
*
* @param salarySobId 薪资帐套id
* @param month 月份
* @return
* 状态需要是归档的
*/
public static String getSalarySobInfoByRecordId(String salarySobId,String month) {
new BaseBean().writeLog("INFO", "根据薪资帐套id获取薪资核算记录表id,薪资帐套id==>" + salarySobId+",月份==>"+month);
RecordSet rs = new RecordSet();
String sql = " select * from hrsa_salary_acct_record where salary_sob_id = ? and status = 3 and salary_month = ? ";
rs.executeQuery(sql, salarySobId, month+"-01");
rs.next();
String id = Util.null2String(rs.getString("id"));
new BaseBean().writeLog("INFO", "根据薪资帐套id获取薪资核算记录表id-->" + id);
return id;
}
/**
* 获取薪资核算人员
*
* @param salarySobId 薪资帐套表id
* @param salaryAcctRecordId 薪资核算记录表id
* @return
*/
public static List<Map<String,String>> getSalaryAcctEmps(String salarySobId, String salaryAcctRecordId) {
RecordSet rs = new RecordSet();
List<Map<String,String>> employeeInfos = new ArrayList<>();
String sql = " select t1.id,t1.tax_agent_id,t3.name taxAgentName,t1.employee_id,t2.gjjsx,t2.njsx from hrsa_salary_acct_emp t1 " +
" left join uf_gjjnjsx t2 on t1.tax_agent_id = t2.gskjywrid " +
" left join hrsa_tax_agent t3 on t1.tax_agent_id = t3.id " +
" where t1.salary_sob_id= ? and t1.salary_acct_record_id= ? and t1.delete_type = 0";
rs.executeQuery(sql, salarySobId, salaryAcctRecordId);
while (rs.next()) {
Map<String,String> info = new HashMap<>();
String employeeId = Util.null2String(rs.getString("employee_id"));
String salary_acct_emp_id = Util.null2String(rs.getString("id"));
String taxAgentId = Util.null2String(rs.getString("tax_agent_id"));
String taxAgentName = Util.null2String(rs.getString("taxAgentName"));
String gjjsx = Util.null2String(rs.getString("gjjsx"));
String njsx = Util.null2String(rs.getString("njsx"));
info.put("salary_acct_emp_id",salary_acct_emp_id);
info.put("employeeId",employeeId);
info.put("taxAgentId",taxAgentId);
info.put("taxAgentName",taxAgentName);
info.put("gjjsx",gjjsx);
info.put("njsx",njsx);
employeeInfos.add(info);
}
return employeeInfos;
}
/**
* 获取薪资核算项目
*
* @param salarySobId 薪资帐套表id
* @return
*/
public static List<String> getSalarySobItems(String salarySobId) {
RecordSet rs = new RecordSet();
List<String> salaryItemIds = new ArrayList<>();
String sql = "select * from hrsa_salary_sob_item where salary_sob_id = ? and delete_type = 0";
rs.executeQuery(sql, salarySobId);
while (rs.next()) {
String salaryItemId = Util.null2String(rs.getString("salary_item_id"));
salaryItemIds.add(salaryItemId);
}
return salaryItemIds;
}
/**
* 获取所有薪资项目
*
* @return
*/
public static Map<String, String> getSalaryItems() {
RecordSet rs = new RecordSet();
Map<String, String> salaryItems = new HashMap<>();
String sql = "select * from hrsa_salary_item where delete_type = 0";
rs.executeQuery(sql);
while (rs.next()) {
String id = Util.null2String(rs.getString("id"));
String name = Util.null2String(rs.getString("name"));
salaryItems.put(id, name);
}
return salaryItems;
}
/**
* 2025-09-11 获取薪资项目若存在于账套则无法删除配置
* @return
*/
public static JSONObject getItemConfig(){
RecordSet rs = new RecordSet();
JSONObject data = new JSONObject();
String sql = "select * from uf_xzxmpzb";
rs.executeQuery(sql);
while (rs.next()){
String name = Util.null2String(rs.getString("xzxmmc"));
String sfbt = Util.null2String(rs.getString("sfbt"));
if (!"".equals(name) && !"".equals(sfbt)){
data.put(name,sfbt);
}
}
return data;
}
/**
* 获取付款单位id
* @param fkdw 付款单位
* @return
*/
public static String getFkdwId(String fkdw) {
RecordSet rs = new RecordSet();
String id = "";
String sql = "select * from uf_ldfkxx where zh = ? ";
rs.executeQuery(sql, fkdw);
if (rs.next()) {
id = Util.null2String(rs.getString("id"));
}
return id;
}
/**
* 获取人员对应薪资核算结果
*
* @param salarySobId 薪资帐套表id
* @param salaryAcctRecordId 薪资核算记录表id
* @param salary_acct_emp_id 薪资帐套人员id
*/
public static Map<String,String> getSalaryAcctResult(String salarySobId, String salaryAcctRecordId, String salary_acct_emp_id) {
RecordSet rs = new RecordSet();
Map<String,String> salaryAcctResult = new HashMap<>();
rs.writeLog("INFO","获取人员对应薪资核算薪资帐套表id==>"+salarySobId+"薪资核算记录表id==>"+salaryAcctRecordId+"薪资帐套人员id==>"+salary_acct_emp_id);
String sql = " select * FROM hrsa_salary_acct_result t where salary_acct_record_id =? " +
" and delete_type = 0 and salary_acct_emp_id= ? and salary_sob_id = ?";
rs.executeQuery(sql, salaryAcctRecordId, salary_acct_emp_id, salarySobId);
while (rs.next()){
String salaryItemId = Util.null2String(rs.getString("salary_item_id"));
String resultValue = Util.null2String(rs.getString("result_value"));
salaryAcctResult.put(salaryItemId,resultValue);
}
rs.writeLog("INFO","获取人员对应薪资核算结果==>"+salaryAcctResult);
return salaryAcctResult;
}
/**
* 2025-12-11 获取所有人员对应薪资核算结果
*
* @param salarySobId 薪资帐套表id
* @param salaryAcctRecordId 薪资核算记录表id
*/
public static Map<String,Map<String,String>> getSalaryAcctResultNew(String salarySobId, String salaryAcctRecordId) {
RecordSet rs = new RecordSet();
Map<String,Map<String,String>> salaryAcctResults = new HashMap<>();
rs.writeLog("INFO","获取所有人员对应薪资核算结果薪资帐套表id==>"+salarySobId+"薪资核算记录表id==>"+salaryAcctRecordId);
String sql = " select * FROM hrsa_salary_acct_result t where salary_acct_record_id =? " +
" and delete_type = 0 and salary_sob_id = ?";
rs.executeQuery(sql, salaryAcctRecordId, salarySobId);
while (rs.next()){
String salaryItemId = Util.null2String(rs.getString("salary_item_id"));
String resultValue = Util.null2String(rs.getString("result_value"));
String salaryAcctEmpId = Util.null2String(rs.getString("salary_acct_emp_id"));
Map<String,String> salaryAcctResult = new HashMap<>();
if (salaryAcctResult.containsKey(salaryAcctEmpId)){
salaryAcctResult = salaryAcctResults.get(salaryAcctEmpId);
}
salaryAcctResult.put(salaryItemId,resultValue);
salaryAcctResults.put(salaryAcctEmpId,salaryAcctResult);
}
rs.writeLog("INFO","获取所有人员对应薪资核算结果==>"+salaryAcctResults);
return salaryAcctResults;
}
/**
* 获取薪资核算人员
*
* @param salarySobId 薪资帐套表id
* @param salaryAcctRecordId 薪资核算记录表id
* @return
*/
public static List<Map<String,String>> getSalaryAcctEmps(String salarySobId, String salaryAcctRecordId,
SalaryAcctEmployeeQueryParam queryParam) {
RecordSet rs = new RecordSet();
new BaseBean().writeLog("INFO","获取薪资核算人员==>"+queryParam);
List<Map<String,String>> employeeInfos = new ArrayList<>();
String sql = " select t.id,t.employee_id from hrsa_salary_acct_emp t " +
" LEFT JOIN hrmresource e ON e.id = t.employee_id " +
" LEFT JOIN hrmdepartment d ON d.id = e.departmentid " +
" LEFT JOIN hrmsubcompany c ON c.id = e.subcompanyid1 " +
" where t.salary_sob_id= ? and t.salary_acct_record_id= ? and t.delete_type = 0 ";
if (queryParam.getStatuses().size() > 0){
sql += " AND e.status IN ("+String.join(",",queryParam.getStatuses())+") ";
}
if (queryParam.getDepartmentIds() != null && queryParam.getDepartmentIds().size() > 0){
sql += " AND d.id IN ("+queryParam.getDepartmentIds().stream()
.map(String::valueOf)
.collect(Collectors.joining(","))+") ";
}
if (queryParam.getPositionIds() != null && queryParam.getPositionIds().size() > 0){
sql += " AND e.jobtitle IN ("+queryParam.getPositionIds().stream()
.map(String::valueOf)
.collect(Collectors.joining(","))+") ";
}
if (queryParam.getWorkcode() != null && queryParam.getWorkcode() != ""){
sql += " AND e.workcode like '%"+queryParam.getWorkcode()+"%' ";
}
if (queryParam.getEmployeeName() != null && queryParam.getEmployeeName() != ""){
sql += " AND e.lastname like '%"+queryParam.getEmployeeName()+"%' ";
}
new BaseBean().writeLog("INFO","查询薪资核算人员sql==>"+sql+",薪资帐套表id==>"+salarySobId+",薪资核算记录表id==>"+salaryAcctRecordId);
rs.executeQuery(sql, salarySobId, salaryAcctRecordId);
while (rs.next()) {
Map<String,String> info = new HashMap<>();
String employeeId = Util.null2String(rs.getString("employee_id"));
String salary_acct_emp_id = Util.null2String(rs.getString("id"));
String taxAgentId = Util.null2String(rs.getString("tax_agent_id"));
String gjjsx = Util.null2String(rs.getString("gjjsx"));
String njsx = Util.null2String(rs.getString("njsx"));
info.put("salary_acct_emp_id",salary_acct_emp_id);
info.put("employeeId",employeeId);
employeeInfos.add(info);
}
return employeeInfos;
}
/**
* 判断该薪资核算记录对应的核算流程是否已经归档
* @param salaryAcctRecordId
* @return
*/
public static boolean checkHrsaSalaryFlowHasArchiving(String salaryAcctRecordId){
RecordSet rs = new RecordSet();
boolean mark = false;
String sql = "select * from uf_xzhscwhzrzb where xzhsjlbid = ? and shlc = 0 order by id desc";
rs.executeQuery(sql,salaryAcctRecordId);
while (rs.next()){
String xzhsshlc = Util.null2String(rs.getString("xzhsshlc"));
// 判断流程有没有归档
sql = "select currentnodetype from workflow_requestbase where requestid = ?";
rs.executeQuery(sql,xzhsshlc);
if (rs.next()) {
String currentnodetype = Util.null2String(rs.getString("currentnodetype"));
if (currentnodetype.equals("3")){
mark = true;
break;
}
}
}
return mark;
}
/**
* 校验个税扣缴义务人和付款账号
* @param taxAgentName 个税扣缴义务人
* @param fkzh 付款账号
* @return
* @time 2026-01-21
*/
public static boolean checkTaxAgentNameAndFkzh(String taxAgentName, String fkzh){
RecordSet rs = new RecordSet();
boolean mark = false;
String sql = "select id from uf_ldfkxx where gsmc = ? and zh = ? ";
rs.executeQuery(sql, taxAgentName, fkzh);
if (rs.next()){
String id = Util.null2String(rs.getString("id"));
if (!CommonUtils.isBlank(id)){
mark = true;
}
}
return mark;
}
/**
* 判断薪资核算记录的薪资账套是否变更
* @param salaryAcctRecordId
* @return
*/
public static boolean compareSobConfig(String salaryAcctRecordId, User user){
Long id = Long.parseLong(salaryAcctRecordId);
log.writeLog("INFO","判断薪资核算记录的薪资账套是否变更,薪资核算记录表id==>"+salaryAcctRecordId);
Map<String,String> salarySobInfo = HrsaSalaryUtils.getSalarySobInfoByRecordId(salaryAcctRecordId);
String salarySobId = Util.null2String(salarySobInfo.get("salarySobId"));
String salaryMonth = Util.null2String(salarySobInfo.get("salaryMonth"));
if (CommonUtils.isBlank(salaryMonth)){
log.writeLog("INFO","薪资所属月为空==>");
return false;
}
// 上月
String lastMonth = CommonUtils.getLastMonth(salaryMonth,-1);
// 获取上月薪资核算记录表id
String lastMonthSalaryAcctRecordId = HrsaSalaryUtils.getSalarySobInfoByRecordId(salarySobId,lastMonth);
if (CommonUtils.isBlank(lastMonthSalaryAcctRecordId)){
log.writeLog("INFO","获取上月薪资核算记录表id为空==>");
return false;
}
// 当前薪资核算记录信息
SalaryAcctRecordPO salaryAcctRecord = getSalaryAcctRecordService(user).getById(id);
if (null == salaryAcctRecord){
log.writeLog("INFO","当前薪资核算记录信息为空==>");
return false;
}
// 查询上月薪资核算记录的账套配置
SalaryAcctSobConfigPO salaryAcctSobConfig = getSalaryAcctSobConfigService(user).getBySalaryAcctRecordId(false, Long.valueOf(lastMonthSalaryAcctRecordId));
// 查询最新的账套配置
SalaryAcctSobConfigPO newSalaryAcctSobConfig = getSalaryAcctSobConfigService(user).initBySalaryAcctRecord(salaryAcctRecord);
SalaryAcctConfig config = SalaryAcctConfig.parse(salaryAcctSobConfig);
SalaryAcctConfig newConfig = SalaryAcctConfig.parse(newSalaryAcctSobConfig);
// 判断账套配置是否已经变更了
SalarySobPO salarySobPO = config.getSalarySob();
SalarySobPO newSalarySobPO = newConfig.getSalarySob();
if (!ValidUtil.compare(salarySobPO, newSalarySobPO)) {
log.writeLog("INFO","账套配置已经变更==>");
return true;
}
// 薪资项目-员工基本信息
List<SalarySobEmpFieldPO> salarySobEmpFields = config.getSalarySobEmpFields();
List<SalarySobEmpFieldPO> newSalarySobEmpFields = newConfig.getSalarySobEmpFields();
if (SalarySobEmpFieldPO.toCompareString(salarySobEmpFields).compareTo(SalarySobEmpFieldPO.toCompareString(newSalarySobEmpFields)) != 0) {
log.writeLog("INFO","账套员工基本信息已经变更==>");
return true;
}
// 薪资账套薪资项目分组
List<SalarySobItemGroupPO> salarySobItemGroups = config.getSalarySobItemGroups();
List<SalarySobItemGroupPO> newSalarySobItemGroups = newConfig.getSalarySobItemGroups();
if (SalarySobItemGroupPO.toCompareString(salarySobItemGroups).compareTo(SalarySobItemGroupPO.toCompareString(newSalarySobItemGroups)) != 0) {
log.writeLog("INFO","账套薪资项目分组已经变更==>");
return true;
}
// 薪资账套薪资项目
List<SalarySobItemPO> salarySobItems = config.getSalarySobItems();
List<SalarySobItemPO> newSalarySobItems = newConfig.getSalarySobItems();
if (SalarySobItemPO.toCompareString(salarySobItems).compareTo(SalarySobItemPO.toCompareString(newSalarySobItems)) != 0) {
log.writeLog("INFO","薪资账套薪资项目已经变更==>");
return true;
}
// 薪资账套回算薪资项目
List<SalarySobBackItemPO> salarySobBackItems = config.getSalarySobBackItems();
List<SalarySobBackItemPO> newSalarySobBackItems = newConfig.getSalarySobBackItems();
if (SalarySobBackItemPO.toCompareString(salarySobBackItems).compareTo(SalarySobBackItemPO.toCompareString(newSalarySobBackItems)) != 0) {
log.writeLog("INFO","薪资账套回算薪资项目已经变更==>");
return true;
}
return false;
}
}