Przeglądaj źródła

pms功能优化 bug修复

zhangcl 3 miesięcy temu
rodzic
commit
2f9ec26824
19 zmienionych plików z 673 dodań i 11 usunięć
  1. 2 0
      yudao-module-pms/yudao-module-pms-api/src/main/java/cn/iocoder/yudao/module/pms/enums/ErrorCodeConstant.java
  2. 1 3
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/IotTreeController.java
  3. 95 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdevicepersonlog/IotDevicePersonLogController.java
  4. 43 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdevicepersonlog/vo/IotDevicePersonLogPageReqVO.java
  5. 51 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdevicepersonlog/vo/IotDevicePersonLogRespVO.java
  6. 36 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdevicepersonlog/vo/IotDevicePersonLogSaveReqVO.java
  7. 11 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotlockstock/vo/IotLockStockPageReqVO.java
  8. 7 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/vo/IotMainWorkOrderBomMaterialPageReqVO.java
  9. 7 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/vo/IotMainWorkOrderBomMaterialSaveReqVO.java
  10. 59 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotdevicepersonlog/IotDevicePersonLogDO.java
  11. 14 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialDO.java
  12. 19 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotdevicecategorytemplateattrs/IotDeviceCategoryTemplateAttrsMapper.java
  13. 33 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotdevicepersonlog/IotDevicePersonLogMapper.java
  14. 33 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotlockstock/IotLockStockMapper.java
  15. 2 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotsapstock/IotSapStockMapper.java
  16. 25 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotdevicecategorytemplateattrs/IotDeviceCategoryTemplateAttrsServiceImpl.java
  17. 55 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotdevicepersonlog/IotDevicePersonLogService.java
  18. 71 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotdevicepersonlog/IotDevicePersonLogServiceImpl.java
  19. 109 7
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorder/IotMainWorkOrderServiceImpl.java

+ 2 - 0
yudao-module-pms/yudao-module-pms-api/src/main/java/cn/iocoder/yudao/module/pms/enums/ErrorCodeConstant.java

