From 70a0b21595941890a9d26cfde01ff17e3427214a Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期四, 23 七月 2026 09:24:41 +0800
Subject: [PATCH] 修改工资计算

---
 src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java |  412 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 317 insertions(+), 95 deletions(-)

diff --git a/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
index d57a25e..c32d868 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
@@ -4,9 +4,10 @@
 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.framework.web.domain.R;
+import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.production.bean.dto.UserAccountDto;
 import com.ruoyi.production.bean.dto.UserProductionAccountingDto;
+import com.ruoyi.production.mapper.ProductionProductMainMapper;
 import com.ruoyi.production.service.SalesLedgerProductionAccountingService;
 import com.ruoyi.project.system.domain.SysDept;
 import com.ruoyi.project.system.domain.SysUser;
@@ -25,11 +26,15 @@
 import org.springframework.util.CollectionUtils;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.DayOfWeek;
+import java.time.YearMonth;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Collectors;
+import java.time.LocalDate;
 
 /**
  * <p>
@@ -49,20 +54,22 @@
     private final SysDeptMapper sysDeptMapper;
     private final StaffOnJobMapper staffOnJobMapper;
     private final SalesLedgerProductionAccountingService salesLedgerProductionAccountingService;
+    private final ProductionProductMainMapper productionProductMainMapper;
 
 
     @Override
-    public R<?> listPage(Page page, SchemeApplicableStaff schemeApplicableStaff) {
+    public AjaxResult listPage(Page page, SchemeApplicableStaff schemeApplicableStaff) {
         LambdaQueryWrapper<SchemeApplicableStaff> schemeApplicableStaffLambdaQueryWrapper = new LambdaQueryWrapper<>();
         if(schemeApplicableStaff != null){
             if(StringUtils.isNotEmpty(schemeApplicableStaff.getTitle())){
                 schemeApplicableStaffLambdaQueryWrapper.like(SchemeApplicableStaff::getTitle, schemeApplicableStaff.getTitle());
             }
         }
+        schemeApplicableStaffLambdaQueryWrapper.orderByDesc(SchemeApplicableStaff::getId);
         Page<SchemeApplicableStaff> page1 = schemeApplicableStaffMapper.selectPage(page, schemeApplicableStaffLambdaQueryWrapper);
         List<Long> collect = page1.getRecords().stream().map(SchemeApplicableStaff::getId).collect(Collectors.toList());
         if(CollectionUtils.isEmpty(collect)){
-            return R.ok(page1);
+            return AjaxResult.success(page1);
         }
         List<SchemeInsuranceDetail> schemeInsuranceDetails = schemeInsuranceDetailMapper
                 .selectList(new LambdaQueryWrapper<SchemeInsuranceDetail>()
@@ -82,7 +89,7 @@
                 item.setDeptNames(sysDepts.stream().map(SysDept::getDeptName).collect(Collectors.joining(",")));
             }
         });
-        return R.ok(page1);
+        return AjaxResult.success(page1);
     }
 
     public void setSchemeApplicableStaffUserInfo(SchemeApplicableStaff schemeApplicableStaff) {
@@ -103,12 +110,12 @@
     }
 
     @Override
-    public R<?> add(SchemeApplicableStaff schemeApplicableStaff) {
+    public AjaxResult add(SchemeApplicableStaff schemeApplicableStaff) {
         if(schemeApplicableStaff == null){
-            return R.fail("鍙傛暟閿欒");
+            return AjaxResult.error("鍙傛暟閿欒");
         }
         if(CollectionUtils.isEmpty(schemeApplicableStaff.getSchemeInsuranceDetailList())){
-            return R.fail("璇烽�夋嫨鏂规鏄庣粏");
+            return AjaxResult.error("璇烽�夋嫨鏂规鏄庣粏");
         }
         setSchemeApplicableStaffUserInfo(schemeApplicableStaff); //鏍规嵁閮ㄩ棬璁剧疆鐢ㄦ埛淇℃伅
         int insert = schemeApplicableStaffMapper.insert(schemeApplicableStaff);
@@ -116,13 +123,13 @@
             item.setSchemeId(schemeApplicableStaff.getId());
             schemeInsuranceDetailMapper.insert(item);
         });
-        return R.ok(insert);
+        return AjaxResult.success(insert);
     }
 
     @Override
-    public R<?> updateSchemeApplicableStaff(SchemeApplicableStaff schemeApplicableStaff) {
+    public AjaxResult updateSchemeApplicableStaff(SchemeApplicableStaff schemeApplicableStaff) {
         if(schemeApplicableStaff == null){
-            return R.fail("鍙傛暟閿欒");
+            return AjaxResult.error("鍙傛暟閿欒");
         }
         setSchemeApplicableStaffUserInfo(schemeApplicableStaff); //鏍规嵁閮ㄩ棬璁剧疆鐢ㄦ埛淇℃伅
         int update = schemeApplicableStaffMapper.updateById(schemeApplicableStaff);
@@ -133,18 +140,18 @@
             item.setSchemeId(schemeApplicableStaff.getId());
             schemeInsuranceDetailMapper.insert(item);
         });
-        return R.ok(update);
+        return AjaxResult.success(update);
     }
 
     @Override
-    public R<?> delete(List<Long> ids) {
+    public AjaxResult delete(List<Long> ids) {
         if (CollectionUtils.isEmpty(ids)) {
-            return R.fail("鍙傛暟閿欒");
+            return AjaxResult.error("鍙傛暟閿欒");
         }
         int delete = schemeApplicableStaffMapper.deleteBatchIds(ids);
         schemeInsuranceDetailMapper.delete(new LambdaQueryWrapper<SchemeInsuranceDetail>()
                 .in(SchemeInsuranceDetail::getSchemeId, ids));
-        return R.ok(delete);
+        return AjaxResult.success(delete);
     }
 
     /**
@@ -152,100 +159,236 @@
      * @param id
      */
     public void calculateByEmployeeId(Integer id,Map<String, Object> map,String date) {
-        // 1. 鍏ュ弬鏍¢獙
-        if (id == null) {
-            return; // 鎴栬繑鍥炵┖鍒楄〃锛屾牴鎹笟鍔¢渶姹傝皟鏁�
+        if (id == null || map == null) {
+            return;
         }
         Long staffId = id.longValue();
-        // 绀句繚閲戦
-        BigDecimal socialPersonal = new BigDecimal("0.00");
-        // 鍏Н閲戦噾棰�
-        BigDecimal fundPersonal = new BigDecimal("0.00");
-        // 鍩烘湰宸ヨ祫
-        BigDecimal basicSalary = new BigDecimal("0.00");
-        map.put("fundPersonal", fundPersonal); // 鍏Н閲�
-        map.put("socialPersonal", socialPersonal); // 绀句繚閲戦
-        map.put("basicSalary", basicSalary); // 鍩烘湰宸ヨ祫
-        // 涓◣閲戦
-        BigDecimal salaryTax = new BigDecimal("0.00");
-        map.put("salaryTax", salaryTax);
-        // 璁′欢宸ヨ祫
-        BigDecimal pieceSalary = new BigDecimal("0.00");
-        map.put("pieceSalary", pieceSalary);
-        // 璁℃椂宸ヨ祫
-        BigDecimal hourlySalary = new BigDecimal("0.00");
-        map.put("hourlySalary", hourlySalary);
-        // 鍏朵粬鏀跺叆
-        BigDecimal otherIncome = new BigDecimal("0.00");
-        map.put("otherIncome", otherIncome);
-        // 鍏朵粬鏀嚭
-        BigDecimal otherDeduct = new BigDecimal("0.00");
-        map.put("otherDeduct", otherDeduct);
-        // 搴斿彂宸ヨ祫
-        BigDecimal grossSalary = new BigDecimal("0.00");
-        map.put("grossSalary", grossSalary);
-        // 搴旀墸宸ヨ祫
-        BigDecimal deductSalary = new BigDecimal("0.00");
-        map.put("deductSalary", deductSalary);
-        // 瀹炲彂宸ヨ祫
-        BigDecimal netSalary = new BigDecimal("0.00");
-        map.put("netSalary", netSalary);
-        // 璋冪敤鍩烘湰宸ヨ祫
         StaffOnJob staffOnJobDto = staffOnJobMapper.selectById(staffId);
         if(staffOnJobDto == null){
             return;
         }
-        basicSalary = staffOnJobDto.getBasicSalary();
-        map.put("basicSalary", basicSalary);
-        // 搴斿彂宸ヨ祫
-        map.put("grossSalary", basicSalary);
-        // 涓◣閲戦锛堟棤绀句繚鐗堬級
-        BigDecimal bigDecimal = TaxCalculator.calculateMonthlyTax(basicSalary, socialPersonal, fundPersonal);
-        map.put("salaryTax", bigDecimal);
-        // 璁℃椂宸ヨ祫 璁′欢宸ヨ祫
+        BigDecimal basicSalary = resolveBasicSalary(map, staffOnJobDto);
+        BigDecimal attendanceBonus = resolveAttendanceBonus(staffOnJobDto);
+        BigDecimal otherIncome = normalizeMoney(getBigDecimal(map, "otherIncome"));
+        BigDecimal otherDeduct = normalizeMoney(getBigDecimal(map, "otherDeduct"));
+        BigDecimal socialSupplementAmount = resolveSocialSupplementAmount(map, staffOnJobDto);
+        BigDecimal socialPersonal = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        BigDecimal fundPersonal = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        int monthWorkDays = calculateWorkDays(date);
+        BigDecimal standardHours = calculateStandardHours(monthWorkDays);
+        BigDecimal actualOutput = resolveActualOutput(map);
+        BigDecimal standardQuantity = resolveStandardQuantity(map);
+        BigDecimal conversionFactor = resolveConversionFactor(map);
+
+        Long sysUserId = getUidByStaffId(staffId);
         UserProductionAccountingDto userProductionAccountingDto = new UserProductionAccountingDto();
-        userProductionAccountingDto.setUserId(getUidByStaffId(staffId));
+        userProductionAccountingDto.setUserId(sysUserId);
         userProductionAccountingDto.setDate(date);
         UserAccountDto byUserId = salesLedgerProductionAccountingService.getByUserId(userProductionAccountingDto);
-        if(byUserId != null){
-            map.put("pieceSalary", byUserId.getAccountBalance());
-            map.put("hourlySalary", byUserId.getAccount());
-            // 搴斿彂 瀹炲彂澧炲姞
-            grossSalary = grossSalary.add(byUserId.getAccountBalance()).add(byUserId.getAccount());
-            map.put("grossSalary", grossSalary);
-            netSalary = netSalary.add(byUserId.getAccountBalance()).add(byUserId.getAccount());
-            map.put("netSalary", netSalary);
-        }
-        // 2. 鏌ヨ璇ヤ汉鍛樺搴旂殑绀句繚鏂规
+        BigDecimal repairWorkHour = resolveRepairWorkHour(sysUserId, date);
+        BigDecimal convertedWorkHours = resolveConvertedWorkHours(
+                map,
+                actualOutput,
+                standardQuantity,
+                conversionFactor,
+                repairWorkHour,
+                byUserId
+        );
+        BigDecimal conversionRatio = calculateConversionRatio(standardHours, convertedWorkHours);
+
+        // 鏌ヨ璇ヤ汉鍛樺搴旂殑绀句繚鏂规
         List<SchemeApplicableStaff> schemeList = schemeApplicableStaffMapper.selectSchemeByStaffId(staffId);
-        if (CollectionUtils.isEmpty(schemeList)) {
-            return; // 鏃犲尮閰嶆柟妗堬紝杩斿洖绌哄垪琛�
-        }
-        // 3. 涓烘瘡涓柟妗堝叧鑱旀槑缁嗗垪琛�
-        for (SchemeApplicableStaff scheme : schemeList) {
-            List<SchemeInsuranceDetail> detailList = schemeApplicableStaffMapper.selectDetailBySchemeId(scheme.getId());
-            // 鏍规嵁鏄庣粏鍒楄〃璁$畻绀句繚缂磋垂閲戦
-            if(CollectionUtils.isEmpty(detailList)){
-                continue;
-            }
-            for (SchemeInsuranceDetail detail : detailList) {
-                if("鍏Н閲�".equals(detail.getInsuranceType())){
-                    fundPersonal = fundPersonal.add(calculateByEmployeeIdType(detail.getInsuranceType(),fundPersonal, staffOnJobDto, detail));
-                }else{
-                    socialPersonal = socialPersonal.add(calculateByEmployeeIdType(detail.getInsuranceType(),socialPersonal, staffOnJobDto, detail));
+        if (!CollectionUtils.isEmpty(schemeList)) {
+            for (SchemeApplicableStaff scheme : schemeList) {
+                List<SchemeInsuranceDetail> detailList = schemeApplicableStaffMapper.selectDetailBySchemeId(scheme.getId());
+                if(CollectionUtils.isEmpty(detailList)){
+                    continue;
+                }
+                for (SchemeInsuranceDetail detail : detailList) {
+                    if("鍏Н閲�".equals(detail.getInsuranceType())){
+                        fundPersonal = calculateByEmployeeIdType(detail.getInsuranceType(), fundPersonal, basicSalary, staffOnJobDto, detail);
+                    }else{
+                        socialPersonal = calculateByEmployeeIdType(detail.getInsuranceType(), socialPersonal, basicSalary, staffOnJobDto, detail);
+                    }
                 }
             }
         }
+
+        // 宸ヨ祫 = 鍏ㄥ嫟濂栭噾 + 鍩烘湰宸ヨ祫 * 鎶樺悎鍊嶆暟
+        BigDecimal grossSalary = attendanceBonus.add(basicSalary.multiply(conversionRatio)).add(otherIncome);
+        BigDecimal salaryTax = TaxCalculator.calculateMonthlyTax(
+                grossSalary,
+                socialPersonal.add(socialSupplementAmount),
+                fundPersonal
+        );
+        BigDecimal deductSalary = salaryTax
+                .add(fundPersonal)
+                .add(socialPersonal)
+                .add(socialSupplementAmount)
+                .add(otherDeduct);
+        BigDecimal netSalary = grossSalary.subtract(deductSalary);
+
+        if (!hasText(map, "staffName")) {
+            map.put("staffName", staffOnJobDto.getStaffName());
+        }
+        if (!hasText(map, "nation")) {
+            map.put("nation", staffOnJobDto.getNation());
+        }
+        map.put("basicSalary", basicSalary);
+        map.put("attendanceBonus", attendanceBonus);
+        map.put("monthWorkDays", monthWorkDays);
+        map.put("standardHours", standardHours);
+        map.put("actualOutput", actualOutput);
+        map.put("standardQuantity", standardQuantity);
+        map.put("conversionFactor", conversionFactor);
+        map.put("convertedWorkHours", convertedWorkHours);
+        map.put("monthTimeTotal", convertedWorkHours);
+        map.put("conversionRatio", conversionRatio);
+        map.put("pieceSalary", convertedWorkHours);
+        map.put("hourlySalary", BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
+        map.put("otherIncome", otherIncome);
         map.put("socialPersonal", socialPersonal);
         map.put("fundPersonal", fundPersonal);
-        // 涓◣閲戦锛堢ぞ淇濈増锛�
-        bigDecimal = TaxCalculator.calculateMonthlyTax(basicSalary, socialPersonal, fundPersonal);
-        map.put("salaryTax", bigDecimal);
-        // 搴旀墸宸ヨ祫
-        map.put("deductSalary", bigDecimal.add(fundPersonal).add(socialPersonal));
-        // 瀹炲彂宸ヨ祫
-        map.put("netSalary", basicSalary.subtract(bigDecimal).subtract(fundPersonal).subtract(socialPersonal));
+        map.put("otherDeduct", otherDeduct);
+        map.put("socialSupplementAmount", socialSupplementAmount);
+        map.put("grossSalary", grossSalary);
+        map.put("salaryTax", salaryTax);
+        map.put("deductSalary", deductSalary);
+        map.put("netSalary", netSalary);
+    }
 
+    /**
+     * 瑙f瀽鍛樺伐鍩虹宸ヨ祫銆�
+     * 浼樺厛浣跨敤宸ヨ祫琛ㄩ噷鏈浼犲叆鐨勫�硷紝鏈紶鏃跺洖钀藉埌鍛樺伐妗f涓殑鍩虹宸ヨ祫銆�
+     */
+    private BigDecimal resolveBasicSalary(Map<String, Object> map, StaffOnJob staffOnJobDto) {
+        // 鍛樺伐鍩虹宸ヨ祫浼樺厛鍙栧伐璧勮〃浼犲叆鍊硷紝娌℃湁鍒欏洖钀藉埌鍛樺伐妗f涓殑鍩虹宸ヨ祫銆�
+        return hasValue(map, "basicSalary")
+                ? normalizeMoney(getBigDecimal(map, "basicSalary"))
+                : normalizeMoney(staffOnJobDto.getBasicSalary());
+    }
+
+    /**
+     * 鑾峰彇鍛樺伐鏈�鏂板叏鍕ゅ閲戙��
+     * 鍏ㄥ嫟濂栭噾缁熶竴浠ュ憳宸ユ。妗堥厤缃负鍑嗐��
+     */
+    private BigDecimal resolveAttendanceBonus(StaffOnJob staffOnJobDto) {
+        // 鍏ㄥ嫟濂栭噾鐩存帴鍙栧憳宸ユ。妗堥噷鐨勬渶鏂伴厤缃��
+        return staffOnJobDto.getAttendanceBonus() == null
+                ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)
+                : normalizeMoney(staffOnJobDto.getAttendanceBonus());
+    }
+
+    /**
+     * 瑙f瀽绀句繚琛ョ即閲戦銆�
+     * 濡傛灉宸ヨ祫琛ㄤ紶鍏ヤ簡琛ョ即閲戦鍒欑洿鎺ヤ娇鐢紝鍚﹀垯鎸夊憳宸ユ墍灞為儴闂ㄦ渶鏂版柟妗堣绠椼��
+     */
+    private BigDecimal resolveSocialSupplementAmount(Map<String, Object> map, StaffOnJob staffOnJobDto) {
+        return hasValue(map, "socialSupplementAmount")
+                ? normalizeMoney(getBigDecimal(map, "socialSupplementAmount"))
+                : calculateLatestDeptSocialSupplementAmount(staffOnJobDto);
+    }
+
+    /**
+     * 璁$畻鏈堟爣鍑嗗伐鏃躲��
+     * 瑙勫垯锛氬伐浣滄棩澶╂暟 * 8 灏忔椂銆�
+     */
+    private BigDecimal calculateStandardHours(int monthWorkDays) {
+        // 鏈堟爣鍑嗗伐鏃� = 宸ヤ綔鏃ュぉ鏁� * 8 灏忔椂銆�
+        return BigDecimal.valueOf(monthWorkDays)
+                .multiply(new BigDecimal("8"))
+                .setScale(2, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * 瑙f瀽褰撴湀瀹為檯浜ч噺銆�
+     */
+    private BigDecimal resolveActualOutput(Map<String, Object> map) {
+        return hasValue(map, "actualOutput")
+                ? normalizeMoney(getBigDecimal(map, "actualOutput"))
+                : BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * 瑙f瀽宸ュ簭鏍囧噯鏁伴噺銆�
+     */
+    private BigDecimal resolveStandardQuantity(Map<String, Object> map) {
+        return hasValue(map, "standardQuantity")
+                ? normalizeMoney(getBigDecimal(map, "standardQuantity"))
+                : BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * 瑙f瀽宸ュ簭鎶樼畻绯绘暟锛屾湭閰嶇疆鏃堕粯璁� 1銆�
+     */
+    private BigDecimal resolveConversionFactor(Map<String, Object> map) {
+        return hasValue(map, "conversionFactor")
+                ? normalizeMoney(getBigDecimal(map, "conversionFactor"))
+                : BigDecimal.ONE.setScale(2, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * 姹囨�昏交寰繑宸ョ殑琛ヤ慨鐞嗗伐鏃躲��
+     * 鎸夌郴缁熺敤鎴� ID 鍜屽伐璧勬湀浠界粺璁★紝骞朵綔涓烘湀鏃堕棿鍚堣鐨勪竴閮ㄥ垎銆�
+     */
+    private BigDecimal resolveRepairWorkHour(Long sysUserId, String date) {
+        if (sysUserId == null || sysUserId <= 0 || StringUtils.isEmpty(date)) {
+            return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        }
+        LocalDate monthStart = YearMonth.parse(date).atDay(1);
+        LocalDate monthEnd = YearMonth.parse(date).atEndOfMonth();
+        return productionProductMainMapper.selectList(new LambdaQueryWrapper<com.ruoyi.production.pojo.ProductionProductMain>()
+                        .eq(com.ruoyi.production.pojo.ProductionProductMain::getUserId, sysUserId)
+                        .eq(com.ruoyi.production.pojo.ProductionProductMain::getReportType, 1)
+                        .ge(com.ruoyi.production.pojo.ProductionProductMain::getCreateTime, monthStart.atStartOfDay())
+                        .le(com.ruoyi.production.pojo.ProductionProductMain::getCreateTime, monthEnd.atTime(23, 59, 59)))
+                .stream()
+                .map(item -> normalizeMoney(item.getRepairWorkHour()))
+                .reduce(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP), BigDecimal::add)
+                .setScale(2, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * 璁$畻鏈堟椂闂村悎璁°��
+     * 璁′欢鍦烘櫙浣跨敤瀹為檯浜ч噺銆佹爣鍑嗘暟閲忓拰鎶樼畻绯绘暟鎹㈢畻锛�
+     * 娌℃湁璁′欢鏁版嵁鏃讹紝鍥炶惤鍒扮敓浜ф牳绠楁眹鎬诲�硷紱
+     * 鏈�鍚庡啀鍙犲姞杩斿伐琛ヤ慨鐞嗗伐鏃躲��
+     */
+    private BigDecimal resolveConvertedWorkHours(Map<String, Object> map,
+                                                 BigDecimal actualOutput,
+                                                 BigDecimal standardQuantity,
+                                                 BigDecimal conversionFactor,
+                                                 BigDecimal repairWorkHour,
+                                                 UserAccountDto byUserId) {
+        if (hasValue(map, "monthTimeTotal")) {
+            BigDecimal monthTimeTotal = normalizeMoney(getBigDecimal(map, "monthTimeTotal"));
+            if (monthTimeTotal.compareTo(BigDecimal.ZERO) > 0) {
+                return monthTimeTotal;
+            }
+        }
+        BigDecimal convertedWorkHours = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        // 璁′欢鎶樼畻宸ユ椂 = 褰撴湀瀹為檯浜ч噺 / 宸ュ簭鏍囧噯鏁伴噺 * 8 * 宸ュ簭鎶樼畻绯绘暟
+        if (actualOutput.compareTo(BigDecimal.ZERO) > 0 && standardQuantity.compareTo(BigDecimal.ZERO) > 0) {
+            convertedWorkHours = actualOutput
+                    .divide(standardQuantity, 8, RoundingMode.HALF_UP)
+                    .multiply(new BigDecimal("8"))
+                    .multiply(conversionFactor)
+                    .setScale(2, RoundingMode.HALF_UP);
+        } else if (byUserId != null) {
+            convertedWorkHours = normalizeMoney(byUserId.getAccountBalance().add(byUserId.getAccount()));
+        }
+        return convertedWorkHours.add(repairWorkHour).setScale(2, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * 璁$畻鎶樺悎鍊嶆暟銆�
+     * 瑙勫垯锛氭湀鏃堕棿鍚堣 / 鏈堟爣鍑嗗伐鏃躲��
+     */
+    private BigDecimal calculateConversionRatio(BigDecimal standardHours, BigDecimal convertedWorkHours) {
+        return standardHours.compareTo(BigDecimal.ZERO) == 0
+                ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)
+                : convertedWorkHours.divide(standardHours, 8, RoundingMode.HALF_UP)
+                .setScale(2, RoundingMode.HALF_UP);
     }
 
     /**
@@ -276,17 +419,96 @@
      * @param detail
      * @return
      */
-    public BigDecimal calculateByEmployeeIdType(String type,BigDecimal bigDecimal, StaffOnJob staffOnJobDto,SchemeInsuranceDetail detail) {
+    public BigDecimal calculateByEmployeeIdType(String type,BigDecimal bigDecimal, BigDecimal basicSalary, StaffOnJob staffOnJobDto,SchemeInsuranceDetail detail) {
         // 鍒ゆ柇鏄惁璋冪敤鍩烘湰宸ヨ祫
         if (detail.getUseBasicSalary() == 1) {
             BigDecimal divide = detail.getPaymentBase().multiply(detail.getPersonalRatio()).divide(new BigDecimal("100"), 2);
             bigDecimal = bigDecimal.add(divide);
         }else{
-            // 璋冪敤鍩烘湰宸ヨ祫
-            BigDecimal multiply = staffOnJobDto.getBasicSalary().multiply(detail.getPersonalRatio().divide(new BigDecimal("100"), 2));
+            // 璋冪敤褰撳墠宸ヨ祫琛ㄤ腑鐨勫熀鏈伐璧�
+            BigDecimal multiply = basicSalary.multiply(detail.getPersonalRatio().divide(new BigDecimal("100"), 2));
             bigDecimal = bigDecimal.add(multiply);
         }
         bigDecimal = bigDecimal.add(detail.getPersonalFixed());
         return bigDecimal;
     }
+
+    private BigDecimal calculateLatestDeptSocialSupplementAmount(StaffOnJob staffOnJobDto) {
+        if (staffOnJobDto == null || staffOnJobDto.getSysDeptId() == null) {
+            return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        }
+        SchemeApplicableStaff latestScheme = schemeApplicableStaffMapper.selectLatestSchemeByDeptId(staffOnJobDto.getSysDeptId());
+        if (latestScheme == null) {
+            return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        }
+        List<SchemeInsuranceDetail> detailList = schemeApplicableStaffMapper.selectDetailBySchemeId(latestScheme.getId());
+        if (CollectionUtils.isEmpty(detailList)) {
+            return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        }
+        BigDecimal socialSupplementAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        for (SchemeInsuranceDetail detail : detailList) {
+            if (!"鍏Н閲�".equals(detail.getInsuranceType())) {
+                socialSupplementAmount = calculateByEmployeeIdType(
+                        detail.getInsuranceType(),
+                        socialSupplementAmount,
+                        normalizeMoney(staffOnJobDto.getBasicSalary()),
+                        staffOnJobDto,
+                        detail
+                );
+            }
+        }
+        return socialSupplementAmount.setScale(2, RoundingMode.HALF_UP);
+    }
+
+    private boolean hasValue(Map<String, Object> map, String key) {
+        return map != null && map.get(key) != null;
+    }
+
+    private boolean hasText(Map<String, Object> map, String key) {
+        if (map == null) {
+            return false;
+        }
+        Object value = map.get(key);
+        return value != null && !String.valueOf(value).trim().isEmpty();
+    }
+
+    private BigDecimal getBigDecimal(Map<String, Object> map, String key) {
+        if (map == null) {
+            return null;
+        }
+        Object value = map.get(key);
+        if (value == null) {
+            return null;
+        }
+        if (value instanceof BigDecimal) {
+            return (BigDecimal) value;
+        }
+        if (value instanceof Number) {
+            return new BigDecimal(String.valueOf(value));
+        }
+        String text = String.valueOf(value).trim();
+        if (text.isEmpty()) {
+            return null;
+        }
+        return new BigDecimal(text);
+    }
+
+    private BigDecimal normalizeMoney(BigDecimal value) {
+        return value == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : value.setScale(2, RoundingMode.HALF_UP);
+    }
+
+    private int calculateWorkDays(String date) {
+        if (StringUtils.isEmpty(date)) {
+            return 0;
+        }
+        YearMonth yearMonth = YearMonth.parse(date);
+        int workDays = 0;
+        for (int day = 1; day <= yearMonth.lengthOfMonth(); day++) {
+            DayOfWeek dayOfWeek = yearMonth.atDay(day).getDayOfWeek();
+            if (dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY) {
+                workDays++;
+            }
+        }
+        return workDays;
+    }
 }

--
Gitblit v1.9.3