package com.engine.salary.entity.salaryarchive.bo; import com.cloudstore.eccom.constant.WeaBoolAttr; import com.cloudstore.eccom.pc.table.WeaTableColumn; import com.engine.salary.common.LocalDateRange; import com.engine.salary.constant.SalaryDefaultTenantConstant; import com.engine.salary.constant.SalaryItemConstant; import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveDataDTO; import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveItemDataDTO; import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveTaxAgentDataDTO; import com.engine.salary.entity.salaryarchive.po.SalaryArchiveItemPO; import com.engine.salary.entity.salaryarchive.po.SalaryArchivePO; import com.engine.salary.entity.salaryitem.po.SalaryItemPO; import com.engine.salary.entity.taxagent.po.TaxAgentEmpChangePO; import com.engine.salary.enums.salaryarchive.SalaryArchiveItemAdjustReasonEnum; import com.engine.salary.enums.salaryarchive.SalaryArchiveStatusEnum; import com.engine.salary.enums.taxagent.TaxAgentEmpChangeTypeEnum; import com.engine.salary.util.SalaryEntityUtil; import com.engine.salary.util.SalaryI18nUtil; import com.google.common.collect.Lists; import com.engine.salary.util.db.IdGenerator; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.apache.commons.lang3.math.NumberUtils; import java.util.*; import java.util.stream.Collectors; /** * @Description: 薪资档案 * @Author: wangxiangzhong * @Date: 2021-11-03 10:51 */ public class SalaryArchiveBO { @Override public String toString() { return "SalaryArchiveBO{}"; } /** * 添加日期范围 * @param weaSearchCondition * @param employeeId * @param tenantKey */ // public static void addDatePickerRangeOtherParams(WeaSearchCondition weaSearchCondition, String datePickerKey, Long employeeId, String tenantKey) { // WeaSearchConditionItem datePickerItem = weaSearchCondition.getItems().get(datePickerKey); // Map otherParams = Maps.newHashMap(); // otherParams.put("isRange", true); // otherParams.put("type", "day"); // otherParams.put("startPlaceholder", SalaryI18nUtil.getI18nLabel(tenantKey, employeeId, 90648, "开始日期")); // otherParams.put("endPlaceholder", SalaryI18nUtil.getI18nLabel(tenantKey, employeeId, 90649, "结束日期")); // datePickerItem.setOtherParams(otherParams); // weaSearchCondition.getItems().put(datePickerKey, datePickerItem); // } /** * 构建表格动态列 * * @param salaryItems */ public static List buildSalaryArchiveTable(List salaryItems) { // 表格表头 List columns = new ArrayList<>(); WeaTableColumn idColumn = new WeaTableColumn("100px", "id", "id"); idColumn.setIsPrimarykey(WeaBoolAttr.TRUE); idColumn.setDisplay(WeaBoolAttr.FALSE); columns.add(idColumn); WeaTableColumn employeeIdColumn = new WeaTableColumn("100px", "人员信息表的主键id", "employeeId"); employeeIdColumn.setDisplay(WeaBoolAttr.FALSE); columns.add(employeeIdColumn); columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(85429, "姓名"), "username")); columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人"), "taxAgentName")); columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86185, "分部"), "subcompanyName")); columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86185, "部门"), "departmentName")); columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86185, "工号"), "workcode")); columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86186, "手机号"), "mobile")); columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86186, "证件号码"), "mobile")); columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86187, "员工状态"), "employeeStatus")); columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86187, "起始发薪日期"), "payStartDate")); columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86187, "最后发薪日期"), "payEndDate")); columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86187, "入职日期"), "companystartdate").setDisplay(WeaBoolAttr.FALSE)); // columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86187, "离职日期"), "dismissdate").setDisplay(WeaBoolAttr.FALSE)); for (SalaryItemPO salaryItem : salaryItems) { columns.add(new WeaTableColumn("100px", salaryItem.getName(), salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX)); } columns.add(new WeaTableColumn("100px", "操作", "operate")); return columns; } /** * 构建薪资档案数据 * * @param salaryArchiveList * @param salaryArchiveItemDataList * @param localDateRange * @param allEmployeeIds * @param isOnlyTaxAgent * @return */ public static List buildSalaryArchiveData(List salaryArchiveList, List salaryArchiveItemDataList, LocalDateRange localDateRange, List allEmployeeIds, boolean isOnlyTaxAgent) { // // 开始日期 // Date start = localDateRange.getFromDate(); // // 结束日期 // Date end = localDateRange.getEndDate(); // // List list = new ArrayList<>(); // allEmployeeIds.forEach(e -> { // // 同一个人的档案数据 // List salaryArchives = salaryArchiveList.stream().filter(f -> f.getEmployeeId().equals(e)).collect(Collectors.toList()); // List salaryArchiveIds = salaryArchives.stream().map(SalaryArchivePO::getId).collect(Collectors.toList()); // // 同一个人的薪资项目调整历史数据 // List salaryArchiveItems = salaryArchiveItemDataList.stream().filter(d -> salaryArchiveIds.contains(d.getSalaryArchiveId())).collect(Collectors.toList()); // List salaryArchiveItemIds = salaryArchiveItems.stream().map(SalaryArchiveItemPO::getSalaryItemId).distinct().collect(Collectors.toList()); // // SalaryArchiveDataDTO salaryArchiveData = new SalaryArchiveDataDTO(); // salaryArchiveData.setEmployeeId(e); // List taxAgents = new ArrayList<>(); // // 按个税扣缴义务人生效日期时间段切割 // for (SalaryArchivePO salaryArchive : salaryArchives) { // Date fromDate = salaryArchive.getPayStartDate(); // Date endDate = salaryArchive.getPayEndDate(); // // 起始发薪日不为空,且不能比结束日期晚,最后发薪日可空可不空,但是如果不为空,就不能比开始日期早,且起始发薪日不能晚于最后发薪日 // boolean isEnable = fromDate != null && !fromDate.after(end) && (endDate == null || (!fromDate.after(endDate) && !endDate.before(start))); // if (isEnable) { // SalaryArchiveTaxAgentDataDTO taxAgent = new SalaryArchiveTaxAgentDataDTO(); // taxAgent.setTaxAgentId(salaryArchive.getTaxAgentId()); //// taxAgent.setIncomeCategory(salaryArchive.getIncomeCategory()); // taxAgent.setEffectiveDateRange(LocalDateRange.builder().fromDate((fromDate.before(start) ? start : fromDate)).endDate(endDate == null || endDate.after(end) ? end : endDate).build()); // // 薪资项目数据按个税扣缴义务人切割 // if (!isOnlyTaxAgent) { // // 开始日期 // Date startItem = taxAgent.getEffectiveDateRange().getFromDate(); // // 结束日期 // Date endItem = taxAgent.getEffectiveDateRange().getEndDate(); // Date endTempItem = endItem; // List salaryItemValues = new ArrayList<>(); // for (Long salaryArchiveItemId : salaryArchiveItemIds) { // for (SalaryArchiveItemPO salaryArchiveItem : salaryArchiveItems) { // if (!salaryArchiveItemId.equals(salaryArchiveItem.getSalaryItemId()) || !salaryArchiveItem.getSalaryArchiveId().equals(salaryArchive.getId())) { // continue; // } // Date fromDateItem = salaryArchiveItem.getEffectiveTime(); // if (fromDateItem.after(endTempItem) || (!endTempItem.after(startItem) && !endTempItem.equals(startItem))) { // continue; // } // SalaryArchiveItemDataDTO salaryArchiveItemData = new SalaryArchiveItemDataDTO(); // salaryArchiveItemData.setEffectiveDateRange(LocalDateRange.builder().fromDate((fromDateItem.before(startItem) ? startItem : fromDateItem)).endDate(endTempItem).build()); // //fixme 排除1号调薪,之前的历史周期为2022-01-01-2022-01-01这种情况 // if (!salaryArchiveItemData.getEffectiveDateRange().getFromDate().before(salaryArchiveItemData.getEffectiveDateRange().getEndDate())) { // continue; // } // salaryArchiveItemData.setSalaryItemId(salaryArchiveItem.getSalaryItemId()); // salaryArchiveItemData.setValue(salaryArchiveItem.getItemValue()); // salaryItemValues.add(salaryArchiveItemData); // endTempItem = fromDateItem; // } // endTempItem = endItem; // } // taxAgent.setSalaryItemValues(salaryItemValues); // } // taxAgents.add(taxAgent); // } // } // salaryArchiveData.setTaxAgents(taxAgents); // list.add(salaryArchiveData); // }); // // return list; // 开始日期 Date start = localDateRange.getFromDate(); // 结束日期 Date end = localDateRange.getEndDate(); List list = new ArrayList<>(); allEmployeeIds.forEach(e -> { // 同一个人的档案数据 List salaryArchives = salaryArchiveList.stream().filter(f -> f.getEmployeeId().equals(e)).collect(Collectors.toList()); List salaryArchiveIds = salaryArchives.stream().map(SalaryArchivePO::getId).collect(Collectors.toList()); // 同一个人的薪资项目调整历史数据 List salaryArchiveItems = salaryArchiveItemDataList.stream().filter(d -> salaryArchiveIds.contains(d.getSalaryArchiveId())).collect(Collectors.toList()); List salaryArchiveItemIds = salaryArchiveItems.stream().map(SalaryArchiveItemPO::getSalaryItemId).distinct().collect(Collectors.toList()); SalaryArchiveDataDTO salaryArchiveData = new SalaryArchiveDataDTO(); salaryArchiveData.setEmployeeId(e); List taxAgents = new ArrayList<>(); // 按个税扣缴义务人生效日期时间段切割 for (SalaryArchivePO salaryArchive : salaryArchives) { Date fromDate = salaryArchive.getPayStartDate(); Date endDate = salaryArchive.getPayEndDate(); // 起始发薪日不为空,且不能比结束日期晚,最后发薪日可空可不空,但是如果不为空,就不能比开始日期早,且起始发薪日不能晚于最后发薪日 boolean isEnable = fromDate != null && !fromDate.after(end) && (endDate == null || (!fromDate.after(endDate) && !endDate.before(start))); if (isEnable) { SalaryArchiveTaxAgentDataDTO taxAgent = new SalaryArchiveTaxAgentDataDTO(); taxAgent.setTaxAgentId(salaryArchive.getTaxAgentId()); // taxAgent.setIncomeCategory(salaryArchive.getIncomeCategory()); // taxAgent.setSalarySobIds(salaryArchiveSobList.stream().filter(sob->sob.getSalaryArchiveId().equals(salaryArchive.getId())).map(SalaryArchiveSobPO::getSalarySobId).distinct().collect(Collectors.toList())); taxAgent.setEffectiveDateRange(LocalDateRange.builder().fromDate((fromDate.before(start) ? start : fromDate)).endDate(endDate == null || endDate.after(end) ? end : endDate).build()); // 薪资项目数据按个税扣缴义务人切割 if (!isOnlyTaxAgent) { // 开始日期 Date startItem = taxAgent.getEffectiveDateRange().getFromDate(); // 结束日期 Date endItem = taxAgent.getEffectiveDateRange().getEndDate(); Date endTempItem = endItem; List salaryItemValues = new ArrayList<>(); for (Long salaryArchiveItemId : salaryArchiveItemIds) { boolean flag = false; for (SalaryArchiveItemPO salaryArchiveItem : salaryArchiveItems) { if (!salaryArchiveItemId.equals(salaryArchiveItem.getSalaryItemId()) || !salaryArchiveItem.getSalaryArchiveId().equals(salaryArchive.getId())) { continue; } Date fromDateItem = salaryArchiveItem.getEffectiveTime(); if (fromDateItem.after(endTempItem) || endTempItem.before(startItem)) { continue; } if (endTempItem.equals(startItem) && flag) { continue; } SalaryArchiveItemDataDTO salaryArchiveItemData = new SalaryArchiveItemDataDTO(); salaryArchiveItemData.setEffectiveDateRange(LocalDateRange.builder().fromDate((fromDateItem.before(startItem) ? startItem : fromDateItem)).endDate(endTempItem).build()); salaryArchiveItemData.setSalaryItemId(salaryArchiveItem.getSalaryItemId()); salaryArchiveItemData.setValue(salaryArchiveItem.getItemValue()); salaryItemValues.add(salaryArchiveItemData); flag = true; endTempItem = fromDateItem; } endTempItem = endItem; } taxAgent.setSalaryItemValues(salaryItemValues); } taxAgents.add(taxAgent); } } salaryArchiveData.setTaxAgents(taxAgents); list.add(salaryArchiveData); }); return list; } /** * 构建增量数据 * * @param taxAgentEmpChangeList * @param salaryArchiveList * @param salaryArchiveItemList * @param currentEmployeeId */ public static ChangeData buildChangeData(List taxAgentEmpChangeList, List salaryArchiveList, List salaryArchiveItemList, Long currentEmployeeId) { List changeIds = taxAgentEmpChangeList.stream().map(TaxAgentEmpChangePO::getId).collect(Collectors.toList()); // 根据个税扣缴义务人和人员以及增量类型分组 Map changeTypeMap = taxAgentEmpChangeList.stream().collect(Collectors.groupingBy(change -> change.getTaxAgentId() + "-" + change.getEmployeeId() + "-" + change.getChangeType(), Collectors.counting())); // 顺序倒转 Collections.reverse(taxAgentEmpChangeList); // 去重 taxAgentEmpChangeList = taxAgentEmpChangeList.stream() .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getTaxAgentId() + "-" + f.getEmployeeId()))), ArrayList::new)); List taxAgentEmpChanges = taxAgentEmpChangeList .stream() // 不相等则保留,否则忽略 .filter(change -> !Objects.equals(changeTypeMap.get(change.getTaxAgentId() + "-" + change.getEmployeeId() + "-" + TaxAgentEmpChangeTypeEnum.ADD.getValue()) , changeTypeMap.get(change.getTaxAgentId() + "-" + change.getEmployeeId() + "-" + TaxAgentEmpChangeTypeEnum.DEL.getValue()))) .collect(Collectors.toList()); Date now = new Date(); Date today = new Date(); List stopStatus = Arrays.asList(SalaryArchiveStatusEnum.STOP_FROM_PENDING.getValue(), SalaryArchiveStatusEnum.STOP_FROM_SUSPEND.getValue()); List salaryArchiveAddTodoList = Lists.newArrayList(); List salaryArchiveUpdateTodoList = Lists.newArrayList(); List salaryArchiveItemAddTodos = Lists.newArrayList(); Map salaryArchiveListMap = SalaryEntityUtil.convert2Map(salaryArchiveList, k -> k.getTaxAgentId() + "-" + k.getEmployeeId()); taxAgentEmpChanges.forEach(change -> { SalaryArchivePO salaryArchive = salaryArchiveListMap.get(change.getTaxAgentId() + "-" + change.getEmployeeId()); // 如果是新增 说明:如果没有档案,则新增,如果有档案而且是停薪,就挪到待定薪中,以个税扣缴义务人和人员id判断唯一 if (change.getChangeType() == TaxAgentEmpChangeTypeEnum.ADD.getValue()) { if (salaryArchive != null) { // 停薪中跳回待定薪:从a调动到b又调动到a,或者是删除待办后再覆盖 if (stopStatus.contains(salaryArchive.getRunStatus())) { // 跳回待定薪 salaryArchive.setRunStatus(SalaryArchiveStatusEnum.PENDING.getValue()); if (salaryArchive.getRunStatus().equals(SalaryArchiveStatusEnum.STOP_FROM_SUSPEND.getValue())) { salaryArchive.setPayStartDate(today); salaryArchive.setPayEndDate(null); } salaryArchiveUpdateTodoList.add(salaryArchive); // 待停薪到停薪的就要复制最新的薪资项目 if (salaryArchive.getRunStatus().equals(SalaryArchiveStatusEnum.STOP_FROM_SUSPEND.getValue())) { // 拷贝最新的薪资项目数据 List salaryArchiveItemValuelList = salaryArchiveItemList.stream().filter(i -> i.getSalaryArchiveId().equals(salaryArchive.getId())).collect(Collectors.toList()); salaryArchiveItemValuelList.forEach(i -> { salaryArchiveItemAddTodos.add(SalaryArchiveItemPO.builder() .id(IdGenerator.generate()) .salaryArchiveId(salaryArchive.getId()) .employeeId(salaryArchive.getEmployeeId()) .effectiveTime(today) .adjustReason(SalaryArchiveItemAdjustReasonEnum.INIT.getValue()) .salaryItemId(i.getSalaryItemId()) .itemValue(i.getItemValue()) .description("") // 不用设置操作人 .operateTime(now) .createTime(now) .updateTime(now) .creator(currentEmployeeId) .deleteType(NumberUtils.INTEGER_ZERO) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .build()); }); } } } else { salaryArchiveAddTodoList.add(SalaryArchivePO.builder() .id(IdGenerator.generate()) .employeeId(change.getEmployeeId()) .taxAgentId(change.getTaxAgentId()) .employeeType(change.getEmployeeType()) .runStatus(SalaryArchiveStatusEnum.PENDING.getValue()) // .incomeCategory(IncomeCategoryEnum.WAGES_AND_SALARIES.getValue()) // .modifier(0L) .createTime(now) .updateTime(now) .creator(currentEmployeeId) .deleteType(NumberUtils.INTEGER_ZERO) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .build()); } // 如果是删除 说明:如果有档案并且是在定薪列表才处理,没档案不用管 } else if (change.getChangeType() == TaxAgentEmpChangeTypeEnum.DEL.getValue()) { if (salaryArchive != null) { if (salaryArchive.getRunStatus().equals(SalaryArchiveStatusEnum.FIXED.getValue())) { // 跳到待停薪 salaryArchive.setRunStatus(SalaryArchiveStatusEnum.SUSPEND.getValue()); // salaryArchive.setPayEndDate(today); salaryArchiveUpdateTodoList.add(salaryArchive); } else if (salaryArchive.getRunStatus().equals(SalaryArchiveStatusEnum.PENDING.getValue())) { // 跳到停薪 salaryArchive.setRunStatus(SalaryArchiveStatusEnum.STOP_FROM_PENDING.getValue()); salaryArchiveUpdateTodoList.add(salaryArchive); } } } }); return ChangeData.builder() .salaryArchiveAddTodoList(salaryArchiveAddTodoList) .salaryArchiveUpdateTodoList(salaryArchiveUpdateTodoList) .salaryArchiveItemAddTodos(salaryArchiveItemAddTodos) .changeIds(changeIds) .build(); } @Data @Builder @NoArgsConstructor @AllArgsConstructor public static class ChangeData { /** * 批量修改薪资档案 */ private List salaryArchiveAddTodoList; /** * 批量新增薪资档案 */ private List salaryArchiveUpdateTodoList; /** * 落库处理薪资项目 */ private List salaryArchiveItemAddTodos; /** * 删除增量数据 */ private List changeIds; } public static boolean isNotExtEmp(SalaryArchivePO po) { return po.getEmployeeType() == null || po.getEmployeeType() == 1; } }