doc/ÄþÏÄ-ÖÐÊ¢½¨²Ä.sql
@@ -1,37 +1,56 @@ CREATE TABLE `production_plan` DROP TABLE IF EXISTS `production_plan`; CREATE TABLE production_plan ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'èªå¢ä¸»é®', `form_instance_id` VARCHAR(64) NOT NULL COMMENT '表åå®ä¾ID', `serial_no` VARCHAR(64) DEFAULT NULL COMMENT 'åæ®æµæ°´å·', `title` VARCHAR(128) DEFAULT NULL COMMENT 'åæ®æ é¢', `originator_user_id` VARCHAR(64) DEFAULT NULL COMMENT 'å起人ID', `originator_name` VARCHAR(64) DEFAULT NULL COMMENT 'å起人å§å', `biz_create_time` DATETIME DEFAULT NULL COMMENT 'åæ®å建æ¶é´', `project_name` VARCHAR(128) DEFAULT NULL COMMENT '项ç®åç§°', `batch_no` VARCHAR(128) DEFAULT NULL COMMENT 'æ¹æ¬¡å·', `contact_person` VARCHAR(128) DEFAULT NULL COMMENT 'è系人', `ext_text1` VARCHAR(128) DEFAULT NULL COMMENT 'é¢ç1', `ext_text2` VARCHAR(128) DEFAULT NULL COMMENT 'é¢ç2', `material_code` VARCHAR(64) DEFAULT NULL COMMENT 'ç©æç¼ç ', `material_category` VARCHAR(64) DEFAULT NULL COMMENT 'ç©æåç±»', `spec_desc` VARCHAR(128) DEFAULT NULL COMMENT 'è§æ ¼æè¿°', `grade_type` VARCHAR(32) DEFAULT NULL COMMENT 'ç级', `length` DECIMAL(10, 2) DEFAULT NULL COMMENT 'é¿åº¦', `width` DECIMAL(10, 2) DEFAULT NULL COMMENT '宽度', `thickness` DECIMAL(10, 2) DEFAULT NULL COMMENT 'å度', `quantity` INT DEFAULT NULL COMMENT 'æ°é', `volume` DECIMAL(10, 4) DEFAULT NULL COMMENT 'æ»ä½ç§¯', `date_start` DATETIME DEFAULT NULL COMMENT 'å¼å§æ¶é´', `date_end` DATETIME DEFAULT NULL COMMENT 'ç»ææ¶é´', `association_receipt` TEXT COMMENT 'å ³èåæ®', `data_sync_type` TINYINT DEFAULT 1 COMMENT 'æ°æ®æ¹å¼: 1=æå¨ 2=宿¶', `data_source_type` TINYINT DEFAULT 1 COMMENT 'æ°æ®æ¥æº: 1=éå®è®¢å 2=çäº§é¢æµ', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_form_instance_id` (`form_instance_id`) ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COMMENT = 'éå®çäº§éæ±'; id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主é®', form_instance_id VARCHAR(64) COMMENT '表åå®ä¾ID', serial_no VARCHAR(50) COMMENT 'æµæ°´å·', apply_no VARCHAR(100) COMMENT 'ç³è¯·åç¼å·', customer_name VARCHAR(200) COMMENT '客æ·åç§°', material_code VARCHAR(100) COMMENT 'ç©æç¼ç ', product_name VARCHAR(200) COMMENT '产ååç§°', product_spec VARCHAR(200) COMMENT '产åè§æ ¼', length INT COMMENT 'é¿', width INT COMMENT '宽', height INT COMMENT 'é«', quantity INT COMMENT 'åæ°', volume DECIMAL(10, 4) COMMENT 'æ¹æ°', strength VARCHAR(50) COMMENT '强度', start_date DATETIME COMMENT 'å¼å§æ¥æ', end_date DATETIME COMMENT 'ç»ææ¥æ', submitter VARCHAR(100) COMMENT 'æäº¤äºº', submit_org VARCHAR(200) COMMENT 'æäº¤äººç»ç»', remark_one TEXT COMMENT '夿³¨1', remark_two TEXT COMMENT '夿³¨2', creator_name VARCHAR(100) COMMENT 'å建人', modifier_name VARCHAR(100) COMMENT 'ä¿®æ¹äºº', form_created_time DATETIME COMMENT '表åå建æ¶é´', form_modified_time DATETIME COMMENT '表åä¿®æ¹æ¶é´', data_sync_type TINYINT DEFAULT 1 COMMENT 'æ°æ®åæ¥ç±»åï¼1=æå¨ 2=宿¶ä»»å¡', data_source_type TINYINT DEFAULT 1 COMMENT 'æ°æ®æ¥æºç±»åï¼1=éå®è®¢å 2=éå®é¢æµ', create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 'æ°æ®åºå建æ¶é´', update_time DATETIME COMMENT 'æ°æ®åºæ´æ°æ¶é´', INDEX idx_apply_no (apply_no), INDEX idx_serial_no (serial_no), INDEX idx_form_instance_id (form_instance_id), INDEX idx_material_code (material_code) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT ='éå®ç产计å'; CREATE TABLE `product-inventory-management-zsjc`.`energy` ( `id` int NOT NULL AUTO_INCREMENT, src/main/java/com/ruoyi/productionPlan/controller/ProductionPlanController.java
@@ -1,11 +1,11 @@ package com.ruoyi.productionPlan.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.productionPlan.dto.ProductionPlanDto; import com.ruoyi.productionPlan.service.ProductionPlanService; import com.ruoyi.productionPlan.service.impl.ProdDemandService; import com.ruoyi.staff.dto.StaffLeaveDto; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.GetMapping; @@ -36,4 +36,11 @@ public AjaxResult productionPlanListPage(Page page, ProductionPlanDto productionPlanDto) { return AjaxResult.success(productionPlanService.listPage(page, productionPlanDto)); } @GetMapping("/loadProdData") @Log(title = "æåéå®ç产计å", businessType = BusinessType.INSERT) public AjaxResult loadProdData() { productionPlanService.loadProdData(); return AjaxResult.success(); } } src/main/java/com/ruoyi/productionPlan/enums/DataSourceTypeEnum.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,39 @@ package com.ruoyi.productionPlan.enums; import lombok.Getter; /** * <br> * æ°æ®æ¥æºæ¹å¼æä¸¾ç±» * </br> * * @author deslrey * @version 1.0 * @since 2026/03/10 10:37 */ @Getter public enum DataSourceTypeEnum { SALES_ORDER(1, "éå®è®¢å"), PRODUCTION_FORECAST(2, "çäº§é¢æµ"); private final Integer code; private final String desc; DataSourceTypeEnum(Integer code, String desc) { this.code = code; this.desc = desc; } public static DataSourceTypeEnum getByCode(Integer code) { if (code == null) { return null; } for (DataSourceTypeEnum type : DataSourceTypeEnum.values()) { if (type.getCode().equals(code)) { return type; } } return null; } } src/main/java/com/ruoyi/productionPlan/enums/DataSyncTypeEnum.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,39 @@ package com.ruoyi.productionPlan.enums; import lombok.Getter; /** * <br> * æ°æ®æ¹å¼æä¸¾ç±» * </br> * * @author deslrey * @version 1.0 * @since 2026/03/10 10:36 */ @Getter public enum DataSyncTypeEnum { MANUAL(1, "æå¨"), SCHEDULED(2, "宿¶"); private final Integer code; private final String desc; DataSyncTypeEnum(Integer code, String desc) { this.code = code; this.desc = desc; } public static DataSyncTypeEnum getByCode(Integer code) { if (code == null) { return null; } for (DataSyncTypeEnum type : DataSyncTypeEnum.values()) { if (type.getCode().equals(code)) { return type; } } return null; } } src/main/java/com/ruoyi/productionPlan/pojo/ProductionPlan.java
@@ -23,7 +23,7 @@ public class ProductionPlan { /** * èªå¢ä¸»é® * ä¸»é® */ @TableId(type = IdType.AUTO) private Long id; @@ -34,55 +34,19 @@ private String formInstanceId; /** * åæ®æµæ°´å· * æµæ°´å· */ private String serialNo; /** * åæ®æ é¢ * ç³è¯·åç¼å· */ private String title; private String applyNo; /** * å起人ID * 客æ·åç§° */ private String originatorUserId; /** * å起人å§å */ private String originatorName; /** * åæ®å建æ¶é´ */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime bizCreateTime; /** * 项ç®åç§° */ private String projectName; /** * æ¹æ¬¡å· */ private String batchNo; /** * è系人 */ private String contactPerson; /** * é¢ç1 */ private String extText1; /** * é¢ç2 */ private String extText2; private String customerName; /** * ç©æç¼ç @@ -90,82 +54,118 @@ private String materialCode; /** * ç©æåç±» * 产ååç§° */ private String materialCategory; private String productName; /** * è§æ ¼æè¿° * 产åè§æ ¼ */ private String specDesc; private String productSpec; /** * ç级 * é¿ */ private String gradeType; private Integer length; /** * é¿åº¦ * 宽 */ private BigDecimal length; private Integer width; /** * 宽度 * é« */ private BigDecimal width; private Integer height; /** * å度 */ private BigDecimal thickness; /** * æ°é * åæ° */ private Integer quantity; /** * æ»ä½ç§¯ * æ¹æ° */ private BigDecimal volume; /** * å¼å§æ¶é´ * 强度 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime dateStart; private String strength; /** * ç»ææ¶é´ * å¼å§æ¥æ */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime dateEnd; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime startDate; /** * å ³èåæ® * ç»ææ¥æ */ private String associationReceipt; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime endDate; /** * æ°æ®æ¹å¼: 1=æå¨ 2=宿¶ * æäº¤äºº */ private String submitter; /** * æäº¤äººç»ç» */ private String submitOrg; /** * 夿³¨1 */ private String remarkOne; /** * 夿³¨2 */ private String remarkTwo; /** * å建人 */ private String creatorName; /** * ä¿®æ¹äºº */ private String modifierName; /** * 表åå建æ¶é´ */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime formCreatedTime; /** * 表åä¿®æ¹æ¶é´ */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime formModifiedTime; /** * æ°æ®åæ¥ç±»åï¼1=æå¨ 2=宿¶ä»»å¡ */ private Integer dataSyncType; /** * æ°æ®æ¥æº: 1=éå®è®¢å 2=çäº§é¢æµ * æ°æ®æ¥æºç±»åï¼1=éå®è®¢å 2=éå®é¢æµ */ private Integer dataSourceType; /** * å建æ¶é´ * æ°æ®åºå建æ¶é´ */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime createTime; /** * æ´æ°æ¶é´ * æ°æ®åºæ´æ°æ¶é´ */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime updateTime; } src/main/java/com/ruoyi/productionPlan/service/ProductionPlanService.java
@@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.productionPlan.dto.ProductionPlanDto; import com.ruoyi.productionPlan.pojo.ProductionPlan; import com.ruoyi.staff.dto.StaffLeaveDto; /** * <br> @@ -18,4 +17,14 @@ */ public interface ProductionPlanService extends IService<ProductionPlan> { IPage<ProductionPlanDto> listPage(Page page, ProductionPlanDto productionPlanDto); /** * æå¨åæ¥ */ void loadProdData(); /** * 宿¶åæ¥ */ void syncProdDataJob(); } src/main/java/com/ruoyi/productionPlan/service/impl/ProdDemandService.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/productionPlan/service/impl/ProductionPlanServiceImpl.java
@@ -1,8 +1,14 @@ 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.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.http.HttpUtils; import com.ruoyi.framework.config.AliDingConfig; import com.ruoyi.productionPlan.dto.ProductionPlanDto; import com.ruoyi.productionPlan.mapper.ProductionPlanMapper; import com.ruoyi.productionPlan.pojo.ProductionPlan; @@ -10,6 +16,16 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.nio.charset.StandardCharsets; import java.time.Instant; import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.ZoneId; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.List; /** * <br> @@ -24,6 +40,10 @@ @Slf4j @Service public class ProductionPlanServiceImpl extends ServiceImpl<ProductionPlanMapper, ProductionPlan> implements ProductionPlanService { @Autowired private AliDingConfig aliDingConfig; @Autowired private ProductionPlanMapper productionPlanMapper; @@ -31,4 +51,181 @@ public IPage<ProductionPlanDto> listPage(Page page, ProductionPlanDto productionPlanDto) { return productionPlanMapper.listPage(page, productionPlanDto); } /** * 页颿å¨åæ¥ */ @Override public void loadProdData() { syncProdData(1); } /** * 宿¶ä»»å¡åæ¥ */ @Override public void syncProdDataJob() { syncProdData(2); } /** * åæ¥æ°æ® */ @Transactional(rollbackFor = Exception.class) public void syncProdData(Integer dataSyncType) { try { // è·åAccessToken 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; } log.info("è·åAccessTokenæå: {}", accessToken); // æ¥è¯¢è¡¨åæ°æ® JSONObject searchParam = new JSONObject(); searchParam.put("appType", aliDingConfig.getAppType()); searchParam.put("systemToken", aliDingConfig.getSystemToken()); searchParam.put("userId", aliDingConfig.getUserId()); searchParam.put("formUuid", aliDingConfig.getFormUuid()); String dataRes = HttpUtils.sendPostJson( aliDingConfig.getSearchFormDataUrl(), searchParam.toJSONString(), StandardCharsets.UTF_8.name(), null, accessToken ); if (StringUtils.isEmpty(dataRes)) { log.error("æåå®ææ°æ®ä¸ºç©º"); return; } JSONObject resultObj = JSON.parseObject(dataRes); JSONArray dataArr = resultObj.getJSONArray("data"); if (dataArr == null || dataArr.isEmpty()) { log.warn("没æè·åå°è¡¨åæ°æ®"); return; } List<ProductionPlan> list = new ArrayList<>(); // è§£æè¡¨å for (int i = 0; i < dataArr.size(); i++) { JSONObject item = dataArr.getJSONObject(i); String formInstanceId = item.getString("formInstanceId"); String serialNo = item.getString("serialNo"); // å起人 JSONObject originator = item.getJSONObject("originator"); String originatorName = originator.getJSONObject("userName").getString("nameInChinese"); JSONObject formData = item.getJSONObject("formData"); // æç»è¡¨ JSONArray tableArr = formData.getJSONArray("tableField_l7fytfcn"); if (tableArr == null || tableArr.isEmpty()) { continue; } // è§£ææç» for (int j = 0; j < tableArr.size(); j++) { JSONObject row = tableArr.getJSONObject(j); ProductionPlan plan = new ProductionPlan(); // 表åä¿¡æ¯ plan.setFormInstanceId(formInstanceId); plan.setSerialNo(serialNo); // è¡¨å¤´åæ®µ plan.setApplyNo(formData.getString("textField_l7fytfco")); plan.setCustomerName(formData.getString("textField_lbkozohg")); // æç»å段 plan.setMaterialCode(row.getString("textField_l9xo62q5")); plan.setProductName(row.getString("textField_l9xo62q7")); plan.setProductSpec(row.getString("textField_l9xo62q8")); plan.setLength(row.getInteger("numberField_lb7lgatg_value")); plan.setWidth(row.getInteger("numberField_lb7lgath_value")); plan.setHeight(row.getInteger("numberField_lb7lgati_value")); plan.setQuantity(row.getInteger("numberField_lb7lgatj_value")); plan.setVolume(row.getBigDecimal("numberField_l7fytfd3_value")); plan.setStrength(row.getString("radioField_m9urarr2_id")); // æ¥æåºé´ JSONArray dateArr = row.getJSONArray("cascadeDateField_lfxqqluw"); if (dateArr != null && dateArr.size() == 2) { long start = Long.parseLong(dateArr.getString(0)); long end = Long.parseLong(dateArr.getString(1)); plan.setStartDate(Instant.ofEpochMilli(start) .atZone(ZoneId.systemDefault()) .toLocalDateTime()); plan.setEndDate(Instant.ofEpochMilli(end) .atZone(ZoneId.systemDefault()) .toLocalDateTime()); } // æäº¤äºº plan.setSubmitter(originatorName); // ç»ç» plan.setSubmitOrg("å®å¤ä¸å绿è½å®ä¸é墿éå ¬å¸"); // 夿³¨ plan.setRemarkOne(formData.getString("textareaField_l7fytfcy")); plan.setRemarkTwo(formData.getString("textField_l7fytfcx")); // å建人 plan.setCreatorName(originatorName); // ä¿®æ¹äºº JSONObject modifyUser = item.getJSONObject("modifyUser"); if (modifyUser != null) { plan.setModifierName(modifyUser.getJSONObject("userName").getString("nameInChinese")); } // è¡¨åæ¶é´ plan.setFormCreatedTime(parseUtcTime(item.getString("createdTimeGMT"))); plan.setFormModifiedTime(parseUtcTime(item.getString("modifiedTimeGMT"))); // åæ¥ä¿¡æ¯ plan.setDataSyncType(dataSyncType); plan.setDataSourceType(1); // æ°æ®åºæ¶é´ LocalDateTime now = LocalDateTime.now(); plan.setCreateTime(now); plan.setUpdateTime(now); list.add(plan); } } if (!list.isEmpty()) { saveBatch(list); } log.info("ç产计å忥宿ï¼å ± {} æ¡", list.size()); } catch (Exception e) { log.error("忥ç产计åå¼å¸¸", e); } } 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; } } } src/main/resources/mapper/productionPlan/ProductionPlanMapper.xml
@@ -9,37 +9,38 @@ <id property="id" column="id"/> <result property="formInstanceId" column="form_instance_id"/> <result property="serialNo" column="serial_no"/> <result property="title" column="title"/> <result property="originatorUserId" column="originator_user_id"/> <result property="originatorName" column="originator_name"/> <result property="bizCreateTime" column="biz_create_time"/> <result property="projectName" column="project_name"/> <result property="batchNo" column="batch_no"/> <result property="contactPerson" column="contact_person"/> <result property="extText1" column="ext_text1"/> <result property="extText2" column="ext_text2"/> <result property="applyNo" column="apply_no"/> <result property="customerName" column="customer_name"/> <result property="materialCode" column="material_code"/> <result property="materialCategory" column="material_category"/> <result property="specDesc" column="spec_desc"/> <result property="gradeType" column="grade_type"/> <result property="productName" column="product_name"/> <result property="productSpec" column="product_spec"/> <result property="length" column="length"/> <result property="width" column="width"/> <result property="thickness" column="thickness"/> <result property="height" column="height"/> <result property="quantity" column="quantity"/> <result property="volume" column="volume"/> <result property="dateStart" column="date_start"/> <result property="dateEnd" column="date_end"/> <result property="associationReceipt" column="association_receipt"/> <result property="strength" column="strength"/> <result property="startDate" column="start_date"/> <result property="endDate" column="end_date"/> <result property="submitter" column="submitter"/> <result property="submitOrg" column="submit_org"/> <result property="remarkOne" column="remark_one"/> <result property="remarkTwo" column="remark_two"/> <result property="creatorName" column="creator_name"/> <result property="modifierName" column="modifier_name"/> <result property="formCreatedTime" column="form_created_time"/> <result property="formModifiedTime" column="form_modified_time"/> <result property="dataSyncType" column="data_sync_type"/> <result property="dataSourceType" column="data_source_type"/> <result property="createTime" column="create_time"/> <result property="updateTime" column="update_time"/> </resultMap> <select id="listPage" resultType="com.ruoyi.productionPlan.dto.ProductionPlanDto"> SELECT production_plan.* <select id="listPage" resultMap="ProductionPlanResultMap"> SELECT * FROM production_plan where 1=1 WHERE 1 = 1 </select> </mapper> src/test/com/ruoyi/productionPlan/service/ProdDemandServiceTest.java
ÎļþÒÑɾ³ý