港湾报表

This commit is contained in:
Harryxzy 2024-07-05 09:24:17 +08:00
parent 858f01c4e3
commit ff33397326
20 changed files with 785 additions and 16 deletions

View File

@ -0,0 +1,27 @@
package com.engine.salary.entity.salaryacct.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author Harryxzy
* @ClassName GwFylbDataDTO
* @date 2024/07/02 16:18
* @description
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class GwFylbDataDTO {
// 员工id
private Long employeeId;
// 费用类别数据需要根据生效日期有序
private List<GwFylbItemDataDTO> fylbItemValues;
}

View File

@ -0,0 +1,26 @@
package com.engine.salary.entity.salaryacct.dto;
import com.engine.salary.common.LocalDateRange;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author Harryxzy
* @ClassName GwFylbDTO
* @date 2024/07/02 16:16
* @description
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class GwFylbItemDataDTO {
//生效日期范围
private LocalDateRange effectiveDateRange;
//费用类别值
private int value;
}

View File

@ -0,0 +1,39 @@
package com.engine.salary.entity.salaryacct.po;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* @author Harryxzy
* @ClassName GwFylbInfo
* @date 2024/07/02 15:55
* @description 港湾费用类型
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class GwFylxInfo {
/**
* 费用类型id
*/
private Integer fylxId;
/**
* 生效日期
*/
private Date sxrq;
/**
* 员工id
*/
private Long employeeId;
}

View File

@ -0,0 +1,41 @@
package com.engine.salary.entity.salaryacct.po;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author Harryxzy
* @ClassName GwSalaryItemRelation
* @date 2024/07/03 10:43
* @description 港湾报表 薪资项目对应关系
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class GwSalaryItemRelation {
/**
* 薪资项目id
*/
private Long salaryItemId;
/**
* 薪资项目名称
*/
private String salaryItemName;
/**
* 显示名称
*/
private String salaryItemShowName;
/**
* 顺序
*/
private int sortedId;
}

View File

@ -0,0 +1,39 @@
package com.engine.salary.entity.salaryacct.po;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* @author Harryxzy
* @ClassName GwFylbInfo
* @date 2024/07/02 15:55
* @description 港湾员工项目经理部
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class GwXmjl {
/**
* 员工id
*/
private Long employeeId;
/**
* 开始日期
*/
private Date startDate;
/**
* 结束日期
*/
private Date endDate;
}

View File

