| | |
| | | |
| | | 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`; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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("åæ°æ ¼å¼") |
| | | private String paramFormat; |
| | | |
| | | @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; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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> { |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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("åæ°æ ¼å¼") |
| | | private String paramFormat; |
| | | |
| | | @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; |
| | | } |
| | |
| | | @ApiModelProperty(value = "弿·è¡å·") |
| | | @Excel(name = "弿·è¡å·") |
| | | private String bankCode; |
| | | |
| | | @ApiModelProperty("å®æè¡¨åå®ä¾ID") |
| | | private String formInstanceId; |
| | | |
| | | @ApiModelProperty("å®æä¿®æ¹æ¶é´") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private LocalDateTime formModifiedTime; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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); |
| | | } |
| | |
| | | List<Customer> selectCustomerLists(Customer customer); |
| | | |
| | | AjaxResult importData(MultipartFile file); |
| | | |
| | | //åæ¥å®¢æ·æ°æ® |
| | | void syncCustomerJob(); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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)); |
| | | } |
| | | } |
| | |
| | | package com.ruoyi.basic.service.impl; |
| | | |
| | | |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.config.AliDingConfig; |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.framework.util.AliDingUtils; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.production.enums.MaterialConfigTypeEnum; |
| | | import com.ruoyi.production.pojo.ProductMaterial; |
| | | import com.ruoyi.production.pojo.ProductMaterialSku; |
| | | import com.ruoyi.productionPlan.enums.DataSourceTypeEnum; |
| | | import com.ruoyi.productionPlan.pojo.ProductionPlan; |
| | | import com.ruoyi.project.system.domain.SysUser; |
| | | import com.ruoyi.sales.mapper.SalesLedgerMapper; |
| | | import com.ruoyi.sales.pojo.SalesLedger; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.time.Instant; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.ZoneId; |
| | | import java.util.*; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | import java.util.stream.Collectors; |
| | | |
| | | |
| | |
| | | private CustomerFollowUpFileService customerFollowUpFileService; |
| | | |
| | | private CustomerReturnVisitService customerReturnVisitService; |
| | | |
| | | private AliDingConfig aliDingConfig; |
| | | |
| | | /** |
| | | * 忥éï¼é²æ¢æå¨å宿¶ä»»å¡åæ¶æ§è¡ |
| | | */ |
| | | private final ReentrantLock syncLock = new ReentrantLock(); |
| | | |
| | | /** |
| | | * æ¥è¯¢å®¢æ·æ¡£æ¡ |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void syncCustomerJob() { |
| | | syncCustomerData(2); |
| | | } |
| | | |
| | | @Override |
| | | public List<Map<String, Object>> customerList(Customer customer) { |
| | | LambdaQueryWrapper<Customer> queryWrapper = Wrappers.lambdaQuery(); |
| | | queryWrapper.select(Customer::getId, Customer::getCustomerName, Customer::getTaxpayerIdentificationNumber); |
| | |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * åæ¥æ°æ® |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void syncCustomerData(Integer dataSyncType) { |
| | | if (!syncLock.tryLock()) { |
| | | log.warn("忥æ£å¨è¿è¡ä¸ï¼æ¬æ¬¡ {} åæ¥è¯·æ±è¢«è·³è¿", dataSyncType == 1 ? "æå¨" : "宿¶ä»»å¡"); |
| | | return; |
| | | } |
| | | try { |
| | | 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.getCustomerCodeFormUuid(), searchFieldJson, this, Customer::getFormModifiedTime); |
| | | |
| | | if (dataArr.isEmpty()) { |
| | | log.info("æ²¡ææ´å¤æ°æ°æ®éè¦åæ¥"); |
| | | return; |
| | | } |
| | | |
| | | // è§£æå¹¶ä¿åæ°æ® |
| | | List<Customer> list = parseCustomer(dataArr); |
| | | if (!list.isEmpty()) { |
| | | // å¤çæ´æ°ææ°å¢ |
| | | int affected = processSaveOrUpdate(list); |
| | | log.info("å®¢æ·æ°æ®åæ¥å®æï¼å
±åæ¥ {} æ¡æ°æ®", affected); |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | log.error("忥客æ·ä¿¡æ¯å¼å¸¸", e); |
| | | } finally { |
| | | // éæ¾é |
| | | syncLock.unlock(); |
| | | } |
| | | } |
| | | |
| | | private List<Customer> parseCustomer(JSONArray dataArr) { |
| | | List<Customer> list = new ArrayList<>(); |
| | | for (int i = 0; i < dataArr.size(); i++) { |
| | | JSONObject item = dataArr.getJSONObject(i); |
| | | String formInstanceId = item.getString("formInstanceId"); |
| | | JSONObject formData = item.getJSONObject("formData"); |
| | | Customer customer = new Customer(); |
| | | customer.setCustomerName(formData.getString("textField_l7fwg8uh")); |
| | | customer.setTaxpayerIdentificationNumber(formData.getString("textField_l88df8ae")); |
| | | customer.setCompanyAddress(formData.getString("textField_l7fwg8uj")); |
| | | customer.setCompanyPhone(formData.getString("textField_lb38bng2")); |
| | | customer.setContactPerson(formData.getString("textField_l7fwg8ut")); |
| | | customer.setContactPhone(formData.getString("textField_l7fwg8uu")); |
| | | customer.setMaintainer("管çåè´¦å·"); |
| | | LocalDateTime dateTime = AliDingUtils.parseUtcTime(item.getString("modifiedTimeGMT")); |
| | | ZoneId zoneId = ZoneId.of("Asia/Shanghai"); |
| | | Date date = Date.from(dateTime.atZone(zoneId).toInstant()); |
| | | customer.setMaintenanceTime(date); |
| | | customer.setFormInstanceId(formInstanceId); |
| | | customer.setFormModifiedTime(dateTime); |
| | | list.add(customer); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | private int processSaveOrUpdate(List<Customer> list) { |
| | | if (list == null || list.isEmpty()) { |
| | | return 0; |
| | | } |
| | | int affected = 0; |
| | | |
| | | for (Customer customer : list) { |
| | | |
| | | LambdaQueryWrapper<Customer> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(Customer::getFormInstanceId, customer.getFormInstanceId()); |
| | | |
| | | Customer exist = this.getOne(wrapper); |
| | | if (exist == null) { |
| | | this.save(customer); |
| | | affected++; |
| | | log.info("æ°å¢å®¢æ·ä¿¡æ¯ {}", customer.getCustomerName()); |
| | | } else { |
| | | if (exist.getFormModifiedTime() == null || !exist.getFormModifiedTime().equals(customer.getFormModifiedTime())) { |
| | | customer.setId(exist.getId()); |
| | | this.updateById(customer); |
| | | affected++; |
| | | log.info("æ´æ°å®¢æ·ä¿¡æ¯ {}", customer.getCustomerName()); |
| | | } |
| | | } |
| | | } |
| | | return affected; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.basic.task; |
| | | |
| | | import com.ruoyi.basic.service.ICustomerService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | @Component |
| | | public class CustomerTask { |
| | | |
| | | @Autowired |
| | | private ICustomerService customerService; |
| | | |
| | | @Scheduled(cron = "0 0 * * * ?") |
| | | public void syncCustomerDataJob() { |
| | | customerService.syncCustomerJob(); |
| | | } |
| | | } |
| | |
| | | private String materialCodeFormUuid; |
| | | |
| | | /** |
| | | * 客æ·ä¿¡æ¯-å®æè¡¨åID |
| | | */ |
| | | private String customerCodeFormUuid; |
| | | |
| | | /** |
| | | * 宿åºç¨å¯é¥ |
| | | * ç¨äºè®¿é®å®æè¡¨å API |
| | | */ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | private Long id; |
| | | |
| | | @ApiModelProperty(value = "产åID") |
| | | //product_model |
| | | //å®å¤-ä¸ç建æä½¿ç¨æ°ç产å表å
³èproduct_material_sku |
| | | private Long productModelId; |
| | | |
| | | @ApiModelProperty(value = "æè¿°") |
| | |
| | | private Long processId; |
| | | |
| | | @ApiModelProperty(value ="产åid") |
| | | //å®å¤-ä¸ç建æä½¿ç¨æ°ç产å表å
³èproduct_material_sku |
| | | private Long productModelId; |
| | | |
| | | @ApiModelProperty(value = "ç§æ·ID") |
| | |
| | | private String bomNo; |
| | | |
| | | @ApiModelProperty("产åè§æ ¼id") |
| | | //å®å¤-ä¸ç建æä½¿ç¨æ°ç产å表å
³èproduct_material_sku |
| | | private Long productModelId; |
| | | |
| | | @ApiModelProperty("夿³¨") |
| | |
| | | private Long id; |
| | | |
| | | @ApiModelProperty("产åid") |
| | | //product_model |
| | | //å®å¤-ä¸ç建æä½¿ç¨æ°ç产å表å
³èproduct_material_sku |
| | | private Long productModelId; |
| | | |
| | | @ApiModelProperty("æè¿°") |
| | |
| | | private Long processId; |
| | | |
| | | @ApiModelProperty(value ="产åid") |
| | | //å®å¤-ä¸ç建æä½¿ç¨æ°ç产å表å
³èproduct_material_sku |
| | | private Long productModelId; |
| | | |
| | | @ApiModelProperty(value = "ç§æ·ID") |
| | |
| | | /** |
| | | * 产ååç§° |
| | | */ |
| | | //å®å¤-ä¸ç建æä½¿ç¨æ°ç产å表å
³èproduct_material_sku |
| | | private Long productModelId; |
| | | |
| | | /** |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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; |
| | | |
| | |
| | | } |
| | | |
| | | 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) { |
| | |
| | | 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); |
| | | |
| | |
| | | } |
| | | } |
| | | 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 |
| | |
| | | */ |
| | | @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()) { |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | |
| | | 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; |
| | |
| | | } |
| | | |
| | | 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) { |
| | |
| | | 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); |
| | |
| | | } |
| | | } |
| | | 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 |
| | |
| | | private Integer id; |
| | | |
| | | @ApiModelProperty("产åID") |
| | | //å®å¤-ä¸ç建æä½¿ç¨æ°ç产å表å
³èproduct_material_sku |
| | | private Long productId; |
| | | |
| | | @ApiModelProperty("å
³èæ£æµæ å主表id") |
| | |
| | | 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" |
| | |
| | | |
| | | 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 |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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="param_format" property="paramFormat"/> |
| | | <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> |