| 5 小时以前 | gongchunyi | ![]() |
| 5 小时以前 | gongchunyi | ![]() |
| 5 小时以前 | zss | ![]() |
| 6 小时以前 | gongchunyi | ![]() |
| 7 小时以前 | zss | ![]() |
| 7 小时以前 | zss | ![]() |
doc/ÄþÏÄ-ÖÐÊ¢½¨²Ä.sql
@@ -175,4 +175,29 @@ ALTER TABLE `product-inventory-management-zsjc`.`production_plan` DROP COLUMN `data_sync_type`, MODIFY COLUMN `data_source_type` tinyint NULL DEFAULT 1 COMMENT 'æ°æ®æ¥æºç±»åï¼1=éé忥 2=æå¨æ°å¢' AFTER `form_modified_time`; MODIFY COLUMN `data_source_type` tinyint NULL DEFAULT 1 COMMENT 'æ°æ®æ¥æºç±»åï¼1=éé忥 2=æå¨æ°å¢' AFTER `form_modified_time`; DROP TABLE IF EXISTS `base_param`; CREATE TABLE `base_param` ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主é®ID', param_key VARCHAR(100) NOT NULL COMMENT 'åæ°å¯ä¸æ è¯', param_name VARCHAR(100) NOT NULL COMMENT 'åæ°åç§°', param_type TINYINT NOT NULL COMMENT 'åæ°ç±»å(1æ°å 2ææ¬)', value_mode TINYINT DEFAULT 1 COMMENT '弿¨¡å¼(1åå¼ 2åºé´)', unit VARCHAR(50) COMMENT 'åä½', default_value VARCHAR(200) COMMENT 'é»è®¤å¼(åå¼åæ°)', default_min DECIMAL(10, 2) COMMENT 'é»è®¤æå°å¼(åºé´åæ°)', default_max DECIMAL(10, 2) COMMENT 'é»è®¤æå¤§å¼(åºé´åæ°)', is_required TINYINT DEFAULT 0 COMMENT 'æ¯å¦å¿ å¡«(0å¦ 1æ¯)', remark VARCHAR(255) COMMENT '夿³¨', create_user VARCHAR(64) COMMENT 'å建人', create_time DATETIME COMMENT 'å建æ¶é´', update_user VARCHAR(64) COMMENT 'ä¿®æ¹äºº', update_time DATETIME COMMENT 'ä¿®æ¹æ¶é´', tenant_id BIGINT NOT NULL COMMENT 'ç§æ·ID' ) COMMENT = 'åºç¡åæ°å®ä¹è¡¨'; ALTER TABLE `product-inventory-management-zsjc`.`customer` ADD COLUMN `form_instance_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'å®æè¡¨åå®ä¾ID' AFTER `customer_type`, ADD COLUMN `form_modified_time` datetime(0) NULL DEFAULT NULL COMMENT 'å®æä¿®æ¹æ¶é´' AFTER `form_instance_id`; src/main/java/com/ruoyi/basic/controller/BaseParamController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,60 @@ package com.ruoyi.basic.controller; import com.ruoyi.basic.pojo.BaseParam; import com.ruoyi.basic.service.BaseParamService; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.domain.AjaxResult; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; /** * <br> * åºç¡åæ°å®ä¹æ§å¶å± * </br> * * @author deslrey * @version 1.0 * @since 2026/03/13 16:42 */ @RestController @RequestMapping("/baseParam") public class BaseParamController extends BaseController { @Autowired private BaseParamService baseParamService; @GetMapping("list") @Log(title = "åºç¡åæ°æ°æ®éå", businessType = BusinessType.OTHER) @ApiOperation("åºç¡åæ°æ°æ®éå") public AjaxResult baseParamList(BaseParam baseParam) { List<BaseParam> list = baseParamService.baseParamList(baseParam); return AjaxResult.success(list); } @PostMapping("/add") @Log(title = "æ°å¢åºç¡åæ°", businessType = BusinessType.INSERT) @ApiOperation("æ°å¢åºç¡åæ°") public AjaxResult baseParamAdd(@RequestBody BaseParam baseParam) { return toAjax(baseParamService.addBaseParam(baseParam)); } @PutMapping("/edit") @Log(title = "ä¿®æ¹åºç¡åæ°", businessType = BusinessType.UPDATE) @ApiOperation("ä¿®æ¹åºç¡åæ°") public AjaxResult baseParamEdit(@RequestBody BaseParam baseParam) { return toAjax(baseParamService.updateBaseParam(baseParam)); } @DeleteMapping("/remove/{ids}") @Log(title = "å é¤åºç¡åæ°", businessType = BusinessType.DELETE) @ApiOperation("å é¤åºç¡åæ°") public AjaxResult baseParamRemove(@PathVariable Long[] ids) { return toAjax(baseParamService.deleteBaseParamByIds(ids)); } } src/main/java/com/ruoyi/basic/dto/BaseParamDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,79 @@ package com.ruoyi.basic.dto; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; import java.time.LocalDateTime; /** * <br> * åºç¡åæ°å®ä¹Dto * </br> * * @author deslrey * @version 1.0 * @since 2026/03/13 17:40 */ @Data @Api("åºç¡åæ°å®ä¹Dto") public class BaseParamDto { @ApiModelProperty("主é®ID") private Long id; @ApiModelProperty("åæ°å¯ä¸æ è¯") private String paramKey; @ApiModelProperty("åæ°åç§°") private String paramName; @ApiModelProperty("åæ°ç±»å(1æ°å 2ææ¬)") private Integer paramType; @ApiModelProperty("弿¨¡å¼(1åå¼ 2åºé´)") private Integer valueMode; @ApiModelProperty("åä½") private String unit; @ApiModelProperty("é»è®¤å¼(åå¼åæ°)") private String defaultValue; @ApiModelProperty("é»è®¤æå°å¼(åºé´åæ°)") private BigDecimal defaultMin; @ApiModelProperty("é»è®¤æå¤§å¼(åºé´åæ°)") private BigDecimal defaultMax; @ApiModelProperty("æ¯å¦å¿ å¡«(0å¦ 1æ¯)") private Integer isRequired; @ApiModelProperty("产åç±»å表IDåç§°") private String baseProductTypeName; @ApiModelProperty("夿³¨") private String remark; @ApiModelProperty("å建人") private String createUser; @ApiModelProperty("å建æ¶é´") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; @ApiModelProperty("ä¿®æ¹äºº") private String updateUser; @ApiModelProperty("ä¿®æ¹æ¶é´") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime updateTime; } src/main/java/com/ruoyi/basic/mapper/BaseParamMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ package com.ruoyi.basic.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.basic.pojo.BaseParam; /** * <br> * åºç¡åæ°å®ä¹Mapper * </br> * * @author deslrey * @version 1.0 * @since 2026/03/13 16:39 */ public interface BaseParamMapper extends BaseMapper<BaseParam> { } src/main/java/com/ruoyi/basic/pojo/BaseParam.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,81 @@ package com.ruoyi.basic.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; import java.time.LocalDateTime; /** * <br> * åºç¡åæ°å®ä¹è¡¨ * </br> * * @author deslrey * @version 1.0 * @since 2026/03/13 16:33 */ @Data @TableName("base_param") @Api("åºç¡åæ°å®ä¹") public class BaseParam { @TableId(type = IdType.AUTO) @ApiModelProperty("主é®ID") private Long id; @ApiModelProperty("åæ°å¯ä¸æ è¯") private String paramKey; @ApiModelProperty("åæ°åç§°") private String paramName; @ApiModelProperty("åæ°ç±»å(1æ°å 2ææ¬)") private Integer paramType; @ApiModelProperty("弿¨¡å¼(1åå¼ 2åºé´)") private Integer valueMode; @ApiModelProperty("åä½") private String unit; @ApiModelProperty("é»è®¤å¼(åå¼åæ°)") private String defaultValue; @ApiModelProperty("é»è®¤æå°å¼(åºé´åæ°)") private BigDecimal defaultMin; @ApiModelProperty("é»è®¤æå¤§å¼(åºé´åæ°)") private BigDecimal defaultMax; @ApiModelProperty("æ¯å¦å¿ å¡«(0å¦ 1æ¯)") private Integer isRequired; @ApiModelProperty("夿³¨") private String remark; @ApiModelProperty("å建人") private String createUser; @ApiModelProperty("å建æ¶é´") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; @ApiModelProperty("ä¿®æ¹äºº") private String updateUser; @ApiModelProperty("ä¿®æ¹æ¶é´") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime updateTime; @ApiModelProperty("ç§æ·ID") private Long tenantId; } src/main/java/com/ruoyi/basic/pojo/Customer.java
@@ -115,4 +115,11 @@ @ApiModelProperty(value = "弿·è¡å·") @Excel(name = "弿·è¡å·") private String bankCode; @ApiModelProperty("å®æè¡¨åå®ä¾ID") private String formInstanceId; @ApiModelProperty("å®æä¿®æ¹æ¶é´") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime formModifiedTime; } src/main/java/com/ruoyi/basic/service/BaseParamService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,25 @@ package com.ruoyi.basic.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.basic.pojo.BaseParam; import java.util.List; /** * <br> * åºç¡åæ°å®ä¹æ¥å£ * </br> * * @author deslrey * @version 1.0 * @since 2026/03/13 16:40 */ public interface BaseParamService extends IService<BaseParam> { List<BaseParam> baseParamList(BaseParam baseParam); int addBaseParam(BaseParam baseParam); int updateBaseParam(BaseParam baseParam); int deleteBaseParamByIds(Long[] ids); } src/main/java/com/ruoyi/basic/service/impl/BaseParamServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,157 @@ package com.ruoyi.basic.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.mapper.BaseParamMapper; import com.ruoyi.basic.pojo.BaseParam; import com.ruoyi.basic.service.BaseParamService; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import io.swagger.annotations.Api; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * <br> * åºç¡åæ°å®ä¹æ¥å£å®ç°ç±» * </br> * * @author deslrey * @version 1.0 * @since 2026/03/13 16:41 */ @Slf4j @Service @Api("åºç¡åæ°å®ä¹æ¥å£å®ç°ç±»") public class BaseParamServiceImpl extends ServiceImpl<BaseParamMapper, BaseParam> implements BaseParamService { @Override public List<BaseParam> baseParamList(BaseParam baseParam) { LambdaQueryWrapper<BaseParam> queryWrapper = new LambdaQueryWrapper<>(); if (StringUtils.isNotEmpty(baseParam.getParamName())) { queryWrapper.like(BaseParam::getParamName, baseParam.getParamName()); } List<BaseParam> list = list(queryWrapper); if (list == null || list.isEmpty()) { return new ArrayList<>(0); } return list; } @Override public int addBaseParam(BaseParam baseParam) { if (baseParam == null) { throw new RuntimeException("æ°å¢åæ°ä¸è½ä¸ºç©º"); } // åæ°æ ¡éª checkBaseParam(baseParam, false); // èªå¨çæparamKey baseParam.setParamKey(generateParamKey()); baseParam.setCreateUser(SecurityUtils.getUsername()); baseParam.setCreateTime(LocalDateTime.now()); return baseMapper.insert(baseParam); } @Override public int updateBaseParam(BaseParam baseParam) { if (baseParam == null || baseParam.getId() == null) { throw new RuntimeException("ä¿®æ¹åæ°IDä¸è½ä¸ºç©º"); } // åæ°æ ¡éª checkBaseParam(baseParam, true); baseParam.setUpdateUser(SecurityUtils.getUsername()); baseParam.setUpdateTime(LocalDateTime.now()); return baseMapper.updateById(baseParam); } /** * çæåæ°å¯ä¸key */ private String generateParamKey() { String prefix = "PARAM_"; // æ¥è¯¢å½åæå¤§key LambdaQueryWrapper<BaseParam> wrapper = new LambdaQueryWrapper<>(); wrapper.select(BaseParam::getParamKey) .likeRight(BaseParam::getParamKey, prefix) .orderByDesc(BaseParam::getParamKey) .last("limit 1"); BaseParam last = baseMapper.selectOne(wrapper); int nextNum = 1; if (last != null) { String lastKey = last.getParamKey(); String numStr = lastKey.replace(prefix, ""); nextNum = Integer.parseInt(numStr) + 1; } return prefix + String.format("%04d", nextNum); } /** * åæ°åæ³æ§æ ¡éª */ private void checkBaseParam(BaseParam baseParam, boolean isUpdate) { if (baseParam == null) { throw new RuntimeException("åæ°å¯¹è±¡ä¸è½ä¸ºç©º"); } if (StringUtils.isEmpty(baseParam.getParamName())) { throw new RuntimeException("åæ°åç§°ä¸è½ä¸ºç©º"); } if (baseParam.getParamType() == null || !(baseParam.getParamType() == 1 || baseParam.getParamType() == 2)) { throw new RuntimeException("åæ°ç±»åå¿ é¡»ä¸º1(æ°å)æ2(ææ¬)"); } if (baseParam.getValueMode() == null || !(baseParam.getValueMode() == 1 || baseParam.getValueMode() == 2)) { throw new RuntimeException("弿¨¡å¼å¿ 须为1(åå¼)æ2(åºé´)"); } // å弿¨¡å¼ if (baseParam.getValueMode() == 1) { if (StringUtils.isEmpty(baseParam.getDefaultValue())) { throw new RuntimeException("åå¼åæ°é»è®¤å¼ä¸è½ä¸ºç©º"); } if (baseParam.getParamType() == 1) { try { new BigDecimal(baseParam.getDefaultValue()); } catch (Exception e) { throw new RuntimeException("é»è®¤å¼å¿ 须为æ°å"); } } baseParam.setDefaultMin(null); baseParam.setDefaultMax(null); } // åºé´æ¨¡å¼ if (baseParam.getValueMode() == 2) { if (baseParam.getParamType() != 1) { throw new RuntimeException("åªææ°åç±»åæè½ä½¿ç¨åºé´æ¨¡å¼"); } if (baseParam.getDefaultMin() == null || baseParam.getDefaultMax() == null) { throw new RuntimeException("åºé´åæ°æå°å¼åæå¤§å¼ä¸è½ä¸ºç©º"); } if (baseParam.getDefaultMin().compareTo(baseParam.getDefaultMax()) > 0) { throw new RuntimeException("æå°å¼ä¸è½å¤§äºæå¤§å¼"); } baseParam.setDefaultValue(null); } } @Override public int deleteBaseParamByIds(Long[] ids) { if (ids == null || ids.length == 0) { throw new RuntimeException("å é¤IDä¸è½ä¸ºç©º"); } return baseMapper.deleteBatchIds(Arrays.asList(ids)); } } src/main/java/com/ruoyi/framework/util/AliDingUtils.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,173 @@ package com.ruoyi.framework.util; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.http.HttpUtils; import com.ruoyi.framework.config.AliDingConfig; import lombok.extern.slf4j.Slf4j; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; /** * <br> * æ ¹æ®å®æè¡¨å ID è·åæ°æ® * </br> * * @author deslrey * @version 1.0 * @since 2026/03/14 11:11 */ @Slf4j public class AliDingUtils { /** * æ ¹æ®è¡¨å ID è·åå®ææ°æ® * * @param aliDingConfig éé宿æ¥å£é ç½® * @param formUuid è·åæ°æ®ç表åID * @param searchFieldJson éè¦æºå¸¦çæ¥è¯¢æ¡ä»¶ * @param service è·åæè¿è¡¨åæ´æ°çæ¥æService * @param timeField 表åä¿®æ¹æ¥æ * @param <T> å®ä½ç±» * @return 对åºè¡¨åçæ°æ® */ public static <T> JSONArray getFormDataList(AliDingConfig aliDingConfig, String formUuid, String searchFieldJson, IService<T> service, SFunction<T, ?> timeField) { // è·å accessToken String accessToken = getAccessToken(aliDingConfig); // è·åæå忥æ¶é´ LocalDateTime lastSyncTime = getLastSyncTime(service, timeField); log.info("å¼å§åæ¥æ°æ®ï¼æ¬å°æåä¿®æ¹æ¶é´: {}", lastSyncTime); JSONArray allData = new JSONArray(); int pageNumber = 1; int pageSize = 50; boolean hasMore = true; while (hasMore) { JSONObject searchParam = new JSONObject(); searchParam.put("appType", aliDingConfig.getAppType()); searchParam.put("systemToken", aliDingConfig.getSystemToken()); searchParam.put("userId", aliDingConfig.getUserId()); searchParam.put("formUuid", formUuid); searchParam.put("currentPage", pageNumber); searchParam.put("pageSize", pageSize); if (StringUtils.isNotEmpty(searchFieldJson)) { searchParam.put("searchFieldJson", searchFieldJson); } searchParam.put("orderConfigJson", "{\"gmt_modified\":\"+\"}"); if (lastSyncTime != null) { String startTime = lastSyncTime.plusSeconds(1) .atZone(ZoneId.systemDefault()) .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); searchParam.put("modifiedFromTimeGMT", startTime); } String endTime = LocalDateTime.now() .atZone(ZoneId.systemDefault()) .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); searchParam.put("modifiedToTimeGMT", endTime); String dataRes = HttpUtils.sendPostJson( aliDingConfig.getSearchFormDataUrl(), searchParam.toJSONString(), StandardCharsets.UTF_8.name(), null, accessToken ); if (StringUtils.isEmpty(dataRes)) { log.warn("第 {} 页æåæ°æ®ä¸ºç©º", pageNumber); break; } JSONObject resultObj = JSON.parseObject(dataRes); JSONArray dataArr = resultObj.getJSONArray("data"); Integer totalCount = resultObj.getInteger("totalCount"); if (dataArr == null || dataArr.isEmpty()) { log.info("æ²¡ææ´å¤æ°æ°æ®éè¦åæ¥"); break; } allData.addAll(dataArr); hasMore = (pageNumber * pageSize) < totalCount; pageNumber++; log.info("æ£å¨æå宿åé¡µæ°æ®ï¼ç¬¬ {} 页已å¤çï¼å½åæåæ°: {}/{}", pageNumber - 1, allData.size(), totalCount); } return allData; } /** * è·åéé AccessToken */ private static String getAccessToken(AliDingConfig aliDingConfig) { String params = "appkey=" + aliDingConfig.getAppKey() + "&appsecret=" + aliDingConfig.getAppSecret(); String tokenRes = HttpUtils.sendGet(aliDingConfig.getAccessTokenUrl(), params); JSONObject tokenObj = JSON.parseObject(tokenRes); String accessToken = tokenObj.getString("access_token"); if (StringUtils.isEmpty(accessToken)) { log.error("è·åééAccessToken失败: {}", tokenRes); } return accessToken; } /** * æ¥ææ ¼å¼å * * @param utcString æ¥æ * @return LocalDateTime */ public static LocalDateTime parseUtcTime(String utcString) { if (StringUtils.isEmpty(utcString)) { return null; } try { OffsetDateTime odt = OffsetDateTime.parse(utcString); return odt.toLocalDateTime(); } catch (DateTimeParseException ex) { log.warn("è§£ææ¶é´ {} 失败: {}", utcString, ex.getMessage()); return null; } } private static <T> LocalDateTime getLastSyncTime(IService<T> service, SFunction<T, ?> timeField) { LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.orderByDesc(timeField).last("LIMIT 1"); T lastRecord = service.getOne(queryWrapper); if (lastRecord == null) { return null; } try { Method writeReplace = timeField.getClass().getDeclaredMethod("writeReplace"); writeReplace.setAccessible(true); SerializedLambda lambda = (SerializedLambda) writeReplace.invoke(timeField); // è·åæ¹æ³å String methodName = lambda.getImplMethodName(); // è½¬åæ®µå String fieldName = methodName.substring(3, 4).toLowerCase() + methodName.substring(4); Field field = lastRecord.getClass().getDeclaredField(fieldName); field.setAccessible(true); return (LocalDateTime) field.get(lastRecord); } catch (Exception e) { throw new RuntimeException("è·åæå忥æ¶é´å¤±è´¥", e); } } } src/main/java/com/ruoyi/production/controller/ProductMaterialController.java
@@ -1,5 +1,8 @@ package com.ruoyi.production.controller; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.basic.pojo.ProductModel; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.AjaxResult; src/main/java/com/ruoyi/production/pojo/ProcessRoute.java
@@ -18,7 +18,7 @@ private Long id; @ApiModelProperty(value = "产åID") //product_model //å®å¤-ä¸ç建æä½¿ç¨æ°ç产åè¡¨å ³èproduct_material_sku private Long productModelId; @ApiModelProperty(value = "æè¿°") src/main/java/com/ruoyi/production/pojo/ProcessRouteItem.java
@@ -22,6 +22,7 @@ private Long processId; @ApiModelProperty(value ="产åid") //å®å¤-ä¸ç建æä½¿ç¨æ°ç产åè¡¨å ³èproduct_material_sku private Long productModelId; @ApiModelProperty(value = "ç§æ·ID") src/main/java/com/ruoyi/production/pojo/ProductBom.java
@@ -38,6 +38,7 @@ private String bomNo; @ApiModelProperty("产åè§æ ¼id") //å®å¤-ä¸ç建æä½¿ç¨æ°ç产åè¡¨å ³èproduct_material_sku private Long productModelId; @ApiModelProperty("夿³¨") src/main/java/com/ruoyi/production/pojo/ProductProcessRoute.java
@@ -34,7 +34,7 @@ private Long id; @ApiModelProperty("产åid") //product_model //å®å¤-ä¸ç建æä½¿ç¨æ°ç产åè¡¨å ³èproduct_material_sku private Long productModelId; @ApiModelProperty("æè¿°") src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java
@@ -23,6 +23,7 @@ private Long processId; @ApiModelProperty(value ="产åid") //å®å¤-ä¸ç建æä½¿ç¨æ°ç产åè¡¨å ³èproduct_material_sku private Long productModelId; @ApiModelProperty(value = "ç§æ·ID") src/main/java/com/ruoyi/production/pojo/ProductStructure.java
@@ -19,6 +19,7 @@ /** * 产ååç§° */ //å®å¤-ä¸ç建æä½¿ç¨æ°ç产åè¡¨å ³èproduct_material_sku private Long productModelId; /** src/main/java/com/ruoyi/production/service/impl/ProductMaterialServiceImpl.java
@@ -1,6 +1,5 @@ package com.ruoyi.production.service.impl; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -8,8 +7,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.http.HttpUtils; import com.ruoyi.framework.config.AliDingConfig; import com.ruoyi.framework.util.AliDingUtils; import com.ruoyi.production.dto.ProductMaterialDto; import com.ruoyi.production.dto.ProductMaterialGroupDto; import com.ruoyi.production.enums.MaterialConfigTypeEnum; @@ -25,13 +24,11 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; @@ -85,126 +82,52 @@ } try { // è·å AccessToken String accessToken = getAccessToken(); if (StringUtils.isEmpty(accessToken)) { JSONArray searchConditions = new JSONArray(); JSONObject statusCondition = new JSONObject(); statusCondition.put("key", "processInstanceStatus"); JSONArray statusValueArray = new JSONArray(); statusValueArray.add("COMPLETED"); statusCondition.put("value", statusValueArray); statusCondition.put("type", "ARRAY"); statusCondition.put("operator", "in"); statusCondition.put("componentName", "SelectField"); searchConditions.add(statusCondition); JSONObject resultCondition = new JSONObject(); resultCondition.put("key", "processApprovedResult"); JSONArray resultValueArray = new JSONArray(); resultValueArray.add("agree"); resultCondition.put("value", resultValueArray); resultCondition.put("type", "ARRAY"); resultCondition.put("operator", "in"); resultCondition.put("componentName", "SelectField"); searchConditions.add(resultCondition); String searchFieldJson = searchConditions.toJSONString(); JSONArray dataArr = AliDingUtils.getFormDataList(aliDingConfig, aliDingConfig.getMaterialCodeFormUuid(), searchFieldJson, productMaterialSkuService, ProductMaterialSku::getFormModifiedTime); if (dataArr.isEmpty()) { log.info("æ²¡ææ´å¤æ°æ°æ®éè¦åæ¥"); return; } // è·åæ¬å°æå忥æ¶é´ LocalDateTime lastSyncTime = getLastSyncTime(); log.info("å¼å§ç©æç¼ç å¢éåæ¥ï¼æ¬å°æåä¿®æ¹æ¶é´: {}", lastSyncTime); int pageNumber = 1; int pageSize = 50; boolean hasMore = true; int totalSynced = 0; while (hasMore) { // æ¥è¯¢åæ° JSONObject searchParam = buildSearchParam(lastSyncTime, pageNumber, pageSize); // è°ç¨å®ææ¥å£æåæ°æ® String dataRes = HttpUtils.sendPostJson(aliDingConfig.getSearchFormDataUrl(), searchParam.toJSONString(), StandardCharsets.UTF_8.name(), null, accessToken); if (StringUtils.isEmpty(dataRes)) { log.warn("第 {} 页æåæ°æ®ä¸ºç©º", pageNumber); break; } JSONObject resultObj = JSON.parseObject(dataRes); JSONArray dataArr = resultObj.getJSONArray("data"); Integer totalCount = resultObj.getInteger("totalCount"); if (dataArr == null || dataArr.isEmpty()) { log.info("æ²¡ææ´å¤æ°æ°æ®éè¦åæ¥"); break; } // è§£æå¹¶ä¿åæ°æ® List<ProductMaterialSku> list = parseProductMaterials(dataArr, totalCount); if (!list.isEmpty()) { // å¤çæ´æ°ææ°å¢ int affected = processSaveOrUpdate(list); totalSynced += affected; } // 夿æ¯å¦è¿æä¸ä¸é¡µ hasMore = (pageNumber * pageSize) < totalCount; pageNumber++; log.info("æ£å¨åæ¥ç¬¬ {} 页ï¼å½å已忥 {}/{}", pageNumber - 1, totalSynced, totalCount); // è§£æå¹¶ä¿åæ°æ® List<ProductMaterialSku> list = parseProductMaterials(dataArr, dataArr.size()); if (!list.isEmpty()) { // å¤çæ´æ°ææ°å¢ int affected = processSaveOrUpdate(list); log.info("ç©ææ°æ®åæ¥å®æï¼å ±åæ¥ {} æ¡æ°æ®", affected); } log.info("ç©ææ°æ®åæ¥å®æï¼å ±åæ¥ {} æ¡æ°æ®", totalSynced); } catch (Exception e) { log.error("åæ¥ç©æç¼ç å¼å¸¸", e); } finally { // éæ¾é syncLock.unlock(); } } private String getAccessToken() { String params = "appkey=" + aliDingConfig.getAppKey() + "&appsecret=" + aliDingConfig.getAppSecret(); String tokenRes = HttpUtils.sendGet(aliDingConfig.getAccessTokenUrl(), params); JSONObject tokenObj = JSON.parseObject(tokenRes); String accessToken = tokenObj.getString("access_token"); if (StringUtils.isEmpty(accessToken)) { log.error("è·åééAccessToken失败: {}", tokenRes); } return accessToken; } private LocalDateTime getLastSyncTime() { LambdaQueryWrapper<ProductMaterialSku> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.orderByDesc(ProductMaterialSku::getFormModifiedTime).last("LIMIT 1"); ProductMaterialSku lastRecord = productMaterialSkuService.getOne(queryWrapper); return lastRecord != null ? lastRecord.getFormModifiedTime() : null; } private JSONObject buildSearchParam(LocalDateTime lastSyncTime, int pageNumber, int pageSize) { JSONObject searchParam = new JSONObject(); searchParam.put("appType", aliDingConfig.getAppType()); searchParam.put("systemToken", aliDingConfig.getSystemToken()); searchParam.put("userId", aliDingConfig.getUserId()); searchParam.put("formUuid", aliDingConfig.getMaterialCodeFormUuid()); searchParam.put("currentPage", pageNumber); searchParam.put("pageSize", pageSize); JSONArray searchConditions = new JSONArray(); JSONObject statusCondition = new JSONObject(); statusCondition.put("key", "processInstanceStatus"); JSONArray statusValueArray = new JSONArray(); statusValueArray.add("COMPLETED"); statusCondition.put("value", statusValueArray); statusCondition.put("type", "ARRAY"); statusCondition.put("operator", "in"); statusCondition.put("componentName", "SelectField"); searchConditions.add(statusCondition); JSONObject resultCondition = new JSONObject(); resultCondition.put("key", "processApprovedResult"); JSONArray resultValueArray = new JSONArray(); resultValueArray.add("agree"); resultCondition.put("value", resultValueArray); resultCondition.put("type", "ARRAY"); resultCondition.put("operator", "in"); resultCondition.put("componentName", "SelectField"); searchConditions.add(resultCondition); searchParam.put("searchFieldJson", searchConditions.toJSONString()); searchParam.put("orderConfigJson", "{\"gmt_modified\":\"+\"}"); if (lastSyncTime != null) { String startTime = lastSyncTime.plusSeconds(1).atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); searchParam.put("modifiedFromTimeGMT", startTime); } String endTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); searchParam.put("modifiedToTimeGMT", endTime); return searchParam; } private List<ProductMaterialSku> parseProductMaterials(JSONArray dataArr, Integer totalCount) { @@ -241,7 +164,7 @@ sku.setSupplyType(formData.getString("selectField_la14k51j")); sku.setOriginatorName(originatorName); sku.setOriginatorOrg("å®å¤ä¸å绿è½å®ä¸é墿éå ¬å¸"); sku.setFormModifiedTime(parseUtcTime(item.getString("modifiedTimeGMT"))); sku.setFormModifiedTime(AliDingUtils.parseUtcTime(item.getString("modifiedTimeGMT"))); sku.setCreateTime(now); sku.setUpdateTime(now); @@ -332,19 +255,6 @@ } } return affected; } private LocalDateTime parseUtcTime(String utcString) { if (StringUtils.isEmpty(utcString)) { return null; } try { OffsetDateTime odt = OffsetDateTime.parse(utcString); return odt.toLocalDateTime(); } catch (DateTimeParseException ex) { log.warn("è§£ææ¶é´ {} 失败: {}", utcString, ex.getMessage()); return null; } } @Override src/main/java/com/ruoyi/production/service/impl/ProductMaterialSkuServiceImpl.java
@@ -51,17 +51,15 @@ */ @Override public Page<ProductMaterialSkuDto> productMaterialSkuList(Page<ProductMaterialSku> page, ProductMaterialSkuDto dto) { if (dto == null || dto.getMaterialId() == null) { return new Page<>(); } LambdaQueryWrapper<ProductMaterialSku> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ProductMaterialSku::getMaterialId, dto.getMaterialId()) .like(StringUtils.isNotBlank(dto.getSpecification()), ProductMaterialSku::getSpecification, dto.getSpecification()) .like(StringUtils.isNotBlank(dto.getMaterialCode()), ProductMaterialSku::getMaterialCode, dto.getMaterialCode()) .orderByAsc(ProductMaterialSku::getId); if (dto != null && dto.getMaterialId() != null) { queryWrapper.eq(ProductMaterialSku::getMaterialId, dto.getMaterialId()) .like(StringUtils.isNotBlank(dto.getSpecification()), ProductMaterialSku::getSpecification, dto.getSpecification()) .like(StringUtils.isNotBlank(dto.getMaterialCode()), ProductMaterialSku::getMaterialCode, dto.getMaterialCode()) .orderByAsc(ProductMaterialSku::getId); } Page<ProductMaterialSku> skuPage = this.page(page, queryWrapper); List<ProductMaterialSku> skuList = skuPage.getRecords(); if (skuList == null || skuList.isEmpty()) { src/main/java/com/ruoyi/productionPlan/service/impl/ProductionPlanServiceImpl.java
@@ -1,6 +1,5 @@ package com.ruoyi.productionPlan.service.impl; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -12,10 +11,9 @@ import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.common.utils.http.HttpUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.config.AliDingConfig; import com.ruoyi.production.pojo.ProductMaterial; import com.ruoyi.framework.util.AliDingUtils; import com.ruoyi.production.pojo.ProductMaterialSku; import com.ruoyi.production.pojo.ProductOrder; import com.ruoyi.production.service.ProductMaterialService; @@ -38,10 +36,9 @@ import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.time.*; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.*; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; @@ -248,133 +245,41 @@ } try { // è·å AccessToken String accessToken = getAccessToken(); if (StringUtils.isEmpty(accessToken)) { JSONArray searchConditions = new JSONArray(); JSONObject condition = new JSONObject(); condition.put("key", "processApprovedResult"); JSONArray valueArray = new JSONArray(); valueArray.add("agree"); condition.put("value", valueArray); condition.put("type", "ARRAY"); condition.put("operator", "in"); condition.put("componentName", "SelectField"); searchConditions.add(condition); String searchFieldJson = searchConditions.toJSONString(); JSONArray dataArr = AliDingUtils.getFormDataList(aliDingConfig, aliDingConfig.getProducePlanFormUuid(), searchFieldJson, this, ProductionPlan::getFormModifiedTime); if (dataArr.isEmpty()) { log.info("æ²¡ææ´å¤æ°æ°æ®éè¦åæ¥"); return; } // è·åæ¬å°æå忥æ¶é´ LocalDateTime lastSyncTime = getLastSyncTime(); log.info("å¼å§å¢éåæ¥ï¼æ¬å°æåä¿®æ¹æ¶é´: {}", lastSyncTime); int pageNumber = 1; int pageSize = 50; boolean hasMore = true; int totalSynced = 0; while (hasMore) { // æ¥è¯¢åæ° JSONObject searchParam = buildSearchParam(lastSyncTime, pageNumber, pageSize); // è°ç¨å®ææ¥å£æåæ°æ® String dataRes = HttpUtils.sendPostJson( aliDingConfig.getSearchFormDataUrl(), searchParam.toJSONString(), StandardCharsets.UTF_8.name(), null, accessToken ); if (StringUtils.isEmpty(dataRes)) { log.warn("第 {} 页æåæ°æ®ä¸ºç©º", pageNumber); break; } JSONObject resultObj = JSON.parseObject(dataRes); JSONArray dataArr = resultObj.getJSONArray("data"); Integer totalCount = resultObj.getInteger("totalCount"); if (dataArr == null || dataArr.isEmpty()) { log.info("æ²¡ææ´å¤æ°æ°æ®éè¦åæ¥"); break; } // è§£æå¹¶ä¿åæ°æ® List<ProductionPlan> list = parseProductionPlans(dataArr, dataSyncType, totalCount); if (!list.isEmpty()) { // å¤çæ´æ°ææ°å¢ int affected = processSaveOrUpdate(list); totalSynced += affected; } // 夿æ¯å¦è¿æä¸ä¸é¡µ hasMore = (pageNumber * pageSize) < totalCount; pageNumber++; log.info("æ£å¨åæ¥ç¬¬ {} 页ï¼å½å已忥 {}/{}", pageNumber - 1, totalSynced, totalCount); // è§£æå¹¶ä¿åæ°æ® List<ProductionPlan> list = parseProductionPlans(dataArr, dataSyncType, dataArr.size()); if (!list.isEmpty()) { // å¤çæ´æ°ææ°å¢ int affected = processSaveOrUpdate(list); log.info("æ°æ®åæ¥å®æï¼å ±åæ¥ {} æ¡æ°æ®", affected); } log.info("æ°æ®åæ¥å®æï¼å ±åæ¥ {} æ¡æ°æ®", totalSynced); } catch (Exception e) { log.error("忥ç产计åå¼å¸¸", e); } finally { // éæ¾é syncLock.unlock(); } } private String getAccessToken() { String params = "appkey=" + aliDingConfig.getAppKey() + "&appsecret=" + aliDingConfig.getAppSecret(); String tokenRes = HttpUtils.sendGet(aliDingConfig.getAccessTokenUrl(), params); JSONObject tokenObj = JSON.parseObject(tokenRes); String accessToken = tokenObj.getString("access_token"); if (StringUtils.isEmpty(accessToken)) { log.error("è·åééAccessToken失败: {}", tokenRes); } return accessToken; } private LocalDateTime getLastSyncTime() { // æ¥è¯¢æ¬å°æ°æ®åºä¸ formModifiedTime æå¤§çè®°å½ LambdaQueryWrapper<ProductionPlan> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.orderByDesc(ProductionPlan::getFormModifiedTime).last("LIMIT 1"); ProductionPlan lastRecord = this.getOne(queryWrapper); return lastRecord != null ? lastRecord.getFormModifiedTime() : null; } private JSONObject buildSearchParam(LocalDateTime lastSyncTime, int pageNumber, int pageSize) { JSONObject searchParam = new JSONObject(); searchParam.put("appType", aliDingConfig.getAppType()); searchParam.put("systemToken", aliDingConfig.getSystemToken()); searchParam.put("userId", aliDingConfig.getUserId()); searchParam.put("formUuid", aliDingConfig.getProducePlanFormUuid()); searchParam.put("currentPage", pageNumber); searchParam.put("pageSize", pageSize); JSONArray searchConditions = new JSONArray(); JSONObject condition = new JSONObject(); condition.put("key", "processApprovedResult"); JSONArray valueArray = new JSONArray(); valueArray.add("agree"); condition.put("value", valueArray); condition.put("type", "ARRAY"); condition.put("operator", "in"); condition.put("componentName", "SelectField"); searchConditions.add(condition); searchParam.put("searchFieldJson", searchConditions.toJSONString()); // é»è®¤æä¿®æ¹æ¶é´ååºæåºï¼ç¡®ä¿å页æåæ°æ®çè¿ç»æ§ // "+" 表示ååºï¼"gmt_modified" æ¯å®æ¹å ç½®åæ®µ searchParam.put("orderConfigJson", "{\"gmt_modified\":\"+\"}"); // è®¾ç½®ä¿®æ¹æ¶é´çéåºé´ (æ ¼å¼å¿ 须为yyyy-MM-dd HH:mm:ss) if (lastSyncTime != null) { // èµ·å§æ¶é´ï¼ä¸æ¬¡åæ¥å°çæå䏿¡æ°æ®çä¿®æ¹æ¶é´ String startTime = lastSyncTime.plusSeconds(1).atZone(ZoneId.systemDefault()) .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); searchParam.put("modifiedFromTimeGMT", startTime); } // æªæ¢æ¶é´ï¼å½åæ¶é´ï¼ç¡®ä¿è·åææ°ç已修æ¹/å·²æ°å¢æ°æ® String endTime = LocalDateTime.now().atZone(ZoneId.systemDefault()) .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); searchParam.put("modifiedToTimeGMT", endTime); return searchParam; } private List<ProductionPlan> parseProductionPlans(JSONArray dataArr, Integer dataSyncType, Integer totalCount) { @@ -458,8 +363,8 @@ plan.setModifierName(modifyUser.getJSONObject("userName").getString("nameInChinese")); } plan.setFormCreatedTime(parseUtcTime(item.getString("createdTimeGMT"))); plan.setFormModifiedTime(parseUtcTime(item.getString("modifiedTimeGMT"))); plan.setFormCreatedTime(AliDingUtils.parseUtcTime(item.getString("createdTimeGMT"))); plan.setFormModifiedTime(AliDingUtils.parseUtcTime(item.getString("modifiedTimeGMT"))); plan.setDataSourceType(DataSourceTypeEnum.DING_TALK.getCode()); plan.setCreateTime(now); plan.setUpdateTime(now); @@ -513,19 +418,6 @@ } } return affected; } private LocalDateTime parseUtcTime(String utcString) { if (StringUtils.isEmpty(utcString)) { return null; } try { OffsetDateTime odt = OffsetDateTime.parse(utcString); return odt.toLocalDateTime(); } catch (DateTimeParseException ex) { log.warn("è§£ææ¶é´ {} 失败: {}", utcString, ex.getMessage()); return null; } } @Override src/main/java/com/ruoyi/quality/pojo/QualityTestStandardBinding.java
@@ -32,6 +32,7 @@ private Integer id; @ApiModelProperty("产åID") //å®å¤-ä¸ç建æä½¿ç¨æ°ç产åè¡¨å ³èproduct_material_sku private Long productId; @ApiModelProperty("å ³èæ£æµæ å主表id") src/main/resources/application-zsjc.yml
@@ -32,6 +32,7 @@ app-type: "APP_UY8XMO7GNA8OF08EFNVQ" produce-plan-form-uuid: "FORM-4IA66891C5H3QWMDBSGO05C0OX9628GRPYF7L8" material-code-form-uuid: "FORM-8I666N718RW4ALO4ETYDDB0U6U8T3EIWTQ0ALL1" customer-code-form-uuid: "FORM-4V966QC1M8B5W4Q89M1VL4ZURJ6C3FVA021ALE" system-token: "4J766L91OFH3V612E7LG5B4DI8M13MQF9VF7LG4" # æ¥å£å°å access-token-url: "https://oapi.dingtalk.com/gettoken" @@ -264,4 +265,4 @@ file: temp-dir: /javaWork/product-inventory-management/file/temp/uploads upload-dir: /javaWork/product-inventory-management/file/prod/uploads upload-dir: /javaWork/product-inventory-management/file/prod/uploads src/main/resources/mapper/basic/BaseParamMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,25 @@ <?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="com.ruoyi.basic.mapper.BaseParamMapper"> <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.BaseParam"> <id column="id" property="id"/> <result column="param_key" property="paramKey"/> <result column="param_name" property="paramName"/> <result column="param_type" property="paramType"/> <result column="value_mode" property="valueMode"/> <result column="unit" property="unit"/> <result column="default_value" property="defaultValue"/> <result column="default_min" property="defaultMin"/> <result column="default_max" property="defaultMax"/> <result column="is_required" property="isRequired"/> <result column="remark" property="remark"/> <result column="create_user" property="createUser"/> <result column="create_time" property="createTime"/> <result column="update_user" property="updateUser"/> <result column="update_time" property="updateTime"/> <result column="tenant_id" property="tenantId"/> </resultMap> </mapper>