package com.ruoyi.staff.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.framework.web.domain.AjaxResult;
|
import com.ruoyi.project.system.domain.SysDept;
|
import com.ruoyi.project.system.mapper.SysDeptMapper;
|
import com.ruoyi.project.system.mapper.SysUserDeptMapper;
|
import com.ruoyi.production.mapper.ProductionAccountMapper;
|
import com.ruoyi.production.pojo.ProductionAccount;
|
import com.ruoyi.technology.mapper.TechnologyOperationMapper;
|
import com.ruoyi.technology.pojo.TechnologyOperation;
|
import com.ruoyi.staff.excel.StaffSalaryExportData;
|
import jakarta.servlet.http.HttpServletResponse;
|
import com.ruoyi.staff.dto.CalculateSalaryDto;
|
import com.ruoyi.staff.dto.StaffSalaryCalculateDto;
|
import com.ruoyi.staff.mapper.StaffLeaveMapper;
|
import com.ruoyi.staff.mapper.StaffSalaryDetailMapper;
|
import com.ruoyi.staff.mapper.StaffSalaryMainMapper;
|
import com.ruoyi.staff.pojo.StaffLeave;
|
import com.ruoyi.staff.pojo.StaffSalaryDetail;
|
import com.ruoyi.staff.pojo.StaffSalaryMain;
|
import com.ruoyi.staff.service.StaffSalaryDetailService;
|
import com.ruoyi.staff.service.StaffSalaryMainService;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.CollectionUtils;
|
|
import java.math.BigDecimal;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.HashMap;
|
import java.util.HashSet;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
import java.util.LinkedHashMap;
|
import java.util.LinkedHashSet;
|
import java.util.stream.Collectors;
|
import java.time.LocalDate;
|
import java.time.YearMonth;
|
import org.apache.poi.ss.usermodel.*;
|
import org.apache.poi.ss.util.CellRangeAddress;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import java.io.IOException;
|
|
/**
|
* <p>
|
* 员工工资主表 服务实现类
|
* </p>
|
*
|
* @author 芯导软件(江苏)有限公司
|
* @since 2026-03-06 01:22:05
|
*/
|
@Service
|
@RequiredArgsConstructor
|
public class StaffSalaryMainServiceImpl extends ServiceImpl<StaffSalaryMainMapper, StaffSalaryMain> implements StaffSalaryMainService {
|
|
private final StaffSalaryMainMapper staffSalaryMainMapper;
|
private final StaffSalaryDetailService staffSalaryDetailService;
|
private final StaffSalaryDetailMapper staffSalaryDetailMapper;
|
private final SchemeApplicableStaffServiceImpl schemeApplicableStaffService;
|
private final SysUserDeptMapper sysUserDeptMapper;
|
private final StaffLeaveMapper staffLeaveMapper;
|
private final SysDeptMapper sysDeptMapper;
|
private final ProductionAccountMapper productionAccountMapper;
|
private final TechnologyOperationMapper technologyOperationMapper;
|
|
@Override
|
public AjaxResult listPage(Page page, StaffSalaryMain staffSalaryMain) {
|
LambdaQueryWrapper<StaffSalaryMain> staffSalaryMainLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
if(staffSalaryMain != null){
|
if(StringUtils.isNotEmpty(staffSalaryMain.getSalaryTitle())){
|
staffSalaryMainLambdaQueryWrapper.like(StaffSalaryMain::getSalaryTitle, staffSalaryMain.getSalaryTitle());
|
}
|
if(StringUtils.isNotEmpty(staffSalaryMain.getSalaryMonth())){
|
staffSalaryMainLambdaQueryWrapper.like(StaffSalaryMain::getSalaryMonth, staffSalaryMain.getSalaryMonth());
|
}
|
if(staffSalaryMain.getStatus() != null){
|
staffSalaryMainLambdaQueryWrapper.eq(StaffSalaryMain::getStatus, staffSalaryMain.getStatus());
|
}
|
}
|
staffSalaryMainLambdaQueryWrapper.orderByDesc(StaffSalaryMain::getId);
|
Page<StaffSalaryMain> page1 = staffSalaryMainMapper.selectPage(page, staffSalaryMainLambdaQueryWrapper);
|
page1.getRecords().forEach(main -> {
|
List<StaffSalaryDetail> staffSalaryDetailList = staffSalaryDetailMapper.selectList(new LambdaQueryWrapper<StaffSalaryDetail>().eq(StaffSalaryDetail::getMainId, main.getId()));
|
main.setStaffSalaryDetailList(staffSalaryDetailList);
|
});
|
return AjaxResult.success(page1);
|
}
|
|
@Override
|
public AjaxResult add(StaffSalaryMain staffSalaryMain) {
|
if (staffSalaryMain == null || StringUtils.isEmpty(staffSalaryMain.getSalaryMonth())) {
|
return AjaxResult.error("参数错误");
|
}
|
|
Integer status = staffSalaryMain.getStatus();
|
if (status != null && status == 5) {
|
String salaryMonth = staffSalaryMain.getSalaryMonth();
|
String deptIds = staffSalaryMain.getDeptIds();
|
|
List<StaffSalaryMain> issuedList = staffSalaryMainMapper.selectList(new LambdaQueryWrapper<StaffSalaryMain>()
|
.eq(StaffSalaryMain::getSalaryMonth, salaryMonth)
|
.eq(StaffSalaryMain::getStatus, 5));
|
|
for (StaffSalaryMain issued : issuedList) {
|
if (hasOverlappingDept(deptIds, issued.getDeptIds())) {
|
return AjaxResult.error("同一月份同一部门工资不可以发放多次");
|
}
|
}
|
}
|
|
staffSalaryMainMapper.insert(staffSalaryMain);
|
staffSalaryMain.getStaffSalaryDetailList().forEach(detail -> {
|
detail.setMainId(staffSalaryMain.getId());
|
});
|
staffSalaryDetailService.saveBatch(staffSalaryMain.getStaffSalaryDetailList());
|
return AjaxResult.success("新增成功");
|
}
|
|
@Override
|
public AjaxResult updateStaffSalaryMain(StaffSalaryMain staffSalaryMain) {
|
if(staffSalaryMain == null){
|
return AjaxResult.error("参数错误");
|
}
|
StaffSalaryMain staffSalaryMain1 = staffSalaryMainMapper.selectById(staffSalaryMain.getId());
|
if(staffSalaryMain1 == null){
|
return AjaxResult.error("参数错误");
|
}
|
|
Integer newStatus = staffSalaryMain.getStatus();
|
if (newStatus != null && newStatus == 5) {
|
String salaryMonth = staffSalaryMain.getSalaryMonth();
|
if (StringUtils.isEmpty(salaryMonth)) {
|
salaryMonth = staffSalaryMain1.getSalaryMonth();
|
}
|
String deptIds = staffSalaryMain.getDeptIds();
|
if (StringUtils.isEmpty(deptIds)) {
|
deptIds = staffSalaryMain1.getDeptIds();
|
}
|
|
List<StaffSalaryMain> issuedList = staffSalaryMainMapper.selectList(new LambdaQueryWrapper<StaffSalaryMain>()
|
.eq(StaffSalaryMain::getSalaryMonth, salaryMonth)
|
.eq(StaffSalaryMain::getStatus, 5)
|
.ne(StaffSalaryMain::getId, staffSalaryMain.getId()));
|
|
for (StaffSalaryMain issued : issuedList) {
|
if (hasOverlappingDept(deptIds, issued.getDeptIds())) {
|
return AjaxResult.error("同一月份同一部门工资不可以发放多次");
|
}
|
}
|
}
|
|
// 待审核不可编辑
|
// if(staffSalaryMain1.getStatus() > 3){
|
// return AjaxResult.error("待审核不可编辑");
|
// }
|
staffSalaryMainMapper.updateById(staffSalaryMain);
|
if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(staffSalaryMain.getStaffSalaryDetailList())){
|
staffSalaryDetailMapper.delete(new LambdaQueryWrapper<StaffSalaryDetail>().eq(StaffSalaryDetail::getMainId, staffSalaryMain.getId()));
|
staffSalaryMain.getStaffSalaryDetailList().forEach(detail -> {
|
detail.setMainId(staffSalaryMain.getId());
|
});
|
staffSalaryDetailService.saveBatch(staffSalaryMain.getStaffSalaryDetailList());
|
}
|
return AjaxResult.success("修改成功");
|
}
|
|
@Override
|
public AjaxResult delete(List<Long> ids) {
|
if(CollectionUtils.isEmpty(ids)){
|
return AjaxResult.error("参数错误");
|
}
|
staffSalaryMainMapper.deleteBatchIds(ids);
|
staffSalaryDetailMapper.delete(new LambdaQueryWrapper<StaffSalaryDetail>().in(StaffSalaryDetail::getMainId, ids));
|
return AjaxResult.success("删除成功");
|
}
|
|
@Override
|
public AjaxResult calculateSalary(CalculateSalaryDto calculateSalaryDto) {
|
if(CollectionUtils.isEmpty(calculateSalaryDto.getIds())){
|
return AjaxResult.error("参数错误");
|
}
|
java.math.BigDecimal deductAmount = calculateSalaryDto.getDeductAmount() == null
|
? java.math.BigDecimal.ZERO
|
: calculateSalaryDto.getDeductAmount();
|
List<Map<String, Object>> longs = setSchemeApplicableStaffUserInfo(calculateSalaryDto.getIds()); // 通过部门ids获取用户信息
|
if(CollectionUtils.isEmpty(longs)){
|
return AjaxResult.error("无员工");
|
}
|
List<Map<String, Object>> mapList = new ArrayList<>();
|
for (Map<String, Object> id : longs) {
|
Long staffOnJobId = id.get("id") == null ? null : ((Number) id.get("id")).longValue();
|
// 判断员工是否为当月离职
|
if((Integer) id.get("staffState") == 0){
|
StaffLeave id1 = staffLeaveMapper.selectOne(new LambdaQueryWrapper<StaffLeave>()
|
.eq(StaffLeave::getStaffOnJobId, staffOnJobId)
|
.like(StaffLeave::getLeaveDate, calculateSalaryDto.getDate()));
|
if(id1 == null){
|
continue;
|
}
|
}
|
id.put("otherDeduct", deductAmount);
|
Long sysUserId = schemeApplicableStaffService.getUidByStaffId(staffOnJobId);
|
BigDecimal monthTimeTotal = resolveMonthTimeTotal(sysUserId, calculateSalaryDto.getDate());
|
id.put("monthTimeTotal", monthTimeTotal);
|
id.put("convertedWorkHours", monthTimeTotal);
|
schemeApplicableStaffService.calculateByEmployeeId(staffOnJobId == null ? null : staffOnJobId.intValue(), id, calculateSalaryDto.getDate());
|
mapList.add(id);
|
}
|
return AjaxResult.success(mapList);
|
}
|
|
@Override
|
public AjaxResult calculateSalaryByEmployee(StaffSalaryCalculateDto staffSalaryCalculateDto) {
|
if (staffSalaryCalculateDto == null
|
|| staffSalaryCalculateDto.getStaffOnJobId() == null
|
|| StringUtils.isEmpty(staffSalaryCalculateDto.getSalaryMonth())) {
|
return AjaxResult.error("参数错误");
|
}
|
Map<String, Object> map = new HashMap<>();
|
map.put("id", staffSalaryCalculateDto.getStaffOnJobId());
|
map.put("staffOnJobId", staffSalaryCalculateDto.getStaffOnJobId());
|
map.put("salaryMonth", staffSalaryCalculateDto.getSalaryMonth());
|
map.put("staffName", staffSalaryCalculateDto.getStaffName());
|
map.put("postName", staffSalaryCalculateDto.getPostName());
|
map.put("deptName", staffSalaryCalculateDto.getDeptName());
|
if (staffSalaryCalculateDto.getBasicSalary() != null) {
|
map.put("basicSalary", staffSalaryCalculateDto.getBasicSalary());
|
}
|
map.put("attendanceBonus", staffSalaryCalculateDto.getAttendanceBonus());
|
map.put("pieceSalary", staffSalaryCalculateDto.getPieceSalary());
|
map.put("hourlySalary", staffSalaryCalculateDto.getHourlySalary());
|
map.put("monthWorkDays", staffSalaryCalculateDto.getMonthWorkDays());
|
map.put("standardHours", staffSalaryCalculateDto.getStandardHours());
|
map.put("monthTimeTotal", staffSalaryCalculateDto.getMonthTimeTotal());
|
map.put("conversionRatio", staffSalaryCalculateDto.getConversionRatio());
|
map.put("convertedWorkHours", staffSalaryCalculateDto.getConvertedWorkHours());
|
map.put("actualOutput", staffSalaryCalculateDto.getActualOutput());
|
map.put("standardQuantity", staffSalaryCalculateDto.getStandardQuantity());
|
map.put("conversionFactor", staffSalaryCalculateDto.getConversionFactor());
|
map.put("otherIncome", staffSalaryCalculateDto.getOtherIncome());
|
map.put("socialPersonal", staffSalaryCalculateDto.getSocialPersonal());
|
map.put("fundPersonal", staffSalaryCalculateDto.getFundPersonal());
|
map.put("otherDeduct", staffSalaryCalculateDto.getOtherDeduct());
|
map.put("socialSupplementAmount", staffSalaryCalculateDto.getSocialSupplementAmount());
|
map.put("salaryTax", staffSalaryCalculateDto.getSalaryTax());
|
map.put("grossSalary", staffSalaryCalculateDto.getGrossSalary());
|
map.put("deductSalary", staffSalaryCalculateDto.getDeductSalary());
|
map.put("netSalary", staffSalaryCalculateDto.getNetSalary());
|
map.put("remark", staffSalaryCalculateDto.getRemark());
|
schemeApplicableStaffService.calculateByEmployeeId(
|
staffSalaryCalculateDto.getStaffOnJobId().intValue(),
|
map,
|
staffSalaryCalculateDto.getSalaryMonth()
|
);
|
return AjaxResult.success(map);
|
}
|
|
@Override
|
public void exportSalaryDetail(HttpServletResponse response, String salaryMonth) {
|
LambdaQueryWrapper<StaffSalaryMain> mainWrapper = new LambdaQueryWrapper<>();
|
if (StringUtils.isNotEmpty(salaryMonth)) {
|
mainWrapper.eq(StaffSalaryMain::getSalaryMonth, salaryMonth);
|
}
|
List<StaffSalaryMain> mainList = staffSalaryMainMapper.selectList(mainWrapper);
|
|
List<StaffSalaryExportData> exportDataList = new ArrayList<>();
|
for (StaffSalaryMain main : mainList) {
|
List<StaffSalaryDetail> detailList = staffSalaryDetailMapper.selectList(
|
new LambdaQueryWrapper<StaffSalaryDetail>().eq(StaffSalaryDetail::getMainId, main.getId())
|
);
|
|
for (StaffSalaryDetail detail : detailList) {
|
StaffSalaryExportData exportData = new StaffSalaryExportData();
|
exportData.setSalaryMonth(main.getSalaryMonth());
|
exportData.setSalaryTitle(main.getSalaryTitle());
|
exportData.setStaffName(detail.getStaffName());
|
exportData.setDeptName(detail.getDeptName());
|
exportData.setBasicSalary(detail.getBasicSalary());
|
exportData.setAttendanceBonus(detail.getAttendanceBonus());
|
exportData.setPieceSalary(detail.getPieceSalary());
|
exportData.setHourlySalary(detail.getHourlySalary());
|
exportData.setMonthWorkDays(detail.getMonthWorkDays());
|
exportData.setStandardHours(detail.getStandardHours());
|
exportData.setMonthTimeTotal(detail.getMonthTimeTotal());
|
exportData.setConversionRatio(detail.getConversionRatio());
|
exportData.setConvertedWorkHours(detail.getConvertedWorkHours());
|
exportData.setOtherIncome(detail.getOtherIncome());
|
exportData.setSocialPersonal(detail.getSocialPersonal());
|
exportData.setFundPersonal(detail.getFundPersonal());
|
exportData.setOtherDeduct(detail.getOtherDeduct());
|
exportData.setSocialSupplementAmount(detail.getSocialSupplementAmount());
|
exportData.setSalaryTax(detail.getSalaryTax());
|
exportData.setGrossSalary(detail.getGrossSalary());
|
exportData.setDeductSalary(detail.getDeductSalary());
|
exportData.setNetSalary(detail.getNetSalary());
|
exportData.setRemark(detail.getRemark());
|
exportDataList.add(exportData);
|
}
|
}
|
|
ExcelUtil<StaffSalaryExportData> util = new ExcelUtil<>(StaffSalaryExportData.class);
|
util.exportExcel(response, exportDataList, "员工薪资明细");
|
}
|
|
/**
|
* 汇总员工当月月时间合计。
|
* 计时工序直接取工时,计件工序按产量折算后再叠加补修理工时。
|
*/
|
private java.math.BigDecimal resolveMonthTimeTotal(Long sysUserId, String date) {
|
if (sysUserId == null || sysUserId <= 0 || StringUtils.isEmpty(date)) {
|
return java.math.BigDecimal.ZERO.setScale(2, java.math.RoundingMode.HALF_UP);
|
}
|
java.math.BigDecimal total = java.math.BigDecimal.ZERO.setScale(2, java.math.RoundingMode.HALF_UP);
|
java.util.List<java.util.Map<String, Object>> items = productionAccountMapper.selectMonthSalaryCalcItems(sysUserId, date);
|
for (java.util.Map<String, Object> item : items) {
|
Integer operationType = item.get("operationType") == null ? null : ((Number) item.get("operationType")).intValue();
|
java.math.BigDecimal finishedNum = toDecimal(item.get("finishedNum"));
|
java.math.BigDecimal workHour = toDecimal(item.get("workHour"));
|
java.math.BigDecimal repairWorkHour = toDecimal(item.get("repairWorkHour"));
|
java.math.BigDecimal standardQuantity = toDecimal(item.get("standardQuantity"));
|
java.math.BigDecimal conversionFactor = toDecimal(item.get("conversionFactor"));
|
java.math.BigDecimal rowTotal;
|
if (Integer.valueOf(0).equals(operationType)) {
|
rowTotal = workHour.add(repairWorkHour);
|
} else {
|
if (standardQuantity.compareTo(java.math.BigDecimal.ZERO) <= 0) {
|
rowTotal = java.math.BigDecimal.ZERO.setScale(2, java.math.RoundingMode.HALF_UP);
|
} else {
|
rowTotal = finishedNum
|
.divide(standardQuantity, 8, java.math.RoundingMode.HALF_UP)
|
.multiply(new java.math.BigDecimal("8"))
|
.multiply(conversionFactor)
|
.add(repairWorkHour)
|
.setScale(2, java.math.RoundingMode.HALF_UP);
|
}
|
}
|
total = total.add(rowTotal).setScale(2, java.math.RoundingMode.HALF_UP);
|
}
|
return total;
|
}
|
|
private java.math.BigDecimal toDecimal(Object value) {
|
if (value == null) {
|
return java.math.BigDecimal.ZERO.setScale(2, java.math.RoundingMode.HALF_UP);
|
}
|
if (value instanceof java.math.BigDecimal) {
|
return ((java.math.BigDecimal) value).setScale(2, java.math.RoundingMode.HALF_UP);
|
}
|
if (value instanceof Number) {
|
return new java.math.BigDecimal(String.valueOf(value)).setScale(2, java.math.RoundingMode.HALF_UP);
|
}
|
String text = String.valueOf(value).trim();
|
if (text.isEmpty()) {
|
return java.math.BigDecimal.ZERO.setScale(2, java.math.RoundingMode.HALF_UP);
|
}
|
return new java.math.BigDecimal(text).setScale(2, java.math.RoundingMode.HALF_UP);
|
}
|
|
@Override
|
public void exportWorkHours(HttpServletResponse response, String salaryMonth) {
|
List<ProductionAccount> accountList = queryProductionAccounts(salaryMonth);
|
List<String> operationNames = accountList.stream()
|
.map(ProductionAccount::getTechnologyOperationName)
|
.filter(StringUtils::isNotEmpty)
|
.distinct()
|
.sorted()
|
.collect(Collectors.toList());
|
Workbook workbook = new XSSFWorkbook();
|
CellStyle titleStyle = createStyle(workbook, true, HorizontalAlignment.CENTER, 14, false);
|
CellStyle headerStyle = createStyle(workbook, false, HorizontalAlignment.CENTER, 11, false);
|
CellStyle labelStyle = createStyle(workbook, false, HorizontalAlignment.CENTER, 10, false);
|
CellStyle numStyle = createStyle(workbook, false, HorizontalAlignment.CENTER, 10, false);
|
DataFormat dataFormat = workbook.createDataFormat();
|
numStyle.setDataFormat(dataFormat.getFormat("0.00"));
|
|
if (CollectionUtils.isEmpty(operationNames)) {
|
operationNames = new ArrayList<>();
|
}
|
|
int sheetIndex = 1;
|
for (String operationName : operationNames) {
|
TechnologyOperation operation = technologyOperationMapper.selectOne(
|
new LambdaQueryWrapper<TechnologyOperation>().eq(TechnologyOperation::getName, operationName).last("limit 1"));
|
String sheetName = operationName;
|
if (sheetName.length() > 31) {
|
sheetName = sheetName.substring(0, 31);
|
}
|
Sheet sheet = workbook.createSheet(sheetName);
|
int rowIdx = 0;
|
Row titleRow = sheet.createRow(rowIdx++);
|
titleRow.setHeightInPoints(52.5f);
|
titleRow.createCell(0).setCellValue(operationName + "工时统计");
|
titleRow.getCell(0).setCellStyle(titleStyle);
|
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 3));
|
|
Row workDayRow = sheet.createRow(rowIdx++);
|
workDayRow.createCell(0).setCellValue("工作日");
|
workDayRow.getCell(0).setCellStyle(headerStyle);
|
Integer monthWorkDays = calculateWorkDays(salaryMonth);
|
createNumberCell(workDayRow, 2, monthWorkDays == null ? null : new java.math.BigDecimal(monthWorkDays), headerStyle);
|
workDayRow.createCell(3).setCellValue("天");
|
workDayRow.getCell(3).setCellStyle(headerStyle);
|
createNumberCell(workDayRow, 4, monthWorkDays == null ? null : new java.math.BigDecimal(monthWorkDays * 8), headerStyle);
|
workDayRow.createCell(5).setCellValue("小时");
|
workDayRow.getCell(5).setCellStyle(headerStyle);
|
|
Row headRow = sheet.createRow(rowIdx++);
|
headRow.createCell(0).setCellValue("人员");
|
headRow.getCell(0).setCellStyle(headerStyle);
|
headRow.createCell(1).setCellValue("月产量");
|
headRow.getCell(1).setCellStyle(headerStyle);
|
headRow.createCell(2).setCellValue("折算时长");
|
headRow.getCell(2).setCellStyle(headerStyle);
|
headRow.createCell(3).setCellValue("工资");
|
headRow.getCell(3).setCellStyle(headerStyle);
|
|
Map<String, java.math.BigDecimal> standardMap = buildStandardQuantityMap(List.of(operationName));
|
Map<String, java.math.BigDecimal> opQtyMap = buildOperationQuantityMap(accountList, operationName);
|
Set<String> employeeNames = accountList.stream()
|
.map(ProductionAccount::getSchedulingUserName)
|
.filter(StringUtils::isNotEmpty)
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
for (String staffName : employeeNames) {
|
Row row = sheet.createRow(rowIdx++);
|
row.createCell(0).setCellValue(staffName);
|
row.getCell(0).setCellStyle(labelStyle);
|
java.math.BigDecimal qty = opQtyMap.getOrDefault(staffName, java.math.BigDecimal.ZERO);
|
createNumberCell(row, 1, qty, numStyle);
|
java.math.BigDecimal standardQty = standardMap.getOrDefault(operationName, java.math.BigDecimal.ONE);
|
createNumberCell(row, 2, standardQty.compareTo(java.math.BigDecimal.ZERO) == 0 ? java.math.BigDecimal.ZERO : qty.divide(standardQty, 2, java.math.RoundingMode.HALF_UP).multiply(new java.math.BigDecimal("8")), numStyle);
|
java.math.BigDecimal wage = operation == null || operation.getSalaryQuota() == null
|
? java.math.BigDecimal.ZERO
|
: (Integer.valueOf(1).equals(operation.getType()) ? operation.getSalaryQuota().multiply(qty) : operation.getSalaryQuota());
|
createNumberCell(row, 3, wage, numStyle);
|
}
|
|
for (int i = 0; i <= 3; i++) {
|
sheet.autoSizeColumn(i);
|
}
|
sheetIndex++;
|
}
|
|
try {
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
response.setCharacterEncoding("UTF-8");
|
String fileName = java.net.URLEncoder.encode("工时表.xlsx", java.nio.charset.StandardCharsets.UTF_8);
|
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName);
|
workbook.write(response.getOutputStream());
|
workbook.close();
|
} catch (IOException e) {
|
throw new RuntimeException("导出工时表失败", e);
|
}
|
}
|
|
public List<Map<String, Object>> setSchemeApplicableStaffUserInfo(List<Long> ids) {
|
if(CollectionUtils.isEmpty(ids)){
|
return new ArrayList<>();
|
}
|
// 通过部门获取人员id
|
return sysUserDeptMapper.setSchemeApplicableStaffUserInfo(ids);
|
}
|
|
@Override
|
public AjaxResult getAvailableDepts(String salaryMonth) {
|
if (StringUtils.isEmpty(salaryMonth)) {
|
return AjaxResult.error("工资月份不能为空");
|
}
|
|
List<String> issuedDeptIdStrings = staffSalaryMainMapper.selectIssuedDeptIds(salaryMonth);
|
|
Set<Long> issuedDeptIds = new HashSet<>();
|
for (String deptIds : issuedDeptIdStrings) {
|
if (StringUtils.isNotEmpty(deptIds)) {
|
String[] ids = deptIds.split(",");
|
for (String id : ids) {
|
issuedDeptIds.add(Long.parseLong(id.trim()));
|
}
|
}
|
}
|
|
List<SysDept> allDepts = sysDeptMapper.selectList(new LambdaQueryWrapper<SysDept>()
|
.eq(SysDept::getStatus, "0")
|
.eq(SysDept::getDelFlag, "0"));
|
|
List<SysDept> availableDepts = new ArrayList<>();
|
for (SysDept dept : allDepts) {
|
if (!issuedDeptIds.contains(dept.getDeptId())) {
|
availableDepts.add(dept);
|
}
|
}
|
|
return AjaxResult.success(availableDepts);
|
}
|
|
private boolean hasOverlappingDept(String deptIds1, String deptIds2) {
|
if (StringUtils.isEmpty(deptIds1) || StringUtils.isEmpty(deptIds2)) {
|
return false;
|
}
|
|
Set<String> deptSet1 = new HashSet<>(Arrays.asList(deptIds1.split(",")));
|
String[] deptArray2 = deptIds2.split(",");
|
|
for (String deptId : deptArray2) {
|
if (deptSet1.contains(deptId.trim())) {
|
return true;
|
}
|
}
|
return false;
|
}
|
|
private String buildWorkHoursTitle(StaffSalaryMain main) {
|
String month = StringUtils.isNotEmpty(main.getSalaryMonth()) ? main.getSalaryMonth() : "未知月份";
|
return month + "工时统计";
|
}
|
|
private Integer calculateWorkDays(String salaryMonth) {
|
if (StringUtils.isEmpty(salaryMonth)) {
|
return 0;
|
}
|
java.time.YearMonth yearMonth = java.time.YearMonth.parse(salaryMonth);
|
int workDays = 0;
|
for (int day = 1; day <= yearMonth.lengthOfMonth(); day++) {
|
java.time.DayOfWeek dayOfWeek = yearMonth.atDay(day).getDayOfWeek();
|
if (dayOfWeek != java.time.DayOfWeek.SATURDAY && dayOfWeek != java.time.DayOfWeek.SUNDAY) {
|
workDays++;
|
}
|
}
|
return workDays;
|
}
|
|
private CellStyle createStyle(Workbook workbook, boolean bold, HorizontalAlignment alignment, int fontSize, boolean fill) {
|
Font font = workbook.createFont();
|
font.setFontName("Microsoft YaHei");
|
font.setFontHeightInPoints((short) fontSize);
|
font.setBold(bold);
|
CellStyle style = workbook.createCellStyle();
|
style.setFont(font);
|
style.setAlignment(alignment);
|
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
style.setBorderTop(BorderStyle.THIN);
|
style.setBorderBottom(BorderStyle.THIN);
|
style.setBorderLeft(BorderStyle.THIN);
|
style.setBorderRight(BorderStyle.THIN);
|
if (fill) {
|
style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
|
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
}
|
return style;
|
}
|
|
private void createTextCell(Row row, int colIndex, String value, CellStyle style) {
|
Cell cell = row.createCell(colIndex);
|
cell.setCellValue(value == null ? "" : value);
|
cell.setCellStyle(style);
|
}
|
|
private void createNumberCell(Row row, int colIndex, java.math.BigDecimal value, CellStyle style) {
|
Cell cell = row.createCell(colIndex);
|
if (value != null) {
|
cell.setCellValue(value.doubleValue());
|
}
|
cell.setCellStyle(style);
|
}
|
|
private void createFormulaCell(Row row, int colIndex, String formula, CellStyle style) {
|
Cell cell = row.createCell(colIndex);
|
cell.setCellFormula(formula.startsWith("=") ? formula.substring(1) : formula);
|
cell.setCellStyle(style);
|
}
|
|
private String toCellRef(int colIndex, int rowNum1Based) {
|
return cellRef(colIndex) + rowNum1Based;
|
}
|
|
private String cellRef(int colIndex) {
|
StringBuilder sb = new StringBuilder();
|
int col = colIndex;
|
do {
|
int rem = col % 26;
|
sb.insert(0, (char) ('A' + rem));
|
col = col / 26 - 1;
|
} while (col >= 0);
|
return sb.toString();
|
}
|
|
private List<ProductionAccount> queryProductionAccounts(String salaryMonth) {
|
if (StringUtils.isEmpty(salaryMonth)) {
|
return new ArrayList<>();
|
}
|
YearMonth ym = YearMonth.parse(salaryMonth);
|
LocalDate start = ym.atDay(1);
|
LocalDate end = ym.atEndOfMonth();
|
return productionAccountMapper.selectList(new LambdaQueryWrapper<ProductionAccount>()
|
.ge(ProductionAccount::getSchedulingDate, start.atStartOfDay())
|
.le(ProductionAccount::getSchedulingDate, end.atTime(23, 59, 59)));
|
}
|
|
private Map<String, java.math.BigDecimal> buildOperationQuantityMap(List<ProductionAccount> accountList, String operationName) {
|
Map<String, java.math.BigDecimal> map = new LinkedHashMap<>();
|
if (CollectionUtils.isEmpty(accountList) || StringUtils.isEmpty(operationName)) {
|
return map;
|
}
|
accountList.stream()
|
.filter(item -> item != null && operationName.equals(item.getTechnologyOperationName()))
|
.filter(item -> StringUtils.isNotEmpty(item.getSchedulingUserName()))
|
.forEach(item -> map.merge(item.getSchedulingUserName(),
|
item.getFinishedNum() == null ? java.math.BigDecimal.ZERO : item.getFinishedNum(),
|
java.math.BigDecimal::add));
|
return map;
|
}
|
|
private Map<String, java.math.BigDecimal> buildStandardQuantityMap(List<String> operationNames) {
|
Map<String, java.math.BigDecimal> map = new LinkedHashMap<>();
|
if (CollectionUtils.isEmpty(operationNames)) {
|
return map;
|
}
|
List<TechnologyOperation> operations = technologyOperationMapper.selectList(
|
new LambdaQueryWrapper<TechnologyOperation>()
|
.in(TechnologyOperation::getName, operationNames)
|
);
|
Map<String, java.math.BigDecimal> opMap = operations.stream()
|
.filter(item -> item != null && StringUtils.isNotEmpty(item.getName()))
|
.collect(Collectors.toMap(
|
TechnologyOperation::getName,
|
item -> item.getStandardQuantity() == null ? java.math.BigDecimal.ZERO : item.getStandardQuantity(),
|
(left, right) -> left,
|
LinkedHashMap::new
|
));
|
for (String operationName : operationNames) {
|
map.put(operationName, opMap.getOrDefault(operationName, java.math.BigDecimal.ZERO));
|
}
|
return map;
|
}
|
|
}
|