Преглед изворни кода

pms 选择物料禁用数据权限 sap同步日志

zhangcl пре 2 месеци
родитељ
комит
7e768948d0
21 измењених фајлова са 900 додато и 38 уклоњено
  1. 1 0
      yudao-module-pms/yudao-module-pms-api/src/main/java/cn/iocoder/yudao/module/pms/enums/ErrorCodeConstant.java
  2. 93 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotsapsynclog/IotSapSyncLogController.java
  3. 39 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotsapsynclog/vo/IotSapSyncLogPageReqVO.java
  4. 43 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotsapsynclog/vo/IotSapSyncLogRespVO.java
  5. 28 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotsapsynclog/vo/IotSapSyncLogSaveReqVO.java
  6. 50 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotsapsynclog/IotSapSyncLogDO.java
  7. 3 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialMapper.java
  8. 18 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmaterial/IotMaterialMapper.java
  9. 17 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmaterial/IotSapMaterialMapper.java
  10. 29 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotsapsynclog/IotSapSyncLogMapper.java
  11. 31 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/framework/config/MultiThreadConfiguration.java
  12. 72 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/sap/SyncSapMaterialsJob.java
  13. 146 3
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/sap/SapController.java
  14. 20 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/sap/service/IotSapService.java
  15. 106 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/sap/service/IotSapServiceImpl.java
  16. 33 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/sap/vo/IotSapMaterialVO.java
  17. 1 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialServiceImpl.java
  18. 55 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotsapsynclog/IotSapSyncLogService.java
  19. 71 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotsapsynclog/IotSapSyncLogServiceImpl.java
  20. 10 0
      yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotSapMaterialMapper.xml
  21. 34 33
      yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotWorkOrderMaterialMapper.xml

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

@@ -63,4 +63,5 @@ public interface ErrorCodeConstant{
     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, "设备责任人日志不存在");
+    ErrorCode IOT_SAP_SYNC_LOG_NOT_EXISTS = new ErrorCode(153, "操作日志记录 V2 版本不存在");
 }

+ 93 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotsapsynclog/IotSapSyncLogController.java