@@ -13,6 +13,7 @@ public interface ErrorCodeConstant{
     ErrorCode IOT_MATERIAL_GROUP_NOT_EXISTS = new ErrorCode(103, "物料组不存在");
     ErrorCode IOT_MATERIAL_NOT_EXISTS = new ErrorCode(104, "物料不存在");
     ErrorCode IOT_DEVICE_TEMPLATE_ATTRS_NOT_EXISTS = new ErrorCode(105, "设备模板属性不存在");
+    ErrorCode IOT_DEVICE_TEMPLATE_ATTRS_EXISTS = new ErrorCode(152, "设备模板属性已经存在");
     ErrorCode IOT_DEVICE_TEMPLATE_NOT_EXISTS = new ErrorCode(106, "设备模板不存在");
     ErrorCode IOT_BOM_NOT_EXISTS = new ErrorCode(107, "BOM 关系不存在");
     ErrorCode IOT_DEVICE_MATERIAL_NOT_EXISTS = new ErrorCode(108, "设备BOM物料关联不存在");
@@ -61,4 +62,5 @@ public interface ErrorCodeConstant{
     ErrorCode IOT_DEVICE_PERSON_NOT_EXISTS = new ErrorCode(148, "设备负责人分配不存在");
     ErrorCode IOT_DEVICE_STATUS_LOG_NOT_EXISTS = new ErrorCode(149, "设备状态调整日志不存在");
     ErrorCode IOT_DEVICE_ALLOT_LOG_NOT_EXISTS = new ErrorCode(150, "设备调拨日志不存在");
+    ErrorCode IOT_DEVICE_PERSON_LOG_NOT_EXISTS = new ErrorCode(151, "设备责任人日志不存在");
 }

+ 1 - 3
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/IotTreeController.java

@@ -1,8 +1,6 @@
 package cn.iocoder.yudao.module.pms.controller.admin;
 
-import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -12,9 +10,9 @@ import cn.iocoder.yudao.module.pms.controller.admin.vo.IotTreeListReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotTreePageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotTreeRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotTreeSaveReqVO;
-import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSimpleRespVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotTreeDO;
 import cn.iocoder.yudao.module.pms.service.IotTreeService;
+import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSimpleRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;

+ 95 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdevicepersonlog/IotDevicePersonLogController.java

@@ -0,0 +1,95 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotdevicepersonlog;
+
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.validation.constraints.*;
+import javax.validation.*;
+import javax.servlet.http.*;
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.yudao.module.pms.controller.admin.iotdevicepersonlog.vo.*;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicepersonlog.IotDevicePersonLogDO;
+import cn.iocoder.yudao.module.pms.service.iotdevicepersonlog.IotDevicePersonLogService;
+
+@Tag(name = "管理后台 - 设备责任人日志")
+@RestController
+@RequestMapping("/pms/iot-device-person-log")
+@Validated
+public class IotDevicePersonLogController {
+
+    @Resource
+    private IotDevicePersonLogService iotDevicePersonLogService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建设备责任人日志")
+    @PreAuthorize("@ss.hasPermission('pms:iot-device-person-log:create')")
+    public CommonResult<Long> createIotDevicePersonLog(@Valid @RequestBody IotDevicePersonLogSaveReqVO createReqVO) {
+        return success(iotDevicePersonLogService.createIotDevicePersonLog(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新设备责任人日志")
+    @PreAuthorize("@ss.hasPermission('pms:iot-device-person-log:update')")
+    public CommonResult<Boolean> updateIotDevicePersonLog(@Valid @RequestBody IotDevicePersonLogSaveReqVO updateReqVO) {
+        iotDevicePersonLogService.updateIotDevicePersonLog(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除设备责任人日志")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('pms:iot-device-person-log:delete')")
+    public CommonResult<Boolean> deleteIotDevicePersonLog(@RequestParam("id") Long id) {
+        iotDevicePersonLogService.deleteIotDevicePersonLog(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得设备责任人日志")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('pms:iot-device-person-log:query')")
+    public CommonResult<IotDevicePersonLogRespVO> getIotDevicePersonLog(@RequestParam("id") Long id) {
+        IotDevicePersonLogDO iotDevicePersonLog = iotDevicePersonLogService.getIotDevicePersonLog(id);
+        return success(BeanUtils.toBean(iotDevicePersonLog, IotDevicePersonLogRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得设备责任人日志分页")
+    @PreAuthorize("@ss.hasPermission('pms:iot-device-person-log:query')")
+    public CommonResult<PageResult<IotDevicePersonLogRespVO>> getIotDevicePersonLogPage(@Valid IotDevicePersonLogPageReqVO pageReqVO) {
+        PageResult<IotDevicePersonLogDO> pageResult = iotDevicePersonLogService.getIotDevicePersonLogPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, IotDevicePersonLogRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出设备责任人日志 Excel")
+    @PreAuthorize("@ss.hasPermission('pms:iot-device-person-log:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportIotDevicePersonLogExcel(@Valid IotDevicePersonLogPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<IotDevicePersonLogDO> list = iotDevicePersonLogService.getIotDevicePersonLogPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "设备责任人日志.xls", "数据", IotDevicePersonLogRespVO.class,
+                        BeanUtils.toBean(list, IotDevicePersonLogRespVO.class));
+    }
+
+}

+ 43 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdevicepersonlog/vo/IotDevicePersonLogPageReqVO.java

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotdevicepersonlog.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 设备责任人日志分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class IotDevicePersonLogPageReqVO extends PageParam {
+
+    @Schema(description = "设备id", example = "14117")
+    private Long deviceId;
+
+    @Schema(description = "设备调整前责任人", example = "12055")
+    private Long oldPersonId;
+
+    @Schema(description = "设备调整前责任人id集合")
+    private String oldPersonIds;
+
+    @Schema(description = "设备调整后责任人", example = "29347")
+    private Long newPersonId;
+
+    @Schema(description = "设备调整后责任人id集合")
+    private String newPersonIds;
+
+    @Schema(description = "调整原因", example = "不好")
+    private String reason;
+
+    @Schema(description = "备注", example = "你猜")
+    private String remark;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 51 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdevicepersonlog/vo/IotDevicePersonLogRespVO.java

@@ -0,0 +1,51 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotdevicepersonlog.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 设备责任人日志 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotDevicePersonLogRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "14500")
+    @ExcelProperty("主键id")
+    private Long id;
+
+    @Schema(description = "设备id", example = "14117")
+    @ExcelProperty("设备id")
+    private Long deviceId;
+
+    @Schema(description = "设备调整前责任人", example = "12055")
+    @ExcelProperty("设备调整前责任人")
+    private Long oldPersonId;
+
+    @Schema(description = "设备调整前责任人id集合")
+    @ExcelProperty("设备调整前责任人id集合")
+    private String oldPersonIds;
+
+    @Schema(description = "设备调整后责任人", example = "29347")
+    @ExcelProperty("设备调整后责任人")
+    private Long newPersonId;
+
+    @Schema(description = "设备调整后责任人id集合")
+    @ExcelProperty("设备调整后责任人id集合")
+    private String newPersonIds;
+
+    @Schema(description = "调整原因", example = "不好")
+    @ExcelProperty("调整原因")
+    private String reason;
+
+    @Schema(description = "备注", example = "你猜")
+    @ExcelProperty("备注")
+    private String remark;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 36 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdevicepersonlog/vo/IotDevicePersonLogSaveReqVO.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotdevicepersonlog.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import javax.validation.constraints.*;
+
+@Schema(description = "管理后台 - 设备责任人日志新增/修改 Request VO")
+@Data
+public class IotDevicePersonLogSaveReqVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "14500")
+    private Long id;
+
+    @Schema(description = "设备id", example = "14117")
+    private Long deviceId;
+
+    @Schema(description = "设备调整前责任人", example = "12055")
+    private Long oldPersonId;
+
+    @Schema(description = "设备调整前责任人id集合")
+    private String oldPersonIds;
+
+    @Schema(description = "设备调整后责任人", example = "29347")
+    private Long newPersonId;
+
+    @Schema(description = "设备调整后责任人id集合")
+    private String newPersonIds;
+
+    @Schema(description = "调整原因", example = "不好")
+    private String reason;
+
+    @Schema(description = "备注", example = "你猜")
+    private String remark;
+
+}

+ 11 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotlockstock/vo/IotLockStockPageReqVO.java

@@ -9,6 +9,8 @@ import org.springframework.format.annotation.DateTimeFormat;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Set;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
@@ -93,4 +95,13 @@ public class IotLockStockPageReqVO extends PageParam {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
 
+    /**
+     * 扩展字段
+     */
+    @Schema(description = "工厂id集合", example = "11671")
+    private Set<Long> factoryIds;
+    @Schema(description = "成本中心id集合", example = "11671")
+    private Set<Long> costCenterIds;
+    @Schema(description = "物料编码集合", example = "11671")
+    private Set<String> materialCodes;
 }

+ 7 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/vo/IotMainWorkOrderBomMaterialPageReqVO.java

@@ -81,6 +81,13 @@ public class IotMainWorkOrderBomMaterialPageReqVO extends PageParam {
     @Schema(description = "物料来源 (SAP库存 本地库存...)")
     private String materialSource;
 
+    @Schema(description = "工厂id")
+    private Long factoryId;
+    @Schema(description = "成本中心id")
+    private Long costCenterId;
+    @Schema(description = "库存地点id")
+    private Long storageLocationId;
+
     @Schema(description = "库存地点")
     private String inventoryAddress;
 

+ 7 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/vo/IotMainWorkOrderBomMaterialSaveReqVO.java

@@ -75,6 +75,13 @@ public class IotMainWorkOrderBomMaterialSaveReqVO {
     @Schema(description = "物料来源 (SAP库存 本地库存...)")
     private String materialSource;
 
+    @Schema(description = "工厂id")
+    private Long factoryId;
+    @Schema(description = "成本中心id")
+    private Long costCenterId;
+    @Schema(description = "库存地点id")
+    private Long storageLocationId;
+
     @Schema(description = "库存地点")
     private String inventoryAddress;
 

+ 59 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotdevicepersonlog/IotDevicePersonLogDO.java

@@ -0,0 +1,59 @@
+package cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicepersonlog;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 设备责任人日志 DO
+ *
+ * @author ruiqi
+ */
+@TableName("rq_iot_device_person_log")
+@KeySequence("rq_iot_device_person_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IotDevicePersonLogDO extends BaseDO {
+
+    /**
+     * 主键id
+     */
+    @TableId
+    private Long id;
+    /**
+     * 设备id
+     */
+    private Long deviceId;
+    /**
+     * 设备调整前责任人
+     */
+    private Long oldPersonId;
+    /**
+     * 设备调整前责任人id集合
+     */
+    private String oldPersonIds;
+    /**
+     * 设备调整后责任人
+     */
+    private Long newPersonId;
+    /**
+     * 设备调整后责任人id集合
+     */
+    private String newPersonIds;
+    /**
+     * 调整原因
+     */
+    private String reason;
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 14 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialDO.java

@@ -112,6 +112,20 @@ public class IotMainWorkOrderBomMaterialDO extends BaseDO {
      * 物料来源 (SAP库存 本地库存...)
      */
     private String materialSource;
+
+    /**
+     * 工厂id
+     */
+    private Long factoryId;
+    /**
+     * 成本中心id
+     */
+    private Long costCenterId;
+    /**
+     * 库存地点id
+     */
+    private Long storageLocationId;
+
     /**
      * 库存地点
      */

+ 19 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotdevicecategorytemplateattrs/IotDeviceCategoryTemplateAttrsMapper.java

@@ -37,6 +37,25 @@ public interface IotDeviceCategoryTemplateAttrsMapper extends BaseMapperX<IotDev
                 .orderByDesc(IotDeviceCategoryTemplateAttrsDO::getId));
     }
 
+    default List<IotDeviceCategoryTemplateAttrsDO> selectList(IotDeviceCategoryTemplateAttrsPageReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<IotDeviceCategoryTemplateAttrsDO>()
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getDeviceCategoryId, reqVO.getDeviceCategoryId())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getTemplateId, reqVO.getTemplateId())
+                .likeIfPresent(IotDeviceCategoryTemplateAttrsDO::getName, reqVO.getName())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getCode, reqVO.getCode())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getType, reqVO.getType())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getRequiredFlag, reqVO.getRequiredFlag())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getDefaultValue, reqVO.getDefaultValue())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getUnit, reqVO.getUnit())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getDescription, reqVO.getDescription())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getRemark, reqVO.getRemark())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getSort, reqVO.getSort())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getSelectOptions, reqVO.getSelectOptions())
+                .eqIfPresent(IotDeviceCategoryTemplateAttrsDO::getVersion, reqVO.getVersion())
+                .betweenIfPresent(IotDeviceCategoryTemplateAttrsDO::getCreateTime, reqVO.getCreateTime()));
+    }
+
     default List<IotDeviceCategoryTemplateAttrsDO> selectList(Long deviceCategoryId) {
         return selectList(IotDeviceCategoryTemplateAttrsDO::getDeviceCategoryId, deviceCategoryId);
     }

