diff --git a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/enums/OrderPlateTypeEnum.java b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/enums/OrderPlateTypeEnum.java new file mode 100644 index 000000000..cd02d4f5e --- /dev/null +++ b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/enums/OrderPlateTypeEnum.java @@ -0,0 +1,29 @@ +package com.cf.imes.framework.common.enums; + + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum OrderPlateTypeEnum { + + + LAYERBOARD(0, "层板"), + RISER(1, "立板"), + BACKBOARD(2, "背板"), + SELFINCREASINGBOARD(3, "自增板"); + + private final Integer type; + private String description; + + public boolean equals(Integer status) { + return this.type .equals(status) ; + } + + public boolean equals(OrderPlateTypeEnum enableStatusEnum) { + return enableStatusEnum != null && enableStatusEnum.type .equals(this.getType()) ; + } + + +} diff --git a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/enums/PlanStatusEnum.java b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/enums/PlanStatusEnum.java index 8d591adce..c9c2625ae 100644 --- a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/enums/PlanStatusEnum.java +++ b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/enums/PlanStatusEnum.java @@ -9,10 +9,11 @@ import lombok.Getter; public enum PlanStatusEnum { - NEWORDER(0,"新单"), - BOARDHASBEENAPPLIEDFOR(1,"板材已申请"), - DURINGCUTTING(2,"开料中"), - OPENEDMATERIAL(3,"已开料"); + NOCUTTING(0, "未开料"), + + OPENING(1, "开料中"), + + OPENED(2, "已开料"); private Integer status; private String scheduling; diff --git a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/exception/enums/GlobalErrorCodeConstants.java b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/exception/enums/GlobalErrorCodeConstants.java index a31e456ec..586bc20fd 100644 --- a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/exception/enums/GlobalErrorCodeConstants.java +++ b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/exception/enums/GlobalErrorCodeConstants.java @@ -33,6 +33,8 @@ public interface GlobalErrorCodeConstants { ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常"); ErrorCode NOT_IMPLEMENTED = new ErrorCode(501, "功能未实现/未开启"); ErrorCode ERROR_CONFIGURATION = new ErrorCode(502, "错误的配置项"); + ErrorCode ES_ERROR_UPDATE = new ErrorCode(503, "ES文档更新失败"); + ErrorCode ES_ERROR_DELETE = new ErrorCode(504, "ES文档删除失败"); // ========== 自定义错误段 ========== ErrorCode REPEATED_REQUESTS = new ErrorCode(900, "重复请求,请稍后重试"); // 重复请求 diff --git a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/encrypt/AesUtils.java b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/encrypt/AesUtils.java new file mode 100644 index 000000000..77a3b4733 --- /dev/null +++ b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/encrypt/AesUtils.java @@ -0,0 +1,99 @@ +package com.cf.imes.framework.common.util.encrypt; + +import cn.hutool.core.util.CharsetUtil; +import lombok.extern.slf4j.Slf4j; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import java.security.GeneralSecurityException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Base64; + +/** + * AES对称加密工具 + * + * @author Gqr + * @since 2024/8/23 16:38 + */ +@Slf4j +public class AesUtils { + + private static final String AES_ALG = "AES"; + + private static final String AES_CBC_PCK_ALG = "AES/CBC/PKCS5Padding"; + + + /** + * 解密 + * + * @param content + * @param aesKey + * @return + * @throws Exception + */ + public static String decrypt(String content, String aesKey) { + try { + Cipher cipher = Cipher.getInstance(AES_CBC_PCK_ALG); + IvParameterSpec iv = new IvParameterSpec(initIv(AES_CBC_PCK_ALG)); + cipher.init(Cipher.DECRYPT_MODE, generateKey(aesKey.getBytes()), iv); + + byte[] cleanBytes = cipher.doFinal(Base64.getDecoder().decode(content.getBytes())); + return new String(cleanBytes, CharsetUtil.UTF_8); + } catch (Exception e) { + log.error("[AesUtils][decrypt]解密失败:{}", e.getMessage(), e); + // nacos热发布配置,空字符串会导致nacos轮训刷新配置 + return "default"; + } + } + + /** + * 生成key + * + * @param bytes + * @return + * @throws NoSuchAlgorithmException + */ + private static SecretKey generateKey(byte[] bytes) throws NoSuchAlgorithmException { + // 生成随机数 + SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); + // 设置随机数种子 + random.setSeed(bytes); + + // aes算法生成器 + KeyGenerator keyGen = KeyGenerator.getInstance(AES_ALG); + keyGen.init(128, random); // 使用128位的密钥 + return keyGen.generateKey(); + } + + + /** + * 初始向量的方法, 全部为0. 这里的写法适合于其它算法,针对AES算法的话,IV值一定是128位的(16字节). + * + * @param fullAlg + * @return + * @throws GeneralSecurityException + */ + private static byte[] initIv(String fullAlg) { + + try { + Cipher cipher = Cipher.getInstance(fullAlg); + int blockSize = cipher.getBlockSize(); + byte[] iv = new byte[blockSize]; + for (int i = 0; i < blockSize; ++i) { + iv[i] = 0; + } + return iv; + } catch (Exception e) { + + int blockSize = 16; + byte[] iv = new byte[blockSize]; + for (int i = 0; i < blockSize; ++i) { + iv[i] = 0; + } + return iv; + } + } +} diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/config/ChenfengSmsAutoConfiguration.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/config/ChenfengSmsAutoConfiguration.java index cd1ad245f..350085d23 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/config/ChenfengSmsAutoConfiguration.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/config/ChenfengSmsAutoConfiguration.java @@ -2,7 +2,9 @@ package com.cf.imes.framework.sms.config; import com.cf.imes.framework.sms.core.client.SmsClientFactory; import com.cf.imes.framework.sms.core.client.impl.SmsClientFactoryImpl; +import com.cf.imes.framework.sms.core.property.SmsProperties; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; /** @@ -11,11 +13,12 @@ import org.springframework.context.annotation.Bean; * @author 晨丰科技 */ @AutoConfiguration +@EnableConfigurationProperties(SmsProperties.class) public class ChenfengSmsAutoConfiguration { @Bean - public SmsClientFactory smsClientFactory() { - return new SmsClientFactoryImpl(); + public SmsClientFactory smsClientFactory(SmsProperties smsProperties) { + return new SmsClientFactoryImpl(smsProperties); } } diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClient.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClient.java index ae9d8ba0c..0ee4eeba4 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClient.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClient.java @@ -14,14 +14,6 @@ import java.util.List; * @since 2021/1/25 14:14 */ public interface SmsClient { - - /** - * 获得渠道编号 - * - * @return 渠道编号 - */ - Long getId(); - /** * 发送消息 * diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClientFactory.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClientFactory.java index b6d6b04e9..519827e02 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClientFactory.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClientFactory.java @@ -1,6 +1,6 @@ package com.cf.imes.framework.sms.core.client; -import com.cf.imes.framework.sms.core.property.SmsChannelProperties; +import com.cf.imes.framework.sms.core.property.SmsProperties; /** * 短信客户端的工厂接口 @@ -9,15 +9,6 @@ import com.cf.imes.framework.sms.core.property.SmsChannelProperties; * @since 2021/1/28 14:01 */ public interface SmsClientFactory { - - /** - * 获得短信 Client - * - * @param channelId 渠道编号 - * @return 短信 Client - */ - SmsClient getSmsClient(Long channelId); - /** * 获得短信 Client * @@ -27,10 +18,11 @@ public interface SmsClientFactory { SmsClient getSmsClient(String channelCode); /** - * 创建短信 Client + * 获得短信 Client * - * @param properties 配置对象 + * @param smsProperties 短信配置 + * @return 短信 Client */ - void createOrUpdateSmsClient(SmsChannelProperties properties); + SmsClient getSmsClient(SmsProperties smsProperties); } diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/dto/SmsSendRespDTO.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/dto/SmsSendRespDTO.java index 6891cbdb1..293d1557c 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/dto/SmsSendRespDTO.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/dto/SmsSendRespDTO.java @@ -40,4 +40,13 @@ public class SmsSendRespDTO { */ private String apiMsg; + /** + * 短信发送的目标手机号 + */ + private String mobile; + + /** + * 渠道编码 + */ + private String channelCode; } diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/AbstractSmsClient.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/AbstractSmsClient.java index df1ff5bcb..9f61ddb99 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/AbstractSmsClient.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/AbstractSmsClient.java @@ -1,7 +1,7 @@ package com.cf.imes.framework.sms.core.client.impl; import com.cf.imes.framework.sms.core.client.SmsClient; -import com.cf.imes.framework.sms.core.property.SmsChannelProperties; +import com.cf.imes.framework.sms.core.property.SmsProperties; import lombok.extern.slf4j.Slf4j; /** @@ -16,9 +16,9 @@ public abstract class AbstractSmsClient implements SmsClient { /** * 短信渠道配置 */ - protected volatile SmsChannelProperties properties; + protected volatile SmsProperties properties; - public AbstractSmsClient(SmsChannelProperties properties) { + public AbstractSmsClient(SmsProperties properties) { this.properties = properties; } @@ -35,7 +35,15 @@ public abstract class AbstractSmsClient implements SmsClient { */ protected abstract void doInit(); - public final void refresh(SmsChannelProperties properties) { + /** + * 配置是否发生改变 + * + * @param properties + * @return + */ + protected abstract boolean propChanged(SmsProperties properties); + + public final void refresh(SmsProperties properties) { // 判断是否更新 if (properties.equals(this.properties)) { return; @@ -46,9 +54,4 @@ public abstract class AbstractSmsClient implements SmsClient { this.init(); } - @Override - public Long getId() { - return properties.getId(); - } - } diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/SmsClientFactoryImpl.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/SmsClientFactoryImpl.java index a5779e0da..668198df1 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/SmsClientFactoryImpl.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/SmsClientFactoryImpl.java @@ -1,5 +1,6 @@ package com.cf.imes.framework.sms.core.client.impl; +import cn.hutool.core.util.ObjectUtil; import com.cf.imes.framework.sms.core.client.SmsClient; import com.cf.imes.framework.sms.core.client.SmsClientFactory; import com.cf.imes.framework.sms.core.client.impl.aliyun.AliyunSmsClient; @@ -7,11 +8,12 @@ import com.cf.imes.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient; import com.cf.imes.framework.sms.core.client.impl.tencent.TencentSmsClient; import com.cf.imes.framework.sms.core.enums.SmsChannelEnum; import com.cf.imes.framework.sms.core.property.SmsChannelProperties; +import com.cf.imes.framework.sms.core.property.SmsProperties; import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; import org.springframework.util.Assert; import org.springframework.validation.annotation.Validated; -import java.util.Arrays; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -22,14 +24,9 @@ import java.util.concurrent.ConcurrentMap; */ @Validated @Slf4j +@Service public class SmsClientFactoryImpl implements SmsClientFactory { - /** - * 短信客户端 Map - * key:渠道编号,使用 {@link SmsChannelProperties#getId()} - */ - private final ConcurrentMap channelIdClients = new ConcurrentHashMap<>(); - /** * 短信客户端 Map * key:渠道编码,使用 {@link SmsChannelProperties#getCode()} ()} @@ -39,21 +36,24 @@ public class SmsClientFactoryImpl implements SmsClientFactory { */ private final ConcurrentMap channelCodeClients = new ConcurrentHashMap<>(); - public SmsClientFactoryImpl() { - // 初始化 channelCodeClients 集合 - Arrays.stream(SmsChannelEnum.values()).forEach(channel -> { - // 创建一个空的 SmsChannelProperties 对象 - SmsChannelProperties properties = new SmsChannelProperties().setCode(channel.getCode()) - .setApiKey("default default").setApiSecret("default"); - // 创建 Sms 客户端 - AbstractSmsClient smsClient = createSmsClient(properties); - channelCodeClients.put(channel.getCode(), smsClient); - }); + public SmsClientFactoryImpl(SmsProperties smsProperties) { + // 从配置初始化对应的client客户端 + AbstractSmsClient client = createSmsClient(smsProperties); + client.init(); + channelCodeClients.put(smsProperties.getChannel(), client); } @Override - public SmsClient getSmsClient(Long channelId) { - return channelIdClients.get(channelId); + public SmsClient getSmsClient(SmsProperties smsProperties) { + String channel = smsProperties.getChannel(); + AbstractSmsClient client = channelCodeClients.get(channel); + // 1、新的短信类型;2、配置改变 + if (ObjectUtil.isNull(client) || client.propChanged(smsProperties)) { + client = this.createSmsClient(smsProperties); + client.init(); + channelCodeClients.put(channel, client); + } + return client; } @Override @@ -61,30 +61,19 @@ public class SmsClientFactoryImpl implements SmsClientFactory { return channelCodeClients.get(channelCode); } - @Override - public void createOrUpdateSmsClient(SmsChannelProperties properties) { - AbstractSmsClient client = channelIdClients.get(properties.getId()); - if (client == null) { - client = this.createSmsClient(properties); - client.init(); - channelIdClients.put(client.getId(), client); - } else { - client.refresh(properties); - } - } - - private AbstractSmsClient createSmsClient(SmsChannelProperties properties) { - SmsChannelEnum channelEnum = SmsChannelEnum.getByCode(properties.getCode()); - Assert.notNull(channelEnum, String.format("渠道类型(%s) 为空", channelEnum)); + private AbstractSmsClient createSmsClient(SmsProperties smsProperties) { + String channel = smsProperties.getChannel(); + SmsChannelEnum channelEnum = SmsChannelEnum.getByCode(channel); + Assert.notNull(channelEnum, String.format("渠道类型(%s) 为空", channel)); // 创建客户端 switch (channelEnum) { - case ALIYUN: return new AliyunSmsClient(properties); - case DEBUG_DING_TALK: return new DebugDingTalkSmsClient(properties); - case TENCENT: return new TencentSmsClient(properties); + case ALIYUN: return new AliyunSmsClient(smsProperties); + case DEBUG_DING_TALK: return new DebugDingTalkSmsClient(smsProperties); + case TENCENT: return new TencentSmsClient(smsProperties); } // 创建失败,错误日志 + 抛出异常 - log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", properties); - throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", properties)); + log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", smsProperties); + throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", smsProperties)); } } diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java index 2a4c063f1..f5194faa0 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java @@ -1,6 +1,8 @@ package com.cf.imes.framework.sms.core.client.impl.aliyun; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjectUtil; +import com.aliyuncs.auth.Credential; import com.cf.imes.framework.common.core.KeyValue; import com.cf.imes.framework.common.util.collection.MapUtils; import com.cf.imes.framework.common.util.json.JsonUtils; @@ -9,7 +11,6 @@ import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; import com.cf.imes.framework.sms.core.client.dto.SmsTemplateRespDTO; import com.cf.imes.framework.sms.core.client.impl.AbstractSmsClient; import com.cf.imes.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import com.cf.imes.framework.sms.core.property.SmsChannelProperties; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; @@ -18,6 +19,7 @@ import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; import com.aliyuncs.profile.DefaultProfile; import com.aliyuncs.profile.IClientProfile; +import com.cf.imes.framework.sms.core.property.SmsProperties; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.annotations.VisibleForTesting; @@ -56,7 +58,7 @@ public class AliyunSmsClient extends AbstractSmsClient { */ private volatile IAcsClient client; - public AliyunSmsClient(SmsChannelProperties properties) { + public AliyunSmsClient(SmsProperties properties) { super(properties); Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); @@ -68,6 +70,23 @@ public class AliyunSmsClient extends AbstractSmsClient { client = new DefaultAcsClient(profile); } + @Override + protected boolean propChanged(SmsProperties properties) { + DefaultAcsClient defaultAcsClient = (DefaultAcsClient) client; + if (ObjectUtil.isNotNull(defaultAcsClient)) { + Credential credential = defaultAcsClient.getProfile().getCredential(); + String accessKeyId = credential.getAccessKeyId(); + if (ObjectUtil.notEqual(properties.getApiKey(), accessKeyId)) { + return true; + } + String accessSecret = credential.getAccessSecret(); + if (ObjectUtil.notEqual(properties.getApiSecret(), accessSecret)) { + return true; + } + } + return false; + } + @Override public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, List> templateParams) throws Throwable { @@ -81,7 +100,7 @@ public class AliyunSmsClient extends AbstractSmsClient { // 执行请求 SendSmsResponse response = client.getAcsResponse(request); return new SmsSendRespDTO().setSuccess(Objects.equals(response.getCode(), API_CODE_SUCCESS)).setSerialNo(response.getBizId()) - .setApiRequestId(response.getRequestId()).setApiCode(response.getCode()).setApiMsg(response.getMessage()); + .setApiRequestId(response.getRequestId()).setApiCode(response.getCode()).setApiMsg(response.getMessage()).setChannelCode(properties.getChannel()); } @Override diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java index 0144e54bc..e329351dd 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java @@ -3,6 +3,7 @@ package com.cf.imes.framework.sms.core.client.impl.debug; import cn.hutool.core.codec.Base64; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; import cn.hutool.crypto.digest.HmacAlgorithm; @@ -15,7 +16,7 @@ import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; import com.cf.imes.framework.sms.core.client.dto.SmsTemplateRespDTO; import com.cf.imes.framework.sms.core.client.impl.AbstractSmsClient; import com.cf.imes.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import com.cf.imes.framework.sms.core.property.SmsChannelProperties; +import com.cf.imes.framework.sms.core.property.SmsProperties; import java.util.HashMap; import java.util.List; @@ -31,7 +32,7 @@ import java.util.Objects; */ public class DebugDingTalkSmsClient extends AbstractSmsClient { - public DebugDingTalkSmsClient(SmsChannelProperties properties) { + public DebugDingTalkSmsClient(SmsProperties properties) { super(properties); Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); @@ -41,6 +42,11 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { protected void doInit() { } + @Override + protected boolean propChanged(SmsProperties properties) { + return false; + } + @Override public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, List> templateParams) throws Throwable { @@ -57,7 +63,7 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { Map responseObj = JsonUtils.parseObject(responseText, Map.class); String errorCode = MapUtil.getStr(responseObj, "errcode"); return new SmsSendRespDTO().setSuccess(Objects.equals(errorCode, "0")).setSerialNo(StrUtil.uuid()) - .setApiCode(errorCode).setApiMsg(MapUtil.getStr(responseObj, "errorMsg")); + .setApiCode(errorCode).setApiMsg(MapUtil.getStr(responseObj, "errorMsg")).setMobile(mobile).setChannelCode(properties.getChannel()); } /** @@ -75,7 +81,7 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { // 生成 sign String secret = properties.getApiSecret(); String stringToSign = timestamp + "\n" + secret; - byte[] signData = DigestUtil.hmac(HmacAlgorithm.HmacSHA256, StrUtil.bytes(secret)).digest(stringToSign); + byte[] signData = DigestUtil.hmac(HmacAlgorithm.HmacSHA256, CharSequenceUtil.bytes(secret)).digest(stringToSign); String sign = Base64.encode(signData); // 构建最终 URL return String.format("https://oapi.dingtalk.com/%s?access_token=%s×tamp=%d&sign=%s", diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClient.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClient.java index 98030b49d..03301d7aa 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClient.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClient.java @@ -10,7 +10,7 @@ import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; import com.cf.imes.framework.sms.core.client.dto.SmsTemplateRespDTO; import com.cf.imes.framework.sms.core.client.impl.AbstractSmsClient; import com.cf.imes.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import com.cf.imes.framework.sms.core.property.SmsChannelProperties; +import com.cf.imes.framework.sms.core.property.SmsProperties; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.annotations.VisibleForTesting; @@ -56,7 +56,7 @@ public class TencentSmsClient extends AbstractSmsClient { private SmsClient client; - public TencentSmsClient(SmsChannelProperties properties) { + public TencentSmsClient(SmsProperties properties) { super(properties); Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); validateSdkAppId(properties); @@ -69,6 +69,11 @@ public class TencentSmsClient extends AbstractSmsClient { client = new SmsClient(credential, ENDPOINT); } + @Override + protected boolean propChanged(SmsProperties properties) { + return false; + } + /** * 参数校验腾讯云的 SDK AppId * @@ -78,7 +83,7 @@ public class TencentSmsClient extends AbstractSmsClient { * * @param properties 配置 */ - private static void validateSdkAppId(SmsChannelProperties properties) { + private static void validateSdkAppId(SmsProperties properties) { String combineKey = properties.getApiKey(); Assert.notEmpty(combineKey, "apiKey 不能为空"); String[] keys = combineKey.trim().split(" "); @@ -108,7 +113,7 @@ public class TencentSmsClient extends AbstractSmsClient { SendSmsResponse response = client.SendSms(request); SendStatus status = response.getSendStatusSet()[0]; return new SmsSendRespDTO().setSuccess(Objects.equals(status.getCode(), API_CODE_SUCCESS)).setSerialNo(status.getSerialNo()) - .setApiRequestId(response.getRequestId()).setApiCode(status.getCode()).setApiMsg(status.getMessage()); + .setApiRequestId(response.getRequestId()).setApiCode(status.getCode()).setApiMsg(status.getMessage()).setChannelCode(properties.getChannel()); } @Override diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/property/SmsProperties.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/property/SmsProperties.java new file mode 100644 index 000000000..0413fe98f --- /dev/null +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/property/SmsProperties.java @@ -0,0 +1,76 @@ +package com.cf.imes.framework.sms.core.property; + +import com.cf.imes.framework.common.util.encrypt.AesUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotEmpty; + +/** + * @author Gqr + * @since 2024/8/23 10:51 + */ +@ConfigurationProperties(prefix = "chenfeng.sms") +@Validated +public class SmsProperties { + + @Value("${chenfeng.encrypt.publicKey:}") + private String publicKey; + + /** + * 短信渠道 + */ + @NotEmpty(message = "短信渠道不能为空") + private String channel; + /** + * 短信签名 + */ + private String signature; + /** + * 短信 API 的账号 + */ + @NotEmpty(message = "短信apiKey不能为空") + private String apiKey; + /** + * 短信 API 的密钥 + */ + @NotEmpty(message = "短信apiSecret不能为空") + private String apiSecret; + + public String getChannel() { + return channel; + } + + public void setChannel(String channel) { + this.channel = channel; + } + + public String getSignature() { + return signature; + } + + public SmsProperties setSignature(String signature) { + this.signature = AesUtils.decrypt(signature, publicKey); + return this; + } + + public String getApiKey() { + return apiKey; + } + + + public SmsProperties setApiKey(String apiKey) { + this.apiKey = AesUtils.decrypt(apiKey, publicKey); + return this; + } + + public String getApiSecret() { + return apiSecret; + } + + public SmsProperties setApiSecret(String apiSecret) { + this.apiSecret = AesUtils.decrypt(apiSecret, publicKey); + return this; + } +} diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java index 5952ee2d8..1fce4400b 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java @@ -7,7 +7,7 @@ import com.cf.imes.framework.sms.core.client.dto.SmsReceiveRespDTO; import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; import com.cf.imes.framework.sms.core.client.dto.SmsTemplateRespDTO; import com.cf.imes.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import com.cf.imes.framework.sms.core.property.SmsChannelProperties; +import com.cf.imes.framework.sms.core.property.SmsProperties; import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.aliyuncs.IAcsClient; import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; @@ -37,7 +37,7 @@ import static org.mockito.Mockito.when; */ public class AliyunSmsClientTest extends BaseMockitoUnitTest { - private final SmsChannelProperties properties = new SmsChannelProperties() + private final SmsProperties properties = new SmsProperties() .setApiKey(randomString()) // 随机一个 apiKey,避免构建报错 .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错 .setSignature("晨丰科技"); diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java index e5ee12e69..2833228c0 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java @@ -9,7 +9,7 @@ import com.cf.imes.framework.sms.core.client.dto.SmsReceiveRespDTO; import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; import com.cf.imes.framework.sms.core.client.dto.SmsTemplateRespDTO; import com.cf.imes.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import com.cf.imes.framework.sms.core.property.SmsChannelProperties; +import com.cf.imes.framework.sms.core.property.SmsProperties; import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.google.common.collect.Lists; import com.tencentcloudapi.sms.v20210111.SmsClient; @@ -39,7 +39,7 @@ import static org.mockito.Mockito.when; */ public class TencentSmsClientTest extends BaseMockitoUnitTest { - private final SmsChannelProperties properties = new SmsChannelProperties() + private final SmsProperties properties = new SmsProperties() .setApiKey(randomString() + " " + randomString()) // 随机一个 apiKey,避免构建报错 .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错 .setSignature("晨丰科技"); @@ -64,7 +64,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { @Test public void testRefresh() { // 准备参数 - SmsChannelProperties p = new SmsChannelProperties() + SmsProperties p = new SmsProperties() .setApiKey(randomString() + " " + randomString()) // 随机一个 apiKey,避免构建报错 .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错 .setSignature("晨丰科技"); diff --git a/cf-framework/cf-spring-boot-starter-elasticsearch/src/main/java/com/cf/imes/framework/es/core/service/ESDocumentServiceImpl.java b/cf-framework/cf-spring-boot-starter-elasticsearch/src/main/java/com/cf/imes/framework/es/core/service/ESDocumentServiceImpl.java index 45b275461..906674244 100644 --- a/cf-framework/cf-spring-boot-starter-elasticsearch/src/main/java/com/cf/imes/framework/es/core/service/ESDocumentServiceImpl.java +++ b/cf-framework/cf-spring-boot-starter-elasticsearch/src/main/java/com/cf/imes/framework/es/core/service/ESDocumentServiceImpl.java @@ -1,7 +1,6 @@ package com.cf.imes.framework.es.core.service; import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.lang.UUID; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; @@ -17,9 +16,6 @@ import java.io.IOException; import java.io.StringReader; import java.text.SimpleDateFormat; import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; import java.util.Date; import java.util.List; import java.util.Map; @@ -146,6 +142,7 @@ public class ESDocumentServiceImpl implements ESDocumentService { esDocument.setCreator(loginUser.getNickname()); esDocument.setCreateTime(simpleDateFormat.format(date)); esDocument.setUpdater(loginUser.getNickname()); + esDocument.setOrganId(loginUser.getOrganId()); esDocument.setUpdateTime(simpleDateFormat.format(date)); br.operations(op -> op.index(idx -> idx diff --git a/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/datasource/config/ChenfengDataSourceEncryptConfiguration.java b/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/datasource/config/ChenfengDataSourceEncryptConfiguration.java new file mode 100644 index 000000000..5fa1cd56c --- /dev/null +++ b/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/datasource/config/ChenfengDataSourceEncryptConfiguration.java @@ -0,0 +1,24 @@ +package com.cf.imes.framework.datasource.config; + +import com.baomidou.dynamic.datasource.event.DataSourceInitEvent; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration; +import com.cf.imes.framework.mybatis.core.event.ChenfengDataSourceEncryptInitEvent; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; + + +/** + * @author Gqr + * @since 2024/8/26 18:20 + */ +@AutoConfiguration +@AutoConfigureBefore(DynamicDataSourceAutoConfiguration.class) +public class ChenfengDataSourceEncryptConfiguration { + @Bean + @ConditionalOnProperty(name = "chenfeng.encrypt.enable", havingValue = "true") + public DataSourceInitEvent getDataSourceInitEvent() { + return new ChenfengDataSourceEncryptInitEvent(); + } +} diff --git a/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/event/ChenfengDataSourceEncryptInitEvent.java b/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/event/ChenfengDataSourceEncryptInitEvent.java new file mode 100644 index 000000000..d21405aeb --- /dev/null +++ b/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/event/ChenfengDataSourceEncryptInitEvent.java @@ -0,0 +1,41 @@ +package com.cf.imes.framework.mybatis.core.event; + +import com.baomidou.dynamic.datasource.creator.DataSourceProperty; +import com.baomidou.dynamic.datasource.event.DataSourceInitEvent; +import com.cf.imes.framework.common.util.encrypt.AesUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; + +import javax.sql.DataSource; + +/** + * @author Gqr + * @since 2024/8/27 9:09 + */ +public class ChenfengDataSourceEncryptInitEvent implements DataSourceInitEvent { + @Value("${chenfeng.encrypt.publicKey:}") + private String publicKey; + + /** + * 数据源创建前 + * + * @param dataSourceProperty 数据源基础信息 + */ + @Override + public void beforeCreate(DataSourceProperty dataSourceProperty) { + if (StringUtils.isNotEmpty(publicKey)) { + dataSourceProperty.setUsername(AesUtils.decrypt(dataSourceProperty.getUsername(), publicKey)); + dataSourceProperty.setPassword(AesUtils.decrypt(dataSourceProperty.getPassword(), publicKey)); + } + } + + /** + * 数据源创建后 + * + * @param dataSource 连接池 + */ + @Override + public void afterCreate(DataSource dataSource) { + + } +} diff --git a/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/query/QueryWrapperX.java b/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/query/QueryWrapperX.java index a4109dc52..d0aa4a1c2 100644 --- a/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/query/QueryWrapperX.java +++ b/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/query/QueryWrapperX.java @@ -1,10 +1,10 @@ package com.cf.imes.framework.mybatis.core.query; import cn.hutool.core.lang.Assert; -import com.cf.imes.framework.mybatis.core.enums.SqlConstants; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.ArrayUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.cf.imes.framework.mybatis.core.enums.SqlConstants; import org.springframework.util.StringUtils; import java.util.Collection; @@ -145,6 +145,12 @@ public class QueryWrapperX extends QueryWrapper { return this; } + @Override + public QueryWrapperX isNotNull(String column) { + super.isNotNull(column); + return this; + } + /** * 设置只返回最后一条 * diff --git a/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/type/CompressStringTypeHandler.java b/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/type/CompressStringTypeHandler.java index 0b805096d..1dbdf562b 100644 --- a/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/type/CompressStringTypeHandler.java +++ b/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/type/CompressStringTypeHandler.java @@ -20,10 +20,11 @@ public class CompressStringTypeHandler extends StringTypeHandler { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { + String compressString = null; if (StringUtils.isNotEmpty(parameter)) { - String compressString = JsonUtils.zipString(parameter); - ps.setString(i, compressString); + compressString = JsonUtils.zipString(parameter); } + ps.setString(i, compressString); } @Override diff --git a/cf-framework/cf-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/cf-framework/cf-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index d501f7943..f8c1535cf 100644 --- a/cf-framework/cf-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/cf-framework/cf-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1,3 @@ +com.cf.imes.framework.datasource.config.ChenfengDataSourceEncryptConfiguration com.cf.imes.framework.datasource.config.ChenfengDataSourceAutoConfiguration com.cf.imes.framework.mybatis.config.ChenfengMybatisAutoConfiguration diff --git a/cf-framework/cf-spring-boot-starter-redis/src/main/java/com/cf/imes/framework/redis/config/ChenfengRedisEncryptAutoConfiguration.java b/cf-framework/cf-spring-boot-starter-redis/src/main/java/com/cf/imes/framework/redis/config/ChenfengRedisEncryptAutoConfiguration.java new file mode 100644 index 000000000..f1cd7435b --- /dev/null +++ b/cf-framework/cf-spring-boot-starter-redis/src/main/java/com/cf/imes/framework/redis/config/ChenfengRedisEncryptAutoConfiguration.java @@ -0,0 +1,77 @@ +package com.cf.imes.framework.redis.config; + +import cn.hutool.core.bean.BeanUtil; +import com.cf.imes.framework.common.util.encrypt.AesUtils; +import org.redisson.config.ClusterServersConfig; +import org.redisson.config.Config; +import org.redisson.config.MasterSlaveServersConfig; +import org.redisson.config.ReplicatedServersConfig; +import org.redisson.config.SentinelServersConfig; +import org.redisson.config.SingleServerConfig; +import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.util.StringUtils; + +/** + * @author Gqr + * @since 2024/8/27 9:46 + */ +@AutoConfiguration +public class ChenfengRedisEncryptAutoConfiguration { + + @Value("${chenfeng.encrypt.publicKey:}") + private String publicKey; + + @Bean + @ConditionalOnProperty(name = "chenfeng.encrypt.enable", havingValue = "true") + public RedissonAutoConfigurationCustomizer redissonAutoConfigurationCustomizer() { + return configuration -> { + Config redissonConfig = new Config(); + BeanUtil.copyProperties(configuration, redissonConfig); + + String password; + SingleServerConfig singleServerConfig = redissonConfig.useSingleServer(); + if (singleServerConfig != null) { + + password = singleServerConfig.getPassword(); + singleServerConfig.setPassword( + StringUtils.isEmpty(password) ? null : AesUtils.decrypt(password, publicKey)); + return; + } + + MasterSlaveServersConfig masterSlaveServersConfig = redissonConfig.useMasterSlaveServers(); + if (masterSlaveServersConfig != null) { + password = masterSlaveServersConfig.getPassword(); + masterSlaveServersConfig.setPassword( + StringUtils.isEmpty(password) ? null : AesUtils.decrypt(password, publicKey)); + return; + } + + SentinelServersConfig sentinelServersConfig = redissonConfig.useSentinelServers(); + if (sentinelServersConfig != null) { + password = sentinelServersConfig.getPassword(); + sentinelServersConfig.setPassword( + StringUtils.isEmpty(password) ? null : AesUtils.decrypt(password, publicKey)); + return; + } + + ClusterServersConfig clusterServersConfig = redissonConfig.useClusterServers(); + if (clusterServersConfig != null) { + password = clusterServersConfig.getPassword(); + clusterServersConfig.setPassword( + StringUtils.isEmpty(password) ? null : AesUtils.decrypt(password, publicKey)); + return; + } + + ReplicatedServersConfig replicatedServersConfig = redissonConfig.useReplicatedServers(); + if (replicatedServersConfig != null) { + password = replicatedServersConfig.getPassword(); + replicatedServersConfig.setPassword( + StringUtils.isEmpty(password) ? null : AesUtils.decrypt(password, publicKey)); + } + }; + } +} diff --git a/cf-framework/cf-spring-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/cf-framework/cf-spring-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 339785994..d24fc60b0 100644 --- a/cf-framework/cf-spring-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/cf-framework/cf-spring-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1,3 @@ com.cf.imes.framework.redis.config.ChenfengRedisAutoConfiguration +com.cf.imes.framework.redis.config.ChenfengRedisEncryptAutoConfiguration com.cf.imes.framework.redis.config.ChenfengCacheAutoConfiguration diff --git a/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java b/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java index 48cfd8025..4f26f0557 100644 --- a/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java +++ b/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java @@ -1,6 +1,5 @@ package com.cf.imes.framework.security.core.util; -import cn.hutool.core.util.StrUtil; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants; import com.cf.imes.framework.security.core.LoginUser; @@ -44,7 +43,7 @@ public class SecurityFrameworkUtils { String headerName, String parameterName) { // 1. 获得 Token。优先级:Header > Parameter String token = request.getHeader(headerName); - if (StrUtil.isEmpty(token)) { + if (StringUtils.isEmpty(token)) { token = request.getParameter(parameterName); } if (!StringUtils.hasText(token)) { @@ -63,7 +62,7 @@ public class SecurityFrameworkUtils { public static Authentication getAuthentication() { SecurityContext context = SecurityContextHolder.getContext(); if (context == null) { - return null; + throw new ServiceException(GlobalErrorCodeConstants.UNAUTHORIZED); } return context.getAuthentication(); } @@ -90,10 +89,7 @@ public class SecurityFrameworkUtils { @Nullable public static Long getLoginUserId() { LoginUser loginUser = getLoginUser(); - if (loginUser == null) { - throw new ServiceException(GlobalErrorCodeConstants.UNAUTHORIZED); - } - return loginUser.getId(); + return loginUser != null ? loginUser.getId() : null; } /** diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/goods/dto/GoodsDTO.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/goods/dto/GoodsDTO.java new file mode 100644 index 000000000..069e31e9f --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/goods/dto/GoodsDTO.java @@ -0,0 +1,81 @@ +package com.cf.imes.module.executor.api.goods.dto; + + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class GoodsDTO { + + /** + * 主键 + */ + private Long id; + + // 组织 ID + private Long organId; + + /** + * 生产单号 + */ + private Long orderId; + /** + * 设计端商品ID + */ + private String rawGoodsId; + /** + * 商品 ID + */ + private String goodsId; + /** + * 商品名称 + */ + private String goodsName; + /** + * 材质:颗粒板、欧松板、多层板、生态板、禾香板、密度板、实木、铝蜂窝板、铝塑板 + */ + private String material; + /** + * 纹路 0 正纹 1 可翻转 2 反纹 + */ + private Boolean texture; + /** + * 颜色 + */ + private String color; + /** + * 宽度 + */ + private BigDecimal width; + /** + * 高度 + */ + private BigDecimal height; + /** + * 厚度 + */ + private BigDecimal thickness; + /** + * 价格 + */ + private BigDecimal price; + /** + * 品牌 + */ + private String brand; + /** + * 规格 + */ + private String spec; + /** + * 备注 + */ + private String remark; + /** + * 是否删除 + */ + private Boolean deleted; + + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/plan/dto/PlanDTO.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/plan/dto/PlanDTO.java new file mode 100644 index 000000000..eafb4a7a7 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/plan/dto/PlanDTO.java @@ -0,0 +1,62 @@ +package com.cf.imes.module.executor.api.plan.dto; + + +import lombok.Data; + +import java.time.LocalDateTime; + + + +@Data +public class PlanDTO { + + + /** + * ID + */ + + private Long id; + // 组织 ID + + private Long organId; + + /** + * 排序优先级 + */ + private Long sort; + /** + * 排单类型:1 混单排单,2 生产单排单 + */ + private Integer type; + /** + * 排单状态:0 新单,1 板材已申请,2 开料中,3 已开料 + */ + private Integer status; + + /** + * 机台 ID + */ + private Long machineId; + /** + * 计划时间 + */ + private LocalDateTime planTime; + /** + * 生产单号 + */ + private String orderNos; + + /** + * 备注 + */ + private String remark; + /** + * 生产操作人 + */ + private String operator; + /** + * 生产时间 + */ + private LocalDateTime produceTime; + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java index 5e49de198..deac2662f 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java @@ -11,12 +11,14 @@ public interface ErrorCodeConstants { // ========== 生产单开料排单 ErrorCode PLAN_NOT_EXISTS = new ErrorCode(1_001_107_000, "生产单开料排单不存在"); - ErrorCode PLAN_NOT_ALLOW_DELETE = new ErrorCode(1_001_107_001, "当前排单已开料不予许删除"); + ErrorCode PLAN_NOT_ALLOW_DELETE = new ErrorCode(1_001_107_001, "排单号:{},已开料不予许删除"); ErrorCode PLAN_NOT_ALLOW_CANCEL = new ErrorCode(1_001_107_002, "排单 新单 不予许作废"); ErrorCode LIST_CHANGES_ARE_PROHIBITED = new ErrorCode(1_001_107_003, "当前排单有板材已开料,禁止更改"); + ErrorCode PLAN_ERROR = new ErrorCode(1_001_107_004, "{} 排单数据不存在"); + // ========== 生产单商品 TODO 补充编号 ========== ErrorCode GOODS_NOT_EXISTS = new ErrorCode(1_001_108_000, "生产单商品不存在"); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/plan/vo/OrderGroupRespVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/plan/vo/OrderGroupRespVO.java new file mode 100644 index 000000000..d3d9568f3 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/plan/vo/OrderGroupRespVO.java @@ -0,0 +1,58 @@ +package com.cf.imes.module.executor.api.plan.vo; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class OrderGroupRespVO { + + + @Schema(description = "加工组ID") + private Long id; + + + + @Schema(description = "生产单号") + private Long orderId; + + + + @Schema(description = "柜体ID") + private Long bodyId; + + + + @Schema(description = "加工组类型") + private String groupTypeName; + + + + @Schema(description = "模块名称") + private String name; + + + + @Schema(description = "加工组宽度") + private Double width; + + + + @Schema(description = "加工组高度") + private Double height; + + + + @Schema(description = "加工组深度") + private Double depth; + + + @Schema(description = "加工组总数") + private Integer groupNum; + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/OrderStatisticsController.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/OrderStatisticsController.java index 22d0f16c4..2b75e2ff1 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/OrderStatisticsController.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/OrderStatisticsController.java @@ -90,7 +90,7 @@ public class OrderStatisticsController { @GetMapping("/bigPlateCount/group") @Operation(summary = "大板数量分组统计") public CommonResult> getBigPlateCount(@Valid OrderStatisticsReqVO reqVO) { - return success(null); + return success(orderStatisticsService.getBigPlateCountGroup(reqVO)); } } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/OptimizePlanController.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/OptimizePlanController.java index bfa63c815..bda77fc0f 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/OptimizePlanController.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/OptimizePlanController.java @@ -1,15 +1,17 @@ package com.cf.imes.module.executor.controller.admin.plan; import com.cf.imes.framework.common.pojo.CommonResult; -import com.cf.imes.framework.operatelog.core.annotations.OperateLog; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderSource; +import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.CuttingStatusRespVO; import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.SavePlanPlateResultReqVO; -import com.cf.imes.module.executor.controller.admin.plan.vo.*; -import com.cf.imes.module.executor.controller.admin.plate.vo.PlateSaveReqVO; +import com.cf.imes.module.executor.controller.admin.plan.vo.AddRemainReqVO; +import com.cf.imes.module.executor.controller.admin.plan.vo.GetSourceDataReq; +import com.cf.imes.module.executor.controller.admin.plan.vo.PlateOptimize; import com.cf.imes.module.executor.dal.dataobject.ordermodel.OrderModelDO; import com.cf.imes.module.executor.service.optimizeplan.OptimizePlanService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; @@ -53,10 +55,15 @@ public class OptimizePlanController { @GetMapping("commit") - @Operation(summary = "开始开料") + @Operation(summary = "开料") + @Parameters({ + @Parameter(name = "planId", description = "排单ID", required = true, example = "1024"), + @Parameter(name = "goodsNo", description = "开料的大板编号", required = true, example = "1") + }) @PreAuthorize("@ss.hasPermission('placeorder:optimize')") - public CommonResult commit(@RequestParam @Valid @NotNull(message = "排单id不能空") Long planId) { - return CommonResult.success(optimizePlanService.commit(planId)); + public CommonResult commit(@RequestParam("planId") Long planId,@RequestParam("goodsNo") List goodsNo) { + + return CommonResult.success(optimizePlanService.commit(planId,goodsNo)); } @GetMapping("/endCutting") @@ -67,14 +74,24 @@ public class OptimizePlanController { } + @PutMapping("/updateCuttingStatus") + @Operation(summary = "修改开料状态") + @PreAuthorize("@ss.hasPermission('placeorder:optimize:updateCuttingStatus')") + public CommonResult updateCuttingStatus(@RequestBody CuttingStatusRespVO respVO) { + return success(optimizePlanService.updateCuttingStatus(respVO)); + } + + + @GetMapping("/getOrderSource") @Operation(summary = "获取生产单源数据") @PreAuthorize("@ss.hasPermission('placeorder:optimize')") public CommonResult getOrderSource(@Schema(description = "生产单id") @RequestParam(required = false) Long orderId, + @Schema(description = "大板IDS-大板分类的IDS") @RequestParam(required = false) List ids, @Schema(description = "排单id") @RequestParam(required = false) Long planId, @Schema(description = "机台Id") @RequestParam("machineId") Long machineId ) { - return CommonResult.success(optimizePlanService.getOrderSource(orderId, planId, machineId)); + return CommonResult.success(optimizePlanService.getOrderSource(orderId, planId, machineId,ids)); } @@ -111,5 +128,13 @@ public class OptimizePlanController { } + @DeleteMapping("/delete") + @Operation(summary = "ES批量删除测试") + @PreAuthorize("@ss.hasPermission('placeorder:delete')") + public CommonResult deleteTest(@RequestParam("id") List id) { + return success(optimizePlanService.deleteTest(id)); + } + + } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/PlanController.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/PlanController.java index 778b8fd13..34650b42c 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/PlanController.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/PlanController.java @@ -1,30 +1,36 @@ package com.cf.imes.module.executor.controller.admin.plan; -import com.cf.imes.framework.es.core.valid.CreateGroup; -import com.cf.imes.framework.es.core.valid.UpdateGroup; -import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderRespVO; -import org.springframework.web.bind.annotation.*; -import javax.annotation.Resource; -import org.springframework.validation.annotation.Validated; -import org.springframework.security.access.prepost.PreAuthorize; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.Operation; -import javax.validation.*; -import javax.servlet.http.*; -import javax.validation.constraints.NotEmpty; -import java.util.*; -import java.io.IOException; +import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.pojo.PageParam; import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.util.object.BeanUtils; -import static com.cf.imes.framework.common.pojo.CommonResult.success; +import com.cf.imes.framework.es.core.valid.CreateGroup; +import com.cf.imes.framework.es.core.valid.UpdateGroup; import com.cf.imes.framework.excel.core.util.ExcelUtils; import com.cf.imes.framework.operatelog.core.annotations.OperateLog; -import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.*; +import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderRespVO; +import com.cf.imes.module.executor.controller.admin.plan.bo.OrderRoomBodyList; +import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.NotPlanGoodsReqVO; +import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.NotPlanGoodsRespVO; import com.cf.imes.module.executor.controller.admin.plan.vo.*; import com.cf.imes.module.executor.service.plan.PlanService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static com.cf.imes.framework.common.pojo.CommonResult.success; +import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - 排单") @RestController @@ -38,7 +44,7 @@ public class PlanController { @PostMapping("/create") @Operation(summary = "创建排单") @PreAuthorize("@ss.hasPermission('placeorder:create')") - public CommonResult createPlan(@Validated(CreateGroup.class) @RequestBody PlanSaveReqVO createReqVO) { + public CommonResult> createPlan(@Validated(CreateGroup.class) @RequestBody PlanSaveReqVO createReqVO) { return success(planService.createPlan(createReqVO)); } @@ -52,16 +58,16 @@ public class PlanController { @DeleteMapping("/delete") @Operation(summary = "删除排单") - @Parameter(name = "id", description = "排单id", required = true) + @Parameter(name = "ids", description = "排单ids", required = true) @PreAuthorize("@ss.hasPermission('placeorder:delete')") - public CommonResult deletePlan(@RequestParam("id") Long id) { - return success(planService.deletePlan(id)); + public CommonResult deletePlan(@RequestParam("ids") List ids) { + return success(planService.deletePlan(ids)); } - @DeleteMapping("cancellation") - @Operation(summary = "作废") - @Parameter(name = "id", description = "排单id", required = true) - @PreAuthorize("@ss.hasPermission('executor:plan:delete')") +// @DeleteMapping("cancellation") +// @Operation(summary = "作废") +// @Parameter(name = "id", description = "排单id", required = true) +// @PreAuthorize("@ss.hasPermission('executor:plan:delete')") public CommonResult cancellation(@RequestParam("id") Long id) { return success(planService.cancellation(id)); } @@ -106,12 +112,19 @@ public class PlanController { } @GetMapping("getNotPlanOrderListPage") - @Operation(summary = "获取未排单的板材生产单板材分页列表") + @Operation(summary = "获取未排单的生产单分页列表") @PreAuthorize("@ss.hasPermission('placeorder:query')") public CommonResult> getOrderPage(@Valid OrderPageReqVOCopy pageReqVO) { return success(planService.getOrderPage(pageReqVO)); } + @GetMapping("getNotPlanOrderPlateList") + @Operation(summary = "获取未排单的板材分页列表") + @PreAuthorize("@ss.hasPermission('placeorder:query')") + public CommonResult> getOrderPlateList(@Valid OrderPageReqVOCopy pageReqVO) { + return success(planService.getOrderPlateList(pageReqVO)); + } + @GetMapping("getNotPlanGoodsListPage") @Operation(summary = "获取未排单的大板板材分页列表") @@ -122,13 +135,14 @@ public class PlanController { - @GetMapping("getNotPlanPlateListPage") - @Operation(summary = "获取未排单的板材分页列表") + @PostMapping("getNotOptimizeGoodsList") + @Operation(summary = "优化界面未排单的大板板材分页列表") @PreAuthorize("@ss.hasPermission('executor:plan:query')") - public CommonResult> getNotPlanPlateListPage(@Valid PlateReqPageVO pageVO) { - return success(planService.getNotPlanPlateListPage(pageVO)); + public CommonResult> getNotOptimizeGoodsList(@Valid @RequestBody NotPlanGoodsReqVO reqVO) { + return success(planService.getNotOptimizeGoodsList(reqVO)); } + @GetMapping("getNotPlanGoodsListPageByOrderId") @Operation(summary = "根据生产单id获取未排单的商品分页列表") @PreAuthorize("@ss.hasPermission('executor:plan:query')") @@ -180,4 +194,15 @@ public class PlanController { return success(planService.getPlateList(planIds)); } + + @GetMapping("getOrderRoomBodyList") + @Operation(summary = "获取未排单的生产单的柜体和房间名称") + @Parameter(name = "orderIds", description = "生产单ID", required = true) + @PreAuthorize("@ss.hasPermission('placeorder:orderlist')") + public CommonResult> getOrderRoomBody(@Valid @RequestParam List orderIds) { + + return success(planService.getOrderRoomBody(orderIds)); + } + + } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderBodyIds.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderBodyIds.java new file mode 100644 index 000000000..de221829a --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderBodyIds.java @@ -0,0 +1,18 @@ +package com.cf.imes.module.executor.controller.admin.plan.bo; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class OrderBodyIds { + + + @Schema(description = "柜体ID") + private Long bodyId; + + @Schema(description = "柜体名称") + private String bodyName; + + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderIds.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderIds.java index 7057f6fcd..62a2ae26f 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderIds.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderIds.java @@ -3,16 +3,15 @@ package com.cf.imes.module.executor.controller.admin.plan.bo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.Builder; @Data -@Builder + public class OrderIds { - @Schema(description = "大板ID") + @Schema(description = "大板ID-大板分类的ID") private Long id; @@ -20,7 +19,7 @@ public class OrderIds { private Long orderId; - @Schema(description = "商品ID") + @Schema(description = "商品ID-板材库对应的大板ID") private Long goodsId; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderRoomBodyList.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderRoomBodyList.java new file mode 100644 index 000000000..7e76d6f2d --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderRoomBodyList.java @@ -0,0 +1,20 @@ +package com.cf.imes.module.executor.controller.admin.plan.bo; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Data +public class OrderRoomBodyList { + + + @Schema(description = "生产单ID") + private Long orderId; + + + @Schema(description = "柜体房间信息") + private List orderRoomIds; + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderRoomIds.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderRoomIds.java new file mode 100644 index 000000000..ef71aed5b --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderRoomIds.java @@ -0,0 +1,23 @@ +package com.cf.imes.module.executor.controller.admin.plan.bo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Data +public class OrderRoomIds { + + + @Schema(description = "房间ID") + private Long roomId; + + @Schema(description = "房间名称") + private String roomName; + + @Schema(description = "柜体信息") + private List orderBodyIds; + + + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/BlockPlaceInfo.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/BlockPlaceInfo.java new file mode 100644 index 000000000..d163a389c --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/BlockPlaceInfo.java @@ -0,0 +1,25 @@ +package com.cf.imes.module.executor.controller.admin.plan.saveOptimize; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +@Schema(description = "小板优化的数据信息") +@Data +@ToString(callSuper = true) +public class BlockPlaceInfo { + + + @Schema(description = "大板编号") + private Long bi; + + @Schema(description = "小板编号") + private Long bo; + + public BlockPlaceInfo(Long bi, Long bo) { + this.bi = bi; + this.bo = bo; + } + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/CuttingStatusRespVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/CuttingStatusRespVO.java new file mode 100644 index 000000000..a019a3893 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/CuttingStatusRespVO.java @@ -0,0 +1,20 @@ +package com.cf.imes.module.executor.controller.admin.plan.saveOptimize; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Data +public class CuttingStatusRespVO { + + + @Schema(description = "排单ID") + private Long planId; + + + @Schema(description = "取消开料的大板编号") + private List goodsNo; + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/NotPlanGoodsReqVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/NotPlanGoodsReqVO.java new file mode 100644 index 000000000..9f3906be0 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/NotPlanGoodsReqVO.java @@ -0,0 +1,57 @@ +package com.cf.imes.module.executor.controller.admin.plan.saveOptimize; + + +import com.cf.imes.module.executor.controller.admin.plan.bo.OrderIds; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +import javax.validation.Valid; +import java.util.List; + +@Schema(description = "管理后台 - 未排单的大板的数据信息") +@Data +@ToString(callSuper = true) +public class NotPlanGoodsReqVO { + + +// @Schema(description = "生产单ids") +// private List orderIds; +// +// @Schema(description = "生产单的大板ids") +// private List goodsIds; +// +// +// @Schema(description = "板材库对应的大板ids") +// private List plateGoodsIds; + + + @Schema(description = "生产单和大板的信息") + private List orderIdList; + + + @Schema(description = "排单类型:1 混单排单,2 生产单排单", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer type; + + + @Schema(description = "混单过滤条件") + private List filter; + + + @Valid + @Data + public static class Information { + + @Schema(description = "材质") + private Boolean material; + + @Schema(description = "颜色") + private Boolean color; + + @Schema(description = "长*宽") + private Boolean spec; + + } + + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/NotPlanGoodsRespVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/NotPlanGoodsRespVO.java new file mode 100644 index 000000000..0311db49b --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/NotPlanGoodsRespVO.java @@ -0,0 +1,87 @@ +package com.cf.imes.module.executor.controller.admin.plan.saveOptimize; + + +import com.cf.imes.module.executor.controller.admin.plan.bo.OrderIds; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +import java.math.BigDecimal; +import java.util.List; + + +@Data +@ToString(callSuper = true) +public class NotPlanGoodsRespVO { + + +// @Schema(description = "生产单ids") +// private List orderIds; +// +// +// @Schema(description = "生产单的大板ids") +// private List goodsIds; +// +// +// @Schema(description = "板材库对应的大板ids") +// private List plateGoodsIds; + + + @Schema(description = "生产单和大板的信息") + private List orderIdList; + + + +// @Schema(description = "余料板ID") +// private List remainPlateIds; + + + @Schema(description = "商品ID-板材库对应的大板ID") + private Long goodsId; + + + @Schema(description = "商品名称") + private String goodsName; + + + @Schema(description = "商品材质") + private String material; + + + @Schema(description = "商品颜色") + private String color; + + + @Schema(description = "商品纹路") + private Boolean texture; + + +// @Schema(description = "宽") +// private BigDecimal width; +// +// +// @Schema(description = "高") +// private BigDecimal height; +// +// + @Schema(description = "厚") + private BigDecimal thickness; + + +// @Schema(description = "面积") +// private BigDecimal area; + + + @Schema(description = "小板数量") + private Integer plateNum; + + + @Schema(description = "大板数量") + private Integer goodsNum; + + + @Schema(description = "尺寸规格") + private String spec; + + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/GoodsReqVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/GoodsReqVO.java index 99955e1d1..a5fa5b3a9 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/GoodsReqVO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/GoodsReqVO.java @@ -15,7 +15,7 @@ import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH public class GoodsReqVO { - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "4109") + @Schema(description = "主键-大板分类ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "4109") private Long id; @@ -29,7 +29,7 @@ public class GoodsReqVO { @Schema(description = "设计端商品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "832") private Long rawGoodsId; - @Schema(description = "商品 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "243") + @Schema(description = "商品 ID-大板的实际ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "243") private Long goodsId; @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰") @@ -79,13 +79,13 @@ public class GoodsReqVO { @Schema(description = "创建时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; + private LocalDateTime createTime; @Schema(description = "更新时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] updateTime; + private LocalDateTime updateTime; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/NotPlanOrderPlateRespVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/NotPlanOrderPlateRespVO.java new file mode 100644 index 000000000..7d7f208e4 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/NotPlanOrderPlateRespVO.java @@ -0,0 +1,55 @@ +package com.cf.imes.module.executor.controller.admin.plan.vo; + + +import com.cf.imes.module.executor.controller.admin.plan.bo.OrderIds; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; + +@Data +public class NotPlanOrderPlateRespVO { + +// @Schema(description = "生产单id") +// private List orderId; +// +// @Schema(description = "生产单的大板ID-大板分类ID") +// private List id; +// +// @Schema(description = "商品id-板材库对应的ID") +// private Long goodsId; + + + @Schema(description = "生产单和大板的信息") + private List orderIdList; + + @Schema(description = "商品ID-板材库对应的大板ID") + private Long goodsId; + + @Schema(description = "商品名称") + private String goodsName; + + @Schema(description = "商品材质") + private String material; + + @Schema(description = "商品颜色") + private String color; + + @Schema(description = "宽") + private BigDecimal width; + + @Schema(description = "高") + private BigDecimal height; + + @Schema(description = "厚") + private BigDecimal thickness; + + @Schema(description = "商品纹路") + private Boolean texture; + + @Schema(description = "商品品牌") + private String brand; + + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderGoodsResp.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderGoodsResp.java index f7fbea228..a36c5a12d 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderGoodsResp.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderGoodsResp.java @@ -5,8 +5,6 @@ import com.cf.imes.module.executor.controller.admin.plan.bo.OrderIds; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.util.List; @@ -32,6 +30,10 @@ public class OrderGoodsResp { private BigDecimal height; @Schema(description = "厚") private BigDecimal thickness; + @Schema(description = "商品纹路") + private Boolean texture; + @Schema(description = "商品品牌") + private String brand; @Schema(description = "面积") private BigDecimal area; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderPageReqVOCopy.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderPageReqVOCopy.java index a3f074eaa..d8f141dc2 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderPageReqVOCopy.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderPageReqVOCopy.java @@ -3,12 +3,10 @@ package com.cf.imes.module.executor.controller.admin.plan.vo; import com.cf.imes.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; import java.time.LocalDateTime; -import java.util.Date; import java.util.List; import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -16,14 +14,12 @@ import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH /** * @author there */ -@NoArgsConstructor + @Data public class OrderPageReqVOCopy extends PageParam { @Schema(description = "生产单id") private Long orderId; - @Schema(description = "商品id") - private String goodsId; @Schema(description = "自定义id") private String defaultId; @Schema(description = "客户") @@ -49,12 +45,6 @@ public class OrderPageReqVOCopy extends PageParam { @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] createTime; - /*@Schema(description = "交付日期开始时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime beginDate; - @Schema(description = "交付日期结束时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime endDate;*/ @Schema(description = "长 小范围") private BigDecimal longMinRang; @Schema(description = "长 大范围") @@ -64,4 +54,18 @@ public class OrderPageReqVOCopy extends PageParam { @Schema(description = "宽 大范围") private BigDecimal widthMaxRang; + + // todo 目前商品ID的数据筛选只解决了非混单的情况(非混单,数据类型为Long即可,混单情况需要改变),混单数据筛选待解决 + @Schema(description = "商品ID-板材库对应的大板ID") + private Long goodsId; + + @Schema(description = "大板分类ID") + private List ids; + @Schema(description = "房间ID") + private List roomId; + @Schema(description = "柜体ID") + private List bodyId; + @Schema(description = "生产单ids") + private List orderIds; + } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderRespVOCopy.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderRespVOCopy.java index ef8d6c9e5..c668709f1 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderRespVOCopy.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderRespVOCopy.java @@ -24,6 +24,8 @@ import static com.cf.imes.framework.common.util.date.DateUtils.*; public class OrderRespVOCopy { @Schema(description = "生产单id") private Long orderId; + @Schema(description = "生产单状态") + private Long status; @Schema(description = "自定义单号") private String defineId; @Schema(description = "客户") diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanPageReqVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanPageReqVO.java index 99a56a2a0..3771c1035 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanPageReqVO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanPageReqVO.java @@ -1,10 +1,12 @@ package com.cf.imes.module.executor.controller.admin.plan.vo; -import lombok.*; -import java.util.*; -import io.swagger.v3.oas.annotations.media.Schema; import com.cf.imes.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; + import java.time.LocalDateTime; import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -16,7 +18,12 @@ import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH public class PlanPageReqVO extends PageParam { @Schema(description = "排单号") - private String id; + private Long id; + + + @Schema(description = "是否翻页-true:上,false:下") + private Boolean isUp; + @Schema(description = "排序优先级") private Integer sort; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanRespVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanRespVO.java index 3dd72074f..f6fcd92ea 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanRespVO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanRespVO.java @@ -1,13 +1,12 @@ package com.cf.imes.module.executor.controller.admin.plan.vo; -import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderRespVO; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -import java.util.*; -import org.springframework.format.annotation.DateTimeFormat; +import lombok.Data; + import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; +import java.util.List; @Schema(description = "管理后台 - 生产单开料排单 Response VO") @Data @@ -18,10 +17,6 @@ public class PlanRespVO { @ExcelProperty("ID") private Long id; -// @Schema(description = "排单号", requiredMode = Schema.RequiredMode.REQUIRED) -// @ExcelProperty("排单号") -// private String planNo; - @Schema(description = "排序优先级", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("排序优先级") private Integer sort; @@ -34,9 +29,6 @@ public class PlanRespVO { @ExcelProperty("排单状态:0 新单,1 板材已申请,2 开料中,3 已开料") private Integer status; -// @Schema(description = "是否支付:0 否,1 是", requiredMode = Schema.RequiredMode.REQUIRED) -// @ExcelProperty("是否支付:0 否,1 是") -// private Boolean isPay; @Schema(description = "机台 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "16707") @ExcelProperty("机台 ID") @@ -57,7 +49,7 @@ public class PlanRespVO { @Schema(description = "排单对应的生产单的信息", requiredMode = Schema.RequiredMode.REQUIRED) private List orderList; - @Schema(description = "板材信息列表", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "板材信息列表-大板信息", requiredMode = Schema.RequiredMode.REQUIRED) private List plateInfoList; @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") @@ -80,4 +72,25 @@ public class PlanRespVO { @ExcelProperty("生产时间") private LocalDateTime produceTime; + + @Schema(description = "优化大板片数") + private Long optimizeGoodsCount; + + + @Schema(description = "已开料的大板片数") + private Long cutGoodsCount; + + + @Schema(description = "总小板片数") + private Long plateNum; + + + @Schema(description = "未优化小板片数") + private Long unOptimizePlateCount; + + + @Schema(description = "已优化小板片数") + private Long optimizePlateCount; + + } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanSaveReqVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanSaveReqVO.java index 5f654bd6c..5dfbdd92f 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanSaveReqVO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlanSaveReqVO.java @@ -2,12 +2,13 @@ package com.cf.imes.module.executor.controller.admin.plan.vo; import com.cf.imes.framework.es.core.valid.CreateGroup; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; +import lombok.Data; + import javax.validation.Valid; -import javax.validation.constraints.*; -import org.springframework.format.annotation.DateTimeFormat; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; +import java.util.List; @Schema(description = "管理后台 - 生产单开料排单新增/修改 Request VO") @Data @@ -18,7 +19,6 @@ public class PlanSaveReqVO { @Schema(description = "排序优先级", requiredMode = Schema.RequiredMode.REQUIRED) - //@NotNull(groups = CreateGroup.class,message = "排序优先级不能为空") private Long sort; @Schema(description = "排单类型:1 混单排单,2 生产单排单", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @@ -38,14 +38,10 @@ public class PlanSaveReqVO { @NotNull(message = "计划时间不能为空", groups = CreateGroup.class) private LocalDateTime planTime; - /*@Schema(description = "生产单id列表", requiredMode = Schema.RequiredMode.REQUIRED) - private List orderIds;*/ - /*@Schema(description = "板件id列表") - private List plateIds;*/ - @Schema(description = "生产单id与商品id 列表",requiredMode = Schema.RequiredMode.REQUIRED) - private List itemList; +// @Schema(description = "余料板ID") +// private List remainPlateIds; @Schema(description = "备注") @@ -59,6 +55,15 @@ public class PlanSaveReqVO { @NotNull(message = "生产时间不能为空", groups = CreateGroup.class) private LocalDateTime produceTime; + + @Schema(description = "生产单id与商品id 列表",requiredMode = Schema.RequiredMode.REQUIRED) + private List itemList; + + + @Schema(description = "去除的大板分类ID",requiredMode = Schema.RequiredMode.REQUIRED) + private List deleteIds; + + @Valid @Data public static class Item { @@ -70,8 +75,13 @@ public class PlanSaveReqVO { @Schema(description = "生产单id") @NotNull private Long orderId; + @Schema(description = "板材库大板id") @NotNull private Long goodsId; + + @Schema(description = "余料板ID") + @NotNull + private Long remainPlateId; } } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlateDetialRespVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlateDetialRespVO.java index 2f4bec75b..6db59c9d4 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlateDetialRespVO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlateDetialRespVO.java @@ -13,7 +13,7 @@ import java.util.List; public class PlateDetialRespVO { @Schema(description = "板件ID", requiredMode = Schema.RequiredMode.REQUIRED) - private Long id; + private Long plateId; @Schema(description = "房间ID", requiredMode = Schema.RequiredMode.REQUIRED) @@ -35,10 +35,13 @@ public class PlateDetialRespVO { private Long orderId; - @Schema(description = "商品ID", requiredMode = Schema.RequiredMode.REQUIRED) - private Long goodsId; + @Schema(description = "商品ID-大板分类ID", requiredMode = Schema.RequiredMode.REQUIRED) + private Long id; + @Schema(description = "大板实例ID", requiredMode = Schema.RequiredMode.REQUIRED) + private Long goodsId; + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED) private String goodsName; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlateInfoVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlateInfoVO.java index 8878d2a82..4e9d8aa34 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlateInfoVO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/PlateInfoVO.java @@ -1,14 +1,15 @@ package com.cf.imes.module.executor.controller.admin.plan.vo; +import com.cf.imes.module.executor.controller.admin.plan.bo.OrderIds; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.math.BigDecimal; +import java.util.List; /** * @author there @@ -18,6 +19,16 @@ import java.math.BigDecimal; @AllArgsConstructor @NoArgsConstructor public class PlateInfoVO { + + + @Schema(description = "生产单和大板的信息") + private List orderIdList; + + + @Schema(description = "板材库对应的大板ID-大板实际ID") + private Long goodsId; + + @Schema(description = "材质:颗粒板、欧松板、多层板、生态板、禾香板、密度板、实木、铝蜂窝板、铝塑板", requiredMode = Schema.RequiredMode.REQUIRED) private String material; @@ -40,7 +51,10 @@ public class PlateInfoVO { @Schema(description = "颜色") private String color; - @Schema(description = "数量") + @Schema(description = "数量-大板对应的小板数量") private Integer count; + @Schema(description = "优化大板片数") + private Long optimizeGoodsCount; + } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plate/vo/OptimizationSavePlateReqVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plate/vo/OptimizationSavePlateReqVO.java index 0b498dd37..a6658c4fc 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plate/vo/OptimizationSavePlateReqVO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plate/vo/OptimizationSavePlateReqVO.java @@ -49,7 +49,7 @@ public class OptimizationSavePlateReqVO { private Integer type; - @Schema(description = "商品ID") + @Schema(description = "商品ID-大板的实际ID") private Long goodsId; @Schema(description = "纹路类型,0 正纹 1 可翻转 2 反纹") diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plate/vo/PlateRespVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plate/vo/PlateRespVO.java index 673982e7b..cf285ddf5 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plate/vo/PlateRespVO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plate/vo/PlateRespVO.java @@ -1,14 +1,14 @@ package com.cf.imes.module.executor.controller.admin.plate.vo; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import com.cf.imes.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -import java.util.*; +import lombok.Data; + import java.math.BigDecimal; -import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; +import java.util.List; /** * @author Beal @@ -173,6 +173,14 @@ public class PlateRespVO extends PageParam { @ExcelProperty("创建时间") private LocalDateTime createTime; + @Schema(description = "加工造型(槽)数") + private Integer sculptNum; + + + @Schema(description = "加工孔数") + private Integer holeNum; + + @Schema(description = "板材颜色") private String color; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/goods/CutedBoardInfo.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/goods/CutedBoardInfo.java new file mode 100644 index 000000000..ef37a28f9 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/goods/CutedBoardInfo.java @@ -0,0 +1,28 @@ +package com.cf.imes.module.executor.dal.dataobject.goods; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "大板开料信息") +public class CutedBoardInfo { + + + @Schema(description = "已开料大板数量") + private Long cutedBoardNumber; + + + @Schema(description = "具体的开料大板编号") + private List cutedBoardList; + + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/goods/OptimizeBoardModelDO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/goods/OptimizeBoardModelDO.java index 8b98331c1..3ef978fa8 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/goods/OptimizeBoardModelDO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/goods/OptimizeBoardModelDO.java @@ -2,6 +2,7 @@ package com.cf.imes.module.executor.dal.dataobject.goods; import com.cf.imes.framework.es.core.dal.ESDocument; +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; @@ -9,6 +10,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import java.math.BigDecimal; +import java.util.List; @Data @@ -23,7 +25,25 @@ public class OptimizeBoardModelDO extends ESDocument { @Schema(description = "生产单id") - private Long orderId; + @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) + private List orderId; + + + @Schema(description = "大板的实际ID") + private Long goodsId; + + + @Schema(description = "生产单已优化小板数量") + private Long placeBlockNumber; + + + // 新的数据集需要去除 + @Schema(description = "排单优化的大板数量") + private Long placeBoardNumber; + + + @Schema(description = "已开料大板数据集") + private CutedBoardInfo cutedBoardInfo; @Schema(description = "大板原长") diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderGroup/OrderGroupDO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderGroup/OrderGroupDO.java index fd7026eb5..e42519f72 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderGroup/OrderGroupDO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderGroup/OrderGroupDO.java @@ -1,11 +1,8 @@ package com.cf.imes.module.executor.dal.dataobject.orderGroup; -import com.cf.imes.framework.organ.core.db.OrganBaseDO; -import lombok.*; import com.baomidou.mybatisplus.annotation.*; import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; - -import java.math.BigDecimal; +import lombok.*; /** * 生产单加工组 DO @@ -51,15 +48,15 @@ public class OrderGroupDO extends BaseDO { */ private String name; /** - * 模块宽度 + * 加工组宽度 */ private Double width; /** - * 模块高度 + * 加工组高度 */ private Double height; /** - * 模块深度 + * 加工组深度 */ private Double depth; /** diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/plate/PlateDO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/plate/PlateDO.java index aa555dccb..e229980e2 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/plate/PlateDO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/plate/PlateDO.java @@ -1,23 +1,10 @@ package com.cf.imes.module.executor.dal.dataobject.plate; -import com.cf.imes.framework.organ.core.db.OrganBaseDO; -import lombok.*; -import java.util.*; -import java.math.BigDecimal; -import java.math.BigDecimal; -import java.math.BigDecimal; -import java.math.BigDecimal; -import java.math.BigDecimal; -import java.math.BigDecimal; -import java.math.BigDecimal; -import java.math.BigDecimal; -import java.math.BigDecimal; -import java.math.BigDecimal; -import java.math.BigDecimal; -import java.time.LocalDateTime; -import java.time.LocalDateTime; import com.baomidou.mybatisplus.annotation.*; import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; +import lombok.*; + +import java.math.BigDecimal; /** * 生产单板件 DO @@ -55,7 +42,7 @@ public class PlateDO extends BaseDO { */ private String plateNo; /** - * 板类型,0 层板 1 立板 2 背板 + * 板类型,0 层板 1 立板 2 背板 3 自增板 */ private Integer type; /** diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/goods/GoodsMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/goods/GoodsMapper.java index 027d39bce..527532694 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/goods/GoodsMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/goods/GoodsMapper.java @@ -1,22 +1,21 @@ package com.cf.imes.module.executor.dal.mysql.goods; -import java.util.*; - import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.executor.controller.admin.goods.vo.GoodsPageReqVO; +import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.NotPlanGoodsRespVO; import com.cf.imes.module.executor.controller.admin.plan.vo.GoodsReqVO; import com.cf.imes.module.executor.controller.admin.plan.vo.OrderGoodsResp; -import com.cf.imes.module.executor.controller.admin.plan.vo.OrderPageReqVOCopy; import com.cf.imes.module.executor.dal.dataobject.goods.GoodsDO; -import com.cf.imes.module.executor.dal.dataobject.orderGroup.OrderGroupDO; import org.apache.ibatis.annotations.Mapper; -import com.cf.imes.module.executor.controller.admin.goods.vo.*; import org.apache.ibatis.annotations.Param; +import java.util.Collection; +import java.util.List; + import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; /** @@ -51,7 +50,7 @@ public interface GoodsMapper extends BaseMapperX { List selectGoodsList(@Param("orderId") Long orderId, @Param("organId") Long organId); - List selectGoodsListByOrderIds(@Param("orderIds") List orderIds, @Param("organId") Long organId); + List selectGoodsListByOrderIds(@Param("goodsIds") List goodsIds, @Param("organId") Long organId); // 单个修改删除状态 @@ -82,12 +81,26 @@ public interface GoodsMapper extends BaseMapperX { IPage selectGoods(@Param("page") IPage page, @Param("goodsIds") List goodsIds, @Param("organId") Long organId); - default GoodsDO selectId(Long orderId, Long goodsId, Long organId) { - return selectOne(new LambdaQueryWrapperX() +// default GoodsDO selectId(Long orderId, Long goodsId, Long organId) { +// return selectOne(new LambdaQueryWrapperX() +// } +// default List selectGoodsPlateList(List goodIds, Long organId) { +// return selectList(new LambdaQueryWrapperX() +// .eq(GoodsDO::getOrganId, organId) +// .inIfPresent(GoodsDO::getOrderId, goodIds) +// .select(GoodsDO::getGoodsId,GoodsDO::getGoodsName, GoodsDO::getMaterial, GoodsDO::getColor, GoodsDO::getTexture,GoodsDO::getThickness, GoodsDO::getSpec)); +// } + + + List selectGoodsPlateList(@Param("goodIds") List goodIds,@Param("organId") Long organId); + + + default List selectListByGoodsId(Long goodsId, Long organId) { + return selectList(new LambdaQueryWrapperX() .eq(GoodsDO::getOrganId, organId) - .eq(GoodsDO::getOrderId, orderId) - .eq(GoodsDO::getGoodsId, goodsId) - .eq(GoodsDO::getDeleted, 0)); + .eq(GoodsDO::getDeleted, false) + .eq(GoodsDO::getGoodsId, goodsId)); + } // 根据生产单删除 @@ -101,4 +114,33 @@ public interface GoodsMapper extends BaseMapperX { return delete(new LambdaQueryWrapperX() .in(GoodsDO::getOrderId, orderId)); } + + +// List seleTestSQL(@Param("sql") String sql); + + + + default List selectListByGoodsIdList(List goodsIds,List orderIds, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(GoodsDO::getOrganId, organId) + .eq(GoodsDO::getDeleted, false) + .in(GoodsDO::getGoodsId, goodsIds) + .in(GoodsDO::getOrderId, orderIds)); + + } + + + List seleTestSQL(@Param("filed") String filed,@Param("goodsIds") List goodsIds ,@Param("organId") Long organId); + + + default GoodsDO selectGoodsId(Long orderId, Long goodsId, Long organId) { + return selectOne(new LambdaQueryWrapperX() + .eq(GoodsDO::getOrganId, organId) + .eq(GoodsDO::getDeleted, false) + .eq(GoodsDO::getGoodsId, goodsId) + .eq(GoodsDO::getOrderId, orderId) + .select(GoodsDO::getId)); + + } + } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderMapper.java index 43d580fb4..cb37350f5 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderMapper.java @@ -13,15 +13,15 @@ import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderCountPro import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderOverdueRespVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderPageReqVO; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderIds; +import com.cf.imes.module.executor.controller.admin.plan.vo.OrderGoodsResp; +import com.cf.imes.module.executor.controller.admin.plan.vo.OrderPageReqVOCopy; import com.cf.imes.module.executor.controller.admin.plan.vo.OrderRespVOCopy; import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; import com.cf.imes.module.executor.enums.OrderDeletedEnum; import com.cf.imes.module.executor.enums.OrderStatusEnum; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; -import org.springframework.beans.factory.annotation.Qualifier; -import javax.annotation.sql.DataSourceDefinition; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; @@ -90,6 +90,7 @@ public interface OrderMapper extends BaseMapperX { IPage selectOrderPage(@Param("page") IPage page, @Param(Constants.WRAPPER) Wrapper wrapper); +// IPage selectOrderPage(@Param("page") IPage page,@Param("pageReqVO") OrderPageReqVOCopy pageReqVO, @Param("organId") Long organId); Map selectDynamicSqlString(@Param("sqlStr") String sqlStr); @@ -143,7 +144,7 @@ public interface OrderMapper extends BaseMapperX { List selectOrderListByIds(@Param("orderIds") List orderIds, @Param("organId") Long organId); - List selectOrderIds(@Param(Constants.WRAPPER) Wrapper wrapper); + IPage selectOrderIds(@Param("page") IPage page, @Param(Constants.WRAPPER) Wrapper wrapper); // 生产单预警统计 List selectOrderNear(@Param("today") LocalDateTime today, @Param("orderDate") LocalDateTime orderDate, @Param("organId") Long organId); @@ -214,4 +215,37 @@ public interface OrderMapper extends BaseMapperX { .eq(OrderDO::getDeleted, OrderDeletedEnum.DELETED.getStatus()) .lt(OrderDO::getUpdateTime, LocalDateTime.now().minusDays(30))).stream().map(OrderDO::getId).collect(Collectors.toList()); } + + default int updateOrderListStatus(List orderIds, Integer status,Long organId) { + return update(new LambdaUpdateWrapper() + .set(OrderDO::getStatus, status) + .in(OrderDO::getId, orderIds) + .eq(OrderDO::getDeleted, 0) + .eq(OrderDO::getOrganId, organId)); + } + + + + List selectTestSQL(@Param("filed") String filed,@Param("orderIds") List orderIds,@Param("organId") Long organId); + + + + + + default List selectOrderIdsList(OrderPageReqVOCopy pageReqVO, List statusList, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(OrderDO::getOrganId, organId) + .eq(OrderDO::getDeleted, false) + .in(OrderDO::getStatus,statusList) + .likeIfPresent(OrderDO::getId,pageReqVO.getOrderId() != null ? pageReqVO.getOrderId().toString() : null) + .inIfPresent(OrderDO::getId,pageReqVO.getOrderIds()) + .likeIfPresent(OrderDO::getCustomOrderNo,pageReqVO.getDefaultId()) + .likeIfPresent(OrderDO::getCustomer,pageReqVO.getConsignee()) + .likeIfPresent(OrderDO::getAddress,pageReqVO.getConsigneeAddress()) + .betweenIfPresent(OrderDO::getCreateTime,pageReqVO.getCreateTime()) + .select(OrderDO::getId)); + + } + + } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderStatisticsMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderStatisticsMapper.java index fc2d6a061..31e06864e 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderStatisticsMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderStatisticsMapper.java @@ -6,13 +6,12 @@ import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisti import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsReqVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsStatusRespVO; import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; +import com.cf.imes.module.executor.enums.OrderDeletedEnum; import com.cf.imes.module.executor.enums.OrderStatusEnum; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; import java.util.List; /** @@ -27,7 +26,7 @@ public interface OrderStatisticsMapper extends BaseMapperX { */ default Integer selectOrderCount() { return Math.toIntExact(selectCount(new LambdaQueryWrapperX() - .eq(OrderDO::getDeleted, 0))); + .eq(OrderDO::getDeleted, OrderDeletedEnum.NOT_DELETED.getStatus()))); } /** @@ -36,6 +35,7 @@ public interface OrderStatisticsMapper extends BaseMapperX { */ default Integer selectOrderCountToday() { return Math.toIntExact(selectCount(new LambdaQueryWrapperX() + .eq(OrderDO::getDeleted, OrderDeletedEnum.NOT_DELETED.getStatus()) .eq(OrderDO::getOrderDate, LocalDate.now()))); } @@ -46,7 +46,9 @@ public interface OrderStatisticsMapper extends BaseMapperX { */ default Integer selectOrderCountTodayFinish() { return Math.toIntExact(selectCount(new LambdaQueryWrapperX() - .between(OrderDO::getFinishTime, LocalDateTime.of(LocalDate.now(), LocalTime.MIN), LocalDateTime.of(LocalDate.now(), LocalTime.MAX)))); + .eq(OrderDO::getDeleted, OrderDeletedEnum.NOT_DELETED.getStatus()) + .eq(OrderDO::getStatus, OrderStatusEnum.FINISH_PRODUCTION.getStatus()) + .eq(OrderDO::getFinishTime, LocalDate.now()))); } /** @@ -55,13 +57,14 @@ public interface OrderStatisticsMapper extends BaseMapperX { */ default Integer selectOrderCountProduce() { return Math.toIntExact(selectCount(new LambdaQueryWrapperX() + .eq(OrderDO::getDeleted, OrderDeletedEnum.NOT_DELETED.getStatus()) .eq(OrderDO::getStatus, OrderStatusEnum.IN_PRODUCTION.getStatus()))); } /** * 生产中生产平方数 * - * @param organId + * @param * @return */ Integer selectOrderSquareProduce(); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderBody/OrderBodyMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderBody/OrderBodyMapper.java index 4e9242919..3c912c3dc 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderBody/OrderBodyMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderBody/OrderBodyMapper.java @@ -4,18 +4,12 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderModuleRespVO; -import com.cf.imes.module.executor.controller.admin.order.vo.product.OrderBodyRespVO; import com.cf.imes.module.executor.controller.admin.order.vo.product.OrderRoomBodyRespVO; -import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; import com.cf.imes.module.executor.dal.dataobject.orderBody.OrderBodyDO; -import com.cf.imes.module.executor.dal.dataobject.orderGroup.OrderGroupDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Update; -import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Set; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderItem/OrderItemMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderItem/OrderItemMapper.java index 5a8971ec1..1e5a65fcd 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderItem/OrderItemMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderItem/OrderItemMapper.java @@ -1,25 +1,18 @@ package com.cf.imes.module.executor.dal.mysql.orderItem; -import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.core.toolkit.Constants; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderModuleRespVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderPlatesDetailRespVO; import com.cf.imes.module.executor.controller.admin.orderParts.vo.OrderPartsRespVO; -import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.OptimizeRemainPlate; +import com.cf.imes.module.executor.controller.admin.plan.bo.OrderRoomBodyList; import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.PrintOrderPackReqVO; import com.cf.imes.module.executor.controller.admin.plate.vo.PlateDetailReqVO; import com.cf.imes.module.executor.controller.admin.plate.vo.PlateDetailRespVO; import com.cf.imes.module.executor.controller.admin.plate.vo.PlateRespVO; -import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; import com.cf.imes.module.executor.dal.dataobject.orderItem.OrderItemDO; -import com.cf.imes.module.executor.dal.dataobject.orderModuleExtra.OrderModuleExtraDO; -import com.cf.imes.module.executor.dal.dataobject.remainplaten.RemainPlateDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Update; import java.util.Collection; import java.util.List; @@ -85,4 +78,29 @@ public interface OrderItemMapper extends BaseMapperX { return delete(new LambdaQueryWrapperX() .in(OrderItemDO::getOrderId, orderId)); } + + + List selectRoomBodyByOrderId( @Param("orderIds") List orderIds, @Param("organId") Long organId); + + + + default List selectPlateIdList(List plateIds, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(OrderItemDO::getOrganId,organId) + .inIfPresent(OrderItemDO::getPlateId, plateIds) + .select(OrderItemDO::getBodyId,OrderItemDO::getRoomId,OrderItemDO::getGroupId)); + + } + + + + + + default List selectPartsList(List partIds, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(OrderItemDO::getOrganId,organId) + .inIfPresent(OrderItemDO::getPlateId, partIds) + .select(OrderItemDO::getNum)); + + } } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderParts/OrderPartsMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderParts/OrderPartsMapper.java index c7537d6b3..d71cdd578 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderParts/OrderPartsMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderParts/OrderPartsMapper.java @@ -1,19 +1,20 @@ package com.cf.imes.module.executor.dal.mysql.orderParts; -import java.util.*; - import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.executor.controller.admin.orderParts.vo.OrderPartsPageReqVO; +import com.cf.imes.module.executor.controller.admin.orderParts.vo.OrderPartsRespVO; +import com.cf.imes.module.executor.controller.admin.orderParts.vo.PartGoodsRespVO; import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.PrintOrderPartsRespVO; -import com.cf.imes.module.executor.dal.dataobject.orderGroup.OrderGroupDO; import com.cf.imes.module.executor.dal.dataobject.orderParts.OrderPartsDO; import org.apache.ibatis.annotations.Mapper; -import com.cf.imes.module.executor.controller.admin.orderParts.vo.*; import org.apache.ibatis.annotations.Param; +import java.util.Collection; +import java.util.List; import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; @@ -84,4 +85,18 @@ public interface OrderPartsMapper extends BaseMapperX { return delete(new LambdaQueryWrapperX() .in(OrderPartsDO::getOrderId, orderId)); } + + + List selectTestSql(@Param("filed") String filed,@Param("partIds") List partIds,@Param("organId") Long organId); + + + + default List selectPartIds(List orderIds, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(OrderPartsDO::getOrganId,organId) + .eq(OrderPartsDO::getDeleted,false) + .in(OrderPartsDO::getOrderId,orderIds) + .select(OrderPartsDO::getId)); + } + } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plan/PlanMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plan/PlanMapper.java index 33ef05b45..a8845c51e 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plan/PlanMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plan/PlanMapper.java @@ -1,21 +1,21 @@ package com.cf.imes.module.executor.dal.mysql.plan; -import java.util.*; - import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.mybatis.core.query.MPJLambdaWrapperX; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsReqVO; +import com.cf.imes.module.executor.controller.admin.plan.vo.*; import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; import com.cf.imes.module.executor.dal.dataobject.orderItem.OrderItemDO; import com.cf.imes.module.executor.dal.dataobject.plan.PlanDO; import com.cf.imes.module.executor.dal.dataobject.planitem.PlanItemDO; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.annotations.Mapper; -import com.cf.imes.module.executor.controller.admin.plan.vo.*; import org.apache.ibatis.annotations.Param; +import java.util.List; + import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; /** @@ -100,4 +100,19 @@ public interface PlanMapper extends BaseMapperX { * @return */ List selectPlanAreaGroupByCreateTime(@Param("req") OrderStatisticsReqVO reqVO); + + + List seleTestSQL(@Param("filed") String filed,@Param("planId") Long planId,@Param("organId") Long organId); + + + + List selectPlanIds(@Param("updateTime") String updateTime,@Param("sort") Long sort,@Param("organId") Long organId,@Param("planId") Long planId); + + + + List selectPlanIdsFalse(@Param("updateTime") String updateTime,@Param("sort") Long sort,@Param("organId") Long organId,@Param("planId") Long planId); + + +// List seleTestSQL(@Param("sql") String sql); + } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/planitem/PlanItemMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/planitem/PlanItemMapper.java index 055c61835..9b88e9067 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/planitem/PlanItemMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/planitem/PlanItemMapper.java @@ -1,17 +1,14 @@ package com.cf.imes.module.executor.dal.mysql.planitem; -import java.util.*; - -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; -import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderRespVO; import com.cf.imes.module.executor.controller.admin.plan.vo.PlanOrderRespVO; import com.cf.imes.module.executor.controller.admin.plan.vo.PlateInfoVO; import com.cf.imes.module.executor.dal.dataobject.planitem.PlanItemDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import java.util.List; + /** * 生产单开料排单明细 Mapper * diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java index 46831309e..096387e97 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java @@ -1,23 +1,29 @@ package com.cf.imes.module.executor.dal.mysql.plate; -import java.math.BigDecimal; -import java.util.*; - import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.cf.imes.framework.common.enums.OrderPlateTypeEnum; import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.module.executor.controller.admin.plan.bo.GoodsNum; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderIds; import com.cf.imes.module.executor.controller.admin.plan.vo.*; +import com.cf.imes.module.executor.controller.admin.plate.vo.PlateGoodsIdVO; +import com.cf.imes.module.executor.controller.admin.plate.vo.PlateGoodsRespVO; +import com.cf.imes.module.executor.controller.admin.plate.vo.PlatePageReqVO; +import com.cf.imes.module.executor.controller.admin.plate.vo.PlateRespVO; import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO; import org.apache.ibatis.annotations.Mapper; -import com.cf.imes.module.executor.controller.admin.plate.vo.*; import org.apache.ibatis.annotations.Param; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; +import java.util.Set; + import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; /** @@ -120,7 +126,9 @@ public interface PlateMapper extends BaseMapperX { List selectPlateGoodsListByList(@Param("plates") List goodsIdList, @Param("orderId") Long orderId, @Param("organId") Long organId); - List selectGoodsPage( @Param("orderIds") List orderIds, @Param("organId") Long organId); +// List selectGoodsPage( @Param("orderIds") List orderIds, @Param("organId") Long organId); + + List selectGoodsPage( @Param(Constants.WRAPPER) Wrapper wrapper); IPage selectGoodsList(@Param("page") IPage page,@Param("goodsIds") List goodsIds,@Param("organId") Long organId); @@ -152,9 +160,67 @@ public interface PlateMapper extends BaseMapperX { .eq(PlateDO::getOrganId, organId) .eqIfPresent(PlateDO::getOrderId, orderId)); } + + + + default List selectGoodsPlateList(List goodIds, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(PlateDO::getOrganId,organId) + .inIfPresent(PlateDO::getGoodsId, goodIds)); + + + } + + + List selectPlateListByGoodIds(@Param("goodIds") List goodIds,@Param("organId") Long organId); + + + List selectPlateArea(@Param("orderIdsList") List orderIdsList,@Param("organId") Long organId); + + + + default List selectPlateByPlateNo(List plateNo, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(PlateDO::getOrganId,organId) + .inIfPresent(PlateDO::getPlateNo, plateNo) + .select(PlateDO::getOrderId)); + + } + + + + default List selectPlateListByGoodsIds(List deleteIds, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(PlateDO::getOrganId,organId) + .inIfPresent(PlateDO::getGoodsId, deleteIds) + .select(PlateDO::getPlateNo)); + + } + + // 批量删除 default int deleteBatch(Collection orderId) { return delete(new LambdaQueryWrapperX() .in(PlateDO::getOrderId, orderId)); } + + + List selectTestSQL(@Param("filed") String filed, @Param("field2") String field2,@Param("goodsIdList") List goodsIdList,@Param("organId") Long organId); + + + + default List selectPlateIdList(List goodsIdList, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(PlateDO::getOrganId,organId) + .eq(PlateDO::getDeleted,false) + .inIfPresent(PlateDO::getGoodsId,goodsIdList) + .eq(PlateDO::getType, OrderPlateTypeEnum.SELFINCREASINGBOARD.getType()) + .select(PlateDO::getId)); + + } + + +// List selectTestSQL(@Param("sql") String sql); + + } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/remainplaten/RemainPlateMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/remainplaten/RemainPlateMapper.java index 8d8bd2545..51a56abdb 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/remainplaten/RemainPlateMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/remainplaten/RemainPlateMapper.java @@ -4,11 +4,10 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.OptimizeRemainPlate; import com.cf.imes.module.executor.controller.admin.remainplate.vo.RemainPlatePageReqVO; -import com.cf.imes.module.executor.dal.dataobject.processStep.ProcessStepDO; import com.cf.imes.module.executor.dal.dataobject.remainplaten.RemainPlateDO; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.Collection; import java.util.List; @@ -59,4 +58,9 @@ public interface RemainPlateMapper extends BaseMapperX { .in(RemainPlateDO::getId, ids) .eq(RemainPlateDO::getOrganId, organId)); } + + List selectTestSQL(@Param("filed") String filed,@Param("planId") Long planId,@Param("organId") Long organId); + + +// List selectTestSQL(@Param("sql") String sql); } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/enums/OrderPlanStatusEnum.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/enums/OrderPlanStatusEnum.java deleted file mode 100644 index 4f993f5a8..000000000 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/enums/OrderPlanStatusEnum.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.cf.imes.module.executor.enums; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -/** - * 排单状态 - * - * @author Gqr - * @since 2024/6/7 14:25 - */ -@RequiredArgsConstructor -@Getter -public enum OrderPlanStatusEnum { - NEW(0, "新单"), - - APPLY(1, "板材已申请"), - - OPENING(2, "开料中"), - - OPENED(3, "已开料"); - - /** - * 类型编码 - */ - private final Integer code; - - /** - * 描述 - */ - private final String desc; -} \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java index d7707899b..b48efa051 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java @@ -5,6 +5,7 @@ import com.cf.imes.module.report.api.template.ReportTemplateApi; import com.cf.imes.module.system.api.application.ApplicationApi; import com.cf.imes.module.system.api.dataSource.DataSourceApi; import com.cf.imes.module.system.api.machine.MachineApi; +import com.cf.imes.module.system.api.organ.OrganApi; import com.cf.imes.module.system.api.process.ProcessApi; import com.cf.imes.module.system.api.process.ProcessGroupApi; import com.cf.imes.module.system.api.user.AdminUserApi; @@ -17,6 +18,6 @@ import org.springframework.context.annotation.Configuration; */ @Configuration(proxyBeanMethods = false) @EnableFeignClients(clients = {AdminUserApi.class, MachineApi.class, DictDataApi.class,AdminUserApi.class, - FileApi.class, ProcessGroupApi.class, FileApi.class, DataSourceApi.class, ApplicationApi.class, ProcessApi.class, ReportTemplateApi.class}) + FileApi.class, ProcessGroupApi.class, FileApi.class, DataSourceApi.class, ApplicationApi.class, ProcessApi.class, ReportTemplateApi.class, OrganApi.class}) public class RpcConfiguration { } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java index efd479af2..82c13fc68 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java @@ -1,10 +1,13 @@ package com.cf.imes.module.executor.service.optimizeplan; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderSource; +import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.CuttingStatusRespVO; import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.SavePlanPlateResultReqVO; import com.cf.imes.module.executor.controller.admin.plan.vo.*; +import com.cf.imes.module.executor.dal.dataobject.goods.OptimizeBoardModelDO; import com.cf.imes.module.executor.dal.dataobject.ordermodel.OrderModelDO; +import java.util.Collection; import java.util.List; import java.util.Map; @@ -18,19 +21,17 @@ public interface OptimizePlanService { Boolean addRemain(AddRemainReqVO vo); - Boolean savePlanPlateResult(SavePlanPlateResult result); - Boolean commit(Long planId); + Boolean commit(Long planId, List goodsNo); + + Boolean updateCuttingStatus(CuttingStatusRespVO respVO); Boolean endCutting(Long planId); - OptimizeParamResVO getOptimizeParam(Long planId); - - OptimizeParamRespVO getOptimizePlanParam(Long planId); Map getLabelDataSourceValue(GetSourceDataReq req); - OrderSource getOrderSource(Long orderId, Long planId, Long machineId); + OrderSource getOrderSource(Long orderId, Long planId, Long machineId,List ids); OrderSource getOrderSourceByOrderId(Long orderId); @@ -41,4 +42,10 @@ public interface OptimizePlanService { List getPlateModel(Long orderId); + + List buildBoardByOrderIds(Collection orderIds, String index, Integer size); + + + String deleteTest(List id); + } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java index 8c57aa199..629bf739b 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.Snowflake; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._types.FieldValue; import co.elastic.clients.elasticsearch.core.*; @@ -12,26 +11,20 @@ import co.elastic.clients.elasticsearch.core.search.Hit; import com.alibaba.fastjson.JSON; import com.cf.imes.framework.common.enums.OrderStatusEnum; import com.cf.imes.framework.common.enums.PlanStatusEnum; -import com.cf.imes.framework.common.enums.ProcessProcessingTypeEnum; import com.cf.imes.framework.common.enums.RemainTypeEnum; import com.cf.imes.framework.common.exception.ServiceException; -import com.cf.imes.framework.common.util.json.JsonUtils; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.es.core.service.ESDocumentService; -import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.mybatis.core.query.MPJLambdaWrapperX; import com.cf.imes.framework.security.core.LoginUser; +import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderSource; import com.cf.imes.module.executor.controller.admin.plan.bo.ProcessGroupList; import com.cf.imes.module.executor.controller.admin.plan.bo.ProcessStepAreaIds; import com.cf.imes.module.executor.controller.admin.plan.bo.ProcessStepSalaryIds; -import com.cf.imes.module.executor.controller.admin.plan.dto.Material; -import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.OptimizeRemainPlate; -import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.PrintOrderPackReqVO; -import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.PrintOrderPartsRespVO; -import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.SavePlanPlateResultReqVO; +import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.*; import com.cf.imes.module.executor.controller.admin.plan.vo.*; -import com.cf.imes.module.executor.controller.admin.plate.vo.PlateDetailVO; +import com.cf.imes.module.executor.dal.dataobject.goods.CutedBoardInfo; import com.cf.imes.module.executor.dal.dataobject.goods.GoodsDO; import com.cf.imes.module.executor.dal.dataobject.goods.OptimizeBoardModelDO; import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; @@ -41,8 +34,6 @@ import com.cf.imes.module.executor.dal.dataobject.plan.PlanDO; import com.cf.imes.module.executor.dal.dataobject.planitem.PlanItemDO; import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO; import com.cf.imes.module.executor.dal.dataobject.processStep.ProcessStepDO; -import com.cf.imes.module.executor.dal.dataobject.remainplaten.OutlineDTO; -import com.cf.imes.module.executor.dal.dataobject.remainplaten.PointDTO; import com.cf.imes.module.executor.dal.dataobject.remainplaten.RemainPlateDO; import com.cf.imes.module.executor.dal.mysql.goods.GoodsMapper; import com.cf.imes.module.executor.dal.mysql.order.OrderMapper; @@ -54,33 +45,32 @@ import com.cf.imes.module.executor.dal.mysql.processStep.ProcessStepMapper; import com.cf.imes.module.executor.dal.mysql.processStepItem.ProcessStepItemMapper; import com.cf.imes.module.executor.dal.mysql.remainplaten.RemainPlateMapper; import com.cf.imes.module.executor.enums.ErrorCodeConstants; -import com.cf.imes.module.executor.util.RandomUtils; -import com.cf.imes.module.executor.util.RectangleChecker; import com.cf.imes.module.infra.api.file.FileApi; -import com.cf.imes.module.infra.api.file.dto.FileCreateReqDTO; import com.cf.imes.module.system.api.dataSource.DataSourceApi; import com.cf.imes.module.system.api.machine.MachineApi; import com.cf.imes.module.system.api.process.ProcessApi; import com.cf.imes.module.system.api.process.dto.ProcessDTO; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.github.yulichang.wrapper.MPJLambdaWrapper; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.io.IOException; -import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; -import static com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; -import static com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants.UNKNOWN; +import static com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants.*; import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getLoginUser; import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_NOT_EXISTS; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.PLAN_NOT_EXISTS; -import org.springframework.transaction.annotation.Transactional; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.INSUFFICIENT_PERMISSIONS; /** * @author there @@ -163,55 +153,200 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { return Boolean.TRUE; } - @Override - public Boolean savePlanPlateResult(SavePlanPlateResult result) { - return null; -// PlanDO planDO = planMapper.selectById(result.getPlanId()); -// if (Objects.isNull(planDO)) { -// throw exception(PLAN_NOT_EXISTS); -// } -// try { -// String placeDateFileUrlSource = planDO.getPlaceDateFileUrl(); -// String placeOrderFileUrlSource = planDO.getPlaceOrderFileUrl(); -// if (StrUtil.isNotBlank(placeDateFileUrlSource)) { -// fileApi.deleteFileByPath(placeDateFileUrlSource).checkError(); -// } -// if (StrUtil.isNotBlank(placeOrderFileUrlSource)) { -// fileApi.deleteFileByPath(placeOrderFileUrlSource).checkError(); -// } -// FileCreateReqDTO fileCreateReqDTO = new FileCreateReqDTO(); -// -// fileCreateReqDTO.setContent(result.getPlaceData().getBytes()); -// fileCreateReqDTO.setName(result.getPlaceData().getOriginalFilename()); -// String placeDateFileUrl = fileApi.createFile(fileCreateReqDTO).getCheckedData(); -// -// fileCreateReqDTO.setContent(result.getPlaceOrder().getBytes()); -// fileCreateReqDTO.setName(result.getPlaceOrder().getOriginalFilename()); -// String placeOrderFileUrl = fileApi.createFile(fileCreateReqDTO).getCheckedData(); -// -// PlanDO updateDO = PlanDO.builder() -// .id(result.getPlanId()) -// .placeDateFileUrl(placeOrderFileUrl) -// .placeOrderFileUrl(placeDateFileUrl) -// .build(); -// planMapper.updateById(updateDO); -// -// } catch (IOException e) { -// throw exception(UNKNOWN); -// } -// return Boolean.TRUE; - } @Override - public Boolean commit(Long planId) { + @Transactional(rollbackFor = Exception.class) + public Boolean commit(Long planId, List goodsNo) { + PlanDO planDO = planMapper.selectById(planId); if (Objects.isNull(planDO)) { throw exception(PLAN_NOT_EXISTS); } - planMapper.updateById(PlanDO.builder() - .id(planId) - .status(PlanStatusEnum.DURINGCUTTING.getStatus()) - .build()); + + + // todo 目前只解决了非混单的情况,混单情况待解决 + List optimizeBoardModelDOS = buildBoardByPlanId(planId, ORDER_REMAIN_PLATE_MODEL, 10); + + OptimizeBoardModelDO optimizeBoardModelDO = optimizeBoardModelDOS.get(0); + + List plateNo = new ArrayList<>(); + + // 创建一个列表存储 BlockPlaceInfo 对象,将优化的小板信息拿出,获取到小板编号,查询生产单,修改生产单的状态 + List outputList = new ArrayList<>(); + + ObjectMapper mapper = new ObjectMapper(); + + try { + // 解析 JSON 字符串 + JsonNode jsonArray = mapper.readTree(optimizeBoardModelDO.getBlockPlaceInfo()); + + // 遍历 JSON 数组并提取所需字段 + if (jsonArray.isArray()) { + for (JsonNode jsonNode : jsonArray) { + Long bi = jsonNode.get("bi").asLong(); + Long bo = jsonNode.get("bo").asLong(); + outputList.add(new BlockPlaceInfo(bi,bo)); + } + } + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + + for (Long goods : goodsNo) { + plateNo.addAll(outputList.stream().filter(f -> f.getBi().equals(goods)).map(BlockPlaceInfo::getBo).distinct().toList()); + } + + + + List plateDOS = plateMapper.selectPlateByPlateNo(plateNo.stream().distinct().toList(), getUserOrganId()); + + + List orderIds = plateDOS.stream().map(PlateDO::getOrderId).distinct().toList(); + + + + // 修改生产单的状态 + orderMapper.updateOrderListStatus(orderIds,OrderStatusEnum.IN_PRODUCTION.getStatus(),getUserOrganId()); + + + CutedBoardInfo cutedBoardInfo = optimizeBoardModelDO.getCutedBoardInfo(); + + + // 获取原排单的开料大板数 + 新增的开料大板数 + long cutedBoardNumber = cutedBoardInfo.getCutedBoardNumber() ; + + + cutedBoardNumber += goodsNo.size(); + + + // 获取原排单的已开料的大板编号 + List cutedBoardList = cutedBoardInfo.getCutedBoardList() == null ? new ArrayList<>() : cutedBoardInfo.getCutedBoardList(); + + + // 将新开料的大板编号添加到已开料的大板编号中 + cutedBoardList.addAll(goodsNo); + + + // 将需要更新更新的数据更新到原数据中 + cutedBoardInfo.setCutedBoardNumber(cutedBoardNumber); + cutedBoardInfo.setCutedBoardList(cutedBoardList); + + + // 更新开料相关的数据 + HashMap objectObjectHashMap = new HashMap<>(); + objectObjectHashMap.put("cutedBoardInfo",cutedBoardInfo); + + try { + + esDocumentService.updateById(ORDER_REMAIN_PLATE_MODEL, optimizeBoardModelDO.getId(), HashMap.class, objectObjectHashMap); + + }catch (IOException e) { + log.error(e.getMessage()); + throw new ServiceException(ES_ERROR_UPDATE); + } + + if(cutedBoardNumber > 0){ + + planDO.setStatus(PlanStatusEnum.OPENING.getStatus()); + planMapper.updateById(planDO); + + } + + if(optimizeBoardModelDO.getBoardCount() == cutedBoardNumber){ + + planDO.setStatus(PlanStatusEnum.OPENED.getStatus()); + planDO.setProduceTime(LocalDateTime.now()); + + planMapper.updateById(planDO); + + } + + return Boolean.TRUE; + } + + + + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean updateCuttingStatus(CuttingStatusRespVO respVO) { + + Long planId = respVO.getPlanId(); + List goodsNo = respVO.getGoodsNo(); + +// LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); +// assert loginUser != null; +// +// if(!loginUser.getIsSupAdmin()){ +// +// throw exception(INSUFFICIENT_PERMISSIONS); +// +// } + + PlanDO planDO = planMapper.selectById(planId); + if (planDO == null) { + throw exception(PLAN_NOT_EXISTS); + } + + // todo 目前只解决了非混单的情况,混单情况待解决 + List optimizeBoardModelDOS = buildBoardByPlanId(planId, ORDER_REMAIN_PLATE_MODEL, 99); + + OptimizeBoardModelDO optimizeBoardModelDO = optimizeBoardModelDOS.get(0); + + CutedBoardInfo cutedBoardInfo = optimizeBoardModelDO.getCutedBoardInfo() == null ? new CutedBoardInfo() : optimizeBoardModelDO.getCutedBoardInfo(); + + + if(cutedBoardInfo.getCutedBoardNumber() != null) { + // 已经开料的大板信息 + List cutedBoardList = cutedBoardInfo.getCutedBoardList(); + // 开料的大板数量 + long cutedBoardNumber = cutedBoardInfo.getCutedBoardNumber(); + + // 移除取消开料的数据 + cutedBoardList.removeAll(goodsNo); + // 减去取消开料的大板数量 + cutedBoardNumber -= (goodsNo.isEmpty() ? 0 : goodsNo.size()); + + + // 将需要更新更新的数据更新到原数据中 + cutedBoardInfo.setCutedBoardNumber(cutedBoardNumber); + cutedBoardInfo.setCutedBoardList(cutedBoardList); + + + // 更新开料相关的数据 + HashMap objectObjectHashMap = new HashMap<>(); + objectObjectHashMap.put("cutedBoardInfo", cutedBoardInfo); + + try { + + esDocumentService.updateById(ORDER_REMAIN_PLATE_MODEL, optimizeBoardModelDO.getId(), HashMap.class, objectObjectHashMap); + + } catch (IOException e) { + log.error(e.getMessage()); + throw new ServiceException(ES_ERROR_UPDATE); + } + + if(cutedBoardInfo.getCutedBoardNumber() == 0){ + + planDO.setStatus(PlanStatusEnum.NOCUTTING.getStatus()); + planDO.setProduceTime(null); + planMapper.updateById(planDO); + + } + + if(planDO.getStatus().equals(PlanStatusEnum.OPENED.getStatus()) && cutedBoardInfo.getCutedBoardNumber() > 0 && cutedBoardInfo.getCutedBoardNumber() < optimizeBoardModelDO.getBoardCount() ){ + planDO.setStatus(PlanStatusEnum.OPENING.getStatus()); + planDO.setProduceTime(null); + planMapper.updateById(planDO); + } + + } + + + // todo 待确认,是否要达到这样的需求 : 生产单的状态也应该更改,如果大板变为未开料,生产单对应的状态应该变为已排单(这时取消开料对应的大板对应的生产单应该在其他排单中不存在,可修改) + + + return Boolean.TRUE; } @@ -224,7 +359,7 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { } planMapper.updateById(PlanDO.builder() .id(planId) - .status(PlanStatusEnum.OPENEDMATERIAL.getStatus()) + .status(PlanStatusEnum.OPENED.getStatus()) .produceTime(LocalDateTime.now()) .build()); @@ -281,93 +416,6 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { } - @Override - public OptimizeParamResVO getOptimizeParam(Long planId) { - //小板列表 - List plates = plateMapper.selectPlateList(planId); - //余料规格列表 - List remainPlateDOS = remainPlateMapper.selectList(new LambdaQueryWrapperX().eq(RemainPlateDO::getPlanId, planId)); - //余料板规格 - List rawSizes = new ArrayList<>(); - List remainPlateCount = new ArrayList<>(); - if (CollectionUtil.isNotEmpty(remainPlateDOS)) { - Map> map = remainPlateDOS.stream() - .map(e -> OutlineDTO.builder() - .list(JsonUtils.parseArray(e.getOutLineJson(), PointDTO.class)) - .length(e.getLength()) - .width(e.getWidth()) - .build() - ) - .filter(e -> e.getList().size() == 4 && RectangleChecker.checkRectangle(e.getList())) - .collect(Collectors.groupingBy(e -> e.getLength() + "," + e.getWidth())); - map.entrySet().forEach(e -> { - String[] split = e.getKey().split(","); - BigDecimal length = new BigDecimal(split[0]); - BigDecimal width = new BigDecimal(split[1]); - List outlines = e.getValue(); - rawSizes.add(OptimizeParamResVO.RawSize.builder() - .length(length) - .width(width) - .x(new BigDecimal(outlines.get(0).getList().get(0).getX())) - .y(new BigDecimal(outlines.get(0).getList().get(0).getY())) - .build()); - remainPlateCount.add(outlines.size()); - }); - } - - //大板规格 - /** - * select * from order_goods a - * left join order_plate b on a.goods_id = b.goods_id - * left join order_item c on b.id = c.plate_id - * left join order_plan_item d on c.id = d.item_id - * where d.plan_id = 1769638780093857792 - */ - MPJLambdaWrapper wrapper = new MPJLambdaWrapperX() - .distinct() - .select(GoodsDO::getId, GoodsDO::getWidth, GoodsDO::getHeight) - .leftJoin(PlateDO.class, PlateDO::getGoodsId, GoodsDO::getGoodsId) - .leftJoin(OrderItemDO.class, OrderItemDO::getPlanId, PlateDO::getPlateNo) - .leftJoin(PlanItemDO.class, PlanItemDO::getItemId, OrderItemDO::getId) - .eq(PlanItemDO::getPlanId, planId); - - GoodsDO goodsDO = goodsMapper.selectJoinOne(GoodsDO.class, wrapper); - rawSizes.add(OptimizeParamResVO.RawSize.builder() - .width(goodsDO.getWidth()) - .length(goodsDO.getHeight()) - .x(new BigDecimal("0")) - .y(new BigDecimal("0")) - .build()); - return OptimizeParamResVO.builder() - .plates(plates) - .rawSizes(rawSizes) - .remainPlateCount(remainPlateCount) - .build(); - - } - - @Override - public OptimizeParamRespVO getOptimizePlanParam(Long planId) { - - OptimizeParamRespVO optimizePlanParam = planMapper.getOptimizePlanParam(planId); - - if (Objects.isNull(optimizePlanParam)) { - return RandomUtils.randomPojo(OptimizeParamRespVO.class); - } - //暂时先mock - ArrayList list = new ArrayList<>(); - list.add(RandomUtils.randomPojo(Material.class)); - list.add(RandomUtils.randomPojo(Material.class)); - ArrayList plateDetailVOS = new ArrayList<>(); - plateDetailVOS.add(RandomUtils.randomPojo(PlateDetailVO.class)); - plateDetailVOS.add(RandomUtils.randomPojo(PlateDetailVO.class)); - plateDetailVOS.add(RandomUtils.randomPojo(PlateDetailVO.class)); - if (CollectionUtil.isNotEmpty(optimizePlanParam.getPlateList())) { - optimizePlanParam.getPlateList().get(0).setPlateDetailList(plateDetailVOS); - } - optimizePlanParam.setMaterialList(list); - return optimizePlanParam; - } @Override public Map getLabelDataSourceValue(GetSourceDataReq req) { @@ -383,9 +431,9 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { } @Override - public OrderSource getOrderSource(Long orderId, Long planId, Long machineId) { - if (!Objects.isNull(orderId) && !Objects.isNull(planId)) { - throw exception(154112, "生产单id与排单id只能传一个"); + public OrderSource getOrderSource(Long orderId, Long planId, Long machineId,List ids) { + if (!Objects.isNull(orderId) && !Objects.isNull(planId) && !Objects.isNull(ids)) { + throw exception(154112, "生产单id与排单id与大板分类ID只能传一个"); } OrderSource orderSource; if (ObjectUtil.isNotNull(orderId)) { @@ -398,6 +446,11 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { orderSource.setMachineDTO(machineApi.getMachineDetail(machineId).getCheckedData()); return orderSource; } + if (ObjectUtil.isNotNull(ids)) { + orderSource = getOrderSourceByGoodId(ids); + orderSource.setMachineDTO(machineApi.getMachineDetail(machineId).getCheckedData()); + return orderSource; + } throw exception(ErrorCodeConstants.SOURCE_NOT_EXITS_ERROR); } @@ -476,7 +529,7 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { throw exception(PLAN_NOT_EXISTS); } MPJLambdaWrapper wrapper = new MPJLambdaWrapperX() - .select(OrderItemDO::getOrderId) + .select(OrderItemDO::getOrderId,OrderItemDO::getPlateId) .rightJoin(PlanItemDO.class, PlanItemDO::getItemId, OrderItemDO::getId) .eq(PlanItemDO::getPlanId, planId) .isNotNull(OrderItemDO::getId); @@ -488,9 +541,14 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { // List goodsDOS = goodsMapper.selectList(new LambdaQueryWrapperX().in(GoodsDO::getOrderId, orderIds)); - List goodsDOS = goodsMapper.selectGoodsListByOrderIds(orderIds,getUserOrganId()); - List plateDOS = plateMapper.selectPlateDetialListByIds(orderIds,getUserOrganId()); + List plateIds = orderItemDOS.stream().map(OrderItemDO::getPlateId).distinct().toList(); + + List goodsIds = plateMapper.selectBatchIds(plateIds).stream().map(PlateDO::getGoodsId).distinct().toList(); + + List goodsDOS = goodsMapper.selectGoodsListByOrderIds(goodsIds,getUserOrganId()); + + List plateDOS = plateMapper.selectPlateDetialListByIds(plateIds,getUserOrganId()); for (PlateDetialRespVO plateDetailsRespVO : plateDOS) { String name = ""; @@ -544,38 +602,102 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { } + public OrderSource getOrderSourceByGoodId(List ids) { + +// PlanDO planDO = planMapper.selectById(planId); +// if (Objects.isNull(planDO)) { +// throw exception(PLAN_NOT_EXISTS); +// } + + +// List goodsDOS = goodsMapper.selectBatchIds(goodIds); + + List goodsReqVOS = goodsMapper.selectJoinList(GoodsReqVO.class, new MPJLambdaWrapperX() + + .leftJoin(RemainPlateDO.class, RemainPlateDO::getGoodsId, GoodsDO::getId) + .selectAll(GoodsDO.class) + .selectAs(RemainPlateDO::getId,"remainId") + .isNotNull(PlanItemDO::getId) + .eq(GoodsDO::getOrganId, getUserOrganId()) + .in(GoodsDO::getId, ids)); + + + + List orderIds = goodsReqVOS.stream().map(GoodsReqVO::getOrderId).distinct().toList(); + + List orderDOS = orderMapper.selectBatchIds(orderIds); + + List plateDetialRespVOS = plateMapper.selectPlateListByGoodIds(ids, getUserOrganId()); + + + for (PlateDetialRespVO plateDetailsRespVO : plateDetialRespVOS) { + String name = ""; + if(!plateDetailsRespVO.getProcessGroupLists().isEmpty()) { + for (ProcessGroupList groupNameList : plateDetailsRespVO.getProcessGroupLists()) { + // 去除最后的逗号 + name += groupNameList.getGroupName() + ","; + + } + name = name.substring(0, name.length() - 1); + } + + plateDetailsRespVO.setProcessGroupName(name); + + plateDetailsRespVO.setGoodsId(goodsReqVOS + .stream() + .filter(f->f.getId().equals(plateDetailsRespVO.getId())) + .map(GoodsReqVO::getGoodsId) + .findAny().orElse(null)); + } + + + // 造型数据的尺寸长度 + Integer orderModelSize = plateDetialRespVOS.size(); + + List orderModelDOS = buildRespByOrderIds(orderIds, ORDER_PLATE_MODEL, orderModelSize); + + +// // 查询生产单对应的配件信息 +// List printOrderPartsRespVOS = orderPartsMapper.selectPartList(orderIds, getUserOrganId()); +// +// // 查询生产单对应的包裹信息 +// List printOrderPackReqVOS = orderItemMapper.selectPackList(orderIds, getUserOrganId()); + + return OrderSource.builder() + .orderList(orderDOS) + .goodsList(goodsReqVOS) + .plateList(plateDetialRespVOS) + .plateModels(orderModelDOS) + .build(); + } + + + + + // 保存优化后的数据 @Override @Transactional(rollbackFor = Exception.class) public void saveOptimizationResults(SavePlanPlateResultReqVO req) { -// // 判断当前的大板数据是否已经优化,有优化,更新,没有,新增 -// if (req.getOptimizeBoardModelDOS().get(0).getIsOptimized().equals(true)) { -// try { -// // 更新大板的优化数据 -// BulkResponse bulkResponse = esDocumentService.bulkUpdate(ORDER_REMAIN_PLATE_MODEL, req.getOptimizeBoardModelDOS()); -// boolean errors = bulkResponse.errors(); -// if (errors) { -// log.error(bulkResponse.items().toString()); -// throw new ServiceException(500, "未知异常"); -// } -// } catch (Exception e) { -// e.printStackTrace(); -// log.error(e.getMessage()); -// throw new RuntimeException(e); -// } -// } -// else { + // 先根据排单查找是否有优化数据,如果有,删除 + List planIds = req.getOptimizeBoardModelDOS().stream().map(OptimizeBoardModelDO::getPlanId).toList(); - // 保存优化后的大板数据 - batchSaveBoardModel(req.getOptimizeBoardModelDOS()); + List optimizeBoardModelDOS = buildBoardByPlanIds(planIds, ORDER_REMAIN_PLATE_MODEL, planIds.size()); + if(!optimizeBoardModelDOS.isEmpty()){ -// } + deleteByPlanId(planIds,ORDER_REMAIN_PLATE_MODEL); + + } + + + // 保存优化后的大板数据 + batchSaveBoardModel(req.getOptimizeBoardModelDOS()); if (CollectionUtil.isNotEmpty(req.getOptimizeRemainPlates())) { - ArrayList remainPlateDOS = new ArrayList(); + ArrayList remainPlateDOS = new ArrayList<>(); for (OptimizeRemainPlate optimizeRemainPlate : req.getOptimizeRemainPlates()) { remainPlateDOS.add(RemainPlateDO.builder() @@ -603,16 +725,6 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { } remainPlateMapper.updateBatch(remainPlateDOS); -// for (RemainPlateDO remainPlateDO : remainPlateDOS) { -// -//// if(remainPlateDO.getId() != null){ -//// remainPlateMapper.insert(remainPlateDO); -//// -//// } -// -// remainPlateMapper.updateById(remainPlateDO); -// -// } } @@ -622,24 +734,17 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { if (CollectionUtil.isNotEmpty(req.getAddPlateIds())) { List addPlates = req.getPlateList().stream() - .filter(m -> req.getAddPlateIds().contains(m.getId())) - .map(m -> m.setId(null)) + .filter(m -> req.getAddPlateIds().contains(m.getPlateId())) + .map(m -> m.setPlateId(null)) .collect(Collectors.toList()); - -// List collect = req.getPlateList().stream().map(m -> m.getId()).collect(Collectors.toList()); -// List addPlateIds = req.getAddPlateIds().stream().filter(m -> !collect.contains(m)).collect(Collectors.toList()); -// List addPlates = req.getPlateList().stream() -// .filter(m -> addPlateIds.contains(m.getId())) -// .map(m->m.setId(null)) -// .collect(Collectors.toList()); // 批量新增小板信息 List plateDOS = BeanUtils.toBean(addPlates, PlateDO.class); plateMapper.insertBatch(plateDOS); // 批量新增生产单明细表信息 - ArrayList orderItemDOS = new ArrayList(); + ArrayList orderItemDOS = new ArrayList<>(); for (PlateDetialRespVO plateDetialRespVO : req.getPlateList()) { orderItemDOS.add(OrderItemDO.builder() @@ -649,7 +754,7 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { // .groupId(Long.valueOf(plateDetialRespVO.getProcessGroupId())) .orderId(plateDetialRespVO.getOrderId()) .type(1) - .plateId(plateDetialRespVO.getId()) + .plateId(plateDetialRespVO.getPlateId()) .build()); } @@ -782,7 +887,9 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { } } - private List buildBoardByOrderIds(Collection orderIds, String index, Integer size) { + + @Override + public List buildBoardByOrderIds(Collection orderIds, String index, Integer size) { List fieldValues = orderIds.stream().map(FieldValue::of).toList(); SearchRequest.Builder builder = new SearchRequest.Builder(); builder.index(index); @@ -802,5 +909,59 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { } + public List buildBoardByPlanIds(Collection planIds, String index, Integer size) { + List fieldValues = planIds.stream().map(FieldValue::of).toList(); + SearchRequest.Builder builder = new SearchRequest.Builder(); + builder.index(index); + builder.size(size); + builder.query(q -> q.terms(b -> b.field("planId").terms(e -> e.value(fieldValues)))); + try { + SearchResponse search = elasticsearchClient.search(builder.build(), OptimizeBoardModelDO.class); + List> hits = search.hits().hits(); + if (CollectionUtil.isNotEmpty(hits)) { + return hits.stream().map(Hit::source).collect(Collectors.toList()); + } + return new ArrayList<>(); + } catch (IOException e) { + log.error(e.getMessage()); + throw new ServiceException(INTERNAL_SERVER_ERROR); + } + } + + + public void deleteByPlanId(List planIds, String index) { + List fieldValues = planIds.stream().map(FieldValue::of).toList(); + + DeleteByQueryRequest.Builder builder = new DeleteByQueryRequest.Builder(); + builder.index(index); + + builder.query(q -> q.terms(b -> b.field("planId").terms(e -> e.value(fieldValues)))); + + try { + DeleteByQueryResponse response = elasticsearchClient.deleteByQuery(builder.build()); + log.info("Deleted {} documents with planId {}", response.deleted(), planIds); + } catch (IOException e) { + log.error("Error deleting documents with planId {}: {}", planIds, e.getMessage()); + throw new ServiceException(ES_ERROR_DELETE); + } + } + + + + @Override + public String deleteTest(List orderIds) { + + Long a = 1801515154546884609L; + + + List optimizeBoardModelDOS = buildBoardByPlanId(a, ORDER_REMAIN_PLATE_MODEL, 999); + + System.out.println("哈哈哈哈哈1 "+optimizeBoardModelDOS); + + + return null; + + } + } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsService.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsService.java index 51d8ad19a..e7645b35c 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsService.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsService.java @@ -72,4 +72,12 @@ public interface OrderStatisticsService { * @return */ Map getOrderPlateAreaGroup(OrderStatisticsReqVO reqVO); + + /** + * 大板数量分组统计 + * + * @param reqVO + * @return + */ + Map getBigPlateCountGroup(OrderStatisticsReqVO reqVO); } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java index f98679ff6..c5d0ae2cf 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java @@ -1,24 +1,43 @@ package com.cf.imes.module.executor.service.order; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.FieldValue; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; + +import co.elastic.clients.elasticsearch._types.aggregations.CalendarInterval; +import co.elastic.clients.elasticsearch._types.aggregations.DateHistogramAggregation; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.util.NamedValue; import com.cf.imes.framework.common.enums.OrderStatusEnum; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderGoodsPlateRespVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsAreaRespVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsReqVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsStatusRespVO; import com.cf.imes.module.executor.controller.admin.plan.vo.OrderPlanStatisticsAreaRespVO; import com.cf.imes.module.executor.controller.admin.plan.vo.OrderPlanStatisticsCountRespVO; +import com.cf.imes.module.executor.dal.dataobject.plate.PlateGoodDO; import com.cf.imes.module.executor.dal.mysql.order.OrderStatisticsMapper; import com.cf.imes.module.executor.dal.mysql.plan.PlanMapper; import com.cf.imes.module.executor.dal.mysql.plate.OrderPlateStatisticsMapper; +import com.cf.imes.module.executor.dal.mysql.plate.PlateGoodMapper; import com.cf.imes.module.executor.enums.OrderStatisticsUnit; +import com.cf.imes.module.executor.service.optimizeplan.OptimizePlanService; import com.cf.imes.module.system.api.dict.DictDataApi; import com.cf.imes.module.system.api.dict.dto.DictDataRespDTO; import com.cf.imes.module.system.enums.DictTypeConstants; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.io.IOException; import java.math.BigDecimal; import java.time.LocalDate; import java.time.format.DateTimeFormatter; @@ -40,6 +59,7 @@ import java.util.stream.Collectors; */ @Service @Validated +@Slf4j public class OrderStatisticsServiceImpl implements OrderStatisticsService { @Resource private OrderStatisticsMapper orderStatisticsMapper; @@ -53,9 +73,21 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { @Resource private DictDataApi dictDataApi; + @Resource + private PlateGoodMapper plateGoodMapper; + + @Resource + private ElasticsearchClient client; + // 常用的字段key private static final String DATELIST_FIELD_NAME = "dateList"; private static final String SERIES_FIELD_NAME = "series"; + private static final String ORDER_REMAIN_PLATE_MODEL_CREATE_TIME_FIELDNAME = "createTime"; + private static final String ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME = "goods_group"; + private static final String ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME = "goods_count"; + private static final String DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH = "yyyy-M"; + private static final String DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH_DAY = "yyyy-M-d"; + private static final String ORDER_REMAIN_PLATE_MODEL_GOODS_ID_NAME = "goodsId"; @Override public Integer orderCount() { @@ -206,18 +238,19 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { // 所有的日期集合 List dateList = getDateList(reqVO); - // 查询时间段内数量最多的小板,排序列出数量前10的goods_id + // 查询时间段内数量最多的小板,列出数量前10的goods_id List topTenCountGoodsId = orderPlateStatisticsMapper.selectPlateCountList(reqVO).stream() - .sorted(Comparator.comparingLong(OrderGoodsPlateRespVO::getOrderCount).reversed()) .map(OrderGoodsPlateRespVO::getGoodsId) - .limit(10) - .collect(Collectors.toList()); - + .toList(); // 前十goods_id基于时间分组 - Map> orderGoodsPlateRespMap = orderPlateStatisticsMapper.selectTopTenPlateCountListGroupByOrderDate(topTenCountGoodsId, reqVO).stream() - .sorted(Comparator.naturalOrder()) - .collect(Collectors.groupingBy(OrderGoodsPlateRespVO::getOrderDate, LinkedHashMap::new, Collectors.toList())); + Map> orderGoodsPlateRespMap = new HashMap<>(); + if (CollUtil.isNotEmpty(topTenCountGoodsId)) { + orderGoodsPlateRespMap = orderPlateStatisticsMapper.selectTopTenPlateCountListGroupByOrderDate(topTenCountGoodsId, reqVO).stream() + .sorted(Comparator.naturalOrder()) + .collect(Collectors.groupingBy(OrderGoodsPlateRespVO::getOrderDate, LinkedHashMap::new, Collectors.toList())); + } + // 获取所有商品{goodsId:respvo},根据top10排序 Map goodsMap = new LinkedHashMap<>(); @@ -225,7 +258,7 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { List list = orderGoodsPlateRespMap.values().stream() .flatMap(List::stream) .filter(vo -> vo.getGoodsId().equals(id)) - .collect(Collectors.toList()); + .toList(); if (!list.isEmpty()) { // goodsId相同,其他属性任取 goodsMap.put(id, list.get(0)); @@ -277,18 +310,19 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { // 所有的日期集合 List dateList = getDateList(reqVO); - // 查询时间段内面积最多的小板,排序列出前10面积的goods_id + // 查询时间段内面积最多的小板,列出前10面积的goods_id List topTenCountGoodsId = orderPlateStatisticsMapper.selectPlateAreaList(reqVO).stream() - .sorted(Comparator.comparing(OrderGoodsPlateRespVO::getOrderArea).reversed()) .map(OrderGoodsPlateRespVO::getGoodsId) - .limit(10) - .collect(Collectors.toList()); + .toList(); + Map> orderGoodsPlateRespMap = new HashMap<>(); + if (CollUtil.isNotEmpty(topTenCountGoodsId)) { + // 前十goods_id基于时间分组 + orderGoodsPlateRespMap = orderPlateStatisticsMapper.selectTopTenPlateAreaListGroupByOrderDate(topTenCountGoodsId, reqVO).stream() + .sorted(Comparator.naturalOrder()) + .collect(Collectors.groupingBy(OrderGoodsPlateRespVO::getOrderDate, LinkedHashMap::new, Collectors.toList())); + } - // 前十goods_id基于时间分组 - Map> orderGoodsPlateRespMap = orderPlateStatisticsMapper.selectTopTenPlateAreaListGroupByOrderDate(topTenCountGoodsId, reqVO).stream() - .sorted(Comparator.naturalOrder()) - .collect(Collectors.groupingBy(OrderGoodsPlateRespVO::getOrderDate, LinkedHashMap::new, Collectors.toList())); // 获取所有商品{goodsId:respvo},根据top10排序 Map goodsMap = new LinkedHashMap<>(); @@ -296,7 +330,7 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { List list = orderGoodsPlateRespMap.values().stream() .flatMap(List::stream) .filter(vo -> vo.getGoodsId().equals(id)) - .collect(Collectors.toList()); + .toList(); if (!list.isEmpty()) { // goodsId相同,其他属性任取 goodsMap.put(id, list.get(0)); @@ -341,6 +375,184 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { return resultMap; } + @Override + public Map getBigPlateCountGroup(OrderStatisticsReqVO reqVO) { + Map resultMap = new LinkedHashMap<>(); + Integer unit = reqVO.getUnit(); + + // 所有的日期集合 + List dateList = getDateList(reqVO); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + SearchResponse response; + try { + // 查询创建时间段内,数量最多的goods_id前十 + SearchRequest searchRequest = new SearchRequest.Builder() + .size(0) + .index(OptimizePlanService.ORDER_REMAIN_PLATE_MODEL) + .query(q -> q.range(r -> r.field(ORDER_REMAIN_PLATE_MODEL_CREATE_TIME_FIELDNAME) + .gte(JsonData.of(reqVO.getCreateTime()[0].format(dateTimeFormatter))) + .lte(JsonData.of(reqVO.getCreateTime()[1].format(dateTimeFormatter)))) + ) + .aggregations(ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME, + agg -> agg.terms(terms -> terms.field(ORDER_REMAIN_PLATE_MODEL_GOODS_ID_NAME).size(10).order(new NamedValue<>(ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME, SortOrder.Desc))) + .aggregations(ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME, sumAgg -> sumAgg.sum(sum -> sum.field("boardCount"))) + ) + .build(); + + response = client.search(searchRequest, Map.class); + + Map goodsCountAggMap = response.aggregations(); + Aggregate goodsCountAgg = goodsCountAggMap.get(ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME); + + List goodsIds = new ArrayList<>(); + // 构建map:{日期:{goodsId、count}} + Map> goodsDateGroupMap = new HashMap<>(); + /** + * 获取数量最大前十的goodsId列表 + */ + goodsCountAgg.lterms().buckets().array().forEach(e -> goodsIds.add(e.key())); + + if (CollUtil.isNotEmpty(goodsIds)) { + List goodsIdFieldValueList = goodsIds.stream().map(FieldValue::of).toList(); + // 查询创建时间段内,数量最多的goods_id前十下的数据,按goods_id和日期分组 + SearchRequest dateGroupRequest = new SearchRequest.Builder() + .size(0) + .index(OptimizePlanService.ORDER_REMAIN_PLATE_MODEL) + .query(q -> q.range(r -> r.field(ORDER_REMAIN_PLATE_MODEL_CREATE_TIME_FIELDNAME) + .gte(JsonData.of(reqVO.getCreateTime()[0].format(dateTimeFormatter))) + .lte(JsonData.of(reqVO.getCreateTime()[1].format(dateTimeFormatter)))) + ) + .query(q -> q.bool(b -> b.must(m -> m.terms(t -> t.field(ORDER_REMAIN_PLATE_MODEL_GOODS_ID_NAME).terms(tv -> tv.value(goodsIdFieldValueList)))))) + .query(q -> q.match(m -> m.field("organId").query(SecurityFrameworkUtils.getUserOrganId()))) + .aggregations(ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME, + agg -> agg.terms(terms -> terms.field(ORDER_REMAIN_PLATE_MODEL_GOODS_ID_NAME).order(new NamedValue<>(ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME, SortOrder.Desc))) + .aggregations("date_group", dateAgg -> dateAgg.dateHistogram(date -> getDateHistogram(unit, date.field(ORDER_REMAIN_PLATE_MODEL_CREATE_TIME_FIELDNAME)))) + .aggregations(ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME, sumAgg -> sumAgg.sum(sum -> sum.field("boardCount"))) + ) + .build(); + response = client.search(dateGroupRequest, Map.class); + Map goodsDateCountAggMap = response.aggregations(); + Aggregate goodsDateAgg = goodsDateCountAggMap.get(ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME); + + + goodsDateAgg.lterms().buckets().array().forEach(goodsDateAggBucket -> { + Long goodsId = goodsDateAggBucket.key(); + // todo 目前没有发现好的es统计月周的方式,先把年月日查出来转周,后续优化 + String dateStr = dateToWeekMonth(goodsDateAggBucket.aggregations().get("date_group").dateHistogram().buckets().array().get(0).keyAsString(), unit); + double goodsCount = goodsDateAggBucket.aggregations().get(ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME).sum().value(); + OrderGoodsPlateRespVO vo = OrderGoodsPlateRespVO.builder().goodsId(goodsId).orderDate(dateStr).orderCount((int) goodsCount).build(); + List orderGoodsPlateRespVOS = goodsDateGroupMap.get(dateStr); + if (ObjectUtil.isNotNull(orderGoodsPlateRespVOS)) { + orderGoodsPlateRespVOS.add(vo); + } else { + ArrayList goodsPlateRespVOS = new ArrayList<>(); + goodsPlateRespVOS.add(vo); + goodsDateGroupMap.put(dateStr, goodsPlateRespVOS); + } + }); + } + + // 遍历所有goods_id + List> series = new ArrayList<>(); + for (Long goodsId : goodsIds) { + Map seriesItem = new HashMap<>(); + int[] countArr = new int[dateList.size()]; + + // 遍历完整的日期范围 + int index = 0; + for (String dateStr : dateList) { + // 查找匹配的goodsId + List orderGoodsPlateRespVOS = goodsDateGroupMap.get(dateStr); + int count = 0; + if (orderGoodsPlateRespVOS != null) { + count = orderGoodsPlateRespVOS.stream() + .filter(respVO -> Objects.equals(goodsId, respVO.getGoodsId())) + .map(OrderGoodsPlateRespVO::getOrderCount) + .findFirst().orElse(0); + } + countArr[index++] = count; + } + + seriesItem.put("data", countArr); + seriesItem.put("id", goodsId); + // 材质-商品名称-颜色-纹理-宽-高-厚-品牌 + List plateGoodDOList = plateGoodMapper.selectList(new LambdaQueryWrapperX().eq(PlateGoodDO::getGoodsId, goodsId)); + if (CollUtil.isEmpty(plateGoodDOList)) { + // 没有对应大板不展示 + log.error("[getBigPlateCountGroup][统计大板数量,查询大板{} 不存在]", goodsId); + continue; + } + // 任意取一个类型 + PlateGoodDO plateGoodDO = plateGoodDOList.get(0); + seriesItem.put("name", plateGoodDO.getMaterial() + "-" + plateGoodDO.getGoodsName() + + "-" + plateGoodDO.getColor() + "-" + getTextureFromDict(plateGoodDO) + "-" + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getWidth())) + + "×" + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getHeight())) + "×" + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getThickness())) + "-" + plateGoodDO.getBrand()); + series.add(seriesItem); + } + resultMap.put(DATELIST_FIELD_NAME, dateList.stream().map(date -> generateDateRangeAxis(date, unit)).toList()); + resultMap.put(SERIES_FIELD_NAME, series); + } catch (IOException e) { + log.error("[getBigPlateCountGroup][统计大板数量异常:{}]", e.getMessage(), e); + } + return resultMap; + } + + /** + * 根据纹路枚举获取字典中纹路描述 + * @param plateGoodDO + * @return + */ + private String getTextureFromDict(PlateGoodDO plateGoodDO) { + // 获取纹路描述 + DictDataRespDTO grainDTO = dictDataApi.getDictData(DictTypeConstants.GRAIN_TYPE, String.valueOf(plateGoodDO.getTexture())).getData(); + if (ObjectUtil.isNotNull(grainDTO)) { + return grainDTO.getLabel(); + } else { + return ""; + } + } + + + /** + * 根据统计维度获取es分组的dateHistogram + * + * @return + */ + private DateHistogramAggregation.Builder getDateHistogram(Integer unit, DateHistogramAggregation.Builder builder) { + switch (OrderStatisticsUnit.fromValue(unit)) { + case QUARTER: + return builder.calendarInterval(CalendarInterval.Quarter).format("yyyy-Q"); + case MONTH: + return builder.calendarInterval(CalendarInterval.Month).format(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH); + case DAY, WEEK: + default: + return builder.calendarInterval(CalendarInterval.Day).format(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH_DAY); + } + } + + + /** + * 年月日转年月周 + * + * @param dateStr + * @return + */ + private String dateToWeekMonth(String dateStr, Integer unit) { + if (OrderStatisticsUnit.WEEK.getValue().equals(unit)) { + LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH_DAY)); + // 年月 + String outDateStr = date.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH)); + // 计算从月份第一天到当前日期经过了多少周 + LocalDate monthStart = date.with(TemporalAdjusters.firstDayOfMonth()); + long weeksInMonth = ChronoUnit.WEEKS.between(monthStart, date) + 1; + return outDateStr + "-" + weeksInMonth; + } + return dateStr; + } + + + /** * 获取日期区间格式下的所有日期字符串 * 1、reqVO设置机构id @@ -372,8 +584,8 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { endTime = now; switch (OrderStatisticsUnit.fromValue(reqVO.getUnit())) { case QUARTER: - // 从now往前的2年 - startTime = now.minusYears(2); + // 从now往前的1年 + startTime = now.minusYears(1); break; case MONTH: // 包含now往前的12个月 @@ -419,22 +631,17 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { startDate = startDate.plusMonths(3); break; case MONTH: - dateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-M")); + dateStr = startDate.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH)); // 加一月 startDate = startDate.plusMonths(1); break; case WEEK: - // 使用自定义格式表示月份 - dateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-M")); - // 计算从月份第一天到当前日期经过了多少周 - LocalDate monthStart = startDate.with(TemporalAdjusters.firstDayOfMonth()); - long weeksInMonth = ChronoUnit.WEEKS.between(monthStart, startDate) + 1; - dateStr = dateStr + "-" + weeksInMonth; + dateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-M-W")); // 加一周 startDate = startDate.plusWeeks(1); break; case DAY: - dateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-M-d")); + dateStr = startDate.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH_DAY)); // 加一天 startDate = startDate.plusDays(1); break; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java index 066549d73..4f13cf6c7 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java @@ -1,12 +1,15 @@ package com.cf.imes.module.executor.service.plan; -import java.util.*; -import javax.validation.*; - -import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderRespVO; -import com.cf.imes.module.executor.controller.admin.plan.vo.*; import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; +import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderRespVO; +import com.cf.imes.module.executor.controller.admin.plan.bo.OrderRoomBodyList; +import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.NotPlanGoodsReqVO; +import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.NotPlanGoodsRespVO; +import com.cf.imes.module.executor.controller.admin.plan.vo.*; + +import javax.validation.Valid; +import java.util.List; +import java.util.Map; /** * 生产单开料排单 Service 接口 @@ -21,7 +24,7 @@ public interface PlanService { * @param createReqVO 创建信息 * @return 编号 */ - Long createPlan(@Valid PlanSaveReqVO createReqVO); + Map createPlan(@Valid PlanSaveReqVO createReqVO); /** * 更新生产单开料排单 @@ -33,9 +36,9 @@ public interface PlanService { /** * 删除生产单开料排单 * - * @param id 编号 + * @param ids 编号 */ - Boolean deletePlan(Long id); + Boolean deletePlan(List ids); /** * 获得生产单开料排单 @@ -75,5 +78,9 @@ public interface PlanService { List getPlateList(List planIds); + List getOrderRoomBody(List orderIds); + List getOrderPlateList(OrderPageReqVOCopy pageReqVO); + + List getNotOptimizeGoodsList(NotPlanGoodsReqVO reqVO); } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java index d3eb44714..09570ec19 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java @@ -1,27 +1,39 @@ package com.cf.imes.module.executor.service.plan; import cn.hutool.core.collection.CollectionUtil; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.FieldValue; +import co.elastic.clients.elasticsearch.core.DeleteByQueryRequest; +import co.elastic.clients.elasticsearch.core.DeleteByQueryResponse; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.Hit; import com.alibaba.fastjson.JSON; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; import com.cf.imes.framework.common.enums.PlanFilterTypeEnum; import com.cf.imes.framework.common.enums.PlanStatusEnum; -import com.cf.imes.framework.common.util.json.JsonUtils; +import com.cf.imes.framework.common.exception.ServiceException; +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.mybatis.core.query.MPJLambdaWrapperX; import com.cf.imes.framework.mybatis.core.query.QueryWrapperX; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderRespVO; -import com.cf.imes.module.executor.controller.admin.plan.bo.GoodsNum; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderIds; -import com.cf.imes.module.executor.controller.admin.plate.vo.PlateRespVO; +import com.cf.imes.module.executor.controller.admin.plan.bo.OrderRoomBodyList; +import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.BlockPlaceInfo; +import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.NotPlanGoodsReqVO; +import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.NotPlanGoodsRespVO; +import com.cf.imes.module.executor.controller.admin.plan.vo.*; import com.cf.imes.module.executor.dal.dataobject.goods.GoodsDO; +import com.cf.imes.module.executor.dal.dataobject.goods.OptimizeBoardModelDO; import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; import com.cf.imes.module.executor.dal.dataobject.orderBody.OrderBodyDO; import com.cf.imes.module.executor.dal.dataobject.orderItem.OrderItemDO; +import com.cf.imes.module.executor.dal.dataobject.plan.PlanDO; import com.cf.imes.module.executor.dal.dataobject.planitem.PlanItemDO; import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO; import com.cf.imes.module.executor.dal.mysql.goods.GoodsMapper; @@ -29,36 +41,37 @@ import com.cf.imes.module.executor.dal.mysql.module.ModuleMapper; import com.cf.imes.module.executor.dal.mysql.order.OrderMapper; import com.cf.imes.module.executor.dal.mysql.orderBody.OrderBodyMapper; import com.cf.imes.module.executor.dal.mysql.orderItem.OrderItemMapper; +import com.cf.imes.module.executor.dal.mysql.plan.PlanMapper; import com.cf.imes.module.executor.dal.mysql.planitem.PlanItemMapper; import com.cf.imes.module.executor.dal.mysql.plate.PlateMapper; import com.cf.imes.module.executor.enums.OrderStatusEnum; +import com.cf.imes.module.executor.service.optimizeplan.OptimizePlanService; import com.cf.imes.module.system.api.machine.MachineApi; import com.cf.imes.module.system.api.machine.dto.CuttingRespDTO; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.github.yulichang.wrapper.MPJLambdaWrapper; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; - -import org.springframework.validation.annotation.Validated; -import org.springframework.transaction.annotation.Transactional; - +import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; -import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; -import com.cf.imes.module.executor.controller.admin.plan.vo.*; -import com.cf.imes.module.executor.dal.dataobject.plan.PlanDO; -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.common.util.object.BeanUtils; - -import com.cf.imes.module.executor.dal.mysql.plan.PlanMapper; - +import static com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants.ES_ERROR_DELETE; +import static com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.cf.imes.framework.common.util.string.SearchUtil.insertSeparator; import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.*; -import static com.cf.imes.framework.common.util.string.SearchUtil.insertSeparator; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.NO_PRODUCTION_ORDER_INFORMATION_AVAILABLE; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.THE_BOARD_HAS_BEEN_CUT_INTO_PIECES; /** * 生产单开料排单 Service 实现类 @@ -67,6 +80,7 @@ import static com.cf.imes.framework.common.util.string.SearchUtil.insertSeparato */ @Service @Validated +@Slf4j public class PlanServiceImpl implements PlanService { @Resource @@ -99,104 +113,276 @@ public class PlanServiceImpl implements PlanService { @Resource private IdentifierGenerator identifierGenerator; + String ORDER_REMAIN_PLATE_MODEL = "imes_order_remain_plate_model"; + + @Resource + private ElasticsearchClient elasticsearchClient; + + @Resource + private OptimizePlanService optimizePlanService; + @Override @Transactional(rollbackFor = Exception.class) - public Long createPlan(PlanSaveReqVO createReqVO) { + public Map createPlan(PlanSaveReqVO createReqVO) { + + // todo 目前只考虑了非混单的情况,混单的情况待考虑 List itemList = createReqVO.getItemList(); - // 插入 - long sort = System.currentTimeMillis(); - PlanDO plan = BeanUtils.toBean(createReqVO, PlanDO.class); -// plan.setIsPay(Boolean.FALSE); - plan.setSort(0L); -// plan.setPlanNo(identifierGenerator.nextId(null).toString()); - String orderNos = itemList.stream().map(PlanSaveReqVO.Item::getOrderId).distinct().toList().toString(); - plan.setOrderNos(orderNos); - plan.setProduceTime(null); - planMapper.insert(plan); - // 修改对应的生产单的状态为 生产中 - List orderIds = JSON.parseArray(orderNos).toJavaList(Long.class); + ArrayList planDOS = new ArrayList<>(); - List goodsNums = plateMapper.selectGoodsNum(orderIds, getUserOrganId()); + ArrayList planItemDOS = new ArrayList<>(); - for (Long orderId : orderIds) { + Map goodsPlanId = new HashMap<>(); - // 传入的生产单的大板数量 - int size1 = itemList.stream().filter(f -> Objects.equals(f.getOrderId(), orderId)).map(PlanSaveReqVO.Item::getId).distinct().toList().size(); - // 当前生产单对应的大板数量 - List list = goodsNums.stream().filter(f -> Objects.equals(f.getOrderId(), orderId)).map(GoodsNum::getGoodsNum).toList(); + Map> groupedItems = itemList.stream() + .collect(Collectors.groupingBy(PlanSaveReqVO.Item::getGoodsId)); + + + for (Map.Entry> entry : groupedItems.entrySet()) { + + List items = entry.getValue(); + + // 创建计划 + PlanDO plan = BeanUtils.toBean(createReqVO, PlanDO.class); + plan.setId(identifierGenerator.nextId(plan).longValue()); + plan.setSort(0L); + String orderNos = items.stream().map(PlanSaveReqVO.Item::getOrderId).distinct().toList().toString(); + plan.setOrderNos(orderNos); + plan.setProduceTime(null); + + planDOS.add(plan); + + goodsPlanId.put(entry.getKey(), plan.getId()); + + Set itemIds = plateMapper.selectBatchOrderIdsAndGoodsIds(items,getUserOrganId()); + + if (CollectionUtil.isNotEmpty(itemIds)) { + + for (Long itemId : itemIds) { + planItemDOS.add(PlanItemDO.builder() + .planId(plan.getId()) + .itemId(itemId) + .build()); + } - if(size1 == list.get(0)){ - OrderDO orderDO = orderMapper.selectById(orderId).setStatus(OrderStatusEnum.IN_PRODUCTION.getStatus()); - orderMapper.updateById(orderDO); } + } - Long planId = plan.getId(); + planMapper.insertBatch(planDOS); - Set itemIds = plateMapper.selectBatchOrderIdsAndGoodsIds(itemList,getUserOrganId()); + planItemMapper.insertBatch(planItemDOS); - if (CollectionUtil.isNotEmpty(itemIds)) { - ArrayList planItemDOS = new ArrayList<>(); - for (Long itemId : itemIds) { - planItemDOS.add(PlanItemDO.builder() - .planId(planId) - .itemId(itemId) - .build()); - } - planItemMapper.insertBatch(planItemDOS); - } - // 返回 - return plan.getId(); + + return goodsPlanId; + +// +// // 插入 +// PlanDO plan = BeanUtils.toBean(createReqVO, PlanDO.class); +// plan.setSort(0L); +// String orderNos = itemList.stream().map(PlanSaveReqVO.Item::getOrderId).distinct().toList().toString(); +// plan.setOrderNos(orderNos); +// plan.setProduceTime(null); +// planMapper.insert(plan); +// +// // 修改对应的生产单的状态为 已排单 +// List orderIds = itemList.stream().map(PlanSaveReqVO.Item::getOrderId).toList(); +// +// List orderDOS = orderMapper.selectBatchIds(orderIds); +// +// List orderDOList = orderDOS.stream().map(o -> o.setStatus(OrderStatusEnum.SORTED.getStatus())).toList(); +// +// orderMapper.updateBatch(orderDOList); +// +// Long planId = plan.getId(); +// +// +// // 返回 +// return plan.getId(); } @Override @Transactional(rollbackFor = Exception.class) public void updatePlan(PlanSaveReqVO updateReqVO) { + // 校验存在 - validatePlanExists(updateReqVO.getId()); + validatePlanExists(updateReqVO.getId(),updateReqVO.getMachineId()); // 更新 PlanDO plan = BeanUtils.toBean(updateReqVO, PlanDO.class); + // 目前只解决非混单的情况 + if(!updateReqVO.getItemList().isEmpty()){ + + List optimizeBoardModelDOS = buildBoardByPlanId(plan.getId(), ORDER_REMAIN_PLATE_MODEL, 99); + + OptimizeBoardModelDO optimizeBoardModelDO = optimizeBoardModelDOS.get(0); + + List goodsNo = optimizeBoardModelDO.getCutedBoardInfo().getCutedBoardList(); + + List plateNo = new ArrayList<>(); + + // 创建一个列表存储 BlockPlaceInfo 对象,将优化的小板信息拿出,获取到小板编号,查询生产单,修改生产单的状态 + List outputList = new ArrayList<>(); + + ObjectMapper mapper = new ObjectMapper(); + + try { + // 解析 JSON 字符串 + JsonNode jsonArray = mapper.readTree(optimizeBoardModelDO.getBlockPlaceInfo()); + + // 遍历 JSON 数组并提取所需字段 + if (jsonArray.isArray()) { + for (JsonNode jsonNode : jsonArray) { + Long bi = jsonNode.get("bi").asLong(); + Long bo = jsonNode.get("bo").asLong(); + outputList.add(new BlockPlaceInfo(bi,bo)); + } + } + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + + for (Long goods : goodsNo) { + plateNo.addAll(outputList.stream().filter(f -> f.getBi().equals(goods)).map(BlockPlaceInfo::getBo).distinct().toList()); + } + + if(updateReqVO.getDeleteIds() != null) { + + List plateDOS = plateMapper.selectPlateListByGoodsIds(updateReqVO.getDeleteIds(), getUserOrganId()); + + List deletePlateNos = plateDOS.stream().map(PlateDO::getPlateNo).map(Long::valueOf).toList(); + + List plateNoCopyList = new ArrayList<>(plateNo); + + // 使用retainAll方法保留 plateNo 中与 deletePlateNos 相同的元素 + plateNoCopyList.retainAll(deletePlateNos); + + // 如果 plateNoCopyList 不为空,说明两个List有共同的元素 + boolean b = !plateNoCopyList.isEmpty(); + + if (b) { + + throw exception(THE_BOARD_HAS_BEEN_CUT_INTO_PIECES); + + } + + } + } + + planMapper.updateById(plan); + } @Override @Transactional(rollbackFor = Exception.class) - public Boolean deletePlan(Long id) { + public Boolean deletePlan(List ids) { // 校验存在 - PlanDO planDO = planMapper.selectById(id); - if (planDO == null) { - throw exception(PLAN_NOT_EXISTS); - } - if (planDO.getStatus().equals(PlanStatusEnum.DURINGCUTTING.getStatus()) || planDO.getStatus().equals(PlanStatusEnum.OPENEDMATERIAL.getStatus())) { - throw exception(PLAN_NOT_ALLOW_DELETE); - } - // 删除 - planMapper.deleteById(id); - /*planOrderMapper.delete(new LambdaQueryWrapperX().eq(PlanOrderDO::getPlanId, id));*/ - planItemMapper.delete(new LambdaQueryWrapperX().eq(PlanItemDO::getPlanId, id)); + validatePlan(ids); - // 修改生产单的状态为待排单 - List orderIds = JSON.parseArray(planDO.getOrderNos()).toJavaList(Long.class); - List orderDOS = orderMapper.selectBatchIds(orderIds).stream().map(m -> m.setStatus(OrderStatusEnum.SORTED.getStatus())).collect(Collectors.toList()); - orderMapper.updateBatch(orderDOS); + List planDOS = planMapper.selectBatchIds(ids); + + List orderIds = new ArrayList<>(); + for (PlanDO planDO : planDOS) { + + orderIds.addAll(JSON.parseArray(planDO.getOrderNos()).toJavaList(Long.class)); + + } + + // 删除排单信息,排单明细表信息,ES优化数据 + planMapper.deleteBatchIds(ids); + planItemMapper.delete(new LambdaQueryWrapperX().in(PlanItemDO::getPlanId, ids)); + + + // 排单对应的自增板的删除 todo 目前值解决了非混单的情况 + List boardModelDOS = buildBoardByPlanIds(ids, ORDER_REMAIN_PLATE_MODEL, ids.size()); + if(!boardModelDOS.isEmpty()) { + + List goodsIds = boardModelDOS.stream().map(OptimizeBoardModelDO::getGoodsId).toList(); + + List goodsIdList = goodsMapper.selectListByGoodsIdList(goodsIds, orderIds, getUserOrganId()).stream().map(GoodsDO::getId).toList(); + + List plateDOS = plateMapper.selectPlateIdList(goodsIdList, getUserOrganId()); + if(!plateDOS.isEmpty()) { + List plateIds = plateDOS.stream().map(PlateDO::getId).toList(); + + plateMapper.deleteBatchIds(plateIds); + + orderItemMapper.delete(new LambdaQueryWrapperX().in(OrderItemDO::getPlateId, plateIds)); + + } + + + // 目前生产单的状态已经去除待排单,所以无需修改生产单的状态 +// List orderDOS = orderMapper.selectBatchIds(orderIds).stream().map(m -> m.setStatus(OrderStatusEnum.SORTED.getStatus())).collect(Collectors.toList()); +// orderMapper.updateBatch(orderDOS); + + + // 删除排单对应的优化生产数据 + deleteByPlanId(ids, ORDER_REMAIN_PLATE_MODEL); + + } + + List orderIdList = new ArrayList<>(); + + List diff; + + // 根据生产单ID查询ES的优化数据 + List optimizeBoardModelDOS = optimizePlanService.buildBoardByOrderIds(orderIds, ORDER_REMAIN_PLATE_MODEL, 999); + + if(optimizeBoardModelDOS.isEmpty()){ + + diff = new ArrayList<>(orderIds); + + }else { + optimizeBoardModelDOS.forEach(f -> orderIdList.addAll(f.getOrderId())); + + // 已经删除的排单的生产单号和新查找的生生产单号对比,找出不同的部分 + diff = orderIds.stream().filter(f -> !orderIdList.contains(f)).toList(); + } + + if(!diff.isEmpty()){ + + List orderList = orderMapper.selectBatchIds(diff); + + List orderDOList = orderList.stream().map(m -> m.setStatus(OrderStatusEnum.NEW_ORDER.getStatus())).toList(); + + orderMapper.updateBatch(orderDOList); + } return Boolean.TRUE; } - private void validatePlanExists(Long id) { - if (planMapper.selectById(id) == null) { + + + private void validatePlanExists(Long id,Long machineId) { + PlanDO planDO = planMapper.selectById(id); + if ( planDO== null) { throw exception(PLAN_NOT_EXISTS); } + + if(planDO.getStatus().equals(PlanStatusEnum.OPENING.getStatus()) && planDO.getMachineId().equals(machineId)){ + throw exception(LIST_CHANGES_ARE_PROHIBITED); + } } private void validatePlan(List ids) { - planMapper.selectPlanByOrderIds(ids); + List planDOS = planMapper.selectBatchIds(ids); + + for (PlanDO planDO : planDOS) { + if ( planDO== null) { + throw exception(PLAN_NOT_EXISTS); + } + + if ( planDO.getStatus().equals(PlanStatusEnum.OPENING.getStatus()) || planDO.getStatus().equals(PlanStatusEnum.OPENED.getStatus()) ) { + throw exception(PLAN_NOT_ALLOW_DELETE,planDO.getId()); + } + + } } @@ -232,21 +418,76 @@ public class PlanServiceImpl implements PlanService { return respVO; } + + @Override public PageResult getPlanPage(PlanPageReqVO pageReqVO) { - PageResult planDOPageResult = planMapper.selectPage(pageReqVO); - if (CollectionUtil.isEmpty(planDOPageResult.getList())) { - return new PageResult<>(); - } - Set macheineIds = planDOPageResult.getList().stream().map(PlanDO::getMachineId).collect(Collectors.toSet()); - List machines = machineApi.list(macheineIds).getCheckedData(); + PageResult planDOPageResult = new PageResult<>(); + + + if(pageReqVO.getIsUp() != null) { + + PlanDO planDO = planMapper.selectById(pageReqVO.getId()); + + + List plan = pageReqVO.getIsUp() ? + planMapper.selectPlanIds(planDO.getUpdateTime().toString(),planDO.getSort(), getUserOrganId(), planDO.getId()) : + + planMapper.selectPlanIdsFalse(planDO.getUpdateTime().toString(),planDO.getSort(), getUserOrganId(), planDO.getId()); + + if (plan.isEmpty()) { + + throw exception(NO_PRODUCTION_ORDER_INFORMATION_AVAILABLE, pageReqVO.getIsUp() ? "第" : "最后"); + } + + planDOPageResult.setList(plan); + + + }else { + + planDOPageResult = planMapper.selectPage(pageReqVO); + if (CollectionUtil.isEmpty(planDOPageResult.getList())) { + return new PageResult<>(); + } + + } + + + Set machineIds = planDOPageResult.getList().stream().map(PlanDO::getMachineId).collect(Collectors.toSet()); List planIds = planDOPageResult.getList().stream().map(PlanDO::getId).collect(Collectors.toList()); + List machines = machineApi.list(machineIds).getCheckedData(); + + + List plateInfoVOS = planItemMapper.selectGoodsList(planIds,getUserOrganId()); + List orderIdsList = new ArrayList<>(); + + plateInfoVOS.forEach(f-> + orderIdsList.addAll(f.getOrderIdList())); + + + List plateInfoVOList = plateMapper.selectPlateArea(orderIdsList, getUserOrganId()); + + + // todo 目前这种情况只解决没有混单的情况,混单情况待解决 (目前解决,数据正确性待测试) + for (PlateInfoVO plateInfoVO : plateInfoVOS) { + plateInfoVO.setArea(plateInfoVOList.stream() + .filter(s->s.getGoodsId().equals(plateInfoVO.getGoodsId())) + .map(PlateInfoVO::getArea) + .reduce(BigDecimal.ZERO,BigDecimal::add)); + +// plateInfoVO.setOptimizeGoodsCount(plateInfoVOList.stream().filter(s->s.getGoodsId().equals(plateInfoVO.getGoodsId())).mapToLong(PlateInfoVO::getOptimizeGoodsCount).sum()); + } + + + // 根据排单ID查询ES中的优化数据 todo 目前只解决无混单的情况,混单情况待解决 + List optimizeBoardModelDOS = buildBoardByPlanIds(planIds, ORDER_REMAIN_PLATE_MODEL, plateInfoVOS.size()); + // 获取排单对应的生产单的信息 List planOrderRespVOS = planItemMapper.selectOrderList(planIds, getUserOrganId()); @@ -256,14 +497,40 @@ public class PlanServiceImpl implements PlanService { planRespVOPageResult.getList().forEach(e -> { + // 机台信息 e.setMachineName(machines.stream() .filter(f -> Objects.equals(f.getId(), e.getMachineId())) .map(CuttingRespDTO::getName) .findAny() .orElse(null)); + // 板材信息列表 e.setPlateInfoList(plateInfoVOS.stream() .filter(f -> Objects.equals(f.getPlanId(), e.getId())) .collect(Collectors.toList())); + // todo 小板总数量目前只解决没有混单的情况时的小板数量,后续待加入混单情况 (目前解决,数据正确性待测试) + e.setPlateNum(plateInfoVOS.stream() + .filter(f -> Objects.equals(f.getPlanId(), e.getId())) + .mapToLong(PlateInfoVO::getCount) + .sum()); + // todo 大板优化数量目前只解决没有混单的情况时的小板数量,后续待加入混单情况 (目前解决,数据正确性待测试) + e.setOptimizeGoodsCount(optimizeBoardModelDOS.stream() + .filter(f -> Objects.equals(f.getPlanId(), e.getId())) + // todo 目前兼容修改,新的需求不需要这个校验 + .mapToLong(m -> m.getBoardCount() == null ?0 : m.getBoardCount()) + .sum()); + // 大板开料数 + e.setCutGoodsCount(optimizeBoardModelDOS.stream() + .filter(f->Objects.equals(f.getPlanId(), e.getId())) + .mapToLong(m-> m.getCutedBoardInfo() == null ? 0 : m.getCutedBoardInfo().getCutedBoardNumber()) + .sum()); + // 小板优化数量 + e.setOptimizePlateCount(optimizeBoardModelDOS.stream() + .filter(f->Objects.equals(f.getPlanId(), e.getId())) + .mapToLong(m-> m.getPlaceBlockNumber() == null ? 0 : m.getPlaceBlockNumber()) + .sum()); + // 未优化小板数量 + e.setUnOptimizePlateCount(e.getPlateNum() - e.getOptimizePlateCount()); + // 生产单信息 e.setOrderList(planOrderRespVOS.stream() .filter( f-> Objects.equals(f.getPlanId(), e.getId())) .collect(Collectors.toList())); @@ -276,25 +543,72 @@ public class PlanServiceImpl implements PlanService { public PageResult getOrderPage(OrderPageReqVOCopy pageReqVO) { PageDTO page = new PageDTO<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()); + List statusList = new ArrayList<>(); + statusList.add(OrderStatusEnum.NEW_ORDER.getStatus()); + statusList.add(OrderStatusEnum.IN_PRODUCTION.getStatus()); + statusList.add(OrderStatusEnum.SORTED.getStatus()); + + // todo 修改排单数据筛选,目前只解决了非混单的情况,混单情况待解决 + List goodsDOS = goodsMapper.selectListByGoodsId(pageReqVO.getGoodsId(), getUserOrganId()); + +// List orderIds = new ArrayList<>(); +// if(pageReqVO.getGoodsId() != null) { +// List goodsDOS = goodsMapper.selectListByGoodsId(pageReqVO.getGoodsId(), getUserOrganId()); +// orderIds = goodsDOS.stream().map(GoodsDO::getOrderId).toList(); +// } + QueryWrapperX queryWrapperX = new QueryWrapperX<>(); queryWrapperX .eq("a.organ_id",getUserOrganId()) - .eq("a.status",OrderStatusEnum.SORTED.getStatus()) +// .eq("a.status",OrderStatusEnum.SORTED.getStatus()) .eq("a.deleted",false) + .in("a.status",statusList) + .isNull("opi.item_id") + // todo 修改排单数据筛选,目前只解决了非混单的情况,混单情况待解决 + .inIfPresent("op.goods_id",goodsDOS.isEmpty() ? null :goodsDOS.stream().map(GoodsDO::getId).toList()) + + .inIfPresent("a.id",pageReqVO.getOrderIds()) .likeIfPresent("a.id", pageReqVO.getOrderId() != null ? pageReqVO.getOrderId().toString() : null) -// .isNull("opi.item_id") + .inIfPresent("op.goods_id",pageReqVO.getIds()) .eqIfPresent("a.customer", pageReqVO.getConsignee()) .eqIfPresent("a.custom_order_no", pageReqVO.getDefaultId()) .eqIfPresent("a.address", pageReqVO.getConsigneeAddress()) .betweenIfPresent("a.create_time", pageReqVO.getCreateTime()) - .eqIfPresent("op.is_special_shaped", pageReqVO.getRectangle() != null ? false: null) - .eqIfPresent("op.is_special_shaped", pageReqVO.getSpecialShaped()) - .eqIfPresent("op.is_sculpt", pageReqVO.getSculpt()) - .eqIfPresent("op.is_door", pageReqVO.getIsDoor()) - .betweenIfPresent("op.height", new BigDecimal[]{pageReqVO.getLongMinRang(), pageReqVO.getLongMaxRang()}) - .betweenIfPresent("op.width", new BigDecimal[]{pageReqVO.getWidthMinRang(), pageReqVO.getWidthMaxRang()}) - .groupBy("a.id", " a.order_date", "a.delivery_date", "a.customer", "a.address", "a.custom_order_no","a.create_time","a.update_time") - .orderByDesc("a.update_time"); + .groupBy("a.id", " a.order_date", "a.delivery_date", "a.customer", "a.address", "a.custom_order_no","a.create_time","a.update_time","a.status") + .having("count(op.id) != 0") + .orderByDesc("a.create_time"); + + + IPage orderRespVOCopies = orderMapper.selectOrderPage(page, queryWrapperX); + + if (CollectionUtil.isEmpty(orderRespVOCopies.getRecords())) { + return new PageResult<>(); + } + + + return new PageResult<>(orderRespVOCopies.getRecords(), orderRespVOCopies.getTotal()); + + } + + + @Override + public List getOrderPlateList(OrderPageReqVOCopy pageReqVO) { + + QueryWrapperX queryWrapperX = new QueryWrapperX<>(); + queryWrapperX + .eq("c.organ_id",getUserOrganId()) + .inIfPresent("c.order_id", pageReqVO.getOrderIds()) + .isNull("opi.item_id") + .inIfPresent("oi.room_id",pageReqVO.getRoomId()) + .inIfPresent("oi.body_id",pageReqVO.getBodyId()) + .eqIfPresent("a.is_special_shaped", pageReqVO.getRectangle() != null ? false: null) + .eqIfPresent("a.is_special_shaped", pageReqVO.getSpecialShaped()) + .eqIfPresent("a.is_sculpt", pageReqVO.getSculpt()) + .eqIfPresent("a.is_door", pageReqVO.getIsDoor()) + .betweenIfPresent("a.height", new BigDecimal[]{pageReqVO.getLongMinRang(), pageReqVO.getLongMaxRang()}) + .betweenIfPresent("a.width", new BigDecimal[]{pageReqVO.getWidthMinRang(), pageReqVO.getWidthMaxRang()}) + .groupBy("c.id", " c.order_id", "c.goods_name", "c.width", "c.height", "c.thickness","c.material","c.color","c.texture","c.goods_id"); + String filterTypes = ""; if (Objects.nonNull(pageReqVO.getHoleThrough()) && pageReqVO.getHoleThrough()) { filterTypes += PlanFilterTypeEnum.DIGGINGTHROUGHTHESHAPE.getType().toString(); @@ -306,46 +620,89 @@ public class PlanServiceImpl implements PlanService { filterTypes += PlanFilterTypeEnum.TWODIMENSIONALCUTTINGPATH.getType().toString(); } - queryWrapperX.likeIfPresent("op.filter_type", insertSeparator(filterTypes)); + queryWrapperX.likeIfPresent("a.filter_type", insertSeparator(filterTypes)); - IPage orderRespVOCopies = orderMapper.selectOrderPage(page, queryWrapperX); +// List platePages = plateMapper.selectGoodsPage(pageReqVO.getOrderIds(),getUserOrganId()/*, orderRespVOCopy.getGoodsId()*/); - if (CollectionUtil.isEmpty(orderRespVOCopies.getRecords())) { - return new PageResult<>(); + List notPlanOrderPlateRespVOS = plateMapper.selectGoodsPage(queryWrapperX); + + // todo 目前数据筛选只考虑了非混单的情况,混单情况待解决 + if(pageReqVO.getGoodsId() != null) { + return notPlanOrderPlateRespVOS.stream().filter(f -> f.getGoodsId().equals(pageReqVO.getGoodsId())).toList(); } - List records = orderRespVOCopies.getRecords(); - List orderIds = records.stream().map(m -> m.getOrderId()).collect(Collectors.toList()); - - - List platePages = plateMapper.selectGoodsPage(orderIds,getUserOrganId()/*, orderRespVOCopy.getGoodsId()*/); + return notPlanOrderPlateRespVOS; - List filteredRecords = records.stream() - .filter(record -> { - List filteredPages = platePages.stream() - .filter(f -> Objects.equals(f.getOrderId(), record.getOrderId())) - .collect(Collectors.toList()); - if (filteredPages.isEmpty()) { - return false; // 移除该记录 - } else { - record.setPlatePages(filteredPages); - return true; // 保留该记录 - } - }) - .collect(Collectors.toList()); - - // 处理后的 filteredRecords 将不包含过滤后的数据为空的 record - orderRespVOCopies.setRecords(filteredRecords); - -// orderRespVOCopies.setTotal(orderRespVOCopies.getRecords().size()); +// List filteredRecords = records.stream() +// .filter(record -> { +// List filteredPages = platePages.stream() +// .filter(f -> Objects.equals(f.getOrderId(), record.getOrderId())) +// .collect(Collectors.toList()); +// if (filteredPages.isEmpty()) { +// return false; // 移除该记录 +// } else { +// record.setPlatePages(filteredPages); +// return true; // 保留该记录 +// } +// }) +// .collect(Collectors.toList()); +// +// // 处理后的 filteredRecords 将不包含过滤后的数据为空的 record +// orderRespVOCopies.setRecords(filteredRecords); +// +//// orderRespVOCopies.setTotal(orderRespVOCopies.getRecords().size()); +// +// +// return new PageResult<>(orderRespVOCopies.getRecords(), orderRespVOCopies.getTotal()); - return new PageResult<>(orderRespVOCopies.getRecords(), orderRespVOCopies.getTotal()); } + @Override + public List getNotOptimizeGoodsList(NotPlanGoodsReqVO reqVO) { + + // 板材库对应的大板ID + List plateGoodIds = reqVO.getOrderIdList().stream().map(OrderIds::getId).toList(); + + + List notPlanGoodsRespVOS = goodsMapper.selectJoinList(NotPlanGoodsRespVO.class, new MPJLambdaWrapperX() + + .leftJoin(PlateDO.class, PlateDO::getGoodsId, GoodsDO::getId) + .selectCount(PlateDO::getId,"plateNum") + .select(GoodsDO::getGoodsId, GoodsDO::getHeight, GoodsDO::getWidth, GoodsDO::getColor, GoodsDO::getGoodsName, GoodsDO::getThickness,GoodsDO::getSpec,GoodsDO::getMaterial,GoodsDO::getTexture) + .isNotNull(PlanItemDO::getId) + .eq(GoodsDO::getOrganId, getUserOrganId()) + .in(GoodsDO::getId, plateGoodIds) + .groupBy(GoodsDO::getGoodsId, GoodsDO::getHeight, GoodsDO::getWidth, GoodsDO::getColor, GoodsDO::getGoodsName, GoodsDO::getThickness,GoodsDO::getSpec,GoodsDO::getMaterial,GoodsDO::getTexture)); + + + +// // 生产单对应的大板ID +// List goodIds = reqVO.getOrderIdList().stream().map(OrderIds::getId).toList(); +// +// // 查询板材库的大板信息 +// List notPlanGoodsRespVOS = goodsMapper.selectGoodsPlateList(plateGoodIds, getUserOrganId()); + + // 查询小板数量 +// List plateDOS = plateMapper.selectGoodsPlateNum(goodIds, getUserOrganId()); + + +// List notPlanGoodsRespVOS = BeanUtils.toBean(goodsDOS, NotPlanGoodsRespVO.class); + + for (NotPlanGoodsRespVO notPlanGoodsRespVO : notPlanGoodsRespVOS) { + notPlanGoodsRespVO.setOrderIdList(reqVO.getOrderIdList() + .stream() + .filter(orderIds -> orderIds.getGoodsId().equals(notPlanGoodsRespVO.getGoodsId())).toList()); + + notPlanGoodsRespVO.setGoodsNum(notPlanGoodsRespVO.getOrderIdList().stream().map(OrderIds::getId).toList().size()); + + } + + return notPlanGoodsRespVOS; + } @@ -356,17 +713,24 @@ public class PlanServiceImpl implements PlanService { PageDTO page = new PageDTO<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()); + List statusList = new ArrayList<>(); + statusList.add(OrderStatusEnum.NEW_ORDER.getStatus()); + statusList.add(OrderStatusEnum.IN_PRODUCTION.getStatus()); + statusList.add(OrderStatusEnum.SORTED.getStatus()); + + List orderIds = orderMapper.selectOrderIdsList(pageReqVO, statusList, getUserOrganId()) + .stream().map(OrderDO::getId).toList(); + QueryWrapperX queryWrapperX = new QueryWrapperX<>(); queryWrapperX - .eq("a.organ_id",getUserOrganId()) - .eq("a.status",OrderStatusEnum.SORTED.getStatus()) - .eq("a.deleted",false) - .likeIfPresent("a.id", pageReqVO.getOrderId() != null ? pageReqVO.getOrderId().toString() : null) -// .isNull("opi.item_id") - .eqIfPresent("a.customer", pageReqVO.getConsignee()) - .eqIfPresent("a.custom_order_no", pageReqVO.getDefaultId()) - .eqIfPresent("a.address", pageReqVO.getConsigneeAddress()) - .betweenIfPresent("a.create_time", pageReqVO.getCreateTime()) + .eq("oi.organ_id",getUserOrganId()) + .eq("og.deleted",false) + .inIfPresent("oi.order_id", orderIds) + .isNull("opi.item_id") + .isNotNull("og.id") + + // todo 修改排单数据筛选,目前只解决了非混单的情况,混单情况待解决 + .eqIfPresent("og.goods_id",pageReqVO.getGoodsId()) .eqIfPresent("op.is_special_shaped", pageReqVO.getRectangle() != null ? false: null) .eqIfPresent("op.is_special_shaped", pageReqVO.getSpecialShaped()) .eqIfPresent("op.is_sculpt", pageReqVO.getSculpt()) @@ -387,36 +751,45 @@ public class PlanServiceImpl implements PlanService { queryWrapperX.likeIfPresent("op.filter_type", insertSeparator(filterTypes)); - List orderIds = orderMapper.selectOrderIds(queryWrapperX); - - if(orderIds.isEmpty()){ - return new PageResult<>(); - } +// List orderIds = orderMapper.selectOrderIds(queryWrapperX); - List orderIdsList = plateMapper.selectOrderIds(orderIds,getUserOrganId()); + IPage orderGoodsResps = orderMapper.selectOrderIds(page,queryWrapperX); + +// if(orderIds.isEmpty()){ +// return new PageResult<>(); +// } +// +// +// List orderIdsList = plateMapper.selectOrderIds(orderIds,getUserOrganId()); +// +// +// List goodsList = orderIdsList.stream().map(OrderIds::getGoodsId).distinct().toList(); +// +// // 修改排单时进行数据筛选,todo 目前只解决非混单情况 +// if(pageReqVO.getGoodsId() != null){ +// +// goodsList = goodsList.stream().filter(f->f.equals(pageReqVO.getGoodsId())).toList(); +// +// } +// +// IPage orderGoodsResps = goodsMapper.selectGoods(page,goodsList, getUserOrganId()); - List goodsList = orderIdsList.stream().map(OrderIds::getGoodsId).distinct().toList(); +// List orderRespVOCopies = orderMapper.selectOrderListByIds(orderIdsList, getUserOrganId()); - IPage orderGoodsResps = goodsMapper.selectGoods(page,goodsList, getUserOrganId()); - - - List orderRespVOCopies = orderMapper.selectOrderListByIds(orderIdsList, getUserOrganId()); - - - for (OrderGoodsResp record : orderGoodsResps.getRecords()) { - record.setNum(orderRespVOCopies.stream().filter(e-> Objects.equals(e.getGoodsId(), record.getGoodsId())). - mapToInt(OrderRespVOCopy::getNum).sum()); - - record.setArea(orderRespVOCopies.stream().filter(e-> Objects.equals(e.getGoodsId(), record.getGoodsId())) - .map(OrderRespVOCopy::getArea) - .reduce(BigDecimal.ZERO,BigDecimal::add)); - - record.setOrderIds(orderIdsList.stream().filter(e -> Objects.equals(e.getGoodsId(), record.getGoodsId())).collect(Collectors.toList())); - record.setOrderList(orderRespVOCopies.stream().filter(e -> Objects.equals(e.getGoodsId(), record.getGoodsId())).collect(Collectors.toList())); - } +// for (OrderGoodsResp record : orderGoodsResps.getRecords()) { +// record.setNum(orderRespVOCopies.stream().filter(e-> Objects.equals(e.getGoodsId(), record.getGoodsId())). +// mapToInt(OrderRespVOCopy::getNum).sum()); +// +// record.setArea(orderRespVOCopies.stream().filter(e-> Objects.equals(e.getGoodsId(), record.getGoodsId())) +// .map(OrderRespVOCopy::getArea) +// .reduce(BigDecimal.ZERO,BigDecimal::add)); +// +// record.setOrderIds(orderIdsList.stream().filter(e -> Objects.equals(e.getGoodsId(), record.getGoodsId())).collect(Collectors.toList())); +//// record.setOrderList(orderRespVOCopies.stream().filter(e -> Objects.equals(e.getGoodsId(), record.getGoodsId())).collect(Collectors.toList())); +// } return new PageResult<>(orderGoodsResps.getRecords(), orderGoodsResps.getTotal()); @@ -466,9 +839,9 @@ public class PlanServiceImpl implements PlanService { if (planDO == null) { throw exception(PLAN_NOT_EXISTS); } - if (planDO.getStatus().equals(PlanStatusEnum.NEWORDER.getStatus()) || planDO.getStatus().equals(PlanStatusEnum.BOARDHASBEENAPPLIEDFOR.getStatus())) { - throw exception(PLAN_NOT_ALLOW_CANCEL); - } +// if (planDO.getStatus().equals(PlanStatusEnum.NEWORDER.getStatus()) || planDO.getStatus().equals(PlanStatusEnum.BOARDHASBEENAPPLIEDFOR.getStatus())) { +// throw exception(PLAN_NOT_ALLOW_CANCEL); +// } Set itemIds = planItemMapper.selectList(new LambdaQueryWrapperX() .eq(PlanItemDO::getOrganId,getUserOrganId()) .eq(PlanItemDO::getPlanId, id)) @@ -484,7 +857,7 @@ public class PlanServiceImpl implements PlanService { return null; } for (Long planId : vo.getPlanIds()) { - validatePlanExists(planId); + validatePlanExists(planId,null); } QueryWrapperX queryWrapperX = new QueryWrapperX<>(); @@ -589,5 +962,74 @@ public class PlanServiceImpl implements PlanService { } + @Override + public List getOrderRoomBody(List orderIds) { + + + List orderRoomBodyLists = orderItemMapper.selectRoomBodyByOrderId(orderIds, getUserOrganId()); + + + return orderRoomBodyLists; + + + } + + + public void deleteByPlanId(List planIds, String index) { + List fieldValues = planIds.stream().map(FieldValue::of).toList(); + + DeleteByQueryRequest.Builder builder = new DeleteByQueryRequest.Builder(); + builder.index(index); + + builder.query(q -> q.terms(b -> b.field("planId").terms(e -> e.value(fieldValues)))); + + try { + DeleteByQueryResponse response = elasticsearchClient.deleteByQuery(builder.build()); + log.info("Deleted {} documents with planId {}", response.deleted(), planIds); + } catch (IOException e) { + log.error("Error deleting documents with planId {}: {}", planIds, e.getMessage()); + throw new ServiceException(ES_ERROR_DELETE); + } + } + + + + public List buildBoardByPlanIds(Collection planIds, String index, Integer size) { + List fieldValues = planIds.stream().map(FieldValue::of).toList(); + SearchRequest.Builder builder = new SearchRequest.Builder(); + builder.index(index); + builder.size(size); + builder.query(q -> q.terms(b -> b.field("planId").terms(e -> e.value(fieldValues)))); + try { + SearchResponse search = elasticsearchClient.search(builder.build(), OptimizeBoardModelDO.class); + List> hits = search.hits().hits(); + if (CollectionUtil.isNotEmpty(hits)) { + return hits.stream().map(Hit::source).collect(Collectors.toList()); + } + return new ArrayList<>(); + } catch (IOException e) { + log.error(e.getMessage()); + throw new ServiceException(INTERNAL_SERVER_ERROR); + } + } + + + private List buildBoardByPlanId(Long planId, String index,Integer size) { + SearchRequest.Builder builder = new SearchRequest.Builder(); + builder.index(index); + builder.size(size); + builder.query(q -> q.term(b -> b.field("planId").value(planId))); + try { + SearchResponse search = elasticsearchClient.search(builder.build(), OptimizeBoardModelDO.class); + List> hits = search.hits().hits(); + if (CollectionUtil.isNotEmpty(hits)) { + return hits.stream().map(Hit::source).collect(Collectors.toList()); + } + return new ArrayList<>(); + } catch (IOException e) { + log.error(e.getMessage()); + throw new ServiceException(INTERNAL_SERVER_ERROR); + } + } } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plate/PlateServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plate/PlateServiceImpl.java index aae596023..d058e5464 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plate/PlateServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plate/PlateServiceImpl.java @@ -1,6 +1,5 @@ package com.cf.imes.module.executor.service.plate; -import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import co.elastic.clients.elasticsearch.ElasticsearchClient; @@ -13,57 +12,44 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; -import com.cf.imes.framework.common.util.json.JsonUtils; -import com.cf.imes.framework.es.core.service.ESDocumentService; +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.mybatis.core.query.MPJLambdaWrapperX; import com.cf.imes.framework.security.core.LoginUser; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.executor.controller.admin.goods.vo.GoodsSaveReqVO; +import com.cf.imes.module.executor.controller.admin.plate.vo.*; import com.cf.imes.module.executor.dal.dataobject.orderBody.OrderBodyDO; import com.cf.imes.module.executor.dal.dataobject.orderItem.OrderItemDO; import com.cf.imes.module.executor.dal.dataobject.ordermodel.OrderModelDO; import com.cf.imes.module.executor.dal.dataobject.planitem.PlanItemDO; -import com.cf.imes.module.executor.dal.dataobject.processStepItem.OrderProcessStepItemDO; +import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO; import com.cf.imes.module.executor.dal.mysql.goods.GoodsMapper; import com.cf.imes.module.executor.dal.mysql.orderBody.OrderBodyMapper; -import com.cf.imes.module.executor.dal.mysql.orderGroup.OrderGroupMapper; import com.cf.imes.module.executor.dal.mysql.orderItem.OrderItemMapper; import com.cf.imes.module.executor.dal.mysql.planitem.PlanItemMapper; +import com.cf.imes.module.executor.dal.mysql.plate.PlateMapper; import com.cf.imes.module.executor.dal.mysql.processStepItem.ProcessStepItemMapper; import com.cf.imes.module.executor.enums.OrderItemType; -import com.cf.imes.module.executor.util.RandomUtils; import com.cf.imes.module.executor.util.fileConversion.admin.SnowflakeIdWorker3rd; import com.cf.imes.module.system.enums.ErrorCodeConstants; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; - -import org.springframework.validation.annotation.Validated; -import org.springframework.transaction.annotation.Transactional; - import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.util.*; import java.util.stream.Collectors; -import com.cf.imes.module.executor.controller.admin.plate.vo.*; -import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO; -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.common.util.object.BeanUtils; - -import com.cf.imes.module.executor.dal.mysql.plate.PlateMapper; - import static com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; import static com.cf.imes.module.executor.service.optimizeplan.OptimizePlanService.ORDER_PLATE_MODEL; -import static com.cf.imes.module.system.enums.ErrorCodeConstants.*; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.PLATE_NOT_EXISTS; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.THE_CURRENT_BOARD_IS_NOT_SELECTED; /** * 生产单板件 Service 实现类 @@ -267,6 +253,8 @@ public class PlateServiceImpl implements PlateService { } + Long goodsId = goodsMapper.selectGoodsId(reqVO.getOrderId(), reqVO.getGoodsId(), getUserOrganId()).getId(); + List plateDOS = new ArrayList<>(); for (int i = 0; i < reqVO.getMultiple(); i++) { @@ -279,7 +267,7 @@ public class PlateServiceImpl implements PlateService { plateDO.setRemark(reqVO.getRemake1() +","+ reqVO.getRemake2()); plateDO.setHoleArrange(reqVO.getPlaceHole()); - plateDO.setGoodsId(reqVO.getGoodsId()); + plateDO.setGoodsId(goodsId); plateDO.setPlateNo((obtainingTime) + Long.toString(plateNo).substring(2)); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/application.yaml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/application.yaml index 3b2c8da47..56cd5da62 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/application.yaml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/application.yaml @@ -160,5 +160,7 @@ chenfeng: send-maximum-quantity-per-day: 10 begin-code: 9999 # 这里配置 9999 的原因是,测试方便。 end-code: 9999 # 这里配置 9999 的原因是,测试方便。 - + encrypt: + enable: false + publicKey: cfimes debug: false diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/goods/GoodsMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/goods/GoodsMapper.xml index 215cf82f0..7bf338290 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/goods/GoodsMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/goods/GoodsMapper.xml @@ -32,9 +32,9 @@ orp.id as remainId from order_goods og left join order_remain_plate orp on og.id = orp.goods_id and og.organ_id = orp.organ_id - where og.organ_id =#{organId} and og.deleted = false and og.order_id in + where og.organ_id =#{organId} and og.deleted = false and og.id in - + #{id} @@ -90,15 +90,48 @@ + + + \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml index f9a372026..8b77ae91f 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml @@ -3,29 +3,77 @@ - + + + + + @@ -65,7 +113,6 @@ and o.organ_id = #{organId} and op.deleted = false - and op.is_cancel = 0 and og.goods_id in @@ -166,4 +213,73 @@ ORDER BY order_date; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderStatisticsMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderStatisticsMapper.xml index 565163bf0..cfa743c1f 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderStatisticsMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderStatisticsMapper.xml @@ -3,8 +3,8 @@ diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderItem/OrderItemMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderItem/OrderItemMapper.xml index 54c5b4426..5360f906c 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderItem/OrderItemMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderItem/OrderItemMapper.xml @@ -207,6 +207,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderParts/OrderPartsMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderParts/OrderPartsMapper.xml index 3bc165a7b..6bb203cff 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderParts/OrderPartsMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderParts/OrderPartsMapper.xml @@ -121,4 +121,22 @@ WHERE order_id = #{orderId} AND organ_id = #{organId} AND deleted = #{deleted} + + + + \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plan/PlanMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plan/PlanMapper.xml index dbcc2eae8..6f9bff1be 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plan/PlanMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plan/PlanMapper.xml @@ -140,8 +140,7 @@ ,CONCAT(YEAR(p.create_time), '-', MONTH(p.create_time), '-', DAY(p.create_time)) as date from order_plan p - where p.organ_id = #{req.organId} - and p.create_time between #{req.createTime[0]} and #{req.createTime[1]} + where p.create_time between #{req.createTime[0]} and #{req.createTime[1]} and p.deleted = 0 group by date; @@ -162,12 +161,55 @@ ,CONCAT(YEAR(p.create_time), '-', MONTH(p.create_time), '-', DAY(p.create_time)) as date from order_plan p - join order_plan_item opi on p.id = opi.plan_id and opi.organ_id = #{req.organId} - join order_item oi on oi.id = opi.item_id and oi.organ_id = #{req.organId} - join order_plate op on oi.plate_id = op.id and op.organ_id = #{req.organId} - where p.organ_id = #{req.organId} - and p.create_time between #{req.createTime[0]} and #{req.createTime[1]} + join order_plan_item opi on p.id = opi.plan_id + join order_item oi on oi.id = opi.item_id + join order_plate op on oi.plate_id = op.id + where p.create_time between #{req.createTime[0]} and #{req.createTime[1]} and p.deleted = 0 group by date; + + + + + + + + + + \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/planitem/PlanItemMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/planitem/PlanItemMapper.xml index 1b061a05d..4bccbfb7b 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/planitem/PlanItemMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/planitem/PlanItemMapper.xml @@ -13,8 +13,20 @@ + + + + + + + + + + + + diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/OrderPlateStatisticsMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/OrderPlateStatisticsMapper.xml index 30c9e277b..2354fd008 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/OrderPlateStatisticsMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/OrderPlateStatisticsMapper.xml @@ -6,12 +6,12 @@ count(a.id) as orderCount from order_goods g left join order_plate a ON g.id = a.goods_id and a.deleted = 0 - left join orders o ON o.id = a.order_id and o.deleted = 0 + join orders o ON o.id = a.order_id and o.deleted = 0 where g.deleted = 0 and o.order_date between #{req.createTime[0]} and #{req.createTime[1]} group by g.goods_id - having orderCount > 0 - order by null; + order by orderCount desc + limit 10; - + + + select distinct + c.texture, + c.width, + c.height, + c.thickness, + c.goods_name, + c.material, + c.color, + c.brand, + + c.order_id as orderId, + c.id as id, + c.goods_id as goodsId + + from order_plate a + LEFT JOIN order_item oi on a.id = oi.plate_id and a.order_id = oi.order_id and a.organ_id = oi.organ_id + LEFT JOIN order_goods c on a.goods_id = c.id and a.organ_id = c.organ_id + left join order_plan_item opi on oi.id = opi.item_id and oi.organ_id = opi.organ_id + + ${ew.customSqlSegment} + @@ -536,7 +589,7 @@ from order_plate a LEFT JOIN order_item oi on a.id = oi.plate_id and a.order_id = oi.order_id and a.organ_id = oi.organ_id - LEFT JOIN `orders` b on a.order_id = b.id and a.organ_id = b.organ_id +-- LEFT JOIN `orders` b on a.order_id = b.id and a.organ_id = b.organ_id LEFT JOIN order_goods c on a.goods_id = c.id and a.organ_id = c.organ_id left join order_plan_item opi on oi.id = opi.item_id and oi.organ_id = opi.organ_id where @@ -564,13 +617,10 @@ c.goods_id as goodsId from order_plate a LEFT JOIN order_item oi on a.id = oi.plate_id and a.order_id = oi.order_id and a.organ_id = oi.organ_id - LEFT JOIN `orders` b on a.order_id = b.id and a.organ_id = b.organ_id LEFT JOIN order_goods c on a.goods_id = c.id and a.organ_id = c.organ_id left join order_plan_item opi on oi.id = opi.item_id and oi.organ_id = opi.organ_id where - c.organ_id = #{organId} - and a.is_cancel = 0 - and b.status = 2 + c.organ_id = #{organId} and a.deleted = false and opi.item_id is null and c.order_id in @@ -581,6 +631,28 @@ + + + + + + + + + + \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/remainplaten/RemainPlateMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/remainplaten/RemainPlateMapper.xml new file mode 100644 index 000000000..16f5967c0 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/remainplaten/RemainPlateMapper.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/controller/admin/pack/PackController.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/controller/admin/pack/PackController.java index 22473a6a9..f54ce90d9 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/controller/admin/pack/PackController.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/controller/admin/pack/PackController.java @@ -2,10 +2,7 @@ package com.cf.imes.module.manage.controller.admin.pack; import com.cf.imes.framework.common.pojo.CommonResult; -import com.cf.imes.framework.common.pojo.PageParam; import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.excel.core.util.ExcelUtils; -import com.cf.imes.framework.operatelog.core.annotations.OperateLog; import com.cf.imes.module.manage.controller.admin.pack.prePack.PrePackReqVO; import com.cf.imes.module.manage.controller.admin.pack.vo.*; import com.cf.imes.module.manage.controller.admin.query.vo.pack.OrderPackageVO; @@ -20,14 +17,10 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; - -import java.io.IOException; import java.util.List; import static com.cf.imes.framework.common.pojo.CommonResult.success; -import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - 生产打包 ") @RestController @@ -80,15 +73,25 @@ public class PackController { @GetMapping("/getOrderPack") - @Operation(summary = "查看生产订单对应的包裹信息") + @Operation(summary = "查看生产订单对应的包裹信息-未分页") @PreAuthorize("@ss.hasPermission('manage:pack:query')") - public CommonResult> getOrderPack(@Valid PackageDetailsReqVO reqVO) { + public CommonResult> getOrderPack(@Valid PackageDetailsReqVO reqVO) { return success(packService.getOrderPack(reqVO)); } + @GetMapping("/getPageOrderPack") + @Operation(summary = "查看生产订单对应的包裹信息-分页") + @PreAuthorize("@ss.hasPermission('manage:pack:query')") + public CommonResult> getPageOrderPack(@Valid PackageDetailsReqVO reqVO) { + + return success(packService.getPageOrderPack(reqVO)); + + } + + @GetMapping("/queryPackageDetails") @Operation(summary = "查询包裹的详细信息") diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.java index bf39ef5c9..29ad347ed 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.java @@ -1,13 +1,15 @@ package com.cf.imes.module.manage.dal.mysql.pack; +import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Constants; import com.cf.imes.framework.common.enums.OrderPackageStatusEnum; +import com.cf.imes.framework.common.enums.OrderPackageTypeEnum; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.module.manage.controller.admin.pack.vo.PackRespVO; -import com.cf.imes.module.manage.controller.admin.pack.vo.PackageDetailsReqVO; import com.cf.imes.module.manage.controller.admin.pack.vo.PlateAndPartIdList; import com.cf.imes.module.manage.controller.admin.pack.vo.PlateDetailsRespVO; import com.cf.imes.module.manage.controller.admin.query.vo.pack.OrderPackageVO; @@ -29,8 +31,9 @@ public interface OrderPackageMapper extends BaseMapperX { // } - IPage selectByOrderNo(@Param("page") IPage page, @Param("reqVO") PackageDetailsReqVO reqVO, @Param("organId") Long organId); +// IPage selectByOrderNo(@Param("page") IPage page, @Param("reqVO") PackageDetailsReqVO reqVO,@Param("packId") List packId, @Param("organId") Long organId); + IPage selectByOrderNo(@Param("page") IPage page, @Param(Constants.WRAPPER) Wrapper wrapper); default OrderPackageDO selectByPackNo(String packNo,Long organId) { return selectOne(new LambdaQueryWrapperX() @@ -81,10 +84,16 @@ public interface OrderPackageMapper extends BaseMapperX { // 删除当前生产单下所有的包裹 - default void updateDelete(Long orderId) { + default void updateDelete(Long orderId,Long organId) { LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper() .set(OrderPackageDO::getDeleted, true) - .eq(OrderPackageDO::getOrderId, orderId); + .eq(OrderPackageDO::getOrganId,organId) + .eq(OrderPackageDO::getOrderId, orderId) + .eq(OrderPackageDO::getType, OrderPackageTypeEnum.PLATE.getType()); update(wrapper); } + + + List selectPackListByOrderId(@Param("orderId") Long orderId,@Param("organId") Long organId); + } diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/plate/OrderPlateMapper.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/plate/OrderPlateMapper.java index e1e0d835b..e0a95fc90 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/plate/OrderPlateMapper.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/plate/OrderPlateMapper.java @@ -3,10 +3,8 @@ package com.cf.imes.module.manage.dal.mysql.plate; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.cf.imes.module.manage.controller.admin.patching.vo.PatchingDetailReqVO; import com.cf.imes.module.manage.controller.admin.patching.vo.PatchingDetailRespVO; import com.cf.imes.module.manage.controller.admin.patching.vo.PatchingPlatePageReqVO; -import com.cf.imes.module.manage.controller.admin.process.vo.OrderPlateReqVO; import com.cf.imes.module.manage.controller.admin.process.vo.PlateDetails; import com.cf.imes.module.manage.dal.dataobject.plate.OrderPlateDO; import org.apache.ibatis.annotations.Mapper; @@ -38,4 +36,13 @@ public interface OrderPlateMapper extends BaseMapperX { .in(OrderPlateDO::getPlateNo, plateNo)); } + + + default List selectplateByPlateNo(Long plateNo, Long orderId, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(OrderPlateDO::getOrganId, organId) + .eq(OrderPlateDO::getOrderId, orderId) + .likeIfPresent(OrderPlateDO::getPlateNo, plateNo.toString()) + .select(OrderPlateDO::getId)); + } } diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/query/ProductionStatusMapper.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/process/OrdersMapper.java similarity index 53% rename from cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/query/ProductionStatusMapper.java rename to cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/process/OrdersMapper.java index ab6e9464c..5582cc07c 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/query/ProductionStatusMapper.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/process/OrdersMapper.java @@ -1,4 +1,4 @@ -package com.cf.imes.module.manage.dal.mysql.query; +package com.cf.imes.module.manage.dal.mysql.process; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -9,17 +9,15 @@ import com.cf.imes.module.manage.controller.admin.pack.vo.PackPageReqVO; import com.cf.imes.module.manage.controller.admin.pack.vo.PackRespVO; import com.cf.imes.module.manage.controller.admin.pack.vo.PrintOrderPackRespVO; import com.cf.imes.module.manage.controller.admin.query.vo.productionStatus.OrderPlatePageReqVO; -import com.cf.imes.module.manage.controller.admin.query.vo.pack.PrintOrderRespVO; import com.cf.imes.module.manage.dal.dataobject.process.OrderDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; -import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; - @Mapper -public interface ProductionStatusMapper extends BaseMapperX { +public interface OrdersMapper extends BaseMapperX { + default PageResult selectProductionPage(OrderPlatePageReqVO pageReqVO) { @@ -38,32 +36,24 @@ public interface ProductionStatusMapper extends BaseMapperX { + List selectOrderIds( @Param("createTime") String createTime, @Param("organId") Long organId, @Param("orderId") Long orderId); - PrintOrderRespVO selectPrintOrder(@Param("orderNo") Long orderNo,@Param("organId")Long organId); - - -// default List selectOrderIds(PackPageReqVO pageReqVO,Long organId) { -// return selectList(new LambdaQueryWrapperX() -// .eq(OrderDO::getOrganId,organId) -// .eqIfPresent(OrderDO::getId, pageReqVO.getOrderId()) -// .eqIfPresent(OrderDO::getCustomOrderNo, pageReqVO.getCustomOrderNo()) -// .likeIfPresent(OrderDO::getCustomer, pageReqVO.getCustomer()) -// .likeIfPresent(OrderDO::getAddress, pageReqVO.getAddress()) -// .eqIfPresent(OrderDO::getStatus, pageReqVO.getStatus()) -// .orderByDesc(OrderDO::getCreateTime)); -// } - - IPage selectOrderPlate( @Param("page") IPage page, @Param("orderIds") List orderIds, @Param("organId") Long organId); + List selectOrderIdsFalse( @Param("createTime") String createTime,@Param("organId") Long organId, @Param("orderId") Long orderId); - - PrintOrderPackRespVO selectOrderPack(@Param("orderNo")Long orderNo,@Param("packageNo") Long packageNo, @Param("organId") Long organId); + IPage selectOrderPlate(@Param("page") IPage page, @Param("orderIds") List orderIds, @Param("organId") Long organId); - List selectOrderIds(@Param("pageReqVO") PackPageReqVO pageReqVO,@Param("organId") Long organId); + PrintOrderPackRespVO selectOrderPack(@Param("orderNo")Long orderNo, @Param("packageNo") Long packageNo, @Param("organId") Long organId); + + + + IPage selectOrderIdList(@Param("page") IPage page, @Param("pageReqVO") PackPageReqVO pageReqVO, @Param("organId") Long organId); + + } diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/process/ProductionProcessMapper.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/process/ProductionProcessMapper.java deleted file mode 100644 index cb955a485..000000000 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/process/ProductionProcessMapper.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.cf.imes.module.manage.dal.mysql.process; - - - -import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; -import com.cf.imes.module.manage.controller.admin.patching.vo.PatchingPlatePageReqVO; -import com.cf.imes.module.manage.controller.admin.patching.vo.PatchingPlateRespVO; -import com.cf.imes.module.manage.dal.dataobject.process.OrderDO; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 生产单表 order_{N} Mapper - * - * @author 晨丰科技 - */ -@Mapper -public interface ProductionProcessMapper extends BaseMapperX { - - - - - - List selectPatchingPlate(PatchingPlatePageReqVO pageReqVO); - - - OrderDO selectOrderIds(@Param("createTime") String createTime, @Param("organId") Long organId, @Param("orderId") Long orderId); - - OrderDO selectOrderIdsFalse(@Param("createTime") String createTime,@Param("organId") Long organId, @Param("orderId") Long orderId); - - -// OrderDO selectOrderIds(@Param("orderId") Long orderId,@Param("organId") Long organId); -// -// OrderDO selectOrderIdsFalse(@Param("orderId") Long orderId,@Param("organId") Long userOrganId); - - - - -} \ No newline at end of file diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/query/OrderItemMapper.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/query/OrderItemMapper.java index cbed9c208..8ad79532b 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/query/OrderItemMapper.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/query/OrderItemMapper.java @@ -1,12 +1,11 @@ package com.cf.imes.module.manage.dal.mysql.query; - -import com.baomidou.mybatisplus.core.metadata.IPage; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.cf.imes.module.manage.controller.admin.pack.vo.*; -import com.cf.imes.module.manage.controller.admin.process.vo.OrderPlateReqVO; +import com.cf.imes.module.manage.controller.admin.pack.vo.OrderPlateDetailsRespVO; +import com.cf.imes.module.manage.controller.admin.pack.vo.PackRespVO; +import com.cf.imes.module.manage.controller.admin.pack.vo.PlateDetailsRespVO; import com.cf.imes.module.manage.controller.admin.process.vo.PlateDetails; import com.cf.imes.module.manage.controller.admin.process.vo.ProcessPlateReqVO; import com.cf.imes.module.manage.controller.admin.query.vo.pack.PackageDetailsRespVO; @@ -14,13 +13,10 @@ import com.cf.imes.module.manage.controller.admin.query.vo.productionStatus.Orde import com.cf.imes.module.manage.controller.admin.query.vo.productionStatus.OrderPlateRespVO; import com.cf.imes.module.manage.controller.admin.query.vo.productionStatus.PlatePageVO; import com.cf.imes.module.manage.dal.dataobject.query.OrderItemDO; -import com.cf.imes.module.manage.dal.dataobject.query.OrderPackageDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; - import java.util.List; -import java.util.stream.Collectors; @Mapper public interface OrderItemMapper extends BaseMapperX { @@ -98,4 +94,24 @@ public interface OrderItemMapper extends BaseMapperX { .eqIfPresent(OrderItemDO::getOrderId, orderId)); } + + List selectPlateNum(@Param("orderIds") List orderIds,@Param("organId") Long organId); + + + + default List selectPartsList(Long orderId, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(OrderItemDO::getOrganId, organId) + .eqIfPresent(OrderItemDO::getOrderId, orderId) + .eq(OrderItemDO::getPackageId,0) + .select(OrderItemDO::getPartsId)); + } + + + default List selectPackByPlateId(List plateId, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(OrderItemDO::getOrganId, organId) + .inIfPresent(OrderItemDO::getPlateId, plateId) + .select(OrderItemDO::getPackageId)); + } } diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackService.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackService.java index 8e304307d..33cccfaa8 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackService.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackService.java @@ -16,9 +16,11 @@ public interface PackService { // 查看生产订单对应的包裹信息 - PageResult getOrderPack(PackageDetailsReqVO reqVO); + List getOrderPack(PackageDetailsReqVO reqVO); + PageResult getPageOrderPack(PackageDetailsReqVO reqVO); + // 查看生产订单对应的板材信息 List getOrderPlateList(Long orderId); diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackServiceImpl.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackServiceImpl.java index c95fabd8f..2b651c340 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackServiceImpl.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackServiceImpl.java @@ -10,6 +10,7 @@ import com.cf.imes.framework.common.enums.UserSettingTypeEnum; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.util.json.JsonUtils; import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.framework.mybatis.core.query.QueryWrapperX; import com.cf.imes.module.manage.controller.admin.pack.prePack.PackPlateList; import com.cf.imes.module.manage.controller.admin.pack.prePack.PrePackOptimizeInfo; import com.cf.imes.module.manage.controller.admin.pack.prePack.PrePackReqVO; @@ -25,13 +26,10 @@ import com.cf.imes.module.manage.dal.mysql.pack.OrderBodyMapper; import com.cf.imes.module.manage.dal.mysql.pack.OrderPackageMapper; import com.cf.imes.module.manage.dal.mysql.pack.OrderPrepackagedMapper; import com.cf.imes.module.manage.dal.mysql.plate.OrderPlateMapper; -import com.cf.imes.module.manage.dal.mysql.process.ProcessStepItemMapper; -import com.cf.imes.module.manage.dal.mysql.process.ProcessStepMapper; -import com.cf.imes.module.manage.dal.mysql.process.ProductionProcessMapper; +import com.cf.imes.module.manage.dal.mysql.plate.PlateMapper; +import com.cf.imes.module.manage.dal.mysql.process.OrdersMapper; import com.cf.imes.module.manage.dal.mysql.query.OrderItemMapper; import com.cf.imes.module.manage.dal.mysql.query.OrderPartsMapper; -import com.cf.imes.module.manage.dal.mysql.query.ProductionStatusMapper; -import com.cf.imes.module.manage.service.process.ProductionProcessServiceImpl; import com.cf.imes.module.manage.util.SnowflakeIdWorker3rd; import com.cf.imes.module.system.api.setting.SettingApi; import com.cf.imes.module.system.api.setting.dto.PackageConfigDTO; @@ -64,8 +62,6 @@ public class PackServiceImpl implements PackService { @Resource private OrderPackageMapper orderPackageMapper; - @Resource - private ProductionStatusMapper productionStatusMapper; @Resource private OrderItemMapper orderItemMapper; @@ -80,16 +76,11 @@ public class PackServiceImpl implements PackService { private OrderPlateMapper orderPlateMapper; @Resource - private ProcessStepMapper processStepMapper; + private OrdersMapper ordersMapper; @Resource - private ProductionProcessServiceImpl productionProcessService; + private PlateMapper plateMapper; - @Resource - private ProcessStepItemMapper processStepItemMapper; - - @Resource - private ProductionProcessMapper productionProcessMapper; @Resource private SnowflakeIdWorker3rd idWorker; @@ -110,48 +101,62 @@ public class PackServiceImpl implements PackService { List orderIds = new ArrayList<>(); + + IPage packRespVOS = new PageDTO<>(); + + if(pageReqVO.getIsUp() != null){ - OrderDO order = productionProcessMapper.selectById(pageReqVO.getOrderId()); + OrderDO order = ordersMapper.selectById(pageReqVO.getOrderId()); - OrderDO orderDO = pageReqVO.getIsUp() ? - productionProcessMapper.selectOrderIds(order.getCreateTime().toString(), getUserOrganId(),order.getId()) : + List packRespVOList = pageReqVO.getIsUp() ? + ordersMapper.selectOrderIds(order.getCreateTime().toString(), getUserOrganId(),order.getId()) : - productionProcessMapper.selectOrderIdsFalse(order.getCreateTime().toString(), getUserOrganId(),order.getId()); + ordersMapper.selectOrderIdsFalse(order.getCreateTime().toString(), getUserOrganId(),order.getId()); - if(orderDO == null){ + if(packRespVOList.isEmpty()){ throw exception(NO_PRODUCTION_ORDER_INFORMATION_AVAILABLE, pageReqVO.getIsUp() ?"第" : "最后"); } - orderIds.add(orderDO.getId()); + packRespVOS.setRecords(packRespVOList); + + orderIds.addAll(packRespVOS.getRecords().stream().map(PackRespVO::getId).toList()); + }else { pageReqVO.setCustomer(insertSeparator(pageReqVO.getCustomer())); pageReqVO.setCustomOrderNo(insertSeparator(pageReqVO.getCustomOrderNo())); pageReqVO.setAddress(insertSeparator(pageReqVO.getAddress())); - // 根据生产状态查询生产单号 -// List orderIds = productionStatusMapper.selectOrderIds(pageReqVO, getUserOrganId()).stream().map(OrderDO::getId).toList(); - orderIds.addAll(productionStatusMapper.selectOrderIds(pageReqVO, getUserOrganId()).stream().map(OrderDO::getId).toList()); + // 查询查询分页 + packRespVOS = ordersMapper.selectOrderIdList(page,pageReqVO, getUserOrganId()); + + orderIds.addAll(packRespVOS.getRecords().stream().map(PackRespVO::getId).toList()); if (orderIds.isEmpty()) { return null; } } - // 查询打包首页分页数据信息,总的板件数量信息 - IPage packRespVOS = productionStatusMapper.selectOrderPlate(page,orderIds,getUserOrganId()); + + // 查询板材的总量 + List packRespVOList = orderItemMapper.selectPlateNum(orderIds,getUserOrganId()); + // 查询当前生产的包裹数量 List respVOS = orderPackageMapper.selectPackPage(orderIds,getUserOrganId()); + // 查询当前生产单已经打包的板材数量 List plateNum = orderPackageMapper.selectPackPieceCount(orderIds, getUserOrganId()); + for (PackRespVO record : packRespVOS.getRecords()) { + // 板材总数 + record.setTotalPieceCount(packRespVOList.stream().filter(f -> Objects.equals(f.getId(), record.getId())).mapToLong(PackRespVO::getTotalPieceCount).sum()); // 已打包数 record.setPackCount(respVOS.stream().filter(f -> Objects.equals(f.getId(), record.getId())).mapToLong(PackRespVO::getPackCount).sum()); // 已打包片数 @@ -238,13 +243,73 @@ public class PackServiceImpl implements PackService { } + // 查看生产订单对应的包裹信息 @Override - public PageResult getOrderPack(PackageDetailsReqVO reqVO) { + public List getOrderPack(PackageDetailsReqVO reqVO) { + + + List orderPackageVOS = orderPackageMapper.selectPackListByOrderId(reqVO.getOrderId(), getUserOrganId()); + + OrderDO orderDO = ordersMapper.selectById(reqVO.getOrderId()); + + // for (OrderPackageVO orderPackageVO : orderPackageVOS) { +// orderPackageVO.setCustomOrderNo(orderDO.getCustomOrderNo()); +// orderPackageVO.setCustomer(orderDO.getCustomer()); +// orderPackageVO.setAddress(orderDO.getAddress()); +// orderPackageVO.setDealer(orderDO.getDealer()); +// orderPackageVO.setOrderRemark(orderDO.getRemark()); +// } + + + return orderPackageVOS.stream().peek(m -> { + m.setCustomOrderNo(orderDO.getCustomOrderNo()); + m.setCustomer(orderDO.getCustomer()); + m.setAddress(orderDO.getAddress()); + m.setDealer(orderDO.getDealer()); + m.setOrderRemark(orderDO.getRemark()); + } + ).toList(); + + } + + + + @Override + public PageResult getPageOrderPack(PackageDetailsReqVO reqVO) { PageDTO page = new PageDTO<>(reqVO.getPageNo(), reqVO.getPageSize()); - IPage orderPackageDOIPage = orderPackageMapper.selectByOrderNo(page,reqVO, getUserOrganId()); + List packId = null; + + if(reqVO.getPlateNo()!= null){ + + + List plateId = orderPlateMapper.selectplateByPlateNo(reqVO.getPlateNo(), reqVO.getOrderId(), getUserOrganId()) + .stream().map(OrderPlateDO::getId).toList(); + + if(plateId.isEmpty()){ + return null; + } + + packId = orderItemMapper.selectPackByPlateId(plateId, getUserOrganId()).stream().map(OrderItemDO::getPackageId).distinct().toList(); + + } + + + QueryWrapperX queryWrapperX = new QueryWrapperX<>(); + queryWrapperX + .eq("o.organ_id",getUserOrganId()) + .eq("o.deleted",false) + .eq("op.deleted",false) + .eq("o.id",reqVO.getOrderId()) + .likeIfPresent("op.package_no",reqVO.getPackageNo()) + .inIfPresent("op.id",packId) + .eqIfPresent("op.status", reqVO.getPackStatus()) + .orderByDesc("op.create_time"); + + + IPage orderPackageDOIPage = orderPackageMapper.selectByOrderNo(page,queryWrapperX); if (CollectionUtil.isEmpty(orderPackageDOIPage.getRecords())) { @@ -261,9 +326,6 @@ public class PackServiceImpl implements PackService { - - - // 查看配件列表分页 @Override public List getPartsList(OrderPartsReqVO reqVO) { @@ -497,7 +559,7 @@ public class PackServiceImpl implements PackService { @Transactional(rollbackFor = Exception.class) public void updateOrderStatus(Long orderId) { - OrderDO orderDO = productionProcessMapper.selectById(orderId); + OrderDO orderDO = ordersMapper.selectById(orderId); if(orderDO.getFinishTime() != null){ return; @@ -525,7 +587,7 @@ public class PackServiceImpl implements PackService { // 修改生产单的打包状态未已打包 orderDO.setPackaged(OrderPackageStatusEnum.PACKAGED.getStatus()); - productionProcessMapper.updateById(orderDO); + ordersMapper.updateById(orderDO); } @@ -549,7 +611,7 @@ public class PackServiceImpl implements PackService { @Override public PrintOrderPackRespVO printOrderPack(PrintOrderPackReqVO reqVO) { - PrintOrderPackRespVO printOrderPackRespVO = productionStatusMapper.selectOrderPack(reqVO.getOrderId(), reqVO.getPackageNo(),getUserOrganId()); + PrintOrderPackRespVO printOrderPackRespVO = ordersMapper.selectOrderPack(reqVO.getOrderId(), reqVO.getPackageNo(),getUserOrganId()); printOrderPackRespVO.setPlateList(orderItemMapper.selectPrintPlateList(reqVO.getOrderId(), reqVO.getPackageNo(),getUserOrganId())); return printOrderPackRespVO; @@ -799,7 +861,8 @@ public class PackServiceImpl implements PackService { if(!packageDOS.isEmpty()){ - orderPackageMapper.updateDelete(reqVO.getOrderId()); + // 删除除配件和其他配件外的所有包裹 + orderPackageMapper.updateDelete(reqVO.getOrderId(),getUserOrganId()); } @@ -828,6 +891,14 @@ public class PackServiceImpl implements PackService { orderItemMapper.updateBatch(orderItemDOS); + List orderItemDoPartsList = orderItemMapper.selectPartsList(reqVO.getOrderId(), getUserOrganId()); + + if(orderItemDoPartsList.isEmpty()) { + OrderDO orderDO = ordersMapper.selectById(reqVO.getOrderId()); + orderDO.setPackaged(OrderPackageStatusEnum.PACKAGED.getStatus()); + ordersMapper.updateById(orderDO); + } + } diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/patching/PatchingPlateServiceImpl.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/patching/PatchingPlateServiceImpl.java index 1734343a6..51d007b3e 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/patching/PatchingPlateServiceImpl.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/patching/PatchingPlateServiceImpl.java @@ -1,22 +1,15 @@ package com.cf.imes.module.manage.service.patching; -import com.alibaba.nacos.shaded.com.google.gson.Gson; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.util.json.JsonUtils; -import com.cf.imes.framework.common.util.object.BeanUtils; -import com.cf.imes.module.manage.controller.admin.pack.vo.PlateDetailsRespVO; import com.cf.imes.module.manage.controller.admin.patching.vo.*; -import com.cf.imes.module.manage.controller.admin.query.vo.productionStatus.OrderPlateRespVO; +import com.cf.imes.module.manage.dal.dataobject.patching.MachineDO; import com.cf.imes.module.manage.dal.dataobject.patching.PatchDetailDO; -import com.cf.imes.module.manage.dal.dataobject.plate.OrderPlateDO; import com.cf.imes.module.manage.dal.mysql.patching.MachineMapper; import com.cf.imes.module.manage.dal.mysql.patching.PatchDetailMapper; import com.cf.imes.module.manage.dal.mysql.plate.OrderPlateMapper; -import com.cf.imes.module.manage.dal.mysql.plate.PlateMapper; -import com.cf.imes.module.manage.dal.mysql.process.ProductionProcessMapper; import com.cf.imes.module.manage.util.page.PageHelperUtil; -import com.cf.imes.module.manage.dal.dataobject.patching.MachineDO; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.springframework.stereotype.Service; @@ -30,8 +23,7 @@ import java.util.List; public class PatchingPlateServiceImpl implements PatchingPlateService{ - @Resource - private ProductionProcessMapper productionProcessMapper; + @Resource private OrderPlateMapper orderPlateMapper; @@ -48,15 +40,7 @@ public class PatchingPlateServiceImpl implements PatchingPlateService{ @Override public PageResult patchingSearchPlate(PatchingPlatePageReqVO pageReqVO) { - - // 查询板件和订单的基础信息 - PageHelper.startPage(pageReqVO.getPageNo(), pageReqVO.getPageSize()); - List patchingPlateRespVOS = productionProcessMapper.selectPatchingPlate(pageReqVO); - - // - PageInfo pageInfo = new PageInfo<>(patchingPlateRespVOS); - return PageHelperUtil.convertToPageResult(pageInfo); - + return null; } diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/process/ProductionProcessServiceImpl.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/process/ProductionProcessServiceImpl.java index 61a96f7cf..93a192e8f 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/process/ProductionProcessServiceImpl.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/process/ProductionProcessServiceImpl.java @@ -2,8 +2,6 @@ package com.cf.imes.module.manage.service.process; import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; import com.cf.imes.framework.common.enums.OrderStatusEnum; @@ -15,15 +13,14 @@ import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.module.manage.controller.admin.process.vo.*; import com.cf.imes.module.manage.controller.admin.query.vo.productionStatus.OrderModuleVO; import com.cf.imes.module.manage.dal.dataobject.pack.OrderBodyDO; -import com.cf.imes.module.manage.dal.dataobject.plate.OrderPlateDO; -import com.cf.imes.module.manage.dal.dataobject.plate.PlateDO; import com.cf.imes.module.manage.dal.dataobject.process.OrderDO; import com.cf.imes.module.manage.dal.dataobject.process.OrderProcessStepItemNDO; import com.cf.imes.module.manage.dal.dataobject.process.OrderProcessStepNDO; import com.cf.imes.module.manage.dal.mysql.pack.OrderBodyMapper; import com.cf.imes.module.manage.dal.mysql.plate.OrderPlateMapper; -import com.cf.imes.module.manage.dal.mysql.plate.PlateMapper; -import com.cf.imes.module.manage.dal.mysql.process.*; +import com.cf.imes.module.manage.dal.mysql.process.OrdersMapper; +import com.cf.imes.module.manage.dal.mysql.process.ProcessStepItemMapper; +import com.cf.imes.module.manage.dal.mysql.process.ProcessStepMapper; import com.cf.imes.module.manage.dal.mysql.query.OrderItemMapper; import com.cf.imes.module.system.api.process.ProcessApi; import com.cf.imes.module.system.enums.ErrorCodeConstants; @@ -35,7 +32,7 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.math.BigDecimal; import java.time.LocalDateTime; -import java.util.*; +import java.util.List; import java.util.stream.Collectors; import static com.cf.imes.framework.common.util.string.SearchUtil.insertSeparator; @@ -73,7 +70,7 @@ public class ProductionProcessServiceImpl implements ProductionProcessService { private OrderPlateMapper orderPlateMapper; @Resource - private ProductionProcessMapper productionProcessMapper; + private OrdersMapper ordersMapper; @Resource @@ -161,10 +158,10 @@ public class ProductionProcessServiceImpl implements ProductionProcessService { } // 当前工序已全部加工,修改生产单的状态为生产完成 if(validateOrderStatus(processStepStatuses.getOrderId())){ - OrderDO orderDO = productionProcessMapper.selectById(processStepStatuses.getOrderId()); + OrderDO orderDO = ordersMapper.selectById(processStepStatuses.getOrderId()); orderDO.setStatus(OrderStatusEnum.FINISH_PRODUCTION.getStatus()); orderDO.setFinishTime(LocalDateTime.now()); - productionProcessMapper.updateById(orderDO); + ordersMapper.updateById(orderDO); } return; @@ -192,10 +189,10 @@ public class ProductionProcessServiceImpl implements ProductionProcessService { } // 当前工序已全部加工,修改生产单的状态为生产完成 if(validateOrderStatus(processStepStatuses.getOrderId())){ - OrderDO orderDO = productionProcessMapper.selectById(processStepStatuses.getOrderId()); + OrderDO orderDO = ordersMapper.selectById(processStepStatuses.getOrderId()); orderDO.setStatus(OrderStatusEnum.FINISH_PRODUCTION.getStatus()); orderDO.setFinishTime(LocalDateTime.now()); - productionProcessMapper.updateById(orderDO); + ordersMapper.updateById(orderDO); } return; @@ -211,19 +208,19 @@ public class ProductionProcessServiceImpl implements ProductionProcessService { // 判断当前工序的状态是否为打包类型,如果是,修改生产的状态为生产完成 if(processStepStatuses.getType().equals(ProcessProcessingTypeEnum.PACK.getNumber())){ - OrderDO orderDO = productionProcessMapper.selectById(processStepStatuses.getOrderId()); + OrderDO orderDO = ordersMapper.selectById(processStepStatuses.getOrderId()); orderDO.setStatus(OrderStatusEnum.FINISH_PRODUCTION.getStatus()); orderDO.setFinishTime(LocalDateTime.now()); - productionProcessMapper.updateById(orderDO); + ordersMapper.updateById(orderDO); return; } // 当前工序已全部加工,修改生产单的状态为生产完成 if(validateOrderStatus(processStepStatuses.getOrderId())){ - OrderDO orderDO = productionProcessMapper.selectById(processStepStatuses.getOrderId()); + OrderDO orderDO = ordersMapper.selectById(processStepStatuses.getOrderId()); orderDO.setStatus(OrderStatusEnum.FINISH_PRODUCTION.getStatus()); orderDO.setFinishTime(LocalDateTime.now()); - productionProcessMapper.updateById(orderDO); + ordersMapper.updateById(orderDO); } }catch (Exception e){ diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/query/ProductionStatusServiceImpl.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/query/ProductionStatusServiceImpl.java index 527c3ba4b..7321c0b21 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/query/ProductionStatusServiceImpl.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/query/ProductionStatusServiceImpl.java @@ -7,12 +7,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO; import com.cf.imes.framework.common.enums.OrderPackageTypeEnum; import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.module.manage.controller.admin.pack.vo.GroupNameList; -import com.cf.imes.module.manage.controller.admin.pack.vo.OrderPartsReqVO; import com.cf.imes.module.manage.controller.admin.pack.vo.PackDetailsReqVO; -import com.cf.imes.module.manage.controller.admin.pack.vo.PlateDetailsRespVO; -import com.cf.imes.module.manage.controller.admin.process.vo.ProcessRespVO; import com.cf.imes.module.manage.controller.admin.query.vo.pack.OrderPackageVO; import com.cf.imes.module.manage.controller.admin.query.vo.pack.PackageDetailsRespVO; import com.cf.imes.module.manage.controller.admin.query.vo.pack.PrintOrderRespVO; @@ -21,11 +17,12 @@ import com.cf.imes.module.manage.controller.admin.query.vo.salary.PriceRatePageR import com.cf.imes.module.manage.controller.admin.query.vo.salary.PriceRateReqVO; import com.cf.imes.module.manage.dal.dataobject.process.OrderDO; import com.cf.imes.module.manage.dal.dataobject.process.OrderProcessStepNDO; -import com.cf.imes.module.manage.dal.dataobject.query.OrderPackageDO; import com.cf.imes.module.manage.dal.mysql.pack.OrderPackageMapper; +import com.cf.imes.module.manage.dal.mysql.process.OrdersMapper; import com.cf.imes.module.manage.dal.mysql.process.ProcessStepItemMapper; import com.cf.imes.module.manage.dal.mysql.process.ProcessStepMapper; -import com.cf.imes.module.manage.dal.mysql.query.*; +import com.cf.imes.module.manage.dal.mysql.query.OrderItemMapper; +import com.cf.imes.module.manage.dal.mysql.query.OrderPartsMapper; import com.cf.imes.module.manage.util.page.PageHelperUtil; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; @@ -43,8 +40,7 @@ import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.ge @Validated public class ProductionStatusServiceImpl implements ProductionStatusService { - @Resource - private ProductionStatusMapper productionStatusMapper; + @Resource private ProcessStepMapper processStepMapper; @@ -56,6 +52,8 @@ public class ProductionStatusServiceImpl implements ProductionStatusService { @Resource private OrderPackageMapper orderPackageMapper; + @Resource + private OrdersMapper ordersMapper; @Resource private OrderItemMapper orderItemMapper; @@ -69,7 +67,7 @@ public class ProductionStatusServiceImpl implements ProductionStatusService { @Override public PageResult getProductionPage(OrderPlatePageReqVO pageReqVO) { - return productionStatusMapper.selectProductionPage(pageReqVO); + return ordersMapper.selectProductionPage(pageReqVO); } @@ -156,7 +154,7 @@ public class ProductionStatusServiceImpl implements ProductionStatusService { @Override public PageResult queryPackage(OrderPlatePageReqVO pageReqVO) { - return productionStatusMapper.selectProductionPage(pageReqVO); + return ordersMapper.selectProductionPage(pageReqVO); } @@ -235,7 +233,9 @@ public class ProductionStatusServiceImpl implements ProductionStatusService { @Override public PrintOrderRespVO printOrder(Long orderNo) { - return productionStatusMapper.selectPrintOrder(orderNo,getUserOrganId()); +// return productionStatusMapper.selectPrintOrder(orderNo,getUserOrganId()); + + return null; } diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.xml b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.xml index 1cfb322df..4900ec70a 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.xml +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.xml @@ -15,42 +15,69 @@ resultMap="PackMap"> - select - op.order_id as id, - count(distinct op.id) as packCount - from order_package op - join order_item oi on op.id = oi.package_id and op.organ_id = oi.organ_id + select + order_id as id, + count(id) as packCount + + from order_package + where - oi.package_id != 0 - and op.organ_id = #{organId} - and op.order_id in + organ_id = #{organId} + + and status !=0 + + and deleted = false + + and order_id in #{id} - group by op.order_id; + + group by order_id + + + + + + + + + + + + + + + + resultType="com.cf.imes.module.manage.controller.admin.query.vo.pack.OrderPackageVO"> select distinct - opn.id, - opn.order_id, - opn.package_no, - opn.type, - opn.status, - opn.organ_id, - opn.creator, - opn.remark as packRemark, - opn.updater, - opn.update_time, - opn.create_time, + op.id, + op.order_id, + op.package_no, + op.type, + op.status, + op.organ_id, + op.creator, + op.remark as packRemark, + op.updater, + op.update_time, + op.create_time, o.custom_order_no, o.dealer, o.customer, o.address, o.remark as orderRemark - from order_package opn - join orders o on opn.order_id = o.id and opn.organ_id = o.organ_id - join order_item oi on opn.id = oi.package_id and opn.organ_id = oi.organ_id - left join order_plate op on oi.plate_id = op.id and oi.organ_id = op.organ_id - - - - and opn.order_id = #{reqVO.orderId} - - - - and op.plate_no like concat('%', #{reqVO.plateNo},'%') - - - - and opn.status= #{reqVO.packStatus} - - - - and opn.package_no like concat('%', #{reqVO.packageNo},'%') - - - and opn.organ_id = #{organId} - + from orders o + left join order_package op on o.id = op.order_id and o.organ_id = op.organ_id + ${ew.customSqlSegment} + + + + \ No newline at end of file diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/query/ProductionStatusMapper.xml b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/process/OrdersMapper.xml similarity index 61% rename from cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/query/ProductionStatusMapper.xml rename to cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/process/OrdersMapper.xml index b1744f594..fafb23ab3 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/query/ProductionStatusMapper.xml +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/process/OrdersMapper.xml @@ -1,40 +1,64 @@ - + - - - - - - - - - - - select - o.id as orderNo , - o.custom_order_no as customOrderNo, - o.dealer as dealer, - o.address as address, - o.customer as customer, - o.phone_number as customerPhone, - count(opn.order_id) as packageQuantity - from `orders` o - join order_package opn on o.id = opn.order_id and o.organ_id = opn.organ_id + SELECT + id as orderNo, + custom_order_no as customOrderNo, + dealer as dealer, + dealer_phone_number as dealerPhoneNumber, + order_date as orderDate, + create_time as createTime, + delivery_date as deliveryDate, + customer as customer, + phone_number as phoneNumber, + address as address, + salesman as salesman, + splitter as splitter, + packaged as packaged + FROM orders + WHERE organ_id = #{organId} and deleted = false and status != 0 and create_time >= #{createTime} and id != #{orderId} + ORDER BY create_time + LIMIT 1 ; - where o.id = #{orderNo} and opn.status <> 0 and o.organ_id = #{organId} ; + + + + + @@ -82,11 +106,11 @@ join order_item oi on o.id = oi.order_id and o.organ_id = oi.organ_id WHERE - o.organ_id = #{organId} and - o.id in - - #{id} - + o.organ_id = #{organId} and + o.id in + + #{id} + group by orderNo,customOrderNo,dealer,deliveryDate,customer,phoneNumber,address,salesman,splitter,packaged,dealerPhoneNumber,orderDate,o.create_time @@ -110,14 +134,14 @@ resultMap="PrintMap"> select o.custom_order_no as customOrderNo, - o.dealer as dealer, - opn.id as packNo , - o.id as orderNo, - o.address as address, - ((SELECT COUNT(t2.id) FROM order_package t2 WHERE t2.create_time <= opn.create_time and t2.order_id =#{orderNo})) as packNum + o.dealer as dealer, + opn.id as packNo , + o.id as orderNo, + o.address as address, + ((SELECT COUNT(t2.id) FROM order_package t2 WHERE t2.create_time <= opn.create_time and t2.order_id =#{orderNo})) as packNum from `orders` o - join order_package opn on o.id = opn.order_id and o.organ_id = opn.organ_id + join order_package opn on o.id = opn.order_id and o.organ_id = opn.organ_id where opn.order_id =#{orderNo} and opn.id = #{packageNo} and opn.status <> 0 and opn.organ_id = #{organId} order by opn.create_time ; @@ -125,10 +149,25 @@ - - select * from orders + select + id as orderNo, + custom_order_no as customOrderNo, + dealer as dealer, + dealer_phone_number as dealerPhoneNumber, + order_date as orderDate, + create_time as createTime, + delivery_date as deliveryDate, + customer as customer, + phone_number as phoneNumber, + address as address, + salesman as salesman, + splitter as splitter, + packaged as packaged + + from orders organ_id =#{organId} @@ -165,7 +204,9 @@ - + + + + + \ No newline at end of file diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/process/ProductionProcessMapper.xml b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/process/ProductionProcessMapper.xml deleted file mode 100644 index 7f4762d3b..000000000 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/process/ProductionProcessMapper.xml +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/query/OrderItemMapper.xml b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/query/OrderItemMapper.xml index 92089cd21..249e46284 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/query/OrderItemMapper.xml +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/query/OrderItemMapper.xml @@ -468,4 +468,27 @@ + + + + \ No newline at end of file diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/query/OrderPartsMapper.xml b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/query/OrderPartsMapper.xml index cf44f34c3..5971391e1 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/query/OrderPartsMapper.xml +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/query/OrderPartsMapper.xml @@ -76,7 +76,7 @@ from order_parts op join order_item oi on op.id = oi.parts_id and op.organ_id = oi.organ_id - where op.organ_id = #{organId} and op.order_id = #{orderId} and oi.package_id = 0 + where op.organ_id = #{organId} and op.order_id = #{orderId} diff --git a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java index db4a7d81c..deef36ac7 100644 --- a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java +++ b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java @@ -12,11 +12,11 @@ public final class ErrorCodeConstants { // ========== UREPORT template模块 1-003-001-000 ========== public static final ErrorCode TEMPLATE_NOT_EXISTS = new ErrorCode(1_003_001_001, "报表模板信息不存在"); + public static final ErrorCode DATATEMPLATE_BUILDIN_OPERATION_PERMISSION_ERROR = new ErrorCode(1_003_001_002, "内置模板操作权限不足"); // ========== UREPORT datasource模块 1-003-002-000 ========== public static final ErrorCode DATASOURCE_NOT_EXISTS = new ErrorCode(1_003_002_001, "报表数据源不存在"); public static final ErrorCode DATASOURCE_CONNECT_FAIL = new ErrorCode(1_003_002_002, "报表数据源连接失败"); - public static final ErrorCode DATASOURCE_BUILDIN_OPERATION_PERMISSION_ERROR = new ErrorCode(1_003_002_003, "内置报表数据源只能由超级管理员操作"); // ========== UREPORT dataset模块 1-003-003-000 ========== diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/ReportDatasetController.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/ReportDatasetController.java index 2a971c838..d0e31458e 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/ReportDatasetController.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/ReportDatasetController.java @@ -37,14 +37,14 @@ public class ReportDatasetController { @PutMapping("/dataset") @Operation(summary = "创建报表数据集") - @PreAuthorize("@ss.hasPermission('report:dataset:create')") +// @PreAuthorize("@ss.hasPermission('report:dataset:create')") public CommonResult createDataset(@Valid @RequestBody ReportDatasetSaveReqVO createReqVO) { return success(datasetService.createDataset(createReqVO)); } @PostMapping("/dataset") @Operation(summary = "更新报表数据集") - @PreAuthorize("@ss.hasPermission('report:dataset:update')") +// @PreAuthorize("@ss.hasPermission('report:dataset:update')") public CommonResult updateDataset(@Valid @RequestBody ReportDatasetSaveReqVO updateReqVO) { datasetService.updateDataset(updateReqVO); return success(true); @@ -53,7 +53,7 @@ public class ReportDatasetController { @DeleteMapping("/dataset/{id}") @Operation(summary = "删除报表数据集") @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('report:dataset:delete')") +// @PreAuthorize("@ss.hasPermission('report:dataset:delete')") public CommonResult deleteDataset(@PathVariable("id") Long id) { datasetService.deleteDataset(id); return success(true); @@ -62,7 +62,7 @@ public class ReportDatasetController { @GetMapping("/dataset/{id}") @Operation(summary = "获得报表数据集") @Parameter(name = "id", description = "编号", required = true, example = "1") - @PreAuthorize("@ss.hasPermission('report:dataset:query')") +// @PreAuthorize("@ss.hasPermission('report:dataset:query')") public CommonResult getDataset(@PathVariable("id") Long id) { ReportDatasetDO dataset = datasetService.getDataset(id); return success(BeanUtils.toBean(dataset, ReportDatasetRespVO.class)); @@ -70,7 +70,7 @@ public class ReportDatasetController { @GetMapping("/datasets") @Operation(summary = "获取数据源下的报表数据集列表") - @PreAuthorize("@ss.hasPermission('report:dataset:query')") +// @PreAuthorize("@ss.hasPermission('report:dataset:query')") public CommonResult> getDatasetPage(@RequestParam(value = "datasourceId") Long datasourceId, @RequestParam(value = "name", required = false) String name) { ReportDatasetReqVO reqVO = new ReportDatasetReqVO(name, datasourceId); diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/ReportDatasourceController.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/ReportDatasourceController.java index 136d982ae..c9f73d2da 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/ReportDatasourceController.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/ReportDatasourceController.java @@ -1,13 +1,17 @@ package com.cf.imes.module.report.controller.admin.datasource; +import com.bstek.common.config.DataSourceConfig; +import com.bstek.common.utils.MultipleJdbcTemplate; +import com.bstek.datasource.bean.DataSourceInfo; +import com.bstek.datasource.bean.PreviewParams; +import com.bstek.datasource.service.DataSourceService; +import com.bstek.ureport.definition.dataset.Field; import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.util.object.BeanUtils; -import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetFieldVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportBeanDatasourceRespVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceReqVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceRespVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceSaveReqVO; -import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceTestConnReqVO; import com.cf.imes.module.report.dal.dataobject.datasource.ReportDatasourceDO; import com.cf.imes.module.report.service.datasource.ReportDatasourceService; import io.swagger.v3.oas.annotations.Operation; @@ -22,6 +26,7 @@ import javax.validation.Valid; import java.util.List; import java.util.Map; +import java.util.Objects; import static com.cf.imes.framework.common.pojo.CommonResult.error; import static com.cf.imes.framework.common.pojo.CommonResult.success; @@ -41,16 +46,22 @@ public class ReportDatasourceController { @Resource private ReportDatasourceService datasourceService; + @Resource + private DataSourceConfig dataSourceConfig; + + @Resource + private DataSourceService ureportDataSourceService; + @PutMapping("/datasource") @Operation(summary = "创建报表数据源") - @PreAuthorize("@ss.hasPermission('report:datasource:create')") +// @PreAuthorize("@ss.hasPermission('report:datasource:create')") public CommonResult createDatasource(@Valid @RequestBody ReportDatasourceSaveReqVO createReqVO) { return success(datasourceService.createDatasource(createReqVO)); } @PostMapping("/datasource") @Operation(summary = "更新报表数据源") - @PreAuthorize("@ss.hasPermission('report:datasource:update')") +// @PreAuthorize("@ss.hasPermission('report:datasource:update')") public CommonResult updateDatasource(@Valid @RequestBody ReportDatasourceSaveReqVO updateReqVO) { datasourceService.updateDatasource(updateReqVO); return success(true); @@ -59,7 +70,7 @@ public class ReportDatasourceController { @DeleteMapping("/datasource/{id}") @Operation(summary = "删除报表数据源") @Parameter(name = "id", description = "编号", required = true, example = "1") - @PreAuthorize("@ss.hasPermission('report:datasource:delete')") +// @PreAuthorize("@ss.hasPermission('report:datasource:delete')") public CommonResult deleteDatasource(@PathVariable("id") Long id) { datasourceService.deleteDatasource(id); return success(true); @@ -68,7 +79,7 @@ public class ReportDatasourceController { @GetMapping("/datasource/{id}") @Operation(summary = "获取报表数据源") @Parameter(name = "id", description = "编号", required = true, example = "1") - @PreAuthorize("@ss.hasPermission('report:datasource:query')") +// @PreAuthorize("@ss.hasPermission('report:datasource:query')") public CommonResult getDatasource(@PathVariable("id") Long id) { ReportDatasourceDO datasource = datasourceService.getDatasource(id); return success(BeanUtils.toBean(datasource, ReportDatasourceRespVO.class)); @@ -76,51 +87,57 @@ public class ReportDatasourceController { @GetMapping("/{templateId}/datasources") @Operation(summary = "获取报表模板下的报表数据源") - @PreAuthorize("@ss.hasPermission('report:datasource:query')") +// @PreAuthorize("@ss.hasPermission('report:datasource:query')") public CommonResult> getDatasourcePage(@PathVariable(value = "templateId") Long templateId) { return success(BeanUtils.toBean(datasourceService.getTemplateDatasourceList(ReportDatasourceReqVO.builder().templateId(templateId).build()), ReportDatasourceRespVO.class)); } @GetMapping("/datasource/beans") @Operation(summary = "获取springbean数据源列表") - @PreAuthorize("@ss.hasPermission('report:datasource:query')") +// @PreAuthorize("@ss.hasPermission('report:datasource:query')") public CommonResult> getBeanDatasourceList() { return success(datasourceService.getBeanDatasourceList()); } @GetMapping("/datasource/bean/methods") @Operation(summary = "获取springbean数据源方法类表") - @PreAuthorize("@ss.hasPermission('report:datasource:query')") +// @PreAuthorize("@ss.hasPermission('report:datasource:query')") public CommonResult> getBeanDatasourceList(@RequestParam(value = "beanId") String beanId) { return success(datasourceService.loadBeanMethods(beanId)); } @GetMapping("/buildin/datasources") @Operation(summary = "获取内置数据源") - @PreAuthorize("@ss.hasPermission('report:datasource:query')") - public CommonResult> getBuildinDatasources() { - return success(BeanUtils.toBean(datasourceService.getBuildinDatasources(), ReportDatasourceRespVO.class)); +// @PreAuthorize("@ss.hasPermission('report:datasource:query')") + public CommonResult> getBuildinDatasources() { + return CommonResult.success(dataSourceConfig.getDatasource()); } @PostMapping("/datasource/connect") @Operation(summary = "测试数据源连接") - @PreAuthorize("@ss.hasPermission('report:datasource:query')") - public CommonResult testDatasourceConnect(@RequestBody ReportDatasourceTestConnReqVO reqVO) { - boolean connResult = datasourceService.testConnect(reqVO); - return connResult ? success(true) : error(DATASOURCE_CONNECT_FAIL); +// @PreAuthorize("@ss.hasPermission('report:datasource:query')") + public CommonResult testDatasourceConnect(@RequestBody DataSourceInfo info) { + String success = MultipleJdbcTemplate.testConnection(info); + return Objects.equals("success", success) ? success(true) : error(DATASOURCE_CONNECT_FAIL); } @PostMapping("/datasource/tables") @Operation(summary = "获取数据源表列表") - @PreAuthorize("@ss.hasPermission('report:datasource:query')") - public CommonResult>> getDatasourceTables(@RequestBody ReportDatasourceTestConnReqVO reqVO) { - return success(datasourceService.getDatasourceTables(reqVO)); +// @PreAuthorize("@ss.hasPermission('report:datasource:query')") + public CommonResult>> getDatasourceTables(@RequestBody DataSourceInfo info) { + return success(ureportDataSourceService.selectTableList(info)); } @PostMapping("/datasource/table/fields") @Operation(summary = "获取数据源表字段") - @PreAuthorize("@ss.hasPermission('report:datasource:query')") - public CommonResult> getDatasourceTableFields(@RequestBody ReportDatasourceTestConnReqVO reqVO) { - return success(datasourceService.getTableFields(reqVO)); +// @PreAuthorize("@ss.hasPermission('report:datasource:query')") + public CommonResult> getDatasourceTableFields(@RequestBody PreviewParams previewParams) { + return success(datasourceService.getTableFields(previewParams)); + } + + @PostMapping("/datasource/preview") + @Operation(summary = "数据源预览") + public CommonResult> previewData(@RequestBody PreviewParams previewParams) { + return success(ureportDataSourceService.previewData(previewParams)); } } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceRespVO.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceRespVO.java index 2505c0bd2..28cb451e4 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceRespVO.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceRespVO.java @@ -1,13 +1,13 @@ package com.cf.imes.module.report.controller.admin.datasource.vo; import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetRespVO; -import com.cf.imes.module.report.enums.datasource.ReportDatasourceTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; +import java.util.Map; /** * @author Gqr @@ -28,10 +28,7 @@ public class ReportDatasourceRespVO { @Schema(description = "数据源名称", example = "测试库") private String name; - @Schema(description = "数据源类型,jdbc、spring", example = "jdbc") - private ReportDatasourceTypeEnum dsType; - - @Schema(description = "模板类型,0内置、1自定义", example = "0") + @Schema(description = "数据源类型,jdbc、spring、buildin、api", example = "0") private Integer type; @Schema(description = "数据源驱动类",example = "com.mysql.cj.jdbc.Driver") @@ -51,4 +48,7 @@ public class ReportDatasourceRespVO { @Schema(description = "数据集") private List datasets; + + @Schema(description = "请求头参数") + private List> headers; } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java index 896aceb1d..acf0d0700 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java @@ -2,7 +2,6 @@ package com.cf.imes.module.report.controller.admin.datasource.vo; import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetSaveReqVO; import com.cf.imes.module.report.validation.datasource.ReportDatasourceTypeInEnum; -import com.cf.imes.module.report.validation.template.ReportTemplateTypeInEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; @@ -13,6 +12,7 @@ import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * @author Gqr @@ -36,13 +36,9 @@ public class ReportDatasourceSaveReqVO implements Serializable { @Schema(description = "数据源名称", example = "测试库") private String name; - @Schema(description = "模板类型,0内置、1自定义", example = "1") - @ReportTemplateTypeInEnum - private Integer type; - - @Schema(description = "数据源类型,jdbc、spring", example = "jdbc") + @Schema(description = "数据源类型,jdbc、spring、buildin、api", example = "1") @ReportDatasourceTypeInEnum - private String dsType; + private String type; @Schema(description = "spring型数据源id") private String beanId; @@ -64,4 +60,7 @@ public class ReportDatasourceSaveReqVO implements Serializable { @Schema(description = "数据集") private List datasets = new ArrayList<>(); + + @Schema(description = "请求头参数") + private List> headers; } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java index 9a2c5023c..0d9bee876 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java @@ -1,14 +1,22 @@ package com.cf.imes.module.report.controller.admin.template; +import com.bstek.designer.bean.PreviewParameters; import com.bstek.designer.bean.ReportDefinitionWrapper; +import com.bstek.designer.excel.ExcelParserUtils; +import com.bstek.ureport.definition.ReportDefinition; +import com.bstek.ureport.dsl.ReportParserLexer; +import com.bstek.ureport.dsl.ReportParserParser; import com.bstek.ureport.export.ExportUtils; import com.bstek.ureport.export.ProducerEnum; import com.bstek.ureport.export.html.HtmlReport; +import com.bstek.ureport.expression.ErrorInfo; +import com.bstek.ureport.expression.ScriptErrorListener; import com.bstek.ureport.model.Report; +import com.bstek.ureport.utils.StringUtils; +import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; -import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplatePreviewPageParametersVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateRespVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateSaveReqVO; @@ -17,17 +25,25 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.TerminalNode; import org.apache.commons.io.IOUtils; +import org.apache.http.HttpStatus; +import org.apache.ibatis.annotations.Param; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.OutputStream; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static com.cf.imes.framework.common.pojo.CommonResult.success; @@ -48,14 +64,14 @@ public class ReportTemplateController { @PutMapping("/template") @Operation(summary = "创建报表模板信息") - @PreAuthorize("@ss.hasPermission('report:template:create')") +// @PreAuthorize("@ss.hasPermission('report:template:create')") public CommonResult createTemplate(@Valid @RequestBody ReportTemplateSaveReqVO createReqVO) { return success(templateService.createReportTemplate(createReqVO)); } @PostMapping("/template") @Operation(summary = "更新报表模板信息") - @PreAuthorize("@ss.hasPermission('report:template:update')") +// @PreAuthorize("@ss.hasPermission('report:template:update')") public CommonResult updateTemplate(@Valid @RequestBody ReportTemplateSaveReqVO updateReqVO) { templateService.updateReportTemplate(updateReqVO); return success(true); @@ -64,7 +80,7 @@ public class ReportTemplateController { @DeleteMapping("/template/{id}") @Operation(summary = "删除报表模板信息") @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('report:template:delete')") +// @PreAuthorize("@ss.hasPermission('report:template:delete')") public CommonResult deleteReportTemplate(@PathVariable("id") Long id) { templateService.deleteReportTemplate(id); return success(true); @@ -73,14 +89,14 @@ public class ReportTemplateController { @GetMapping("/template/{id}") @Operation(summary = "获取报表模板信息") @Parameter(name = "id", description = "编号", required = true, example = "1") - @PreAuthorize("@ss.hasPermission('report:template:query')") +// @PreAuthorize("@ss.hasPermission('report:template:query')") public CommonResult getReportTemplate(@PathVariable("id") Long id) { return success(templateService.getReportTemplateDefinition(id)); } @GetMapping("/templates") @Operation(summary = "获取报表模板信息列表") - @PreAuthorize("@ss.hasPermission('report:template:query')") +// @PreAuthorize("@ss.hasPermission('report:template:query')") public CommonResult> getTemplatePage(@RequestParam(value = "name", required = false) String name) { ReportTemplateReqVO reqVO = new ReportTemplateReqVO(name, null); return success(BeanUtils.toBean(templateService.getReportTemplateList(reqVO), ReportTemplateRespVO.class)); @@ -88,14 +104,14 @@ public class ReportTemplateController { @PostMapping("/template/preview") @Operation(summary = "模板预览") - @PreAuthorize("@ss.hasPermission('report:template:query')") - public CommonResult preview(@Valid @RequestBody ReportTemplatePreviewPageParametersVO pageParametersVO) { - return success(templateService.preview(pageParametersVO)); +// @PreAuthorize("@ss.hasPermission('report:template:query')") + public CommonResult preview(@RequestBody PreviewParameters params) { + return success(templateService.preview(params)); } @PostMapping("/template/export") @Operation(summary = "模板导出") - @PreAuthorize("@ss.hasPermission('report:template:query')") +// @PreAuthorize("@ss.hasPermission('report:template:query')") public void generateTemplate(@Valid @RequestBody ReportTemplateGenerateReqDTO reqDTO, HttpServletResponse response) { OutputStream out = null; try { @@ -109,4 +125,60 @@ public class ReportTemplateController { IOUtils.closeQuietly(out); } } + + @GetMapping("/template/excel/import") + @Operation(summary = "导入excel模板") +// @PreAuthorize("@ss.hasPermission('report:template:import')") + public ReportDefinitionWrapper importExcel(@RequestParam("file") MultipartFile file) { + ReportDefinition report = ExcelParserUtils.parser(file); + if (report != null) { + report.setReportFullName(""); + return new ReportDefinitionWrapper(report); + } + throw new ServiceException(HttpStatus.SC_INTERNAL_SERVER_ERROR, "文件未识别"); + } + + @GetMapping("/scriptValidation") + @Operation(summary = "校验表达式") + @Parameter(name = "content", description = "表达式", required = true) + public List scriptValidation(@Param("content") String content) { + content = StringUtils.decode(content); + ANTLRInputStream antlrInputStream = new ANTLRInputStream(content); + ReportParserLexer lexer = new ReportParserLexer(antlrInputStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + ReportParserParser parser = new ReportParserParser(tokenStream); + ScriptErrorListener errorListener = new ScriptErrorListener(); + parser.removeErrorListeners(); + parser.addErrorListener(errorListener); + parser.expression(); + return errorListener.getInfos(); + } + + /** + * 解析表达式中的数据集 + * + * @param expr + * @return + */ + @GetMapping("/parseDataSet") + @Operation(summary = "解析表达式中的数据集") + @Parameter(name = "expr", description = "表达式", required = true) + public Map parseDatasetName(@Param("expr") String expr) { + ANTLRInputStream antlrInputStream = new ANTLRInputStream(expr); + ReportParserLexer lexer = new ReportParserLexer(antlrInputStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + ReportParserParser parser = new ReportParserParser(tokenStream); + parser.removeErrorListeners(); + + Map result = new HashMap<>(); + ReportParserParser.DatasetContext ctx = parser.dataset(); + if (ctx != null) { + TerminalNode node = ctx.Identifier(); + if (node != null) { + String datasetName = ctx.Identifier().getText(); + result.put("datasetName", datasetName); + } + } + return result; + } } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/vo/ReportTemplateSaveReqVO.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/vo/ReportTemplateSaveReqVO.java index 6dcf2360a..963a4ff30 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/vo/ReportTemplateSaveReqVO.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/vo/ReportTemplateSaveReqVO.java @@ -1,7 +1,6 @@ package com.cf.imes.module.report.controller.admin.template.vo; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceSaveReqVO; -import com.cf.imes.module.report.validation.template.ReportTemplateTypeInEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; @@ -34,10 +33,6 @@ public class ReportTemplateSaveReqVO { @Schema(description = "数据源") private List datasource = new ArrayList<>(); - @Schema(description = "模板类型,0内置、1自定义", example = "1") - @ReportTemplateTypeInEnum - private Integer type; - @Schema(description = "备注", example = "该模板仅供生产使用") private String remark; } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/dal/dataobject/datasource/ReportDatasourceDO.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/dal/dataobject/datasource/ReportDatasourceDO.java index 7e56e6a99..0f761a61b 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/dal/dataobject/datasource/ReportDatasourceDO.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/dal/dataobject/datasource/ReportDatasourceDO.java @@ -5,12 +5,18 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; +import com.cf.imes.framework.mybatis.core.type.CompressObjectListTypeHandler; import com.cf.imes.module.report.dal.dataobject.dataset.ReportDatasetDO; import com.cf.imes.module.report.enums.datasource.ReportDatasourceTypeEnum; -import com.cf.imes.module.report.enums.template.ReportTemplateTypeEnum; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; import java.util.List; +import java.util.Map; /** * 报表数据源DO @@ -18,7 +24,7 @@ import java.util.List; * @author Gqr * @since 2024/7/8 11:01 */ -@TableName("report_datasource") +@TableName(value = "report_datasource", autoResultMap = true) @KeySequence("report_datasource_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @@ -40,15 +46,11 @@ public class ReportDatasourceDO extends BaseDO { * 数据源名称 */ private String name; - /** - * 模板类型,jdbc、spring - */ - private ReportDatasourceTypeEnum dsType; /** * 模板类型,0内置、1自定义 */ - private ReportTemplateTypeEnum type; + private ReportDatasourceTypeEnum type; /** * spring型数据源id @@ -84,4 +86,7 @@ public class ReportDatasourceDO extends BaseDO { */ @TableField(exist = false) private List datasets; + + @TableField(typeHandler = CompressObjectListTypeHandler.class) + private List> headers; } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/enums/datasource/ReportDatasourceTypeEnum.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/enums/datasource/ReportDatasourceTypeEnum.java index 2e2a03057..0f9d30cb5 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/enums/datasource/ReportDatasourceTypeEnum.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/enums/datasource/ReportDatasourceTypeEnum.java @@ -13,8 +13,10 @@ import lombok.Getter; @Getter @AllArgsConstructor public enum ReportDatasourceTypeEnum { - JDBC(0,"jdbc"), - SPRING(1,"spring"); + JDBC(0, "jdbc"), + SPRING(1, "spring"), + BUILDIN(2, "buildin"), + API(3, "api"); @EnumValue private final Integer code; diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/ReportConfig.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/ReportConfig.java index e5f7b56dc..738e6ea8e 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/ReportConfig.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/ReportConfig.java @@ -1,5 +1,8 @@ package com.cf.imes.module.report.framework.ureport.config; +import com.bstek.datasource.service.DataSourceService; +import com.bstek.datasource.service.impl.DataSourceServiceImpl; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -10,4 +13,9 @@ import org.springframework.context.annotation.Import; @Configuration @Import(CfReportSpringbeanRegistrar.class) public class ReportConfig { + + @Bean + public DataSourceService getUreportDataSourceService() { + return new DataSourceServiceImpl(); + } } \ No newline at end of file diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceService.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceService.java index c2d36a457..a87036e9b 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceService.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceService.java @@ -1,15 +1,14 @@ package com.cf.imes.module.report.service.datasource; -import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetFieldVO; +import com.bstek.datasource.bean.PreviewParams; +import com.bstek.ureport.definition.dataset.Field; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportBeanDatasourceRespVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceReqVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceSaveReqVO; -import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceTestConnReqVO; import com.cf.imes.module.report.dal.dataobject.datasource.ReportDatasourceDO; import javax.validation.Valid; import java.util.List; -import java.util.Map; /** * 报表数据源 Service 接口 @@ -63,12 +62,6 @@ public interface ReportDatasourceService { */ List getBeanDatasourceList(); - /** - * 获取内置数据源列表 - * @return - */ - List getBuildinDatasources(); - /** * 获取bean方法 * @@ -77,27 +70,13 @@ public interface ReportDatasourceService { */ List loadBeanMethods(String beanId); - /** - * 测试数据源连接 - * - * @param reqVO 连接信息请求 - * @return - */ - boolean testConnect(ReportDatasourceTestConnReqVO reqVO); - - /** - * 获取数据源表列表 - * - * @param reqVO 连接信息请求 - * @return - */ - List> getDatasourceTables(ReportDatasourceTestConnReqVO reqVO); - /** * 获取数据源表字段 * - * @param reqVO 连接信息请求 + * @param previewParams 连接信息请求 * @return */ - List getTableFields(ReportDatasourceTestConnReqVO reqVO); + List getTableFields(PreviewParams previewParams); + + } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java index fcd29b866..41c87841c 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java @@ -4,6 +4,9 @@ import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils; +import com.bstek.common.utils.MultipleJdbcTemplate; +import com.bstek.datasource.bean.DataSourceInfo; +import com.bstek.datasource.bean.PreviewParams; import com.bstek.ureport.definition.dataset.Field; import com.bstek.ureport.definition.dataset.Parameter; import com.bstek.ureport.definition.dataset.SqlDatasetDefinition; @@ -11,21 +14,14 @@ import com.bstek.ureport.utils.ProcedureUtils; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.cf.imes.framework.organ.core.aop.OrganIgnore; -import com.cf.imes.framework.security.core.LoginUser; -import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; -import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetFieldVO; -import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetParameterVO; import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetReqVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportBeanDatasourceRespVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceReqVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceSaveReqVO; -import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceTestConnReqVO; import com.cf.imes.module.report.dal.dataobject.dataset.ReportDatasetDO; import com.cf.imes.module.report.dal.dataobject.datasource.ReportDatasourceDO; import com.cf.imes.module.report.dal.mysql.dataset.ReportDatasetMapper; import com.cf.imes.module.report.dal.mysql.datasource.ReportDatasourceMapper; -import com.cf.imes.module.report.enums.template.ReportTemplateTypeEnum; import com.cf.imes.module.report.framework.ureport.annotation.CfReportSpringbeanDatasource; import com.cf.imes.module.report.service.dataset.ReportDatasetService; import com.cf.imes.module.report.util.SqlInjectionUtil; @@ -43,11 +39,7 @@ import javax.annotation.Resource; import javax.sql.DataSource; import java.lang.reflect.Method; import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.DriverManager; -import java.sql.ResultSet; import java.sql.ResultSetMetaData; -import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -58,7 +50,6 @@ import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASET_GET_FIE import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASET_SQL_ILLEGAL; import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASET_SQL_INJECTION_RISK; import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASET_SQL_REQUIRED; -import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASOURCE_BUILDIN_OPERATION_PERMISSION_ERROR; import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASOURCE_NOT_EXISTS; /** @@ -89,12 +80,8 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { @Override public Long createDatasource(ReportDatasourceSaveReqVO createReqVO) { ReportDatasourceDO datasource = BeanUtils.toBean(createReqVO, ReportDatasourceDO.class); - // 校验内置数据源操作权限 - validateBuildinsource(datasource); // 插入 datasourceMapper.insert(datasource); - // 解析数据集 - analyzeDataset(datasource); // 返回 return datasource.getId(); } @@ -104,54 +91,10 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { // 校验存在 validateDatasourceExists(updateReqVO.getId()); ReportDatasourceDO updateObj = BeanUtils.toBean(updateReqVO, ReportDatasourceDO.class); - // 校验内置数据源操作权限 - validateBuildinsource(updateObj); // 更新 datasourceMapper.updateById(updateObj); - // 解析数据集 - analyzeDataset(updateObj); } - /** - * 校验只有超管可以操作内置数据源 - */ - private void validateBuildinsource(ReportDatasourceDO datasource) { - LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); - boolean isSuperAdmin = loginUser != null && loginUser.getIsSupAdmin(); - // 非超管不能操作内置数据源 - if (ReportTemplateTypeEnum.SYSTEM.equals(datasource.getType()) && !isSuperAdmin) { - throw exception(DATASOURCE_BUILDIN_OPERATION_PERMISSION_ERROR); - } - } - - /** - * 解析数据源下的数据集 - * - * @param datasource - */ - private void analyzeDataset(ReportDatasourceDO datasource) { - List datasets = datasource.getDatasets(); - List batchInsertDataset = new ArrayList<>(); - List batchupdateDataset = new ArrayList<>(); - datasets.forEach(dataset -> { - // 更新/新增数据集 - if (ObjectUtil.isNotNull(dataset.getId())) { - batchupdateDataset.add(dataset); - } else { - dataset.setDatasourceId(datasource.getId()); - batchInsertDataset.add(dataset); - } - }); - - // 批量插入数据集 - if (CollUtil.isNotEmpty(batchInsertDataset)) { - datasetMapper.insertBatch(batchInsertDataset); - } - // 批量更新数据集 - if (CollUtil.isNotEmpty(batchupdateDataset)) { - datasetMapper.updateBatch(batchupdateDataset); - } - } @Override public void deleteDatasource(Long id) { @@ -159,6 +102,8 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { validateDatasourceExists(id); // 删除 datasourceMapper.deleteById(id); + // 删除关联数据集 + datasetMapper.delete(new LambdaQueryWrapperX().eq(ReportDatasetDO::getDatasourceId, id)); } /** @@ -185,7 +130,6 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { List reportDatasourceDOS = datasourceMapper.selectList(new LambdaQueryWrapperX() .eqIfPresent(ReportDatasourceDO::getTemplateId, reqVO.getTemplateId()) .likeIfPresent(ReportDatasourceDO::getName, reqVO.getName()) - .eqIfPresent(ReportDatasourceDO::getDsType, reqVO.getType()) .orderByDesc(ReportDatasourceDO::getCreateTime)); // 查询数据集 if (CollUtil.isNotEmpty(reportDatasourceDOS)) { @@ -210,21 +154,6 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { return beanDatasourceRespVOList; } - @Override - @OrganIgnore - public List getBuildinDatasources() { - List reportDatasourceDOS = datasourceMapper.selectList(new LambdaQueryWrapperX() - .eqIfPresent(ReportDatasourceDO::getType, ReportTemplateTypeEnum.SYSTEM) - .orderByDesc(ReportDatasourceDO::getCreateTime)); - // 查询数据集 - if (CollUtil.isNotEmpty(reportDatasourceDOS)) { - reportDatasourceDOS.forEach(reportDatasourceDO -> { - queryDatasetInSource(reportDatasourceDO); - }); - } - return reportDatasourceDOS; - } - @Override public List loadBeanMethods(String beanId) { Object obj = applicationContext.getBean(beanId); @@ -255,71 +184,25 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { } @Override - public boolean testConnect(ReportDatasourceTestConnReqVO reqVO) { + public List getTableFields(PreviewParams previewParams) { Connection conn = null; + String sql = previewParams.getSql(); + List parameters = previewParams.getParameters(); + DataSourceInfo info = previewParams.getInfo(); try { - // 获取数据库连接 - conn = buildConn(reqVO); - } catch (Exception ex) { - log.error("[testConnect][报表数据源测试连接失败:{}]", ex.getMessage()); - return false; - } finally { - JdbcUtils.closeConnection(conn); - } - return true; - } - - @Override - public List> getDatasourceTables(ReportDatasourceTestConnReqVO reqVO) { - Connection conn = null; - ResultSet rs = null; - List> tables = new ArrayList>(); - try { - // 获取数据库连接 - conn = buildConn(reqVO); - DatabaseMetaData metaData = conn.getMetaData(); - String url = metaData.getURL(); - String schema = null; - if (url.toLowerCase().contains("oracle")) { - schema = metaData.getUserName(); - } - - rs = metaData.getTables(conn.getCatalog(), schema, null, new String[]{"TABLE", "VIEW"}); - // 轮询获取表信息 - while (rs.next()) { - Map table = new HashMap(); - table.put("name", rs.getString("TABLE_NAME")); - table.put("type", rs.getString("TABLE_TYPE")); - tables.add(table); - } - } catch (Exception ex) { - log.error("[testConnect][报表数据源库表失败:{}]", ex.getMessage()); - } finally { - JdbcUtils.closeResultSet(rs); - JdbcUtils.closeConnection(conn); - } - return tables; - } - - @Override - public List getTableFields(ReportDatasourceTestConnReqVO reqVO) { - Connection conn = null; - String sql = reqVO.getSql(); - List parameters = reqVO.getParameters(); - try { - if(StringUtils.isEmpty(sql)) { + if (StringUtils.isEmpty(sql)) { throw exception(DATASET_SQL_REQUIRED); } // 获取数据库连接 - conn = buildConn(reqVO); + conn = MultipleJdbcTemplate.buildConnection(info); // 自定义工具校验sql if (SqlInjectionUtil.checkEditSql(sql)) { throw exception(DATASET_SQL_ILLEGAL); } // 检查参数sql注入 - for (ReportDatasetParameterVO parameterVO : parameters) { + for (Parameter parameter : parameters) { // mybatis-plus util检查参数 - if (SqlInjectionUtils.check(parameterVO.getDefaultValue())) { + if (SqlInjectionUtils.check(parameter.getDefaultValue())) { throw exception(DATASET_SQL_INJECTION_RISK); } } @@ -332,19 +215,18 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { Map pmap = sqlDatasetDefinition.buildParameters(params); String sqlForUse = sqlDatasetDefinition.parseSql(pmap); if (ProcedureUtils.isProcedure(sqlForUse)) { - List fields = ProcedureUtils.procedureColumnsQuery(sqlForUse, pmap, conn); - return BeanUtils.toBean(fields, ReportDatasetFieldVO.class); + return ProcedureUtils.procedureColumnsQuery(sqlForUse, pmap, conn); } DataSource dataSource = new SingleConnectionDataSource(conn, false); NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(dataSource); - final List fields = new ArrayList<>(); + final List fields = new ArrayList<>(); jdbcTemplate.query(sqlForUse, pmap, (ResultSetExtractor) rs -> { ResultSetMetaData metadata = rs.getMetaData(); List metadataList = new ArrayList<>(); for (int i = 1; i <= metadata.getColumnCount(); i++) { String columnName = metadata.getColumnLabel(i); metadataList.add(columnName); - fields.add(new ReportDatasetFieldVO(columnName)); + fields.add(new Field(columnName)); } return null; }); @@ -359,31 +241,6 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { } } - /** - * 构建数据库连接 - * 有数据源id从库里查数据源信息 - * 没有数据源id用请求中的driver等连接 - * @param reqVO - * @return - * @throws ClassNotFoundException - * @throws SQLException - */ - private Connection buildConn(ReportDatasourceTestConnReqVO reqVO) throws ClassNotFoundException, SQLException { - Long datasourceId = reqVO.getDatasourceId(); - Connection conn = null; - if (ObjectUtil.isNotNull(datasourceId)) { - ReportDatasourceDO datasourceDO = datasourceMapper.selectById(datasourceId); - if (ObjectUtil.isNotNull(datasourceDO)) { - Class.forName(datasourceDO.getDriver()); - conn = DriverManager.getConnection(datasourceDO.getUrl(), datasourceDO.getUsername(), datasourceDO.getPassword()); - } - } else { - Class.forName(reqVO.getDriver()); - conn = DriverManager.getConnection(reqVO.getUrl(), reqVO.getUserName(), reqVO.getPassword()); - } - return conn; - } - /** * 查询数据源下的数据集 * diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java index f7b652091..387473383 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java @@ -1,10 +1,10 @@ package com.cf.imes.module.report.service.template; +import com.bstek.designer.bean.PreviewParameters; import com.bstek.designer.bean.ReportDefinitionWrapper; import com.bstek.ureport.export.html.HtmlReport; import com.bstek.ureport.model.Report; import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; -import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplatePreviewPageParametersVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateSaveReqVO; import com.cf.imes.module.report.dal.dataobject.template.ReportTemplateDO; @@ -68,10 +68,10 @@ public interface ReportTemplateService { /** * 模板预览 * - * @param pageParametersVO + * @param params * @return */ - HtmlReport preview(ReportTemplatePreviewPageParametersVO pageParametersVO); + HtmlReport preview(PreviewParameters params); /** diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java index 53b828905..35a2d6f30 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java @@ -5,40 +5,44 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.URLUtil; -import com.bstek.designer.bean.PreviewPageParameters; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.bstek.common.exception.ReportDesignException; import com.bstek.designer.bean.PreviewParameters; import com.bstek.designer.bean.ReportDefinitionWrapper; -import com.bstek.ureport.build.paging.Page; -import com.bstek.ureport.definition.Paper; import com.bstek.ureport.definition.ReportDefinition; +import com.bstek.ureport.definition.dataset.ApiDatasetDefinition; import com.bstek.ureport.definition.dataset.BeanDatasetDefinition; import com.bstek.ureport.definition.dataset.DatasetDefinition; import com.bstek.ureport.definition.dataset.SqlDatasetDefinition; +import com.bstek.ureport.definition.datasource.ApiDatasourceDefinition; import com.bstek.ureport.definition.datasource.DatasourceDefinition; import com.bstek.ureport.definition.datasource.JdbcDatasourceDefinition; import com.bstek.ureport.definition.datasource.SpringBeanDatasourceDefinition; -import com.bstek.ureport.export.PageBuilder; +import com.bstek.ureport.exception.ReportComputeException; import com.bstek.ureport.export.ReportRender; -import com.bstek.ureport.export.SinglePageData; import com.bstek.ureport.export.html.HtmlProducer; import com.bstek.ureport.export.html.HtmlReport; -import com.bstek.ureport.export.html.SearchFormData; import com.bstek.ureport.model.Report; import com.bstek.ureport.parser.ReportParser; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.framework.organ.core.aop.OrganIgnore; +import com.cf.imes.framework.security.core.LoginUser; +import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetReqVO; import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetSaveReqVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceReqVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceSaveReqVO; -import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplatePreviewPageParametersVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateSaveReqVO; import com.cf.imes.module.report.dal.dataobject.dataset.ReportDatasetDO; import com.cf.imes.module.report.dal.dataobject.datasource.ReportDatasourceDO; import com.cf.imes.module.report.dal.dataobject.template.ReportTemplateDO; +import com.cf.imes.module.report.dal.mysql.dataset.ReportDatasetMapper; +import com.cf.imes.module.report.dal.mysql.datasource.ReportDatasourceMapper; import com.cf.imes.module.report.dal.mysql.template.ReportTemplateMapper; +import com.cf.imes.module.report.enums.template.ReportTemplateTypeEnum; import com.cf.imes.module.report.service.dataset.ReportDatasetService; import com.cf.imes.module.report.service.datasource.ReportDatasourceService; import org.apache.commons.lang3.StringUtils; @@ -49,11 +53,14 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATATEMPLATE_BUILDIN_OPERATION_PERMISSION_ERROR; import static com.cf.imes.module.report.enums.ErrorCodeConstants.TEMPLATE_NOT_EXISTS; /** @@ -74,6 +81,12 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { @Resource private ReportDatasetService datasetService; + @Resource + private ReportDatasourceMapper datasourceMapper; + + @Resource + private ReportDatasetMapper datasetMapper; + @Override @Transactional(rollbackFor = Exception.class) public Long createReportTemplate(ReportTemplateSaveReqVO createReqVO) { @@ -84,6 +97,14 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { } // 新增模板 ReportTemplateDO template = BeanUtils.toBean(createReqVO, ReportTemplateDO.class); + // 超管创建的作为内置模板 + LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); + boolean isSuperAdmin = loginUser != null && loginUser.getIsSupAdmin(); + if (isSuperAdmin) { + template.setType(ReportTemplateTypeEnum.SYSTEM); + } else { + template.setType(ReportTemplateTypeEnum.CUSTOM); + } templateMapper.insert(template); Long templateId = template.getId(); // 解析数据源 @@ -134,10 +155,13 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { } @Override + @Transactional(rollbackFor = Exception.class) public void updateReportTemplate(ReportTemplateSaveReqVO updateReqVO) { Long templateId = updateReqVO.getId(); // 校验存在 - validateTemplateExists(templateId); + ReportTemplateDO reportTemplateDO = validateTemplateExists(templateId); + // 校验内置模板操作权限 + validateSystemTemplate(reportTemplateDO); // url解码xml String content = updateReqVO.getContent(); if (StringUtils.isNotEmpty(content)) { @@ -152,11 +176,36 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { } @Override + @Transactional(rollbackFor = Exception.class) public void deleteReportTemplate(Long id) { // 校验存在 - validateTemplateExists(id); + ReportTemplateDO reportTemplateDO = validateTemplateExists(id); + // 校验内置模板操作权限 + validateSystemTemplate(reportTemplateDO); // 删除 templateMapper.deleteById(id); + // 删除关联数据源 + List reportDatasourceDOS = datasourceMapper.selectList(new LambdaQueryWrapperX().eq(ReportDatasourceDO::getTemplateId, id)); + if (CollUtil.isNotEmpty(reportDatasourceDOS)) { + // 模板下的数据源id + List datasourceIds = reportDatasourceDOS.stream().map(ReportDatasourceDO::getId).toList(); + datasourceMapper.deleteBatchIds(datasourceIds); + // 删除关联数据集 + datasetMapper.delete(new LambdaQueryWrapperX().in(ReportDatasetDO::getDatasourceId, datasourceIds)); + } + } + + + /** + * 校验只有超管可以操作内置模板 + */ + private void validateSystemTemplate(ReportTemplateDO templateDO) { + LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); + boolean isSuperAdmin = loginUser != null && loginUser.getIsSupAdmin(); + // 非超管不能操作内置模板 + if (ReportTemplateTypeEnum.SYSTEM.equals(templateDO.getType()) && !isSuperAdmin) { + throw exception(DATATEMPLATE_BUILDIN_OPERATION_PERMISSION_ERROR); + } } /** @@ -164,9 +213,12 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { * * @param id */ - private void validateTemplateExists(Long id) { - if (templateMapper.selectById(id) == null) { + private ReportTemplateDO validateTemplateExists(Long id) { + ReportTemplateDO reportTemplateDO = templateMapper.selectById(id); + if (reportTemplateDO == null) { throw exception(TEMPLATE_NOT_EXISTS); + } else { + return reportTemplateDO; } } @@ -196,8 +248,14 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { // 查询模板 ReportTemplateDO template = templateMapper.selectById(id); String xmlContent = template.getContent(); + InputStream is; + if (StringUtils.isNotEmpty(xmlContent)) { + is = new ByteArrayInputStream(xmlContent.getBytes()); + } else { + is = this.getClass().getClassLoader().getResourceAsStream("templates/template.ureport.xml"); + } // 解析xml - ReportDefinition reportDefinition = new ReportParser().parse(new ByteArrayInputStream(xmlContent.getBytes()), template.getName()); + ReportDefinition reportDefinition = new ReportParser().parse(is, template.getName()); if (ObjectUtil.isNotNull(template)) { queryDatasource(template.getId(), reportDefinition); } @@ -218,83 +276,94 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { // 查询数据集 List datasetList = datasetService.getDatasetList(ReportDatasetReqVO.builder().datasourceId(ds.getId()).build()); List datasetDefinitions = new ArrayList<>(); - switch (ds.getDsType()) { - case JDBC -> { + // 忽略转换的字段名,手动转列表 + String ignorePropertieName = "datasets"; + switch (ds.getType()) { + case JDBC, BUILDIN -> { // 转换对应的ureport对象 - JdbcDatasourceDefinition jdbcDatasourceDefinition = BeanUtil.copyProperties(ds, JdbcDatasourceDefinition.class, "datasets"); + JdbcDatasourceDefinition jdbcDatasourceDefinition = BeanUtil.copyProperties(ds, JdbcDatasourceDefinition.class, ignorePropertieName); datasetDefinitions.addAll(BeanUtils.toBean(datasetList, SqlDatasetDefinition.class)); jdbcDatasourceDefinition.setDatasets(datasetDefinitions); datasourceDefinitions.add(jdbcDatasourceDefinition); } case SPRING -> { // 转换对应的ureport对象 - SpringBeanDatasourceDefinition springBeanDatasourceDefinition = BeanUtil.copyProperties(ds, SpringBeanDatasourceDefinition.class, "datasets"); + SpringBeanDatasourceDefinition springBeanDatasourceDefinition = BeanUtil.copyProperties(ds, SpringBeanDatasourceDefinition.class, ignorePropertieName); datasetDefinitions.addAll(BeanUtils.toBean(datasetList, BeanDatasetDefinition.class)); springBeanDatasourceDefinition.setDatasets(datasetDefinitions); datasourceDefinitions.add(springBeanDatasourceDefinition); } + case API -> { + // 转换对应的ureport对象 + ApiDatasourceDefinition apiDatasourceDefinition = BeanUtil.copyProperties(ds, ApiDatasourceDefinition.class, ignorePropertieName); + datasetDefinitions.addAll(BeanUtils.toBean(datasetList, ApiDatasetDefinition.class)); + apiDatasourceDefinition.setDatasets(datasetDefinitions); + datasourceDefinitions.add(apiDatasourceDefinition); + } } } reportDefinition.setDatasources(datasourceDefinitions); } @Override + @OrganIgnore public List getReportTemplateList(ReportTemplateReqVO reqVO) { - return templateMapper.selectList(new LambdaQueryWrapperX() - .likeIfPresent(ReportTemplateDO::getName, reqVO.getName()) - .eqIfPresent(ReportTemplateDO::getType, reqVO.getType()) + LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapperX().likeIfPresent(ReportTemplateDO::getName, reqVO.getName()) .orderByDesc(ReportTemplateDO::getCreateTime) // 不返回content xml,点击具体的模板中返回xml - .select(ReportTemplateDO::getId, ReportTemplateDO::getName, ReportTemplateDO::getCreateTime, ReportTemplateDO::getRemark)); + .select(ReportTemplateDO::getId, ReportTemplateDO::getName, ReportTemplateDO::getCreateTime, ReportTemplateDO::getRemark); + if (loginUser != null && Boolean.FALSE.equals(loginUser.getIsSupAdmin())) { + // 普通用户查看机构下的和system模板 + queryWrapper.or(wrapper -> wrapper + .eq(ReportTemplateDO::getOrganId, loginUser.getOrganId()) + .eq(ReportTemplateDO::getType, ReportTemplateTypeEnum.CUSTOM)) + .or(wrapper -> wrapper.eq(ReportTemplateDO::getType, ReportTemplateTypeEnum.SYSTEM)); + } + // 超管查看全部 + return templateMapper.selectList(queryWrapper); } @Override - public HtmlReport preview(ReportTemplatePreviewPageParametersVO pageParametersVO) { + public HtmlReport preview(PreviewParameters params) { HtmlProducer htmlProducer = new HtmlProducer(); ReportRender reportRender = new ReportRender(); - HtmlReport htmlReport = new HtmlReport(); - - // 转换ureport参数 - PreviewPageParameters pageParameters = BeanUtils.toBean(pageParametersVO, PreviewPageParameters.class); - PreviewParameters params = pageParameters.getParams(); - - // 解析xml - ReportDefinition reportDefinition = reportRender.getReportDefinition(URLUtil.decode(params.getContent()), CharsetUtil.UTF_8); - + ReportDefinition reportDefinition = getReportDefinition(reportRender, params); Map parameters = params.getQuery(); - - Paper paper = reportDefinition.getPaper(); - Report report; - String html; - // 构建html - if (paper.isPageEnabled()) { - // todo 后续有可能做成缓存 - report = reportRender.render(reportDefinition, parameters); - int pageIndex = pageParameters.getPageIndex(); - SinglePageData pageData = PageBuilder.buildSinglePageData(pageIndex, report); - List pages = pageData.getPages(); - html = htmlProducer.produce(report.getContext(), pages, pageData.getColumnMargin(), false); - htmlReport.setTotalPage(pageData.getTotalPages()); - htmlReport.setPageIndex(pageIndex); - if (reportDefinition.getPaper().isColumnEnabled()) { - htmlReport.setColumn(reportDefinition.getPaper().getColumnCount()); - } - } else { - report = reportRender.render(reportDefinition, parameters); - html = htmlProducer.produce(report); - } - htmlReport.setChartDatas(report.getContext().getChartDataMap().values()); - htmlReport.setContent(html); - htmlReport.setStyle(reportDefinition.getStyle()); - SearchFormData searchFormData = reportDefinition.buildSearchFormData(report.getContext().getDatasetMap(), parameters); - htmlReport.setSearchFormData(searchFormData); - htmlReport.setReportAlign(report.getPaper().getHtmlReportAlign().name()); - htmlReport.setBgImage(report.getPaper().getBgImage()); - htmlReport.setFreeze(reportDefinition.getFreeze()); - htmlReport.setFloatImages(reportDefinition.getFloatImages()); - return htmlReport; + Report report = reportRender.render(reportDefinition, parameters); + return htmlProducer.produce(reportDefinition, report); } + private ReportDefinition getReportDefinition(ReportRender reportRender, PreviewParameters params) { + ReportDefinition reportDefinition; + + String content = params.getContent(); + if (StringUtils.isNotBlank(content)) { + content = URLUtil.decode(content); + reportDefinition = reportRender.getReportDefinition(content, "utf-8"); + } else { + throw new ReportComputeException("模版文件不能为空"); + } + if (reportDefinition == null) { + throw new ReportDesignException("模板数据已过期,无法预览"); + } + Map parameters = params.getQuery(); + if (parameters == null) { + parameters = new HashMap<>(); + params.setQuery(parameters); + } + Map component = params.getComponent(); + if (component == null) { + component = new HashMap<>(); + params.setComponent(component); + } + // 相同的低优先级的参数会被高优先级参数覆盖 + // 参数优先级, token参数 > 页面表单参数 > url链接参数 > 数据集默认参数 + parameters.put("pageIndex", params.getPageIndex()); + return reportDefinition; + } + + @Override public Report generateReport(ReportTemplateGenerateReqDTO reqDTO) { Long templateId = reqDTO.getTemplateId(); diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/validation/datasource/ReportDatasourceTypeInEnum.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/validation/datasource/ReportDatasourceTypeInEnum.java index c9036826c..411c32a9d 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/validation/datasource/ReportDatasourceTypeInEnum.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/validation/datasource/ReportDatasourceTypeInEnum.java @@ -28,7 +28,7 @@ import java.lang.annotation.Target; validatedBy = {ReportDatasourceTypeInEnumValidator.class} ) public @interface ReportDatasourceTypeInEnum { - String message() default "数据源类型[dsType]错误,请检查是否jdbc/spring"; + String message() default "数据源类型[type]错误,请检查是否jdbc/spring/buildin/api"; Class[] groups() default {}; diff --git a/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar b/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar index 88c8279ef..ed9ae8b6d 100644 Binary files a/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar and b/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar differ diff --git a/cf-module-report/cf-module-report-biz/src/main/resources/templates/template.ureport.xml b/cf-module-report/cf-module-report-biz/src/main/resources/templates/template.ureport.xml new file mode 100644 index 000000000..718f29edc --- /dev/null +++ b/cf-module-report/cf-module-report-biz/src/main/resources/templates/template.ureport.xml @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportCommonServiceImplTest.java b/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportCommonServiceImplTest.java index 9901e4668..34e5da3c5 100644 --- a/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportCommonServiceImplTest.java +++ b/cf-module-report/cf-module-report-biz/src/test/java/com/cf/imes/module/report/service/template/ReportCommonServiceImplTest.java @@ -8,7 +8,6 @@ import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetSaveRe import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceSaveReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateSaveReqVO; import com.cf.imes.module.report.enums.datasource.ReportDatasourceTypeEnum; -import com.cf.imes.module.report.enums.template.ReportTemplateTypeEnum; import java.util.ArrayList; import java.util.List; @@ -30,7 +29,6 @@ public abstract class ReportCommonServiceImplTest { .id(id) .name("单元测试模板") .content(JsonUtil.zipString(TEMPLATE)) - .type(ReportTemplateTypeEnum.SYSTEM.getType()) .remark(RandomUtils.randomString()) .datasource(new ArrayList<>()) .build(); @@ -42,8 +40,7 @@ public abstract class ReportCommonServiceImplTest { .id(id) .name("单元测试数据源") .templateId(reportId) - .dsType(ReportDatasourceTypeEnum.SPRING.getDesc()) - .type(ReportTemplateTypeEnum.SYSTEM.getType()) + .type(ReportDatasourceTypeEnum.SPRING.getDesc()) .driver("com.mysql.cj.jdbc.Driver") .url("jdbc:mysql://192.168.1.205:3307/imes_base?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true") .username("root") diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeSendReqDTO.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeSendReqDTO.java index acb888fc7..333dbf00d 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeSendReqDTO.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeSendReqDTO.java @@ -7,7 +7,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; @Schema(description = "RPC 服务 - 短信验证码的发送 Request DTO") @Data @@ -19,12 +18,10 @@ public class SmsCodeSendReqDTO { private String mobile; @Schema(description = "发送场景", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "发送场景不能为空") @InEnum(SmsSceneEnum.class) - private Integer scene; + @Schema(description = "发送 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.20.30.40") - @NotEmpty(message = "发送 IP 不能为空") private String createIp; } diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeUseReqDTO.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeUseReqDTO.java index 480044cba..2d31f8834 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeUseReqDTO.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeUseReqDTO.java @@ -4,6 +4,7 @@ import com.cf.imes.framework.common.validation.InEnum; import com.cf.imes.framework.common.validation.Mobile; import com.cf.imes.module.system.enums.sms.SmsSceneEnum; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; import lombok.Data; import javax.validation.constraints.NotEmpty; @@ -11,6 +12,7 @@ import javax.validation.constraints.NotNull; @Schema(description = "RPC 服务 - 短信验证码的使用 Request DTO") @Data +@Builder public class SmsCodeUseReqDTO { @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300") @@ -28,7 +30,6 @@ public class SmsCodeUseReqDTO { private String code; @Schema(description = "发送 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.20.30.40") - @NotEmpty(message = "使用 IP 不能为空") private String usedIp; } diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeValidateReqDTO.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeValidateReqDTO.java index 542d67d04..4a312008e 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeValidateReqDTO.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/api/sms/dto/code/SmsCodeValidateReqDTO.java @@ -4,6 +4,7 @@ import com.cf.imes.framework.common.validation.InEnum; import com.cf.imes.framework.common.validation.Mobile; import com.cf.imes.module.system.enums.sms.SmsSceneEnum; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; import lombok.Data; import javax.validation.constraints.NotEmpty; @@ -11,6 +12,7 @@ import javax.validation.constraints.NotNull; @Schema(description = "RPC 服务 - 短信验证码的校验 Request DTO") @Data +@Builder public class SmsCodeValidateReqDTO { @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300") diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java index 0166b5d7a..910f015b4 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java @@ -16,6 +16,7 @@ public interface ErrorCodeConstants { ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_002_000_005, "未绑定账号,需要进行绑定"); ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1_002_000_006, "Token 已经过期"); ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_007, "手机号不存在"); + ErrorCode AUTH_LOGIN_FIRST_LOGIN = new ErrorCode(1_002_000_008, "请通过验证码登录"); // ========== 菜单模块 1-002-001-000 ========== ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1_002_001_000, "已经存在该名字的菜单"); @@ -44,7 +45,7 @@ public interface ErrorCodeConstants { ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1_002_003_005, "用户密码校验失败"); ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用"); ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过组织最大组织配额({})!"); - ErrorCode USER_ME_ERROR = new ErrorCode(1_002_003_009, "不可操作用户自身"); + ErrorCode USER_ME_ERROR = new ErrorCode(1_002_003_009, "不允许操作用户自身"); ErrorCode THE_PASSWORD_LENGTH_MUST_BE_AT_LEAST_6_CHARACTERS = new ErrorCode(1_002_003_010, "密码长度必须至少为6个字符"); @@ -53,6 +54,10 @@ public interface ErrorCodeConstants { ErrorCode THE_PASSWORD_MUST_CONTAIN_AT_LEAST_ONE_NUMBER = new ErrorCode(1_002_003_012, "密码必须包含至少一个数字"); ErrorCode PASSWORDS_CAN_ONLY_CONTAIN_LETTERS_AND_NUMBERS = new ErrorCode(1_002_003_013, "密码只能包含字母和数字"); + ErrorCode INSUFFICIENT_PERMISSIONS = new ErrorCode(1_002_003_014, "当前用户权限不足,无法修改开料状态"); + ErrorCode USERNAME_MULTIPLE_ERROR = new ErrorCode(1_002_003_015,"存在【{}】重复用户,请联系系统管理员"); + ErrorCode USER_OPERATE_SELF_STATUS_ERROR = new ErrorCode(1_002_003_016, "不允许操作用户自身状态"); + // ========== 部门模块 1-002-004-000 ========== ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门"); @@ -104,14 +109,15 @@ public interface ErrorCodeConstants { ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_013_002, "短信模板不存在"); // ========== 短信验证码 1-002-014-000 ========== - ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1_002_014_000, "验证码不存在"); - ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1_002_014_001, "验证码已过期"); - ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用"); + ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1_002_014_000, "验证码不存在,请点击获取"); + ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1_002_014_001, "验证码已过期,请重新获取"); + ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用,请重新获取"); ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1_002_014_003, "验证码不正确"); ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量"); ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频率"); ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1_002_014_006, "手机号已被使用"); ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1_002_014_007, "验证码未被使用"); + ErrorCode SMS_CODE_IS_VALID = new ErrorCode(1_002_014_008, "验证码在有效期内,5分钟内请勿重复发送!"); // ========== 组织信息 1-002-015-000 ========== ErrorCode ORGAN_NOT_EXISTS = new ErrorCode(1_002_015_000, "组织不存在"); @@ -213,7 +219,8 @@ public interface ErrorCodeConstants { ErrorCode MACHINE_ERROR = new ErrorCode(1_002_029_007, "当前机台错误,请重新选择机台"); ErrorCode THE_CURRENT_BRAND_OF_THE_MACHINE_EXISTS = new ErrorCode(1_002_029_008, "当前机台配置的模板中,该品牌已存在,请重新输入品牌名称"); ErrorCode THE_MODEL_OF_THE_MACHINE_DOES_NOT_EXIST = new ErrorCode(1_002_029_009, "该型号的机台不存在,请进行配置"); - ErrorCode THE_CURRENT_BRAND = new ErrorCode(1_002_029_666, "品牌ID错误,或品牌不存在"); + ErrorCode THE_CURRENT_BRAND = new ErrorCode(1_002_029_010, "品牌ID错误,或品牌不存在"); + ErrorCode MACHINE_NUM_ERROR = new ErrorCode(1_002_029_011, "当前模板创建的机台数量已达到最大轴,无法继续创建"); // ========== 标签模板 1-002-300-000 ========== ErrorCode LABEL_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_300_000, "标签模板不存在"); @@ -257,6 +264,7 @@ public interface ErrorCodeConstants { //=========== 板材信息 1-002-035-000 ============ ErrorCode RAW_GOODS_NOT_EXISTS = new ErrorCode(1_002_033_001, "设计板材不存再"); ErrorCode RAW_GOODS_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_002_033_002, "生产板材导入数据不可以为空"); + ErrorCode PLATENO_ERROR = new ErrorCode(1_002_033_003, "当前板编号无对应包裹信息"); //=========== 配件信息 1-002-035-000 ============ ErrorCode ORDER_PARTS_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_002_034_001, "生产配件导入数据不可以为空"); diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/logger/LoginLogTypeEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/logger/LoginLogTypeEnum.java index 192df5947..b79a4d8d4 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/logger/LoginLogTypeEnum.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/logger/LoginLogTypeEnum.java @@ -14,6 +14,7 @@ public enum LoginLogTypeEnum { LOGIN_SOCIAL(101), // 使用社交登录 LOGIN_MOBILE(103), // 使用手机登陆 LOGIN_SMS(104), // 使用短信登陆 + LOGIN_FORGET_PWD(105), // 登录忘记密码 LOGOUT_SELF(200), // 自己主动登出 LOGOUT_DELETE(202), // 强制退出 diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/logger/LoginResultEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/logger/LoginResultEnum.java index dd341fb4e..faba49989 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/logger/LoginResultEnum.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/logger/LoginResultEnum.java @@ -15,8 +15,7 @@ public enum LoginResultEnum { USER_DISABLED(20), // 用户被禁用 CAPTCHA_NOT_FOUND(30), // 图片验证码不存在 CAPTCHA_CODE_ERROR(31), // 图片验证码不正确 - - ; + FIRST_LOGIN(32); // 首次登录 /** * 结果 diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/sms/SmsSceneEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/sms/SmsSceneEnum.java index 11f624976..70406edcf 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/sms/SmsSceneEnum.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/sms/SmsSceneEnum.java @@ -16,12 +16,13 @@ import java.util.Arrays; @AllArgsConstructor public enum SmsSceneEnum implements IntArrayValuable { - MEMBER_LOGIN(1, "user-sms-login", "会员用户 - 手机号登陆"), - MEMBER_UPDATE_MOBILE(2, "user-update-mobile", "会员用户 - 修改手机"), - MEMBER_UPDATE_PASSWORD(3, "user-update-password", "会员用户 - 修改密码"), - MEMBER_RESET_PASSWORD(4, "user-reset-password", "会员用户 - 忘记密码"), - - ADMIN_MEMBER_LOGIN(21, "admin-sms-login", "后台用户 - 手机号登录"); + USER_UPDATE_MOBILE(1, "user-update-mobile", "修改手机"), + USER_RESET_PASSWORD(2, "user-reset-password", "忘记密码"), + USER_UPDATE_PASSWORD(3, "user-update-password", "修改密码"), + USER_LOGIN_CAPTCHAVERIFICATION(4, "user-login-captchaverification", "登录验证码"), + ADMIN_LOGIN(20, "admin-sms-login", "后台用户 - 手机号登录"), + ADMIN_MEMBER_LOGIN(21, "admin-sms-login", "后台用户 - 手机号登录"), + MEMBER_LOGIN(22, "user-sms-login", "会员用户 - 手机号登陆"); public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SmsSceneEnum::getScene).toArray(); diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/sms/SmsTemplateTypeEnum.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/sms/SmsTemplateTypeEnum.java index 64171fee2..ff052f877 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/sms/SmsTemplateTypeEnum.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/sms/SmsTemplateTypeEnum.java @@ -22,4 +22,17 @@ public enum SmsTemplateTypeEnum { */ private final int type; + + public static SmsTemplateTypeEnum valueOf(Integer type) { + if (type == null) { + return null; + } + for (SmsTemplateTypeEnum value : values()) { + if (type == value.getType()) { + return value; + } + } + return null; + } + } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/SystemServerApplication.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/SystemServerApplication.java index be0d9596a..189dad7fd 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/SystemServerApplication.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/SystemServerApplication.java @@ -2,12 +2,14 @@ package com.cf.imes.module.system; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.context.config.annotation.RefreshScope; /** * 项目的启动类 * @author 晨丰科技 */ @SpringBootApplication +@RefreshScope public class SystemServerApplication { public static void main(String[] args) { diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java index 5f443f64f..35bd09bd0 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/AuthController.java @@ -1,13 +1,14 @@ package com.cf.imes.module.system.controller.admin.auth; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; import com.cf.imes.framework.common.enums.CommonStatusEnum; import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.framework.common.validation.Mobile; import com.cf.imes.framework.operatelog.core.annotations.OperateLog; import com.cf.imes.framework.security.config.SecurityProperties; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; +import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthPermissionInfoRespVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO; @@ -20,6 +21,7 @@ import com.cf.imes.module.system.service.auth.AdminAuthService; import com.cf.imes.module.system.service.permission.MenuService; import com.cf.imes.module.system.service.permission.PermissionService; import com.cf.imes.module.system.service.permission.RoleService; +import com.cf.imes.module.system.service.sms.SmsCodeService; import com.cf.imes.module.system.service.social.SocialClientService; import com.cf.imes.module.system.service.user.AdminUserService; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginRespVO; @@ -30,6 +32,8 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.annotations.Param; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -37,12 +41,14 @@ import javax.annotation.Resource; import javax.annotation.security.PermitAll; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; import java.util.Collections; import java.util.List; import java.util.Set; import static com.cf.imes.framework.common.pojo.CommonResult.success; import static com.cf.imes.framework.common.util.collection.CollectionUtils.convertSet; +import static com.cf.imes.framework.common.util.servlet.ServletUtils.getClientIP; import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - 认证") @@ -68,14 +74,27 @@ public class AuthController { @Resource private SecurityProperties securityProperties; + @Resource + private SmsCodeService smsCodeService; + @PostMapping("/login") @PermitAll @Operation(summary = "使用账号密码登录") @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 - public CommonResult login(@RequestBody @Valid AuthLoginReqVO reqVO) { + public CommonResult login(@Valid @RequestBody AuthLoginReqVO reqVO) { return success(authService.login(reqVO)); } + @PostMapping("/check") + @PermitAll + @Operation(summary = "校验账号") + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 + @Parameter(name = "mobile", description = "手机号", required = true) + public CommonResult loginCheck( + @Param("mobile") @NotEmpty(message = "手机号不能为空") @Mobile String mobile) { + return success(authService.loginCheck(mobile)); + } + @PostMapping("/logout") @PermitAll @Operation(summary = "登出系统") @@ -83,7 +102,7 @@ public class AuthController { public CommonResult logout(HttpServletRequest request) { String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader(), securityProperties.getTokenParameter()); - if (StrUtil.isNotBlank(token)) { + if (StringUtils.isNotBlank(token)) { authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType()); } return success(true); @@ -112,7 +131,6 @@ public class AuthController { if (CollUtil.isEmpty(roleIds)) { return success(AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList())); } - //List roles = roleService.getRoleList(roleIds); List roles = roleService.getRoleList1(roleIds); roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 @@ -144,6 +162,18 @@ public class AuthController { return success(true); } + @PutMapping("/sms-code") + @Operation(summary = "发送短信验证码") + @PermitAll + @OperateLog(enable = false) + public CommonResult sendSmsCode(@Valid @RequestBody SmsCodeSendReqDTO reqDTO) { + // 获取请求ip + reqDTO.setCreateIp(getClientIP()); + // 发送验证码 + smsCodeService.sendSmsCode(reqDTO); + return success(true); + } + // ========== 社交登录相关 ========== @GetMapping("/social-auth-redirect") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/vo/AuthLoginReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/vo/AuthLoginReqVO.java index e91319c0e..4b1835075 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/vo/AuthLoginReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/vo/AuthLoginReqVO.java @@ -1,6 +1,6 @@ package com.cf.imes.module.system.controller.admin.auth.vo; -import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.ObjectUtil; import com.cf.imes.framework.common.validation.InEnum; import com.cf.imes.module.system.enums.social.SocialTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; @@ -8,10 +8,10 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; import org.hibernate.validator.constraints.Length; import javax.validation.constraints.AssertTrue; -import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; @@ -29,12 +29,10 @@ public class AuthLoginReqVO { private String username; @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao") - @NotEmpty(message = "密码不能为空") @Length(min = 4, max = 16, message = "密码长度为 4-16 位") private String password; @Schema(description = "组织名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰科技") - @NotBlank(message = "组织名称不能空") private String organName; // ========== 图片验证码相关 ========== @@ -44,6 +42,10 @@ public class AuthLoginReqVO { @NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class) private String captchaVerification; + @Schema(description = "短信验证码", example = "123456") + @Length(min = 6, max = 6, message = "短信验证码长度为 6 位") + private String smsCaptchaVerification; + // ========== 绑定社交登录时,需要传递如下参数 ========== @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") @@ -63,12 +65,17 @@ public class AuthLoginReqVO { @AssertTrue(message = "授权码不能为空") public boolean isSocialCodeValid() { - return socialType == null || StrUtil.isNotEmpty(socialCode); + return socialType == null || StringUtils.isNotEmpty(socialCode); } @AssertTrue(message = "授权 state 不能为空") public boolean isSocialState() { - return socialType == null || StrUtil.isNotEmpty(socialState); + return socialType == null || StringUtils.isNotEmpty(socialState); } + @AssertTrue(message = "请输入密码后登陆") + public boolean isPasswordValid() { + // 要么是密码登录、要么是验证码登录 + return ObjectUtil.isNotNull(password) || ObjectUtil.isNotNull(smsCaptchaVerification); + } } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java index 8efa123a6..8c30da745 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java @@ -46,6 +46,9 @@ public class AuthPermissionInfoRespVO { @Schema(description = "组织id") private Long organId; + + @Schema(description = "是否需要设置密码") + private boolean needSetPwd; } @Schema(description = "管理后台 - 登录用户的菜单信息 Response VO") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganSaveReqVO.java index da0db8e16..57cea191f 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganSaveReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganSaveReqVO.java @@ -1,13 +1,10 @@ package com.cf.imes.module.system.controller.admin.organ.vo.organ; -import cn.hutool.core.util.ObjectUtil; import com.cf.imes.framework.common.validation.Mobile; -import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.AssertTrue; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; @@ -30,6 +27,7 @@ public class OrganSaveReqVO { @Schema(description = "联系手机", example = "15601691300") @Mobile + @NotNull(message = "联系人手机不能为空") private String contactMobile; @Schema(description = "组织状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @@ -62,13 +60,6 @@ public class OrganSaveReqVO { @Length(min = 4, max = 16, message = "密码长度为 4-16 位") private String password; - @AssertTrue(message = "用户账号、密码不能为空") - @JsonIgnore - public boolean isUsernameValid() { - return id != null // 修改时,不需要传递 - || (ObjectUtil.isAllNotEmpty(username, password)); // 新增时,必须都传递 username、password - } - @Schema(description = "是否大型组织") private Boolean large; diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/MenuController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/MenuController.java index 90e567eb9..1a6ea7b3b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/MenuController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/MenuController.java @@ -5,12 +5,10 @@ import com.cf.imes.framework.common.enums.CommonStatusEnum; import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.security.core.LoginUser; -import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.system.controller.admin.permission.vo.menu.MenuListReqVO; import com.cf.imes.module.system.controller.admin.permission.vo.menu.MenuRespVO; import com.cf.imes.module.system.controller.admin.permission.vo.menu.MenuSaveVO; import com.cf.imes.module.system.controller.admin.permission.vo.menu.MenuSimpleRespVO; -import com.cf.imes.module.system.convert.auth.AuthConvert; import com.cf.imes.module.system.dal.dataobject.permission.MenuDO; import com.cf.imes.module.system.dal.dataobject.permission.RoleDO; import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; @@ -110,8 +108,9 @@ public class MenuController { @Operation(summary = "获取菜单精简信息列表", description = "只包含被开启的菜单,用于【角色分配菜单】功能的选项。" + "在多组织的场景下,会只返回组织所在套餐有的菜单") public CommonResult> getSimpleMenuList() { + // status:0 开启 visiable:1 显示 List list = menuService.getMenuListByOrgan( - new MenuListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); + new MenuListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()).setVisiable(CommonStatusEnum.DISABLE.getStatus())); list.sort(Comparator.comparing(MenuDO::getSort)); return success(BeanUtils.toBean(list, MenuSimpleRespVO.class)); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java index ba7db8d8e..7e9300d38 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java @@ -10,7 +10,9 @@ public class MenuListReqVO { @Schema(description = "菜单名称,模糊匹配", example = "晨丰") private String name; - @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") + @Schema(description = "菜单状态,参见 CommonStatusEnum 枚举类", example = "1") private Integer status; + @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") + private Integer visiable; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/UserController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/UserController.java index 1bd4daa91..3167c2d1e 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/UserController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/UserController.java @@ -38,6 +38,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; +import javax.annotation.security.PermitAll; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; @@ -100,6 +101,15 @@ public class UserController { return success(true); } + @PutMapping("/reset-password") + @Operation(summary = "忘记密码重置") + @PermitAll + @OperateLog(enable = false) + public CommonResult resetUserPassword(@Valid @RequestBody UserResetPasswordReqVO reqVO) { + userService.resetUserPassword(reqVO); + return success(true); + } + @PutMapping("/update-status") @Operation(summary = "修改用户状态") // @PreAuthorize("@ss.hasPermission('system:user:update')") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/UserProfileController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/UserProfileController.java index 59a18aae7..8a218610b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/UserProfileController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/UserProfileController.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.datapermission.core.annotation.DataPermission; +import com.cf.imes.module.system.controller.admin.user.vo.profile.UserMobileUpdateReqVO; import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileRespVO; import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; @@ -97,4 +98,10 @@ public class UserProfileController { return success(avatar); } + @PostMapping("/security/phone") + @Operation(summary = "修改密保手机") + public CommonResult updateUserSecurityPhone(@Valid @RequestBody UserMobileUpdateReqVO reqVO) { + userService.updateUserSecurityPhone(getLoginUserId(), reqVO); + return success(true); + } } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/profile/UserMobileUpdateReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/profile/UserMobileUpdateReqVO.java new file mode 100644 index 000000000..8d25db462 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/profile/UserMobileUpdateReqVO.java @@ -0,0 +1,26 @@ +package com.cf.imes.module.system.controller.admin.user.vo.profile; + +import com.cf.imes.framework.common.validation.Mobile; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotEmpty; + + +@Schema(description = "管理后台 - 用户密保手机更新 Request VO") +@Data +public class UserMobileUpdateReqVO { + + + @Schema(description = "手机号码", example = "15601691300") + @Length(min = 11, max = 11, message = "手机号长度必须 11 位") + @Mobile + @NotEmpty(message = "手机号不能为空") + private String mobile; + + @Schema(description = "验证码", example = "123456") + @Length(min = 6, max = 6, message = "验证码长度必须 6 位") + @NotEmpty(message = "短信验证码不能为空") + private String smsCaptchaVerification; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java index 7f7488ac5..35f1c83bb 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java @@ -1,5 +1,6 @@ package com.cf.imes.module.system.controller.admin.user.vo.profile; +import com.cf.imes.framework.common.validation.Mobile; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.hibernate.validator.constraints.Length; @@ -23,6 +24,7 @@ public class UserProfileUpdateReqVO { @Schema(description = "手机号码", example = "15601691300") @Length(min = 11, max = 11, message = "手机号长度必须 11 位") + @Mobile private String mobile; @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/user/UserResetPasswordReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/user/UserResetPasswordReqVO.java new file mode 100644 index 000000000..d8447f844 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/user/UserResetPasswordReqVO.java @@ -0,0 +1,28 @@ +package com.cf.imes.module.system.controller.admin.user.vo.user; + +import com.cf.imes.framework.common.validation.Mobile; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotEmpty; + +@Schema(description = "管理后台 - 用户重置密码 Request VO") +@Data +public class UserResetPasswordReqVO { + + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") + @NotEmpty(message = "密码不能为空") + @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + private String password; + + @Schema(description = "短信验证码", example = "123456") + @Length(min = 6, max = 6, message = "短信验证码长度为 6 位") + @NotEmpty(message = "短信验证码不能为空") + private String smsCaptchaVerification; + + @Schema(description = "手机号", example = "15601691300") + @Mobile + @NotEmpty(message = "手机号不能为空") + private String mobile; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/user/UserSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/user/UserSaveReqVO.java index a88ef6c82..857adafe1 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/user/UserSaveReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/user/vo/user/UserSaveReqVO.java @@ -17,12 +17,6 @@ public class UserSaveReqVO { @Schema(description = "用户编号", example = "1024") private Long id; - @Schema(description = "a", requiredMode = Schema.RequiredMode.REQUIRED, example = "chenfeng") - @NotBlank(message = "用户名不能为空") - @Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户名由 数字、字母 组成") - @Size(min = 4, max = 30, message = "用户名长度为 4-30 个字符") - private String username; - @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰") @Size(max = 30, message = "用户昵称长度不能超过30个字符") private String nickname; @@ -43,6 +37,7 @@ public class UserSaveReqVO { @Schema(description = "手机号码", example = "15601691300") @Mobile + @NotBlank(message = "手机号码不能为空") private String mobile; @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1") @@ -57,13 +52,6 @@ public class UserSaveReqVO { @Length(min = 4, max = 16, message = "密码长度为 4-16 位") private String password; - @AssertTrue(message = "密码不能为空") - @JsonIgnore - public boolean isPasswordValid() { - return id != null // 修改时,不需要传递 - || (ObjectUtil.isAllNotEmpty(password)); // 新增时,必须都传递 password - } - @Schema(description = "帐号状态(0正常 1停用)") @NotNull(message = "账号状态不能空") private Integer status; diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/auth/AuthConvert.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/auth/AuthConvert.java index faaa9cdb8..0aa4d49e6 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/auth/AuthConvert.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/auth/AuthConvert.java @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import com.cf.imes.module.system.api.social.dto.SocialUserBindReqDTO; -import com.cf.imes.module.system.controller.admin.auth.vo.*; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginRespVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthPermissionInfoRespVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO; @@ -15,6 +14,7 @@ import com.cf.imes.module.system.dal.dataobject.permission.MenuDO; import com.cf.imes.module.system.dal.dataobject.permission.RoleDO; import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; import com.cf.imes.module.system.enums.permission.MenuTypeEnum; +import org.apache.commons.lang3.StringUtils; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; import org.slf4j.LoggerFactory; @@ -33,7 +33,8 @@ public interface AuthConvert { default AuthPermissionInfoRespVO convert(AdminUserDO user, List roleList, List menuList) { return AuthPermissionInfoRespVO.builder() - .user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).organId(user.getOrganId()).build()) + .user(AuthPermissionInfoRespVO.UserVO.builder() + .id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).organId(user.getOrganId()).needSetPwd(StringUtils.isEmpty(user.getPassword())).build()) .roles(convertSet(roleList, RoleDO::getCode)) // 权限标识信息 .permissions(convertSet(menuList, MenuDO::getPermission)) diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/organ/OrganConvert.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/organ/OrganConvert.java index d02b65f76..ed438f0a8 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/organ/OrganConvert.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/organ/OrganConvert.java @@ -17,9 +17,8 @@ public interface OrganConvert { default UserSaveReqVO convert02(OrganSaveReqVO bean) { UserSaveReqVO reqVO = new UserSaveReqVO(); - reqVO.setUsername(bean.getUsername()); - reqVO.setPassword(bean.getPassword()); - reqVO.setNickname(bean.getContactName()).setMobile(bean.getContactMobile()); + reqVO.setMobile(bean.getContactMobile()); + reqVO.setNickname(bean.getContactName()); return reqVO; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/permission/MenuMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/permission/MenuMapper.java index 6971ae3d4..7e3d39cff 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/permission/MenuMapper.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/permission/MenuMapper.java @@ -22,7 +22,8 @@ public interface MenuMapper extends BaseMapperX { default List selectList(MenuListReqVO reqVO) { return selectList(new LambdaQueryWrapperX() .likeIfPresent(MenuDO::getName, reqVO.getName()) - .eqIfPresent(MenuDO::getStatus, reqVO.getStatus())); + .eqIfPresent(MenuDO::getStatus, reqVO.getStatus()) + .eqIfPresent(MenuDO::getVisible, reqVO.getVisiable())); } default List selectListByPermission(String permission) { diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java index 074e8c1b1..cc79ad4c7 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/user/AdminUserMapper.java @@ -1,8 +1,9 @@ package com.cf.imes.module.system.dal.mysql.user; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.cf.imes.framework.common.enums.CommonStatusEnum; +import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; @@ -11,10 +12,10 @@ import com.cf.imes.framework.security.core.LoginUser; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.executor.enums.OrderDeletedEnum; import com.cf.imes.module.system.controller.admin.user.vo.user.UserPageReqVO; -import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO; import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; import java.time.LocalDate; import java.time.LocalDateTime; @@ -22,7 +23,8 @@ import java.time.LocalTime; import java.util.Collection; import java.util.List; import java.util.Objects; -import java.util.function.Consumer; + +import static com.cf.imes.module.system.enums.ErrorCodeConstants.USERNAME_MULTIPLE_ERROR; @Mapper public interface AdminUserMapper extends BaseMapperX { @@ -35,6 +37,26 @@ public interface AdminUserMapper extends BaseMapperX { ); } + /** + * 用户名查询唯一用户,存在多个用户抛出业务异常 + * + * @param userName + * @return + */ + @OrganIgnore + default AdminUserDO selectByUsernameUnique(String userName) { + AdminUserDO adminUserDO = null; + List adminUserDOS = selectList(new LambdaQueryWrapperX() + .eq(AdminUserDO::getUsername, userName)); + if (CollectionUtil.isNotEmpty(adminUserDOS)) { + if (adminUserDOS.size() > 1) { + throw ServiceExceptionUtil.exception(USERNAME_MULTIPLE_ERROR, userName); + } + adminUserDO = adminUserDOS.get(0); + } + return adminUserDO; + } + default AdminUserDO selectByEmail(String email) { return selectOne(AdminUserDO::getEmail, email); } @@ -141,4 +163,13 @@ public interface AdminUserMapper extends BaseMapperX { .eq(AdminUserDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) .between(AdminUserDO::getLoginDate, startTime, endTIme))); } + + /** + * 数据库锁id下的数据,注意使用 + * + * @param id + * @return + */ + @Select("SELECT username FROM system_users WHERE id = #{id} FOR UPDATE") + AdminUserDO selectByIdForUpdate(@Param("id") Long id); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/redis/RedisKeyConstants.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/redis/RedisKeyConstants.java index 52d97e7a6..fb6ff8302 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/redis/RedisKeyConstants.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/redis/RedisKeyConstants.java @@ -98,4 +98,14 @@ public interface RedisKeyConstants { * VALUE 数据格式:String 模版信息 */ String SMS_TEMPLATE = "sms_template"; + + /** + * 短信验证码的缓存 + */ + String SMS_CAPTCHA_VERIFICATION = "sms_captcha_verification:%s"; + + /** + * 短信验证码次数上限的缓存 + */ + String SMS_CAPTCHA_VERIFICATION_LIMIT = "sms_captcha_verification_limit:%s"; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/framework/sms/SmsCodeProperties.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/framework/sms/SmsCodeProperties.java index 32c61170c..7f7284de6 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/framework/sms/SmsCodeProperties.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/framework/sms/SmsCodeProperties.java @@ -38,4 +38,15 @@ public class SmsCodeProperties { @NotNull(message = "验证码最大值不能为空") private Integer endCode; + /** + * 窗口时间 + */ + @NotNull(message = "窗口时间不能为空") + private Duration sendWindowSizeMin; + + /** + * 窗口最大请求次数 + */ + @NotNull(message = "窗口最大请求次数不能为空") + private Integer sendMaxSendTimesPerWindow; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/sms/SmsSendMessage.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/sms/SmsSendMessage.java index 92a07b800..502c9bc91 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/sms/SmsSendMessage.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/sms/SmsSendMessage.java @@ -39,4 +39,9 @@ public class SmsSendMessage { */ private List> templateParams; + /** + * 短信消息模板类型:system_sms_template.type + * 不同的消息模板类型有不同的消息发送后处理器 + */ + private Integer templateType; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/sms/SmsProducer.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/sms/SmsProducer.java index 1061fbf46..88981e9a9 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/sms/SmsProducer.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/sms/SmsProducer.java @@ -1,10 +1,12 @@ package com.cf.imes.module.system.mq.producer.sms; import com.cf.imes.framework.common.core.KeyValue; +import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO; import com.cf.imes.module.system.mq.message.sms.SmsSendMessage; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; import javax.annotation.Resource; import java.util.List; @@ -25,16 +27,16 @@ public class SmsProducer { /** * 发送 {@link SmsSendMessage} 消息 * - * @param logId 短信日志编号 - * @param mobile 手机号 - * @param channelId 渠道编号 - * @param apiTemplateId 短信模板编号 + * @param logId 短信日志编号 + * @param mobile 手机号 + * @param template 模板信息 * @param templateParams 短信模板参数 */ - public void sendSmsSendMessage(Long logId, String mobile, - Long channelId, String apiTemplateId, List> templateParams) { + public void sendSmsSendMessage(Long logId, String mobile, SmsTemplateDO template, List> templateParams) { SmsSendMessage message = new SmsSendMessage().setLogId(logId).setMobile(mobile); - message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams); + message.setChannelId(template.getChannelId()).setApiTemplateId(template.getApiTemplateId()).setTemplateType(template.getType()).setTemplateParams(templateParams); + // event异步发送短信,保证子线程内部request不为空 + RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(), true); applicationContext.publishEvent(message); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java index ab6ae3bb9..d6d9acf26 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthService.java @@ -1,6 +1,5 @@ package com.cf.imes.module.system.service.auth; -import com.cf.imes.module.system.controller.admin.auth.vo.*; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginRespVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO; @@ -22,11 +21,10 @@ public interface AdminAuthService { /** * 验证账号 + 密码。如果通过,则返回用户 * - * @param username 账号 - * @param password 密码 + * @param reqVO * @return 用户 */ - AdminUserDO authenticate(String username, String password, String organName); + AdminUserDO authenticate(AuthLoginReqVO reqVO); /** * 账号登录 @@ -36,6 +34,13 @@ public interface AdminAuthService { */ AuthLoginRespVO login(@Valid AuthLoginReqVO reqVO); + /** + * 登录校验 + * @param mobile + * @return true需要验证码,false不需要验证码 + */ + boolean loginCheck(String mobile); + /** * 基于 token 退出登录 * diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java index 328c51fc5..469ea9859 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImpl.java @@ -9,6 +9,7 @@ import com.cf.imes.framework.common.util.servlet.ServletUtils; import com.cf.imes.framework.common.util.validation.ValidationUtils; import com.cf.imes.module.system.api.logger.dto.LoginLogCreateReqDTO; import com.cf.imes.module.system.api.sms.SmsCodeApi; +import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import com.cf.imes.module.system.api.social.dto.SocialUserBindReqDTO; import com.cf.imes.module.system.api.social.dto.SocialUserRespDTO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginReqVO; @@ -27,6 +28,7 @@ import com.cf.imes.module.system.enums.sms.SmsSceneEnum; import com.cf.imes.module.system.service.logger.LoginLogService; import com.cf.imes.module.system.service.member.MemberService; import com.cf.imes.module.system.service.oauth2.OAuth2TokenService; +import com.cf.imes.module.system.service.sms.SmsCodeService; import com.cf.imes.module.system.service.social.SocialUserService; import com.cf.imes.module.system.service.organ.OrganService; import com.cf.imes.module.system.service.user.AdminUserService; @@ -47,7 +49,6 @@ import java.util.Objects; import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.cf.imes.framework.common.util.servlet.ServletUtils.getClientIP; import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAN_DATA_CODE_NOT_EXISTS; -import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAN_NOT_EXISTS; /** * Auth Service 实现类 @@ -77,6 +78,9 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Resource private OrganService organService; + @Resource + private SmsCodeService smsCodeService; + /** * 验证码的开关,默认为 true */ @@ -84,19 +88,23 @@ public class AdminAuthServiceImpl implements AdminAuthService { private Boolean captchaEnable; @Override - public AdminUserDO authenticate(String username, String password, String organName) { + public AdminUserDO authenticate(AuthLoginReqVO reqVO) { + String username = reqVO.getUsername(); + String password = reqVO.getPassword(); + String smsCaptchaVerification = reqVO.getSmsCaptchaVerification(); final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME; - OrganizationDO organ = organService.getOrganByName(organName); - if(Objects.isNull(organ)) { - throw ServiceExceptionUtil.exception(ORGAN_NOT_EXISTS); - } - // 校验账号是否存在 - AdminUserDO user = userService.getUserByUsernameAndOrganId(username, organ.getId()); + // 查询账号 + AdminUserDO user = userService.getUserUniqueByUserName(username); + // 校验用户是否存在 if (user == null) { createLoginLog(null, username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS); } - if (!userService.isPasswordMatch(password, user.getPassword())) { + // 校验机构有效性 + organService.validOrgan(user.getOrganId()); + // 校验密码 + String userPassword = user.getPassword(); + if (StringUtils.isNotEmpty(userPassword) && !userService.isPasswordMatch(password, userPassword)) { createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS); } @@ -105,6 +113,11 @@ public class AdminAuthServiceImpl implements AdminAuthService { createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.USER_DISABLED); throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_USER_DISABLED); } + // 校验没有密码并且没有传验证码,告诉前端需要验证码登录 + if (StringUtils.isEmpty(userPassword) && StringUtils.isEmpty(smsCaptchaVerification)) { + createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.FIRST_LOGIN); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_FIRST_LOGIN); + } return user; } @@ -114,7 +127,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { validateCaptcha(reqVO); // 使用账号密码,进行登录 - AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword(), reqVO.getOrganName()); + AdminUserDO user = authenticate(reqVO); // 如果 socialType 非空,说明需要绑定社交用户 if (reqVO.getSocialType() != null) { @@ -122,18 +135,36 @@ public class AdminAuthServiceImpl implements AdminAuthService { reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())); } Long organId = user.getOrganId(); - // 校验机构有效性 - organService.validOrgan(organId); OrganizationDO organ = organService.getOrgan(organId); String dataSourceCode = organ.getDataSourceCode(); // 校验机构数据源 if (StringUtils.isBlank(dataSourceCode)) { throw exception(ORGAN_DATA_CODE_NOT_EXISTS); } + // 验证并消耗验证码 + String smsCaptchaVerification = reqVO.getSmsCaptchaVerification(); + if (StringUtils.isNotEmpty(smsCaptchaVerification)) { + smsCodeService.useSmsCode(SmsCodeUseReqDTO.builder().mobile(user.getUsername()).code(smsCaptchaVerification).scene(SmsSceneEnum.USER_LOGIN_CAPTCHAVERIFICATION.getScene()).build()); + } // 创建 Token 令牌,记录登录日志 return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME,organ.getLarge(), dataSourceCode, user.getOrganId(), user.getNickname()); } + @Override + public boolean loginCheck(String mobile) { + // 查询账号 + AdminUserDO user = userService.getUserUniqueByUserName(mobile); + // 校验用户是否存在 + if (user == null) { + createLoginLog(null, mobile, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.BAD_CREDENTIALS); + return false; + } + if (StringUtils.isEmpty(user.getPassword())) { + return true; + } + return false; + } + @Override public void sendSmsCode(AuthSmsSendReqVO reqVO) { // 登录场景,验证是否存在 diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/oauth2/OAuth2GrantServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/oauth2/OAuth2GrantServiceImpl.java index 5154f2c6e..0bec5e061 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/oauth2/OAuth2GrantServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/oauth2/OAuth2GrantServiceImpl.java @@ -1,14 +1,12 @@ package com.cf.imes.module.system.service.oauth2; import cn.hutool.core.lang.Assert; +import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; import com.cf.imes.framework.common.enums.UserTypeEnum; -import com.cf.imes.framework.common.exception.ServerException; -import com.cf.imes.framework.organ.core.context.OrganContextHolder; +import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginReqVO; import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2CodeDO; -import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO; import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; import com.cf.imes.module.system.enums.ErrorCodeConstants; import com.cf.imes.module.system.service.auth.AdminAuthService; @@ -17,7 +15,6 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; -import java.util.Objects; import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -64,16 +61,16 @@ public class OAuth2GrantServiceImpl implements OAuth2GrantService { OAuth2CodeDO codeDO = oauth2CodeService.consumeAuthorizationCode(code); Assert.notNull(codeDO, "授权码不能为空"); // 防御性编程 // 校验 clientId 是否匹配 - if (!StrUtil.equals(clientId, codeDO.getClientId())) { + if (!CharSequenceUtil.equals(clientId, codeDO.getClientId())) { throw exception(ErrorCodeConstants.OAUTH2_GRANT_CLIENT_ID_MISMATCH); } // 校验 redirectUri 是否匹配 - if (!StrUtil.equals(redirectUri, codeDO.getRedirectUri())) { + if (!CharSequenceUtil.equals(redirectUri, codeDO.getRedirectUri())) { throw exception(ErrorCodeConstants.OAUTH2_GRANT_REDIRECT_URI_MISMATCH); } // 校验 state 是否匹配 - state = StrUtil.nullToDefault(state, ""); // 数据库 state 为 null 时,会设置为 "" 空串 - if (!StrUtil.equals(state, codeDO.getState())) { + state = CharSequenceUtil.nullToDefault(state, ""); // 数据库 state 为 null 时,会设置为 "" 空串 + if (!CharSequenceUtil.equals(state, codeDO.getState())) { throw exception(ErrorCodeConstants.OAUTH2_GRANT_STATE_MISMATCH); } @@ -91,7 +88,7 @@ public class OAuth2GrantServiceImpl implements OAuth2GrantService { @Override public OAuth2AccessTokenDO grantPassword(String username, String password, String clientId, List scopes) { // 使用账号 + 密码进行登录 - AdminUserDO user = adminAuthService.authenticate(username, password, null); + AdminUserDO user = adminAuthService.authenticate(AuthLoginReqVO.builder().username(username).password(password).build()); Assert.notNull(user, "用户不能为空!"); // 防御性编程 /*Long organId = OrganContextHolder.getOrganId(); OrganizationDO organ = organService.getOrgan(organId); diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsChannelService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsChannelService.java index 57ea2ae89..d6dc0d99b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsChannelService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsChannelService.java @@ -78,4 +78,11 @@ public interface SmsChannelService { */ SmsClient getSmsClient(String code); + /** + * 根据配置获得短信客户端 + * + * @param + * @return 短信客户端 + */ + SmsClient getSmsClient(); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsChannelServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsChannelServiceImpl.java index a7464a033..7c97daf3f 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsChannelServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsChannelServiceImpl.java @@ -6,7 +6,7 @@ import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.sms.core.client.SmsClient; import com.cf.imes.framework.sms.core.client.SmsClientFactory; -import com.cf.imes.framework.sms.core.property.SmsChannelProperties; +import com.cf.imes.framework.sms.core.property.SmsProperties; import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; import com.cf.imes.module.system.dal.dataobject.sms.SmsChannelDO; @@ -22,7 +22,6 @@ import javax.annotation.Resource; import java.time.Duration; import java.util.List; -import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.cf.imes.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; /** @@ -34,22 +33,28 @@ import static com.cf.imes.framework.common.util.cache.CacheUtils.buildAsyncReloa @Slf4j public class SmsChannelServiceImpl implements SmsChannelService { + @Resource + private SmsClientFactory smsClientFactory; + + @Resource + private SmsChannelMapper smsChannelMapper; + + @Resource + private SmsTemplateService smsTemplateService; + + @Resource + private SmsProperties smsProperties; + /** * {@link SmsClient} 缓存,通过它异步刷新 smsClientFactory */ @Getter private final LoadingCache idClientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L), - new CacheLoader() { + new CacheLoader<>() { @Override public SmsClient load(Long id) { - // 查询,然后尝试刷新 - SmsChannelDO channel = smsChannelMapper.selectById(id); - if (channel != null) { - SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class); - smsClientFactory.createOrUpdateSmsClient(properties); - } - return smsClientFactory.getSmsClient(id); + return smsClientFactory.getSmsClient(smsProperties); } }); @@ -59,30 +64,15 @@ public class SmsChannelServiceImpl implements SmsChannelService { */ @Getter private final LoadingCache codeClientCache = buildAsyncReloadingCache(Duration.ofSeconds(60L), - new CacheLoader() { + new CacheLoader<>() { @Override public SmsClient load(String code) { - // 查询,然后尝试刷新 - SmsChannelDO channel = smsChannelMapper.selectByCode(code); - if (channel != null) { - SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class); - smsClientFactory.createOrUpdateSmsClient(properties); - } - return smsClientFactory.getSmsClient(code); + return smsClientFactory.getSmsClient(smsProperties); } }); - @Resource - private SmsClientFactory smsClientFactory; - - @Resource - private SmsChannelMapper smsChannelMapper; - - @Resource - private SmsTemplateService smsTemplateService; - @Override public Long createSmsChannel(SmsChannelSaveReqVO createReqVO) { SmsChannelDO channel = BeanUtils.toBean(createReqVO, SmsChannelDO.class); @@ -160,7 +150,12 @@ public class SmsChannelServiceImpl implements SmsChannelService { @Override public SmsClient getSmsClient(String code) { - return codeClientCache.getUnchecked(code); + return smsClientFactory.getSmsClient(smsProperties); + } + + @Override + public SmsClient getSmsClient() { + return smsClientFactory.getSmsClient(smsProperties); } } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeServiceImpl.java index dbcc31a34..7c93141e2 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsCodeServiceImpl.java @@ -3,24 +3,29 @@ package com.cf.imes.module.system.service.sms; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import com.cf.imes.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; import com.cf.imes.module.system.dal.dataobject.sms.SmsCodeDO; +import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; import com.cf.imes.module.system.dal.mysql.sms.SmsCodeMapper; +import com.cf.imes.module.system.dal.redis.RedisKeyConstants; import com.cf.imes.module.system.enums.sms.SmsSceneEnum; import com.cf.imes.module.system.framework.sms.SmsCodeProperties; import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; import com.cf.imes.module.system.enums.ErrorCodeConstants; +import com.cf.imes.module.system.service.user.AdminUserService; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.time.Duration; import java.time.LocalDateTime; +import java.util.HashMap; import static cn.hutool.core.util.RandomUtil.randomInt; -import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; -import static com.cf.imes.framework.common.util.date.DateUtils.isToday; /** * 短信验证码 Service 实现类 @@ -40,49 +45,118 @@ public class SmsCodeServiceImpl implements SmsCodeService { @Resource private SmsSendService smsSendService; + @Resource + private RedisTemplate redisTemplate; + + @Resource + private AdminUserService userService; + @Override public void sendSmsCode(SmsCodeSendReqDTO reqDTO) { + // 非修改手机号的场景时校验手机号是否存在 + AdminUserDO user = userService.getUserByUsernameAndOrganId(reqDTO.getMobile(), null); + if (ObjectUtil.isNull(user) && ObjectUtil.notEqual(SmsSceneEnum.USER_UPDATE_MOBILE.getScene(), reqDTO.getScene())) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_MOBILE_NOT_EXISTS); + } SmsSceneEnum sceneEnum = SmsSceneEnum.getCodeByScene(reqDTO.getScene()); Assert.notNull(sceneEnum, "验证码场景({}) 查找不到配置", reqDTO.getScene()); // 创建验证码 - String code = createSmsCode(reqDTO.getMobile(), reqDTO.getScene(), reqDTO.getCreateIp()); + String code = createSmsCode(reqDTO.getMobile(), reqDTO.getCreateIp()); // 发送验证码 + HashMap map = MapUtil.of("code", code); + map.put("product","晨丰科技"); smsSendService.sendSingleSms(reqDTO.getMobile(), null, null, - sceneEnum.getTemplateCode(), MapUtil.of("code", code)); + sceneEnum.getTemplateCode(), map); } - private String createSmsCode(String mobile, Integer scene, String ip) { - // 校验是否可以发送验证码,不用筛选场景 - SmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, null, null); - if (lastSmsCode != null) { - if (LocalDateTimeUtil.between(lastSmsCode.getCreateTime(), LocalDateTime.now()).toMillis() - < smsCodeProperties.getSendFrequency().toMillis()) { // 发送过于频繁 + /** + * 生成验证码 + * + * @param mobile 手机号 + * @param ip 请求来源ip + * @return + */ + private String createSmsCode(String mobile, String ip) { + String redisMobileKey = String.format(RedisKeyConstants.SMS_CAPTCHA_VERIFICATION, mobile); + String redisMobileCountKey = String.format(RedisKeyConstants.SMS_CAPTCHA_VERIFICATION_LIMIT, mobile); + String redisIpCountKey = String.format(RedisKeyConstants.SMS_CAPTCHA_VERIFICATION_LIMIT, ip); + boolean hasCode = redisTemplate.hasKey(redisMobileKey); + if (!hasCode) { + // 验证码不存在 + Duration sendWindowSizeMin = smsCodeProperties.getSendWindowSizeMin(); + Integer sendMaxSendTimesPerWindow = smsCodeProperties.getSendMaxSendTimesPerWindow(); + // 限制手机号请求次数:10分钟5次 + boolean mobileCountRateLimit = slidingWindowRateLimit(redisMobileCountKey, sendWindowSizeMin.toMinutesPart(), sendMaxSendTimesPerWindow); + if (!mobileCountRateLimit) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CODE_SEND_TOO_FAST); } - if (isToday(lastSmsCode.getCreateTime()) && // 必须是今天,才能计算超过当天的上限 - lastSmsCode.getTodayIndex() >= smsCodeProperties.getSendMaximumQuantityPerDay()) { // 超过当天发送的上限。 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY); + // 限制ip请求次数 + boolean ipCountRateLimit = slidingWindowRateLimit(redisIpCountKey, sendWindowSizeMin.toMinutesPart(), sendMaxSendTimesPerWindow); + if (!ipCountRateLimit) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CODE_SEND_TOO_FAST); } - // TODO 晨丰:提升,每个 IP 每天可发送数量 - // TODO 晨丰:提升,每个 IP 每小时可发送数量 + } else { + // 验证码存在提示请勿重复发送 + throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CODE_IS_VALID); } - // 创建验证码记录 - String code = String.valueOf(randomInt(smsCodeProperties.getBeginCode(), smsCodeProperties.getEndCode() + 1)); - SmsCodeDO newSmsCode = SmsCodeDO.builder().mobile(mobile).code(code).scene(scene) - .todayIndex(lastSmsCode != null && isToday(lastSmsCode.getCreateTime()) ? lastSmsCode.getTodayIndex() + 1 : 1) - .createIp(ip).used(false).build(); - smsCodeMapper.insert(newSmsCode); - return code; + // 生成6位随机验证码 + StringBuffer code = new StringBuffer(6); + for (int i = 0; i < 6; i++) { + code.append(randomInt(0, 9)); + } + return code.toString(); + } + + /** + * 滑动窗口限制发送次数 + * + * @param key + * @param winSizeMin 窗口时间大小 + * @param maxSendTimesPerWin 窗口内最大请求次数 + * @return false没有达到发送频繁告警要求 + */ + public boolean slidingWindowRateLimit(String key, int winSizeMin, int maxSendTimesPerWin) { + // 获取当前时间戳 + long currentTime = System.currentTimeMillis(); + + // 清除过期的时间片 + redisTemplate.opsForZSet().removeRangeByScore(key, 0L, currentTime - (winSizeMin * 60 * 1000)); + + // 检查过去 winSizeMin 分钟内的请求次数 + long requestCount = redisTemplate.opsForZSet().zCard(key); + if (requestCount >= maxSendTimesPerWin) { + return false; + } + + // 窗口足够添加当前请求的时间戳 + redisTemplate.opsForZSet().add(key, currentTime, currentTime); + + return true; } @Override public void useSmsCode(SmsCodeUseReqDTO reqDTO) { - // 检测验证码是否有效 - SmsCodeDO lastSmsCode = validateSmsCode0(reqDTO.getMobile(), reqDTO.getCode(), reqDTO.getScene()); - // 使用验证码 - smsCodeMapper.updateById(SmsCodeDO.builder().id(lastSmsCode.getId()) - .used(true).usedTime(LocalDateTime.now()).usedIp(reqDTO.getUsedIp()).build()); + // 非修改手机号的场景时校验手机号是否存在 + AdminUserDO user = userService.getUserByUsernameAndOrganId(reqDTO.getMobile(), null); + if (ObjectUtil.isNull(user) && ObjectUtil.notEqual(SmsSceneEnum.USER_UPDATE_MOBILE.getScene(), reqDTO.getScene())) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_MOBILE_NOT_EXISTS); + } + String smsCodeKey = String.format(RedisKeyConstants.SMS_CAPTCHA_VERIFICATION, reqDTO.getMobile()); + Object keyObj = redisTemplate.opsForValue().get(smsCodeKey); + if (ObjectUtil.isNotNull(keyObj)) { + // 校验码存在 + if (ObjectUtil.notEqual(String.valueOf(keyObj), reqDTO.getCode())) { + // 验证码不正确 + throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CODE_NOT_CORRECT); + } else { + // 消耗验证码 + redisTemplate.delete(smsCodeKey); + } + } else { + // 提示验证码不存在 + throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CODE_NOT_FOUND); + } } @Override diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsLogService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsLogService.java index c76849e3d..288e30f82 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsLogService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsLogService.java @@ -40,10 +40,11 @@ public interface SmsLogService { * @param apiSendMsg 短信 API 发送失败的提示 * @param apiRequestId 短信 API 发送返回的唯一请求 ID * @param apiSerialNo 短信 API 发送返回的序号 + * @param channelCode 短信 API 渠道编码 */ void updateSmsSendResult(Long id, Boolean success, String apiSendCode, String apiSendMsg, - String apiRequestId, String apiSerialNo); + String apiRequestId, String apiSerialNo, String channelCode); /** * 更新日志的接收结果 diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsLogServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsLogServiceImpl.java index 650f92490..d03f445d3 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsLogServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsLogServiceImpl.java @@ -40,8 +40,6 @@ public class SmsLogServiceImpl implements SmsLogService { logBuilder.templateId(template.getId()).templateCode(template.getCode()).templateType(template.getType()); logBuilder.templateContent(templateContent).templateParams(templateParams) .apiTemplateId(template.getApiTemplateId()); - // 设置渠道相关字段 - logBuilder.channelId(template.getChannelId()).channelCode(template.getChannelCode()); // 设置接收相关字段 logBuilder.receiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); @@ -54,12 +52,12 @@ public class SmsLogServiceImpl implements SmsLogService { @Override public void updateSmsSendResult(Long id, Boolean success, String apiSendCode, String apiSendMsg, - String apiRequestId, String apiSerialNo) { + String apiRequestId, String apiSerialNo, String channelCode) { SmsSendStatusEnum sendStatus = success ? SmsSendStatusEnum.SUCCESS : SmsSendStatusEnum.FAILURE; smsLogMapper.updateById(SmsLogDO.builder().id(id) .sendStatus(sendStatus.getStatus()).sendTime(LocalDateTime.now()) .apiSendCode(apiSendCode).apiSendMsg(apiSendMsg) - .apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).build()); + .apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).channelCode(channelCode).build()); } @Override diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsSendServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsSendServiceImpl.java index e44a5687d..de56919f6 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsSendServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsSendServiceImpl.java @@ -3,7 +3,6 @@ package com.cf.imes.module.system.service.sms; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.StrUtil; import com.cf.imes.framework.common.core.KeyValue; import com.cf.imes.framework.common.enums.CommonStatusEnum; import com.cf.imes.framework.common.enums.UserTypeEnum; @@ -12,16 +11,17 @@ import com.cf.imes.framework.datapermission.core.annotation.DataPermission; import com.cf.imes.framework.sms.core.client.SmsClient; import com.cf.imes.framework.sms.core.client.dto.SmsReceiveRespDTO; import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; -import com.cf.imes.module.system.dal.dataobject.sms.SmsChannelDO; import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO; import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; import com.cf.imes.module.system.mq.message.sms.SmsSendMessage; import com.cf.imes.module.system.mq.producer.sms.SmsProducer; import com.cf.imes.module.system.service.member.MemberService; +import com.cf.imes.module.system.service.sms.handler.SmsSendAfterSendHandler; import com.cf.imes.module.system.service.user.AdminUserService; import com.cf.imes.module.system.enums.ErrorCodeConstants; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -29,8 +29,6 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; - /** * 短信发送 Service 发送的实现 * @@ -54,11 +52,14 @@ public class SmsSendServiceImpl implements SmsSendService { @Resource private SmsProducer smsProducer; + @Resource + private List smsSendAfterSendHandlers; + @Override @DataPermission(enable = false) // 发送短信时,无需考虑数据权限 public Long sendSingleSmsToAdmin(String mobile, Long userId, String templateCode, Map templateParams) { // 如果 mobile 为空,则加载用户编号对应的手机号 - if (StrUtil.isEmpty(mobile)) { + if (StringUtils.isEmpty(mobile)) { AdminUserDO user = adminUserService.getUser(userId); if (user != null) { mobile = user.getMobile(); @@ -71,7 +72,7 @@ public class SmsSendServiceImpl implements SmsSendService { @Override public Long sendSingleSmsToMember(String mobile, Long userId, String templateCode, Map templateParams) { // 如果 mobile 为空,则加载用户编号对应的手机号 - if (StrUtil.isEmpty(mobile)) { + if (StringUtils.isEmpty(mobile)) { mobile = memberService.getMemberUserMobile(userId); } // 执行发送 @@ -83,8 +84,6 @@ public class SmsSendServiceImpl implements SmsSendService { String templateCode, Map templateParams) { // 校验短信模板是否合法 SmsTemplateDO template = validateSmsTemplate(templateCode); - // 校验短信渠道是否合法 - SmsChannelDO smsChannel = validateSmsChannel(template.getChannelId()); // 校验手机号码是否存在 mobile = validateMobile(mobile); @@ -92,30 +91,17 @@ public class SmsSendServiceImpl implements SmsSendService { List> newTemplateParams = buildTemplateParams(template, templateParams); // 创建发送日志。如果模板被禁用,则不发送短信,只记录日志 - Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus()) - && CommonStatusEnum.ENABLE.getStatus().equals(smsChannel.getStatus()); + Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus()); String content = smsTemplateService.formatSmsTemplateContent(template.getContent(), templateParams); Long sendLogId = smsLogService.createSmsLog(mobile, userId, userType, isSend, template, content, templateParams); // 发送 MQ 消息,异步执行发送短信 if (isSend) { - smsProducer.sendSmsSendMessage(sendLogId, mobile, template.getChannelId(), - template.getApiTemplateId(), newTemplateParams); + smsProducer.sendSmsSendMessage(sendLogId, mobile, template, newTemplateParams); } return sendLogId; } - @VisibleForTesting - SmsChannelDO validateSmsChannel(Long channelId) { - // 获得短信模板。考虑到效率,从缓存中获取 - SmsChannelDO channelDO = smsChannelService.getSmsChannel(channelId); - // 短信模板不存在 - if (channelDO == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS); - } - return channelDO; - } - @VisibleForTesting SmsTemplateDO validateSmsTemplate(String templateCode) { // 获得短信模板。考虑到效率,从缓存中获取 @@ -149,7 +135,7 @@ public class SmsSendServiceImpl implements SmsSendService { @VisibleForTesting public String validateMobile(String mobile) { - if (StrUtil.isEmpty(mobile)) { + if (StringUtils.isEmpty(mobile)) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_SEND_MOBILE_NOT_EXISTS); } return mobile; @@ -158,19 +144,29 @@ public class SmsSendServiceImpl implements SmsSendService { @Override public void doSendSms(SmsSendMessage message) { // 获得渠道对应的 SmsClient 客户端 - SmsClient smsClient = smsChannelService.getSmsClient(message.getChannelId()); + SmsClient smsClient = smsChannelService.getSmsClient(); Assert.notNull(smsClient, "短信客户端({}) 不存在", message.getChannelId()); + + List> templateParams = message.getTemplateParams(); + String channelCode = null; // 发送短信 try { SmsSendRespDTO sendResponse = smsClient.sendSms(message.getLogId(), message.getMobile(), - message.getApiTemplateId(), message.getTemplateParams()); + message.getApiTemplateId(), templateParams); + channelCode = sendResponse.getChannelCode(); + // 发送成功后操作 + for (SmsSendAfterSendHandler afterSendHandler : smsSendAfterSendHandlers) { + if (afterSendHandler.checkTemplateType(message.getTemplateType())) { + afterSendHandler.afterSend(sendResponse, templateParams); + } + } smsLogService.updateSmsSendResult(message.getLogId(), sendResponse.getSuccess(), sendResponse.getApiCode(), sendResponse.getApiMsg(), - sendResponse.getApiRequestId(), sendResponse.getSerialNo()); + sendResponse.getApiRequestId(), sendResponse.getSerialNo(), channelCode); } catch (Throwable ex) { log.error("[doSendSms][发送短信异常,日志编号({})]", message.getLogId(), ex); smsLogService.updateSmsSendResult(message.getLogId(), false, - "EXCEPTION", ExceptionUtil.getRootCauseMessage(ex), null, null); + "EXCEPTION", ExceptionUtil.getRootCauseMessage(ex), null, null, channelCode); } } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsTemplateServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsTemplateServiceImpl.java index ab9995331..0989f9875 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsTemplateServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsTemplateServiceImpl.java @@ -165,7 +165,7 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { @VisibleForTesting void validateApiTemplate(Long channelId, String apiTemplateId) { // 获得短信模板 - SmsClient smsClient = smsChannelService.getSmsClient(channelId); + SmsClient smsClient = smsChannelService.getSmsClient(); Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", channelId)); SmsTemplateRespDTO template; try { diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/SmsSendAfterSendHandler.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/SmsSendAfterSendHandler.java new file mode 100644 index 000000000..897635319 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/SmsSendAfterSendHandler.java @@ -0,0 +1,25 @@ +package com.cf.imes.module.system.service.sms.handler; + +import com.cf.imes.framework.common.core.KeyValue; +import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; + +import java.util.List; + +/** + * 短信发送后处理器接口 + * + * @author Gqr + * @since 2024/8/12 18:42 + */ +public interface SmsSendAfterSendHandler { + /** + * 校验消息模板类型 + * + * @param templateType + * @return + */ + boolean checkTemplateType(Integer templateType); + + + void afterSend(SmsSendRespDTO sendResponse, List> params); +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/impl/SmsSendAfterSendHandlerImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/impl/SmsSendAfterSendHandlerImpl.java new file mode 100644 index 000000000..37b488055 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/impl/SmsSendAfterSendHandlerImpl.java @@ -0,0 +1,46 @@ +package com.cf.imes.module.system.service.sms.handler.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.cf.imes.framework.common.core.KeyValue; +import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; +import com.cf.imes.module.system.dal.redis.RedisKeyConstants; +import com.cf.imes.module.system.enums.sms.SmsTemplateTypeEnum; +import com.cf.imes.module.system.framework.sms.SmsCodeProperties; +import com.cf.imes.module.system.service.sms.handler.SmsSendAfterSendHandler; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author Gqr + * @since 2024/8/12 18:49 + */ +@Service +public class SmsSendAfterSendHandlerImpl implements SmsSendAfterSendHandler { + + @Resource + private RedisTemplate redisTemplate; + + @Resource + private SmsCodeProperties smsCodeProperties; + + @Override + public boolean checkTemplateType(Integer templateType) { + SmsTemplateTypeEnum smsTemplateTypeEnum = SmsTemplateTypeEnum.valueOf(templateType); + return ObjectUtil.isNotNull(smsTemplateTypeEnum); + } + + @Override + public void afterSend(SmsSendRespDTO sendResponse, List> params) { + // 发送成功把验证码存入redis + if (sendResponse.getSuccess()) { + for (KeyValue keyValue : params) { + if ("code".equals(keyValue.getKey())) { + redisTemplate.opsForValue().set(String.format(RedisKeyConstants.SMS_CAPTCHA_VERIFICATION, sendResponse.getMobile()), keyValue.getValue(), smsCodeProperties.getExpireTimes()); + } + } + } + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserService.java index 44cfb5c61..5e524384b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserService.java @@ -4,11 +4,13 @@ import cn.hutool.core.collection.CollUtil; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.util.collection.CollectionUtils; import com.cf.imes.module.system.api.user.dto.OrganAdminUserRespDTO; +import com.cf.imes.module.system.controller.admin.user.vo.profile.UserMobileUpdateReqVO; import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; import com.cf.imes.module.system.controller.admin.user.vo.user.UserImportExcelVO; import com.cf.imes.module.system.controller.admin.user.vo.user.UserImportRespVO; import com.cf.imes.module.system.controller.admin.user.vo.user.UserPageReqVO; +import com.cf.imes.module.system.controller.admin.user.vo.user.UserResetPasswordReqVO; import com.cf.imes.module.system.controller.admin.user.vo.user.UserSaveReqVO; import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; @@ -71,7 +73,7 @@ public interface AdminUserService { * @param id 用户 id * @param avatarFile 头像文件 */ - String updateUserAvatar(Long id, InputStream avatarFile) throws Exception; + String updateUserAvatar(Long id, InputStream avatarFile); /** * 修改密码 @@ -81,6 +83,13 @@ public interface AdminUserService { */ void updateUserPassword(Long id, String password); + /** + * 重置密码 + * + * @param reqVO + */ + void resetUserPassword(UserResetPasswordReqVO reqVO); + /** * 修改状态 * @@ -113,6 +122,14 @@ public interface AdminUserService { */ AdminUserDO getUserByUsernameAndOrganId(String username, Long organId); + /** + * 用户名查询唯一用户 + * + * @param userName + * @return + */ + AdminUserDO getUserUniqueByUserName(String userName); + /** * 通过手机号获取用户 * @@ -242,4 +259,12 @@ public interface AdminUserService { * 用户活跃数统计 */ Map userActTotal(); + + /** + * 修改密保手机 + * + * @param id 用户编号 + * @param reqVO 用户个人信息 + */ + void updateUserSecurityPhone(Long id, @Valid UserMobileUpdateReqVO reqVO); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserServiceImpl.java index 42e949da7..4c218da84 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/user/AdminUserServiceImpl.java @@ -4,13 +4,17 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.cf.imes.framework.common.enums.CommonStatusEnum; +import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.util.collection.CollectionUtils; +import com.cf.imes.framework.common.util.monitor.TracerUtils; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.common.util.pinyin.PinYinUtils; +import com.cf.imes.framework.common.util.servlet.ServletUtils; import com.cf.imes.framework.datapermission.core.util.DataPermissionUtils; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.mybatis.core.query.MPJLambdaWrapperX; @@ -18,13 +22,17 @@ import com.cf.imes.framework.organ.core.aop.OrganIgnore; import com.cf.imes.framework.organ.core.context.OrganContextHolder; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.infra.api.file.FileApi; +import com.cf.imes.module.system.api.logger.dto.LoginLogCreateReqDTO; +import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import com.cf.imes.module.system.api.user.dto.OrganAdminUserRespDTO; import com.cf.imes.module.system.constants.permission.InternalRoleConstants; +import com.cf.imes.module.system.controller.admin.user.vo.profile.UserMobileUpdateReqVO; import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; import com.cf.imes.module.system.controller.admin.user.vo.user.UserImportExcelVO; import com.cf.imes.module.system.controller.admin.user.vo.user.UserImportRespVO; import com.cf.imes.module.system.controller.admin.user.vo.user.UserPageReqVO; +import com.cf.imes.module.system.controller.admin.user.vo.user.UserResetPasswordReqVO; import com.cf.imes.module.system.controller.admin.user.vo.user.UserSaveReqVO; import com.cf.imes.module.system.dal.dataobject.dept.DeptDO; import com.cf.imes.module.system.dal.dataobject.dept.UserPostDO; @@ -32,11 +40,16 @@ import com.cf.imes.module.system.dal.dataobject.permission.UserRoleDO; import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; import com.cf.imes.module.system.dal.mysql.dept.UserPostMapper; import com.cf.imes.module.system.dal.mysql.user.AdminUserMapper; +import com.cf.imes.module.system.enums.logger.LoginLogTypeEnum; +import com.cf.imes.module.system.enums.logger.LoginResultEnum; +import com.cf.imes.module.system.enums.sms.SmsSceneEnum; import com.cf.imes.module.system.service.dept.DeptService; import com.cf.imes.module.system.service.dept.PostService; +import com.cf.imes.module.system.service.logger.LoginLogService; import com.cf.imes.module.system.service.permission.PermissionService; import com.cf.imes.module.system.service.organ.OrganService; import com.cf.imes.module.system.enums.ErrorCodeConstants; +import com.cf.imes.module.system.service.sms.SmsCodeService; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -58,6 +71,7 @@ import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.e import static com.cf.imes.framework.common.util.collection.CollectionUtils.convertList; import static com.cf.imes.framework.common.util.collection.CollectionUtils.convertSet; import static com.cf.imes.module.system.enums.ErrorCodeConstants.USER_ME_ERROR; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.USER_OPERATE_SELF_STATUS_ERROR; /** * 后台用户 Service 实现类 @@ -92,6 +106,12 @@ public class AdminUserServiceImpl implements AdminUserService { @Resource private FileApi fileApi; + @Resource + private SmsCodeService smsCodeService; + + @Resource + private LoginLogService loginLogService; + // 定义密码校验的正则表达式 private static final String LENGTH_PATTERN = ".{6,}"; @@ -110,15 +130,15 @@ public class AdminUserServiceImpl implements AdminUserService { throw ServiceExceptionUtil.exception(ErrorCodeConstants.USER_COUNT_MAX, organ.getAccountCount()); } }); + // 校验正确性 - validateUserForCreateOrUpdate(null, createReqVO.getUsername(), - createReqVO.getMobile(), createReqVO.getEmail(), createReqVO.getDeptId(), createReqVO.getPostIds(),createReqVO.getPassword(), organId); + validateUserForCreateOrUpdate(null, createReqVO.getMobile(), + createReqVO.getEmail(), createReqVO.getDeptId(), createReqVO.getPostIds(), null, organId); // 插入用户 AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class); + // 改造:手机号直接当做用户名 + user.setUsername(createReqVO.getMobile()); user.setOrganId(createReqVO.getOrganId()); - //user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 - user.setPassword(encodePassword(createReqVO.getPassword())); // 加密密码 - String pinyinFull = PinYinUtils.convertToPinyin(user.getNickname()); if (StringUtils.isNotBlank(pinyinFull)) { pinyinFull = pinyinFull.replace(" ", ""); @@ -138,12 +158,12 @@ public class AdminUserServiceImpl implements AdminUserService { @Transactional(rollbackFor = Exception.class) public void updateUser(UserSaveReqVO updateReqVO) { Long organId = updateReqVO.getOrganId() == null ? OrganContextHolder.getOrganId(): updateReqVO.getOrganId(); - updateReqVO.setPassword(null); // 特殊:此处不更新密码 - // 不允许自身操作 - checkCurrentWhenOperate(updateReqVO.getId()); + String mobile = updateReqVO.getMobile(); + // 不允许关闭自身状态 + checkCurrentWhenOperateStatus(updateReqVO.getId(), updateReqVO.getStatus()); // 校验正确性 - validateUserForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getUsername(), - updateReqVO.getMobile(), updateReqVO.getEmail(), updateReqVO.getDeptId(), updateReqVO.getPostIds(),null, organId); + validateUserForCreateOrUpdate(updateReqVO.getId(), mobile, + updateReqVO.getEmail(), updateReqVO.getDeptId(), updateReqVO.getPostIds(), null, organId); // 更新用户 AdminUserDO updateObj = BeanUtils.toBean(updateReqVO, AdminUserDO.class); @@ -156,7 +176,16 @@ public class AdminUserServiceImpl implements AdminUserService { updateObj.setPinyinFull(pinyinFull); updateObj.setPinyinInitial(PinYinUtils.convertFirstChar(updateReqVO.getNickname())); } - + Long id = updateObj.getId(); + if (ObjectUtil.isNotNull(id)) { + AdminUserDO adminUserDO = userMapper.selectByIdForUpdate(id); + // 当手机号(账号)发生改变时,清空密码 + if (ObjectUtil.isNotNull(adminUserDO) && !Objects.equals(adminUserDO.getUsername(), mobile)) { + // 清空密码 + updateObj.setPassword(""); + updateObj.setUsername(mobile); + } + } userMapper.updateById(updateObj); // 更新岗位 updateUserPost(updateReqVO, updateObj); @@ -190,7 +219,7 @@ public class AdminUserServiceImpl implements AdminUserService { // 校验正确性 validateUserExists(id); validateEmailUnique(id, reqVO.getEmail(), organId); - validateMobileUnique(id, reqVO.getMobile(), organId); + validateMobileUnique(id, reqVO.getMobile()); // 执行更新 userMapper.updateById(BeanUtils.toBean(reqVO, AdminUserDO.class).setId(id)); } @@ -231,6 +260,46 @@ public class AdminUserServiceImpl implements AdminUserService { userMapper.updateById(updateObj); } + @Override + @Transactional(rollbackFor = Exception.class) + public void resetUserPassword(UserResetPasswordReqVO reqVO) { + String mobile = reqVO.getMobile(); + String password = reqVO.getPassword(); + // 校验用户名 + AdminUserDO adminUserDO = validateUserNameExists(mobile); + Long userId = adminUserDO.getId(); + String username = adminUserDO.getUsername(); + // 校验密码 + validatePassword(password); + // 更新密码 + AdminUserDO updateObj = new AdminUserDO(); + updateObj.setId(userId); + updateObj.setPassword(encodePassword(password)); // 加密密码 + userMapper.updateById(updateObj); + + // 记录日志 + createLoginLog(userId, username, LoginLogTypeEnum.LOGIN_FORGET_PWD, LoginResultEnum.SUCCESS); + // 消耗验证码 + smsCodeService.useSmsCode(SmsCodeUseReqDTO.builder() + .mobile(mobile).code(reqVO.getSmsCaptchaVerification()).scene(SmsSceneEnum.USER_RESET_PASSWORD.getScene()) + .build()); + } + + private void createLoginLog(Long userId, String username, + LoginLogTypeEnum logTypeEnum, LoginResultEnum loginResult) { + // 插入登录日志 + LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO(); + reqDTO.setLogType(logTypeEnum.getType()); + reqDTO.setTraceId(TracerUtils.getTraceId()); + reqDTO.setUserId(userId); + reqDTO.setUserType(UserTypeEnum.ADMIN.getValue()); + reqDTO.setUsername(username); + reqDTO.setUserAgent(ServletUtils.getUserAgent()); + reqDTO.setUserIp(ServletUtils.getClientIP()); + reqDTO.setResult(loginResult.getResult()); + loginLogService.createLoginLog(reqDTO); + } + @Override public void updateUserStatus(Long id, Integer status) { // 不允许自身操作 @@ -269,10 +338,15 @@ public class AdminUserServiceImpl implements AdminUserService { public AdminUserDO getUserByUsernameAndOrganId(String username, Long organId) { return userMapper.selectOne(new LambdaQueryWrapperX() .eq(AdminUserDO::getUsername, username) - .eq(AdminUserDO::getOrganId, organId) + .eqIfPresent(AdminUserDO::getOrganId, organId) ); } + @Override + public AdminUserDO getUserUniqueByUserName(String userName) { + return userMapper.selectByUsernameUnique(userName); + } + @Override public AdminUserDO getUserByMobile(String mobile) { return userMapper.selectByMobile(mobile); @@ -363,7 +437,7 @@ public class AdminUserServiceImpl implements AdminUserService { return deptIds; } - private void validateUserForCreateOrUpdate(Long id, String username, String mobile, String email, + private void validateUserForCreateOrUpdate(Long id, String username, String email, Long deptId, Set postIds,String password ,Long organId) { // 关闭数据权限,避免因为没有数据权限,查询不到数据,进而导致唯一校验不正确 DataPermissionUtils.executeIgnore(() -> { @@ -375,8 +449,6 @@ public class AdminUserServiceImpl implements AdminUserService { validateUserExists(id); // 校验用户名唯一 validateUsernameUnique(id, username, organId); - // 校验手机号唯一 - validateMobileUnique(id, mobile, organId); // 校验邮箱唯一 validateEmailUnique(id, email, organId); // 校验部门处于开启状态 @@ -420,11 +492,21 @@ public class AdminUserServiceImpl implements AdminUserService { } @VisibleForTesting + private AdminUserDO validateUserNameExists(String userName) { + AdminUserDO user = userMapper.selectByUsernameUnique(userName); + if (user == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.USER_NOT_EXISTS); + } + return user; + } + + @VisibleForTesting + @OrganIgnore void validateUsernameUnique(Long id, String username, Long organId) { if (StringUtils.isBlank(username)) { return; } - AdminUserDO user = userMapper.selectOne(AdminUserDO::getUsername, username, AdminUserDO::getOrganId, organId); + AdminUserDO user = userMapper.selectOne(AdminUserDO::getUsername, username); if (user == null) { return; } @@ -456,11 +538,12 @@ public class AdminUserServiceImpl implements AdminUserService { } @VisibleForTesting - void validateMobileUnique(Long id, String mobile, Long organId) { + @OrganIgnore + void validateMobileUnique(Long id, String mobile) { if (StringUtils.isBlank(mobile)) { return; } - AdminUserDO user = userMapper.selectOne(AdminUserDO::getOrganId, organId, AdminUserDO::getMobile, mobile); + AdminUserDO user = userMapper.selectOne(AdminUserDO::getUsername, mobile); if (user == null) { return; } @@ -501,7 +584,7 @@ public class AdminUserServiceImpl implements AdminUserService { importUsers.forEach(importUser -> { // 校验,判断是否有不符合的原因 try { - validateUserForCreateOrUpdate(null, null, importUser.getMobile(), importUser.getEmail(), + validateUserForCreateOrUpdate(null, null, importUser.getEmail(), importUser.getDeptId(), null,null, organId); } catch (ServiceException ex) { respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage()); @@ -510,6 +593,8 @@ public class AdminUserServiceImpl implements AdminUserService { // 判断如果不存在,在进行插入 AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername(), organId); if (existUser == null) { + // 改造:手机号直接当做用户名 + importUser.setUsername(importUser.getMobile()); userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class) .setPassword(encodePassword(userInitPassword)).setPostIds(new HashSet<>())); // 设置默认密码及空岗位编号数组 respVO.getCreateUsernames().add(importUser.getUsername()); @@ -563,6 +648,24 @@ public class AdminUserServiceImpl implements AdminUserService { return organAdminUserRespDTOS; } + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUserSecurityPhone(Long id, UserMobileUpdateReqVO reqVO) { + String mobile = reqVO.getMobile(); + // 校验手机号唯一 + validateMobileUnique(id, mobile); + + // 新手机号入库 -> setUsername + userMapper.update(new LambdaUpdateWrapper() + .set(AdminUserDO::getUsername, mobile) + .eq(AdminUserDO::getId, id)); + + // 校验和消耗验证码 + smsCodeService.useSmsCode(SmsCodeUseReqDTO.builder() + .mobile(reqVO.getMobile()).code(reqVO.getSmsCaptchaVerification()).scene(SmsSceneEnum.USER_UPDATE_MOBILE.getScene()) + .build()); + } + /** * 对密码进行加密 * @@ -582,6 +685,12 @@ public class AdminUserServiceImpl implements AdminUserService { } } + private void checkCurrentWhenOperateStatus(Long userId, Integer status) { + if (ObjectUtil.equal(userId, SecurityFrameworkUtils.getLoginUserId()) && Objects.equals(CommonStatusEnum.DISABLE.getStatus(), status)) { + throw exception(USER_OPERATE_SELF_STATUS_ERROR); + } + } + @Override public Map userTotal() { Map map = new HashMap<>(); diff --git a/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml b/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml index eddbc4904..13d7cee08 100644 --- a/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml +++ b/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml @@ -159,6 +159,9 @@ chenfeng: - /admin-api/system/data-source/* - /admin-api/system/auth/login - /admin-api/system/auth/logout + - /admin-api/system/auth/sms-code + - /admin-api/system/user/reset-password + - /admin-api/system/auth/check - /rpc-api/** #- /admin-api/system/** #- /rpc-api/system/organ/valid # 防止递归。避免调用 /rpc-api/system/organ/valid 接口时,又去触发 /rpc-api/system/organ/valid 去校验 @@ -193,10 +196,19 @@ chenfeng: use-data-code: imes_prod #动态数据源标识,后期添加的数据源需要修改此值 sms-code: # 短信验证码相关的配置项 - expire-times: 10m + expire-times: 5m send-frequency: 1m send-maximum-quantity-per-day: 10 + send-max-send-times-per-window: 5 #窗口最大请求次数 + send-window-size-min: 10m #窗口时间 begin-code: 9999 # 这里配置 9999 的原因是,测试方便。 end-code: 9999 # 这里配置 9999 的原因是,测试方便。 - + sms: + channel: DEBUG_DING_TALK + signature: + apiKey: 28PlJanD0aJLMyMLuH6JI5oVj1/j5ZNGvZPx/zguEvJl02PdrbWe5yIV4s1RSD3CDX9obUhITNlc6glW7MNJq03N7H/v50MFgN4f8mK1oAA= + apiSecret: O6Yk9gT3xQ9fqSKFuZa9I4bWOULCw2syH4/a1OrD2W7BAE2aQ+bSgqLXfBJT+de0GKHKgjuPNv0v+sDKkizLP22gsYIhdn/3OPSvyJF7Tng= + encrypt: + enable: false + publicKey: cfimes debug: false diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImplTest.java index 3d8a0d8c5..99d651035 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImplTest.java @@ -5,20 +5,14 @@ import com.cf.imes.framework.common.enums.CommonStatusEnum; import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.test.core.ut.BaseDbUnitTest; import com.cf.imes.module.system.api.sms.SmsCodeApi; -import com.cf.imes.module.system.api.social.dto.SocialUserBindReqDTO; -import com.cf.imes.module.system.api.social.dto.SocialUserRespDTO; -import com.cf.imes.module.system.controller.admin.auth.vo.*; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthLoginRespVO; -import com.cf.imes.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO; import com.cf.imes.module.system.controller.admin.auth.vo.AuthSmsSendReqVO; -import com.cf.imes.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO; import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; import com.cf.imes.module.system.enums.logger.LoginLogTypeEnum; import com.cf.imes.module.system.enums.logger.LoginResultEnum; import com.cf.imes.module.system.enums.sms.SmsSceneEnum; -import com.cf.imes.module.system.enums.social.SocialTypeEnum; import com.cf.imes.module.system.service.logger.LoginLogService; import com.cf.imes.module.system.service.member.MemberService; import com.cf.imes.module.system.service.oauth2.OAuth2TokenService; @@ -91,7 +85,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { when(userService.isPasswordMatch(eq(password), eq(user.getPassword()))).thenReturn(true); // 调用 - AdminUserDO loginUser = authService.authenticate(username, password, null); + AdminUserDO loginUser = authService.authenticate(AuthLoginReqVO.builder().username(username).password(password).build()); // 校验 assertPojoEquals(user, loginUser); } @@ -103,7 +97,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { String password = randomString(); // 调用, 并断言异常 - assertServiceException(() -> authService.authenticate(username, password, null), + assertServiceException(() -> authService.authenticate(AuthLoginReqVO.builder().username(username).password(password).build()), AUTH_LOGIN_BAD_CREDENTIALS); verify(loginLogService).createLoginLog( argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) @@ -123,7 +117,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { when(userService.getUserByUsername(eq(username), null)).thenReturn(user); // 调用, 并断言异常 - assertServiceException(() -> authService.authenticate(username, password, null), + assertServiceException(() -> authService.authenticate(AuthLoginReqVO.builder().username(username).password(password).build()), AUTH_LOGIN_BAD_CREDENTIALS); verify(loginLogService).createLoginLog( argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) @@ -145,7 +139,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { when(userService.isPasswordMatch(eq(password), eq(user.getPassword()))).thenReturn(true); // 调用, 并断言异常 - assertServiceException(() -> authService.authenticate(username, password, null), + assertServiceException(() -> authService.authenticate(AuthLoginReqVO.builder().username(username).password(password).build()), AUTH_LOGIN_USER_DISABLED); verify(loginLogService).createLoginLog( argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsChannelServiceTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsChannelServiceTest.java index 2a6fdcb40..bfd612c8a 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsChannelServiceTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsChannelServiceTest.java @@ -5,6 +5,7 @@ import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.sms.core.client.SmsClient; import com.cf.imes.framework.sms.core.client.SmsClientFactory; +import com.cf.imes.framework.sms.core.enums.SmsChannelEnum; import com.cf.imes.framework.sms.core.property.SmsChannelProperties; import com.cf.imes.framework.test.core.ut.BaseDbUnitTest; import com.cf.imes.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; @@ -200,16 +201,12 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { Long id = channel.getId(); // mock 方法 SmsClient mockClient = mock(SmsClient.class); - when(smsClientFactory.getSmsClient(eq(id))).thenReturn(mockClient); + when(smsClientFactory.getSmsClient(eq(SmsChannelEnum.ALIYUN.getCode()))).thenReturn(mockClient); // 调用 SmsClient client = smsChannelService.getSmsClient(id); // 断言 assertSame(client, mockClient); - verify(smsClientFactory).createOrUpdateSmsClient(argThat(arg -> { - SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class); - return properties.equals(arg); - })); } @Test @@ -227,10 +224,6 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { SmsClient client = smsChannelService.getSmsClient(code); // 断言 assertSame(client, mockClient); - verify(smsClientFactory).createOrUpdateSmsClient(argThat(arg -> { - SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class); - return properties.equals(arg); - })); } } diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsLogServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsLogServiceImplTest.java index 33752d6e8..0576fd92e 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsLogServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsLogServiceImplTest.java @@ -130,10 +130,11 @@ public class SmsLogServiceImplTest extends BaseDbUnitTest { String apiSendMsg = randomString(); String apiRequestId = randomString(); String apiSerialNo = randomString(); + String channelCode = randomString(); // 调用 smsLogService.updateSmsSendResult(id, success, - apiSendCode, apiSendMsg, apiRequestId, apiSerialNo); + apiSendCode, apiSendMsg, apiRequestId, apiSerialNo, channelCode); // 断言 dbSmsLog = smsLogMapper.selectById(id); assertEquals(success ? SmsSendStatusEnum.SUCCESS.getStatus() : SmsSendStatusEnum.FAILURE.getStatus(), diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsSendServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsSendServiceImplTest.java index bf0f196f4..a21c8b6ef 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsSendServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsSendServiceImplTest.java @@ -85,8 +85,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { // 断言 assertEquals(smsLogId, resultSmsLogId); // 断言调用 - verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(user.getMobile()), - eq(template.getChannelId()), eq(template.getApiTemplateId()), + verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(user.getMobile()), eq(template), eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login")))); } @@ -124,8 +123,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { // 断言 assertEquals(smsLogId, resultSmsLogId); // 断言调用 - verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(mobile), - eq(template.getChannelId()), eq(template.getApiTemplateId()), + verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(mobile), eq(template), eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login")))); } @@ -164,8 +162,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { // 断言 assertEquals(smsLogId, resultSmsLogId); // 断言调用 - verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(mobile), - eq(template.getChannelId()), eq(template.getApiTemplateId()), + verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(mobile), eq(template), eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login")))); } @@ -204,8 +201,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { // 断言 assertEquals(smsLogId, resultSmsLogId); // 断言调用 - verify(smsProducer, times(0)).sendSmsSendMessage(anyLong(), anyString(), - anyLong(), any(), anyList()); + verify(smsProducer, times(0)).sendSmsSendMessage(anyLong(), any(), any(), anyList()); } @Test @@ -274,7 +270,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { // 断言 verify(smsLogService).updateSmsSendResult(eq(message.getLogId()), eq(sendResult.getSuccess()), eq(sendResult.getApiCode()), - eq(sendResult.getApiMsg()), eq(sendResult.getApiRequestId()), eq(sendResult.getSerialNo())); + eq(sendResult.getApiMsg()), eq(sendResult.getApiRequestId()), eq(sendResult.getSerialNo()), eq(sendResult.getChannelCode())); } @Test diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/user/AdminUserServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/user/AdminUserServiceImplTest.java index 61a9c5866..e38a94fd5 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/user/AdminUserServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/user/AdminUserServiceImplTest.java @@ -588,7 +588,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { userMapper.insert(randomAdminUserDO(o -> o.setMobile(mobile))); // 调用,校验异常 - assertServiceException(() -> userService.validateMobileUnique(null, mobile, 1L), + assertServiceException(() -> userService.validateMobileUnique(null, mobile), USER_MOBILE_EXISTS); } @@ -601,7 +601,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { userMapper.insert(randomAdminUserDO(o -> o.setMobile(mobile))); // 调用,校验异常 - assertServiceException(() -> userService.validateMobileUnique(id, mobile, 1L), + assertServiceException(() -> userService.validateMobileUnique(id, mobile), USER_MOBILE_EXISTS); }