From 4862b3218cf19d646b4b95791009cd1aed629d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E4=B9=BE=E7=BF=94?= Date: Sat, 25 Apr 2026 16:17:14 +0800 Subject: [PATCH 1/3] bug --- .../mapper/EpciuPatrolInspectionMapper.xml | 10 +- .../BsEpciuPatrolInspectionServiceImpl.java | 6 +- .../BsSafePatrolInspectionServiceImpl.java | 15 +- .../desk/energy/util/DateTools.java | 498 ++++++++++++++++++ .../service/impl/PdaLoadServiceImpl.java | 4 +- 5 files changed, 518 insertions(+), 15 deletions(-) create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/energy/util/DateTools.java diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/energy/mapper/EpciuPatrolInspectionMapper.xml b/blade-service/blade-desk/src/main/java/org/springblade/desk/energy/mapper/EpciuPatrolInspectionMapper.xml index 074f564d..dea5924a 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/energy/mapper/EpciuPatrolInspectionMapper.xml +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/energy/mapper/EpciuPatrolInspectionMapper.xml @@ -32,7 +32,7 @@ left join blade_user u on u.id = n.INS_MAN n.is_deleted = 0 - + and n.TASK_STATUS = #{bsEpciuPatrolInspection.taskStatus} @@ -41,19 +41,19 @@ and n.INS_SITE like '%' || #{bsEpciuPatrolInspection.insSite} || '%' - + and n.INS_TYPE = #{bsEpciuPatrolInspection.insType} and n.INS_MAN like '%' || #{bsEpciuPatrolInspection.insMan} || '%' - + and n.INS_TYPE = #{bsEpciuPatrolInspection.insType} - + and n.LAUNCH_TIME BETWEEN to_date(#{bsEpciuPatrolInspection.startDate},'YYYY-MM-DD HH24:MI:SS') AND to_date(#{bsEpciuPatrolInspection.endDate},'YYYY-MM-DD HH24:MI:SS') - + and n.TEST_TIME BETWEEN to_date(#{bsEpciuPatrolInspection.startTestDate},'YYYY-MM-DD HH24:MI:SS') AND to_date(#{bsEpciuPatrolInspection.endTestDate},'YYYY-MM-DD HH24:MI:SS') diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/energy/service/impl/BsEpciuPatrolInspectionServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/energy/service/impl/BsEpciuPatrolInspectionServiceImpl.java index 9ec0a8d5..aa474b5f 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/energy/service/impl/BsEpciuPatrolInspectionServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/energy/service/impl/BsEpciuPatrolInspectionServiceImpl.java @@ -124,7 +124,7 @@ public class BsEpciuPatrolInspectionServiceImpl extends BaseServiceImpl ipLiST = bsSafeInspectionPointService.list(); if (ipLiST.size() == 0) { @@ -107,13 +109,16 @@ public class BsSafePatrolInspectionServiceImpl extends BaseServiceImplupdate().lambda().set(BsSafePatrolInspectionEntity::getTaskStatus, BsSafePatrolInspectionEntity.NO_CHECK).eq(BsSafePatrolInspectionEntity::getTaskStatus, BsSafePatrolInspectionEntity.PREPARE_TEXT)); + baseMapper.update(Wrappers.update().lambda() + .set(BsSafePatrolInspectionEntity::getTaskStatus, BsSafePatrolInspectionEntity.NO_CHECK) + .eq(BsSafePatrolInspectionEntity::getTaskStatus, BsSafePatrolInspectionEntity.PREPARE_TEXT)); } @Override diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/energy/util/DateTools.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/energy/util/DateTools.java new file mode 100644 index 00000000..afbada77 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/energy/util/DateTools.java @@ -0,0 +1,498 @@ +package org.springblade.desk.energy.util;/** + * @date : 2026/4/25 11:47 + */ + +import com.alibaba.fastjson.JSONObject; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +/** + * 文件名称 + * @module 归属项目 + * @author *** + * @date 2025/11/26 10:27 + */ +public class DateTools { + + + /** + * 查询今日是否是节假日 + * + * @return + */ + public static Boolean isHoliday() { + //IBsFactoryCalDataService bsFactoryCalDataService = (IBsFactoryCalDataService) SpringContextUtil.getBean("bsFactoryCalDataService"); + // + //Calendar c = Calendar.getInstance(); + //c.setTime(new Date()); + // + //int YY = c.get(Calendar.YEAR); + //int MM = c.get(Calendar.MONTH) + 1; + //int DD = c.get(Calendar.DATE); + // + //StringBuffer sb = new StringBuffer(); + //sb.append(YY); + //sb.append(MM < 10 ? "0" : "").append(MM); + //sb.append(DD < 10 ? "0" : "").append(DD); + //BsFactoryCalData bsFactoryCalData = bsFactoryCalDataService.getByYmd(Integer.valueOf(sb.toString())); + // + //return bsFactoryCalData == null ? false : bsFactoryCalData.getDayOff() == 1 ? true : false; + return false; + } + + /** + * 获取当前日期的往后day天的所有日期集合 + * + * @return + */ + public static List listNextDayDates(Integer day) { + + Calendar cal1 = Calendar.getInstance(); + Calendar cal2 = Calendar.getInstance(); + + cal1.setTime(new Date()); + cal2.setTime(new Date()); + + cal1.add(Calendar.DAY_OF_MONTH, 0); + cal2.add(Calendar.DAY_OF_MONTH, day); + + Calendar cStart = Calendar.getInstance(); + cStart.setTime(cal1.getTime()); + + List dateList = new ArrayList(); + //别忘了,把起始日期加上 + dateList.add(cal1.getTime()); + // 此日期是否在指定日期之后 + while (cal2.getTime().after(cStart.getTime())) { + // 根据日历的规则,为给定的日历字段添加或减去指定的时间量 + cStart.add(Calendar.DAY_OF_MONTH, 1); + dateList.add(cStart.getTime()); + } + return dateList; + } + + /** + * 获取当前时、天、月 例:时:Calendar.HOUR_OF_DAY + * + * @return + */ + public static Integer getDateTime(int cal) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + + int i = calendar.get(cal); + if (Calendar.MONTH == cal) { + i += 1; + } + return i; + } + + /** + * 获取传入日期时、天、月 例:时:Calendar.HOUR_OF_DAY + * + * @return + */ + public static Integer getDateTime(Date date, int cal) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + + int i = calendar.get(cal); + if (Calendar.MONTH == cal) { + i += 1; + } + + return i; + } + + /** + * 补全数值类型 + * + * @return + */ + public static String repairVal(Integer val) { + String valStr = null; + if (val < 10) { + valStr = "0" + val; + } else { + valStr = "" + val; + } + return valStr; + } + + + /** + * 获取月多少天 + * + * @return + */ + public static Integer getMonthHowDay(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + return calendar.getActualMaximum(Calendar.DAY_OF_MONTH); + } + + /** + * 获取月份最小日期时间 + * + * @param d + * @return + */ + public static final String getDateWithoutTime(Date d) { + if (d == null) { + return null; + } else { + Calendar c = Calendar.getInstance(); + c.setTime(d); + c.set(Calendar.DATE, 1); + c.set(11, 0); + c.set(12, 0); + c.set(13, 0); + c.set(14, 0); + return DateTime.date2String(c.getTime(), true, true); + } + } + + /** + * 获取月份最大日期时间 + * + * @param d + * @return + */ + public static final String getDateWithMaxTime(Date d) { + Calendar c = Calendar.getInstance(); + c.setTime(d); + c.set(Calendar.DATE, DateTools.getMonthHowDay(d)); + c.set(11, 23); + c.set(12, 59); + c.set(13, 59); + c.set(14, 999); + return DateTime.date2String(c.getTime(), true, true); + } + + /** + * 获取当年的第一天 + * + * @return + */ + public static final String getCurrYearFirst() { + Calendar currCal = Calendar.getInstance(); + int currentYear = currCal.get(Calendar.YEAR); + return getYearFirst(currentYear); + } + + /** + * 获取当年的最后一天 + * + * @return + */ + public static final String getCurrYearLast() { + Calendar currCal = Calendar.getInstance(); + int currentYear = currCal.get(Calendar.YEAR); + return getYearLast(currentYear); + } + + /** + * 获取某年第一天日期 + * + * @param year 年份 + * @return Date + */ + public static final String getYearFirst(int year) { + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + calendar.set(Calendar.YEAR, year); + return DateTime.date2String(calendar.getTime(), true, true); + } + + /** + * 获取某年最后一天日期 + * + * @param year 年份 + * @return Date + */ + public static final String getYearLast(int year) { + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + calendar.set(Calendar.YEAR, year); + calendar.roll(Calendar.DAY_OF_YEAR, -1); + return DateTime.date2String(calendar.getTime(), true, true); + } + + /** + * 获得本月的开始时间 + * + * @return + */ + public static String getMonthStartTimeStr(Date date) { + Calendar c = Calendar.getInstance(); + c.clear(); + c.setTime(date); + c.set(Calendar.DATE, 1); + return new SimpleDateFormat("yyyy-MM-dd").format(c.getTime()) + " 00:00:00"; + } + + /** + * 本月的结束时间 + * + * @return + */ + public static String getMonthEndTimeStr(Date date) { + Calendar c = Calendar.getInstance(); + c.clear(); + c.setTime(date); + c.set(Calendar.DATE, 1); + c.add(Calendar.MONTH, 1); + c.add(Calendar.DATE, -1); + return new SimpleDateFormat("yyyy-MM-dd").format(c.getTime()) + " 23:59:59"; + } + + /** + * 获取某年开始时间 + * + * @return Date + */ + public static final String getYearStartTimeStr(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + calendar.setTime(date); + return calendar.get(Calendar.YEAR) + "-01-01 00:00:00"; + } + + /** + * 获取某年结束时间 + * + * @return Date + */ + public static final String getYearEndTimeStr(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + calendar.setTime(date); + return calendar.get(Calendar.YEAR) + "-12-31 23:59:59"; + } + + /** + *