@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotsapsynclog;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotsapsynclog.vo.IotSapSyncLogPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotsapsynclog.vo.IotSapSyncLogRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotsapsynclog.vo.IotSapSyncLogSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotsapsynclog.IotSapSyncLogDO;
+import cn.iocoder.yudao.module.pms.service.iotsapsynclog.IotSapSyncLogService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 操作日志记录 V2 版本")
+@RestController
+@RequestMapping("/pms/iot-sap-sync-log")
+@Validated
+public class IotSapSyncLogController {
+
+    @Resource
+    private IotSapSyncLogService iotSapSyncLogService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建操作日志记录 V2 版本")
+    @PreAuthorize("@ss.hasPermission('pms:iot-sap-sync-log:create')")
+    public CommonResult<Long> createIotSapSyncLog(@Valid @RequestBody IotSapSyncLogSaveReqVO createReqVO) {
+        return success(iotSapSyncLogService.createIotSapSyncLog(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新操作日志记录 V2 版本")
+    @PreAuthorize("@ss.hasPermission('pms:iot-sap-sync-log:update')")
+    public CommonResult<Boolean> updateIotSapSyncLog(@Valid @RequestBody IotSapSyncLogSaveReqVO updateReqVO) {
+        iotSapSyncLogService.updateIotSapSyncLog(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除操作日志记录 V2 版本")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('pms:iot-sap-sync-log:delete')")
+    public CommonResult<Boolean> deleteIotSapSyncLog(@RequestParam("id") Long id) {
+        iotSapSyncLogService.deleteIotSapSyncLog(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得操作日志记录 V2 版本")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('pms:iot-sap-sync-log:query')")
+    public CommonResult<IotSapSyncLogRespVO> getIotSapSyncLog(@RequestParam("id") Long id) {
+        IotSapSyncLogDO iotSapSyncLog = iotSapSyncLogService.getIotSapSyncLog(id);
+        return success(BeanUtils.toBean(iotSapSyncLog, IotSapSyncLogRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得操作日志记录 V2 版本分页")
+    @PreAuthorize("@ss.hasPermission('pms:iot-sap-sync-log:query')")
+    public CommonResult<PageResult<IotSapSyncLogRespVO>> getIotSapSyncLogPage(@Valid IotSapSyncLogPageReqVO pageReqVO) {
+        PageResult<IotSapSyncLogDO> pageResult = iotSapSyncLogService.getIotSapSyncLogPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, IotSapSyncLogRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出操作日志记录 V2 版本 Excel")
+    @PreAuthorize("@ss.hasPermission('pms:iot-sap-sync-log:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportIotSapSyncLogExcel(@Valid IotSapSyncLogPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<IotSapSyncLogDO> list = iotSapSyncLogService.getIotSapSyncLogPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "操作日志记录 V2 版本.xls", "数据", IotSapSyncLogRespVO.class,
+                        BeanUtils.toBean(list, IotSapSyncLogRespVO.class));
+    }
+
+}

+ 39 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotsapsynclog/vo/IotSapSyncLogPageReqVO.java

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotsapsynclog.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+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 = "管理后台 - 操作日志记录 V2 版本分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class IotSapSyncLogPageReqVO extends PageParam {
+
+    @Schema(description = "链路追踪编号", example = "30037")
+    private String traceId;
+
+    @Schema(description = "操作类型(同步领料单picking、同步物料主数据material、同步SAP库存stock、同步客商数据supply)", example = "1")
+    private String subType;
+
+    @Schema(description = "操作内容")
+    private String action;
+
+    @Schema(description = "操作结果")
+    private Boolean success;
+
+    @Schema(description = "拓展字段")
+    private String extra;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

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

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotsapsynclog.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 操作日志记录 V2 版本 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotSapSyncLogRespVO {
+
+    @Schema(description = "日志主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "30630")
+    @ExcelProperty("日志主键")
+    private Long id;
+
+    @Schema(description = "链路追踪编号", example = "30037")
+    @ExcelProperty("链路追踪编号")
+    private String traceId;
+
+    @Schema(description = "操作类型(同步领料单picking、同步物料主数据material、同步SAP库存stock、同步客商数据supply)", example = "1")
+    @ExcelProperty("操作类型(同步领料单picking、同步物料主数据material、同步SAP库存stock、同步客商数据supply)")
+    private String subType;
+
+    @Schema(description = "操作内容")
+    @ExcelProperty("操作内容")
+    private String action;
+
+    @Schema(description = "操作结果")
+    @ExcelProperty("操作结果")
+    private Boolean success;
+
+    @Schema(description = "拓展字段")
+    @ExcelProperty("拓展字段")
+    private String extra;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 28 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotsapsynclog/vo/IotSapSyncLogSaveReqVO.java

@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotsapsynclog.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 操作日志记录 V2 版本新增/修改 Request VO")
+@Data
+public class IotSapSyncLogSaveReqVO {
+
+    @Schema(description = "日志主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "30630")
+    private Long id;
+
+    @Schema(description = "链路追踪编号", example = "30037")
+    private String traceId;
+
+    @Schema(description = "操作类型(同步领料单picking、同步物料主数据material、同步SAP库存stock、同步客商数据supply)", example = "1")
+    private String subType;
+
+    @Schema(description = "操作内容")
+    private String action;
+
+    @Schema(description = "操作结果")
+    private Boolean success;
+
+    @Schema(description = "拓展字段")
+    private String extra;
+
+}

+ 50 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotsapsynclog/IotSapSyncLogDO.java

@@ -0,0 +1,50 @@
+package cn.iocoder.yudao.module.pms.dal.dataobject.iotsapsynclog;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+/**
+ * 操作日志记录 V2 版本 DO
+ *
+ * @author ruiqi
+ */
+@TableName("rq_iot_sap_sync_log")
+@KeySequence("rq_iot_sap_sync_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IotSapSyncLogDO extends BaseDO {
+
+    /**
+     * 日志主键
+     */
+    @TableId
+    private Long id;
+    /**
+     * 链路追踪编号
+     */
+    private String traceId;
+    /**
+     * 操作类型(同步领料单picking、同步物料主数据material、同步SAP库存stock、同步客商数据supply)
+     */
+    private String subType;
+    /**
+     * 操作内容
+     */
+    private String action;
+    /**
+     * 操作结果
+     */
+    private Boolean success;
+    /**
+     * 拓展字段
+     */
+    private String extra;
+
+}

+ 3 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialMapper.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderbommaterial;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialPageReqVO;
@@ -52,7 +53,8 @@ public interface IotMainWorkOrderBomMaterialMapper extends BaseMapperX<IotMainWo
                 .orderByDesc(IotMainWorkOrderBomMaterialDO::getId));
     }
 
-    IPage<IotMainWorkOrderBomMaterialRespVO> selectMaterialsBySapOrg(IPage<IotMainWorkOrderBomMaterialRespVO> page, @Param("deptId") Long deptId,
+    @DataPermission(enable = false)
+    IPage<IotMainWorkOrderBomMaterialRespVO> selectMaterialsBySapOrg(IPage<IotMainWorkOrderBomMaterialRespVO> page,
                                                                    @Param("parentDept") Long parentDept, @Param("materialCodes") List<String> materialCodes,
                                                                      @Param("factoryIds") Set<Long> factoryIds,
                                                                      @Param("costCenterIds") Set<Long> costCenterIds,

+ 18 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmaterial/IotMaterialMapper.java

@@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.pms.dal.dataobject.iotcommonbommaterial.IotCommon
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicematerial.IotDeviceMaterialDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotmaterial.IotMaterialDO;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Update;
 
 import java.util.Collection;
 import java.util.List;
@@ -43,6 +44,23 @@ public interface IotMaterialMapper extends BaseMapperX<IotMaterialDO> {
                 .orderByDesc(IotMaterialDO::getId));
     }
 
+    /**
+     * 查询 未同步的物料 列表
+     * @return
+     */
+    default List<IotMaterialDO> selectSyncList() {
+        return selectList(new LambdaQueryWrapperX<IotMaterialDO>()
+                .isNull(IotMaterialDO::getSyncTime)
+                .last("LIMIT 1000"));
+    }
+
+    /**
+     * 将所有物料记录的 sync_time 设置为 NULL
+     * @param
+     */
+    @Update("UPDATE rq_iot_material SET sync_time = NULL")
+    void resetMaterialSyncTime();
+
     default List<IotMaterialDO> selectListByStatus(Integer status) {
         return selectList(IotMaterialDO::getStatus, status);
     }

+ 17 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmaterial/IotSapMaterialMapper.java

@@ -0,0 +1,17 @@
+package cn.iocoder.yudao.module.pms.dal.mysql.iotmaterial;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * PMS 功能优化 SAP 同步 物料 Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface IotSapMaterialMapper {
+
+    List<String> allMaterialCodes();
+
+}

+ 29 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotsapsynclog/IotSapSyncLogMapper.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.pms.dal.mysql.iotsapsynclog;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.pms.controller.admin.iotsapsynclog.vo.IotSapSyncLogPageReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotsapsynclog.IotSapSyncLogDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 操作日志记录 V2 版本 Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface IotSapSyncLogMapper extends BaseMapperX<IotSapSyncLogDO> {
+
+    default PageResult<IotSapSyncLogDO> selectPage(IotSapSyncLogPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<IotSapSyncLogDO>()
+                .eqIfPresent(IotSapSyncLogDO::getTraceId, reqVO.getTraceId())
+                .eqIfPresent(IotSapSyncLogDO::getSubType, reqVO.getSubType())
+                .eqIfPresent(IotSapSyncLogDO::getAction, reqVO.getAction())
+                .eqIfPresent(IotSapSyncLogDO::getSuccess, reqVO.getSuccess())
+                .eqIfPresent(IotSapSyncLogDO::getExtra, reqVO.getExtra())
+                .betweenIfPresent(IotSapSyncLogDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(IotSapSyncLogDO::getId));
+    }
+
+}

+ 31 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/framework/config/MultiThreadConfiguration.java

@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.pms.framework.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 多线程配置
+ */
+@Configuration(proxyBeanMethods = false)
+public class MultiThreadConfiguration {
+
+    public static final String PMS_THREAD_POOL_TASK_EXECUTOR = "PMS_THREAD_POOL_TASK_EXECUTOR";
+
+    @Bean(PMS_THREAD_POOL_TASK_EXECUTOR)
+    public ThreadPoolTaskExecutor pmsThreadPoolTaskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(8); // 设置核心线程数
+        executor.setMaxPoolSize(16); // 设置最大线程数
+        executor.setKeepAliveSeconds(60); // 设置空闲时间
+        executor.setQueueCapacity(100); // 设置队列大小
+        executor.setThreadNamePrefix("pms-task-"); // 配置线程池的前缀
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        // 进行加载
+        executor.initialize();
+        return executor;
+    }
+
+}

+ 72 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/sap/SyncSapMaterialsJob.java

@@ -0,0 +1,72 @@
+package cn.iocoder.yudao.module.pms.job.sap;
+
+import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
+import cn.iocoder.yudao.module.pms.sap.SapConnector;
+import cn.iocoder.yudao.module.pms.sap.service.IotSapService;
+import cn.iocoder.yudao.module.pms.sap.vo.IotSapMaterialVO;
+import com.sap.conn.jco.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 同步 SAP 物料主数据 定时任务
+ */
+@Component
+@Slf4j
+public class SyncSapMaterialsJob implements JobHandler {
+    @Autowired
+    private SapConnector sapConnector;
+    @Autowired
+    private IotSapService iotSapService;
+
+    /**
+     * 暂时只同步当前租户的数据
+     * @param param 参数
+     * @return
+     * @throws Exception
+     */
+    @Override
+    public String execute(String param) throws Exception {
+        try {
+            JCoDestination destination = sapConnector.getDestination();
+            JCoFunction function = destination.getRepository().getFunction("ZPMS_005");
+
+            // 设置输入参数
+            JCoParameterList input = function.getImportParameterList();
+            input.setValue("IV_LAEDA", ""); // 上次更改的日期
+            input.setValue("IV_MATNR", ""); // 物料编号
+            input.setValue("IV_MAKTX", ""); // 物料描述
+
+            // 执行 RFC 调用
+            function.execute(destination);
+
+            // 获取输出参数
+            JCoParameterList output = function.getTableParameterList();
+            JCoTable otItabTable = function.getTableParameterList().getTable("OT_ITAB");
+            if (otItabTable != null && otItabTable.getNumRows() > 0) {
+                List<IotSapMaterialVO> sapMaterials = new ArrayList<>();
+                for (int i = 0; i < otItabTable.getNumRows(); i++) {
+                    otItabTable.setRow(i);
+                    IotSapMaterialVO tempMaterial = new IotSapMaterialVO();
+                    tempMaterial.setMATNR(otItabTable.getString("MATNR"));
+                    tempMaterial.setMAKTX(otItabTable.getString("MAKTX"));
+                    tempMaterial.setMTART(otItabTable.getString("MTART"));
+                    tempMaterial.setMTBEZ(otItabTable.getString("MTBEZ"));
+                    tempMaterial.setMATKL(otItabTable.getString("MATKL"));
+                    tempMaterial.setWGBEZ(otItabTable.getString("WGBEZ"));
+                    tempMaterial.setLVORM(otItabTable.getString("LVORM"));
+                    sapMaterials.add(tempMaterial);
+                }
+                iotSapService.processMaterials(sapMaterials);
+            }
+            return "Material Info: " + output.getString("OT_ITAB");
+        } catch (JCoException e) {
+            return "Error calling SAP Material Master Data: " + e.getMessage();
+        }
+    }
+
+}

+ 146 - 3
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/sap/SapController.java

@@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.pms.sap;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjUtil;
+import cn.iocoder.yudao.module.pms.sap.service.IotSapService;
+import cn.iocoder.yudao.module.pms.sap.vo.IotSapMaterialVO;
 import cn.iocoder.yudao.module.system.api.saporg.SapOrgApi;
 import cn.iocoder.yudao.module.system.api.saporg.dto.SapOrgRespDTO;
 import com.sap.conn.jco.*;
@@ -13,6 +15,7 @@ import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -25,6 +28,8 @@ public class SapController {
     private SapConnector sapConnector;
     @Autowired
     private SapOrgApi sapOrgApi;
+    @Autowired
+    private IotSapService iotSapService;
 
     @GetMapping("/callSapStock")
     @Operation(summary = "同步sap 库存接口")
@@ -181,9 +186,19 @@ public class SapController {
                 });
             }
             if (otItabTable != null && otItabTable.getNumRows() > 0) {
+                List<IotSapMaterialVO> sapMaterials = new ArrayList<>();
                 for (int i = 0; i < otItabTable.getNumRows(); i++) {
                     otItabTable.setRow(i);
-                    System.out.println(String.format("行号 %d: 物料编码=%s, 物料描述=%s, 物料类型=%s, 物料类型描述=%s, 物料组=%s, 物料组描述=%s, 集团级的DF=%s\n",
+                    IotSapMaterialVO tempMaterial = new IotSapMaterialVO();
+                    tempMaterial.setMATNR(otItabTable.getString("MATNR"));
+                    tempMaterial.setMAKTX(otItabTable.getString("MAKTX"));
+                    tempMaterial.setMTART(otItabTable.getString("MTART"));
+                    tempMaterial.setMTBEZ(otItabTable.getString("MTBEZ"));
+                    tempMaterial.setMATKL(otItabTable.getString("MATKL"));
+                    tempMaterial.setWGBEZ(otItabTable.getString("WGBEZ"));
+                    tempMaterial.setLVORM(otItabTable.getString("LVORM"));
+                    sapMaterials.add(tempMaterial);
+                    /* System.out.println(String.format("行号 %d: 物料编码=%s, 物料描述=%s, 物料类型=%s, 物料类型描述=%s, 物料组=%s, 物料组描述=%s, 集团级的DF=%s\n",
                             i,
                             otItabTable.getString("MATNR"), // 物料编码
                             otItabTable.getString("MAKTX"), // 物料描述
@@ -192,8 +207,9 @@ public class SapController {
                             otItabTable.getString("MATKL"), // 物料组
                             otItabTable.getString("WGBEZ"), // 物料组描述
                             otItabTable.getString("LVORM")  // 集团级的DF
-                    ));
+                    )); */
                 }
+                iotSapService.processMaterials(sapMaterials);
             }
             return "Material Info: " + output.getString("OT_ITAB");
         } catch (JCoException e) {
@@ -201,8 +217,64 @@ public class SapController {
         }
     }
 
+    @GetMapping("/callSapMaterialMasterDatas")
+    @Operation(summary = "同步sap 物料主数据接口")
+    public String callSapMaterialMasterDatas() {
+        //
+        try {
+            JCoDestination destination = sapConnector.getDestination();
+            JCoFunction function = destination.getRepository().getFunction("BAPI_MATERIAL_GETLIST");
+
+            // 设置输入参数
+            /* JCoParameterList input = function.getImportParameterList();
+            input.setValue("IV_LAEDA", ""); // 上次更改的日期
+            input.setValue("IV_MATNR", ""); // 物料编号
+            input.setValue("IV_MAKTX", ""); // 物料描述 */
+
+            // JCoTable materialRange = function.getTableParameterList().getTable("MATNR_RANGE");
+            function.getImportParameterList().setValue("MATERIAL_TYPE", "ALL");
+            // 执行 RFC 调用
+            function.execute(destination);
+
+            // JCoParameterList returnParams = function.getExportParameterList();
+            // String returnType = returnParams.getString("RETURN_TYPE");
+            // String returnMessage = returnParams.getString("RETURN_MESSAGE");
+
+            /* if ("E".equals(returnType) || "A".equals(returnType)) {
+                throw new RuntimeException("SAP调用错误: " + returnMessage);
+            } */
+            List<SapMaterial> materialList = new ArrayList<>();
+            // 处理返回的物料列表
+            JCoTable materialTable = function.getTableParameterList().getTable("RETURN");
+            for (int i = 0; i < materialTable.getNumRows(); i++) {
+                materialTable.setRow(i);
+
+                SapMaterial material = new SapMaterial();
+                material.setMaterialNumber(materialTable.getString("MATERIAL"));
+                material.setMaterialDescription(materialTable.getString("MATL_DESC"));
+                material.setMaterialType(materialTable.getString("MATL_TYPE"));
+                material.setPlant(materialTable.getString("PLANT"));
+                material.setBaseUnit(materialTable.getString("BASE_UOM"));
+                material.setIndustrySector(materialTable.getString("INDUSTRY"));
+
+                materialList.add(material);
+                System.out.println("物料编码:" + material.getMaterialNumber());
+            }
+
+            // 释放资源
+            function.getTableParameterList().getTable("MATLIST").clear();
+
+            // 获取输出参数
+            JCoParameterList output = function.getTableParameterList();
+
+            return "Material Info: " + output.getString("OT_ITAB");
+        } catch (JCoException e) {
+            return "Error calling SAP Material Master Data: " + e.getMessage();
+        }
+    }
+
     /**
-     * 查询所有SAP工厂
+     * 查询所有 SAP 工厂
      */
     private List<String> factoryCodes(){
         List<SapOrgRespDTO> sapOrgs = sapOrgApi.getSapOrgByType(1);
@@ -214,4 +286,75 @@ public class SapController {
                 .collect(Collectors.toList());
         return CollUtil.isEmpty(factoryCodes) ? CollUtil.empty(String.class) : factoryCodes;
     }
+
+    // 物料数据模型类
+    public static class SapMaterial {
+        private String materialNumber;
+        private String materialDescription;
+        private String materialType;
+        private String plant;
+        private String baseUnit;
+        private String industrySector;
+
+        // Getters and Setters
+        public String getMaterialNumber() {
+            return materialNumber;
+        }
+
+        public void setMaterialNumber(String materialNumber) {
+            this.materialNumber = materialNumber;
+        }
+
+        public String getMaterialDescription() {
+            return materialDescription;
+        }
+
+        public void setMaterialDescription(String materialDescription) {
+            this.materialDescription = materialDescription;
+        }
+
+        public String getMaterialType() {
+            return materialType;
+        }
+
+        public void setMaterialType(String materialType) {
+            this.materialType = materialType;
+        }
+
+        public String getPlant() {
+            return plant;
+        }
+
+        public void setPlant(String plant) {
+            this.plant = plant;
+        }
+
+        public String getBaseUnit() {
+            return baseUnit;
+        }
+
+        public void setBaseUnit(String baseUnit) {
+            this.baseUnit = baseUnit;
+        }
+
+        public String getIndustrySector() {
+            return industrySector;
+        }
+
+        public void setIndustrySector(String industrySector) {
+            this.industrySector = industrySector;
+        }
+
+        @Override
+        public String toString() {
+            return "SapMaterial{" +
+                    "materialNumber='" + materialNumber + '\'' +
+                    ", materialDescription='" + materialDescription + '\'' +
+                    ", materialType='" + materialType + '\'' +
+                    ", plant='" + plant + '\'' +
+                    ", baseUnit='" + baseUnit + '\'' +
+                    ", industrySector='" + industrySector + '\'' +
+                    '}';
+        }
+    }
 }

+ 20 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/sap/service/IotSapService.java

@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.pms.sap.service;
+
+import cn.iocoder.yudao.module.pms.sap.vo.IotSapMaterialVO;
+
+import java.util.List;
+
+/**
+ * SAP 同步接口相关的服务
+ */
+public interface IotSapService {
+
+    /**
+     * 处理SAP接口返回的 物料主数据
+     *
+     * @param
+     * @return 设备
+     */
+    void processMaterials(List<IotSapMaterialVO>  sapMaterials);
+
+}

+ 106 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/sap/service/IotSapServiceImpl.java

@@ -0,0 +1,106 @@
+package cn.iocoder.yudao.module.pms.sap.service;
+
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotmaterial.IotMaterialDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotmaterial.IotMaterialMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotmaterial.IotSapMaterialMapper;
+import cn.iocoder.yudao.module.pms.sap.vo.IotSapMaterialVO;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+
+import static cn.iocoder.yudao.module.pms.framework.config.MultiThreadConfiguration.PMS_THREAD_POOL_TASK_EXECUTOR;
+
+/**
+ * SAP 同步接口相关的服务
+ */
+@Service
+@Validated
+public class IotSapServiceImpl implements IotSapService {
+    private static final Logger log = LoggerFactory.getLogger(IotSapServiceImpl.class);
+
+    @Autowired
+    private IotSapMaterialMapper iotSapMaterialMapper;
+    @Autowired
+    private IotMaterialMapper iotMaterialMapper;
+    @Resource(name = PMS_THREAD_POOL_TASK_EXECUTOR)
+    private ThreadPoolTaskExecutor pmsThreadPoolTaskExecutor;
+
+    @Override
+    public void processMaterials(List<IotSapMaterialVO> sapMaterials) {
+        // SAP接口返回的物料编码 砍掉前端的 00000000
+        if (CollUtil.isEmpty(sapMaterials)) {
+            return;
+        }
+        // 1.新增物料
+        // 查询所有物料集合A,如果 sapMaterials 中有物料不在A中 新增物料
+        Set<String> existingMaterialCodes = new HashSet<>();
+        // List<String> materialCodes = iotSapMaterialMapper.allMaterialCodes();
+        List<IotMaterialDO> existMaterials = iotMaterialMapper.selectList();
+        if (CollUtil.isNotEmpty(existMaterials)) {
+            existingMaterialCodes = existMaterials.stream()
+                    .filter(material -> ObjUtil.isNotEmpty(material) && StrUtil.isNotBlank(material.getCode()))  // 过滤非空对象和非空code
+                    .map(IotMaterialDO::getCode)
+                    .collect(Collectors.toSet());
+        }
+        System.out.println("当前库中已有物料数量:" + existMaterials.size());
+        // 找出需要新增的物料(SAP物料编码去掉前导零后,不在现有物料集合中的记录)
+        Set<String> finalExistingMaterialCodes = existingMaterialCodes;
+        List<IotSapMaterialVO> newMaterials = sapMaterials.stream()
+                .filter(sapMaterial -> {
+                    // 处理前导零:移除MATNR前的00000000
+                    String processedCode = sapMaterial.getMATNR().replaceFirst("^0+", "");
+                    return !finalExistingMaterialCodes.contains(processedCode);
+                })
+                .collect(Collectors.toList());
+        System.out.println("需要新添加的物料数量:" + newMaterials.size());
+        // 需要新增的物料列表
+        List<IotMaterialDO> tobeAddedMaterials = new ArrayList<>();
+        if (CollUtil.isNotEmpty(newMaterials)) {
+            newMaterials.forEach(nm -> {
+                if (StrUtil.isNotBlank(nm.getMATNR())) {
+                    IotMaterialDO tempMaterial = new IotMaterialDO();
+                    tempMaterial.setCode(nm.getMATNR().replaceFirst("^0+", ""));    // 物料编码需要去除 前导0
+                    tempMaterial.setName(nm.getMAKTX());
+                    tempMaterial.setSyncTime(LocalDateTime.now());
+                    tobeAddedMaterials.add(tempMaterial);
+                }
+            });
+        }
+        if (CollUtil.isNotEmpty(tobeAddedMaterials)) {
+            CountDownLatch latch = new CountDownLatch(tobeAddedMaterials.size());
+            tobeAddedMaterials.forEach(material -> {
+                int tempBatchSize = 500;
+                for (int i = 0; i < tobeAddedMaterials.size(); i += tempBatchSize) {
+                    List<IotMaterialDO> batchMaterials = tobeAddedMaterials.subList(i, Math.min(i + tempBatchSize, tobeAddedMaterials.size()));
+                    pmsThreadPoolTaskExecutor.execute(() -> {
+                        try {
+                            iotMaterialMapper.insertBatch(batchMaterials);
+                        } finally {
+                            latch.countDown();
+                        }
+                    });
+                }
+            });
+        }
+
+        // 2.更新已有物料 物料描述可能会变化
+
+        // 3.记录接口调用日志
+    }
+}

+ 33 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/sap/vo/IotSapMaterialVO.java

@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.pms.sap.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - SAP 同步接口 物料 VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotSapMaterialVO {
+
+    @Schema(description = "物料编码", example = "000000003000000689")
+    private String MATNR;
+
+    @Schema(description = "物料描述", example = "活塞F1600 170")
+    private String MAKTX;
+
+    @Schema(description = "物料类型", example = "Z003")
+    private String MTART;
+
+    @Schema(description = "物料类型描述", example = "专业工具")
+    private String MTBEZ;
+
+    @Schema(description = "物料组", example = "302010")
+    private String MATKL;
+
+    @Schema(description = "物料组描述", example = "泥浆泵")
+    private String WGBEZ;
+
+    @Schema(description = "集团级的DF")
+    private String LVORM;
+
+}

+ 1 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialServiceImpl.java

@@ -155,7 +155,7 @@ public class IotMainWorkOrderBomMaterialServiceImpl implements IotMainWorkOrderB
         }
         IPage<IotMainWorkOrderBomMaterialRespVO> iotMaintainMaterialDOIPage =
                 iotMainWorkOrderBomMaterialMapper.selectMaterialsBySapOrg(Page.of(pageReqVO.getPageNo(), pageReqVO.getPageSize()),
-                        pageReqVO.getDeptId(), null, materialCodes, factoryIds, costCenterIds, stockLocationIds,
+                         null, materialCodes, factoryIds, costCenterIds, stockLocationIds,
                         pageReqVO.getMaterialName(), pageReqVO.getMaterialCode());
         List<IotMainWorkOrderBomMaterialRespVO> materials = iotMaintainMaterialDOIPage.getRecords();
         if (CollUtil.isNotEmpty(materials)) {

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

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.pms.service.iotsapsynclog;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.pms.controller.admin.iotsapsynclog.vo.IotSapSyncLogPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotsapsynclog.vo.IotSapSyncLogSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotsapsynclog.IotSapSyncLogDO;
+
+import javax.validation.Valid;
+
+/**
+ * 操作日志记录 V2 版本 Service 接口
+ *
+ * @author ruiqi
+ */
+public interface IotSapSyncLogService {
+
+    /**
+     * 创建操作日志记录 V2 版本
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createIotSapSyncLog(@Valid IotSapSyncLogSaveReqVO createReqVO);
+
+    /**
+     * 更新操作日志记录 V2 版本
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateIotSapSyncLog(@Valid IotSapSyncLogSaveReqVO updateReqVO);
+
+    /**
+     * 删除操作日志记录 V2 版本
+     *
+     * @param id 编号
+     */
+    void deleteIotSapSyncLog(Long id);
+
+    /**
+     * 获得操作日志记录 V2 版本
+     *
+     * @param id 编号
+     * @return 操作日志记录 V2 版本
+     */
+    IotSapSyncLogDO getIotSapSyncLog(Long id);
+
+    /**
+     * 获得操作日志记录 V2 版本分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 操作日志记录 V2 版本分页
+     */
+    PageResult<IotSapSyncLogDO> getIotSapSyncLogPage(IotSapSyncLogPageReqVO pageReqVO);
+
+}

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

@@ -0,0 +1,71 @@
+package cn.iocoder.yudao.module.pms.service.iotsapsynclog;
+
+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.iotsapsynclog.vo.IotSapSyncLogPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotsapsynclog.vo.IotSapSyncLogSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotsapsynclog.IotSapSyncLogDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotsapsynclog.IotSapSyncLogMapper;
+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_SAP_SYNC_LOG_NOT_EXISTS;
+
+/**
+ * 操作日志记录 V2 版本 Service 实现类
+ *
+ * @author ruiqi
+ */
+@Service
+@Validated
+public class IotSapSyncLogServiceImpl implements IotSapSyncLogService {
+
+    @Resource
+    private IotSapSyncLogMapper iotSapSyncLogMapper;
+
+    @Override
+    public Long createIotSapSyncLog(IotSapSyncLogSaveReqVO createReqVO) {
+        // 插入
+        IotSapSyncLogDO iotSapSyncLog = BeanUtils.toBean(createReqVO, IotSapSyncLogDO.class);
+        iotSapSyncLogMapper.insert(iotSapSyncLog);
+        // 返回
+        return iotSapSyncLog.getId();
+    }
+
+    @Override
+    public void updateIotSapSyncLog(IotSapSyncLogSaveReqVO updateReqVO) {
+        // 校验存在
+        validateIotSapSyncLogExists(updateReqVO.getId());
+        // 更新
+        IotSapSyncLogDO updateObj = BeanUtils.toBean(updateReqVO, IotSapSyncLogDO.class);
+        iotSapSyncLogMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteIotSapSyncLog(Long id) {
+        // 校验存在
+        validateIotSapSyncLogExists(id);
+        // 删除
+        iotSapSyncLogMapper.deleteById(id);
+    }
+
+    private void validateIotSapSyncLogExists(Long id) {
+        if (iotSapSyncLogMapper.selectById(id) == null) {
+            throw exception(IOT_SAP_SYNC_LOG_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public IotSapSyncLogDO getIotSapSyncLog(Long id) {
+        return iotSapSyncLogMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<IotSapSyncLogDO> getIotSapSyncLogPage(IotSapSyncLogPageReqVO pageReqVO) {
+        return iotSapSyncLogMapper.selectPage(pageReqVO);
+    }
+
+}

+ 10 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotSapMaterialMapper.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.iocoder.yudao.module.pms.dal.mysql.iotmaterial.IotSapMaterialMapper">
+
+    <!-- 查询所有物料 -->
+    <select id="allMaterialCodes" resultType="java.lang.String">
+        SELECT rim.`code` FROM rq_iot_material rim WHERE rim.deleted = 0 AND rim.tenant_id = 1
+    </select>
+
+</mapper>

+ 34 - 33
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotWorkOrderMaterialMapper.xml

@@ -47,19 +47,19 @@
         UNION ALL
         -- 本地库存物料
         SELECT
-            lo.factory_id AS factoryId,
-            lo.cost_center_id AS costCenterId,
-            lo.storage_location_id AS storageLocationId,
-            lo.material_code AS materialCode,
-            lo.material_name AS materialName,
-            lo.unit_price AS unitPrice,
-            lo.quantity AS totalInventoryQuantity,
-            lo.unit AS unit,
-            '本地库存' AS materialSource
+        lo.factory_id AS factoryId,
+        lo.cost_center_id AS costCenterId,
+        lo.storage_location_id AS storageLocationId,
+        lo.material_code AS materialCode,
+        lo.material_name AS materialName,
+        lo.unit_price AS unitPrice,
+        lo.quantity AS totalInventoryQuantity,
+        lo.unit AS unit,
+        '本地库存' AS materialSource
         FROM
-            rq_iot_lock_stock lo
+        rq_iot_lock_stock lo
         WHERE
-            1=1
+        1=1
         <if test="materialCodes != null and materialCodes.size &gt; 0">
             AND lo.material_code NOT IN
             <foreach collection="materialCodes" index="index" item="key" open="(" separator="," close=")">
@@ -89,19 +89,19 @@
 
         -- sap库存物料
         SELECT
-            sap.factory_id AS factoryId,
-            0 AS costCenterId,
-            sap.storage_location_id AS storageLocationId,
-            sap.material_code AS materialCode,
-            sap.material_name AS materialName,
-            sap.unit_price AS unitPrice,
-            sap.quantity AS totalInventoryQuantity,
-            sap.unit AS unit,
-            'sap库存' AS materialSource
+        sap.factory_id AS factoryId,
+        0 AS costCenterId,
+        sap.storage_location_id AS storageLocationId,
+        sap.material_code AS materialCode,
+        sap.material_name AS materialName,
+        sap.unit_price AS unitPrice,
+        sap.quantity AS totalInventoryQuantity,
+        sap.unit AS unit,
+        'sap库存' AS materialSource
         FROM
-            rq_iot_sap_stock sap
+        rq_iot_sap_stock sap
         WHERE
-            1=1
+        1=1
         <if test="materialCodes != null and materialCodes.size &gt; 0">
             AND sap.material_code IN
             <foreach collection="materialCodes" index="index" item="key" open="(" separator="," close=")">
@@ -130,19 +130,19 @@
         UNION ALL
         -- sap库存物料
         SELECT
-            sap.factory_id AS factoryId,
-            0 AS costCenterId,
-            sap.storage_location_id AS storageLocationId,
-            sap.material_code AS materialCode,
-            sap.material_name AS materialName,
-            sap.unit_price AS unitPrice,
-            sap.quantity AS totalInventoryQuantity,
-            sap.unit AS unit,
-            'sap库存' AS materialSource
+        sap.factory_id AS factoryId,
+        0 AS costCenterId,
+        sap.storage_location_id AS storageLocationId,
+        sap.material_code AS materialCode,
+        sap.material_name AS materialName,
+        sap.unit_price AS unitPrice,
+        sap.quantity AS totalInventoryQuantity,
+        sap.unit AS unit,
+        'sap库存' AS materialSource
         FROM
-            rq_iot_sap_stock sap
+        rq_iot_sap_stock sap
         WHERE
-            1=1
+        1=1
         <if test="materialCodes != null and materialCodes.size &gt; 0">
             AND sap.material_code NOT IN
             <foreach collection="materialCodes" index="index" item="key" open="(" separator="," close=")">
@@ -168,5 +168,6 @@
             AND sap.material_code LIKE concat(concat("%",#{materialCode}),"%")
         </if>
 
+
     </select>
 </mapper>