+ 33 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotdevicepersonlog/IotDevicePersonLogMapper.java

@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.pms.dal.mysql.iotdevicepersonlog;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicepersonlog.IotDevicePersonLogDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdevicepersonlog.vo.*;
+
+/**
+ * 设备责任人日志 Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface IotDevicePersonLogMapper extends BaseMapperX<IotDevicePersonLogDO> {
+
+    default PageResult<IotDevicePersonLogDO> selectPage(IotDevicePersonLogPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<IotDevicePersonLogDO>()
+                .eqIfPresent(IotDevicePersonLogDO::getDeviceId, reqVO.getDeviceId())
+                .eqIfPresent(IotDevicePersonLogDO::getOldPersonId, reqVO.getOldPersonId())
+                .eqIfPresent(IotDevicePersonLogDO::getOldPersonIds, reqVO.getOldPersonIds())
+                .eqIfPresent(IotDevicePersonLogDO::getNewPersonId, reqVO.getNewPersonId())
+                .eqIfPresent(IotDevicePersonLogDO::getNewPersonIds, reqVO.getNewPersonIds())
+                .eqIfPresent(IotDevicePersonLogDO::getReason, reqVO.getReason())
+                .eqIfPresent(IotDevicePersonLogDO::getRemark, reqVO.getRemark())
+                .betweenIfPresent(IotDevicePersonLogDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(IotDevicePersonLogDO::getId));
+    }
+
+}

+ 33 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotlockstock/IotLockStockMapper.java

@@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.pms.controller.admin.iotlockstock.vo.IotLockStock
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotlockstock.IotLockStockDO;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+
 /**
  * PMS 本地 库存 Mapper
  *
@@ -45,4 +47,35 @@ public interface IotLockStockMapper extends BaseMapperX<IotLockStockDO> {
                 .orderByDesc(IotLockStockDO::getId));
     }
 
+    default List<IotLockStockDO> selectList(IotLockStockPageReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<IotLockStockDO>()
+                .eqIfPresent(IotLockStockDO::getDeptId, reqVO.getDeptId())
+                .eqIfPresent(IotLockStockDO::getFactoryId, reqVO.getFactoryId())
+                .eqIfPresent(IotLockStockDO::getFactory, reqVO.getFactory())
+                .eqIfPresent(IotLockStockDO::getStorageLocationId, reqVO.getStorageLocationId())
+                .eqIfPresent(IotLockStockDO::getProjectDepartment, reqVO.getProjectDepartment())
+                .eqIfPresent(IotLockStockDO::getCostCenterId, reqVO.getCostCenterId())
+                .eqIfPresent(IotLockStockDO::getCostCenter, reqVO.getCostCenter())
+                .eqIfPresent(IotLockStockDO::getPickingListNumber, reqVO.getPickingListNumber())
+                .likeIfPresent(IotLockStockDO::getMaterialCode, reqVO.getMaterialCode())
+                .likeIfPresent(IotLockStockDO::getMaterialName, reqVO.getMaterialName())
+                .likeIfPresent(IotLockStockDO::getMaterialGroupName, reqVO.getMaterialGroupName())
+                .eqIfPresent(IotLockStockDO::getMaterialGroupId, reqVO.getMaterialGroupId())
+                .eqIfPresent(IotLockStockDO::getQuantity, reqVO.getQuantity())
+                .eqIfPresent(IotLockStockDO::getUnitPrice, reqVO.getUnitPrice())
+                .eqIfPresent(IotLockStockDO::getUnit, reqVO.getUnit())
+                .betweenIfPresent(IotLockStockDO::getStorageTime, reqVO.getStorageTime())
+                .eqIfPresent(IotLockStockDO::getStorageAreaId, reqVO.getStorageAreaId())
+                .eqIfPresent(IotLockStockDO::getShelvesId, reqVO.getShelvesId())
+                .eqIfPresent(IotLockStockDO::getCargoLocationId, reqVO.getCargoLocationId())
+                .eqIfPresent(IotLockStockDO::getSort, reqVO.getSort())
+                .eqIfPresent(IotLockStockDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(IotLockStockDO::getProcessInstanceId, reqVO.getProcessInstanceId())
+                .eqIfPresent(IotLockStockDO::getAuditStatus, reqVO.getAuditStatus())
+                .eqIfPresent(IotLockStockDO::getRemark, reqVO.getRemark())
+                .inIfPresent(IotLockStockDO::getFactoryId, reqVO.getFactoryIds())
+                .inIfPresent(IotLockStockDO::getCostCenterId, reqVO.getCostCenterIds())
+                .betweenIfPresent(IotLockStockDO::getCreateTime, reqVO.getCreateTime()));
+    }
+
 }

+ 2 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotsapstock/IotSapStockMapper.java

@@ -47,6 +47,8 @@ public interface IotSapStockMapper extends BaseMapperX<IotSapStockDO> {
                 .orderByDesc(IotSapStockDO::getId);
         if ("Y".equals(reqVO.getConfigFlag())) {
             query.gt(IotSapStockDO::getSafetyStock, 0);
+        } else if ("N".equals(reqVO.getConfigFlag())) {
+            query.eq(IotSapStockDO::getSafetyStock, 0);
         }
         return selectJoinPage(reqVO, IotSapStockDO.class, query);
     }

+ 25 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotdevicecategorytemplateattrs/IotDeviceCategoryTemplateAttrsServiceImpl.java

@@ -1,11 +1,13 @@
 package cn.iocoder.yudao.module.pms.service.iotdevicecategorytemplateattrs;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.pms.controller.admin.iotdevicecategorytemplateattrs.vo.IotDeviceCategoryTemplateAttrsPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotdevicecategorytemplateattrs.vo.IotDeviceCategoryTemplateAttrsSaveReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicecategorytemplateattrs.IotDeviceCategoryTemplateAttrsDO;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotdevicecategorytemplateattrs.IotDeviceCategoryTemplateAttrsMapper;
+import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
@@ -15,6 +17,8 @@ import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_DEVICE_CATEGORY_TEMPLATE_ATTRS_NOT_EXISTS;
+import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_DEVICE_TEMPLATE_ATTRS_EXISTS;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.POST_NAME_DUPLICATE;
 
 /**
  * 设备分类公共模板属性 Service 实现类
@@ -39,13 +43,33 @@ public class IotDeviceCategoryTemplateAttrsServiceImpl implements IotDeviceCateg
 
     @Override
     public void updateIotDeviceCategoryTemplateAttrs(IotDeviceCategoryTemplateAttrsSaveReqVO updateReqVO) {
-        // 校验存在
+        // 校验属性是否存在
         validateIotDeviceCategoryTemplateAttrsExists(updateReqVO.getId());
+        // 查验是否存在相同标识符的属性
+        validateAttrCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
         // 更新
         IotDeviceCategoryTemplateAttrsDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceCategoryTemplateAttrsDO.class);
         iotDeviceCategoryTemplateAttrsMapper.updateById(updateObj);
     }
 
+    private void validateAttrCodeUnique(Long id, String code) {
+        IotDeviceCategoryTemplateAttrsPageReqVO reqVO = new IotDeviceCategoryTemplateAttrsPageReqVO();
+        reqVO.setCode(code);
+        List<IotDeviceCategoryTemplateAttrsDO> attrs = iotDeviceCategoryTemplateAttrsMapper.selectList(reqVO);
+        if (CollUtil.isEmpty(attrs)) {
+            return;
+        }
+        // 如果有相同的标识符,随机取一个
+        IotDeviceCategoryTemplateAttrsDO attr = attrs.get(0);
+        // 如果 id 为空,说明不用比较是否为相同 id 的岗位
+        if (id == null) {
+            throw exception(IOT_DEVICE_TEMPLATE_ATTRS_EXISTS);
+        }
+        if (!attr.getId().equals(id)) {
+            throw exception(IOT_DEVICE_TEMPLATE_ATTRS_EXISTS);
+        }
+    }
+
     @Override
     public void deleteIotDeviceCategoryTemplateAttrs(Long id) {
         // 校验存在

+ 55 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotdevicepersonlog/IotDevicePersonLogService.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.pms.service.iotdevicepersonlog;
+
+import java.util.*;
+import javax.validation.*;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdevicepersonlog.vo.*;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicepersonlog.IotDevicePersonLogDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+
+/**
+ * 设备责任人日志 Service 接口
+ *
+ * @author ruiqi
+ */
+public interface IotDevicePersonLogService {
+
+    /**
+     * 创建设备责任人日志
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createIotDevicePersonLog(@Valid IotDevicePersonLogSaveReqVO createReqVO);
+
+    /**
+     * 更新设备责任人日志
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateIotDevicePersonLog(@Valid IotDevicePersonLogSaveReqVO updateReqVO);
+
+    /**
+     * 删除设备责任人日志
+     *
+     * @param id 编号
+     */
+    void deleteIotDevicePersonLog(Long id);
+
+    /**
+     * 获得设备责任人日志
+     *
+     * @param id 编号
+     * @return 设备责任人日志
+     */
+    IotDevicePersonLogDO getIotDevicePersonLog(Long id);
+
+    /**
+     * 获得设备责任人日志分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 设备责任人日志分页
+     */
+    PageResult<IotDevicePersonLogDO> getIotDevicePersonLogPage(IotDevicePersonLogPageReqVO pageReqVO);
+
+}