方法名: getTomorrow

+ *

方法描述: 获取当前日期后几天

+ * + * @param day + * @author lyj + * @date 2022-02-19 16:59 + */ + public static final String getTomorrow(int day) { + + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DATE, day); + + return DateTime.date2String(calendar.getTime(), true, true); + } + + /** + *

方法名: getYesterday

+ *

方法描述: 获取当前日期前几天

+ * + * @param day + * @author lyj + * @date 2022-02-19 16:59 + */ + public static final String getYesterday(int day) { + + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DATE, -day); + + return DateTime.date2String(calendar.getTime(), true, true); + } + + public static Date dateAdd(Date date, int x) { + //入参的格式 + // 24小时制 + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + if (date == null) { + return null; + } + + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + // 24小时制 + cal.add(Calendar.DATE, x); + //得到结算后的结果 yyyy-MM-dd HH:mm + date = cal.getTime(); + return date; + } + + public static Date dateAdd(Date date, int field, int x) { + //入参的格式 + // 24小时制 + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + if (date == null) { + return null; + } + + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + cal.add(field, x); + //得到结算后的结果 yyyy-MM-dd HH:mm + date = cal.getTime(); + return date; + } + + + /** + *

Description: 计算间隔天数

+ * + * @param date + * @param remDays + * @return: int + * @Author qjh + * @Date: 2022-10-11 9:11 + */ + public static int cycleDay(Date date, Integer remDays) { + + int days = ((int) (System.currentTimeMillis() / 1000) - (int) (date.getTime() / 1000)) / (60 * 60 * 24); + if (remDays != null) { + days += remDays; + } + return days; + } + + /** + * 根据当前日期返回日期范围 + * + * @return + */ + public static JSONObject getQuantityDate() { + Calendar cal = Calendar.getInstance(); + + int YY = cal.get(Calendar.YEAR); + int MM = cal.get(Calendar.MONTH) + 1; + int DD = cal.get(Calendar.DATE); + JSONObject obj = new JSONObject(); + String str1 = ""; + String str2 = ""; + String str3 = ""; + String str4 = ""; + // 如果当前日期大于20,返回本月21号,下月20 + if (DD > 20) { + // 本月 + str1 = YY + "-" + MM + "-" + "21 00:00:00"; + if (MM == 12) { + str2 = (YY + 1) + "-" + 1 + "-" + "20 23:59:59"; + } else { + str2 = YY + "-" + (MM + 1) + "-" + "20 23:59:59"; + } + str3 = String.valueOf(MM); + str4 = String.valueOf(YY); + } else { + + str3 = String.valueOf(MM); + str4 = String.valueOf(YY); + // 返回上月21号,本月20 + if (MM == 1) { + str1 = (YY - 1) + "-" + 12 + "-" + "21 00:00:00"; + str4 = String.valueOf(YY - 1); + } else { + str1 = YY + "-" + (MM - 1) + "-" + "21 00:00:00"; + str3 = String.valueOf(MM - 1); + } + str2 = YY + "-" + MM + "-" + "20 23:59:59"; + } + obj.put("YY", str4 + "-1-1 00:00:00"); + obj.put("MM", str3); + obj.put("startTime", str1); + obj.put("endTime", str2); + return obj; + } + + /** + * 获取传入日期的年月 + * + * @return + */ + public static String getYearMonth(Date date) { + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + int year = cal.get(Calendar.YEAR); + String month = cal.get(Calendar.MONTH) + 1 >= 10 ? String.valueOf(cal.get(Calendar.MONTH) + 1) : "0" + (cal.get(Calendar.MONTH) + 1); + return year + "-" + month; + } + + /** + * 根据当前日期获取上个月减去N天的日期 + * + * @return + */ + public static String getLastMonthData(Integer day) { + Calendar cal = Calendar.getInstance(); + + int YY = cal.get(Calendar.YEAR); + int MM = cal.get(Calendar.MONTH); + int DD = cal.get(Calendar.DATE); + String mm = MM < 10 ? "0" + MM : MM + ""; + String dd = DD < 10 ? "0" + DD : DD + ""; + + Integer monthHowDay = DateTools.getMonthHowDay(DateTime.parse(YY + "-" + mm + "-" + dd + " 00:00:00")); + DD = monthHowDay - day + 1; + System.out.println(YY + "-" + mm + "-" + DD + " 00:00:00"); + return YY + "-" + mm + "-" + DD + " 00:00:00"; + } + + /** + * 功能描述: 获取上一周的开始时间和结束时间 + */ + public static JSONObject getLastWeekStartOrEndDayOfWeek(Integer weekNum) { + + JSONObject obj = new JSONObject(); + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DATE, -7 * weekNum); // 获取上一周 + calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); // 设置为周一 + Date monday = calendar.getTime(); + + calendar.add(Calendar.DATE, 6); // 设置为周日 + Date sunday = calendar.getTime(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + obj.put("monday",sdf.format(monday)); + obj.put("sunday",sdf.format(sunday)); + return obj; + + } + //20240929 新建以下方法 获取25-25号的时间 + public static JSONObject getStartEndDate() { + Calendar cal = Calendar.getInstance(); + + int YY = cal.get(Calendar.YEAR); + int MM = cal.get(Calendar.MONTH) + 1; + int DD = cal.get(Calendar.DATE); + JSONObject obj = new JSONObject(); + String str1 = ""; + String str2 = ""; + // 如果当前日期大于25,返回本月25号,下月25 + if (DD > 25) { + // 本月 + str1 = YY + "-" + (MM > 9 ? MM : "0" + MM) + "-" + "25 00:00:00"; + if (MM == 12) { + str2 = (YY + 1) + "-" + "01" + "-" + "25 23:59:59"; + } else { + str2 = YY + "-" + ((MM + 1) > 9 ? (MM + 1) : "0" + (MM + 1)) + "-" + "25 23:59:59"; + } + } else { + // 返回上月25号,本月25 + if (MM == 1) { + str1 = (YY - 1) + "-" + 12 + "-" + "25 00:00:00"; + } else { + str1 = YY + "-" + ((MM - 1) > 9 ? MM - 1 : "0" + (MM - 1)) + "-" + "25 00:00:00"; + } + str2 = YY + "-" + (MM > 9 ? MM : "0" + MM) + "-" + "25 23:59:59"; + } + obj.put("startTime", str1); + obj.put("endTime", str2); + System.out.println(str1); + System.out.println(str2); + return obj; + } +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/PdaLoadServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/PdaLoadServiceImpl.java index c14cdb40..43f89380 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/PdaLoadServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/PdaLoadServiceImpl.java @@ -451,8 +451,8 @@ public class PdaLoadServiceImpl extends BaseServiceImpl piList = inspectionService.getByCode(code); - piList = piList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> - new TreeSet<>(Comparator.comparing(BsSafePatrolInspectionEntity::getIpId))), ArrayList::new)); + //piList = piList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> + // new TreeSet<>(Comparator.comparing(BsSafePatrolInspectionEntity::getIpId))), ArrayList::new)); if (null == piList || piList.size() == 0) { if (flag) { throw new RuntimeException("未查询到安全巡检任务,product.noPatrolCheckTask"); From 8804aa8c279f33eee80e65c71873743bf12699c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=B6=9B?= Date: Sat, 25 Apr 2026 16:35:16 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E7=94=9F=E4=BA=A7=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../desk/produce/service/impl/WorkOrderServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderServiceImpl.java index 85d06729..ba0be64b 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderServiceImpl.java @@ -465,7 +465,7 @@ public class WorkOrderServiceImpl extends BaseServiceImpl 0) { wpr.setReason("工序不可外协"); } else { - oemCraftAbilityService.count(Wrappers.lambdaQuery(OemCraftAbilityEntity.class).eq(OemCraftAbilityEntity::getCraftAbilityId, wp.getCaId())); + count = oemCraftAbilityService.count(Wrappers.lambdaQuery(OemCraftAbilityEntity.class).eq(OemCraftAbilityEntity::getCraftAbilityId, wp.getCaId())); if (count == 0) { wpr.setReason("无对应工艺能力厂商"); } From 8786869e5e69c0e3b37a9bf5cfce07a3af8db10e Mon Sep 17 00:00:00 2001 From: maxiangong <298222784@qq.com> Date: Sat, 25 Apr 2026 17:48:10 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E7=BB=A9=E6=95=88=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E8=B0=83=E6=95=B4=EF=BC=8C=E6=96=B0=E5=A2=9E=E8=96=AA=E8=B5=84?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../desk/order/pojo/entity/YieldOrder.java | 3 +- .../desk/produce/pojo/entity/WorkPlan.java | 5 + .../BsEfficiencyTaskController.java | 29 +- .../BsSalaryCalculationController.java | 44 +++ .../BsSalaryStandardController.java | 351 ++++++++++++++++++ .../enums/BsEfficiencyTaskEnum.java | 1 + .../enums/BsSalaryStandardEnum.java | 105 ++++++ .../excel/BsSalaryStandardExcel.java | 89 +++++ .../mapper/BsSalaryStandardMapper.java | 29 ++ .../mapper/EfficiencyTaskMapper.xml | 4 +- .../mapper/EfficiencyTaskReportMapper.xml | 8 +- .../mapper/SalaryStandardMapper.xml | 151 ++++++++ .../pojo/dto/BsSalaryCalculationDTO.java | 103 +++++ .../pojo/entity/BsSalaryStandardEntity.java | 84 +++++ .../pojo/vo/BsSalaryCalculationVO.java | 163 ++++++++ .../pojo/vo/BsSalaryStandardVO.java | 38 ++ .../service/IBsSalaryStandardService.java | 34 ++ .../impl/BsEfficiencyTempServiceImpl.java | 6 + .../impl/BsSalaryStandardServiceImpl.java | 37 ++ .../desk/efficiency/util/BsSalaryUtil.java | 163 ++++++++ .../desk/produce/mapper/WorkPlanMapper.java | 4 + .../desk/produce/mapper/WorkPlanMapper.xml | 119 ++++++ .../produce/service/IWorkOrderService.java | 6 + .../produce/service/IWorkPlanService.java | 4 + .../service/impl/WorkOrderServiceImpl.java | 112 ++++++ .../service/impl/WorkPlanServiceImpl.java | 9 + .../Excel/efficiency/工资维护标准.xls | Bin 0 -> 20992 bytes 27 files changed, 1693 insertions(+), 8 deletions(-) create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsSalaryCalculationController.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsSalaryStandardController.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/enums/BsSalaryStandardEnum.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/excel/BsSalaryStandardExcel.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/BsSalaryStandardMapper.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/SalaryStandardMapper.xml create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/dto/BsSalaryCalculationDTO.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/entity/BsSalaryStandardEntity.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/vo/BsSalaryCalculationVO.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/vo/BsSalaryStandardVO.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/service/IBsSalaryStandardService.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/service/impl/BsSalaryStandardServiceImpl.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/util/BsSalaryUtil.java create mode 100644 blade-service/blade-desk/src/main/resources/Excel/efficiency/工资维护标准.xls diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/order/pojo/entity/YieldOrder.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/order/pojo/entity/YieldOrder.java index 1eaa1d2a..f5890168 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/order/pojo/entity/YieldOrder.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/order/pojo/entity/YieldOrder.java @@ -472,7 +472,8 @@ public class YieldOrder extends BaseEntity { /** * 计划部门 */ - @TableField(value = "plan_deptcode") +// @TableField(value = "plan_deptcode") + @TableField(exist = false) private String planDeptCode; @JsonSerialize(nullsUsing = NullSerializer.class) diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/produce/pojo/entity/WorkPlan.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/produce/pojo/entity/WorkPlan.java index a77b7ac8..a56982f8 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/produce/pojo/entity/WorkPlan.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/produce/pojo/entity/WorkPlan.java @@ -344,5 +344,10 @@ public class WorkPlan extends BaseEntity { @Schema(description = "车间计划修改记录") private WorkPlanLog workPlanLog; + @Schema(description = "基础薪资金额") + private BigDecimal baseAmount; + + @Schema(description = "补贴薪资金额") + private BigDecimal subsidyAmount; } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsEfficiencyTaskController.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsEfficiencyTaskController.java index ff2e4711..cca0fb85 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsEfficiencyTaskController.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsEfficiencyTaskController.java @@ -196,7 +196,34 @@ public class BsEfficiencyTaskController extends BladeController { @PostMapping("/remove") @Operation(summary = "逻辑删除", description = "传入ids") public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) { - return R.status(bsEfficiencyTaskService.deleteLogic(Func.toLongList(ids))); + List idList = Func.toLongList(ids); + Set parentIds = new HashSet<>(); + for (Long id : idList) { + BsEfficiencyTaskEntity bsEfficiencyTaskEntity = bsEfficiencyTaskService.getById(id); + if (bsEfficiencyTaskEntity == null || bsEfficiencyTaskEntity.getStatus() != BsEfficiencyTaskEnum.STATUS_IN_PROGRESS.getCode()) { + return R.fail("选中任务明细不能删除"); + } + if (bsEfficiencyTaskEntity != null && bsEfficiencyTaskEntity.getParentId() != null && bsEfficiencyTaskEntity.getParentId() != 0) { + parentIds.add(bsEfficiencyTaskEntity.getParentId()); + } + } + for (Long parentId : parentIds) { + BsEfficiencyTaskEntity entity = bsEfficiencyTaskService.getById(parentId); + if (entity != null && entity.getStatus() != BsEfficiencyTaskEnum.STATUS_IN_PROGRESS.getCode()) { + return R.fail("选中任务明细不能删除"); + } + } + bsEfficiencyTaskService.deleteLogic(idList); + for (Long parentId : parentIds) { + List list = bsEfficiencyTaskService.list(new LambdaQueryWrapper().eq(BsEfficiencyTaskEntity::getParentId, parentId)); + if (CollectionUtils.isEmpty(list)) { + BsEfficiencyTaskEntity upd = new BsEfficiencyTaskEntity(); + upd.setId(parentId); + upd.setStatus(BsEfficiencyTaskEnum.STATUS_FAIL.getCode()); + bsEfficiencyTaskService.saveOrUpdate(upd); + } + } + return R.success(); } /** diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsSalaryCalculationController.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsSalaryCalculationController.java new file mode 100644 index 00000000..3b80c35c --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsSalaryCalculationController.java @@ -0,0 +1,44 @@ +package org.springblade.desk.efficiency.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.springblade.core.mp.support.Condition; +import org.springblade.core.mp.support.Query; +import org.springblade.core.tool.api.R; +import org.springblade.desk.efficiency.pojo.dto.BsSalaryCalculationDTO; +import org.springblade.desk.efficiency.pojo.vo.BsSalaryCalculationVO; +import org.springblade.desk.efficiency.pojo.vo.BsSalaryStandardVO; +import org.springblade.desk.produce.service.IWorkOrderService; +import org.springblade.desk.produce.service.IWorkPlanService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 薪资计算 控制器 + * + * @author BladeX + * @since 2026-04-23 + */ +@RestController +@AllArgsConstructor +@RequestMapping("/bsSalaryCalculation") +@Tag(name = "薪资规则表", description = "薪资计算接口") +public class BsSalaryCalculationController { + + private final IWorkPlanService workPlanService; + + private final IWorkOrderService workOrderService; + + /** + * 薪资计算 自定义分页 + */ + @GetMapping("/page") + @Operation(summary = "分页", description = "传入bsSalaryCalculation") + public R> page(BsSalaryCalculationDTO bsSalaryCalculation, Query query) { + IPage pages = workPlanService.selectBsSalaryCalculationPage(Condition.getPage(query), bsSalaryCalculation); + return R.data(pages); + } +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsSalaryStandardController.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsSalaryStandardController.java new file mode 100644 index 00000000..041d05b8 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/controller/BsSalaryStandardController.java @@ -0,0 +1,351 @@ +package org.springblade.desk.efficiency.controller; + +import com.alibaba.excel.util.StringUtils; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.AllArgsConstructor; +import net.logstash.logback.encoder.org.apache.commons.lang3.ObjectUtils; +import org.springblade.core.excel.util.ExcelUtil; +import org.springblade.core.mp.support.Condition; +import org.springblade.core.mp.support.Query; +import org.springblade.core.tool.api.R; +import org.springblade.core.tool.utils.Func; +import org.springblade.desk.basic.util.ExcelExtUtil; +import org.springblade.desk.dashboard.pojo.entity.BsProcessSetEntity; +import org.springblade.desk.dashboard.service.IBsProcessSetService; +import org.springblade.desk.efficiency.enums.BsSalaryStandardEnum; +import org.springblade.desk.efficiency.excel.BsSalaryStandardExcel; +import org.springblade.desk.efficiency.pojo.entity.BsSalaryStandardEntity; +import org.springblade.desk.efficiency.pojo.vo.BsSalaryStandardVO; +import org.springblade.desk.efficiency.service.IBsSalaryStandardService; +import org.springframework.beans.BeanUtils; +import org.springframework.core.io.Resource; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 薪资规则 控制器 + * + * @author BladeX + * @since 2026-04-23 + */ +@RestController +@AllArgsConstructor +@RequestMapping("/bsSalaryStandard") +@Tag(name = "薪资规则表", description = "薪资规则接口") +public class BsSalaryStandardController { + + private final IBsSalaryStandardService bsSalaryStandardService; + + private final IBsProcessSetService bsProcessSetService; + + /** + * 薪资规则表 自定义分页 + */ + @GetMapping("/page") + @Operation(summary = "分页", description = "传入bsEfficiencyTemp") + public R> page(BsSalaryStandardVO bsSalaryStandardVO, Query query) { + IPage pages = bsSalaryStandardService.selectBsSalaryStandardPage(Condition.getPage(query), bsSalaryStandardVO); + return R.data(pages); + } + + /** + * 薪资规则表 新增或修改 + */ + @PostMapping("/submit") + @Operation(summary = "新增或修改", description = "传入bsEnergyTarget") + public R submit(@Valid @RequestBody BsSalaryStandardEntity bsSalaryStandard) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper().eq(BsSalaryStandardEntity::getProcessId, bsSalaryStandard.getProcessId()); + if (bsSalaryStandard.getId() != null) { + wrapper.ne(BsSalaryStandardEntity::getId, bsSalaryStandard.getId()); + } + List list = bsSalaryStandardService.list(wrapper); + if (checkExcelDuplicateData(bsSalaryStandard,list)) { + return R.fail("已存在重复的薪资规则"); + } + if (BsSalaryStandardEnum.STEP_TYPE_STEP.getCode().equals(bsSalaryStandard.getStepType())) { + if (!checkStepNumber(bsSalaryStandard.getStep(), bsSalaryStandard.getStepSettlementPrice())) { + return R.fail("阶梯结算价与阶梯不一致"); + } + } + return R.status(bsSalaryStandardService.saveOrUpdate(bsSalaryStandard)); + } + + /** + * 薪资规则表 删除 + */ + @PostMapping("/remove") + @Operation(summary = "逻辑删除", description = "传入ids") + public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) { + return R.status(bsSalaryStandardService.deleteLogic(Func.toLongList(ids))); + } + + /** + * 薪资规则表 详情 + */ + @GetMapping("/detail") + @Operation(summary = "详情", description = "传入bsSalaryStandard") + public R detail(BsSalaryStandardEntity bsSalaryStandardEntity) { + BsSalaryStandardVO vo = new BsSalaryStandardVO(); + BsSalaryStandardEntity bsSalaryStandard = bsSalaryStandardService.getById(bsSalaryStandardEntity.getId()); + BeanUtils.copyProperties(bsSalaryStandard, vo); + return R.data(vo); + } + + /** + * 检查阶梯数据 + * + * @param step + * @param stepSettlementPrice + * @return + */ + private boolean checkStepNumber(String step, String stepSettlementPrice) { + // ====================== 1、先校验 step 必须严格递增 ====================== + if (step != null && !step.isBlank()) { + String[] stepArr = step.trim().split("\\s+"); + if (Double.parseDouble(stepArr[0].trim()) <= 0) { + return false; + } + // 校验递增 + for (int i = 1; i < stepArr.length; i++) { + try { + double prev = Double.parseDouble(stepArr[i - 1].trim()); + double curr = Double.parseDouble(stepArr[i].trim()); + if (curr <= prev) { + return false; + } + } catch (NumberFormatException e) { + return false; + } + } + } + + // ====================== 2、校验个数:stepSettlementPrice = step + 1 ====================== + int stepCount = 0; + if (step != null && !step.isBlank()) { + stepCount = step.trim().split("\\s+").length; + } + + int otherCount = 0; + if (stepSettlementPrice != null && !stepSettlementPrice.isBlank()) { + otherCount = stepSettlementPrice.trim().split("\\s+").length; + } + + // 必须满足:otherStep 分段数 = step 分段数 + 1 + return otherCount == stepCount + 1; + } + + /** + * 下载Excel模板 + * + * @return + */ + @GetMapping("/download-excel-template") + @Operation(summary = "下载Excel模板", description = "") + public ResponseEntity downloadExcelTemplate() { + return ExcelExtUtil.downloadXlsTemplate("Excel/efficiency/工资维护标准.xls", "导入模版-工资维护标准.xls"); + } + + /** + * 导入Excel + * + * @param file + * @return + */ + @PostMapping("/import-excel") + @Operation(summary = "导入Excel", description = "MultipartFile") + public R waterImportExcel(@RequestParam("file") MultipartFile file) { + R checkR = ExcelExtUtil.importExcelCheck(file); + if (checkR != null) { + return checkR; + } + List importList = ExcelUtil.read(file, 0, 1, BsSalaryStandardExcel.class); + if (checkExcelDuplicate(importList)) { + return R.fail("Excel中存在重复数据,请检查后重新导入"); + } + List saveBatchList = new ArrayList<>(); + for (BsSalaryStandardExcel excel : importList) { + BsProcessSetEntity processSet = bsProcessSetService.getOne(new LambdaQueryWrapper().eq(BsProcessSetEntity::getCode, excel.getProcessCode()).eq(BsProcessSetEntity::getName, excel.getProcessName())); + if (processSet == null) { + return R.fail(excel.getProcessCode() + "-" + excel.getProcessName() + "工序不存在"); + } + List list = bsSalaryStandardService.list(new LambdaQueryWrapper().eq(BsSalaryStandardEntity::getProcessId, processSet.getId())); + BsSalaryStandardEntity bsSalaryStandard = new BsSalaryStandardEntity(); + BeanUtils.copyProperties(excel, bsSalaryStandard); + bsSalaryStandard.setProcessId(processSet.getId()); + bsSalaryStandard.setStandardType(BsSalaryStandardEnum.convertStandType(bsSalaryStandard.getStandardType())); + bsSalaryStandard.setStepType(BsSalaryStandardEnum.convertStepType(bsSalaryStandard.getStepType())); + bsSalaryStandard.setStepUnit(BsSalaryStandardEnum.convertStepUnit(bsSalaryStandard.getStepUnit())); + bsSalaryStandard.setStepSettlementUnit(BsSalaryStandardEnum.convertStepSettlementUnit(bsSalaryStandard.getStepSettlementUnit())); + bsSalaryStandard.setSettlementUnit(BsSalaryStandardEnum.convertSettlementUnit(bsSalaryStandard.getSettlementUnit())); + if (checkExcelDuplicateData(bsSalaryStandard, list)) { + return R.fail("已存在重复的薪资规则"); + } + if (BsSalaryStandardEnum.STEP_TYPE_STEP.getCode().equals(bsSalaryStandard.getStepType())) { + if (!checkStepNumber(bsSalaryStandard.getStep(), bsSalaryStandard.getStepSettlementPrice())) { + return R.fail("阶梯结算价与阶梯不一致"); + } + } + saveBatchList.add(bsSalaryStandard); + } + return R.status(bsSalaryStandardService.saveBatch(saveBatchList)); + } + + /** + * 校验 Excel 数据重复 + * + * @param excelList + */ + private boolean checkExcelDuplicate(List excelList) { + // 外层:逐个检查 + for (int i = 0; i < excelList.size(); i++) { + BsSalaryStandardExcel current = excelList.get(i); + + // 内层:和前面所有行比较 + for (int j = 0; j < i; j++) { + BsSalaryStandardExcel previous = excelList.get(j); + + // 1. 先判断:processCode + processName 必须相同才可能重复 + boolean sameProcess = ObjectUtils.equals(current.getProcessCode(), previous.getProcessCode()) && ObjectUtils.equals(current.getProcessName(), previous.getProcessName()); + + if (!sameProcess) { + continue; + } + + // 2. 核心:类型冲突判断 + boolean typeConflict = isTypeConflict(current.getStandardType(), previous.getStandardType()); + if (!typeConflict) { + continue; + } + + // 3. partNo 模糊匹配判断(支持空=%) + boolean partNoMatch = isPartNoMatch(current.getPartNo(), previous.getPartNo()); + + if (partNoMatch) { + return true; + } + } + } + return false; + } + + private boolean checkExcelDuplicateData(BsSalaryStandardEntity current, List entities) { + for (int i = 0; i < entities.size(); i++) { + BsSalaryStandardEntity previous = entities.get(i); + boolean sameProcess = ObjectUtils.equals(current.getProcessId(), previous.getProcessId()); + if (!sameProcess) { + continue; + } + boolean typeConflict = isTypeConflictCode(current.getStandardType(), previous.getStandardType()); + if (!typeConflict) { + continue; + } + boolean partNoMatch = isPartNoMatch(current.getPartNo(), previous.getPartNo()); + if (partNoMatch) { + return true; + } + } + return false; + } + + /** + * 判断规则类型是否重复 + * + * @param type1 + * @param type2 + * @return + */ + private boolean isTypeConflict(String type1, String type2) { + String COMMON = BsSalaryStandardEnum.STANDARD_TYPE_COMMON.getName(); + String MILITARY = BsSalaryStandardEnum.STANDARD_TYPE_MILITARY.getName(); + String NON_MILITARY = BsSalaryStandardEnum.STANDARD_TYPE_NON_MILITARY.getName(); + if (COMMON.equals(type1) || COMMON.equals(type2)) { + return true; + } + if (MILITARY.equals(type1) && MILITARY.equals(type2)) { + return true; + } + if (NON_MILITARY.equals(type1) && NON_MILITARY.equals(type2)) { + return true; + } + return false; + } + + private boolean isTypeConflictCode(String type1, String type2) { + String COMMON = BsSalaryStandardEnum.STANDARD_TYPE_COMMON.getCode(); + String MILITARY = BsSalaryStandardEnum.STANDARD_TYPE_MILITARY.getCode(); + String NON_MILITARY = BsSalaryStandardEnum.STANDARD_TYPE_NON_MILITARY.getCode(); + if (COMMON.equals(type1) || COMMON.equals(type2)) { + return true; + } + if (MILITARY.equals(type1) && MILITARY.equals(type2)) { + return true; + } + if (NON_MILITARY.equals(type1) && NON_MILITARY.equals(type2)) { + return true; + } + return false; + } + + /** + * partNo 匹配规则: + * 1. 空 = % + * 2. 按空格拆分 + * 3. 任意一个片段匹配即返回 true + */ + private boolean isPartNoMatch(String partNo1, String partNo2) { + // 空 = % 匹配所有 + List list1 = splitPartNo(partNo1); + List list2 = splitPartNo(partNo2); + if (StringUtils.isEmpty(partNo1) && StringUtils.isEmpty(partNo2)) { + return true; + } + // 任意片段匹配就重复 + for (String p1 : list1) { + for (String p2 : list2) { + if (likeMatch(p1, p2) || likeMatch(p2, p1)) { + return true; + } + } + } + return false; + } + + /** + * 拆分 partNo:空 → [%],否则按空格拆分 + */ + private List splitPartNo(String partNo) { + List list = new ArrayList<>(); + if (partNo == null || partNo.isBlank()) { +// list.add("%"); + return list; + } + String[] arr = partNo.trim().split("\\s+"); + for (String s : arr) { + if (!s.isBlank()) { + list.add(s.trim()); + } + } + return list; + } + + /** + * 实现模糊匹配:支持 % + * likeMatch("100", "10%") → true + */ + private boolean likeMatch(String pattern, String value) { + // 转成 Java 正则 + String regex = pattern.replace("%", ".*"); + return value.matches(regex); + } + +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/enums/BsEfficiencyTaskEnum.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/enums/BsEfficiencyTaskEnum.java index bfbfe3e9..a313ae73 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/enums/BsEfficiencyTaskEnum.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/enums/BsEfficiencyTaskEnum.java @@ -16,6 +16,7 @@ public enum BsEfficiencyTaskEnum { STATUS_APPROVED("审批通过", 4), STATUS_REJECTED("审批不通过", 5), STATUS_EXPIRED("已超期", 6), + STATUS_FAIL("任务失败", 7), ; final String name; diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/enums/BsSalaryStandardEnum.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/enums/BsSalaryStandardEnum.java new file mode 100644 index 00000000..8a92f892 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/enums/BsSalaryStandardEnum.java @@ -0,0 +1,105 @@ +package org.springblade.desk.efficiency.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 工资规则维护枚举 + */ +@Getter +@AllArgsConstructor +public enum BsSalaryStandardEnum { + + /** + * 规则类型 + */ + STANDARD_TYPE_COMMON("通用", "1"), + STANDARD_TYPE_MILITARY("军品", "2"), + STANDARD_TYPE_NON_MILITARY("非军品", "3"), + + /** + * 阶梯类型 + */ + STEP_TYPE_NON("无补贴金额", "1"), + STEP_TYPE_FIXED("固定补贴金额", "2"), + STEP_TYPE_STEP("阶梯补贴金额", "3"), + + /** + * 阶梯单位 + */ + STEP_UNIT_PIECE("件", "1"), + STEP_UNIT_AREA("面积", "2"), + + /** + * 阶梯结算单位 + */ + STEP_SETTLEMENT_UNIT_BATCH("批", "1"), + STEP_SETTLEMENT_UNIT_MULTIPLE("倍", "2"), + + /** + * 工人结算单位 + */ + SETTLEMENT_UNIT_PIECE("件", "1"), + SETTLEMENT_UNIT_BATCH("批", "2"), + SETTLEMENT_UNIT_AREA("面积", "3"), + + ; + final String name; + final String code; + + public static String convertStandType(String name){ + if (BsSalaryStandardEnum.STANDARD_TYPE_COMMON.getName().equals(name)) { + return BsSalaryStandardEnum.STANDARD_TYPE_COMMON.getCode(); + } + if (BsSalaryStandardEnum.STANDARD_TYPE_MILITARY.getName().equals(name)) { + return BsSalaryStandardEnum.STANDARD_TYPE_MILITARY.getCode(); + } + if (BsSalaryStandardEnum.STANDARD_TYPE_NON_MILITARY.getName().equals(name)) { + return BsSalaryStandardEnum.STANDARD_TYPE_NON_MILITARY.getCode(); + } + return null; + } + public static String convertStepType(String name){ + if (BsSalaryStandardEnum.STEP_TYPE_NON.getName().equals(name)) { + return BsSalaryStandardEnum.STEP_TYPE_NON.getCode(); + } + if (BsSalaryStandardEnum.STEP_TYPE_FIXED.getName().equals(name)) { + return BsSalaryStandardEnum.STEP_TYPE_FIXED.getCode(); + } + if (BsSalaryStandardEnum.STEP_TYPE_STEP.getName().equals(name)) { + return BsSalaryStandardEnum.STEP_TYPE_STEP.getCode(); + } + return null; + } + public static String convertStepUnit(String name){ + if (BsSalaryStandardEnum.STEP_UNIT_PIECE.getName().equals(name)) { + return BsSalaryStandardEnum.STEP_UNIT_PIECE.getCode(); + } + if (BsSalaryStandardEnum.STEP_UNIT_AREA.getName().equals(name)) { + return BsSalaryStandardEnum.STEP_UNIT_AREA.getCode(); + } + return null; + } + public static String convertStepSettlementUnit(String name){ + if (BsSalaryStandardEnum.STEP_SETTLEMENT_UNIT_BATCH.getName().equals(name)) { + return BsSalaryStandardEnum.STEP_SETTLEMENT_UNIT_BATCH.getCode(); + } + if (BsSalaryStandardEnum.STEP_SETTLEMENT_UNIT_MULTIPLE.getName().equals(name)) { + return BsSalaryStandardEnum.STEP_SETTLEMENT_UNIT_MULTIPLE.getCode(); + } + return null; + } + + public static String convertSettlementUnit(String name){ + if (BsSalaryStandardEnum.SETTLEMENT_UNIT_PIECE.getName().equals(name)) { + return BsSalaryStandardEnum.SETTLEMENT_UNIT_PIECE.getCode(); + } + if (BsSalaryStandardEnum.SETTLEMENT_UNIT_BATCH.getName().equals(name)) { + return BsSalaryStandardEnum.SETTLEMENT_UNIT_BATCH.getCode(); + } + if (BsSalaryStandardEnum.SETTLEMENT_UNIT_AREA.getName().equals(name)) { + return BsSalaryStandardEnum.SETTLEMENT_UNIT_AREA.getCode(); + } + return null; + } +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/excel/BsSalaryStandardExcel.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/excel/BsSalaryStandardExcel.java new file mode 100644 index 00000000..acdd2ae8 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/excel/BsSalaryStandardExcel.java @@ -0,0 +1,89 @@ +package org.springblade.desk.efficiency.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentRowHeight; +import com.alibaba.excel.annotation.write.style.HeadRowHeight; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; + +@Data +@ColumnWidth(25) +@HeadRowHeight(20) +@ContentRowHeight(18) +public class BsSalaryStandardExcel implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 规则类型 + */ + @ExcelProperty("规则类型") + private String standardType; + + /** + * 工序编码 + */ + @ExcelProperty("工序编码") + private String processCode; + + /** + * 工序名称 + */ + @ExcelProperty("工序名称") + private String processName; + + /** + * 零件号 + */ + @ExcelProperty("零件号") + private String partNo; + + /** + * 工人结算价 + */ + @ExcelProperty("工人结算价") + private BigDecimal settlementPrice; + + /** + * 工人结算单位 + */ + @ExcelProperty("工人结算单位") + private String settlementUnit; + + /** + * 阶梯类型 + */ + @Schema(description = "阶梯类型") + private String stepType; + + /** + * 阶梯上下限 + */ + @Schema(description = "阶梯上下限") + private String step; + + /** + * 阶梯单位 + */ + @Schema(description = "阶梯单位") + private String stepUnit; + + /** + * 阶梯结算价 + */ + @Schema(description = "阶梯结算价") + private String stepSettlementPrice; + + /** + * 阶梯结算单位 + */ + @Schema(description = "阶梯结算单位") + private String stepSettlementUnit; + +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/BsSalaryStandardMapper.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/BsSalaryStandardMapper.java new file mode 100644 index 00000000..c35a0927 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/BsSalaryStandardMapper.java @@ -0,0 +1,29 @@ +package org.springblade.desk.efficiency.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import org.apache.ibatis.annotations.Param; +import org.springblade.desk.efficiency.pojo.entity.BsSalaryStandardEntity; +import org.springblade.desk.efficiency.pojo.vo.BsEfficiencyTaskVO; +import org.springblade.desk.efficiency.pojo.vo.BsSalaryStandardVO; + +import java.util.List; + +/** + * 薪资规则参数 Mapper 接口 + * + * @author BladeX + * @since 2026-04-23 + */ +public interface BsSalaryStandardMapper extends BaseMapper { + + /** + * 自定义分页 + * + * @param page 分页参数 + * @param bsSalaryStandard 查询参数 + * @return List + */ + List selectBsSalaryStandardPage(IPage page, BsSalaryStandardVO bsSalaryStandard); + +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/EfficiencyTaskMapper.xml b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/EfficiencyTaskMapper.xml index e177704f..996db1f5 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/EfficiencyTaskMapper.xml +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/EfficiencyTaskMapper.xml @@ -26,7 +26,7 @@ SELECT t.*, bu.real_name as reportUserName, bu1.real_name as createUserName, - case when t.status = '1' then '进行中' when t.status = '2' then '已完成' when t.status = '3' then '待审批' when t.status = '4' then '审批通过' when t.status = '5' then '审批不通过' when t.status = '6' then '已超期' else '' end as statusName, + case when t.status = '1' then '进行中' when t.status = '2' then '已完成' when t.status = '3' then '待审批' when t.status = '4' then '审批通过' when t.status = '5' then '审批不通过' when t.status = '6' then '已超期' when t.status = '7' then '任务失败' else '' end as statusName, ba.link as attachLink, ba.original_name as attackName FROM BS_EFFICIENCY_TASK t @@ -64,7 +64,7 @@ SELECT t.*, bu.real_name as reportUserName, bu1.real_name as createUserName, - case when t.status = '1' then '进行中' when t.status = '2' then '已完成' when t.status = '3' then '待审批' when t.status = '4' then '审批通过' when t.status = '5' then '审批不通过' when t.status = '6' then '已超期' else '' end as statusName, + case when t.status = '1' then '进行中' when t.status = '2' then '已完成' when t.status = '3' then '待审批' when t.status = '4' then '审批通过' when t.status = '5' then '审批不通过' when t.status = '6' then '已超期' when t.status = '7' then '任务失败' else '' end as statusName, ba.link as attachLink, ba.original_name as attackName FROM BS_EFFICIENCY_TASK t diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/EfficiencyTaskReportMapper.xml b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/EfficiencyTaskReportMapper.xml index c7de64ea..e06978b7 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/EfficiencyTaskReportMapper.xml +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/EfficiencyTaskReportMapper.xml @@ -42,10 +42,10 @@ tr.is_deleted = 0 and t.is_deleted = 0 and t.status = 4 - and tr.EMPLOYEE_CODE like concat(concat('%',#{bsEfficiencyTaskReport.employeeCode},'%') + and tr.EMPLOYEE_CODE like concat(concat('%', #{bsEfficiencyTaskReport.employeeCode}),'%') - and tr.EMPLOYEE_NAME like concat(concat('%',#{bsEfficiencyTaskReport.employeeName},'%') + and tr.EMPLOYEE_NAME like concat(concat('%', #{bsEfficiencyTaskReport.employeeName}),'%') GROUP BY @@ -66,10 +66,10 @@ and tr.TASK_ID = #{taskId} - and tr.EMPLOYEE_CODE like concat(concat('%',#{employeeCode},'%') + and tr.EMPLOYEE_CODE like concat(concat('%', #{employeeCode}),'%') - and tr.EMPLOYEE_NAME like concat(concat('%',#{employeeName},'%') + and tr.EMPLOYEE_NAME like concat(concat('%', #{employeeName}),'%') and tr.EMPLOYEE_CODE = #{employeeCodeExact} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/SalaryStandardMapper.xml b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/SalaryStandardMapper.xml new file mode 100644 index 00000000..7f4c8487 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/mapper/SalaryStandardMapper.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/dto/BsSalaryCalculationDTO.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/dto/BsSalaryCalculationDTO.java new file mode 100644 index 00000000..433a3096 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/dto/BsSalaryCalculationDTO.java @@ -0,0 +1,103 @@ +package org.springblade.desk.efficiency.pojo.dto; + +import lombok.Data; + +import java.io.Serial; + +@Data +public class BsSalaryCalculationDTO { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 订单号 + */ + private String woCode; + + /** + * 流程卡号 + */ + private String cardNo; + /** + * 开始时间 + */ + private String startDate; + + /** + * 结束时间 + */ + private String endDate; + + /** + * 产品型号 + */ + private String productType; + + /** + * 镀种 + */ + private String plate; + + /** + * 作业中心名称 + */ + private String wcName; + + /** + * 作业中心ID + */ + private String wcId; + + /** + * 作业中心ID + */ + private String wcIds; + + /** + * 工序ID + */ + private String ppsId; + + /** + * 工序ID + */ + private String ppsIds; + + /** + * 工序名称 + */ + private String ppsName; + + /** + * 生产标识 + */ + private String prodIdent; + + /** + * 生产标识 + */ + private String prodIdents; + + /** + * 最小单批数量 + */ + private String minSingleBatchNo; + + /** + * 最大单批数量 + */ + private String maxSingleBatchNo; + + /** + * 最小总面积 + */ + private String minTotalArea; + + /** + * 最大总面积 + */ + private String maxTotalArea; + + +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/entity/BsSalaryStandardEntity.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/entity/BsSalaryStandardEntity.java new file mode 100644 index 00000000..4cbf7dfb --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/entity/BsSalaryStandardEntity.java @@ -0,0 +1,84 @@ +package org.springblade.desk.efficiency.pojo.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springblade.core.mp.base.BaseEntity; + +import java.math.BigDecimal; + +/** + * 薪资标准 实体类 + * + * @author BladeX + * @since 2026-04-23 + */ +@Data +@TableName("BS_SALARY_STANDARD") +@Schema(description = "BsSalaryStandard对象") +@EqualsAndHashCode(callSuper = true) +public class BsSalaryStandardEntity extends BaseEntity { + + /** + * 规则类型 + */ + @Schema(description = "规则类型") + private String standardType; + + /** + * 工序ID + */ + @Schema(description = "工序ID") + private Long processId; + + /** + * 零件号 + */ + @Schema(description = "零件号") + private String partNo; + + /** + * 工人结算价 + */ + @Schema(description = "工人结算价") + private BigDecimal settlementPrice; + + /** + * 工人结算单位 + */ + @Schema(description = "工人结算单位") + private String settlementUnit; + + /** + * 阶梯类型 + */ + @Schema(description = "阶梯类型") + private String stepType; + + /** + * 阶梯 + */ + @Schema(description = "阶梯") + private String step; + + /** + * 阶梯单位 + */ + @Schema(description = "阶梯单位") + private String stepUnit; + + /** + * 阶梯结算价 + */ + @Schema(description = "阶梯结算价") + private String stepSettlementPrice; + + /** + * 阶梯结算单位 + */ + @Schema(description = "阶梯结算单位") + private String stepSettlementUnit; + + +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/vo/BsSalaryCalculationVO.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/vo/BsSalaryCalculationVO.java new file mode 100644 index 00000000..5a31d07c --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/vo/BsSalaryCalculationVO.java @@ -0,0 +1,163 @@ +package org.springblade.desk.efficiency.pojo.vo; + +import lombok.Data; + +import java.io.Serial; + +@Data +public class BsSalaryCalculationVO { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 订单号 + */ + private String woCode; + + /** + * 零件号 + */ + private String partCode; + + /** + * 零件名称 + */ + private String partName; + + /** + * 批次号 + */ + private String batchNo; + + /** + * 使用部门 + */ + private String useDept; + + /** + * 镀种 + */ + private String plate; + + /** + * 作业中心 + */ + private String wcName; + + /** + * 班组 + */ + private String team; + + /** + * 工序 + */ + private String ppsName; + + /** + * 定额工时 + */ + private String hourQuota; + + /** + * 准备工时 + */ + private String hourPrepar; + + /** + * 工时额定单位 + */ + private String hqUnit; + + /** + * 报工数 + */ + private String workQty; + + /** + * 总工时 + */ + private String hourTotal; + + /** + * 责任人 + */ + private String worker; + + /** + * 厚度 + */ + private String plateThickness; + + /** + * 产品系列 + */ + private String productType; + + /** + * 生产标识 + */ + private String prodIdent; + + /** + * 单批数量 + */ + private String singleBatchNo; + + /** + * 入库数量 + */ + private String putQuantity; + + /** + * 报废数量 + */ + private String scrapQty; + + /** + * 消耗数量 + */ + private String lossQty; + + /** + * 试验数量 + */ + private String testQty; + + /** + * 单件面积(dm²) + */ + private String poArea; + + /** + * 总面积(d㎡) + */ + private String totalArea; + + /** + * 镀后入库时间 + */ + private String putStoreTime; + + /** + * 金额 + */ + private String wpMoney; + + /** + * 基础薪资金额 + */ + private String baseAmount; + + /** + * 补贴薪资金额 + */ + private String subsidyAmount; + + /** + * 总薪资金额 + */ + private String totalAmount; + +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/vo/BsSalaryStandardVO.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/vo/BsSalaryStandardVO.java new file mode 100644 index 00000000..061f0ce4 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/pojo/vo/BsSalaryStandardVO.java @@ -0,0 +1,38 @@ +package org.springblade.desk.efficiency.pojo.vo; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springblade.desk.efficiency.pojo.entity.BsSalaryStandardEntity; + +import java.io.Serial; +import java.math.BigDecimal; + +@Data +@EqualsAndHashCode(callSuper = true) +public class BsSalaryStandardVO extends BsSalaryStandardEntity { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 工序名称 + */ + private String processName; + + /** + * 阶梯下限 + */ + private BigDecimal minStep; + + /** + * 阶梯上限 + */ + private BigDecimal maxStep; + + /** + * 阶梯价格 + */ + private BigDecimal price; + + +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/service/IBsSalaryStandardService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/service/IBsSalaryStandardService.java new file mode 100644 index 00000000..211c6d31 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/service/IBsSalaryStandardService.java @@ -0,0 +1,34 @@ +package org.springblade.desk.efficiency.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import org.springblade.core.mp.base.BaseService; +import org.springblade.desk.efficiency.pojo.entity.BsSalaryStandardEntity; +import org.springblade.desk.efficiency.pojo.vo.BsSalaryStandardVO; + +/** + * 薪资规则 服务类 + * + * @author BladeX + * @since 2026-04-20 + */ +public interface IBsSalaryStandardService extends BaseService { + + /** + * 自定义分页 + * + * @param page 分页参数 + * @param bsSalaryStandard 查询参数 + * @return IPage + */ + IPage selectBsSalaryStandardPage(IPage page, BsSalaryStandardVO bsSalaryStandard); + + /** + * 查询匹配的薪资标准 + * + * @param processId 工序ID + * @param partNo 零件号 + * @param standardType 薪资标准类型 + * @return + */ + BsSalaryStandardEntity getStandard(Long processId, String partNo, String standardType); +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/service/impl/BsEfficiencyTempServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/service/impl/BsEfficiencyTempServiceImpl.java index a20a3d00..f3a5b53c 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/service/impl/BsEfficiencyTempServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/service/impl/BsEfficiencyTempServiceImpl.java @@ -61,6 +61,12 @@ public class BsEfficiencyTempServiceImpl extends BaseServiceImpl implements IBsSalaryStandardService { + + @Override + public IPage selectBsSalaryStandardPage(IPage page, BsSalaryStandardVO bsSalaryStandard) { + return page.setRecords(baseMapper.selectBsSalaryStandardPage(page, bsSalaryStandard)); + } + + @Override + public BsSalaryStandardEntity getStandard(Long processId, String partNo, String standardType) { + List standardList = this.list(new LambdaQueryWrapper().eq(BsSalaryStandardEntity::getProcessId, processId).in(BsSalaryStandardEntity::getStandardType, Arrays.asList(standardType, "1"))); + BsSalaryStandardEntity bsSalaryStandardEntity = BsSalaryUtil.matchBestRule(standardList, partNo, Integer.getInteger(standardType)); + return bsSalaryStandardEntity; + } + +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/util/BsSalaryUtil.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/util/BsSalaryUtil.java new file mode 100644 index 00000000..c8baf826 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/efficiency/util/BsSalaryUtil.java @@ -0,0 +1,163 @@ +package org.springblade.desk.efficiency.util; + +import org.springblade.desk.efficiency.enums.BsSalaryStandardEnum; +import org.springblade.desk.efficiency.pojo.entity.BsSalaryStandardEntity; +import org.springframework.util.StringUtils; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class BsSalaryUtil { + + /** + * 最终入口方法:返回匹配到的唯一最高优先级规则 + * + * @param ruleList 从数据库查出的规则(按工序+类型) + * @param inputPartNo 前端输入的零件号(如 4005) + * @param standardType 2军品 3非军品 + * @return 唯一匹配规则 + */ + public static BsSalaryStandardEntity matchBestRule(List ruleList, String inputPartNo, Integer standardType) { + if (ruleList == null || ruleList.isEmpty()) return null; + + return ruleList.stream() + .filter(rule -> isMatch(rule.getPartNo(), inputPartNo)) + .sorted(comparator(standardType)) // 按优先级排序 + .findFirst() + .orElse(null); + } + + /** + * 【核心】零件号匹配方法 + * + * @param rulePartNo 规则:100 200 300 400% + * @param inputPartNo 输入:4005 + */ + private static boolean isMatch(String rulePartNo, String inputPartNo) { + // 规则为空 → 直接匹配(兜底) + if (!StringUtils.hasText(rulePartNo)) { + return true; + } + // 按空格拆分规则段 + String[] parts = rulePartNo.split("\\s+"); + for (String part : parts) { + if (matchSinglePart(part, inputPartNo)) { + return true; // 任意一段匹配就成功 + } + } + return false; + } + + /** + * 单段匹配:支持 % 通配符 + * 400% → ^400.*$ + */ + private static boolean matchSinglePart(String rulePart, String input) { + if (!StringUtils.hasText(rulePart) || !StringUtils.hasText(input)) { + return false; + } + // 把 % 转成正则 .* (只允许后缀%) + String regex = rulePart.replace("%", ".*"); + return Pattern.matches(regex, input); + } + + /** + * 优先级排序器 + */ + private static Comparator comparator(Integer salaryType) { + return (r1, r2) -> { + int p1 = getPriority(r1, salaryType); + int p2 = getPriority(r2, salaryType); + return Integer.compare(p1, p2); // 小的在前 + }; + } + + /** + * 计算优先级:数字越小越优先 + */ + private static int getPriority(BsSalaryStandardEntity rule, Integer standardType) { + boolean isEmpty = !StringUtils.hasText(rule.getPartNo()); + boolean isMatch = isMatch(rule.getPartNo(), "dummy"); // 外层已过滤 + if (standardType == 2) { // 军品 + if (Integer.parseInt(rule.getStandardType()) == 2 && isMatch) return 1; + if (Integer.parseInt(rule.getStandardType()) == 2 && isEmpty) return 2; + if (Integer.parseInt(rule.getStandardType()) == 1 && isMatch) return 3; + if (Integer.parseInt(rule.getStandardType()) == 1 && isEmpty) return 4; + } else { // 非军品 + if (Integer.parseInt(rule.getStandardType()) == 3 && isMatch) return 1; + if (Integer.parseInt(rule.getStandardType()) == 3 && isEmpty) return 2; + if (Integer.parseInt(rule.getStandardType()) == 1 && isMatch) return 3; + if (Integer.parseInt(rule.getStandardType()) == 1 && isEmpty) return 4; + } + return 99; + } + + + /** + * 计算阶梯价格 + * + * @param stepStr + * @param stepPriceStr + * @param count + * @return + */ + public static BigDecimal calcStepAmount(String stepStr, String stepPriceStr, BigDecimal count, String stepSettlementUnit, BigDecimal settlementPrice) { + // 空值校验 + if (!StringUtils.hasText(stepStr) || !StringUtils.hasText(stepPriceStr) || count == null || count.compareTo(BigDecimal.ZERO) <= 0) { + return BigDecimal.ZERO; + } + + // 解析阶梯区间 + List stepList = Arrays.stream(stepStr.split(" ")) + .filter(StringUtils::hasText) + .map(BigDecimal::new) + .collect(Collectors.toList()); + // 解析阶梯价格 + List priceList = Arrays.stream(stepPriceStr.split(" ")) + .filter(StringUtils::hasText) + .map(BigDecimal::new) + .collect(Collectors.toList()); + + // 格式非法:价格必须比阶梯多1位 + if (priceList.size() != stepList.size() + 1) { + return BigDecimal.ZERO; + } + BigDecimal totalAmount = BigDecimal.ZERO; + BigDecimal remain = count; + BigDecimal preStep = BigDecimal.ZERO; + // 遍历每一档阶梯 + BigDecimal one = new BigDecimal(1); + for (int i = 0; i < stepList.size() && remain.compareTo(BigDecimal.ZERO) > 0; i++) { + BigDecimal currStep = stepList.get(i).subtract(one); + BigDecimal stepDiff = currStep.subtract(preStep); + // 当前区间实际耗用数量 + BigDecimal useNum = remain.min(stepDiff); + // 累加金额 + if (BsSalaryStandardEnum.STEP_SETTLEMENT_UNIT_BATCH.getCode().equals(stepSettlementUnit)) { + totalAmount = totalAmount.add(priceList.get(i)); + } + if (BsSalaryStandardEnum.STEP_SETTLEMENT_UNIT_MULTIPLE.getCode().equals(stepSettlementUnit)) { + totalAmount = totalAmount.add(useNum.multiply(priceList.get(i)).multiply(settlementPrice)); + } + // 剩余数量 + remain = remain.subtract(useNum); + // 记录上一档阶梯 + preStep = currStep; + } + // 超出所有阶梯的部分,取最后一档价格 + if (remain.compareTo(BigDecimal.ZERO) > 0) { + BigDecimal lastPrice = priceList.get(priceList.size() - 1); + if (BsSalaryStandardEnum.STEP_SETTLEMENT_UNIT_BATCH.getCode().equals(stepSettlementUnit)) { + totalAmount = totalAmount.add(lastPrice); + } + if (BsSalaryStandardEnum.STEP_SETTLEMENT_UNIT_MULTIPLE.getCode().equals(stepSettlementUnit)) { + totalAmount = totalAmount.add(remain.multiply(lastPrice).multiply(settlementPrice)); + } + } + return totalAmount; + } +} \ No newline at end of file diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/mapper/WorkPlanMapper.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/mapper/WorkPlanMapper.java index ad0586ed..fdc84f3e 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/mapper/WorkPlanMapper.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/mapper/WorkPlanMapper.java @@ -5,6 +5,8 @@ import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import org.springblade.desk.dashboard.pojo.entity.DsPartRelationEntity; import org.springblade.desk.dashboard.pojo.entity.DsPartSub; +import org.springblade.desk.efficiency.pojo.dto.BsSalaryCalculationDTO; +import org.springblade.desk.efficiency.pojo.vo.BsSalaryCalculationVO; import org.springblade.desk.produce.pojo.dto.MesRbFilePreserveDetailDTO; import org.springblade.desk.produce.pojo.entity.*; import org.springblade.desk.produce.pojo.vo.*; @@ -89,4 +91,6 @@ public interface WorkPlanMapper extends BaseMapper { List getByRfpsIdMesNew(Long id); List getWorkOrderProcess(String cardNo); + + List selectBsSalaryCalculationPage(IPage page, BsSalaryCalculationDTO bsSalaryCalculation); } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/mapper/WorkPlanMapper.xml b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/mapper/WorkPlanMapper.xml index fa8c69a6..6d2101c6 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/mapper/WorkPlanMapper.xml +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/mapper/WorkPlanMapper.xml @@ -437,4 +437,123 @@ ORDER BY wp.ORDERS ASC + + diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/IWorkOrderService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/IWorkOrderService.java index e42f562e..023c77a8 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/IWorkOrderService.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/IWorkOrderService.java @@ -270,6 +270,12 @@ public interface IWorkOrderService extends BaseService { */ Map queryAllocationMess(AllocationMessPageDTO dto); + /** + * 薪资计算 + * @param woId + */ + void salaryCalculation(Long woId); + /** * 查询配套统计信息 * @param dto 查询条件 diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/IWorkPlanService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/IWorkPlanService.java index 66a8ee8f..045b4957 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/IWorkPlanService.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/IWorkPlanService.java @@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import org.springblade.common.exception.BusinessException; import org.springblade.core.mp.base.BaseService; import org.springblade.core.secure.BladeUser; +import org.springblade.desk.efficiency.pojo.dto.BsSalaryCalculationDTO; +import org.springblade.desk.efficiency.pojo.vo.BsSalaryCalculationVO; import org.springblade.desk.produce.pojo.entity.WorkOrder; import org.springblade.desk.produce.pojo.entity.WorkPlan; import org.springblade.desk.produce.pojo.vo.ProduceMonitorWorkPlanVO; @@ -57,4 +59,6 @@ public interface IWorkPlanService extends BaseService { void workPlanEnd(Long wpId, Date putStoreTime, Double makeQty); List getWorkOrderProcess(String cardNo); + + IPage selectBsSalaryCalculationPage(IPage page, BsSalaryCalculationDTO bsSalaryCalculation); } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderServiceImpl.java index ba0be64b..212dc136 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkOrderServiceImpl.java @@ -40,6 +40,10 @@ import org.springblade.desk.device.pojo.entity.RackSetEntity; import org.springblade.desk.device.service.IEquipmentService; import org.springblade.desk.device.service.IFeiBaSetService; import org.springblade.desk.device.service.IRackSetService; +import org.springblade.desk.efficiency.enums.BsSalaryStandardEnum; +import org.springblade.desk.efficiency.pojo.entity.BsSalaryStandardEntity; +import org.springblade.desk.efficiency.service.IBsSalaryStandardService; +import org.springblade.desk.efficiency.util.BsSalaryUtil; import org.springblade.desk.energy.util.HttpRequestService; import org.springblade.desk.logistics.pojo.dto.AllocationMessPageDTO; import org.springblade.desk.logistics.pojo.vo.AllocationMessVO; @@ -61,7 +65,9 @@ import org.springblade.desk.quality.service.*; import org.springblade.desk.util.date.DateUtils; import org.springblade.erpdata.feign.IErpDataLogisticsClient; import org.springblade.erpdata.feign.IErpDataProduceClient; +import org.springblade.scheduling.pojo.entity.QualityGradeEntity; import org.springblade.scheduling.pojo.entity.WorkOrderEntity; +import org.springblade.scheduling.pojo.entity.WorkPlanEntity; import org.springblade.system.cache.DictCache; import org.springblade.system.cache.UserCache; import org.springblade.system.feign.IDictClient; @@ -184,6 +190,10 @@ public class WorkOrderServiceImpl extends BaseServiceImpl selectWorkOrderPage(IPage page, WorkOrderDTO workOrder) { return page.setRecords(baseMapper.selectWorkOrderPage(page, workOrder)); @@ -2793,4 +2803,106 @@ public class WorkOrderServiceImpl extends BaseServiceImpl qualityGrades = qualityGradeService.list(new LambdaQueryWrapper().eq(QualityGradeEntity::getQualityGrade, yieldOrder.getProductIdent())); + if (!CollectionUtils.isEmpty(qualityGrades)) { + if (!StringUtils.isEmpty(qualityGrades.get(0).getType())) { + boolean hasOne = Arrays.asList(qualityGrades.get(0).getType().split(",")).contains("1"); + if (hasOne) { + // 军品 + standardType = "2"; + } + } + } + List updList = new ArrayList<>(); + List workPlanList = workPlanService.selectByWoId(woId); + for (WorkPlanEntity workPlanEntity : workPlanList) { + if (!"0".equals(StringUtils.trim(workPlanEntity.getOem())) || workPlanEntity.getWorkQty() <= 0) { + continue; + } + BsSalaryStandardEntity standard = bsSalaryStandardService.getStandard(workPlanEntity.getPpsId(), yieldOrder.getPartCode(), standardType); + if (standard == null) { + continue; + } + // 基础薪资金额 + BigDecimal baseAmount = new BigDecimal(0); + // 补贴薪资金额 + BigDecimal subsidyAmount = new BigDecimal(0); + // 面积 + BigDecimal ypArea = new BigDecimal(yieldOrder.getYpArea()); + // 数量 + BigDecimal workQty = new BigDecimal(workPlanEntity.getWorkQty()); + // 计算基础薪资金额 + if (BsSalaryStandardEnum.SETTLEMENT_UNIT_PIECE.getCode().equals(standard.getSettlementUnit())) { + // 件 = 工人结算价 * 数量 + baseAmount = standard.getSettlementPrice().multiply(workQty); + } + if (BsSalaryStandardEnum.SETTLEMENT_UNIT_BATCH.getCode().equals(standard.getSettlementUnit())) { + // 批 = 工人结算价 + baseAmount = standard.getSettlementPrice(); + } + if (BsSalaryStandardEnum.SETTLEMENT_UNIT_AREA.getCode().equals(standard.getSettlementUnit())) { + // 面积 = 工人结算价 * 数量 * 面积 + baseAmount = standard.getSettlementPrice().multiply(ypArea).multiply(workQty); + } + // 计算补贴薪资金额 + if (BsSalaryStandardEnum.STEP_TYPE_NON.getCode().equals(standard.getStepType())) { + // 无补贴 = 0 + subsidyAmount = new BigDecimal(0); + } + if (BsSalaryStandardEnum.STEP_TYPE_FIXED.getCode().equals(standard.getStepType())) { + BigDecimal stepSettlementPrice = new BigDecimal(standard.getStepSettlementPrice()); + BigDecimal stepBasePrice = new BigDecimal(0); + // 固定补贴按批 = 阶梯结算价 + if (BsSalaryStandardEnum.STEP_SETTLEMENT_UNIT_BATCH.getCode().equals(standard.getStepSettlementUnit())) { + subsidyAmount = stepSettlementPrice; + } + if (BsSalaryStandardEnum.STEP_SETTLEMENT_UNIT_MULTIPLE.getCode().equals(standard.getStepSettlementUnit())) { + // 固定补贴按件 = 阶梯结算价 * 数量 + if (BsSalaryStandardEnum.STEP_UNIT_PIECE.getCode().equals(standard.getStepUnit())) { + stepBasePrice = stepSettlementPrice.multiply(workQty); + } + // 固定补贴按面积 = 阶梯结算价 * 数量 * 面积 + if (BsSalaryStandardEnum.STEP_UNIT_AREA.getCode().equals(standard.getStepUnit())) { + stepBasePrice = stepSettlementPrice.multiply(ypArea).multiply(workQty); + } + // 固定补贴按倍 = 固定补贴金额 * 工人结算价格 + subsidyAmount = stepBasePrice.multiply(standard.getSettlementPrice()); + } + } + if (BsSalaryStandardEnum.STEP_TYPE_STEP.getCode().equals(standard.getStepType())) { + if (BsSalaryStandardEnum.STEP_UNIT_PIECE.getCode().equals(standard.getStepUnit())) { + subsidyAmount = BsSalaryUtil.calcStepAmount(standard.getStep(), standard.getStepSettlementPrice(), workQty, standard.getStepSettlementUnit(), standard.getSettlementPrice()); + } + if (BsSalaryStandardEnum.STEP_UNIT_AREA.getCode().equals(standard.getStepUnit())) { + subsidyAmount = BsSalaryUtil.calcStepAmount(standard.getStep(), standard.getStepSettlementPrice(), workQty.multiply(ypArea), standard.getStepSettlementUnit(), standard.getSettlementPrice()); + } + } + WorkPlan upd = new WorkPlan(); + upd.setId(workPlanEntity.getId()); + upd.setBaseAmount(baseAmount); + upd.setSubsidyAmount(subsidyAmount); + updList.add(upd); + } + if (!CollectionUtils.isEmpty(updList)) { + workPlanService.saveOrUpdateBatch(updList); + } + } catch (Exception e) { + log.error("订单:" + woId + ",薪资计算错误", e); + } + + } } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkPlanServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkPlanServiceImpl.java index 0c48360f..f2307cdd 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkPlanServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/produce/service/impl/WorkPlanServiceImpl.java @@ -21,6 +21,10 @@ import org.springblade.desk.dashboard.pojo.entity.BsTeamSetEntity; import org.springblade.desk.dashboard.pojo.entity.DsProcessMeasuringToolEntity; import org.springblade.desk.dashboard.pojo.entity.DsProcessProjectEntity; import org.springblade.desk.dashboard.service.*; +import org.springblade.desk.efficiency.pojo.dto.BsSalaryCalculationDTO; +import org.springblade.desk.efficiency.pojo.vo.BsSalaryCalculationVO; +import org.springblade.desk.order.pojo.entity.YieldOrder; +import org.springblade.desk.order.service.IYieldOrderService; import org.springblade.desk.produce.mapper.PlateAroundMapper; import org.springblade.desk.produce.mapper.WorkPlanMapper; import org.springblade.desk.produce.pojo.entity.*; @@ -318,4 +322,9 @@ public class WorkPlanServiceImpl extends BaseServiceImpl getWorkOrderProcess(String cardNo) { return baseMapper.getWorkOrderProcess(cardNo); } + + @Override + public IPage selectBsSalaryCalculationPage(IPage page, BsSalaryCalculationDTO bsSalaryCalculation) { + return page.setRecords(baseMapper.selectBsSalaryCalculationPage(page, bsSalaryCalculation)); + } } diff --git a/blade-service/blade-desk/src/main/resources/Excel/efficiency/工资维护标准.xls b/blade-service/blade-desk/src/main/resources/Excel/efficiency/工资维护标准.xls new file mode 100644 index 0000000000000000000000000000000000000000..2097718e4793d6979ea37ef38691e8094d424b10 GIT binary patch literal 20992 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 literal 0 HcmV?d00001