@ -113,10 +113,10 @@ public enum UserStatusEnum implements BaseEnum {
return Arrays.stream(UserStatusEnum.values()).filter(v -> v != INVALID).collect(Collectors.toList());
}
public static List<HrmStatus> getHrmStatusList() {
public static List<HrmStatus> getHrmStatusList(User user) {
return Arrays.stream(UserStatusEnum.values())
.filter(v -> v != INVALID)
.map(v -> HrmStatus.builder().id(v.value.toString()).name(v.defaultLabel).build()).collect(Collectors.toList());
.map(v -> HrmStatus.builder().id(v.value.toString()).name( SalaryI18nUtil.getI18nLabel(user.getLanguage(),v.getLabelId() ,v.getDefaultLabel())).build()).collect(Collectors.toList());
}
// public static UserStatusEnum parseByValue(Integer value) {

View File

@ -4,6 +4,7 @@ package com.engine.salary.enums.salarysob;
import cn.hutool.core.util.ObjectUtil;
import com.engine.salary.enums.BaseEnum;
import com.engine.salary.util.SalaryI18nUtil;
import weaver.hrm.User;
import java.util.ArrayList;
import java.util.Arrays;
@ -105,14 +106,14 @@ public enum SalaryEmployeeStatusEnum implements BaseEnum<Integer> {
* @author Harryxzy
* @date 2023/1/9 14:35
*/
public static List<String> parseByFormatStr(String statusStr, Boolean[] haveError) {
public static List<String> parseByFormatStr(String statusStr, Boolean[] haveError, User user) {
List<String> result = new ArrayList<>();
String[] status = statusStr.split("");
Arrays.stream(status).forEach(s -> {
String value = null;
for (SalaryEmployeeStatusEnum statusEnum : SalaryEmployeeStatusEnum.values()) {
if (Objects.equals(statusEnum.getDefaultLabel(), s)) {
if (Objects.equals(SalaryI18nUtil.getI18nLabel(user.getLanguage(),statusEnum.getLabelId() ,statusEnum.getDefaultLabel()).trim(), s)) {
value = ObjectUtil.toString(statusEnum.getValue());
break;
}
@ -134,14 +135,14 @@ public enum SalaryEmployeeStatusEnum implements BaseEnum<Integer> {
* @author Harryxzy
* @date 2023/1/9 14:35
*/
public static SalaryEmployeeStatusEnum[] getEnumsParseByFormatStr(String statusStr, Boolean[] haveError) {
public static SalaryEmployeeStatusEnum[] getEnumsParseByFormatStr(String statusStr, Boolean[] haveError, User user) {
List<SalaryEmployeeStatusEnum> result = new ArrayList<>();
String[] status = statusStr.split("");
Arrays.stream(status).forEach(s -> {
SalaryEmployeeStatusEnum value = null;
for (SalaryEmployeeStatusEnum statusEnum : SalaryEmployeeStatusEnum.values()) {
if (Objects.equals(statusEnum.getDefaultLabel(), s)) {
if (Objects.equals(SalaryI18nUtil.getI18nLabel(user.getLanguage(),statusEnum.getLabelId() ,statusEnum.getDefaultLabel()).trim(), s)) {
value =statusEnum;
break;
}

View File

@ -130,6 +130,9 @@ public interface EmployMapper {
*/
List<DataCollectionEmployee> listByDismissDate(String dismissDate);
List<DataCollectionEmployee> listDismissEmpByIds(@Param("empIds") List<Long> empIds);
/**
* 根据上级id获取人员
* @param managerId

View File

@ -599,4 +599,23 @@
</foreach>
</if>
</select>
<select id="listDismissEmpByIds"
resultType="com.engine.salary.entity.datacollection.DataCollectionEmployee">
select e.id as employeeId,
e.lastname as username,
e.status as status,
e.certificatenum as idNo,
e.workcode as workcode,
e.companystartdate as companystartdate,
e.mobile as mobile,
e.enddate as dismissdate
from hrmresource e
where e.status in (4,5,6)
AND e.dismissdate is not null AND e.dismissdate != ''
AND e.id IN
<foreach collection="empIds" open="(" item="empId" separator="," close=")">
#{empId}
</foreach>
</select>
</mapper>

View File

@ -117,15 +117,15 @@
#{id}
</foreach>
</if>
<if test="taxAgentId != null">
AND tax_agent_id = #{taxAgentId}
</if>
<if test="taxAgentIds != null and taxAgentIds.size()>0">
AND tax_agent_id IN
<foreach collection="taxAgentIds" open="(" item="taxAgentId" separator="," close=")">
#{taxAgentId}
</foreach>
</if>
<if test="taxAgentId != null">
AND tax_agent_id = #{taxAgentId}
</if>
<include refid="listSomeParamSql"/>
ORDER BY create_time DESC
</select>

View File

@ -217,4 +217,12 @@ public interface SalaryAcctResultService {
* @param param
*/
void batchUpdate(SalaryAcctResultBatchUpdateParam param);
/**
* 港湾费用归属地报表
*
* @param param
* @return
*/
Map<String, Object> fygsdReport(SalaryAcctRecordQueryParam param);
}

View File

@ -167,4 +167,6 @@ public interface SalaryEmployeeService {
* @return
*/
List<DataCollectionEmployee> listBySubCompanyOrDepartment(List<Long> subCompanyIds, List<Long> departmentIds);
List<DataCollectionEmployee> listDismissEmpByIds(List<Long> allEmployeeIds);
}

View File

@ -1,6 +1,7 @@
package com.engine.salary.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.cloudstore.eccom.pc.table.WeaTableColumn;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.hrmelog.entity.dto.LoggerContext;
@ -15,9 +16,7 @@ import com.engine.salary.entity.progress.ProgressDTO;
import com.engine.salary.entity.report.bo.SalaryAcctResultReportBO;
import com.engine.salary.entity.report.po.SalaryAcctResultReportPO;
import com.engine.salary.entity.salaryacct.bo.*;
import com.engine.salary.entity.salaryacct.dto.ConsolidatedTaxDetailDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctResultDetailDTO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctResultListColumnDTO;
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.salaryformula.ExpressFormula;
@ -66,10 +65,14 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.util.StopWatch;
import weaver.conn.RecordSet;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.User;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.CountDownLatch;
@ -190,6 +193,10 @@ public class SalaryAcctResultServiceImpl extends Service implements SalaryAcctRe
return ServiceUtil.getService(TaxAgentAdminServiceImpl.class, user);
}
private SalaryEmployeeService getSalaryEmployeeService() {
return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user);
}
private SalaryCheckResultService salaryCheckResultService;
@ -1238,4 +1245,491 @@ public class SalaryAcctResultServiceImpl extends Service implements SalaryAcctRe
}
}
@Override
public Map<String, Object> fygsdReport(SalaryAcctRecordQueryParam param) {
if (param.getStartMonth() == null || param.getEndMonth() == null) {
throw new SalaryRunTimeException("报表参数错误");
}
RecordSet rs = new RecordSet();
Map<String, Object> resultMap = new HashMap<>();
// 获取薪资核算记录信息
Collection<TaxAgentPO> taxAgentList = getTaxAgentService(user).listAllTaxAgents(Long.valueOf(user.getUID()));
List<Long> taxAgentIds = taxAgentList.stream().map(TaxAgentPO::getId).collect(Collectors.toList());
List<SalarySobPO> salarySobList = getSalarySobService(user).listByTaxAgentIds(taxAgentIds);
List<Long> salarySobIds = salarySobList.stream().map(SalarySobPO::getId).collect(Collectors.toList());
List<SalaryAcctRecordPO> salaryAcctRecordList= new ArrayList<>();
if (CollectionUtils.isNotEmpty(salarySobIds)) {
// 查询参数
SalaryAcctRecordPO po = SalaryAcctRecordPO.builder().salarySobIds(salarySobIds).build();
LocalDateRange localDateRange = new LocalDateRange();
localDateRange.setFromDate(SalaryDateUtil.localDateToDate(param.getStartMonth().atDay(1)));
localDateRange.setEndDate(SalaryDateUtil.localDateToDate(param.getEndMonth().atEndOfMonth()));
po.setSalaryMonths(localDateRange);
salaryAcctRecordList.addAll(getSalaryAcctRecordService(user).listSome(po));
// 获取薪资核算人员
List<Long> salaryAcctRecordIds = salaryAcctRecordList.stream().map(SalaryAcctRecordPO::getId).collect(Collectors.toList());
List<SalaryAcctEmployeePO> salaryAcctEmployeeList = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordIds(salaryAcctRecordIds);
List<Long> employeeIds = salaryAcctEmployeeList.stream().map(SalaryAcctEmployeePO::getEmployeeId).distinct().collect(Collectors.toList());
// 获取这些员工的费用类型信息
List<GwFylxInfo> fylbInfoList = getGwEmpFylxInfo(employeeIds, rs, localDateRange);
List<GwFylbDataDTO> gwFylbDataDTOS = buildGwFylbData(fylbInfoList, localDateRange, employeeIds);
// 获取需要查询哪些薪资项目(有序)
List<GwSalaryItemRelation> itemRelationList = getGwReportItems(rs);
// 查询这些员工每个人每个费用类型下的人天数及薪资数据
Map<Long, Map<Integer, Map<String, String>>> salaryAcctEmpReportInfo = getGwReportInfoByAcctEmp(salaryAcctEmployeeList, gwFylbDataDTOS, itemRelationList, localDateRange, rs);
// 获取费用类型下拉框信息
Map<Integer, String> fylxMap = getFylxSelectItemMap(rs);
// 根据薪资账套分组
Map<Long, Set<Long>> acctEmpGroupBySob = SalaryEntityUtil.group2Map(salaryAcctEmployeeList, SalaryAcctEmployeePO::getSalarySobId, SalaryAcctEmployeePO::getId);
// 构建报表信息计算小计
List<Map<String, String>> dataList = buildReportData(acctEmpGroupBySob, fylxMap, salaryAcctEmpReportInfo, itemRelationList, salarySobList);
// 构建表头
List<WeaTableColumn> columns = new ArrayList<>();
columns.add(new WeaTableColumn("100px", "国家", "gj"));
columns.add(new WeaTableColumn("100px", "费用类型", "fylx1"));
columns.add(new WeaTableColumn("100px", "费用类型2", "fylx2"));
columns.add(new WeaTableColumn("100px", "人数", "empNums"));
for (GwSalaryItemRelation itemRelation : itemRelationList) {
columns.add(new WeaTableColumn("100px", itemRelation.getSalaryItemShowName(), itemRelation.getSalaryItemId().toString()));
}
resultMap.put("column", columns);
resultMap.put("dataList", dataList);
}
return resultMap;
}
/**
* 构建报表信息计算小计
*
* @param acctEmpGroupBySob
* @param fylxMap
* @param salaryAcctEmpReportInfo
* @return
*/
private List<Map<String, String>> buildReportData(Map<Long, Set<Long>> acctEmpGroupBySob,
Map<Integer, String> fylxMap,
Map<Long, Map<Integer, Map<String, String>>> salaryAcctEmpReportInfo,
List<GwSalaryItemRelation> itemRelationList,
List<SalarySobPO> salarySobList) {
List<Map<String, String>> resultList = new ArrayList<>();
Set<Integer> fylxIds = fylxMap.keySet();
List<String> itemIdList = itemRelationList.stream().map(item -> item.getSalaryItemId().toString()).collect(Collectors.toList());
Map<Long, String> salarySobNameMap = SalaryEntityUtil.convert2Map(salarySobList, SalarySobPO::getId, SalarySobPO::getName);
// 获取办公室费用其他关系对应的id
BaseBean baseBean = new BaseBean();
int bgsfySelectId = Integer.valueOf(baseBean.getPropValue("shgwSalaryReport", "fylx_bgsfy_select_id")).intValue();
int qtgxSelectId = Integer.valueOf(baseBean.getPropValue("shgwSalaryReport", "fylx_bgsfy_select_id")).intValue();
for (Map.Entry<Long, Set<Long>> entry : acctEmpGroupBySob.entrySet()){
// 该账套下的结果用于计算小计
List<Map<String, String>> resultListBySob = new ArrayList<>();
String sobName = salarySobNameMap.getOrDefault(entry.getKey(), "");
// 该分组下的薪资核算人员id
Set<Long> acctEmpIds = entry.getValue();
List<Map<Integer, Map<String, String>>> reportInfoListBySob = new ArrayList<>();
acctEmpIds.stream().forEach(acctEmpId -> {
if (salaryAcctEmpReportInfo.get(acctEmpId) != null) {
reportInfoListBySob.add(salaryAcctEmpReportInfo.get(acctEmpId));
}
});
// 计算每一个费用类型的合计值
for (Integer fylxId : fylxIds) {
String fylxName = fylxMap.getOrDefault(fylxId, "");
// 获取该账套下 该费用类型下所有报表结果
List<Map<String, String>> reportInfoListByFylx = reportInfoListBySob.stream().map(map -> map.get(fylxId))
.filter(m -> m != null)
.collect(Collectors.toList());
// 先获取该费用类型下的人数是否为0
BigDecimal empNums = reportInfoListByFylx.stream()
.map(map -> map.get("empNums"))
.filter(NumberUtils::isCreatable)
.map(BigDecimal::new)
.reduce(BigDecimal.ZERO, BigDecimal::add);
if (!empNums.equals(BigDecimal.ZERO)) {
Map<String, String> fylxSumMap = new HashMap<>();
// 薪资项目值
itemIdList.stream().forEach(itemId -> {
BigDecimal sum = reportInfoListByFylx.stream()
.map(map -> map.get(itemId))
.filter(NumberUtils::isCreatable)
.map(BigDecimal::new)
.reduce(BigDecimal.ZERO, BigDecimal::add);
fylxSumMap.put(itemId.toString(), sum.toPlainString());
});
// 人数
fylxSumMap.put("empNums", empNums.toPlainString());
// 国家
fylxSumMap.put("gj", sobName);
// 2个费用类型
if (fylxId.equals(bgsfySelectId)) {
fylxSumMap.put("fylx1","办公室费用");
} else if (fylxId.equals(qtgxSelectId)) {
fylxSumMap.put("fylx1", "其他费用");
} else {
fylxSumMap.put("fylx1", "项目费用");
}
fylxSumMap.put("fylx2", fylxName);
resultListBySob.add(fylxSumMap);
}
}
// 该账套下的小计
Map<String, String> xjMap = new HashMap<>();
// 薪资项目值
itemIdList.stream().forEach(itemId -> {
BigDecimal xjSum = resultListBySob.stream()
.map(map -> map.get(itemId))
.filter(NumberUtils::isCreatable)
.map(BigDecimal::new)
.reduce(BigDecimal.ZERO, BigDecimal::add);
xjMap.put(itemId.toString(), xjSum.toPlainString());
});
// 人数
BigDecimal xjEmpNums = resultListBySob.stream()
.map(map -> map.get("empNums"))
.filter(NumberUtils::isCreatable)
.map(BigDecimal::new)
.reduce(BigDecimal.ZERO, BigDecimal::add)
.setScale(0,BigDecimal.ROUND_HALF_UP);
xjMap.put("empNums", xjEmpNums.toPlainString());
// 国家
xjMap.put("gj", sobName);
// 2个费用类型
xjMap.put("fylx1", "小计");
xjMap.put("fylx2", "小计");
resultListBySob.add(xjMap);
resultList.addAll(resultListBySob);
}
return resultList;
}
/**
* 获取港湾费用类型下拉框信息
*
* @return
*/
private Map<Integer, String> getFylxSelectItemMap(RecordSet rs) {
Map<Integer, String> resultMap = new HashMap<>();
BaseBean baseBean = new BaseBean();
String fylxFieldId = baseBean.getPropValue("shgwSalaryReport", "fylx_field_id");
rs.execute("select selectvalue,selectname from workflow_selectitem where fieldid = " + fylxFieldId);
while (rs.next()) {
resultMap.put(rs.getInt(1), Util.formatMultiLang(rs.getString(2)));
}
resultMap.put(-1, "");
return resultMap;
}
/**
* 查询这些员工每个人每个费用类型下的人天数及薪资数据
*
* @param salaryAcctEmployeeList
* @param gwFylbDataDTOS
* @param itemRelationList
* @return
*/
private Map<Long, Map<Integer, Map<String, String>>> getGwReportInfoByAcctEmp(List<SalaryAcctEmployeePO> salaryAcctEmployeeList,
List<GwFylbDataDTO> gwFylbDataDTOS,
List<GwSalaryItemRelation> itemRelationList,
LocalDateRange localDateRange,
RecordSet rs) {
Map<Long, Map<Integer, Map<String, String>>> resultMap = new HashMap<>();
// 查询这个核算人员的薪资核算结果
if (CollectionUtils.isNotEmpty(salaryAcctEmployeeList) && CollectionUtils.isNotEmpty(itemRelationList)) {
List<Long> salaryAcctEmpIds = salaryAcctEmployeeList.stream().map(SalaryAcctEmployeePO::getId).collect(Collectors.toList());
List<Long> salaryItemIds = itemRelationList.stream().map(GwSalaryItemRelation::getSalaryItemId).collect(Collectors.toList());
List<SalaryAcctResultPO> acctResultList = listByAcctEmployeeIdsAndSalaryItemIds(salaryAcctEmpIds, salaryItemIds);
Map<Long, List<SalaryAcctResultPO>> acctResultMap = SalaryEntityUtil.group2Map(acctResultList, SalaryAcctResultPO::getSalaryAcctEmpId);
// 获取这些员工的项目经历信息
List<GwXmjl> xmjlList = gwGetEmpXmjlInfo(rs, localDateRange, salaryAcctEmployeeList);
Map<Long, List<GwXmjl>> xmjlMapByEmpId = SalaryEntityUtil.group2Map(xmjlList, GwXmjl::getEmployeeId);
// 获取办公室费用其他关系对应的id
BaseBean baseBean = new BaseBean();
int bgsfySelectId = Integer.valueOf(baseBean.getPropValue("shgwSalaryReport", "fylx_bgsfy_select_id")).intValue();
int qtgxSelectId = Integer.valueOf(baseBean.getPropValue("shgwSalaryReport", "fylx_bgsfy_select_id")).intValue();
Map<Long, GwFylbDataDTO> gwFylbDataMap = SalaryEntityUtil.convert2Map(gwFylbDataDTOS, GwFylbDataDTO::getEmployeeId);
for (SalaryAcctEmployeePO salaryAcctEmployeePO : salaryAcctEmployeeList) {
Map<Integer, Map<String, String>> empFylbMap = new HashMap<Integer, Map<String, String>>();
// 获取该员工的费用类型信息
GwFylbDataDTO gwFylbDataDTO = gwFylbDataMap.getOrDefault(salaryAcctEmployeePO.getEmployeeId(), GwFylbDataDTO.builder().fylbItemValues(Collections.emptyList()).build());
List<GwFylbItemDataDTO> fylbItemValues = gwFylbDataDTO.getFylbItemValues();
// 获取该员工薪资核算信息
List<SalaryAcctResultPO> salaryValueList = acctResultMap.get(salaryAcctEmployeePO.getId());
Map<Long, String> acctResultValueMap = SalaryEntityUtil.convert2Map(salaryValueList, SalaryAcctResultPO::getSalaryItemId, SalaryAcctResultPO::getResultValue);
if (CollectionUtils.isNotEmpty(fylbItemValues)) {
// 存在费用类型信息
// 获取该员工的项目经历信息
List<GwXmjl> empXmjlList = xmjlMapByEmpId.getOrDefault(salaryAcctEmployeePO.getEmployeeId(), Collections.emptyList());
if (fylbItemValues.size() == 1) {
// 薪资周期内没有发生过费用类型调整
LocalDateRange effectiveDateRange = fylbItemValues.get(0).getEffectiveDateRange();
int fylx = fylbItemValues.get(0).getValue();
if (fylx == bgsfySelectId || fylx == qtgxSelectId) {
// 费用类型是办公室费用其他关系则不需要再查询项目经历表不需要考虑分段计算
Map<String, String> empSalaryMap = new HashMap<String, String>();
empSalaryMap.put("empNums", "1.00");
// 获取薪资数据
for (Long salaryItemId : salaryItemIds) {
empSalaryMap.put(salaryItemId.toString(), acctResultValueMap.getOrDefault(salaryItemId, ""));
}
empFylbMap.put(fylx, empSalaryMap);
} else {
// 费用类型不是办公室费用其他关系需要查项目经历中项目有几天其余归类为办公室费用
// 获取薪资周期内有多少天是有项目经历的
Map<String, Integer> xmDaysMap = gwGetDaysInRange(effectiveDateRange.getFromDate(), effectiveDateRange.getEndDate(), empXmjlList);
BigDecimal xmDays = new BigDecimal(xmDaysMap.get("xmDays"));
BigDecimal officeDays = new BigDecimal(xmDaysMap.get("officeDays"));
BigDecimal totalDays = xmDays.add(officeDays);
// 分段计算人数和薪资封装项目天数办公室天数
BigDecimal baseDay = new BigDecimal(1).divide(totalDays, 15, RoundingMode.HALF_UP);
Map<String, String> empXmSalaryMap = new HashMap<String, String>();
empXmSalaryMap.put("empNums", baseDay.multiply(xmDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
Map<String, String> empOfficeSalaryMap = new HashMap<String, String>();
empOfficeSalaryMap.put("empNums", baseDay.multiply(officeDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
for (Long salaryItemId : salaryItemIds) {
BigDecimal itemValue = NumberUtils.isCreatable(acctResultValueMap.getOrDefault(salaryItemId, "")) ? new BigDecimal(acctResultValueMap.getOrDefault(salaryItemId, ""))
: new BigDecimal("0");
BigDecimal itemValeBase = itemValue.divide(totalDays, 15, RoundingMode.HALF_UP);
empXmSalaryMap.put(salaryItemId.toString(), itemValeBase.multiply(xmDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
empOfficeSalaryMap.put(salaryItemId.toString(), itemValeBase.multiply(officeDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
}
empFylbMap.put(fylx, empXmSalaryMap);
empFylbMap.put(bgsfySelectId, empOfficeSalaryMap);
}
} else {
// 薪资周期内发生过费用类型变更
// 获取费用类型周期
LocalDateRange effectiveDateRange = LocalDateRange.builder()
.fromDate(fylbItemValues.get(fylbItemValues.size()-1).getEffectiveDateRange().getFromDate())
.endDate(fylbItemValues.get(0).getEffectiveDateRange().getEndDate())
.build();
// 获取总计天数
BigDecimal totalDays = new BigDecimal(SalaryDateUtil.getDays(effectiveDateRange.getFromDate(), effectiveDateRange.getEndDate()));
BigDecimal totalXmDays = new BigDecimal(0);
BigDecimal baseDay = new BigDecimal(1).divide(totalDays, 15, RoundingMode.HALF_UP);
for (GwFylbItemDataDTO fylbItemData : fylbItemValues) {
// 获取此费用类别中有多少天有项目经历这里不能取计算出来的办公室天数
Map<String, Integer> xmDaysMap = gwGetDaysInRange(fylbItemData.getEffectiveDateRange().getFromDate(), fylbItemData.getEffectiveDateRange().getEndDate(), empXmjlList);
BigDecimal xmDays = new BigDecimal(xmDaysMap.get("xmDays"));
totalXmDays = totalXmDays.add(xmDays);
// 封装各个项目的天数和薪资分段计算
Map<String, String> empXmSalaryMap = new HashMap<String, String>();
empXmSalaryMap.put("empNums", baseDay.multiply(xmDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
for (Long salaryItemId : salaryItemIds) {
BigDecimal itemValue = NumberUtils.isCreatable(acctResultValueMap.getOrDefault(salaryItemId, "")) ? new BigDecimal(acctResultValueMap.getOrDefault(salaryItemId, ""))
: new BigDecimal("0");
empXmSalaryMap.put(salaryItemId.toString(), itemValue.divide(totalDays, 15, RoundingMode.HALF_UP).multiply(xmDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
}
empFylbMap.put(fylbItemData.getValue(), empXmSalaryMap);
}
// 封装计算办公室类型
BigDecimal officeDays = totalDays.subtract(totalXmDays);
Map<String, String> empOfficeSalaryMap = new HashMap<String, String>();
empOfficeSalaryMap.put("empNums", baseDay.multiply(officeDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
for (Long salaryItemId : salaryItemIds) {
BigDecimal itemValue = NumberUtils.isCreatable(acctResultValueMap.getOrDefault(salaryItemId, "")) ? new BigDecimal(acctResultValueMap.getOrDefault(salaryItemId, ""))
: new BigDecimal("0");
empOfficeSalaryMap.put(salaryItemId.toString(), itemValue.divide(totalDays, 15, RoundingMode.HALF_UP).multiply(officeDays).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
}
empFylbMap.put(bgsfySelectId, empOfficeSalaryMap);
}
} else {
// 不存在费用费别信息
Map<String, String> empSalaryMap = new HashMap<String, String>();
empSalaryMap.put("empNums", "1.00");
for (Long salaryItemId : salaryItemIds) {
BigDecimal itemValue = NumberUtils.isCreatable(acctResultValueMap.getOrDefault(salaryItemId, "")) ? new BigDecimal(acctResultValueMap.getOrDefault(salaryItemId, ""))
: new BigDecimal("0");
empSalaryMap.put(salaryItemId.toString(), itemValue.toPlainString());
}
empFylbMap.put(-1, empSalaryMap);
}
resultMap.put(salaryAcctEmployeePO.getId(), empFylbMap);
}
}
return resultMap;
}
/**
* 获取薪资周期内多少天有项目经历
*
* @return
*/
private Map<String, Integer> gwGetDaysInRange(Date startDate, Date endDate, List<GwXmjl> xmjlList) {
Map<String, Integer> resultMap = new HashMap<>();
// 项目天数
int xmDays = 0;
// 办公室天数
int officeDays = 0;
if (CollectionUtils.isEmpty(xmjlList)) {
resultMap.put("xmDays", xmDays);
resultMap.put("officeDays", SalaryDateUtil.getDays(startDate, endDate));
return resultMap;
}
LocalDate startLocalDate = SalaryDateUtil.dateToLocalDate(startDate);
LocalDate endLocalDate = SalaryDateUtil.dateToLocalDate(endDate);
LocalDate tempLocalDate = startLocalDate;
while (!tempLocalDate.isAfter(endLocalDate)) {
// 默认不在范围内
boolean flag = false;
for (int i = 0; i < xmjlList.size(); i++) {
Date xmjlStartDate = xmjlList.get(i).getStartDate();
Date xmjlEndDate = xmjlList.get(i).getEndDate();
if (SalaryDateUtil.dayInRange(tempLocalDate, SalaryDateUtil.dateToLocalDate(xmjlStartDate), SalaryDateUtil.dateToLocalDate(xmjlEndDate))) {
flag = true;
break;
}
}
if (flag == true) {
xmDays++;
} else {
officeDays++;
}
tempLocalDate = tempLocalDate.plusDays(1);
}
resultMap.put("xmDays", xmDays);
resultMap.put("officeDays", officeDays);
return resultMap;
}
/**
* 获取需要查询哪些薪资项目(有序)
*
* @return
*/
private List<GwSalaryItemRelation> getGwReportItems(RecordSet rs) {
List<GwSalaryItemRelation> resultList = new ArrayList<>();
rs.execute("select item.id,item.name,xsmc,px from uf_fygsdxzxm a " +
"left join hrsa_salary_item item on a.xzxm=item.name " +
"where item.delete_type=0 order by px");
while (rs.next()) {
String itemStr = rs.getString(1);
if (NumberUtils.isCreatable(itemStr)) {
GwSalaryItemRelation itemRelation = new GwSalaryItemRelation();
itemRelation.setSalaryItemId(Long.valueOf(itemStr));
itemRelation.setSalaryItemName(rs.getString(2));
itemRelation.setSalaryItemShowName(rs.getString("xsmc"));
itemRelation.setSortedId(rs.getInt("px"));
resultList.add(itemRelation);
}
}
return resultList;
}
/**
* 获取港湾员工项目经历信息
* @param localDateRange
* @param salaryAcctEmployeeList
* @return
*/
private List<GwXmjl> gwGetEmpXmjlInfo(RecordSet rs, LocalDateRange localDateRange, List<SalaryAcctEmployeePO> salaryAcctEmployeeList) {
String startDate = SalaryDateUtil.getFormatDate(localDateRange.getFromDate());
String endDate = SalaryDateUtil.getFormatDate(localDateRange.getEndDate());
List<Long> empIds = salaryAcctEmployeeList.stream().map(SalaryAcctEmployeePO::getEmployeeId).distinct().collect(Collectors.toList());
List<List<Long>> partition = Lists.partition(empIds, 800);
List<GwXmjl> xmjlList = new ArrayList<>();
partition.forEach(part -> {
String empStr = "(" + StringUtils.join(part, ",") + ")";
rs.execute("select ygxm,xxmbdrq,lkrq from uf_xmjlgljmb where CAST(xxmbdrq as DATE) <= CAST('"+ endDate +"' as DATE) and (lkrq is null or lkrq = '' or CAST(lkrq as DATE) >= CAST('"+ startDate +"' as DATE)) and ygxm in " + empStr);
while (rs.next()) {
GwXmjl gwXmjl = new GwXmjl();
gwXmjl.setEmployeeId(Long.valueOf(rs.getInt(1)));
gwXmjl.setStartDate(SalaryDateUtil.stringToDate(rs.getString(2)));
gwXmjl.setEndDate(SalaryDateUtil.stringToDate(rs.getString(3)));
xmjlList.add(gwXmjl);
}
});
return xmjlList;
}
/**
* 获取港湾员工费用类型信息
* @param employeeIds
* @return
*/
private List<GwFylxInfo> getGwEmpFylxInfo(List<Long> employeeIds, RecordSet rs, LocalDateRange localDateRange) {
List<GwFylxInfo> resultList = new ArrayList<>();
if (CollectionUtils.isEmpty(employeeIds)) {
return resultList;
}
List<List<Long>> partition = Lists.partition(employeeIds, 500);
partition.forEach(part -> {
String sql = "select xm,sxrq,fylx from uf_fylxgx where cast(sxrq as DATE) <= cast('"+ SalaryDateUtil.getFormatDate(localDateRange.getEndDate()) +"' as date) and xm in (" + StringUtils.join(part, ",") + ")";
rs.execute(sql);
while (rs.next()) {
Date sxrqDate = SalaryDateUtil.dateStrToLocalDate(rs.getString("sxrq"));
int fylx = rs.getInt("fylx");
if (sxrqDate != null) {
resultList.add(GwFylxInfo.builder().employeeId(Long.valueOf(rs.getInt("xm"))).sxrq(sxrqDate).fylxId(fylx).build());
}
}
});
return resultList;
}
/**
* 构建港湾费用类别数据
*
* @return
*/
public List<GwFylbDataDTO> buildGwFylbData(List<GwFylxInfo> fylbInfoList,
LocalDateRange localDateRange,
List<Long> allEmployeeIds) {
// 获取离职员工的离职日期
List<DataCollectionEmployee> dismissEmpList = getSalaryEmployeeService(user).listDismissEmpByIds(allEmployeeIds);
Map<Long, String> dismissDateMap = SalaryEntityUtil.convert2Map(dismissEmpList, DataCollectionEmployee::getEmployeeId, DataCollectionEmployee::getDismissdate);
Map<Long, List<GwFylxInfo>> fylbInfoMap = SalaryEntityUtil.group2Map(fylbInfoList, GwFylxInfo::getEmployeeId);
List<GwFylbDataDTO> list = new ArrayList<>();
allEmployeeIds.forEach(e -> {
GwFylbDataDTO gwFylbData = new GwFylbDataDTO();
gwFylbData.setEmployeeId(e);
// 获取该员工的费用类别信息
List<GwFylxInfo> gwFylxInfos = fylbInfoMap.getOrDefault(e, Collections.emptyList());
// 费用类型信息降序排序
gwFylxInfos = gwFylxInfos.stream().sorted(Comparator.comparing(GwFylxInfo::getSxrq).reversed()).collect(Collectors.toList());
// 开始日期
Date startItem = localDateRange.getFromDate();
// 结束日期
Date endItem = localDateRange.getEndDate();
// 对于离职的员工结束日期就是离职日期
if (dismissDateMap.containsKey(e)) {
endItem = SalaryDateUtil.dateStrToLocalDate(dismissDateMap.get(e));
}
Date endTempItem = endItem;
List<GwFylbItemDataDTO> gwFylbItemDataValues = new ArrayList<>();
boolean flag = false;
for (GwFylxInfo gwFylxInfo : gwFylxInfos) {
Date fromDateItem = gwFylxInfo.getSxrq();
if (fromDateItem.after(endTempItem) || endTempItem.before(startItem)) {
continue;
}
if (endTempItem.equals(startItem) && flag) {
continue;
}
GwFylbItemDataDTO gwFylbItemDataValue = new GwFylbItemDataDTO();
LocalDateRange dateRange = LocalDateRange.builder().fromDate((fromDateItem.before(startItem) ? startItem : fromDateItem)).endDate(endTempItem).build();
if (flag == true) {
// 不是第一条结束日期都要减1天
dateRange.setEndDate(SalaryDateUtil.localDateToDate(SalaryDateUtil.dateToLocalDate(dateRange.getEndDate()).minusDays(1)));
}
gwFylbItemDataValue.setEffectiveDateRange(dateRange);
gwFylbItemDataValue.setValue(gwFylxInfo.getFylxId());
gwFylbItemDataValues.add(gwFylbItemDataValue);
flag = true;
endTempItem = fromDateItem;
}
gwFylbData.setFylbItemValues(gwFylbItemDataValues);
list.add(gwFylbData);
});
return list;
}
}

View File

@ -515,4 +515,15 @@ public class SalaryEmployeeServiceImpl extends Service implements SalaryEmployee
}
return SalaryI18nUtil.i18nList(employeeList);
}
@Override
public List<DataCollectionEmployee> listDismissEmpByIds(List<Long> empIds) {
List<DataCollectionEmployee> resultList = new ArrayList<>();
if (CollectionUtils.isEmpty(empIds)) {
return resultList;
}
List<List<Long>> partition = Lists.partition(empIds, 500);
partition.forEach(part -> resultList.addAll(getEmployMapper().listDismissEmpByIds(part)));
return resultList;
}
}

View File

@ -378,7 +378,7 @@ public class SalarySobRangeServiceImpl extends Service implements SalarySobRange
} else {
Boolean[] haveError = {false};
// 人员状态字符串转换为对应的value
SalaryEmployeeStatusEnum[] status = SalaryEmployeeStatusEnum.getEnumsParseByFormatStr(employeeStatusStr, haveError);
SalaryEmployeeStatusEnum[] status = SalaryEmployeeStatusEnum.getEnumsParseByFormatStr(employeeStatusStr, haveError, user);
if (haveError[0]) {
Map<String, String> errorMessageMap = new HashMap<>();
errorMessageMap.put("message", rowIndex + SalaryI18nUtil.getI18nLabel(user.getLanguage(),542431,"员工状态不存在,或格式有误。格式为:试用、正式、临时、试用延期"));

View File

@ -296,7 +296,7 @@ public class TaxAgentManageRangeServiceImpl extends Service implements TaxAgentM
PageInfo<TaxAgentManageRangeListDTO> dtoPage = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), TaxAgentManageRangeListDTO.class, user);
// 查询人员状态
// List<HrmStatus> hrmStatusList = hrmCommonHrmStatusService.list();
List<HrmStatus> hrmStatusList = UserStatusEnum.getHrmStatusList();
List<HrmStatus> hrmStatusList = UserStatusEnum.getHrmStatusList(user);
// List<UserStatusEnum> userStatusEnumList = UserStatusEnum.getEffectiveList();
// List<HrmStatus> hrmStatusList = new ArrayList<>();
// userStatusEnumList.forEach(f -> {
@ -930,7 +930,7 @@ public class TaxAgentManageRangeServiceImpl extends Service implements TaxAgentM
} else {
Boolean[] haveError = {false};
// 人员状态字符串转换为对应的value
List<String> status = SalaryEmployeeStatusEnum.parseByFormatStr(employeeStatusStr, haveError);
List<String> status = SalaryEmployeeStatusEnum.parseByFormatStr(employeeStatusStr, haveError, user);
if (haveError[0]) {
Map<String, String> errorMessageMap = new HashMap<>();
errorMessageMap.put("message", rowIndex + SalaryI18nUtil.getI18nLabel(user.getLanguage(),542431,"员工状态不存在,或格式有误。格式为:试用、正式、临时、试用延期"));

View File

@ -15,6 +15,7 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
@ -605,6 +606,42 @@ public class SalaryDateUtil {
LocalDate localDate = SalaryDateUtil.dateToLocalDate(date).plusMonths(i);
return SalaryDateUtil.localDateToDate(localDate);
}
/**
* 获取2个时间段之间的日期包含开始和结束
* @param fromDate
* @param endDate
* @return
*/
public static int getDays(Date fromDate, Date endDate) {
if (fromDate == null || endDate == null) {
return 0;
} else {
LocalDate date1 = dateToLocalDate(fromDate);
LocalDate date2 = dateToLocalDate(endDate);
if (date1.isAfter(date2)) {
throw new SalaryRunTimeException("开始时间不能晚余结束时间"+date1+date2);
}
long between = ChronoUnit.DAYS.between(date1, date2);
return (int) between + 1;
}
}
/**
* 判断某个日期是否在时间段内
*
* @return
*/
public static boolean dayInRange(LocalDate localDate, LocalDate start, LocalDate end) {
if (localDate == null || start == null) {
return false;
}
if (end == null) {
return !localDate.isBefore(start);
} else {
return !localDate.isBefore(start) && !localDate.isAfter(end);
}
}
}

View File

@ -963,4 +963,17 @@ public class SalaryAcctController {
return new ResponseResult<PltxInitEmployeeParam, pltxEmployeeDTO>(user).run(getSalaryAcctExcelService(user)::pltxGetJbgz, param);
}
/**********************************上海港湾 批量调薪流程 end*********************************/
/**********************************上海港湾 薪酬报表 start*********************************/
// 港湾费用归属地报表
@POST
@Path("/fygsdReport")
@Produces(MediaType.APPLICATION_JSON)
public String fygsdReport(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctRecordQueryParam queryParam) {
User user = HrmUserVarify.getUser(request, response);
queryParam.setStartMonth(SalaryDateUtil.String2YearMonth(queryParam.getStartMonthStr()));
queryParam.setEndMonth(SalaryDateUtil.String2YearMonth(queryParam.getEndMonthStr()));
return new ResponseResult<SalaryAcctRecordQueryParam, Map<String, Object>>(user).run(getSalaryAcctResultWrapper(user)::fygsdReport, queryParam);
}
/**********************************上海港湾 薪酬报表 end*********************************/
}

View File

@ -274,6 +274,15 @@ public class SalaryAcctResultWrapper extends Service {
getSalaryAcctResultService(user).batchUpdate(param);
}
/**
* 港湾归属地报表
*
* @param param
*/
public Map<String, Object> fygsdReport(SalaryAcctRecordQueryParam param) {
return getSalaryAcctResultService(user).fygsdReport(param);
}
/**
* 薪资核算-校验
*

View File

@ -151,7 +151,7 @@ public class TaxAgentSubAdminWrapper extends Service {
* @return
*/
public TaxAgentManageRangeFormDTO getRangeFrom() {
return TaxAgentManageRangeFormDTO.builder().employeeStatus(UserStatusEnum.getHrmStatusList()).build();
return TaxAgentManageRangeFormDTO.builder().employeeStatus(UserStatusEnum.getHrmStatusList(user)).build();
}
/**