|
@@ -0,0 +1,583 @@
|
|
|
|
+package com.management.platform.service.impl;
|
|
|
|
+
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
|
+import com.management.platform.entity.*;
|
|
|
|
+import com.management.platform.mapper.*;
|
|
|
|
+import com.management.platform.service.FinanceService;
|
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
|
+import com.management.platform.util.ExcelUtil;
|
|
|
|
+import com.management.platform.util.HttpRespMsg;
|
|
|
|
+import com.management.platform.util.MD5Util;
|
|
|
|
+import com.management.platform.util.SnowFlake;
|
|
|
|
+import lombok.extern.log4j.Log4j;
|
|
|
|
+import org.apache.log4j.LogManager;
|
|
|
|
+import org.apache.log4j.Logger;
|
|
|
|
+import org.apache.poi.hssf.usermodel.*;
|
|
|
|
+import org.apache.poi.ss.usermodel.CellType;
|
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFCell;
|
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFRow;
|
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFSheet;
|
|
|
|
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
|
+
|
|
|
|
+import javax.annotation.Resource;
|
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
|
+import java.io.*;
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
+import java.sql.Timestamp;
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
|
+import java.util.*;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * <p>
|
|
|
|
+ * 服务实现类
|
|
|
|
+ * </p>
|
|
|
|
+ *
|
|
|
|
+ * @author Seyason
|
|
|
|
+ * @since 2021-02-18
|
|
|
|
+ */
|
|
|
|
+@Service
|
|
|
|
+public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> implements FinanceService {
|
|
|
|
+ Logger logger = LogManager.getLogger(org.apache.logging.log4j.LogManager.ROOT_LOGGER_NAME);
|
|
|
|
+ @Resource
|
|
|
|
+ private FinanceMapper financeMapper;
|
|
|
|
+ @Resource
|
|
|
|
+ private ReportMapper reportMapper;
|
|
|
|
+ @Resource
|
|
|
|
+ private UserMapper userMapper;
|
|
|
|
+ @Resource
|
|
|
|
+ private DepartmentMapper departmentMapper;
|
|
|
|
+ @Resource
|
|
|
|
+ private FinanceService financeService;
|
|
|
|
+ @Resource
|
|
|
|
+ private ProjectMapper projectMapper;
|
|
|
|
+ @Value(value = "${upload.path}")
|
|
|
|
+ private String path;
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public HttpRespMsg getByMonth(Integer companyId, String yearMonth) {
|
|
|
|
+ HttpRespMsg msg = new HttpRespMsg();
|
|
|
|
+ List<Finance> financeList = financeMapper.selectList(new QueryWrapper<Finance>().eq("company_id", companyId).eq("ymonth", yearMonth));
|
|
|
|
+ msg.data = financeList;
|
|
|
|
+ return msg;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public HttpRespMsg importData(Integer companyId, String yearMonth, MultipartFile multipartFile, HttpServletRequest request) {
|
|
|
|
+ HttpRespMsg msg = new HttpRespMsg();
|
|
|
|
+
|
|
|
|
+ //然后处理文件
|
|
|
|
+ String fileName = multipartFile.getOriginalFilename();
|
|
|
|
+ File file = new File(fileName == null ? "file" : fileName);
|
|
|
|
+ InputStream inputStream = null;
|
|
|
|
+ OutputStream outputStream = null;
|
|
|
|
+ try {
|
|
|
|
+ inputStream = multipartFile.getInputStream();
|
|
|
|
+ outputStream = new FileOutputStream(file);
|
|
|
|
+ byte[] buffer = new byte[4096];
|
|
|
|
+ int temp = 0;
|
|
|
|
+ while ((temp = inputStream.read(buffer, 0, 4096)) != -1) {
|
|
|
|
+ outputStream.write(buffer, 0, temp);
|
|
|
|
+ }
|
|
|
|
+ inputStream.close();
|
|
|
|
+ outputStream.close();
|
|
|
|
+ //然后解析表格
|
|
|
|
+ XSSFWorkbook workbook = new XSSFWorkbook(file);
|
|
|
|
+ //我们只需要第一个sheet
|
|
|
|
+ XSSFSheet sheet = workbook.getSheetAt(0);
|
|
|
|
+ //要插入的账号列表
|
|
|
|
+ List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
|
|
|
|
+ List<Department> departmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
|
|
|
|
+ List<Finance> financeList = new ArrayList<Finance>();
|
|
|
|
+ List<Finance> oldFinanceList = financeMapper.selectList(new QueryWrapper<Finance>().eq("company_id", companyId).eq("ymonth", yearMonth));
|
|
|
|
+ //获取月成本列表
|
|
|
|
+ DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
|
+ String dateStr = yearMonth+"-01 00:00:00";
|
|
|
|
+ LocalDateTime startDate = LocalDateTime.parse(dateStr,df);
|
|
|
|
+ LocalDateTime endDate = LocalDateTime.parse(dateStr,df);
|
|
|
|
+ endDate = endDate.plusMonths(1);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //由于第一行需要指明列对应的标题
|
|
|
|
+ for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
|
|
|
+ XSSFRow row = sheet.getRow(rowIndex);
|
|
|
|
+ if (row == null) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ //姓名 工资 奖金 津贴 养老保险 医疗保险 失业保险 住房公积金 其他
|
|
|
|
+ XSSFCell nameCell = row.getCell(0);
|
|
|
|
+ XSSFCell salaryCell = row.getCell(1);
|
|
|
|
+ XSSFCell bonusCell = row.getCell(2);
|
|
|
|
+ XSSFCell allowanceCell = row.getCell(3);
|
|
|
|
+ XSSFCell inOldCell = row.getCell(4);
|
|
|
|
+ XSSFCell inMedicalCell = row.getCell(5);
|
|
|
|
+ XSSFCell inJobCell = row.getCell(6);
|
|
|
|
+ XSSFCell houseFundCell = row.getCell(7);
|
|
|
|
+ XSSFCell otherCell = row.getCell(8);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ nameCell.setCellType(CellType.STRING);
|
|
|
|
+ salaryCell.setCellType(CellType.STRING);
|
|
|
|
+ bonusCell.setCellType(CellType.STRING);
|
|
|
|
+ allowanceCell.setCellType(CellType.STRING);
|
|
|
|
+ inOldCell.setCellType(CellType.STRING);
|
|
|
|
+ inMedicalCell.setCellType(CellType.STRING);
|
|
|
|
+ inJobCell.setCellType(CellType.STRING);
|
|
|
|
+ houseFundCell.setCellType(CellType.STRING);
|
|
|
|
+ otherCell.setCellType(CellType.STRING);
|
|
|
|
+
|
|
|
|
+ String name = nameCell.getStringCellValue();
|
|
|
|
+ Finance finance = new Finance();
|
|
|
|
+ if (name.equals("姓名") && rowIndex == 0) {
|
|
|
|
+ //跳过第一行标题
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ finance.setCompanyId(companyId);
|
|
|
|
+ finance.setName(name);
|
|
|
|
+ Integer deptId = null;
|
|
|
|
+
|
|
|
|
+ Optional<User> first = first = userList.stream().filter(u -> u.getName().equals(name)).findFirst();
|
|
|
|
+ if (first.isPresent()) {
|
|
|
|
+ finance.setUserId(first.get().getId());
|
|
|
|
+ BigDecimal total = new BigDecimal(0);
|
|
|
|
+ if (salaryCell != null) {
|
|
|
|
+ salaryCell.setCellType(CellType.STRING);
|
|
|
|
+ String item = salaryCell.getStringCellValue();
|
|
|
|
+ BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
|
|
|
|
+ finance.setMonthCost(value);
|
|
|
|
+ total = total.add(value);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //按姓名做匹配
|
|
|
|
+ Optional<Finance> matchItem = oldFinanceList.stream().filter(o -> o.getName().equals(finance.getName())).findFirst();
|
|
|
|
+ if (matchItem.isPresent()) {
|
|
|
|
+ finance.setId(matchItem.get().getId());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (bonusCell != null) {
|
|
|
|
+ bonusCell.setCellType(CellType.STRING);
|
|
|
|
+ String bonusString = bonusCell.getStringCellValue();
|
|
|
|
+ BigDecimal bonus = bonusString != null ? new BigDecimal(bonusString) : BigDecimal.valueOf(0);
|
|
|
|
+ finance.setBonus(bonus);
|
|
|
|
+ total = total.add(bonus);
|
|
|
|
+ }
|
|
|
|
+ if (allowanceCell != null) {
|
|
|
|
+ allowanceCell.setCellType(CellType.STRING);
|
|
|
|
+ String item = allowanceCell.getStringCellValue();
|
|
|
|
+ BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
|
|
|
|
+ finance.setAllowance(value);
|
|
|
|
+ total = total.add(value);
|
|
|
|
+ }
|
|
|
|
+ if (inJobCell != null) {
|
|
|
|
+ inJobCell.setCellType(CellType.STRING);
|
|
|
|
+ String item = inJobCell.getStringCellValue();
|
|
|
|
+ BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
|
|
|
|
+ finance.setInsuranceLosejob(value);
|
|
|
|
+ total = total.add(value);
|
|
|
|
+ }
|
|
|
|
+ if (inMedicalCell != null) {
|
|
|
|
+ inMedicalCell.setCellType(CellType.STRING);
|
|
|
|
+ String item = inMedicalCell.getStringCellValue();
|
|
|
|
+ BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
|
|
|
|
+ finance.setInsuranceMedical(value);
|
|
|
|
+ total = total.add(value);
|
|
|
|
+ }
|
|
|
|
+ if (inOldCell != null) {
|
|
|
|
+ inOldCell.setCellType(CellType.STRING);
|
|
|
|
+ String item = inOldCell.getStringCellValue();
|
|
|
|
+ BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
|
|
|
|
+ finance.setInsuranceOld(value);
|
|
|
|
+ total = total.add(value);
|
|
|
|
+ }
|
|
|
|
+ if (houseFundCell != null) {
|
|
|
|
+ houseFundCell.setCellType(CellType.STRING);
|
|
|
|
+ String item = houseFundCell.getStringCellValue();
|
|
|
|
+ BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
|
|
|
|
+ finance.setHouseFund(value);
|
|
|
|
+ total = total.add(value);
|
|
|
|
+ }
|
|
|
|
+ if (otherCell != null) {
|
|
|
|
+ otherCell.setCellType(CellType.STRING);
|
|
|
|
+ String item = otherCell.getStringCellValue();
|
|
|
|
+ BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
|
|
|
|
+ finance.setOthers(value);
|
|
|
|
+ total = total.add(value);
|
|
|
|
+ }
|
|
|
|
+ finance.setTotalCost(total);
|
|
|
|
+ } else {
|
|
|
|
+ msg.setError("用户["+name+"]不存在,请在组织结构中添加该成员");
|
|
|
|
+ return msg;
|
|
|
|
+ }
|
|
|
|
+ finance.setYmonth(yearMonth);
|
|
|
|
+ financeList.add(finance);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ //最后删掉这个文件
|
|
|
|
+// if (!file.delete()) {
|
|
|
|
+// System.out.println("临时文件" + file.getName() + "删除失败");
|
|
|
|
+// }
|
|
|
|
+ System.out.println("size=="+financeList.size());
|
|
|
|
+ //批量插入
|
|
|
|
+ financeService.saveOrUpdateBatch(financeList);
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ msg.setError("文件处理出错");
|
|
|
|
+ return msg;
|
|
|
|
+ } catch (NullPointerException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ msg.setError("数据格式有误或存在空数据 导入失败");
|
|
|
|
+ return msg;
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ msg.setError("发生其他错误");
|
|
|
|
+ return msg;
|
|
|
|
+ } finally {
|
|
|
|
+ //关闭流
|
|
|
|
+ try {
|
|
|
|
+ if (outputStream != null && inputStream != null) {
|
|
|
|
+ outputStream.close();
|
|
|
|
+ inputStream.close();
|
|
|
|
+ System.out.println("流已关闭");
|
|
|
|
+ }
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+// file.deleteOnExit();//程序退出时删除临时文件
|
|
|
|
+ System.out.println(file.delete());
|
|
|
|
+ }
|
|
|
|
+ return msg;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public HttpRespMsg exportData(String yearMonth, HttpServletRequest request) {
|
|
|
|
+ HttpRespMsg httpRespMsg = new HttpRespMsg();
|
|
|
|
+ try {
|
|
|
|
+ Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
|
|
|
|
+ Map<String, Object> resultMap = new HashMap<>();
|
|
|
|
+ double totalCostTime = 0;
|
|
|
|
+ BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
|
|
|
|
+ BigDecimal totalSalary = BigDecimal.valueOf(0);
|
|
|
|
+ BigDecimal totalBonus = BigDecimal.valueOf(0);
|
|
|
|
+ BigDecimal totalAllowance = BigDecimal.valueOf(0);
|
|
|
|
+ BigDecimal totalOld = BigDecimal.valueOf(0);
|
|
|
|
+ BigDecimal totalMedical = BigDecimal.valueOf(0);
|
|
|
|
+ BigDecimal totalLoseJob = BigDecimal.valueOf(0);
|
|
|
|
+ BigDecimal totalHouse = BigDecimal.valueOf(0);
|
|
|
|
+ BigDecimal totalOther = BigDecimal.valueOf(0);
|
|
|
|
+
|
|
|
|
+ List<String> headList = new ArrayList<String>();
|
|
|
|
+ headList.add("项目");
|
|
|
|
+ headList.add("人员");
|
|
|
|
+ headList.add("时间(h)");
|
|
|
|
+ headList.add("工资(元)");
|
|
|
|
+ headList.add("奖金(元)");
|
|
|
|
+ headList.add("津贴(元)");
|
|
|
|
+ headList.add("养老保险(元)");
|
|
|
|
+ headList.add("医疗保险(元)");
|
|
|
|
+ headList.add("失业保险(元)");
|
|
|
|
+ headList.add("住房公积金(元)");
|
|
|
|
+ headList.add("其他(元)");
|
|
|
|
+ headList.add("总成本(元)");
|
|
|
|
+ List<List<String>> allList = new ArrayList<List<String>>();
|
|
|
|
+ allList.add(headList);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //获取月成本列表
|
|
|
|
+ DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
|
+ String dateStr = yearMonth+"-01 00:00:00";
|
|
|
|
+ LocalDateTime startDate = LocalDateTime.parse(dateStr,df);
|
|
|
|
+ LocalDateTime endDate = LocalDateTime.parse(dateStr,df);
|
|
|
|
+ endDate = endDate.plusMonths(1);
|
|
|
|
+
|
|
|
|
+ List<Map<String, Object>> projectTimeList = reportMapper.getRealProjectTime(startDate, endDate, companyId);
|
|
|
|
+
|
|
|
|
+ //计算每个项目的时间和成本
|
|
|
|
+ ProjectSumItem item = new ProjectSumItem();
|
|
|
|
+ List<ProjectSumItem> pList = new ArrayList<ProjectSumItem>();
|
|
|
|
+
|
|
|
|
+ //计算每个人的实际时薪(包含工资,奖金等)
|
|
|
|
+ HashMap<String, UserWorkTime> userTime = new HashMap<String, UserWorkTime>();
|
|
|
|
+ for (Map<String, Object> map : projectTimeList) {
|
|
|
|
+ String creatorId = (String) map.get("creatorId");
|
|
|
|
+ totalCostTime += (Double)map.get("workingTime");
|
|
|
|
+ if (userTime.get(creatorId) == null) {
|
|
|
|
+ UserWorkTime user = new UserWorkTime();
|
|
|
|
+ user.workingTime = new BigDecimal((Double)map.get("workingTime"));
|
|
|
|
+ userTime.put(creatorId, user);
|
|
|
|
+ } else {
|
|
|
|
+ //时间累加
|
|
|
|
+ userTime.get(creatorId).workingTime = userTime.get(creatorId).workingTime.add(new BigDecimal((Double)map.get("workingTime")));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ List<Finance> finances = financeMapper.selectList(new QueryWrapper<Finance>().eq("company_id", companyId).eq("ymonth", yearMonth));
|
|
|
|
+ List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
|
|
|
|
+
|
|
|
|
+ for (Map<String, Object> map : projectTimeList) {
|
|
|
|
+ String curProject = (String) map.get("project");
|
|
|
|
+ String creatorId = (String) map.get("creatorId");
|
|
|
|
+ Optional<Finance> first = finances.stream().filter(f -> f.getUserId().equals(creatorId)).findFirst();
|
|
|
|
+ Double workingTime = (Double)map.get("workingTime");
|
|
|
|
+ BigDecimal cost = new BigDecimal(0);
|
|
|
|
+ BigDecimal salary = new BigDecimal(0);
|
|
|
|
+ BigDecimal bonus = new BigDecimal(0);
|
|
|
|
+ BigDecimal allowance = new BigDecimal(0);
|
|
|
|
+ BigDecimal old = new BigDecimal(0);
|
|
|
|
+ BigDecimal medical = new BigDecimal(0);
|
|
|
|
+ BigDecimal loseJob = new BigDecimal(0);
|
|
|
|
+ BigDecimal house = new BigDecimal(0);
|
|
|
|
+ BigDecimal other = new BigDecimal(0);
|
|
|
|
+ if (first.isPresent()) {
|
|
|
|
+ Finance userFinance = first.get();
|
|
|
|
+ cost = userFinance.getTotalCost().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ salary = userFinance.getMonthCost().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ bonus = userFinance.getBonus().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ allowance = userFinance.getAllowance().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ old = userFinance.getInsuranceOld().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ medical = userFinance.getInsuranceMedical().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ loseJob = userFinance.getInsuranceLosejob().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ house = userFinance.getHouseFund().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ other = userFinance.getOthers().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ } else {
|
|
|
|
+ System.out.println("财务数据中未找到用户:"+creatorId);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (curProject.equals(item.project)) {
|
|
|
|
+ item.workingTime += workingTime;
|
|
|
|
+ item.cost = item.cost.add(cost);
|
|
|
|
+ item.salary = item.salary.add(salary);
|
|
|
|
+ item.bonus = item.bonus.add(bonus);
|
|
|
|
+ item.allowance = item.allowance.add(allowance);
|
|
|
|
+ item.old = item.old.add(old);
|
|
|
|
+ item.medical = item.medical.add(medical);
|
|
|
|
+ item.loseJob = item.loseJob.add(loseJob);
|
|
|
|
+ item.house = item.house.add(house);
|
|
|
|
+ item.other = item.other.add(other);
|
|
|
|
+ } else {
|
|
|
|
+ item = new ProjectSumItem();
|
|
|
|
+ pList.add(item);
|
|
|
|
+ item.project = curProject;
|
|
|
|
+ item.workingTime = workingTime;
|
|
|
|
+ item.cost = cost;
|
|
|
|
+ item.salary = salary;
|
|
|
|
+ item.bonus = bonus;
|
|
|
|
+ item.allowance = allowance;
|
|
|
|
+ item.old = old;
|
|
|
|
+ item.medical = medical;
|
|
|
|
+ item.loseJob = loseJob;
|
|
|
|
+ item.house = house;
|
|
|
|
+ item.other = other;
|
|
|
|
+ }
|
|
|
|
+ totalMoneyCost = totalMoneyCost.add(cost);
|
|
|
|
+ totalSalary = totalSalary.add(salary);
|
|
|
|
+ totalBonus = totalBonus.add(bonus);
|
|
|
|
+ totalAllowance = totalAllowance.add(allowance);
|
|
|
|
+ totalOld = totalOld.add(old);
|
|
|
|
+ totalMedical = totalMedical.add(medical);
|
|
|
|
+ totalLoseJob = totalLoseJob.add(loseJob);
|
|
|
|
+ totalHouse = totalHouse.add(house);
|
|
|
|
+ totalOther = totalOther.add(other);
|
|
|
|
+ }
|
|
|
|
+ //整体四舍五入处理
|
|
|
|
+ totalMoneyCost = totalMoneyCost.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ totalSalary = totalSalary.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ totalBonus = totalBonus.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ totalAllowance = totalAllowance.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ totalOld = totalOld.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ totalMedical = totalMedical.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ totalLoseJob = totalLoseJob.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ totalHouse = totalHouse.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ totalOther = totalOther.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+
|
|
|
|
+ pList.forEach(p->{
|
|
|
|
+ p.cost = p.cost.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ p.salary = p.salary.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ p.bonus = p.bonus.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ p.allowance = p.allowance.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ p.old = p.old.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ p.medical = p.medical.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ p.loseJob = p.loseJob.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ p.house = p.house.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ p.other = p.other.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+
|
|
|
|
+ //组装写入excel文件的数据,从项目开始,项目下面挂成员
|
|
|
|
+ List<String> rowData = new ArrayList<String>();
|
|
|
|
+ rowData.add(p.project);
|
|
|
|
+ rowData.add("");
|
|
|
|
+ rowData.add(p.workingTime+"");
|
|
|
|
+ rowData.add(p.salary.toPlainString());
|
|
|
|
+ rowData.add(p.bonus.toPlainString());
|
|
|
|
+ rowData.add(p.allowance.toPlainString());
|
|
|
|
+ rowData.add(p.old.toPlainString());
|
|
|
|
+ rowData.add(p.medical.toPlainString());
|
|
|
|
+ rowData.add(p.loseJob.toPlainString());
|
|
|
|
+ rowData.add(p.house.toPlainString());
|
|
|
|
+ rowData.add(p.other.toPlainString());
|
|
|
|
+ rowData.add(p.cost.toPlainString());
|
|
|
|
+ allList.add(rowData);
|
|
|
|
+
|
|
|
|
+ //获取成员
|
|
|
|
+ for (Map<String, Object> membMap : projectTimeList) {
|
|
|
|
+ if (membMap.get("project").equals(p.project)) {
|
|
|
|
+ //匹配到项目了
|
|
|
|
+ List<String> membRowData = new ArrayList<String>();
|
|
|
|
+ membRowData.add("");
|
|
|
|
+ Double workingTime = (Double) membMap.get("workingTime");
|
|
|
|
+ String creatorId = (String) membMap.get("creatorId");
|
|
|
|
+ User us = userList.stream().filter(u->u.getId().equals(creatorId)).findFirst().get();
|
|
|
|
+ Optional<Finance> first = finances.stream().filter(f -> f.getUserId().equals(creatorId)).findFirst();
|
|
|
|
+ if (!first.isPresent()) {
|
|
|
|
+ logger.info("用户["+us.getName()+"]在财务报表中不存在,请重新导入");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ Finance userFinance = first.get();
|
|
|
|
+
|
|
|
|
+ BigDecimal cost = userFinance.getTotalCost().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ BigDecimal salary = userFinance.getMonthCost().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ BigDecimal bonus = userFinance.getBonus().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ BigDecimal allowance = userFinance.getAllowance().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ BigDecimal old = userFinance.getInsuranceOld().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ BigDecimal medical = userFinance.getInsuranceMedical().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ BigDecimal loseJob = userFinance.getInsuranceLosejob().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ BigDecimal house = userFinance.getHouseFund().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ BigDecimal other = userFinance.getOthers().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+
|
|
|
|
+ membRowData.add(us.getName());
|
|
|
|
+ membRowData.add(workingTime+"");
|
|
|
|
+ membRowData.add(salary.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
|
|
|
|
+ membRowData.add(bonus.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
|
|
|
|
+ membRowData.add(allowance.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
|
|
|
|
+ membRowData.add(old.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
|
|
|
|
+ membRowData.add(medical.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
|
|
|
|
+ membRowData.add(loseJob.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
|
|
|
|
+ membRowData.add(house.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
|
|
|
|
+ membRowData.add(other.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
|
|
|
|
+ membRowData.add(cost.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
|
|
|
|
+ allList.add(membRowData);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ String total = totalMoneyCost.toString();
|
|
|
|
+ //合计
|
|
|
|
+ List<String> sumRow = new ArrayList<String>();
|
|
|
|
+ sumRow.add("合计");
|
|
|
|
+ sumRow.add("");
|
|
|
|
+ sumRow.add(""+totalCostTime);
|
|
|
|
+ sumRow.add(totalSalary.toString());
|
|
|
|
+ sumRow.add(totalBonus.toString());
|
|
|
|
+ sumRow.add(totalAllowance.toString());
|
|
|
|
+ sumRow.add(totalOld.toString());
|
|
|
|
+ sumRow.add(totalMedical.toString());
|
|
|
|
+ sumRow.add(totalLoseJob.toString());
|
|
|
|
+ sumRow.add(totalHouse.toString());
|
|
|
|
+ sumRow.add(totalOther.toString());
|
|
|
|
+ sumRow.add(totalMoneyCost.toString());
|
|
|
|
+
|
|
|
|
+ allList.add(sumRow);
|
|
|
|
+ //生成excel文件导出
|
|
|
|
+ String fileName = "财务人员成本_"+System.currentTimeMillis();
|
|
|
|
+ String resp = ExcelUtil.exportGeneralExcelByTitleAndList(fileName , allList, path);
|
|
|
|
+
|
|
|
|
+ httpRespMsg.data = resp;
|
|
|
|
+ } catch (NullPointerException e) {
|
|
|
|
+ httpRespMsg.setError("验证失败");
|
|
|
|
+ return httpRespMsg;
|
|
|
|
+ }
|
|
|
|
+ return httpRespMsg;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public HttpRespMsg getTimeCost(String yearMonth, HttpServletRequest request) {
|
|
|
|
+ HttpRespMsg httpRespMsg = new HttpRespMsg();
|
|
|
|
+ try {
|
|
|
|
+ Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
|
|
|
|
+ Map<String, Object> resultMap = new HashMap<>();
|
|
|
|
+ //获取月成本列表
|
|
|
|
+ DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
|
+ String dateStr = yearMonth+"-01 00:00:00";
|
|
|
|
+ LocalDateTime startDate = LocalDateTime.parse(dateStr,df);
|
|
|
|
+ LocalDateTime endDate = LocalDateTime.parse(dateStr,df);
|
|
|
|
+ endDate = endDate.plusMonths(1);
|
|
|
|
+
|
|
|
|
+ List<Map<String, Object>> projectTimeList = reportMapper.getRealProjectTime(startDate, endDate, companyId);
|
|
|
|
+
|
|
|
|
+ BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
|
|
|
|
+ //计算每个项目的时间和成本
|
|
|
|
+ ProjectSumItem item = new ProjectSumItem();
|
|
|
|
+ List<ProjectSumItem> pList = new ArrayList<ProjectSumItem>();
|
|
|
|
+
|
|
|
|
+ //计算每个人的实际时薪(包含工资,奖金等)
|
|
|
|
+ HashMap<String, BigDecimal> userTime = new HashMap<String, BigDecimal>();
|
|
|
|
+ for (Map<String, Object> map : projectTimeList) {
|
|
|
|
+ String creatorId = (String) map.get("creatorId");
|
|
|
|
+ if (userTime.get(creatorId) == null) {
|
|
|
|
+ userTime.put(creatorId, new BigDecimal((Double)map.get("workingTime")));
|
|
|
|
+ } else {
|
|
|
|
+ //时间累加
|
|
|
|
+ BigDecimal d = userTime.get(creatorId).add(new BigDecimal((Double)map.get("workingTime")));
|
|
|
|
+ userTime.put(creatorId, d);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ Set<String> strings = userTime.keySet();
|
|
|
|
+ Iterator<String> iterator = strings.iterator();
|
|
|
|
+ while (iterator.hasNext()) {
|
|
|
|
+ String next = iterator.next();
|
|
|
|
+ System.out.println(next+": "+userTime.get(next));
|
|
|
|
+ }
|
|
|
|
+ List<Finance> finances = financeMapper.selectList(new QueryWrapper<Finance>().eq("company_id", companyId).eq("ymonth", yearMonth));
|
|
|
|
+ List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
|
|
|
|
+ finances.forEach(f->{
|
|
|
|
+ String uid = f.getUserId();
|
|
|
|
+ BigDecimal b = userTime.get(uid);
|
|
|
|
+ BigDecimal avgHourCost = f.getTotalCost().divide(b,4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ f.setHourCost(avgHourCost);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ for (Map<String, Object> map : projectTimeList) {
|
|
|
|
+ String curProject = (String) map.get("project");
|
|
|
|
+ String creatorId = (String) map.get("creatorId");
|
|
|
|
+ Optional<Finance> first = finances.stream().filter(f -> f.getUserId().equals(creatorId)).findFirst();
|
|
|
|
+ Double workingTime = (Double)map.get("workingTime");
|
|
|
|
+ BigDecimal cost = new BigDecimal(0);
|
|
|
|
+ if (first.isPresent()) {
|
|
|
|
+ cost = first.get().getHourCost().multiply(new BigDecimal(workingTime));
|
|
|
|
+ } else {
|
|
|
|
+ System.out.println("财务数据中未找到用户:"+creatorId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (curProject.equals(item.project)) {
|
|
|
|
+ item.workingTime += workingTime;
|
|
|
|
+ item.cost = item.cost.add(cost);
|
|
|
|
+ } else {
|
|
|
|
+ item = new ProjectSumItem();
|
|
|
|
+ pList.add(item);
|
|
|
|
+ item.project = curProject;
|
|
|
|
+ item.workingTime = workingTime;
|
|
|
|
+ item.cost = cost;
|
|
|
|
+ }
|
|
|
|
+ totalMoneyCost = totalMoneyCost.add(cost);
|
|
|
|
+ }
|
|
|
|
+ //整体四舍五入处理
|
|
|
|
+ totalMoneyCost = totalMoneyCost.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ pList.forEach(p->{
|
|
|
|
+ p.cost = p.cost.setScale(2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
+ });
|
|
|
|
+ resultMap.put("costList", pList);
|
|
|
|
+ resultMap.put("totalMoneyCost", totalMoneyCost);
|
|
|
|
+ httpRespMsg.data = resultMap;
|
|
|
|
+ } catch (NullPointerException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ httpRespMsg.setError("验证失败");
|
|
|
|
+ return httpRespMsg;
|
|
|
|
+ }
|
|
|
|
+ return httpRespMsg;
|
|
|
|
+ }
|
|
|
|
+}
|