+ 71 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotdevicepersonlog/IotDevicePersonLogServiceImpl.java

@@ -0,0 +1,71 @@
+package cn.iocoder.yudao.module.pms.service.iotdevicepersonlog;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdevicepersonlog.vo.IotDevicePersonLogPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotdevicepersonlog.vo.IotDevicePersonLogSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicepersonlog.IotDevicePersonLogDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotdevicepersonlog.IotDevicePersonLogMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_DEVICE_PERSON_LOG_NOT_EXISTS;
+
+/**
+ * 设备责任人日志 Service 实现类
+ *
+ * @author ruiqi
+ */
+@Service
+@Validated
+public class IotDevicePersonLogServiceImpl implements IotDevicePersonLogService {
+
+    @Resource
+    private IotDevicePersonLogMapper iotDevicePersonLogMapper;
+
+    @Override
+    public Long createIotDevicePersonLog(IotDevicePersonLogSaveReqVO createReqVO) {
+        // 插入
+        IotDevicePersonLogDO iotDevicePersonLog = BeanUtils.toBean(createReqVO, IotDevicePersonLogDO.class);
+        iotDevicePersonLogMapper.insert(iotDevicePersonLog);
+        // 返回
+        return iotDevicePersonLog.getId();
+    }
+
+    @Override
+    public void updateIotDevicePersonLog(IotDevicePersonLogSaveReqVO updateReqVO) {
+        // 校验存在
+        validateIotDevicePersonLogExists(updateReqVO.getId());
+        // 更新
+        IotDevicePersonLogDO updateObj = BeanUtils.toBean(updateReqVO, IotDevicePersonLogDO.class);
+        iotDevicePersonLogMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteIotDevicePersonLog(Long id) {
+        // 校验存在
+        validateIotDevicePersonLogExists(id);
+        // 删除
+        iotDevicePersonLogMapper.deleteById(id);
+    }
+
+    private void validateIotDevicePersonLogExists(Long id) {
+        if (iotDevicePersonLogMapper.selectById(id) == null) {
+            throw exception(IOT_DEVICE_PERSON_LOG_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public IotDevicePersonLogDO getIotDevicePersonLog(Long id) {
+        return iotDevicePersonLogMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<IotDevicePersonLogDO> getIotDevicePersonLogPage(IotDevicePersonLogPageReqVO pageReqVO) {
+        return iotDevicePersonLogMapper.selectPage(pageReqVO);
+    }
+
+}

+ 109 - 7
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorder/IotMainWorkOrderServiceImpl.java

@@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotlockstock.vo.IotLockStockPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderSaveReqVO;
@@ -16,9 +17,11 @@ import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMa
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomSaveReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialSaveReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotlockstock.IotLockStockDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorder.IotMainWorkOrderDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbom.IotMainWorkOrderBomDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbommaterial.IotMainWorkOrderBomMaterialDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotlockstock.IotLockStockMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorder.IotMainWorkOrderMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderbom.IotMainWorkOrderBomMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderbommaterial.IotMainWorkOrderBomMaterialMapper;
@@ -31,9 +34,8 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.math.BigDecimal;
+import java.util.*;
 import java.util.stream.Stream;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -59,6 +61,8 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
     private IotMainWorkOrderBomMaterialMapper iotMainWorkOrderBomMaterialMapper;
     @Resource
     private IotDeviceService iotDeviceService;
+    @Resource
+    private IotLockStockMapper iotLockStockMapper;
 
     @Override
     public Long createIotMainWorkOrder(IotMainWorkOrderSaveReqVO createReqVO) {
@@ -99,6 +103,9 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
 
     @Override
     public PageResult<IotMainWorkOrderDO> getIotMainWorkOrderPage(IotMainWorkOrderPageReqVO pageReqVO) {
+        if (ObjUtil.isNotEmpty(pageReqVO.getResult()) && 0 == pageReqVO.getResult()) {
+            pageReqVO.setResult(null);
+        }
         return iotMainWorkOrderMapper.selectPage(pageReqVO);
     }
 
@@ -136,7 +143,7 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
         if (ObjectUtil.isEmpty(workOrderMaterials)) {
             throw exception(IOT_MAIN_WORK_ORDER_NOT_EXISTS);
         }
-        // todo 保养工单 主表 还有 保养费用 、人工费用 、其他费用
+        // 保养工单 主表 还有 保养费用 、人工费用 、其他费用
         IotMainWorkOrderDO updateObj = BeanUtils.toBean(mainWorkOrder, IotMainWorkOrderDO.class);
         updateObj.setResult(2);
         iotMainWorkOrderMapper.updateById(updateObj);
@@ -149,13 +156,73 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
         iotMainWorkOrderBomMapper.updateBatch(workOrderBomDOS);
         // 保养工单 bom 明细关联的物料消耗
         List<IotMainWorkOrderBomMaterialDO> workOrderBomMaterialDOS = new ArrayList<>();
+        Set<Long> factoryIds = new HashSet<>();
+        Set<Long> costCenterIds = new HashSet<>();
+        Set<Long> storageLocationIds = new HashSet<>();
+        Set<String> materialCodes = new HashSet<>();
+        Map<String, BigDecimal> lockStockPair = new HashMap<>();
         workOrderMaterials.forEach(material -> {
             IotMainWorkOrderBomMaterialDO tempMaterial = BeanUtils.toBean(material, IotMainWorkOrderBomMaterialDO.class);
             tempMaterial.setWorkOrderId(mainWorkOrder.getId());
             workOrderBomMaterialDOS.add(tempMaterial);
+            if ("本地库存".equals(material.getMaterialSource())) {
+                if (ObjUtil.isNotEmpty(material.getFactoryId())) {
+                    factoryIds.add(material.getFactoryId());
+                }
+                if (ObjUtil.isNotEmpty(material.getCostCenterId())) {
+                    costCenterIds.add(material.getCostCenterId());
+                }
+                if (ObjUtil.isNotEmpty(material.getStorageLocationId())) {
+                    storageLocationIds.add(material.getStorageLocationId());
+                }
+                if (ObjUtil.isNotEmpty(material.getMaterialCode())) {
+                    materialCodes.add(material.getMaterialCode());
+                }
+                String tempKey = material.getFactoryId() + String.valueOf(material.getCostCenterId())
+                        + material.getMaterialCode();
+                if (lockStockPair.containsKey(tempKey)) {
+                    BigDecimal tempQuantity = lockStockPair.get(tempKey);
+                    BigDecimal totalQuantity = tempQuantity.add(material.getQuantity());
+                    lockStockPair.put(tempKey, totalQuantity);
+                } else {
+                    lockStockPair.put(tempKey, material.getQuantity());
+                }
+            }
         });
+        // 添加 工单消耗的物料记录
         iotMainWorkOrderBomMaterialMapper.insertBatch(workOrderBomMaterialDOS);
-        // todo 处理库存减少
+        // 只扣减本地库存 不处理SAP库存
+        if (CollUtil.isNotEmpty(factoryIds) && CollUtil.isNotEmpty(costCenterIds) && CollUtil.isNotEmpty(materialCodes)) {
+            IotLockStockPageReqVO reqVO = new IotLockStockPageReqVO();
+            reqVO.setFactoryIds(factoryIds);
+            reqVO.setCostCenterIds(costCenterIds);
+            reqVO.setMaterialCodes(materialCodes);
+            processLockStock(reqVO, lockStockPair);
+        }
+    }
+
+    /**
+     * 批量处理 库存扣减
+     * @param reqVO
+     * @param lockStockPair
+     */
+    private void processLockStock(IotLockStockPageReqVO reqVO, Map<String, BigDecimal> lockStockPair){
+        List<IotLockStockDO> lockStocks = iotLockStockMapper.selectList(reqVO);
+        List<IotLockStockDO> tobeUpdatedLockStocks = new ArrayList<>();
+        if (CollUtil.isNotEmpty(lockStocks)) {
+            lockStocks.forEach(lockStock -> {
+                String tempKey = lockStock.getFactoryId() + String.valueOf(lockStock.getCostCenterId())
+                        + lockStock.getMaterialCode();
+                if (lockStockPair.containsKey(tempKey)) {
+                    lockStock.setQuantity(lockStock.getQuantity().subtract(lockStockPair.get(tempKey)));
+                    tobeUpdatedLockStocks.add(lockStock);
+                }
+            });
+        }
+        if (CollUtil.isNotEmpty(tobeUpdatedLockStocks)) {
+            // 扣减本地库存
+            iotLockStockMapper.updateBatch(tobeUpdatedLockStocks);
+        }
     }
 
     @Override
@@ -175,7 +242,7 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
         if (ObjectUtil.isEmpty(workOrderMaterials)) {
             throw exception(IOT_MAIN_WORK_ORDER_NOT_EXISTS);
         }
-        // todo 保养工单 主表 还有 保养费用 、人工费用 、其他费用
+        // 保养工单 主表 还有 保养费用 、人工费用 、其他费用
         IotMainWorkOrderDO order = BeanUtils.toBean(mainWorkOrder, IotMainWorkOrderDO.class);
         // 生成保养工单号
         order.setOrderNumber(createWorkOrderNumber());
@@ -198,13 +265,48 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
         iotMainWorkOrderBomMapper.insertBatch(workOrderBomDOS);
         // 保养工单 bom 明细关联的物料消耗
         List<IotMainWorkOrderBomMaterialDO> workOrderBomMaterialDOS = new ArrayList<>();
+        Set<Long> factoryIds = new HashSet<>();
+        Set<Long> costCenterIds = new HashSet<>();
+        Set<Long> storageLocationIds = new HashSet<>();
+        Set<String> materialCodes = new HashSet<>();
+        Map<String, BigDecimal> lockStockPair = new HashMap<>();
         workOrderMaterials.forEach(material -> {
             IotMainWorkOrderBomMaterialDO tempMaterial = BeanUtils.toBean(material, IotMainWorkOrderBomMaterialDO.class);
             tempMaterial.setWorkOrderId(order.getId());
             workOrderBomMaterialDOS.add(tempMaterial);
+            if ("本地库存".equals(material.getMaterialSource())) {
+                if (ObjUtil.isNotEmpty(material.getFactoryId())) {
+                    factoryIds.add(material.getFactoryId());
+                }
+                if (ObjUtil.isNotEmpty(material.getCostCenterId())) {
+                    costCenterIds.add(material.getCostCenterId());
+                }
+                if (ObjUtil.isNotEmpty(material.getStorageLocationId())) {
+                    storageLocationIds.add(material.getStorageLocationId());
+                }
+                if (ObjUtil.isNotEmpty(material.getMaterialCode())) {
+                    materialCodes.add(material.getMaterialCode());
+                }
+                String tempKey = material.getFactoryId() + String.valueOf(material.getCostCenterId())
+                        + material.getMaterialCode();
+                if (lockStockPair.containsKey(tempKey)) {
+                    BigDecimal tempQuantity = lockStockPair.get(tempKey);
+                    BigDecimal totalQuantity = tempQuantity.add(material.getQuantity());
+                    lockStockPair.put(tempKey, totalQuantity);
+                } else {
+                    lockStockPair.put(tempKey, material.getQuantity());
+                }
+            }
         });
         iotMainWorkOrderBomMaterialMapper.insertBatch(workOrderBomMaterialDOS);
-        // todo 处理库存减少
+        // 只扣减本地库存 不处理SAP库存
+        if (CollUtil.isNotEmpty(factoryIds) && CollUtil.isNotEmpty(costCenterIds) && CollUtil.isNotEmpty(materialCodes)) {
+            IotLockStockPageReqVO reqVO = new IotLockStockPageReqVO();
+            reqVO.setFactoryIds(factoryIds);
+            reqVO.setCostCenterIds(costCenterIds);
+            reqVO.setMaterialCodes(materialCodes);
+            processLockStock(reqVO, lockStockPair);
+        }
     }
 
     @Override