Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6355059ee3 | ||
|
|
2c7e05cbad | ||
|
|
9f56c47105 | ||
|
|
22c7963bf5 | ||
|
|
e932af0404 | ||
|
|
3113ba2542 | ||
|
|
d976555206 | ||
|
|
0da708c29f | ||
|
|
bcf22400b5 | ||
|
|
2b6c4ff7f3 | ||
|
|
e1a9fba2ca | ||
|
|
f88d4d8fe7 | ||
|
|
eda31fcffd | ||
|
|
bfcb05893a | ||
|
|
5e2972e8c5 | ||
|
|
a323ddb10b | ||
|
|
e6a12aaeb2 | ||
|
|
371daf2eee | ||
|
|
c03bcfb043 | ||
|
|
677349559c | ||
|
|
90eb4a1af8 | ||
|
|
95242f772e | ||
|
|
8196e34cb4 | ||
|
|
da9823ee18 | ||
|
|
f55ace8ec0 | ||
|
|
ca91379e38 | ||
|
|
4f34e267d7 | ||
|
|
5f86b1c909 | ||
|
|
e8c34248e9 | ||
|
|
6da72d6702 | ||
|
|
402d04294c | ||
|
|
c4f29d3ee5 | ||
|
|
8bacb6ec5e | ||
|
|
027da720fd | ||
|
|
3b8d01b673 | ||
|
|
18dbf7a042 | ||
|
|
1937049b0e | ||
|
|
2d3d4e3f56 | ||
|
|
06c600f67d | ||
|
|
50a1c03776 | ||
|
|
61a18e781d | ||
|
|
8d588502aa | ||
|
|
bf1af52660 | ||
| cd1ba55b26 | |||
|
|
d60966dd3f | ||
|
|
687be5840e | ||
|
|
d9f808ecc1 | ||
| c1d84aaf81 | |||
|
|
dec15eb913 | ||
| 18e014d9cb | |||
| 2cb03b146a |
@@ -1,212 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter</artifactId>
|
||||
<version>2.9.0</version>
|
||||
</parent>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-admin</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<description>园区管理系统</description>
|
||||
<url>https://github.com/wms-org/wms-admin</url>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU LESSER GENERAL PUBLIC LICENSE</name>
|
||||
<url>http://www.gnu.org/licenses/lgpl.html</url>
|
||||
</license>
|
||||
</licenses>
|
||||
<modules>
|
||||
<module>wms-webapi</module>
|
||||
<module>wms-module-system</module>
|
||||
<module>wms-plugin</module>
|
||||
<module>wms-common</module>
|
||||
<module>wms-extension</module>
|
||||
</modules>
|
||||
<properties>
|
||||
<revision>3.6.0-SNAPSHOT</revision>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-webapi</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-module-system</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-common</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-plugin-schedule</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-plugin-generator</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
<version>1.5.5.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>1.5.5.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.8.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>29.0-jre</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>huawei-mirror</id>
|
||||
<name>HuaweiCloud Mirror</name>
|
||||
<url>https://mirrors.huaweicloud.com/repository/maven/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>ali-mirror</id>
|
||||
<name>AliYun Mirror</name>
|
||||
<url>https://maven.aliyun.com/repository/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>huawei-mirror</id>
|
||||
<name>HuaweiCloud Mirror</name>
|
||||
<url>https://mirrors.huaweicloud.com/repository/maven/</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>ali-mirror</id>
|
||||
<name>AliYun Mirror</name>
|
||||
<url>https://maven.aliyun.com/repository/public/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<compilerArgument>-parameters</compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.diffplug.spotless</groupId>
|
||||
<artifactId>spotless-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>apply</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<java>
|
||||
<removeUnusedImports />
|
||||
<eclipse>
|
||||
<file>.style/p3c-codestyle.xml</file>
|
||||
</eclipse>
|
||||
<licenseHeader>
|
||||
<file>.style/license-header</file>
|
||||
</licenseHeader>
|
||||
</java>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>flatten-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>flatten</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>flatten</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>flatten-clean</id>
|
||||
<phase>clean</phase>
|
||||
<goals>
|
||||
<goal>clean</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<updatePomFile>true</updatePomFile>
|
||||
<flattenMode>resolveCiFriendliesOnly</flattenMode>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>sonar</id>
|
||||
<activation />
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.sonarsource.scanner.maven</groupId>
|
||||
<artifactId>sonar-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sonar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<sonar.projectKey>Charles7c_wms-admin</sonar.projectKey>
|
||||
<sonar.moduleKey>${project.groupId}:${project.artifactId}</sonar.moduleKey>
|
||||
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
|
||||
<sonar.organization>charles7c</sonar.organization>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
51
.gitignore
vendored
Normal file
51
.gitignore
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
logs/
|
||||
sdklog/
|
||||
*.log
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Maven ###
|
||||
.flattened-pom.xml
|
||||
|
||||
### JVM ###
|
||||
hs_err_pid*
|
||||
replay_pid*
|
||||
|
||||
### OS ###
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
### Spotless ###
|
||||
spotless-index
|
||||
@@ -1,123 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-admin</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>wms-common</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
<description>公共模块(存放公共工具类,公共配置等)</description>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU LESSER GENERAL PUBLIC LICENSE</name>
|
||||
<url>http://www.gnu.org/licenses/lgpl.html</url>
|
||||
</license>
|
||||
</licenses>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.ahoo.cosid</groupId>
|
||||
<artifactId>cosid-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.ahoo.cosid</groupId>
|
||||
<artifactId>cosid-spring-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara.sms4j</groupId>
|
||||
<artifactId>sms4j-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara.x-file-storage</groupId>
|
||||
<artifactId>x-file-storage-spring</artifactId>
|
||||
<version>2.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<version>1.12.780</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-extension-crud-mp</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-auth-satoken</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-auth-justauth</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-cache-jetcache</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-extension-datapermission-mp</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-messaging-websocket</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-messaging-mail</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-captcha-graphic</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-captcha-behavior</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-security-limiter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-security-crypto</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-security-mask</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-security-password</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-json-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -155,5 +155,12 @@
|
||||
<artifactId>spring-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.1.100.Final</version> <!-- 使用较新稳定版本 -->
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
/**
|
||||
* DPA6024V-2T-1.0 数字控制器命令类型枚举
|
||||
* 定义控制器支持的指令字
|
||||
*/
|
||||
public enum CommandTypeEnum {
|
||||
|
||||
/**
|
||||
* 打开对应通道 (指令字: 1)
|
||||
*/
|
||||
ON('1'),
|
||||
|
||||
/**
|
||||
* 关闭对应通道 (指令字: 2)
|
||||
*/
|
||||
OFF('2'),
|
||||
|
||||
/**
|
||||
* 设置对应通道亮度参数 (指令字: 3)
|
||||
*/
|
||||
SET_BRIGHTNESS('3'),
|
||||
|
||||
/**
|
||||
* 读出对应通道亮度参数 (指令字: 4)
|
||||
*/
|
||||
READ('4');
|
||||
|
||||
private final char commandCode;
|
||||
|
||||
CommandTypeEnum(char commandCode) {
|
||||
this.commandCode = commandCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指令字字符
|
||||
*
|
||||
* @return 指令字 (如 '1', '2', '3', '4')
|
||||
*/
|
||||
public char getCommandCode() {
|
||||
return commandCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指令字获取对应的命令类型
|
||||
*
|
||||
* @param commandCode 指令字字符
|
||||
* @return 对应的CommandType,找不到返回null
|
||||
*/
|
||||
public static CommandTypeEnum fromCommandCode(char commandCode) {
|
||||
for (CommandTypeEnum type : values()) {
|
||||
if (type.commandCode == commandCode) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(commandCode);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 交易状态枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ConsumeOrderTypeEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 在线消费
|
||||
*/
|
||||
CONSUME(0, "消费");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 支付方式枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ConsumePayModeEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 人脸
|
||||
*/
|
||||
FACE(0, "人脸"),
|
||||
|
||||
/**
|
||||
* 云卡
|
||||
*/
|
||||
CLOUD_CARD(1, "云卡"),
|
||||
|
||||
/**
|
||||
* 刷卡
|
||||
*/
|
||||
SWIPE_CARD(2, "刷卡"),
|
||||
|
||||
/**
|
||||
* 支付宝
|
||||
*/
|
||||
ALIPAY(3, "支付宝"),
|
||||
|
||||
/**
|
||||
* 微信
|
||||
*/
|
||||
WECHAT(4, "微信"),
|
||||
|
||||
/**
|
||||
* 取餐码
|
||||
*/
|
||||
MEAL_CODE(5, "取餐码");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 消费-充值方式
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ConsumeRechargeModeEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 现金
|
||||
*/
|
||||
CASH(0, "现金"),
|
||||
|
||||
/**
|
||||
* 支付宝
|
||||
*/
|
||||
ALIPAY(1, "支付宝"),
|
||||
|
||||
/**
|
||||
* 微信
|
||||
*/
|
||||
WECHAT(2, "微信"),
|
||||
|
||||
/**
|
||||
* 网银
|
||||
*/
|
||||
ONLINE_BANKING(3, "网银");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 消费-操作类型
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ConsumeRechargeTypeEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 补贴
|
||||
*/
|
||||
SUBSIDY(0, "补贴"),
|
||||
|
||||
/**
|
||||
* 充值
|
||||
*/
|
||||
RECHARGE(1, "充值"),
|
||||
|
||||
/**
|
||||
* 退款
|
||||
*/
|
||||
REFUND(2, "退款"),
|
||||
|
||||
/**
|
||||
* 清零(全部)
|
||||
*/
|
||||
CLEAR(3, "清零(全部)"),
|
||||
|
||||
/**
|
||||
* 清零(充值)
|
||||
*/
|
||||
CLEAR_CZ(4, "清零(充值)"),
|
||||
|
||||
/**
|
||||
* 清零(补贴)
|
||||
*/
|
||||
CLEAR_BT(5, "清零(补贴)");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 消费-充值来源
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ConsumeRechargeWayEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 在线消费
|
||||
*/
|
||||
WEB(0, "平台"),
|
||||
|
||||
/**
|
||||
* 离线消费
|
||||
*/
|
||||
PHONE(1, "手机");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 交易状态枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ConsumeResultEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 在线消费
|
||||
*/
|
||||
ONLINE_CONSUME(0, "在线消费"),
|
||||
|
||||
/**
|
||||
* 离线消费
|
||||
*/
|
||||
OFFLINE_CONSUME(1, "离线消费"),
|
||||
|
||||
/**
|
||||
* 超时
|
||||
*/
|
||||
TIMEOUT(2, "超时"),
|
||||
|
||||
/**
|
||||
* 消费异常
|
||||
*/
|
||||
CONSUMPTION_EXCEPTION(3, "消费异常"),
|
||||
|
||||
/**
|
||||
* 异常消费
|
||||
*/
|
||||
EXCEPTION_CONSUMPTION(4, "异常消费");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 消费-充值来源
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ConsumeTmrtypeEnum implements BaseEnum<Integer> {
|
||||
/**
|
||||
* 早餐
|
||||
*/
|
||||
BREAKFAST(0, "早餐"),
|
||||
|
||||
/**
|
||||
* 中餐
|
||||
*/
|
||||
LUNCH(1, "中餐"),
|
||||
|
||||
/**
|
||||
* 午餐
|
||||
*/
|
||||
DINNER(2, "午餐"),
|
||||
|
||||
/**
|
||||
* 夜餐
|
||||
*/
|
||||
NIGHT(3, "夜餐");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 消费类型枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ConsumeTypeConverter implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
UNIT_PRICE(0, "单价"),
|
||||
|
||||
/**
|
||||
* 定额
|
||||
*/
|
||||
FIXED_PRICE(1, "定额"),
|
||||
|
||||
/**
|
||||
* 时段模式
|
||||
*/
|
||||
TIME_PERIOD(2, "时段模式"),
|
||||
|
||||
/**
|
||||
* 计次
|
||||
*/
|
||||
COUNTING(3, "计次"),
|
||||
|
||||
/**
|
||||
* 点餐机模式
|
||||
*/
|
||||
ORDERING_MACHINE(5, "点餐机模式"),
|
||||
|
||||
/**
|
||||
* 身份模式
|
||||
*/
|
||||
IDENTITY(9, "身份模式");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 钱包消费模式枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ConsumeWalletModeEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 先消费补贴再个人
|
||||
*/
|
||||
SUBSIDY_THEN_PERSONAL(0, "先消费补贴再个人"),
|
||||
|
||||
/**
|
||||
* 仅现金
|
||||
*/
|
||||
ONLY_CASH(1, "仅现金"),
|
||||
|
||||
/**
|
||||
* 仅补贴
|
||||
*/
|
||||
ONLY_SUBSIDY(2, "仅补贴");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 启用禁用
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum EnableEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 禁用
|
||||
*/
|
||||
DISABLE(0, "禁用"),
|
||||
|
||||
/**
|
||||
* 在线消费
|
||||
*/
|
||||
ENABLE(1, "启用");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/26 21:35
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum LightLevelEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 一级
|
||||
*/
|
||||
LEVEL1(1, "一级"),
|
||||
|
||||
/**
|
||||
* 二级
|
||||
*/
|
||||
LEVEL2(2, "二级"),
|
||||
|
||||
/**
|
||||
* 三级
|
||||
*/
|
||||
LEVEL3(3, "三级");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
* 根据描述获取值
|
||||
*
|
||||
* @param description 描述
|
||||
* @return 值,如果找不到则返回 null
|
||||
*/
|
||||
public static Integer getValueByDescription(String description) {
|
||||
for (LightLevelEnum enumValue : values()) {
|
||||
if (enumValue.getDescription().equals(description)) {
|
||||
return enumValue.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import com.alibaba.excel.converters.Converter;
|
||||
import com.alibaba.excel.enums.CellDataTypeEnum;
|
||||
import com.alibaba.excel.metadata.GlobalConfiguration;
|
||||
import com.alibaba.excel.metadata.data.ReadCellData;
|
||||
import com.alibaba.excel.metadata.data.WriteCellData;
|
||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class LightLevelEnumConverter implements Converter<Integer> {
|
||||
|
||||
private static final Map<Integer, String> LIGHT_LEVEL_MAP = new HashMap<>();
|
||||
static {
|
||||
LIGHT_LEVEL_MAP.put(1, "一级");
|
||||
LIGHT_LEVEL_MAP.put(2, "二级");
|
||||
LIGHT_LEVEL_MAP.put(3, "三级");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> supportJavaTypeKey() {
|
||||
return Integer.class; // 支持的 Java 类型
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellDataTypeEnum supportExcelTypeKey() {
|
||||
return CellDataTypeEnum.STRING; // 写入 Excel 时用字符串
|
||||
}
|
||||
|
||||
@Override
|
||||
public WriteCellData<String> convertToExcelData(Integer value,
|
||||
ExcelContentProperty contentProperty,
|
||||
GlobalConfiguration globalConfiguration) {
|
||||
if (value == null) {
|
||||
return new WriteCellData<>("");
|
||||
}
|
||||
String label = LIGHT_LEVEL_MAP.getOrDefault(value, "");
|
||||
return new WriteCellData<>(label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer convertToJavaData(ReadCellData<?> cellData,
|
||||
ExcelContentProperty contentProperty,
|
||||
GlobalConfiguration globalConfiguration) {
|
||||
String stringValue = cellData.getStringValue();
|
||||
for (Map.Entry<Integer, String> entry : LIGHT_LEVEL_MAP.entrySet()) {
|
||||
if (entry.getValue().equals(stringValue)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package top.wms.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum OperTypeEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
ADD(0, "新增"),
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*/
|
||||
UPDATE(1, "修改"),
|
||||
|
||||
/**
|
||||
* 下发
|
||||
*/
|
||||
DOWN(2, "下发"),
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
DEL(3, "删除");
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-admin</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>wms-extension</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<description>扩展模块(存放其他扩展模块)</description>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU LESSER GENERAL PUBLIC LICENSE</name>
|
||||
<url>http://www.gnu.org/licenses/lgpl.html</url>
|
||||
</license>
|
||||
</licenses>
|
||||
<modules>
|
||||
<module>wms-extension-schedule-server</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-extension</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>wms-extension-schedule-server</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
<description>任务调度服务端</description>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU LESSER GENERAL PUBLIC LICENSE</name>
|
||||
<url>http://www.gnu.org/licenses/lgpl.html</url>
|
||||
</license>
|
||||
</licenses>
|
||||
<properties>
|
||||
<snail-job.version>1.2.0</snail-job.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.aizuda</groupId>
|
||||
<artifactId>snail-job-server-starter</artifactId>
|
||||
<version>${snail-job.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.liquibase</groupId>
|
||||
<artifactId>liquibase-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-admin</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>wms-module-system</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
<description>系统管理模块(存放系统管理相关业务功能,例如:部门管理、角色管理、用户管理等)</description>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU LESSER GENERAL PUBLIC LICENSE</name>
|
||||
<url>http://www.gnu.org/licenses/lgpl.html</url>
|
||||
</license>
|
||||
</licenses>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-common</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -18,5 +18,19 @@
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<version>1.3.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 串口通信依赖 -->
|
||||
<dependency>
|
||||
<groupId>com.fazecast</groupId>
|
||||
<artifactId>jSerialComm</artifactId>
|
||||
<version>2.10.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -1,39 +1,15 @@
|
||||
package top.wms.admin.auth.handler;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.xkcoding.justauth.AuthRequestFactory;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
import top.wms.admin.auth.AbstractLoginHandler;
|
||||
import top.wms.admin.auth.enums.AuthTypeEnum;
|
||||
import top.wms.admin.auth.model.req.SocialLoginReq;
|
||||
import top.wms.admin.auth.model.resp.LoginResp;
|
||||
import top.wms.admin.common.constant.RegexConstants;
|
||||
import top.wms.admin.common.constant.SysConstants;
|
||||
import top.wms.admin.common.enums.DisEnableStatusEnum;
|
||||
import top.wms.admin.common.enums.GenderEnum;
|
||||
import top.wms.admin.system.model.entity.RoleDO;
|
||||
import top.wms.admin.system.model.entity.UserDO;
|
||||
import top.wms.admin.system.model.entity.UserSocialDO;
|
||||
import top.wms.admin.system.model.resp.ClientResp;
|
||||
import top.wms.admin.system.service.UserRoleService;
|
||||
import top.wms.admin.system.service.UserSocialService;
|
||||
import top.continew.starter.core.autoconfigure.project.ProjectProperties;
|
||||
import top.continew.starter.core.exception.BadRequestException;
|
||||
import top.continew.starter.core.validation.ValidationUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* 第三方账号登录处理器
|
||||
@@ -46,57 +22,10 @@ import java.util.Collections;
|
||||
@RequiredArgsConstructor
|
||||
public class SocialLoginHandler extends AbstractLoginHandler<SocialLoginReq> {
|
||||
|
||||
private final AuthRequestFactory authRequestFactory;
|
||||
private final UserSocialService userSocialService;
|
||||
private final UserRoleService userRoleService;
|
||||
private final ProjectProperties projectProperties;
|
||||
|
||||
@Override
|
||||
public LoginResp login(SocialLoginReq req, ClientResp client, HttpServletRequest request) {
|
||||
// 获取第三方登录信息
|
||||
AuthRequest authRequest = this.getAuthRequest(req.getSource());
|
||||
AuthCallback callback = new AuthCallback();
|
||||
callback.setCode(req.getCode());
|
||||
callback.setState(req.getState());
|
||||
AuthResponse<AuthUser> response = authRequest.login(callback);
|
||||
ValidationUtils.throwIf(!response.ok(), response.getMsg());
|
||||
AuthUser authUser = response.getData();
|
||||
// 如未绑定则自动注册新用户,保存或更新关联信息
|
||||
String source = authUser.getSource();
|
||||
String openId = authUser.getUuid();
|
||||
UserSocialDO userSocial = userSocialService.getBySourceAndOpenId(source, openId);
|
||||
UserDO user;
|
||||
if (null == userSocial) {
|
||||
String username = authUser.getUsername();
|
||||
UserDO existsUser = userService.getByUsername(username);
|
||||
String randomStr = RandomUtil.randomString(RandomUtil.BASE_CHAR, 5);
|
||||
if (null != existsUser || !ReUtil.isMatch(RegexConstants.USERNAME, username)) {
|
||||
username = randomStr + IdUtil.fastSimpleUUID();
|
||||
}
|
||||
user = new UserDO();
|
||||
user.setUsername(username);
|
||||
user.setGender(GenderEnum.valueOf(authUser.getGender().name()));
|
||||
user.setAvatar(authUser.getAvatar());
|
||||
user.setStatus(DisEnableStatusEnum.ENABLE);
|
||||
userService.save(user);
|
||||
Long userId = user.getId();
|
||||
RoleDO role = roleService.getByCode(SysConstants.SUPER_ROLE_CODE);
|
||||
userRoleService.assignRolesToUser(Collections.singletonList(role.getId()), userId);
|
||||
userSocial = new UserSocialDO();
|
||||
userSocial.setUserId(userId);
|
||||
userSocial.setSource(source);
|
||||
userSocial.setOpenId(openId);
|
||||
} else {
|
||||
user = BeanUtil.copyProperties(userService.getById(userSocial.getUserId()), UserDO.class);
|
||||
}
|
||||
// 检查用户状态
|
||||
super.checkUserStatus(user);
|
||||
userSocial.setMetaJson(JSONUtil.toJsonStr(authUser));
|
||||
userSocial.setLastLoginTime(LocalDateTime.now());
|
||||
userSocialService.saveOrUpdate(userSocial);
|
||||
// 执行认证
|
||||
String token = super.authenticate(user, client);
|
||||
return LoginResp.builder().token(token).build();
|
||||
// 第三方登录已禁用
|
||||
throw new BadRequestException("第三方登录功能已禁用");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,18 +41,4 @@ public class SocialLoginHandler extends AbstractLoginHandler<SocialLoginReq> {
|
||||
return AuthTypeEnum.SOCIAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 AuthRequest
|
||||
*
|
||||
* @param source 平台名称
|
||||
* @return AuthRequest
|
||||
*/
|
||||
private AuthRequest getAuthRequest(String source) {
|
||||
try {
|
||||
return authRequestFactory.get(source);
|
||||
} catch (Exception e) {
|
||||
throw new BadRequestException("暂不支持 [%s] 平台账号登录".formatted(source));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.wms.admin.fullWorkOrder.mapper;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
import top.continew.starter.data.mp.base.BaseMapper;
|
||||
import top.wms.admin.fullWorkOrder.model.entity.FullWorkOrderInfoDO;
|
||||
|
||||
/**
|
||||
* 整箱领取记录 Mapper
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/24 09:36
|
||||
*/
|
||||
@Repository
|
||||
public interface FullWorkOrderInfoMapper extends BaseMapper<FullWorkOrderInfoDO> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package top.wms.admin.fullWorkOrder.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import top.continew.starter.data.mp.base.BaseMapper;
|
||||
import top.wms.admin.fullWorkOrder.model.entity.FullWorkOrderDO;
|
||||
import top.wms.admin.fullWorkOrder.model.resp.FullWorkOrderResp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 整箱领取记录 Mapper
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/24 09:36
|
||||
*/
|
||||
@Repository
|
||||
public interface FullWorkOrderMapper extends BaseMapper<FullWorkOrderDO> {
|
||||
|
||||
IPage<FullWorkOrderResp> selectFullWorkOrderPage(@Param("page") Page<Object> objectPage,
|
||||
@Param(Constants.WRAPPER) QueryWrapper<FullWorkOrderDO> queryWrapper);
|
||||
|
||||
List<FullWorkOrderResp> selectFullWorkOrderExport(@Param(Constants.WRAPPER) QueryWrapper<FullWorkOrderDO> queryWrapper);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package top.wms.admin.fullWorkOrder.model.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
||||
import top.wms.admin.common.model.entity.BaseDO;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 整箱领取记录实体
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/24 09:36
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_full_work_order")
|
||||
public class FullWorkOrderDO extends BaseDO {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 任务工单号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
private String materialCode;
|
||||
|
||||
/**
|
||||
* 打印物料编码
|
||||
*/
|
||||
private String encodingPrint;
|
||||
|
||||
/**
|
||||
* 图片地址
|
||||
*/
|
||||
private String imgUrl;
|
||||
|
||||
/**
|
||||
* 批次号
|
||||
*/
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
private String mark;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer count;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package top.wms.admin.fullWorkOrder.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 整箱领取记录实体
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/24 09:36
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_full_work_order_info")
|
||||
public class FullWorkOrderInfoDO {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long fullWorkOrderId;
|
||||
|
||||
private BigDecimal weight;
|
||||
|
||||
/**
|
||||
* 图片地址
|
||||
*/
|
||||
private String imgUrl;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package top.wms.admin.fullWorkOrder.model.query;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 整箱领取记录查询条件
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/24 09:36
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "整箱领取记录查询条件")
|
||||
public class FullWorkOrderQuery implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务工单号
|
||||
*/
|
||||
@Schema(description = "任务工单号")
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@Schema(description = "物料编码")
|
||||
private String materialCode;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
@Schema(description = "物料名称")
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 批次号
|
||||
*/
|
||||
@Schema(description = "批次号")
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@Schema(description = "创建人")
|
||||
private Long createUser;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
|
||||
private List<Date> createTime;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package top.wms.admin.fullWorkOrder.model.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 创建或修改整箱领取记录参数
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/24 09:36
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "创建或修改整箱领取记录参数")
|
||||
public class FullWorkOrderInfoReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 重量
|
||||
*/
|
||||
@Schema(description = "重量")
|
||||
@NotNull(message = "重量不能为空")
|
||||
private BigDecimal weight;
|
||||
|
||||
/**
|
||||
* 整箱领取记录ID
|
||||
*/
|
||||
@Schema(description = "整箱领取记录ID")
|
||||
@NotNull(message = "整箱领取记录ID不能为空")
|
||||
private Long fullWorkOrderId;
|
||||
|
||||
/**
|
||||
* 图片地址
|
||||
*/
|
||||
@Schema(description = "图片地址")
|
||||
@NotBlank(message = "图片未采集到")
|
||||
@Length(max = 255, message = "图片地址长度不能超过 {max} 个字符")
|
||||
private String imgUrl;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package top.wms.admin.fullWorkOrder.model.req;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.*;
|
||||
|
||||
/**
|
||||
* 创建或修改整箱领取记录参数
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/24 09:36
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "创建或修改整箱领取记录参数")
|
||||
public class FullWorkOrderReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 任务工单号
|
||||
*/
|
||||
@Schema(description = "任务工单号")
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@Schema(description = "物料编码")
|
||||
@NotBlank(message = "物料编码不能为空")
|
||||
@Length(max = 255, message = "物料编码长度不能超过 {max} 个字符")
|
||||
private String materialCode;
|
||||
|
||||
/**
|
||||
* /**
|
||||
* 图片地址
|
||||
*/
|
||||
@Schema(description = "图片地址")
|
||||
@NotBlank(message = "图片未采集到")
|
||||
@Length(max = 255, message = "图片地址长度不能超过 {max} 个字符")
|
||||
private String imgUrl;
|
||||
|
||||
/**
|
||||
* 批次号
|
||||
*/
|
||||
@Schema(description = "批次号")
|
||||
@NotBlank(message = "批次号不能为空")
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
@Schema(description = "标记号")
|
||||
@NotBlank(message = "标记号不能为空")
|
||||
private String mark;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
@Schema(description = "数量")
|
||||
@NotNull(message = "数量不能为空")
|
||||
private Integer count;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package top.wms.admin.fullWorkOrder.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
|
||||
import top.wms.admin.common.model.resp.BaseDetailResp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.*;
|
||||
|
||||
/**
|
||||
* 整箱领取记录详情信息
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/24 09:36
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@Schema(description = "整箱领取记录详情信息")
|
||||
public class FullWorkOrderDetailResp extends BaseDetailResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@Schema(description = "标题")
|
||||
@ExcelProperty(value = "标题")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 任务工单号
|
||||
*/
|
||||
@Schema(description = "任务工单号")
|
||||
@ExcelProperty(value = "任务工单号")
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@Schema(description = "物料编码")
|
||||
@ExcelProperty(value = "物料编码")
|
||||
private String materialCode;
|
||||
|
||||
/**
|
||||
* 图片地址
|
||||
*/
|
||||
@Schema(description = "图片地址")
|
||||
@ExcelProperty(value = "图片地址")
|
||||
private String imgUrl;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package top.wms.admin.fullWorkOrder.model.resp;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.wms.admin.common.model.resp.BaseDetailResp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.*;
|
||||
|
||||
/**
|
||||
* 整箱领取记录信息
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/24 09:36
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "整箱领取记录信息")
|
||||
public class FullWorkOrderResp extends BaseDetailResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@Schema(description = "标题")
|
||||
@ExcelProperty(value = "标题", order = 1)
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 任务工单号
|
||||
*/
|
||||
@Schema(description = "任务工单号")
|
||||
@ExcelProperty(value = "任务工单号", order = 2)
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@Schema(description = "物料编码")
|
||||
@ExcelProperty(value = "物料编码", order = 4)
|
||||
private String materialCode;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
@Schema(description = "物料名称")
|
||||
@ExcelProperty(value = "物料名称", order = 3)
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 图片地址
|
||||
*/
|
||||
@Schema(description = "图片地址")
|
||||
@ExcelProperty(value = "图片地址", order = 5)
|
||||
private String imgUrl;
|
||||
|
||||
/**
|
||||
* 批次号
|
||||
*/
|
||||
@Schema(description = "批次号")
|
||||
@ExcelProperty(value = "批次号", order = 6)
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
@Schema(description = "标记号")
|
||||
@ExcelProperty(value = "标记号", order = 7)
|
||||
private String mark;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
@Schema(description = "标记号")
|
||||
@ExcelProperty(value = "数量", order = 8)
|
||||
private Integer count;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package top.wms.admin.fullWorkOrder.service;
|
||||
|
||||
import top.continew.starter.extension.crud.service.BaseService;
|
||||
import top.wms.admin.fullWorkOrder.model.entity.FullWorkOrderInfoDO;
|
||||
import top.wms.admin.fullWorkOrder.model.query.FullWorkOrderQuery;
|
||||
import top.wms.admin.fullWorkOrder.model.req.FullWorkOrderInfoReq;
|
||||
import top.wms.admin.fullWorkOrder.model.req.FullWorkOrderReq;
|
||||
import top.wms.admin.fullWorkOrder.model.resp.FullWorkOrderResp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 整箱领取记录业务接口
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/24 09:36
|
||||
*/
|
||||
public interface FullWorkOrderService extends BaseService<FullWorkOrderResp, FullWorkOrderResp, FullWorkOrderQuery, FullWorkOrderReq> {
|
||||
|
||||
void saveFullWorkOrderDetail(List<FullWorkOrderInfoReq> infos);
|
||||
|
||||
List<FullWorkOrderInfoDO> getFullWorkOrderInfos(Long fullWorkOrderId);
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package top.wms.admin.fullWorkOrder.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.query.SortQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
import top.continew.starter.extension.crud.service.BaseServiceImpl;
|
||||
import top.continew.starter.file.excel.util.ExcelUtils;
|
||||
import top.wms.admin.common.context.UserContextHolder;
|
||||
import top.wms.admin.fullWorkOrder.mapper.FullWorkOrderInfoMapper;
|
||||
import top.wms.admin.fullWorkOrder.mapper.FullWorkOrderMapper;
|
||||
import top.wms.admin.fullWorkOrder.model.entity.FullWorkOrderDO;
|
||||
import top.wms.admin.fullWorkOrder.model.entity.FullWorkOrderInfoDO;
|
||||
import top.wms.admin.fullWorkOrder.model.query.FullWorkOrderQuery;
|
||||
import top.wms.admin.fullWorkOrder.model.req.FullWorkOrderInfoReq;
|
||||
import top.wms.admin.fullWorkOrder.model.req.FullWorkOrderReq;
|
||||
import top.wms.admin.fullWorkOrder.model.resp.FullWorkOrderResp;
|
||||
import top.wms.admin.fullWorkOrder.service.FullWorkOrderService;
|
||||
import top.wms.admin.material.mapper.MaterialInfoMapper;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 整箱领取记录业务实现
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/24 09:36
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class FullWorkOrderServiceImpl extends BaseServiceImpl<FullWorkOrderMapper, FullWorkOrderDO, FullWorkOrderResp, FullWorkOrderResp, FullWorkOrderQuery, FullWorkOrderReq> implements FullWorkOrderService {
|
||||
|
||||
private final FullWorkOrderInfoMapper fullWorkOrderInfoMapper;
|
||||
|
||||
private final MaterialInfoMapper materialInfoMapper;
|
||||
|
||||
@Override
|
||||
public PageResp<FullWorkOrderResp> page(FullWorkOrderQuery query, PageQuery pageQuery) {
|
||||
QueryWrapper<FullWorkOrderDO> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.like(StrUtil.isNotBlank(query.getMaterialCode()), "f.material_code", query.getMaterialCode());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getOrderNo()), "f.order_no", query.getOrderNo());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getBatch()), "f.batch", query.getBatch());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getMaterialName()), "m.material_name", query.getMaterialName());
|
||||
queryWrapper.between(CollUtil.isNotEmpty(query.getCreateTime()), "f.create_time", CollUtil.getFirst(query
|
||||
.getCreateTime()), CollUtil.getLast(query.getCreateTime()));
|
||||
this.sort(queryWrapper, pageQuery);
|
||||
|
||||
IPage<FullWorkOrderResp> page = baseMapper.selectFullWorkOrderPage(new Page<>(pageQuery.getPage(), pageQuery
|
||||
.getSize()), queryWrapper);
|
||||
|
||||
return PageResp.build(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeAdd(FullWorkOrderReq req) {
|
||||
String timestamp = DateUtil.format(new Date(), "yyyyMMddHHmmss");
|
||||
String randomNum = String.format("%06d", (int)(Math.random() * 1000000));
|
||||
req.setOrderNo(timestamp + randomNum);
|
||||
String title = DateUtil.format(new Date(), DatePattern.CHINESE_DATE_PATTERN) + "-" + UserContextHolder
|
||||
.getUsername();
|
||||
req.setTitle(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void export(FullWorkOrderQuery query, SortQuery sortQuery, HttpServletResponse response) {
|
||||
QueryWrapper<FullWorkOrderDO> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.like(StrUtil.isNotBlank(query.getMaterialCode()), "f.material_code", query.getMaterialCode());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getOrderNo()), "f.order_no", query.getOrderNo());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getBatch()), "f.batch", query.getBatch());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getMaterialName()), "m.material_name", query.getMaterialName());
|
||||
queryWrapper.between(CollUtil.isNotEmpty(query.getCreateTime()), "f.create_time", CollUtil.getFirst(query
|
||||
.getCreateTime()), CollUtil.getLast(query.getCreateTime()));
|
||||
|
||||
List<FullWorkOrderResp> list = baseMapper.selectFullWorkOrderExport(queryWrapper);
|
||||
|
||||
ExcelUtils.export(list, "整箱领取导出记录", FullWorkOrderResp.class, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveFullWorkOrderDetail(List<FullWorkOrderInfoReq> infos) {
|
||||
List<FullWorkOrderInfoDO> fullWorkOrderInfoDOS = BeanUtil.copyToList(infos, FullWorkOrderInfoDO.class);
|
||||
fullWorkOrderInfoMapper.insertBatch(fullWorkOrderInfoDOS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FullWorkOrderInfoDO> getFullWorkOrderInfos(Long fullWorkOrderId) {
|
||||
List<FullWorkOrderInfoDO> fullWorkOrderInfoDOS = fullWorkOrderInfoMapper
|
||||
.selectList(new QueryWrapper<FullWorkOrderInfoDO>().eq("full_work_order_id", fullWorkOrderId));
|
||||
return fullWorkOrderInfoDOS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
package top.wms.admin.light;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import top.wms.admin.common.enums.CommandTypeEnum;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* DPA6024V-2T-1.0 数字控制器 Java 控制类
|
||||
* 支持通过RS232串口控制LED光源的亮度(0-255级)
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class LightService {
|
||||
|
||||
private SerialPortHandler serialHandler;
|
||||
private final Object connectLock = new Object();
|
||||
|
||||
/**
|
||||
* 连接控制器
|
||||
* 前端页面进入"称重管理"页面时调用
|
||||
*/
|
||||
public boolean connect() {
|
||||
synchronized (connectLock) {
|
||||
try {
|
||||
// 先关闭旧的连接(如果存在)
|
||||
if (serialHandler != null) {
|
||||
log.info("关闭旧的串口连接");
|
||||
serialHandler.close();
|
||||
serialHandler = null;
|
||||
}
|
||||
|
||||
// 使用COM1串口
|
||||
String portName = "COM1";
|
||||
// 默认波特率9600
|
||||
int baudRate = 9600;
|
||||
serialHandler = new SerialPortHandler(portName, baudRate);
|
||||
boolean connected = serialHandler.open();
|
||||
if (connected) {
|
||||
log.info("数字控制器连接成功");
|
||||
} else {
|
||||
log.error("数字控制器连接失败");
|
||||
}
|
||||
return connected;
|
||||
} catch (Exception e) {
|
||||
log.error("连接失败: {}", e.getMessage());
|
||||
// 确保异常情况下serialHandler为null
|
||||
serialHandler = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 断开连接
|
||||
* 前端页面离开"称重管理"页面时调用
|
||||
*/
|
||||
public void disconnect() {
|
||||
synchronized (connectLock) {
|
||||
if (serialHandler != null) {
|
||||
log.info("正在断开数字控制器连接");
|
||||
try {
|
||||
serialHandler.close();
|
||||
} catch (Exception e) {
|
||||
log.error("关闭串口失败: {}", e.getMessage());
|
||||
} finally {
|
||||
serialHandler = null;
|
||||
log.info("数字控制器连接已断开");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否已连接
|
||||
*
|
||||
* @return 已连接返回true,否则返回false
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
synchronized (connectLock) {
|
||||
return serialHandler != null && serialHandler.isOpen();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查连接状态并尝试重连
|
||||
*
|
||||
* @return 重连成功返回true,否则返回false
|
||||
*/
|
||||
public boolean checkAndReconnect() {
|
||||
synchronized (connectLock) {
|
||||
if (isConnected()) {
|
||||
return true;
|
||||
}
|
||||
log.warn("串口连接异常,尝试重新连接");
|
||||
return connect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新连接控制器
|
||||
*
|
||||
* @return 重连成功返回true,否则返回false
|
||||
*/
|
||||
public boolean reconnect() {
|
||||
synchronized (connectLock) {
|
||||
if (serialHandler != null) {
|
||||
try {
|
||||
serialHandler.close();
|
||||
} catch (Exception e) {
|
||||
log.error("关闭串口失败: {}", e.getMessage());
|
||||
} finally {
|
||||
serialHandler = null;
|
||||
}
|
||||
}
|
||||
return connect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开指定通道
|
||||
*
|
||||
* @param channel 通道号 (1-2)
|
||||
*/
|
||||
public boolean turnOn(int channel) {
|
||||
return sendCommand(CommandTypeEnum.ON, channel, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭指定通道
|
||||
*
|
||||
* @param channel 通道号 (1-2)
|
||||
*/
|
||||
public boolean turnOff(int channel) {
|
||||
return sendCommand(CommandTypeEnum.OFF, channel, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置通道亮度
|
||||
*
|
||||
* @param channel 通道号 (1-2)
|
||||
* @param brightness 亮度等级 (0-255)
|
||||
*/
|
||||
public boolean setBrightness(int channel, int brightness) {
|
||||
if (brightness < 0 || brightness > 255) {
|
||||
log.error("亮度等级必须在0-255之间");
|
||||
return false;
|
||||
}
|
||||
log.info("设置通道 {} 亮度为: {}", channel, brightness);
|
||||
return sendCommand(CommandTypeEnum.SET_BRIGHTNESS, channel, brightness);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取通道亮度
|
||||
*
|
||||
* @param channel 通道号 (1-2)
|
||||
* @return 亮度等级 (0-255),失败返回-1
|
||||
*/
|
||||
public int getBrightness(int channel) {
|
||||
int brightness = sendReadCommand(channel);
|
||||
if (brightness != -1) {
|
||||
log.info("通道 {} 当前亮度: {}", channel, brightness);
|
||||
}
|
||||
return brightness;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送命令到控制器
|
||||
*/
|
||||
private boolean sendCommand(CommandTypeEnum type, int channel, int brightness) {
|
||||
if (!checkAndReconnect()) {
|
||||
log.error("控制器未连接");
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] command = buildCommand(type, channel, brightness);
|
||||
|
||||
// 发送命令
|
||||
serialHandler.sendData(command);
|
||||
|
||||
// 等待响应(对于ON/OFF/SET命令,返回'$'表示成功)
|
||||
if (type != CommandTypeEnum.READ) {
|
||||
String response = serialHandler.receiveResponse(100);
|
||||
boolean success = response != null && response.contains("$");
|
||||
if (success) {
|
||||
log.debug("命令执行成功");
|
||||
} else {
|
||||
log.error("命令执行失败,响应: {}", response);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送读取命令并获取返回值
|
||||
*/
|
||||
private int sendReadCommand(int channel) {
|
||||
if (!checkAndReconnect()) {
|
||||
log.error("控制器未连接");
|
||||
return -1;
|
||||
}
|
||||
|
||||
byte[] command = buildCommand(CommandTypeEnum.READ, channel, 0);
|
||||
|
||||
// 发送命令
|
||||
serialHandler.sendData(command);
|
||||
|
||||
// 接收响应(返回格式同发送格式,包含亮度数据)
|
||||
String response = serialHandler.receiveResponse(200);
|
||||
if (response == null || !response.startsWith("$")) {
|
||||
log.error("读取亮度失败,响应: {}", response);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 解析返回的亮度值
|
||||
int brightness = parseBrightnessFromResponse(response);
|
||||
if (brightness == -1) {
|
||||
log.error("解析亮度值失败,响应: {}", response);
|
||||
}
|
||||
return brightness;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建命令字节数组
|
||||
* 格式: 特征字(1) + 指令字(1) + 通道字(1) + 数据(3) + 异或校验字(2)
|
||||
* 所有字节采用ASCII码
|
||||
* 数据部分:3个ASCII字符,表示亮度的十六进制值(高位在前)
|
||||
*/
|
||||
private byte[] buildCommand(CommandTypeEnum type, int channel, int brightness) {
|
||||
// 特征字: $ (ASCII 36)
|
||||
char featureChar = '$';
|
||||
|
||||
// 指令字
|
||||
char cmdChar = type.getCommandCode();
|
||||
|
||||
// 通道字 (1-2)
|
||||
char channelChar = (char)(channel + '0');
|
||||
|
||||
// 数据: 3字节,亮度的十六进制表示,高位在前
|
||||
// 亮度值范围0-255,需要转换为3个十六进制ASCII字符
|
||||
String dataStr;
|
||||
if (type == CommandTypeEnum.SET_BRIGHTNESS) {
|
||||
// 将亮度值转换为十六进制字符串,并确保是3位
|
||||
dataStr = String.format("%03X", brightness);
|
||||
} else {
|
||||
// ON/OFF/READ命令的数据字段固定为 "000"
|
||||
dataStr = "000";
|
||||
}
|
||||
|
||||
// 构建命令字符串用于计算校验和
|
||||
String cmdStr = featureChar + String.valueOf(cmdChar) + channelChar + dataStr;
|
||||
byte[] cmdBytes = cmdStr.getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
// 计算异或校验和
|
||||
byte xorSum = 0;
|
||||
for (int i = 0; i < cmdBytes.length; i++) {
|
||||
xorSum ^= cmdBytes[i];
|
||||
}
|
||||
|
||||
// 将校验和转换为2位十六进制ASCII码
|
||||
String xorStr = String.format("%02X", xorSum & 0xFF).toUpperCase();
|
||||
|
||||
// 最终命令字符串
|
||||
String fullCommand = cmdStr + xorStr;
|
||||
|
||||
log.debug("构建命令: {} (亮度: {} -> 十六进制: {})", fullCommand, brightness, dataStr);
|
||||
return fullCommand.getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 从响应字符串解析亮度值
|
||||
* 响应格式: $ + 指令字 + 通道字 + 数据(3) + 校验字(2)
|
||||
* 例如: "$43038E" 表示通道3亮度56
|
||||
*/
|
||||
private int parseBrightnessFromResponse(String response) {
|
||||
if (response == null || response.length() < 8) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
// 提取数据部分(第4-6个字符,索引3-5)
|
||||
String dataStr = response.substring(3, 6);
|
||||
return Integer.parseInt(dataStr);
|
||||
} catch (NumberFormatException e) {
|
||||
log.error("解析亮度值失败: {}", e.getMessage());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 便捷方法:设置所有通道亮度
|
||||
*
|
||||
* @param brightness 亮度等级 (0-255)
|
||||
*/
|
||||
public void setAllBrightness(int brightness) {
|
||||
log.info("设置所有通道亮度为: {}", brightness);
|
||||
for (int channel = 1; channel <= 2; channel++) {
|
||||
setBrightness(channel, brightness);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 便捷方法:关闭所有通道
|
||||
*/
|
||||
public void turnAllOff() {
|
||||
log.info("关闭所有通道");
|
||||
for (int channel = 1; channel <= 2; channel++) {
|
||||
turnOff(channel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 便捷方法:打开所有通道
|
||||
*/
|
||||
public void turnAllOn() {
|
||||
log.info("打开所有通道");
|
||||
for (int channel = 1; channel <= 2; channel++) {
|
||||
turnOn(channel);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
package top.wms.admin.light;
|
||||
|
||||
import com.fazecast.jSerialComm.SerialPort;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 串口通信处理器
|
||||
* 负责与DPA6024V-2T-1.0数字控制器进行串口通信
|
||||
*/
|
||||
@Slf4j
|
||||
public class SerialPortHandler {
|
||||
|
||||
private InputStream inputStream;
|
||||
private OutputStream outputStream;
|
||||
private SerialPort serialPort;
|
||||
|
||||
/**
|
||||
* 串口名称
|
||||
*/
|
||||
@Getter
|
||||
private final String portName;
|
||||
|
||||
/**
|
||||
* 波特率
|
||||
*/
|
||||
@Getter
|
||||
private final int baudRate;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param portName 串口名称,如 "COM3" (Windows) 或 "/dev/ttyUSB0" (Linux)
|
||||
* @param baudRate 波特率
|
||||
*/
|
||||
public SerialPortHandler(String portName, int baudRate) {
|
||||
this.portName = portName;
|
||||
this.baudRate = baudRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开串口连接
|
||||
*
|
||||
* @return 打开成功返回true,失败返回false
|
||||
*/
|
||||
public boolean open() {
|
||||
try {
|
||||
// 获取所有可用的串口
|
||||
SerialPort[] ports = SerialPort.getCommPorts();
|
||||
log.info("可用串口列表: {}", java.util.Arrays.stream(ports).map(SerialPort::getSystemPortName).toList());
|
||||
|
||||
// 查找指定的串口
|
||||
SerialPort targetPort = null;
|
||||
for (SerialPort port : ports) {
|
||||
String portName = port.getSystemPortName();
|
||||
log.debug("检查串口: {}", portName);
|
||||
if (portName.equals(this.portName)) {
|
||||
targetPort = port;
|
||||
log.info("找到目标串口: {}", portName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPort == null) {
|
||||
log.error("未找到串口: {}", this.portName);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 配置串口参数
|
||||
targetPort.setBaudRate(baudRate);
|
||||
targetPort.setNumDataBits(8);
|
||||
targetPort.setNumStopBits(1);
|
||||
targetPort.setParity(SerialPort.NO_PARITY);
|
||||
targetPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
|
||||
|
||||
// 打开串口
|
||||
boolean opened = targetPort.openPort();
|
||||
if (opened) {
|
||||
// 设置读取超时时间(毫秒)
|
||||
targetPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 1000, 0);
|
||||
this.serialPort = targetPort;
|
||||
this.inputStream = targetPort.getInputStream();
|
||||
this.outputStream = targetPort.getOutputStream();
|
||||
log.info("串口 {} 打开成功,波特率: {}", this.portName, baudRate);
|
||||
} else {
|
||||
log.error("串口 {} 打开失败", this.portName);
|
||||
}
|
||||
return opened;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("打开串口 {} 失败: {}", this.portName, e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查串口是否已打开
|
||||
*
|
||||
* @return 已打开返回true,否则返回false
|
||||
*/
|
||||
public boolean isOpen() {
|
||||
return serialPort != null && serialPort.isOpen();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送数据
|
||||
*
|
||||
* @param data 要发送的字节数组
|
||||
*/
|
||||
public void sendData(byte[] data) {
|
||||
try {
|
||||
// 验证串口是否正确打开
|
||||
if (serialPort == null || !serialPort.isOpen()) {
|
||||
log.error("串口 {} 未打开,无法发送数据", portName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (outputStream == null) {
|
||||
log.error("串口 {} 输出流未初始化", portName);
|
||||
return;
|
||||
}
|
||||
outputStream.write(data);
|
||||
outputStream.flush();
|
||||
log.info("串口 {} 发送数据: {}", portName, new String(data));
|
||||
} catch (IOException e) {
|
||||
log.error("串口 {} 发送数据失败: {}", portName, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送字符串数据
|
||||
*
|
||||
* @param data 要发送的字符串
|
||||
*/
|
||||
public void sendData(String data) {
|
||||
try {
|
||||
log.info("串口 {} 准备发送字符串: {}", portName, data);
|
||||
sendData(data.getBytes(StandardCharsets.US_ASCII));
|
||||
} catch (Exception e) {
|
||||
log.error("串口 {} 发送字符串数据失败: {}", portName, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收响应数据
|
||||
*
|
||||
* @param timeoutMs 超时时间(毫秒)
|
||||
* @return 接收到的字符串,超时或无数据返回null
|
||||
*/
|
||||
public String receiveResponse(int timeoutMs) {
|
||||
try {
|
||||
// 验证串口是否正确打开
|
||||
if (serialPort == null || !serialPort.isOpen()) {
|
||||
log.error("串口 {} 未打开,无法接收数据", portName);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 验证输入流是否初始化
|
||||
if (inputStream == null) {
|
||||
log.error("串口 {} 输入流未初始化", portName);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 等待数据到达
|
||||
long startTime = System.currentTimeMillis();
|
||||
while (inputStream.available() == 0 && (System.currentTimeMillis() - startTime) < timeoutMs) {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
// 读取数据
|
||||
byte[] buffer = new byte[1024];
|
||||
int available = inputStream.available();
|
||||
if (available > 0) {
|
||||
int len = inputStream.read(buffer, 0, Math.min(available, buffer.length));
|
||||
String response = new String(buffer, 0, len);
|
||||
log.info("串口 {} 接收数据: {}", portName, response);
|
||||
return response;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("串口 {} 接收响应失败: {}", portName, e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收指定长度的响应数据
|
||||
*
|
||||
* @param length 期望接收的字节数
|
||||
* @param timeoutMs 超时时间(毫秒)
|
||||
* @return 接收到的字符串,超时或无数据返回null
|
||||
*/
|
||||
public String receiveResponse(int length, int timeoutMs) {
|
||||
try {
|
||||
// 验证串口是否正确打开
|
||||
if (serialPort == null || !serialPort.isOpen()) {
|
||||
log.error("串口 {} 未打开,无法接收数据", portName);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 验证输入流是否初始化
|
||||
if (inputStream == null) {
|
||||
log.error("串口 {} 输入流未初始化", portName);
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[length];
|
||||
int bytesRead = 0;
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
while (bytesRead < length && (System.currentTimeMillis() - startTime) < timeoutMs) {
|
||||
if (inputStream.available() > 0) {
|
||||
int read = inputStream.read(buffer, bytesRead, length - bytesRead);
|
||||
if (read > 0) {
|
||||
bytesRead += read;
|
||||
}
|
||||
}
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
if (bytesRead > 0) {
|
||||
String response = new String(buffer, 0, bytesRead);
|
||||
log.info("串口 {} 接收数据: {}", portName, response);
|
||||
return response;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("串口 {} 接收响应失败: {}", portName, e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空输入缓冲区
|
||||
*/
|
||||
public void clearInputBuffer() {
|
||||
try {
|
||||
if (inputStream != null && inputStream.available() > 0) {
|
||||
byte[] buffer = new byte[inputStream.available()];
|
||||
inputStream.read(buffer);
|
||||
log.debug("清空输入缓冲区: {}", new String(buffer));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("清空输入缓冲区失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空输出缓冲区
|
||||
*/
|
||||
public void clearOutputBuffer() {
|
||||
try {
|
||||
if (outputStream != null) {
|
||||
outputStream.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("清空输出缓冲区失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭串口连接
|
||||
*/
|
||||
public void close() {
|
||||
try {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
inputStream = null;
|
||||
}
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
outputStream = null;
|
||||
}
|
||||
if (serialPort != null && serialPort.isOpen()) {
|
||||
serialPort.closePort();
|
||||
log.info("串口 {} 已关闭", portName);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("关闭串口失败: {}", e.getMessage());
|
||||
} finally {
|
||||
serialPort = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,14 @@
|
||||
package top.wms.admin.material.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import top.continew.starter.data.mp.base.BaseMapper;
|
||||
import top.wms.admin.material.model.entity.MaterialInfoDO;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import top.wms.admin.material.model.resp.MaterialInfoResp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -14,7 +20,16 @@ import java.util.List;
|
||||
*/
|
||||
@Repository
|
||||
public interface MaterialInfoMapper extends BaseMapper<MaterialInfoDO> {
|
||||
public int updateByName(List<MaterialInfoDO> list);
|
||||
int updateByName(@Param("list") List<MaterialInfoDO> list);
|
||||
|
||||
public int updateByCode(List<MaterialInfoDO> list);
|
||||
int updateByCode(@Param("list") List<MaterialInfoDO> list);
|
||||
|
||||
IPage<MaterialInfoResp> selectMaterialInfoPage(@Param("page") Page<Object> objectPage,
|
||||
@Param(Constants.WRAPPER) QueryWrapper<MaterialInfoDO> queryWrapper);
|
||||
|
||||
List<MaterialInfoResp> selectMaterialInfoExport(@Param(Constants.WRAPPER) QueryWrapper<MaterialInfoDO> queryWrapper);
|
||||
|
||||
void updateBatchNull();
|
||||
|
||||
int updateBatchByCode(List<MaterialInfoDO> materialInfoDOS);
|
||||
}
|
||||
|
||||
@@ -32,18 +32,54 @@ public class MaterialInfoDO extends BaseDO {
|
||||
*/
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* 打印物料编码
|
||||
*/
|
||||
private String encodingPrint;
|
||||
|
||||
/**
|
||||
* 物料单位重量(g)
|
||||
*/
|
||||
private BigDecimal unitWeight;
|
||||
|
||||
/*
|
||||
物料规格
|
||||
物料直径
|
||||
*/
|
||||
private String materialSpec;
|
||||
private Double materialSpec;
|
||||
|
||||
/**
|
||||
* 物料照片地址
|
||||
*/
|
||||
private String photoUrl;
|
||||
|
||||
/**
|
||||
* 物料品类ID
|
||||
*/
|
||||
private Long materialTypeId;
|
||||
|
||||
/**
|
||||
* 物料流程
|
||||
*/
|
||||
private String materialProcess;
|
||||
|
||||
/**
|
||||
* 灯光等级
|
||||
*/
|
||||
private Integer lightLevel;
|
||||
|
||||
/**
|
||||
* 颜色
|
||||
*/
|
||||
private String color;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记
|
||||
*/
|
||||
private String mark;
|
||||
|
||||
}
|
||||
|
||||
@@ -36,4 +36,18 @@ public class MaterialInfoQuery implements Serializable {
|
||||
@Schema(description = "物料编码")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
@Schema(description = "批次")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记
|
||||
*/
|
||||
@Schema(description = "标记")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String mark;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package top.wms.admin.material.model.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@Schema(description = "批次导入参数")
|
||||
public class BatchImportReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 导入会话KEY
|
||||
*/
|
||||
@Schema(description = "导入会话KEY", example = "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed")
|
||||
@NotBlank(message = "导入已过期,请重新上传")
|
||||
private String importKey;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package top.wms.admin.material.model.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@Schema(description = "物料信息导入行数据")
|
||||
public class BatchImportRowReq implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
@Schema(description = "物料编码")
|
||||
@NotBlank(message = "物料编码不能为空")
|
||||
@Length(max = 255, message = "物料编码长度不能超过 {max} 个字符")
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
@Schema(description = "批次")
|
||||
@NotBlank(message = "批次不能为空")
|
||||
@Length(max = 255, message = "批次长度不能超过 {max} 个字符")
|
||||
private String batch;
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package top.wms.admin.material.model.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
@@ -28,18 +29,44 @@ public class MaterialImportRowReq implements Serializable {
|
||||
*/
|
||||
@Schema(description = "物料编码")
|
||||
@NotBlank(message = "物料编码不能为空")
|
||||
@Length(max = 255, message = "物料编码长度不能超过 {max} 个字符")
|
||||
@Length(max = 64, message = "物料编码长度不能超过 {max} 个字符")
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* 物料单位重量(g)
|
||||
*/
|
||||
@Schema(description = "物料单位重量(g)")
|
||||
@NotNull(message = "物料单位重量不能为空")
|
||||
private BigDecimal unitWeight;
|
||||
|
||||
/**
|
||||
* 灯光等级
|
||||
*/
|
||||
@Schema(description = "灯光等级")
|
||||
private String lightLevelName;
|
||||
|
||||
/*
|
||||
* 物料规格
|
||||
* 物料直径
|
||||
* */
|
||||
@Schema(description = "物料规格")
|
||||
private String materialSpec;
|
||||
@Schema(description = "物料直径")
|
||||
private Double materialSpec;
|
||||
|
||||
/**
|
||||
* 物料品类名称
|
||||
*/
|
||||
@Schema(description = "物料品类名称")
|
||||
private String typeName;
|
||||
|
||||
/**
|
||||
* 流程名称
|
||||
*/
|
||||
@Schema(description = "物料流程")
|
||||
private String materialProcess;
|
||||
|
||||
/**
|
||||
* 颜色
|
||||
*/
|
||||
@Schema(description = "颜色")
|
||||
private String color;
|
||||
|
||||
}
|
||||
|
||||
@@ -37,20 +37,21 @@ public class MaterialInfoReq implements Serializable {
|
||||
*/
|
||||
@Schema(description = "物料编码")
|
||||
@NotBlank(message = "物料编码不能为空")
|
||||
@Length(max = 255, message = "物料编码长度不能超过 {max} 个字符")
|
||||
@Length(max = 64, message = "物料编码长度不能超过 {max} 个字符")
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* 物料单位重量(g)
|
||||
*/
|
||||
@Schema(description = "物料单位重量(g)")
|
||||
@NotNull(message = "物料单位重量不能为空")
|
||||
private Double unitWeight;
|
||||
|
||||
/*
|
||||
* 物料规格
|
||||
* */
|
||||
@Schema(description = "物料规格")
|
||||
private String materialSpec;
|
||||
* 物料直径
|
||||
* */
|
||||
@Schema(description = "物料直径")
|
||||
private Double materialSpec;
|
||||
|
||||
/**
|
||||
* 物料照片地址
|
||||
@@ -58,4 +59,43 @@ public class MaterialInfoReq implements Serializable {
|
||||
@Schema(description = "物料照片地址")
|
||||
@Length(max = 255, message = "物料照片地址长度不能超过 {max} 个字符")
|
||||
private String photoUrl;
|
||||
|
||||
/**
|
||||
* 物料品类ID
|
||||
*/
|
||||
@Schema(description = "物料品类ID")
|
||||
@NotNull(message = "物料品类ID不能为空")
|
||||
private Long materialTypeId;
|
||||
|
||||
/**
|
||||
* 流程ID
|
||||
*/
|
||||
@Schema(description = "流程ID")
|
||||
@NotBlank(message = "流程ID不能为空")
|
||||
private String materialProcess;
|
||||
|
||||
/**
|
||||
* 灯光等级
|
||||
*/
|
||||
@Schema(description = "灯光等级")
|
||||
private Integer lightLevel;
|
||||
|
||||
/**
|
||||
* 颜色
|
||||
*/
|
||||
@Schema(description = "颜色")
|
||||
private String color;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
@Schema(description = "批次")
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记
|
||||
*/
|
||||
@Schema(description = "标记")
|
||||
private String mark;
|
||||
|
||||
}
|
||||
|
||||
@@ -2,13 +2,12 @@ package top.wms.admin.material.model.resp;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnore;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import lombok.Data;
|
||||
import top.wms.admin.common.model.resp.BaseDetailResp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 物料信息信息
|
||||
@@ -27,29 +26,29 @@ public class MaterialInfoResp extends BaseDetailResp {
|
||||
* 物料名称
|
||||
*/
|
||||
@Schema(description = "物料名称")
|
||||
@ExcelProperty(value = "物料名称")
|
||||
@ExcelProperty(value = "物料名称", order = 1)
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@Schema(description = "物料编码")
|
||||
@ExcelProperty(value = "物料编码")
|
||||
@ExcelProperty(value = "物料编码", order = 2)
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* 物料单位重量(g)
|
||||
*/
|
||||
@Schema(description = "物料单位重量(g)")
|
||||
@ExcelProperty(value = "物料单位重量(g)")
|
||||
@ExcelProperty(value = "物料单位重量(g)", order = 3)
|
||||
private Double unitWeight;
|
||||
|
||||
/**
|
||||
* 物料规格
|
||||
* 物料直径
|
||||
*/
|
||||
@Schema(description = "物料规格")
|
||||
@ExcelProperty(value = "物料规格")
|
||||
private String materialSpec;
|
||||
@Schema(description = "物料直径")
|
||||
@ExcelProperty(value = "物料直径", order = 5)
|
||||
private Double materialSpec;
|
||||
|
||||
/**
|
||||
* 物料照片地址
|
||||
@@ -57,4 +56,68 @@ public class MaterialInfoResp extends BaseDetailResp {
|
||||
@Schema(description = "物料照片地址")
|
||||
@ExcelIgnore
|
||||
private String photoUrl;
|
||||
|
||||
/**
|
||||
* 物料品类名称
|
||||
*/
|
||||
@Schema(description = "物料品类名称")
|
||||
@ExcelProperty(value = "物料品类")
|
||||
private String typeName;
|
||||
|
||||
/**
|
||||
* 物料流程
|
||||
*/
|
||||
@Schema(description = "物料流程")
|
||||
@ExcelProperty(value = "物料流程")
|
||||
private String materialProcess;
|
||||
|
||||
/**
|
||||
* 物料品类ID
|
||||
*/
|
||||
@Schema(description = "物料品类ID")
|
||||
@ExcelIgnore
|
||||
private Long materialTypeId;
|
||||
|
||||
/**
|
||||
* 品类下行浮动范围(%)
|
||||
*/
|
||||
@Schema(description = "品类下行浮动范围(%)")
|
||||
@ExcelIgnore
|
||||
private BigDecimal downFloatRatio;
|
||||
|
||||
/**
|
||||
* 品类上行浮动范围(%)
|
||||
*/
|
||||
@Schema(description = "品类上行浮动范围(%)")
|
||||
@ExcelIgnore
|
||||
private BigDecimal upFloatRatio;
|
||||
|
||||
/**
|
||||
* 颜色灯光值
|
||||
*/
|
||||
@Schema(description = "灯光等级")
|
||||
@ExcelProperty(value = "灯光等级", order = 4)
|
||||
private Integer lightLevel;
|
||||
|
||||
/**
|
||||
* 颜色
|
||||
*/
|
||||
@Schema(description = "颜色")
|
||||
@ExcelProperty(value = "颜色", order = 6)
|
||||
private String color;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
@Schema(description = "批次")
|
||||
@ExcelProperty(value = "批次", order = 7)
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记
|
||||
*/
|
||||
@Schema(description = "标记")
|
||||
@ExcelProperty(value = "标记", order = 8)
|
||||
private String mark;
|
||||
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package top.wms.admin.material.service;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.continew.starter.extension.crud.service.BaseService;
|
||||
import top.wms.admin.material.model.entity.MaterialInfoDO;
|
||||
import top.wms.admin.material.model.query.MaterialInfoQuery;
|
||||
import top.wms.admin.material.model.req.BatchImportReq;
|
||||
import top.wms.admin.material.model.req.MaterialInfoImportReq;
|
||||
import top.wms.admin.material.model.req.MaterialInfoReq;
|
||||
import top.wms.admin.material.model.resp.MaterialImportParseResp;
|
||||
@@ -21,11 +21,21 @@ import java.io.IOException;
|
||||
*/
|
||||
public interface MaterialInfoService extends BaseService<MaterialInfoResp, MaterialInfoResp, MaterialInfoQuery, MaterialInfoReq> {
|
||||
|
||||
/*
|
||||
*
|
||||
* 根据编码查询物料信息
|
||||
* */
|
||||
public MaterialInfoDO getMaterialInfoByCode(String code);
|
||||
/**
|
||||
* 根据编码查询物料信息
|
||||
*
|
||||
* @param code 物料编码
|
||||
* @return 物料信息
|
||||
*/
|
||||
MaterialInfoResp getMaterialInfoByCode(String code);
|
||||
|
||||
/**
|
||||
* 根据物料ID查询亮度
|
||||
*
|
||||
* @param materialId 物料ID
|
||||
* @return 亮度
|
||||
*/
|
||||
Integer getBrightness(Long materialId);
|
||||
|
||||
/**
|
||||
* 下载导入模板
|
||||
@@ -56,9 +66,32 @@ public interface MaterialInfoService extends BaseService<MaterialInfoResp, Mater
|
||||
* */
|
||||
void uploadMaterialPhotos(MultipartFile file);
|
||||
|
||||
|
||||
/*
|
||||
* 称重时照片抓取
|
||||
* */
|
||||
String catchPhoto(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 下载批量导入模板
|
||||
*
|
||||
* @param response 响应对象
|
||||
* @throws IOException /
|
||||
*/
|
||||
void downloadBatchImportTemplate(HttpServletResponse response) throws IOException;
|
||||
|
||||
/**
|
||||
* 解析批量导入数据
|
||||
*
|
||||
* @param file 导入文件
|
||||
* @return 解析结果
|
||||
*/
|
||||
MaterialImportParseResp parseBatchImport(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 导入批量数据
|
||||
*
|
||||
* @param req 导入信息
|
||||
* @return 导入结果
|
||||
*/
|
||||
MaterialInfoImportResp importBatchMaterial(BatchImportReq req);
|
||||
}
|
||||
|
||||
@@ -5,29 +5,39 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import cn.hutool.core.util.*;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.validation.ValidationUtil;
|
||||
import cn.hutool.http.ContentType;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
|
||||
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dreamlu.mica.core.result.R;
|
||||
import org.dromara.x.file.storage.core.FileInfo;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.continew.starter.cache.redisson.util.RedisUtils;
|
||||
import top.continew.starter.core.exception.BusinessException;
|
||||
import top.continew.starter.core.validation.CheckUtils;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.query.SortQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
import top.continew.starter.extension.crud.service.BaseServiceImpl;
|
||||
import top.continew.starter.file.excel.util.ExcelUtils;
|
||||
import top.continew.starter.web.util.FileUploadUtils;
|
||||
import top.wms.admin.common.constant.CacheConstants;
|
||||
import top.wms.admin.common.context.UserContextHolder;
|
||||
@@ -35,13 +45,13 @@ import top.wms.admin.common.util.SecureUtils;
|
||||
import top.wms.admin.material.mapper.MaterialInfoMapper;
|
||||
import top.wms.admin.material.model.entity.MaterialInfoDO;
|
||||
import top.wms.admin.material.model.query.MaterialInfoQuery;
|
||||
import top.wms.admin.material.model.req.MaterialImportRowReq;
|
||||
import top.wms.admin.material.model.req.MaterialInfoImportReq;
|
||||
import top.wms.admin.material.model.req.MaterialInfoReq;
|
||||
import top.wms.admin.material.model.req.*;
|
||||
import top.wms.admin.material.model.resp.MaterialImportParseResp;
|
||||
import top.wms.admin.material.model.resp.MaterialInfoImportResp;
|
||||
import top.wms.admin.material.model.resp.MaterialInfoResp;
|
||||
import top.wms.admin.material.service.MaterialInfoService;
|
||||
import top.wms.admin.materialType.mapper.MaterialTypeMapper;
|
||||
import top.wms.admin.materialType.model.entity.MaterialTypeDO;
|
||||
import top.wms.admin.system.service.FileService;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
@@ -49,7 +59,6 @@ import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -57,7 +66,6 @@ import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import static top.wms.admin.system.enums.ImportPolicyEnum.*;
|
||||
import static top.wms.admin.system.enums.ImportPolicyEnum.SKIP;
|
||||
|
||||
/**
|
||||
* 物料信息业务实现
|
||||
@@ -74,13 +82,68 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl<MaterialInfoMapper,
|
||||
|
||||
private final FileService fileService;
|
||||
|
||||
private final MaterialTypeMapper materialTypeMapper;
|
||||
|
||||
@Override
|
||||
public MaterialInfoDO getMaterialInfoByCode(String code) {
|
||||
if (StrUtil.isNotBlank(code)) {
|
||||
return baseMapper.lambdaQuery().eq(MaterialInfoDO::getEncoding, code).one();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
public void beforeAdd(MaterialInfoReq materialInfoReq) {
|
||||
MaterialInfoDO materialInfoDO = baseMapper.selectOne(new LambdaQueryWrapper<MaterialInfoDO>()
|
||||
.eq(MaterialInfoDO::getEncoding, materialInfoReq.getEncoding()));
|
||||
CheckUtils.throwIf(materialInfoDO != null, "物料编码已存在");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeUpdate(MaterialInfoReq materialInfoReq, Long id) {
|
||||
MaterialInfoDO materialInfoDO = baseMapper.selectOne(new LambdaQueryWrapper<MaterialInfoDO>()
|
||||
.eq(MaterialInfoDO::getEncoding, materialInfoReq.getEncoding())
|
||||
.ne(MaterialInfoDO::getId, id));
|
||||
CheckUtils.throwIf(materialInfoDO != null, "物料编码已存在");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResp<MaterialInfoResp> page(MaterialInfoQuery query, PageQuery pageQuery) {
|
||||
QueryWrapper<MaterialInfoDO> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.like(StrUtil.isNotBlank(query.getMaterialName()), "mi.material_name", query.getMaterialName());
|
||||
queryWrapper.like(StrUtil.isNotBlank(query.getEncoding()), "mi.encoding", query.getEncoding());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getBatch()), "mi.batch", query.getBatch());
|
||||
this.sort(queryWrapper, pageQuery);
|
||||
|
||||
IPage<MaterialInfoResp> page = baseMapper.selectMaterialInfoPage(new Page<>(pageQuery.getPage(), pageQuery
|
||||
.getSize()), queryWrapper);
|
||||
|
||||
return PageResp.build(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void export(MaterialInfoQuery query, SortQuery sortQuery, HttpServletResponse response) {
|
||||
|
||||
QueryWrapper<MaterialInfoDO> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.like(StrUtil.isNotBlank(query.getMaterialName()), "mi.material_name", query.getMaterialName());
|
||||
queryWrapper.like(StrUtil.isNotBlank(query.getEncoding()), "mi.encoding", query.getEncoding());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getBatch()), "mi.batch", query.getBatch());
|
||||
this.sort(queryWrapper, sortQuery);
|
||||
|
||||
List<MaterialInfoResp> list = baseMapper.selectMaterialInfoExport(queryWrapper);
|
||||
ExcelUtils.export(list, "物料信息导出", MaterialInfoResp.class, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialInfoResp getMaterialInfoByCode(String code) {
|
||||
MaterialInfoResp materialInfoResp = new MaterialInfoResp();
|
||||
MaterialInfoDO materialInfoDO = baseMapper.lambdaQuery().eq(MaterialInfoDO::getEncoding, code).one();
|
||||
CheckUtils.throwIf(materialInfoDO == null, "物料信息不存在");
|
||||
MaterialTypeDO materialTypeDO = materialTypeMapper.selectById(materialInfoDO.getMaterialTypeId());
|
||||
CheckUtils.throwIf(materialTypeDO == null, "该物料对应类型不存在");
|
||||
BeanUtil.copyProperties(materialInfoDO, materialInfoResp);
|
||||
materialInfoResp.setUpFloatRatio(materialTypeDO.getUpFloatRatio());
|
||||
materialInfoResp.setDownFloatRatio(materialTypeDO.getDownFloatRatio());
|
||||
return materialInfoResp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getBrightness(Long materialId) {
|
||||
MaterialInfoDO materialInfoDO = baseMapper.selectById(materialId);
|
||||
CheckUtils.throwIf(materialInfoDO == null, "物料信息不存在");
|
||||
return materialInfoDO.getLightLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,10 +152,10 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl<MaterialInfoMapper,
|
||||
FileUploadUtils.download(response, ResourceUtil
|
||||
.getStream("templates/import/materialInfo.xlsx"), "物料信息导入模板.xlsx");
|
||||
} catch (Exception e) {
|
||||
log.error("下载用户导入模板失败:{}", e);
|
||||
log.error("下载物料信息导入模板失败:", e);
|
||||
response.setCharacterEncoding(CharsetUtil.UTF_8);
|
||||
response.setContentType(ContentType.JSON.toString());
|
||||
response.getWriter().write(JSONUtil.toJsonStr(R.fail("下载用户导入模板失败")));
|
||||
response.getWriter().write(JSONUtil.toJsonStr(R.fail("下载物料信息导入模板失败")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +171,7 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl<MaterialInfoMapper,
|
||||
.headRowNumber(1)
|
||||
.doReadSync();
|
||||
} catch (Exception e) {
|
||||
log.error("物料信息导入数据文件解析异常:{}", e);
|
||||
log.error("物料信息导入数据文件解析异常:", e);
|
||||
throw new BusinessException("数据文件解析异常");
|
||||
}
|
||||
// 总计行数
|
||||
@@ -126,10 +189,10 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl<MaterialInfoMapper,
|
||||
.anyMatch(encoding -> encoding != null && !seenCode.add(encoding));
|
||||
CheckUtils.throwIf(hasDuplicateEncoding, "存在重复物料编码,请检测数据");
|
||||
|
||||
// 查询重复用户
|
||||
// 查询重复物料名
|
||||
materialImportResp
|
||||
.setDuplicateNameRows(countExistByField(validRowList, MaterialImportRowReq::getMaterialName, MaterialInfoDO::getMaterialName, false));
|
||||
// 查询重复邮箱
|
||||
// 查询重复物料编码
|
||||
materialImportResp
|
||||
.setDuplicateCodeRows(countExistByField(validRowList, MaterialImportRowReq::getEncoding, MaterialInfoDO::getEncoding, false));
|
||||
// 设置导入会话并缓存数据,有效期10分钟
|
||||
@@ -157,33 +220,47 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl<MaterialInfoMapper,
|
||||
List<String> existName = listExistByField(importMaterialList, MaterialImportRowReq::getMaterialName, MaterialInfoDO::getMaterialName);
|
||||
List<String> existCode = listExistByField(importMaterialList, MaterialImportRowReq::getEncoding, MaterialInfoDO::getEncoding);
|
||||
CheckUtils.throwIf(isExitImportMaterial(req, importMaterialList, existName, existCode), "数据不符合导入策略,已退出导入");
|
||||
|
||||
//查询物料品类
|
||||
List<String> collect = importMaterialList.stream().map(MaterialImportRowReq::getTypeName).distinct().toList();
|
||||
Map<String, Long> materialTypeMap = new HashMap<>();
|
||||
if (CollUtil.isNotEmpty(collect)) {
|
||||
List<MaterialTypeDO> materialTypeList = materialTypeMapper
|
||||
.selectList(new LambdaQueryWrapper<MaterialTypeDO>().in(MaterialTypeDO::getTypeName, collect));
|
||||
materialTypeMap = materialTypeList.stream()
|
||||
.collect(Collectors.toMap(MaterialTypeDO::getTypeName, MaterialTypeDO::getId, (k1, v1) -> v1));
|
||||
}
|
||||
|
||||
// 批量操作数据库集合
|
||||
List<MaterialInfoDO> insertList = new ArrayList<>();
|
||||
List<MaterialInfoDO> updateByNameList = new ArrayList<>();
|
||||
List<MaterialInfoDO> updateByCodeList = new ArrayList<>();
|
||||
// ID生成器
|
||||
// IdGenerator idGenerator = DefaultIdGeneratorProvider.INSTANCE.getShare();
|
||||
for (MaterialImportRowReq row : importMaterialList) {
|
||||
if (isSkipMaterialImport(req, row, existName, existCode)) {
|
||||
// 按规则跳过该行
|
||||
continue;
|
||||
}
|
||||
MaterialInfoDO materialDO = BeanUtil.toBeanIgnoreError(row, MaterialInfoDO.class);
|
||||
materialDO.setUnitWeight(NumberUtil.isValidNumber(row.getUnitWeight()) ? row.getUnitWeight() : null);
|
||||
materialDO.setMaterialSpec(StrUtil.isNotBlank(row.getMaterialSpec()) ? row.getMaterialSpec() : null);
|
||||
materialDO.setMaterialSpec(row.getMaterialSpec());
|
||||
materialDO.setColor(row.getColor());
|
||||
materialDO.setMaterialProcess(StrUtil.isNotBlank(row.getMaterialProcess())
|
||||
? row.getMaterialProcess()
|
||||
: null);
|
||||
materialDO.setMaterialTypeId(materialTypeMap.get(row.getTypeName()));
|
||||
materialDO.setLightLevel(StrUtil.isNotBlank(row.getLightLevelName())
|
||||
? Integer.parseInt(row.getLightLevelName())
|
||||
: null);
|
||||
// 修改 or 新增
|
||||
if (UPDATE.validate(req.getDuplicateName(), row.getMaterialName(), existName)) {
|
||||
materialDO.setMaterialName(row.getMaterialName());
|
||||
materialDO.setUpdateTime(LocalDateTime.now());
|
||||
materialDO.setUpdateUser(UserContextHolder.getUserId());
|
||||
updateByNameList.add(materialDO);
|
||||
} else if (UPDATE.validate(req.getDuplicateCode(), row.getEncoding(), existCode)) {
|
||||
materialDO.setEncoding(row.getEncoding());
|
||||
materialDO.setUpdateTime(LocalDateTime.now());
|
||||
materialDO.setUpdateUser(UserContextHolder.getUserId());
|
||||
updateByCodeList.add(materialDO);
|
||||
} else {
|
||||
// materialDO.setId(idGenerator.generate());
|
||||
insertList.add(materialDO);
|
||||
}
|
||||
}
|
||||
@@ -227,16 +304,17 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl<MaterialInfoMapper,
|
||||
*/
|
||||
private List<MaterialImportRowReq> filterImportData(List<MaterialImportRowReq> importRowList) {
|
||||
// 校验过滤
|
||||
List<MaterialImportRowReq> list = importRowList.stream()
|
||||
.filter(row -> ValidationUtil.validate(row).isEmpty())
|
||||
.toList();
|
||||
// 物料名去重
|
||||
return list.stream()
|
||||
.collect(Collectors.toMap(MaterialImportRowReq::getMaterialName, row -> row, (existing,
|
||||
replacement) -> existing))
|
||||
.values()
|
||||
.stream()
|
||||
.toList();
|
||||
return importRowList.stream().filter(row -> ValidationUtil.validate(row).isEmpty()).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤无效的导入用户数据(批量导入不严格校验数据)
|
||||
*
|
||||
* @param importRowList 导入数据
|
||||
*/
|
||||
private List<BatchImportRowReq> filterImportData2(List<BatchImportRowReq> importRowList) {
|
||||
// 校验过滤
|
||||
return importRowList.stream().filter(row -> ValidationUtil.validate(row).isEmpty()).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -321,7 +399,7 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl<MaterialInfoMapper,
|
||||
// 1. 初始化物料编码-照片地址Map
|
||||
Map<String, String> codeUrlMap = new HashMap<>();
|
||||
// 物料照片存储路径(自定义,比如按日期分目录)
|
||||
String photoStoragePath = "/" + DateUtil.today() + "/";
|
||||
String photoStoragePath = "material/";
|
||||
|
||||
try (ZipInputStream zipInputStream = new ZipInputStream(zipFile.getInputStream())) {
|
||||
ZipEntry zipEntry;
|
||||
@@ -333,7 +411,7 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl<MaterialInfoMapper,
|
||||
}
|
||||
// 2. 提取物料编码(照片名 = 物料编码,去掉后缀)
|
||||
String fileName = zipEntry.getName();
|
||||
log.info("正在处理的照片:" + fileName);
|
||||
log.info("正在处理的照片:{}", fileName);
|
||||
//去除windows或linux环境下 可能存在的多层级目录
|
||||
if (fileName.contains("/")) {
|
||||
fileName = fileName.substring(fileName.lastIndexOf("/") + 1);
|
||||
@@ -360,7 +438,7 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl<MaterialInfoMapper,
|
||||
.equals("jpg") ? "jpeg" : imageExt), imageBytes);
|
||||
|
||||
// 6. 调用upload方法上传图片
|
||||
FileInfo fileInfo = fileService.upload(singleImageFile, photoStoragePath, null, true, true);
|
||||
FileInfo fileInfo = fileService.upload(singleImageFile, photoStoragePath, null, false, false);
|
||||
|
||||
// 7. 将物料编码和图片URL存入Map
|
||||
codeUrlMap.put(materialCode, fileInfo.getUrl());
|
||||
@@ -413,13 +491,95 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl<MaterialInfoMapper,
|
||||
.forEach(code -> log.warn("物料编码 [{}] 不存在,照片更新失败", code));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String catchPhoto(MultipartFile file){
|
||||
public String catchPhoto(MultipartFile file) {
|
||||
String photoStoragePath = "catch" + DateUtil.today() + "/";
|
||||
FileInfo fileInfo = fileService.upload(file, photoStoragePath, null, true, true);
|
||||
CheckUtils.throwIfNull(fileInfo,"照片上传失败");
|
||||
CheckUtils.throwIfNull(fileInfo, "照片上传失败");
|
||||
return fileInfo.getUrl();
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void downloadBatchImportTemplate(HttpServletResponse response) throws IOException {
|
||||
try {
|
||||
FileUploadUtils.download(response, ResourceUtil.getStream("templates/import/batch.xlsx"), "批次导入模板.xlsx");
|
||||
} catch (Exception e) {
|
||||
log.error("下载批次导入模板失败:", e);
|
||||
response.setCharacterEncoding(CharsetUtil.UTF_8);
|
||||
response.setContentType(ContentType.JSON.toString());
|
||||
response.getWriter().write(JSONUtil.toJsonStr(R.fail("下载批次导入模板失败")));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialImportParseResp parseBatchImport(MultipartFile file) {
|
||||
MaterialImportParseResp materialImportResp = new MaterialImportParseResp();
|
||||
List<BatchImportRowReq> importRowList;
|
||||
// 读取表格数据
|
||||
try {
|
||||
importRowList = EasyExcel.read(file.getInputStream())
|
||||
.head(BatchImportRowReq.class)
|
||||
.sheet()
|
||||
.headRowNumber(1)
|
||||
.doReadSync();
|
||||
} catch (Exception e) {
|
||||
log.error("物料信息导入数据文件解析异常:", e);
|
||||
throw new BusinessException("数据文件解析异常");
|
||||
}
|
||||
// 总计行数
|
||||
materialImportResp.setTotalRows(importRowList.size());
|
||||
CheckUtils.throwIfEmpty(importRowList, "数据文件格式错误");
|
||||
// 有效行数:过滤无效数据
|
||||
List<BatchImportRowReq> validRowList = this.filterImportData2(importRowList);
|
||||
materialImportResp.setValidRows(validRowList.size());
|
||||
CheckUtils.throwIfEmpty(validRowList, "数据文件格式错误");
|
||||
|
||||
Set<String> batchSet = validRowList.stream().map(BatchImportRowReq::getBatch).collect(Collectors.toSet());
|
||||
if (batchSet.size() > 1) {
|
||||
throw new BusinessException("存在不同批次数据,请检查批次信息");
|
||||
}
|
||||
|
||||
validRowList = validRowList.stream().distinct().collect(Collectors.toList());
|
||||
// 设置导入会话并缓存数据,有效期10分钟
|
||||
String importKey = UUID.fastUUID().toString(true);
|
||||
RedisUtils.set(CacheConstants.DATA_IMPORT_KEY + importKey, JSONUtil.toJsonStr(validRowList), Duration
|
||||
.ofMinutes(10));
|
||||
materialImportResp.setImportKey(importKey);
|
||||
return materialImportResp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialInfoImportResp importBatchMaterial(BatchImportReq req) {
|
||||
// 校验导入会话是否过期
|
||||
List<BatchImportRowReq> batchImportRowReqs;
|
||||
try {
|
||||
String data = RedisUtils.get(CacheConstants.DATA_IMPORT_KEY + req.getImportKey());
|
||||
batchImportRowReqs = JSONUtil.toList(data, BatchImportRowReq.class);
|
||||
CheckUtils.throwIf(CollUtil.isEmpty(batchImportRowReqs), "导入已过期,请重新上传");
|
||||
} catch (Exception e) {
|
||||
log.error("导入异常:", e);
|
||||
throw new BusinessException("导入已过期,请重新上传");
|
||||
}
|
||||
|
||||
// 转换为MaterialInfoDO列表
|
||||
List<MaterialInfoDO> materialInfoDOS = batchImportRowReqs.stream().map(row -> {
|
||||
MaterialInfoDO materialInfoDO = new MaterialInfoDO();
|
||||
materialInfoDO.setEncoding(row.getEncoding());
|
||||
materialInfoDO.setBatch(row.getBatch());
|
||||
materialInfoDO.setUpdateUser(UserContextHolder.getUserId());
|
||||
return materialInfoDO;
|
||||
}).toList();
|
||||
|
||||
// 批量操作数据库集合
|
||||
try {
|
||||
InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().blockAttack(true).build());
|
||||
baseMapper.updateBatchNull();
|
||||
} finally {
|
||||
InterceptorIgnoreHelper.clearIgnoreStrategy();
|
||||
}
|
||||
int totalUpdateCount = baseMapper.updateBatchByCode(materialInfoDOS);
|
||||
RedisUtils.delete(CacheConstants.DATA_IMPORT_KEY + req.getImportKey());
|
||||
return new MaterialInfoImportResp(materialInfoDOS.size(), 0, totalUpdateCount);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package top.wms.admin.materialProcess.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import top.continew.starter.data.mp.base.BaseMapper;
|
||||
import top.wms.admin.materialProcess.model.entity.MaterialProcessDO;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 海康物料流程 Mapper
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 17:22
|
||||
*/
|
||||
@Repository
|
||||
public interface MaterialProcessMapper extends BaseMapper<MaterialProcessDO> {
|
||||
|
||||
void updateByName(@Param("list") List<MaterialProcessDO> updateByNameList);
|
||||
|
||||
void updateByCode(@Param("list") List<MaterialProcessDO> updateByCodeList);
|
||||
|
||||
String getCodeByMaterial(@Param("materialCode") String materialCode);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package top.wms.admin.materialProcess.mapstruct;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.wms.admin.materialProcess.model.entity.MaterialProcessDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface MaterialProcessConvert {
|
||||
|
||||
@Mapping(source = "id", target = "value")
|
||||
@Mapping(source = "processName", target = "label")
|
||||
LabelValueResp labelValue(MaterialProcessDO materialProcessDO);
|
||||
|
||||
List<LabelValueResp> labelValueList(List<MaterialProcessDO> materialProcessDOList);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package top.wms.admin.materialProcess.model.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
||||
import top.wms.admin.common.model.entity.BaseDO;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 海康物料流程实体
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 17:22
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_material_process")
|
||||
public class MaterialProcessDO extends BaseDO {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程名称
|
||||
*/
|
||||
private String processName;
|
||||
|
||||
/**
|
||||
* 流程编码
|
||||
*/
|
||||
private String processCode;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package top.wms.admin.materialProcess.model.query;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.continew.starter.data.core.annotation.Query;
|
||||
import top.continew.starter.data.core.enums.QueryType;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.*;
|
||||
|
||||
/**
|
||||
* 海康物料流程查询条件
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 17:22
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "海康物料流程查询条件")
|
||||
public class MaterialProcessQuery implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程名称
|
||||
*/
|
||||
@Schema(description = "流程名称")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String processName;
|
||||
|
||||
/**
|
||||
* 流程编码
|
||||
*/
|
||||
@Schema(description = "流程编码")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String processCode;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package top.wms.admin.materialProcess.model.req;
|
||||
|
||||
import lombok.Data;
|
||||
import top.wms.admin.system.enums.ImportPolicyEnum;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 物料流程导入请求
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/20
|
||||
*/
|
||||
@Data
|
||||
public class MaterialProcessImportReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 导入key
|
||||
*/
|
||||
private String importKey;
|
||||
|
||||
/**
|
||||
* 重复流程名称处理策略: 0-跳过 1-更新 2-退出
|
||||
*/
|
||||
private ImportPolicyEnum duplicateName;
|
||||
|
||||
/**
|
||||
* 重复流程编码处理策略: 0-跳过 1-更新 2-退出
|
||||
*/
|
||||
private ImportPolicyEnum duplicateCode;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package top.wms.admin.materialProcess.model.req;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 物料流程导入行数据
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/20
|
||||
*/
|
||||
@Data
|
||||
public class MaterialProcessImportRowReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程名称
|
||||
*/
|
||||
@NotBlank(message = "流程名称不能为空")
|
||||
private String processName;
|
||||
|
||||
/**
|
||||
* 流程编码
|
||||
*/
|
||||
@NotBlank(message = "流程编码不能为空")
|
||||
private String processCode;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package top.wms.admin.materialProcess.model.req;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.*;
|
||||
|
||||
/**
|
||||
* 创建或修改海康物料流程参数
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 17:22
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "创建或修改海康物料流程参数")
|
||||
public class MaterialProcessReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程名称
|
||||
*/
|
||||
@Schema(description = "流程名称")
|
||||
@NotBlank(message = "流程名称不能为空")
|
||||
@Length(max = 255, message = "流程名称长度不能超过 {max} 个字符")
|
||||
private String processName;
|
||||
|
||||
/**
|
||||
* 流程编码
|
||||
*/
|
||||
@Schema(description = "流程编码")
|
||||
@NotBlank(message = "流程编码不能为空")
|
||||
@Length(max = 255, message = "流程编码长度不能超过 {max} 个字符")
|
||||
private String processCode;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package top.wms.admin.materialProcess.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
|
||||
import top.wms.admin.common.model.resp.BaseDetailResp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.*;
|
||||
|
||||
/**
|
||||
* 海康物料流程详情信息
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 17:22
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@Schema(description = "海康物料流程详情信息")
|
||||
public class MaterialProcessDetailResp extends BaseDetailResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程名称
|
||||
*/
|
||||
@Schema(description = "流程名称")
|
||||
@ExcelProperty(value = "流程名称")
|
||||
private String processName;
|
||||
|
||||
/**
|
||||
* 流程编码
|
||||
*/
|
||||
@Schema(description = "流程编码")
|
||||
@ExcelProperty(value = "流程编码")
|
||||
private String processCode;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package top.wms.admin.materialProcess.model.resp;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(description = "用户导入解析结果")
|
||||
public class MaterialProcessImportParseResp implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 导入会话 Key
|
||||
*/
|
||||
@Schema(description = "导入会话Key", example = "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed")
|
||||
private String importKey;
|
||||
|
||||
/**
|
||||
* 总计行数
|
||||
*/
|
||||
@Schema(description = "总计行数", example = "100")
|
||||
private Integer totalRows;
|
||||
|
||||
/**
|
||||
* 有效行数
|
||||
*/
|
||||
@Schema(description = "有效行数", example = "100")
|
||||
private Integer validRows;
|
||||
|
||||
/**
|
||||
* 重复名称行数
|
||||
*/
|
||||
@Schema(description = "重复名称行数", example = "100")
|
||||
private Integer duplicateNameRows;
|
||||
|
||||
/**
|
||||
* 重复编码行数
|
||||
*/
|
||||
@Schema(description = "重复编码行数", example = "100")
|
||||
private Integer duplicateCodeRows;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package top.wms.admin.materialProcess.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 物料流程导入响应
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/20
|
||||
*/
|
||||
@Data
|
||||
public class MaterialProcessImportResp implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 总处理数
|
||||
*/
|
||||
private Integer totalHandleCount;
|
||||
|
||||
/**
|
||||
* 新增数
|
||||
*/
|
||||
private Integer insertCount;
|
||||
|
||||
/**
|
||||
* 更新数
|
||||
*/
|
||||
private Integer updateCount;
|
||||
|
||||
public MaterialProcessImportResp(Integer totalHandleCount, Integer insertCount, Integer updateCount) {
|
||||
this.totalHandleCount = totalHandleCount;
|
||||
this.insertCount = insertCount;
|
||||
this.updateCount = updateCount;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package top.wms.admin.materialProcess.model.resp;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.wms.admin.common.model.resp.BaseDetailResp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.*;
|
||||
|
||||
/**
|
||||
* 海康物料流程信息
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 17:22
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "海康物料流程信息")
|
||||
public class MaterialProcessResp extends BaseDetailResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程名称
|
||||
*/
|
||||
@Schema(description = "流程名称")
|
||||
@ExcelProperty(value = "流程名称", order = 1)
|
||||
private String processName;
|
||||
|
||||
/**
|
||||
* 流程编码
|
||||
*/
|
||||
@Schema(description = "流程编码")
|
||||
@ExcelProperty(value = "流程编码", order = 2)
|
||||
private String processCode;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package top.wms.admin.materialProcess.service;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.continew.starter.extension.crud.service.BaseService;
|
||||
import top.wms.admin.materialProcess.model.query.MaterialProcessQuery;
|
||||
import top.wms.admin.materialProcess.model.req.MaterialProcessImportReq;
|
||||
import top.wms.admin.materialProcess.model.req.MaterialProcessReq;
|
||||
import top.wms.admin.materialProcess.model.resp.MaterialProcessImportParseResp;
|
||||
import top.wms.admin.materialProcess.model.resp.MaterialProcessImportResp;
|
||||
import top.wms.admin.materialProcess.model.resp.MaterialProcessResp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 海康物料流程业务接口
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 17:22
|
||||
*/
|
||||
public interface MaterialProcessService extends BaseService<MaterialProcessResp, MaterialProcessResp, MaterialProcessQuery, MaterialProcessReq> {
|
||||
|
||||
/**
|
||||
* 获取流程下拉列表
|
||||
*
|
||||
* @return 流程下拉列表
|
||||
*/
|
||||
List<LabelValueResp> getSelectList();
|
||||
|
||||
/**
|
||||
* 下载导入模板
|
||||
*
|
||||
* @param response 响应对象
|
||||
*/
|
||||
void downloadImportTemplate(HttpServletResponse response) throws Exception;
|
||||
|
||||
/**
|
||||
* 解析导入文件
|
||||
*
|
||||
* @param file 导入文件
|
||||
* @return 解析响应
|
||||
*/
|
||||
MaterialProcessImportParseResp parseImport(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 导入物料流程
|
||||
*
|
||||
* @param req 导入请求
|
||||
* @return 导入响应
|
||||
*/
|
||||
MaterialProcessImportResp importMaterialProcess(MaterialProcessImportReq req);
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
package top.wms.admin.materialProcess.service.impl;
|
||||
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.extra.validation.ValidationUtil;
|
||||
import cn.hutool.http.ContentType;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.dreamlu.mica.core.result.R;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.continew.starter.cache.redisson.util.RedisUtils;
|
||||
import top.continew.starter.core.exception.BusinessException;
|
||||
import top.continew.starter.core.validation.CheckUtils;
|
||||
import top.continew.starter.extension.crud.model.query.SortQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.continew.starter.extension.crud.service.BaseServiceImpl;
|
||||
import top.continew.starter.file.excel.util.ExcelUtils;
|
||||
import top.continew.starter.web.util.FileUploadUtils;
|
||||
import top.wms.admin.common.constant.CacheConstants;
|
||||
import top.wms.admin.common.context.UserContextHolder;
|
||||
import top.wms.admin.materialProcess.mapper.MaterialProcessMapper;
|
||||
import top.wms.admin.materialProcess.mapstruct.MaterialProcessConvert;
|
||||
import top.wms.admin.materialProcess.model.entity.MaterialProcessDO;
|
||||
import top.wms.admin.materialProcess.model.query.MaterialProcessQuery;
|
||||
import top.wms.admin.materialProcess.model.req.MaterialProcessImportReq;
|
||||
import top.wms.admin.materialProcess.model.req.MaterialProcessImportRowReq;
|
||||
import top.wms.admin.materialProcess.model.req.MaterialProcessReq;
|
||||
import top.wms.admin.materialProcess.model.resp.MaterialProcessImportParseResp;
|
||||
import top.wms.admin.materialProcess.model.resp.MaterialProcessImportResp;
|
||||
import top.wms.admin.materialProcess.model.resp.MaterialProcessResp;
|
||||
import top.wms.admin.materialProcess.service.MaterialProcessService;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static top.wms.admin.system.enums.ImportPolicyEnum.*;
|
||||
|
||||
/**
|
||||
* 海康物料流程业务实现
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 17:22
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MaterialProcessServiceImpl extends BaseServiceImpl<MaterialProcessMapper, MaterialProcessDO, MaterialProcessResp, MaterialProcessResp, MaterialProcessQuery, MaterialProcessReq> implements MaterialProcessService {
|
||||
|
||||
private final MaterialProcessConvert materialProcessConvert;
|
||||
|
||||
@Override
|
||||
public void beforeAdd(MaterialProcessReq req) {
|
||||
// 校验流程名称是否重复
|
||||
MaterialProcessDO processDO = baseMapper.selectOne(Wrappers.lambdaQuery(MaterialProcessDO.class)
|
||||
.eq(MaterialProcessDO::getProcessName, req.getProcessName()));
|
||||
CheckUtils.throwIf(ObjectUtil.isNotEmpty(processDO), "流程名称已存在");
|
||||
// 校验流程编码是否重复
|
||||
processDO = baseMapper.selectOne(Wrappers.lambdaQuery(MaterialProcessDO.class)
|
||||
.eq(MaterialProcessDO::getProcessCode, req.getProcessCode()));
|
||||
CheckUtils.throwIf(ObjectUtil.isNotEmpty(processDO), "流程编码已存在");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeUpdate(MaterialProcessReq req, Long id) {
|
||||
// 校验流程名称是否重复
|
||||
MaterialProcessDO processDO = baseMapper.selectOne(Wrappers.lambdaQuery(MaterialProcessDO.class)
|
||||
.eq(MaterialProcessDO::getProcessName, req.getProcessName())
|
||||
.ne(MaterialProcessDO::getId, id));
|
||||
CheckUtils.throwIf(ObjectUtil.isNotEmpty(processDO), "流程名称已存在");
|
||||
// 校验流程编码是否重复
|
||||
processDO = baseMapper.selectOne(Wrappers.lambdaQuery(MaterialProcessDO.class)
|
||||
.eq(MaterialProcessDO::getProcessCode, req.getProcessCode())
|
||||
.ne(MaterialProcessDO::getId, id));
|
||||
CheckUtils.throwIf(ObjectUtil.isNotEmpty(processDO), "流程编码已存在");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void export(MaterialProcessQuery query, SortQuery sortQuery, HttpServletResponse response) {
|
||||
List<MaterialProcessResp> list = super.list(query, sortQuery, this.getDetailClass());
|
||||
list.forEach(super::fill);
|
||||
ExcelUtils.export(list, "物料流程导出", MaterialProcessResp.class, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LabelValueResp> getSelectList() {
|
||||
List<MaterialProcessDO> materialProcessDOS = baseMapper.selectList(new QueryWrapper<>());
|
||||
return materialProcessConvert.labelValueList(materialProcessDOS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadImportTemplate(HttpServletResponse response) throws Exception {
|
||||
try {
|
||||
FileUploadUtils.download(response, ResourceUtil
|
||||
.getStream("templates/import/materialProcess.xlsx"), "物料流程导入模板.xlsx");
|
||||
} catch (Exception e) {
|
||||
log.error("下载用户导入模板失败:", e);
|
||||
response.setCharacterEncoding(CharsetUtil.UTF_8);
|
||||
response.setContentType(ContentType.JSON.toString());
|
||||
response.getWriter().write(JSONUtil.toJsonStr(R.fail("下载用户导入模板失败")));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialProcessImportParseResp parseImport(MultipartFile file) {
|
||||
MaterialProcessImportParseResp importResp = new MaterialProcessImportParseResp();
|
||||
List<MaterialProcessImportRowReq> importRowList;
|
||||
// 读取表格数据
|
||||
try {
|
||||
importRowList = com.alibaba.excel.EasyExcel.read(file.getInputStream())
|
||||
.head(MaterialProcessImportRowReq.class)
|
||||
.sheet()
|
||||
.headRowNumber(1)
|
||||
.doReadSync();
|
||||
} catch (Exception e) {
|
||||
log.error("物料流程导入数据文件解析异常:", e);
|
||||
throw new BusinessException("数据文件解析异常");
|
||||
}
|
||||
// 总计行数
|
||||
importResp.setTotalRows(importRowList.size());
|
||||
CheckUtils.throwIfEmpty(importRowList, "数据文件格式错误");
|
||||
// 有效行数:过滤无效数据
|
||||
List<MaterialProcessImportRowReq> validRowList = this.filterImportData(importRowList);
|
||||
importResp.setValidRows(validRowList.size());
|
||||
CheckUtils.throwIfEmpty(validRowList, "数据文件格式错误");
|
||||
|
||||
// 检测表格内数据是否合法
|
||||
Set<String> seenCode = new HashSet<>();
|
||||
boolean hasDuplicateCode = validRowList.stream()
|
||||
.map(MaterialProcessImportRowReq::getProcessCode)
|
||||
.anyMatch(code -> code != null && !seenCode.add(code));
|
||||
CheckUtils.throwIf(hasDuplicateCode, "存在重复流程编码,请检测数据");
|
||||
|
||||
// 查询重复流程名称
|
||||
importResp
|
||||
.setDuplicateNameRows(countExistByField(validRowList, MaterialProcessImportRowReq::getProcessName, MaterialProcessDO::getProcessName));
|
||||
// 查询重复流程编码
|
||||
importResp
|
||||
.setDuplicateCodeRows(countExistByField(validRowList, MaterialProcessImportRowReq::getProcessCode, MaterialProcessDO::getProcessCode));
|
||||
// 设置导入会话并缓存数据,有效期10分钟
|
||||
String importKey = java.util.UUID.randomUUID().toString().replace("-", "");
|
||||
RedisUtils.set(CacheConstants.DATA_IMPORT_KEY + importKey, JSONUtil.toJsonStr(validRowList), Duration
|
||||
.ofMinutes(10));
|
||||
importResp.setImportKey(importKey);
|
||||
return importResp;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public MaterialProcessImportResp importMaterialProcess(MaterialProcessImportReq req) {
|
||||
// 校验导入会话是否过期
|
||||
List<MaterialProcessImportRowReq> importMaterialList;
|
||||
try {
|
||||
String data = RedisUtils.get(CacheConstants.DATA_IMPORT_KEY + req.getImportKey());
|
||||
importMaterialList = JSONUtil.toList(data, MaterialProcessImportRowReq.class);
|
||||
CheckUtils.throwIf(ObjectUtil.isEmpty(importMaterialList), "导入已过期,请重新上传");
|
||||
} catch (Exception e) {
|
||||
log.error("导入异常:", e);
|
||||
throw new BusinessException("导入已过期,请重新上传");
|
||||
}
|
||||
// 已存在数据查询
|
||||
List<String> existName = listExistByField(importMaterialList, MaterialProcessImportRowReq::getProcessName, MaterialProcessDO::getProcessName);
|
||||
List<String> existCode = listExistByField(importMaterialList, MaterialProcessImportRowReq::getProcessCode, MaterialProcessDO::getProcessCode);
|
||||
CheckUtils.throwIf(isExitImportMaterial(req, importMaterialList, existName, existCode), "数据不符合导入策略,已退出导入");
|
||||
|
||||
// 批量操作数据库集合
|
||||
List<MaterialProcessDO> insertList = new ArrayList<>();
|
||||
List<MaterialProcessDO> updateByNameList = new ArrayList<>();
|
||||
List<MaterialProcessDO> updateByCodeList = new ArrayList<>();
|
||||
// 处理导入数据
|
||||
for (MaterialProcessImportRowReq row : importMaterialList) {
|
||||
if (isSkipMaterialImport(req, row, existName, existCode)) {
|
||||
continue;
|
||||
}
|
||||
MaterialProcessDO materialProcessDO = new MaterialProcessDO();
|
||||
materialProcessDO.setProcessName(row.getProcessName());
|
||||
materialProcessDO.setProcessCode(row.getProcessCode());
|
||||
// 修改 or 新增
|
||||
if (UPDATE.validate(req.getDuplicateName(), row.getProcessName(), existName)) {
|
||||
materialProcessDO.setProcessCode(row.getProcessCode());
|
||||
materialProcessDO.setUpdateUser(UserContextHolder.getUserId());
|
||||
updateByNameList.add(materialProcessDO);
|
||||
} else if (UPDATE.validate(req.getDuplicateCode(), row.getProcessCode(), existCode)) {
|
||||
materialProcessDO.setProcessCode(row.getProcessCode());
|
||||
materialProcessDO.setUpdateUser(UserContextHolder.getUserId());
|
||||
updateByCodeList.add(materialProcessDO);
|
||||
} else {
|
||||
insertList.add(materialProcessDO);
|
||||
}
|
||||
}
|
||||
doImportMaterial(insertList, updateByNameList, updateByCodeList);
|
||||
RedisUtils.delete(CacheConstants.DATA_IMPORT_KEY + req.getImportKey());
|
||||
int insertCount = insertList.size();
|
||||
int updateByNameCount = updateByNameList.size();
|
||||
int updateByCodeCount = updateByCodeList.size();
|
||||
int totalUpdateCount = updateByNameCount + updateByCodeCount;
|
||||
int totalHandleCount = insertCount + totalUpdateCount;
|
||||
return new MaterialProcessImportResp(totalHandleCount, // 总处理数
|
||||
insertCount, // 新增数
|
||||
totalUpdateCount // 更新总数
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按指定数据集获取数据库已存在的数量
|
||||
*
|
||||
* @param materialRowList 导入的数据源
|
||||
* @param rowField 导入数据的字段
|
||||
* @param dbField 对比数据库的字段
|
||||
* @return 存在的数量
|
||||
*/
|
||||
private int countExistByField(List<MaterialProcessImportRowReq> materialRowList,
|
||||
Function<MaterialProcessImportRowReq, String> rowField,
|
||||
SFunction<MaterialProcessDO, ?> dbField) {
|
||||
List<String> fieldValues = materialRowList.stream().map(rowField).filter(Objects::nonNull).toList();
|
||||
if (fieldValues.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return (int)this.count(Wrappers.<MaterialProcessDO>lambdaQuery().in(dbField, fieldValues));
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤无效的导入数据
|
||||
*
|
||||
* @param importRowList 导入数据
|
||||
*/
|
||||
private List<MaterialProcessImportRowReq> filterImportData(List<MaterialProcessImportRowReq> importRowList) {
|
||||
// 校验过滤
|
||||
return importRowList.stream().filter(row -> ValidationUtil.validate(row).isEmpty()).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 按指定数据集获取数据库已存在内容
|
||||
*
|
||||
* @param materialRowList 导入的数据源
|
||||
* @param rowField 导入数据的字段
|
||||
* @param dbField 对比数据库的字段
|
||||
* @return 存在的内容
|
||||
*/
|
||||
private List<String> listExistByField(List<MaterialProcessImportRowReq> materialRowList,
|
||||
Function<MaterialProcessImportRowReq, String> rowField,
|
||||
SFunction<MaterialProcessDO, String> dbField) {
|
||||
List<String> fieldValues = materialRowList.stream().map(rowField).filter(Objects::nonNull).toList();
|
||||
if (fieldValues.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<MaterialProcessDO> materialProcessDOList = baseMapper.selectList(Wrappers.<MaterialProcessDO>lambdaQuery()
|
||||
.in(dbField, fieldValues)
|
||||
.select(dbField));
|
||||
return materialProcessDOList.stream().map(dbField).filter(Objects::nonNull).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否退出导入
|
||||
*
|
||||
* @param req 导入参数
|
||||
* @param list 导入数据
|
||||
* @param existName 导入数据中已存在的流程名称
|
||||
* @param existCode 导入数据中已存在的流程编码
|
||||
* @return 是否退出
|
||||
*/
|
||||
private boolean isExitImportMaterial(MaterialProcessImportReq req,
|
||||
List<MaterialProcessImportRowReq> list,
|
||||
List<String> existName,
|
||||
List<String> existCode) {
|
||||
return list.stream()
|
||||
.anyMatch(row -> EXIT.validate(req.getDuplicateName(), row.getProcessName(), existName) || EXIT.validate(req
|
||||
.getDuplicateCode(), row.getProcessCode(), existCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否跳过导入
|
||||
*
|
||||
* @param req 导入参数
|
||||
* @param row 导入数据
|
||||
* @param existName 导入数据中已存在的流程名称
|
||||
* @param existCode 导入数据中已存在的流程编码
|
||||
* @return 是否跳过
|
||||
*/
|
||||
private boolean isSkipMaterialImport(MaterialProcessImportReq req,
|
||||
MaterialProcessImportRowReq row,
|
||||
List<String> existName,
|
||||
List<String> existCode) {
|
||||
return SKIP.validate(req.getDuplicateName(), row.getProcessName(), existName) || SKIP.validate(req
|
||||
.getDuplicateCode(), row.getProcessCode(), existCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入物料流程
|
||||
*
|
||||
* @param insertList 新增流程
|
||||
* @param updateByNameList 根据名称修改流程
|
||||
* @param updateByCodeList 根据编码修改流程
|
||||
*/
|
||||
private void doImportMaterial(List<MaterialProcessDO> insertList,
|
||||
List<MaterialProcessDO> updateByNameList,
|
||||
List<MaterialProcessDO> updateByCodeList) {
|
||||
if (insertList != null && !insertList.isEmpty()) {
|
||||
baseMapper.insertBatch(insertList);
|
||||
}
|
||||
if (updateByNameList != null && !updateByNameList.isEmpty()) {
|
||||
baseMapper.updateByName(updateByNameList);
|
||||
}
|
||||
if (updateByCodeList != null && !updateByCodeList.isEmpty()) {
|
||||
baseMapper.updateByCode(updateByCodeList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.wms.admin.materialType.mapper;
|
||||
|
||||
import top.continew.starter.data.mp.base.BaseMapper;
|
||||
import top.wms.admin.materialType.model.entity.MaterialTypeDO;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* 物料品类 Mapper
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 11:18
|
||||
*/
|
||||
@Repository
|
||||
public interface MaterialTypeMapper extends BaseMapper<MaterialTypeDO> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package top.wms.admin.materialType.mapstruct;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.wms.admin.materialType.model.entity.MaterialTypeDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface MaterialTypeConvert {
|
||||
|
||||
@Mapping(source = "id", target = "value")
|
||||
@Mapping(source = "typeName", target = "label")
|
||||
LabelValueResp labelValue(MaterialTypeDO materialTypeDO);
|
||||
|
||||
List<LabelValueResp> labelValueList(List<MaterialTypeDO> materialTypeDOList);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package top.wms.admin.materialType.model.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
||||
import top.wms.admin.common.model.entity.BaseDO;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 物料品类实体
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 11:18
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_material_type")
|
||||
public class MaterialTypeDO extends BaseDO {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 品类名称
|
||||
*/
|
||||
private String typeName;
|
||||
|
||||
/**
|
||||
* 品类下行浮动范围(%)
|
||||
*/
|
||||
private BigDecimal downFloatRatio;
|
||||
|
||||
/**
|
||||
* 品类上行浮动范围(%)
|
||||
*/
|
||||
private BigDecimal upFloatRatio;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package top.wms.admin.materialType.model.query;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.continew.starter.data.core.annotation.Query;
|
||||
import top.continew.starter.data.core.enums.QueryType;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.*;
|
||||
|
||||
/**
|
||||
* 物料品类查询条件
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 11:18
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "物料品类查询条件")
|
||||
public class MaterialTypeQuery implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 品类名称
|
||||
*/
|
||||
@Schema(description = "品类名称")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String typeName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package top.wms.admin.materialType.model.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import top.wms.admin.system.enums.ImportPolicyEnum;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@Schema(description = "物料品类导入参数")
|
||||
public class MaterialTypeImportReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 导入会话KEY
|
||||
*/
|
||||
@Schema(description = "导入会话KEY", example = "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed")
|
||||
@NotBlank(message = "导入已过期,请重新上传")
|
||||
private String importKey;
|
||||
|
||||
/**
|
||||
* 品类名称重复策略
|
||||
*/
|
||||
@Schema(description = "品类名称重复策略", example = "1")
|
||||
@NotNull(message = "品类名称重复策略不能为空")
|
||||
private ImportPolicyEnum duplicateTypeName;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package top.wms.admin.materialType.model.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Schema(description = "物料品类导入行数据")
|
||||
public class MaterialTypeImportRowReq implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 品类名称
|
||||
*/
|
||||
@Schema(description = "品类名称")
|
||||
@NotBlank(message = "品类名称不能为空")
|
||||
@Length(max = 255, message = "品类名称长度不能超过 {max} 个字符")
|
||||
private String typeName;
|
||||
|
||||
/**
|
||||
* 品类下行浮动范围(%)
|
||||
*/
|
||||
@Schema(description = "品类下行浮动范围(%)")
|
||||
@NotNull(message = "品类下行浮动范围不能为空")
|
||||
private BigDecimal downFloatRatio;
|
||||
|
||||
/**
|
||||
* 品类上行浮动范围(%)
|
||||
*/
|
||||
@Schema(description = "品类上行浮动范围(%)")
|
||||
@NotNull(message = "品类上行浮动范围不能为空")
|
||||
private BigDecimal upFloatRatio;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package top.wms.admin.materialType.model.req;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.*;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 创建或修改物料品类参数
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 11:18
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "创建或修改物料品类参数")
|
||||
public class MaterialTypeReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 品类名称
|
||||
*/
|
||||
@Schema(description = "品类名称")
|
||||
@NotBlank(message = "品类名称不能为空")
|
||||
@Length(max = 255, message = "品类名称长度不能超过 {max} 个字符")
|
||||
private String typeName;
|
||||
|
||||
/**
|
||||
* 品类浮动比
|
||||
*/
|
||||
@Schema(description = "品类浮动比")
|
||||
@NotNull(message = "品类下行浮动范围不能为空")
|
||||
private BigDecimal downFloatRatio;
|
||||
|
||||
/**
|
||||
* 品类上行浮动范围(%)
|
||||
*/
|
||||
@Schema(description = "品类上行浮动范围(%)")
|
||||
@NotNull(message = "品类上行浮动范围不能为空")
|
||||
private BigDecimal upFloatRatio;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package top.wms.admin.materialType.model.resp;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(description = "物料品类导入解析结果")
|
||||
public class MaterialTypeImportParseResp implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 导入会话 Key
|
||||
*/
|
||||
@Schema(description = "导入会话Key", example = "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed")
|
||||
private String importKey;
|
||||
|
||||
/**
|
||||
* 总计行数
|
||||
*/
|
||||
@Schema(description = "总计行数", example = "100")
|
||||
private Integer totalRows;
|
||||
|
||||
/**
|
||||
* 有效行数
|
||||
*/
|
||||
@Schema(description = "有效行数", example = "100")
|
||||
private Integer validRows;
|
||||
|
||||
/**
|
||||
* 重复品类名称行数
|
||||
*/
|
||||
@Schema(description = "重复品类名称行数", example = "100")
|
||||
private Integer duplicateNameRows;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package top.wms.admin.materialType.model.resp;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@Schema(description = "物料品类导入结果")
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MaterialTypeImportResp implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 总计行数
|
||||
*/
|
||||
@Schema(description = "总计行数", example = "100")
|
||||
private Integer totalRows;
|
||||
|
||||
/**
|
||||
* 新增行数
|
||||
*/
|
||||
@Schema(description = "新增行数", example = "100")
|
||||
private Integer insertRows;
|
||||
|
||||
/**
|
||||
* 修改行数
|
||||
*/
|
||||
@Schema(description = "修改行数", example = "100")
|
||||
private Integer updateRows;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package top.wms.admin.materialType.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.wms.admin.common.model.resp.BaseDetailResp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.*;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 物料品类信息
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 11:18
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "物料品类信息")
|
||||
public class MaterialTypeResp extends BaseDetailResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 品类名称
|
||||
*/
|
||||
@Schema(description = "品类名称")
|
||||
private String typeName;
|
||||
|
||||
/**
|
||||
* 品类下行浮动范围(%)
|
||||
*/
|
||||
@Schema(description = "品类下行浮动范围(%)")
|
||||
private BigDecimal downFloatRatio;
|
||||
|
||||
/**
|
||||
* 品类上行浮动范围(%)
|
||||
*/
|
||||
@Schema(description = "品类上行浮动范围(%)")
|
||||
private BigDecimal upFloatRatio;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package top.wms.admin.materialType.service;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.continew.starter.extension.crud.service.BaseService;
|
||||
import top.wms.admin.materialType.model.query.MaterialTypeQuery;
|
||||
import top.wms.admin.materialType.model.req.MaterialTypeImportReq;
|
||||
import top.wms.admin.materialType.model.req.MaterialTypeReq;
|
||||
import top.wms.admin.materialType.model.resp.MaterialTypeImportParseResp;
|
||||
import top.wms.admin.materialType.model.resp.MaterialTypeImportResp;
|
||||
import top.wms.admin.materialType.model.resp.MaterialTypeResp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 物料品类业务接口
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 11:18
|
||||
*/
|
||||
public interface MaterialTypeService extends BaseService<MaterialTypeResp, MaterialTypeResp, MaterialTypeQuery, MaterialTypeReq> {
|
||||
|
||||
List<LabelValueResp> getSelectList();
|
||||
|
||||
void downloadImportTemplate(HttpServletResponse response) throws IOException;
|
||||
|
||||
MaterialTypeImportParseResp parseImport(MultipartFile file);
|
||||
|
||||
MaterialTypeImportResp importMaterial(MaterialTypeImportReq req);
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package top.wms.admin.materialType.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.extra.validation.ValidationUtil;
|
||||
import cn.hutool.http.ContentType;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dreamlu.mica.core.result.R;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.continew.starter.cache.redisson.util.RedisUtils;
|
||||
import top.continew.starter.core.exception.BusinessException;
|
||||
import top.continew.starter.core.validation.CheckUtils;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.continew.starter.extension.crud.service.BaseServiceImpl;
|
||||
import top.continew.starter.web.util.FileUploadUtils;
|
||||
import top.wms.admin.common.constant.CacheConstants;
|
||||
import top.wms.admin.common.context.UserContextHolder;
|
||||
import top.wms.admin.materialType.mapper.MaterialTypeMapper;
|
||||
import top.wms.admin.materialType.mapstruct.MaterialTypeConvert;
|
||||
import top.wms.admin.materialType.model.entity.MaterialTypeDO;
|
||||
import top.wms.admin.materialType.model.query.MaterialTypeQuery;
|
||||
import top.wms.admin.materialType.model.req.MaterialTypeImportReq;
|
||||
import top.wms.admin.materialType.model.req.MaterialTypeImportRowReq;
|
||||
import top.wms.admin.materialType.model.req.MaterialTypeReq;
|
||||
import top.wms.admin.materialType.model.resp.MaterialTypeImportParseResp;
|
||||
import top.wms.admin.materialType.model.resp.MaterialTypeImportResp;
|
||||
import top.wms.admin.materialType.model.resp.MaterialTypeResp;
|
||||
import top.wms.admin.materialType.service.MaterialTypeService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static top.wms.admin.system.enums.ImportPolicyEnum.*;
|
||||
|
||||
/**
|
||||
* 物料品类业务实现
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/03/16 11:18
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class MaterialTypeServiceImpl extends BaseServiceImpl<MaterialTypeMapper, MaterialTypeDO, MaterialTypeResp, MaterialTypeResp, MaterialTypeQuery, MaterialTypeReq> implements MaterialTypeService {
|
||||
|
||||
private final MaterialTypeConvert materialTypeConvert;
|
||||
|
||||
@Override
|
||||
public List<LabelValueResp> getSelectList() {
|
||||
List<MaterialTypeDO> materialTypeDOS = baseMapper.selectList(new QueryWrapper<>());
|
||||
return materialTypeConvert.labelValueList(materialTypeDOS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadImportTemplate(HttpServletResponse response) throws IOException {
|
||||
try {
|
||||
FileUploadUtils.download(response, ResourceUtil
|
||||
.getStream("templates/import/materialType.xlsx"), "物料品类导入模板.xlsx");
|
||||
} catch (Exception e) {
|
||||
log.error("下载物料品类导入模板失败:", e);
|
||||
response.setCharacterEncoding(CharsetUtil.UTF_8);
|
||||
response.setContentType(ContentType.JSON.toString());
|
||||
response.getWriter().write(JSONUtil.toJsonStr(R.fail("下载批次导入模板失败")));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialTypeImportParseResp parseImport(MultipartFile file) {
|
||||
MaterialTypeImportParseResp materialTypeImportResp = new MaterialTypeImportParseResp();
|
||||
List<MaterialTypeImportRowReq> importRowList;
|
||||
try {
|
||||
importRowList = EasyExcel.read(file.getInputStream())
|
||||
.head(MaterialTypeImportRowReq.class)
|
||||
.sheet()
|
||||
.headRowNumber(1)
|
||||
.doReadSync();
|
||||
} catch (Exception e) {
|
||||
log.error("物料品类导入数据文件解析异常:", e);
|
||||
throw new BusinessException("数据文件解析异常");
|
||||
}
|
||||
materialTypeImportResp.setTotalRows(importRowList.size());
|
||||
CheckUtils.throwIfEmpty(importRowList, "数据文件格式错误");
|
||||
List<MaterialTypeImportRowReq> validRowList = this.filterImportData(importRowList);
|
||||
materialTypeImportResp.setValidRows(validRowList.size());
|
||||
CheckUtils.throwIfEmpty(validRowList, "数据文件格式错误");
|
||||
|
||||
Set<String> seenTypeName = new HashSet<>();
|
||||
boolean hasDuplicateTypeName = validRowList.stream()
|
||||
.map(MaterialTypeImportRowReq::getTypeName)
|
||||
.anyMatch(typeName -> typeName != null && !seenTypeName.add(typeName));
|
||||
CheckUtils.throwIf(hasDuplicateTypeName, "存在重复品类名称,请检测数据");
|
||||
|
||||
materialTypeImportResp
|
||||
.setDuplicateNameRows(countExistByField(validRowList, MaterialTypeImportRowReq::getTypeName, MaterialTypeDO::getTypeName, false));
|
||||
|
||||
String importKey = UUID.fastUUID().toString(true);
|
||||
RedisUtils.set(CacheConstants.DATA_IMPORT_KEY + importKey, JSONUtil.toJsonStr(validRowList), Duration
|
||||
.ofMinutes(10));
|
||||
materialTypeImportResp.setImportKey(importKey);
|
||||
return materialTypeImportResp;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public MaterialTypeImportResp importMaterial(MaterialTypeImportReq req) {
|
||||
List<MaterialTypeImportRowReq> importMaterialTypeList;
|
||||
try {
|
||||
String data = RedisUtils.get(CacheConstants.DATA_IMPORT_KEY + req.getImportKey());
|
||||
importMaterialTypeList = JSONUtil.toList(data, MaterialTypeImportRowReq.class);
|
||||
CheckUtils.throwIf(CollUtil.isEmpty(importMaterialTypeList), "导入已过期,请重新上传");
|
||||
} catch (Exception e) {
|
||||
log.error("导入异常:", e);
|
||||
throw new BusinessException("导入已过期,请重新上传");
|
||||
}
|
||||
|
||||
List<String> existTypeName = listExistByField(importMaterialTypeList, MaterialTypeImportRowReq::getTypeName, MaterialTypeDO::getTypeName);
|
||||
CheckUtils.throwIf(isExitImportMaterialType(req, importMaterialTypeList, existTypeName), "数据不符合导入策略,已退出导入");
|
||||
|
||||
List<MaterialTypeDO> insertList = new ArrayList<>();
|
||||
List<MaterialTypeDO> updateList = new ArrayList<>();
|
||||
|
||||
for (MaterialTypeImportRowReq row : importMaterialTypeList) {
|
||||
if (isSkipImportMaterialType(req, row, existTypeName)) {
|
||||
continue;
|
||||
}
|
||||
MaterialTypeDO materialTypeDO = BeanUtil.toBeanIgnoreError(row, MaterialTypeDO.class);
|
||||
|
||||
if (UPDATE.validate(req.getDuplicateTypeName(), row.getTypeName(), existTypeName)) {
|
||||
materialTypeDO.setTypeName(row.getTypeName());
|
||||
materialTypeDO.setUpdateUser(UserContextHolder.getUserId());
|
||||
updateList.add(materialTypeDO);
|
||||
} else {
|
||||
insertList.add(materialTypeDO);
|
||||
}
|
||||
}
|
||||
|
||||
doImportMaterialType(insertList, updateList);
|
||||
RedisUtils.delete(CacheConstants.DATA_IMPORT_KEY + req.getImportKey());
|
||||
|
||||
int insertCount = insertList.size();
|
||||
int updateCount = updateList.size();
|
||||
int totalHandleCount = insertCount + updateCount;
|
||||
return new MaterialTypeImportResp(totalHandleCount, insertCount, updateCount);
|
||||
}
|
||||
|
||||
private int countExistByField(List<MaterialTypeImportRowReq> materialTypeRowList,
|
||||
Function<MaterialTypeImportRowReq, String> rowField,
|
||||
com.baomidou.mybatisplus.core.toolkit.support.SFunction<MaterialTypeDO, ?> dbField,
|
||||
boolean fieldEncrypt) {
|
||||
List<String> fieldValues = materialTypeRowList.stream().map(rowField).filter(Objects::nonNull).toList();
|
||||
if (fieldValues.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return (int)this.count(Wrappers.<MaterialTypeDO>lambdaQuery().in(dbField, fieldValues));
|
||||
}
|
||||
|
||||
private List<MaterialTypeImportRowReq> filterImportData(List<MaterialTypeImportRowReq> importRowList) {
|
||||
return importRowList.stream().filter(row -> ValidationUtil.validate(row).isEmpty()).toList();
|
||||
}
|
||||
|
||||
private List<String> listExistByField(List<MaterialTypeImportRowReq> materialTypeRowList,
|
||||
Function<MaterialTypeImportRowReq, String> rowField,
|
||||
com.baomidou.mybatisplus.core.toolkit.support.SFunction<MaterialTypeDO, String> dbField) {
|
||||
List<String> fieldValues = materialTypeRowList.stream().map(rowField).filter(Objects::nonNull).toList();
|
||||
if (fieldValues.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<MaterialTypeDO> materialTypeDOList = baseMapper.selectList(Wrappers.<MaterialTypeDO>lambdaQuery()
|
||||
.in(dbField, fieldValues)
|
||||
.select(dbField));
|
||||
return materialTypeDOList.stream().map(dbField).filter(Objects::nonNull).toList();
|
||||
}
|
||||
|
||||
private boolean isExitImportMaterialType(MaterialTypeImportReq req,
|
||||
List<MaterialTypeImportRowReq> list,
|
||||
List<String> existTypeName) {
|
||||
return list.stream()
|
||||
.anyMatch(row -> EXIT.validate(req.getDuplicateTypeName(), row.getTypeName(), existTypeName));
|
||||
}
|
||||
|
||||
private boolean isSkipImportMaterialType(MaterialTypeImportReq req,
|
||||
MaterialTypeImportRowReq row,
|
||||
List<String> existTypeName) {
|
||||
return SKIP.validate(req.getDuplicateTypeName(), row.getTypeName(), existTypeName);
|
||||
}
|
||||
|
||||
private void doImportMaterialType(List<MaterialTypeDO> insertList, List<MaterialTypeDO> updateList) {
|
||||
if (CollUtil.isNotEmpty(insertList)) {
|
||||
baseMapper.insertBatch(insertList);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(updateList)) {
|
||||
for (MaterialTypeDO materialTypeDO : updateList) {
|
||||
baseMapper.update(materialTypeDO, Wrappers.<MaterialTypeDO>lambdaUpdate()
|
||||
.eq(MaterialTypeDO::getTypeName, materialTypeDO.getTypeName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.wms.admin.print.mapper;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
import top.continew.starter.data.mp.base.BaseMapper;
|
||||
import top.wms.admin.print.model.entity.PrintInfoDO;
|
||||
|
||||
/**
|
||||
* 打印记录 Mapper
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/06/15 16:57
|
||||
*/
|
||||
@Repository
|
||||
public interface PrintInfoMapper extends BaseMapper<PrintInfoDO> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.wms.admin.print.mapper;
|
||||
|
||||
import top.continew.starter.data.mp.base.BaseMapper;
|
||||
import top.wms.admin.print.model.entity.PrintDO;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* 打印记录 Mapper
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/06/15 16:57
|
||||
*/
|
||||
@Repository
|
||||
public interface PrintMapper extends BaseMapper<PrintDO> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package top.wms.admin.print.model.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
||||
import top.wms.admin.common.model.entity.BaseDO;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 打印记录实体
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/06/15 16:57
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_print")
|
||||
public class PrintDO extends BaseDO {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* 打印编码
|
||||
*/
|
||||
private String encodingPrint;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 打印名称
|
||||
*/
|
||||
private String materialNamePrint;
|
||||
|
||||
/**
|
||||
* 任务工单号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 任务工单id
|
||||
*/
|
||||
private Long workerOrderId;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标签数量
|
||||
*/
|
||||
private Integer labelCount;
|
||||
|
||||
/**
|
||||
* 打印类型 0:明细标签打印 1:整体标签打印
|
||||
*/
|
||||
private Integer labelType;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package top.wms.admin.print.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 打印记录详情实体
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/06/15 16:58
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_print_info")
|
||||
public class PrintInfoDO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long printId;
|
||||
|
||||
/**
|
||||
* 打印编码
|
||||
*/
|
||||
private String encodingPrint;
|
||||
|
||||
/**
|
||||
* 检验签字
|
||||
*/
|
||||
private String inspectionSignature;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
private String mark;
|
||||
|
||||
/**
|
||||
* 打印名称
|
||||
*/
|
||||
private String materialNamePrint;
|
||||
|
||||
/**
|
||||
* 包装签字
|
||||
*/
|
||||
private String packingSignature;
|
||||
|
||||
/**
|
||||
* 生产日期
|
||||
*/
|
||||
private String productionDate;
|
||||
|
||||
/**
|
||||
* 二维码数据
|
||||
*/
|
||||
private String qrCodeData;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标重
|
||||
*/
|
||||
private BigDecimal totalCalculatedWeight;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer totalCount;
|
||||
|
||||
/**
|
||||
* 实重
|
||||
*/
|
||||
private BigDecimal totalWeight;
|
||||
|
||||
/**
|
||||
* 任务工单ID
|
||||
*/
|
||||
private Long workerOrderId;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package top.wms.admin.print.model.query;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.continew.starter.data.core.annotation.Query;
|
||||
import top.continew.starter.data.core.enums.QueryType;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.*;
|
||||
|
||||
/**
|
||||
* 打印记录查询条件
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/06/15 16:57
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "打印记录查询条件")
|
||||
public class PrintQuery implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 打印编码
|
||||
*/
|
||||
@Schema(description = "打印编码")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String encodingPrint;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
@Schema(description = "物料名称")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 打印名称
|
||||
*/
|
||||
@Schema(description = "打印名称")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String materialNamePrint;
|
||||
|
||||
/**
|
||||
* 任务工单号
|
||||
*/
|
||||
@Schema(description = "任务工单号")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 任务工单id
|
||||
*/
|
||||
@Schema(description = "任务工单id")
|
||||
@Query(type = QueryType.EQ)
|
||||
private Long workerOrderId;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
@Schema(description = "批次")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@Schema(description = "创建人")
|
||||
@Query(type = QueryType.EQ)
|
||||
private Long createUser;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description = "创建时间")
|
||||
@Query(type = QueryType.EQ)
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package top.wms.admin.print.model.req;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 创建或修改打印记录详情参数
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/06/15 17:03
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "创建或修改打印记录详情参数")
|
||||
public class PrintInfoReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 打印编码
|
||||
*/
|
||||
@Schema(description = "打印编码")
|
||||
@Length(max = 255, message = "打印编码长度不能超过 {max} 个字符")
|
||||
private String encodingPrint;
|
||||
|
||||
/**
|
||||
* 检验签字
|
||||
*/
|
||||
@Schema(description = "检验签字")
|
||||
@Length(max = 25, message = "检验签字长度不能超过 {max} 个字符")
|
||||
private String inspectionSignature;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
@Schema(description = "标记号")
|
||||
@Length(max = 25, message = "标记号长度不能超过 {max} 个字符")
|
||||
private String mark;
|
||||
|
||||
/**
|
||||
* 打印名称
|
||||
*/
|
||||
@Schema(description = "打印名称")
|
||||
@NotBlank(message = "打印名称不能为空")
|
||||
@Length(max = 255, message = "打印名称长度不能超过 {max} 个字符")
|
||||
private String materialNamePrint;
|
||||
|
||||
/**
|
||||
* 包装签字
|
||||
*/
|
||||
@Schema(description = "包装签字")
|
||||
@Length(max = 25, message = "包装签字长度不能超过 {max} 个字符")
|
||||
private String packingSignature;
|
||||
|
||||
/**
|
||||
* 生产日期
|
||||
*/
|
||||
@Schema(description = "生产日期")
|
||||
@Length(max = 50, message = "生产日期长度不能超过 {max} 个字符")
|
||||
private String productionDate;
|
||||
|
||||
/**
|
||||
* 二维码数据
|
||||
*/
|
||||
@Schema(description = "二维码数据")
|
||||
@Length(max = 500, message = "二维码数据长度不能超过 {max} 个字符")
|
||||
private String qrCodeData;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
@Schema(description = "批次")
|
||||
@NotBlank(message = "批次不能为空")
|
||||
@Length(max = 255, message = "批次长度不能超过 {max} 个字符")
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标重
|
||||
*/
|
||||
@Schema(description = "标重")
|
||||
private BigDecimal totalCalculatedWeight;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
@Schema(description = "数量")
|
||||
private Integer totalCount;
|
||||
|
||||
/**
|
||||
* 实重
|
||||
*/
|
||||
@Schema(description = "实重")
|
||||
private BigDecimal totalWeight;
|
||||
|
||||
/**
|
||||
* 任务工单ID
|
||||
*/
|
||||
@Schema(description = "任务工单ID")
|
||||
private Long workerOrderId;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package top.wms.admin.print.model.req;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.wms.admin.print.model.entity.PrintInfoDO;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 创建或修改打印记录参数
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/06/15 17:04
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "创建或修改打印记录参数")
|
||||
public class PrintReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@Schema(description = "物料编码")
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* 打印编码
|
||||
*/
|
||||
@Schema(description = "打印编码")
|
||||
private String encodingPrint;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
@Schema(description = "物料名称")
|
||||
@NotBlank(message = "物料名称不能为空")
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 打印名称
|
||||
*/
|
||||
@Schema(description = "打印名称")
|
||||
private String materialNamePrint;
|
||||
|
||||
/**
|
||||
* 任务工单号
|
||||
*/
|
||||
@Schema(description = "任务工单号")
|
||||
@NotBlank(message = "任务工单号不能为空")
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 任务工单id
|
||||
*/
|
||||
@Schema(description = "任务工单id")
|
||||
@NotNull(message = "任务工单id不能为空")
|
||||
private Long workerOrderId;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
@Schema(description = "批次")
|
||||
@NotBlank(message = "批次不能为空")
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标签数量
|
||||
*/
|
||||
@Schema(description = "标签数量")
|
||||
private Integer labelCount;
|
||||
|
||||
/**
|
||||
* 打印类型 0:明细标签打印 1:整体标签打印
|
||||
*/
|
||||
@Schema(description = "打印类型 0:明细标签打印 1:整体标签打印")
|
||||
private Integer labelType;
|
||||
|
||||
private List<PrintInfoDO> printInfoList;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package top.wms.admin.print.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 打印记录详情信息
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/06/15 17:08
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "打印记录详情信息")
|
||||
public class PrintInfoResp implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 打印编码
|
||||
*/
|
||||
@Schema(description = "打印编码")
|
||||
private String encodingPrint;
|
||||
|
||||
/**
|
||||
* 检验签字
|
||||
*/
|
||||
@Schema(description = "检验签字")
|
||||
private String inspectionSignature;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
@Schema(description = "标记号")
|
||||
private String mark;
|
||||
|
||||
/**
|
||||
* 打印名称
|
||||
*/
|
||||
@Schema(description = "打印名称")
|
||||
private String materialNamePrint;
|
||||
|
||||
/**
|
||||
* 包装签字
|
||||
*/
|
||||
@Schema(description = "包装签字")
|
||||
private String packingSignature;
|
||||
|
||||
/**
|
||||
* 生产日期
|
||||
*/
|
||||
@Schema(description = "生产日期")
|
||||
private String productionDate;
|
||||
|
||||
/**
|
||||
* 二维码数据
|
||||
*/
|
||||
@Schema(description = "二维码数据")
|
||||
private String qrCodeData;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
@Schema(description = "批次")
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标重
|
||||
*/
|
||||
@Schema(description = "标重")
|
||||
private BigDecimal totalCalculatedWeight;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
@Schema(description = "数量")
|
||||
private Integer totalCount;
|
||||
|
||||
/**
|
||||
* 实重
|
||||
*/
|
||||
@Schema(description = "实重")
|
||||
private BigDecimal totalWeight;
|
||||
|
||||
/**
|
||||
* 任务工单ID
|
||||
*/
|
||||
@Schema(description = "任务工单ID")
|
||||
private Long workerOrderId;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package top.wms.admin.print.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.wms.admin.common.model.resp.BaseDetailResp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.*;
|
||||
|
||||
/**
|
||||
* 打印记录信息
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/06/15 16:57
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "打印记录信息")
|
||||
public class PrintResp extends BaseDetailResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@Schema(description = "物料编码")
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* 打印编码
|
||||
*/
|
||||
@Schema(description = "打印编码")
|
||||
private String encodingPrint;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
@Schema(description = "物料名称")
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 打印名称
|
||||
*/
|
||||
@Schema(description = "打印名称")
|
||||
private String materialNamePrint;
|
||||
|
||||
/**
|
||||
* 任务工单号
|
||||
*/
|
||||
@Schema(description = "任务工单号")
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 任务工单id
|
||||
*/
|
||||
@Schema(description = "任务工单id")
|
||||
private Long workerOrderId;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
@Schema(description = "批次")
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标签数量
|
||||
*/
|
||||
@Schema(description = "标签数量")
|
||||
private Integer labelCount;
|
||||
|
||||
/**
|
||||
* 打印类型 0:明细标签打印 1:整体标签打印
|
||||
*/
|
||||
@Schema(description = "打印类型 0:明细标签打印 1:整体标签打印")
|
||||
private Integer labelType;
|
||||
|
||||
/**
|
||||
* 修改人
|
||||
*/
|
||||
@Schema(description = "修改人")
|
||||
private Long updateUser;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@Schema(description = "修改时间")
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package top.wms.admin.print.service;
|
||||
|
||||
import top.continew.starter.extension.crud.service.BaseService;
|
||||
import top.wms.admin.print.model.query.PrintQuery;
|
||||
import top.wms.admin.print.model.req.PrintReq;
|
||||
import top.wms.admin.print.model.resp.PrintInfoResp;
|
||||
import top.wms.admin.print.model.resp.PrintResp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 打印记录业务接口
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/06/15 16:57
|
||||
*/
|
||||
public interface PrintService extends BaseService<PrintResp, PrintResp, PrintQuery, PrintReq> {
|
||||
|
||||
List<PrintInfoResp> getInfo(Long id);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package top.wms.admin.print.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import top.continew.starter.extension.crud.service.BaseServiceImpl;
|
||||
import top.wms.admin.print.mapper.PrintInfoMapper;
|
||||
import top.wms.admin.print.mapper.PrintMapper;
|
||||
import top.wms.admin.print.model.entity.PrintDO;
|
||||
import top.wms.admin.print.model.entity.PrintInfoDO;
|
||||
import top.wms.admin.print.model.query.PrintQuery;
|
||||
import top.wms.admin.print.model.req.PrintReq;
|
||||
import top.wms.admin.print.model.resp.PrintInfoResp;
|
||||
import top.wms.admin.print.model.resp.PrintResp;
|
||||
import top.wms.admin.print.service.PrintService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 打印记录业务实现
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/06/15 16:57
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PrintServiceImpl extends BaseServiceImpl<PrintMapper, PrintDO, PrintResp, PrintResp, PrintQuery, PrintReq> implements PrintService {
|
||||
|
||||
private final PrintInfoMapper printInfoMapper;
|
||||
|
||||
@Override
|
||||
public List<PrintInfoResp> getInfo(Long id) {
|
||||
PrintDO printDO = baseMapper.selectById(id);
|
||||
List<PrintInfoDO> printInfoRespList = printInfoMapper.selectList(new QueryWrapper<PrintInfoDO>()
|
||||
.eq("worker_order_id", printDO.getWorkerOrderId()));
|
||||
return BeanUtil.copyToList(printInfoRespList, PrintInfoResp.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterAdd(PrintReq req, PrintDO printDO) {
|
||||
printInfoMapper.insertBatch(req.getPrintInfoList()
|
||||
.stream()
|
||||
.peek(item -> item.setPrintId(printDO.getId()))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class FileServiceImpl extends BaseServiceImpl<FileMapper, FileDO, FileRes
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileInfo upload(MultipartFile file, String path, String storageCode, Boolean createMin, Boolean store) {
|
||||
public FileInfo upload(MultipartFile file, String path, String storageCode, Boolean createMin, Boolean store) {
|
||||
StorageDO storage;
|
||||
if (StrUtil.isBlank(storageCode)) {
|
||||
storage = storageService.getDefaultStorage();
|
||||
|
||||
@@ -40,4 +40,11 @@ public interface WorkOrderMapper extends BaseMapper<WorkOrderDO> {
|
||||
*/
|
||||
List<WorkOrderInfoResp> getDetail(Long id);
|
||||
|
||||
/**
|
||||
* 导出任务工单列表
|
||||
*
|
||||
* @param queryWrapper 查询参数
|
||||
* @return 任务工单列表
|
||||
*/
|
||||
List<WorkOrderResp> selectExport(@Param(Constants.WRAPPER) QueryWrapper<WorkOrderDO> queryWrapper);
|
||||
}
|
||||
@@ -38,13 +38,33 @@ public class WorkOrderDO extends BaseDO {
|
||||
private Long materialId;
|
||||
|
||||
/**
|
||||
* 总重量
|
||||
* 打印物料编码
|
||||
*/
|
||||
private String encodingPrint;
|
||||
|
||||
/**
|
||||
* 实际总重量
|
||||
*/
|
||||
private BigDecimal totalWeight;
|
||||
|
||||
/**
|
||||
* 标准总重量(标重)
|
||||
*/
|
||||
private BigDecimal totalCalculatedWeight;
|
||||
|
||||
/**
|
||||
* 总数量
|
||||
*/
|
||||
private Integer totalCount;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
private String mark;
|
||||
|
||||
}
|
||||
@@ -45,7 +45,7 @@ public class WorkOrderInfoDO extends BaseDO {
|
||||
/**
|
||||
* 物料数量
|
||||
*/
|
||||
private BigDecimal quantity;
|
||||
private Integer quantity;
|
||||
|
||||
/**
|
||||
* 称重重量
|
||||
@@ -56,4 +56,20 @@ public class WorkOrderInfoDO extends BaseDO {
|
||||
* 计算重量
|
||||
*/
|
||||
private BigDecimal calculatedWeight;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
private String mark;
|
||||
|
||||
/**
|
||||
* 称重数量
|
||||
*/
|
||||
private Integer weightQuantity;
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package top.wms.admin.weighManage.model.query;
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
@@ -56,11 +57,19 @@ public class WorkOrderQuery implements Serializable {
|
||||
* 创建开始时间
|
||||
*/
|
||||
@Schema(description = "创建开始时间")
|
||||
private Date startTime;
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime startDate;
|
||||
|
||||
/**
|
||||
* 创建结束时间
|
||||
*/
|
||||
@Schema(description = "创建结束时间")
|
||||
private Date endTime;
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date endDate;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
private String batch;
|
||||
|
||||
}
|
||||
@@ -65,4 +65,15 @@ public class WorkOrderInfoReq implements Serializable {
|
||||
@Schema(description = "抓拍的图片")
|
||||
private String imgUrl;
|
||||
|
||||
/**
|
||||
* 称重数量
|
||||
*/
|
||||
private Integer weightQuantity;
|
||||
|
||||
/**
|
||||
* 标记
|
||||
*/
|
||||
@Schema(description = "标记")
|
||||
private String mark;
|
||||
|
||||
}
|
||||
@@ -30,13 +30,6 @@ public class WorkOrderReq implements Serializable {
|
||||
@NotNull(message = "物料主键id不能为空")
|
||||
private Long materialId;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
@Schema(description = "物料名称")
|
||||
@NotBlank(message = "物料名称不能为空")
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 称重列表
|
||||
*/
|
||||
@@ -44,16 +37,29 @@ public class WorkOrderReq implements Serializable {
|
||||
@NotEmpty(message = "称重列表不能为空")
|
||||
private List<WorkOrderInfoReq> workOrderInfos;
|
||||
|
||||
|
||||
/**
|
||||
* 手动填写的物料数量
|
||||
*/
|
||||
private String inputQuantity;
|
||||
|
||||
|
||||
/**
|
||||
* 电子秤重量
|
||||
*/
|
||||
private String ahDeviceWeight;
|
||||
|
||||
/**
|
||||
* 计算重量
|
||||
*/
|
||||
private String calculatedWeight;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
private String mark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package top.wms.admin.weighManage.model.resp;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 任务工单导出信息(扁平化,包含主表和子表字段)
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/04/16
|
||||
*/
|
||||
@Data
|
||||
public class WorkOrderExportResp {
|
||||
|
||||
@ExcelProperty(value = "人员卡号", order = 1)
|
||||
private String cardNo;
|
||||
|
||||
@ExcelProperty(value = "工单编号", order = 2)
|
||||
private String orderNo;
|
||||
|
||||
@ExcelProperty(value = "标题", order = 3)
|
||||
private String title;
|
||||
|
||||
@ExcelProperty(value = "物料名称", order = 4)
|
||||
private String materialName;
|
||||
|
||||
@ExcelProperty(value = "物料编码", order = 5)
|
||||
private String encoding;
|
||||
|
||||
@ExcelProperty(value = "单位重量", order = 6)
|
||||
private BigDecimal unitWeight;
|
||||
|
||||
@ExcelProperty(value = "物料直径", order = 7)
|
||||
private Double materialSpec;
|
||||
|
||||
@ExcelProperty(value = "图片地址", order = 8)
|
||||
private String photoUrl;
|
||||
|
||||
@ExcelProperty(value = "标准总重量(g)", order = 11)
|
||||
private BigDecimal totalCalculatedWeight;
|
||||
|
||||
@ExcelProperty(value = "实际总重量(g)", order = 12)
|
||||
private BigDecimal totalWeight;
|
||||
|
||||
@ExcelProperty(value = "总数量", order = 13)
|
||||
private Integer totalCount;
|
||||
|
||||
@ExcelProperty(value = "输入数量", order = 14)
|
||||
private Integer quantity;
|
||||
|
||||
@ExcelProperty(value = "标准重量(g)", order = 15)
|
||||
private BigDecimal calculatedWeight;
|
||||
|
||||
@ExcelProperty(value = "称重数量", order = 16)
|
||||
private Integer weightQuantity;
|
||||
|
||||
@ExcelProperty(value = "称重重量(g)", order = 17)
|
||||
private BigDecimal weight;
|
||||
|
||||
@ExcelProperty(value = "图片地址", order = 18)
|
||||
private String imgUrl;
|
||||
|
||||
@ExcelProperty(value = "批次", order = 9)
|
||||
private String infoBatch;
|
||||
|
||||
@ExcelProperty(value = "标记号", order = 10)
|
||||
private String infoMark;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package top.wms.admin.weighManage.model.resp;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -34,9 +35,10 @@ public class WorkOrderInfoResp {
|
||||
private Long materialId;
|
||||
|
||||
/**
|
||||
* 物料主键id
|
||||
* 物料名称
|
||||
*/
|
||||
@Schema(description = "物料主键id")
|
||||
@Schema(description = "物料名称")
|
||||
@ExcelProperty(value = "物料名称", order = 1)
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
@@ -49,24 +51,48 @@ public class WorkOrderInfoResp {
|
||||
* 物料数量
|
||||
*/
|
||||
@Schema(description = "物料数量")
|
||||
private BigDecimal quantity;
|
||||
@ExcelProperty(value = "输入数量", order = 2)
|
||||
private Integer quantity;
|
||||
/**
|
||||
* 计算重量
|
||||
*/
|
||||
@Schema(description = "计算重量")
|
||||
@ExcelProperty(value = "标准重量(g)", order = 3)
|
||||
private BigDecimal calculatedWeight;
|
||||
|
||||
/**
|
||||
* 称重数量
|
||||
*/
|
||||
@Schema(description = "称重数量")
|
||||
@ExcelProperty(value = "称重数量", order = 4)
|
||||
private Integer weightQuantity;
|
||||
|
||||
/**
|
||||
* 称重重量
|
||||
*/
|
||||
@Schema(description = "称重重量")
|
||||
@ExcelProperty(value = "称重重量(g)", order = 5)
|
||||
private BigDecimal weight;
|
||||
|
||||
/**
|
||||
* 计算重量
|
||||
*/
|
||||
@Schema(description = "计算重量")
|
||||
private BigDecimal calculatedWeight;
|
||||
|
||||
/**
|
||||
* 抓拍的图片
|
||||
*/
|
||||
@Schema(description = "抓拍的图片")
|
||||
@ExcelProperty(value = "图片地址", order = 6)
|
||||
private String imgUrl;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
@Schema(description = "批次")
|
||||
@ExcelProperty(value = "批次", order = 7)
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
@Schema(description = "标记号")
|
||||
@ExcelProperty(value = "标记号", order = 8)
|
||||
private String mark;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package top.wms.admin.weighManage.model.resp;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnore;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@@ -28,78 +30,104 @@ public class WorkOrderResp extends BaseDetailResp {
|
||||
* 卡号
|
||||
*/
|
||||
@Schema(description = "卡号")
|
||||
@ExcelProperty(value = "人员卡号", order = 1)
|
||||
private String cardNo;
|
||||
|
||||
/**
|
||||
* 工单编号
|
||||
*/
|
||||
@Schema(description = "工单编号")
|
||||
@ExcelProperty(value = "工单编号", order = 2)
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@Schema(description = "标题")
|
||||
@ExcelProperty(value = "标题", order = 3)
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 物料主键id
|
||||
*/
|
||||
@Schema(description = "物料主键id")
|
||||
@ExcelIgnore
|
||||
private Long materialId;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
@Schema(description = "物料名称")
|
||||
@ExcelProperty(value = "物料名称", order = 4)
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 物料编码
|
||||
*/
|
||||
@Schema(description = "物料编码")
|
||||
@ExcelProperty(value = "物料编码", order = 5)
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* 物料单位重量
|
||||
*/
|
||||
@Schema(description = "物料单位重量")
|
||||
@ExcelProperty(value = "单位重量", order = 6)
|
||||
private BigDecimal unitWeight;
|
||||
|
||||
/**
|
||||
* 物料规格
|
||||
* 物料直径
|
||||
*/
|
||||
@Schema(description = "物料规格")
|
||||
private String materialSpec;
|
||||
@Schema(description = "物料直径")
|
||||
@ExcelProperty(value = "物料直径", order = 7)
|
||||
private Double materialSpec;
|
||||
|
||||
/**
|
||||
* 物料图片
|
||||
*/
|
||||
@Schema(description = "物料图片")
|
||||
@ExcelProperty(value = "图片地址", order = 8)
|
||||
private String photoUrl;
|
||||
|
||||
/**
|
||||
* 计算总重量(标重)
|
||||
*/
|
||||
@Schema(description = "计算总重量(标重)")
|
||||
@ExcelProperty(value = "标准总重量(g)", order = 9)
|
||||
private BigDecimal totalCalculatedWeight;
|
||||
|
||||
/**
|
||||
* 实际总重量
|
||||
*/
|
||||
@Schema(description = "实际总重量")
|
||||
@ExcelProperty(value = "实际总重量(g)", order = 10)
|
||||
private BigDecimal totalWeight;
|
||||
|
||||
/**
|
||||
* 总数量
|
||||
*/
|
||||
@Schema(description = "总数量")
|
||||
@ExcelProperty(value = "总数量", order = 11)
|
||||
private int totalCount;
|
||||
|
||||
/**
|
||||
* 任务工单详情信息列表
|
||||
*/
|
||||
@Schema(description = "任务工单详情信息列表")
|
||||
@ExcelProperty(value = "任务工单详情信息列表", order = 12)
|
||||
private List<WorkOrderInfoResp> workOrderInfos;
|
||||
|
||||
/**
|
||||
* 批次
|
||||
*/
|
||||
@Schema(description = "批次")
|
||||
@ExcelProperty(value = "批次", order = 12)
|
||||
private String batch;
|
||||
|
||||
/**
|
||||
* 标记号
|
||||
*/
|
||||
@Schema(description = "标记号")
|
||||
@ExcelProperty(value = "标记号", order = 13)
|
||||
private String mark;
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import top.wms.admin.weighManage.model.resp.WorkOrderInfoResp;
|
||||
import top.wms.admin.weighManage.model.resp.WorkOrderResp;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 任务工单信息业务接口
|
||||
@@ -24,7 +25,7 @@ public interface WorkOrderService extends BaseService<WorkOrderResp, WorkOrderRe
|
||||
*/
|
||||
WorkOrderResp getDetail(Long id);
|
||||
|
||||
/**
|
||||
/**
|
||||
* 创建任务工单
|
||||
*
|
||||
* @param req 创建任务工单参数
|
||||
@@ -41,9 +42,10 @@ public interface WorkOrderService extends BaseService<WorkOrderResp, WorkOrderRe
|
||||
List<WorkOrderInfoResp> getWorkOrderInfos(Long id);
|
||||
|
||||
/**
|
||||
* 校验物料数量和重量是否匹配
|
||||
* 校验物料数量和重量是否匹配
|
||||
*
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
int validateWeighing(WorkOrderReq req);
|
||||
Map<String, String> validateWeighing(WorkOrderReq req);
|
||||
}
|
||||
@@ -4,26 +4,34 @@ import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.continew.starter.core.exception.BusinessException;
|
||||
import top.continew.starter.core.validation.CheckUtils;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.query.SortQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
import top.continew.starter.extension.crud.service.BaseServiceImpl;
|
||||
import top.continew.starter.file.excel.util.ExcelUtils;
|
||||
import top.wms.admin.common.context.UserContextHolder;
|
||||
import top.wms.admin.material.mapper.MaterialInfoMapper;
|
||||
import top.wms.admin.material.model.entity.MaterialInfoDO;
|
||||
import top.wms.admin.system.service.ConfigService;
|
||||
import top.wms.admin.materialType.mapper.MaterialTypeMapper;
|
||||
import top.wms.admin.materialType.model.entity.MaterialTypeDO;
|
||||
import top.wms.admin.weighManage.mapper.WorkOrderInfoMapper;
|
||||
import top.wms.admin.weighManage.mapper.WorkOrderMapper;
|
||||
import top.wms.admin.weighManage.model.entity.WorkOrderDO;
|
||||
import top.wms.admin.weighManage.model.entity.WorkOrderInfoDO;
|
||||
import top.wms.admin.weighManage.model.query.WorkOrderQuery;
|
||||
import top.wms.admin.weighManage.model.resp.WorkOrderExportResp;
|
||||
import top.wms.admin.weighManage.model.resp.WorkOrderInfoResp;
|
||||
import top.wms.admin.weighManage.model.resp.WorkOrderResp;
|
||||
import top.wms.admin.weighManage.model.req.WorkOrderInfoReq;
|
||||
import top.wms.admin.weighManage.model.req.WorkOrderReq;
|
||||
import top.wms.admin.weighManage.model.resp.WorkOrderInfoResp;
|
||||
@@ -31,8 +39,8 @@ import top.wms.admin.weighManage.model.resp.WorkOrderResp;
|
||||
import top.wms.admin.weighManage.service.WorkOrderService;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 任务工单信息业务实现
|
||||
@@ -45,18 +53,23 @@ import java.util.List;
|
||||
@RequiredArgsConstructor
|
||||
public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrderMapper, WorkOrderDO, WorkOrderResp, WorkOrderResp, WorkOrderQuery, WorkOrderReq> implements WorkOrderService {
|
||||
|
||||
private final WorkOrderInfoMapper workOrderInfoMapper;
|
||||
private final WorkOrderInfoMapper workOrderInfoMapper;
|
||||
|
||||
private final MaterialInfoMapper materialInfoMapper;
|
||||
|
||||
private final ConfigService configService;
|
||||
private final MaterialInfoMapper materialInfoMapper;
|
||||
|
||||
private final MaterialTypeMapper materialTypeMapper;
|
||||
|
||||
@Override
|
||||
public PageResp<WorkOrderResp> page(WorkOrderQuery query, PageQuery pageQuery) {
|
||||
QueryWrapper<WorkOrderDO> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.like(StrUtil.isNotBlank(query.getMaterialName()), "m.material_name", query.getMaterialName());
|
||||
queryWrapper.eq(null != query.getOrderNo(), "w.order_no", query.getOrderNo());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getBatch()), "w.batch", query.getBatch());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getUserName()), "u.username", query.getUserName());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getCarNo()), "u.card_no", query.getCarNo());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getEncoding()), "m.encoding", query.getEncoding());
|
||||
queryWrapper.ge(null != query.getStartDate(), "w.create_time", query.getStartDate());
|
||||
queryWrapper.le(null != query.getEndDate(), "w.create_time", query.getEndDate());
|
||||
this.sort(queryWrapper, pageQuery);
|
||||
|
||||
IPage<WorkOrderResp> page = baseMapper.selectWorkOrderPage(new Page<>(pageQuery.getPage(), pageQuery
|
||||
@@ -65,6 +78,55 @@ private final ConfigService configService;
|
||||
return PageResp.build(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void export(WorkOrderQuery query, SortQuery sortQuery, HttpServletResponse response) {
|
||||
QueryWrapper<WorkOrderDO> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.like(StrUtil.isNotBlank(query.getMaterialName()), "m.material_name", query.getMaterialName());
|
||||
queryWrapper.eq(null != query.getOrderNo(), "w.order_no", query.getOrderNo());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getBatch()), "w.batch", query.getBatch());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getUserName()), "u.username", query.getUserName());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getCarNo()), "u.card_no", query.getCarNo());
|
||||
queryWrapper.eq(StrUtil.isNotBlank(query.getEncoding()), "m.encoding", query.getEncoding());
|
||||
queryWrapper.ge(null != query.getStartDate(), "w.create_time", query.getStartDate());
|
||||
queryWrapper.le(null != query.getEndDate(), "w.create_time", query.getEndDate());
|
||||
queryWrapper.orderByDesc("w.id");
|
||||
List<WorkOrderResp> workOrders = baseMapper.selectExport(queryWrapper);
|
||||
Map<Long, List<WorkOrderInfoResp>> collect = new HashMap<>();
|
||||
if (CollUtil.isNotEmpty(workOrders)) {
|
||||
List<Long> ids = workOrders.stream().map(WorkOrderResp::getId).collect(Collectors.toList());
|
||||
List<WorkOrderInfoDO> workOrderInfos = workOrderInfoMapper.selectList(new QueryWrapper<WorkOrderInfoDO>()
|
||||
.in("work_order_id", ids));
|
||||
List<WorkOrderInfoResp> workOrderInfoResps = BeanUtil.copyToList(workOrderInfos, WorkOrderInfoResp.class);
|
||||
collect = workOrderInfoResps.stream().collect(Collectors.groupingBy(WorkOrderInfoResp::getWorkOrderId));
|
||||
}
|
||||
List<WorkOrderExportResp> exportList = new ArrayList<>();
|
||||
for (WorkOrderResp workOrder : workOrders) {
|
||||
List<WorkOrderInfoResp> infos = collect.get(workOrder.getId());
|
||||
|
||||
WorkOrderExportResp mainExport = new WorkOrderExportResp();
|
||||
BeanUtil.copyProperties(workOrder, mainExport);
|
||||
mainExport.setInfoBatch(workOrder.getBatch());
|
||||
mainExport.setInfoMark(workOrder.getMark());
|
||||
exportList.add(mainExport);
|
||||
|
||||
if (CollUtil.isNotEmpty(infos)) {
|
||||
for (WorkOrderInfoResp info : infos) {
|
||||
WorkOrderExportResp infoExport = new WorkOrderExportResp();
|
||||
infoExport.setOrderNo(workOrder.getOrderNo());
|
||||
infoExport.setQuantity(info.getQuantity());
|
||||
infoExport.setCalculatedWeight(info.getCalculatedWeight());
|
||||
infoExport.setWeightQuantity(info.getWeightQuantity());
|
||||
infoExport.setWeight(info.getWeight());
|
||||
infoExport.setImgUrl(info.getImgUrl());
|
||||
infoExport.setInfoBatch(info.getBatch());
|
||||
infoExport.setInfoMark(info.getMark());
|
||||
exportList.add(infoExport);
|
||||
}
|
||||
}
|
||||
}
|
||||
ExcelUtils.export(exportList, "任务工单导出", WorkOrderExportResp.class, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkOrderResp getDetail(Long id) {
|
||||
WorkOrderDO workOrderDO = baseMapper.selectById(id);
|
||||
@@ -74,16 +136,11 @@ private final ConfigService configService;
|
||||
workOrderResp.setMaterialName(materialInfoDO.getMaterialName());
|
||||
workOrderResp.setEncoding(materialInfoDO.getEncoding());
|
||||
}
|
||||
|
||||
List<WorkOrderInfoDO> workOrderInfos = workOrderInfoMapper.selectList(new QueryWrapper<WorkOrderInfoDO>().eq("work_order_id", id));
|
||||
if (CollUtil.isNotEmpty(workOrderInfos)) {
|
||||
BigDecimal bigDecimal = new BigDecimal("0");
|
||||
for (WorkOrderInfoDO workOrderInfoDO : workOrderInfos) {
|
||||
bigDecimal = bigDecimal.add(workOrderInfoDO.getCalculatedWeight());
|
||||
}
|
||||
workOrderResp.setTotalCalculatedWeight(bigDecimal);
|
||||
List<WorkOrderInfoDO> infos = workOrderInfoMapper.selectList(new QueryWrapper<WorkOrderInfoDO>()
|
||||
.eq("work_order_id", id));
|
||||
if (CollUtil.isNotEmpty(infos)) {
|
||||
workOrderResp.setWorkOrderInfos(BeanUtil.copyToList(infos, WorkOrderInfoResp.class));
|
||||
}
|
||||
|
||||
return workOrderResp;
|
||||
}
|
||||
|
||||
@@ -92,17 +149,19 @@ private final ConfigService configService;
|
||||
return baseMapper.getDetail(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterDelete(List<Long> ids) {
|
||||
workOrderInfoMapper.delete(new QueryWrapper<WorkOrderInfoDO>().in("work_order_id", ids));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WorkOrderResp addWorKerOrder(WorkOrderReq req) {
|
||||
if (CollUtil.isEmpty(req.getWorkOrderInfos())) {
|
||||
throw new IllegalArgumentException("称重列表不能为空");
|
||||
throw new BusinessException("称重列表不能为空");
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(req.getWorkOrderInfos().get(0).getMark())) {
|
||||
throw new BusinessException("标记号不能为空");
|
||||
}
|
||||
|
||||
BigDecimal totalWeight = new BigDecimal("0");
|
||||
@@ -112,58 +171,79 @@ private final ConfigService configService;
|
||||
totalCount += workOrderInfoReq.getQuantity();
|
||||
}
|
||||
|
||||
MaterialInfoDO materialInfoDO = materialInfoMapper.selectById(req.getMaterialId());
|
||||
|
||||
WorkOrderDO workOrder = new WorkOrderDO();
|
||||
// 生成纯数字订单号:年月日时分秒 + 6位随机数
|
||||
String timestamp = DateUtil.format(new Date(), "yyyyMMddHHmmss");
|
||||
String randomNum = String.format("%06d", (int)(Math.random() * 1000000));
|
||||
workOrder.setOrderNo(timestamp + randomNum);
|
||||
String title = DateUtil.format(new Date(), DatePattern.CHINESE_DATE_PATTERN) + "-"
|
||||
+ UserContextHolder.getUsername() + "-" + req.getMaterialName();
|
||||
String title = DateUtil.format(new Date(), DatePattern.CHINESE_DATE_PATTERN) + "-" + UserContextHolder
|
||||
.getUsername() + "-" + materialInfoDO.getMaterialName();
|
||||
workOrder.setTitle(title);
|
||||
workOrder.setMaterialId(req.getMaterialId());
|
||||
workOrder.setBatch(materialInfoDO.getBatch());
|
||||
workOrder.setMark(req.getWorkOrderInfos().get(0).getMark());
|
||||
workOrder.setTotalWeight(totalWeight);
|
||||
workOrder.setTotalCount(totalCount);
|
||||
workOrder.setTotalCalculatedWeight(materialInfoDO.getUnitWeight().multiply(BigDecimal.valueOf(totalCount)));
|
||||
baseMapper.insert(workOrder);
|
||||
|
||||
//新增工单详情列表信息
|
||||
List<WorkOrderInfoDO> workOrderInfoDOList = BeanUtil.copyToList(req.getWorkOrderInfos(), WorkOrderInfoDO.class);
|
||||
workOrderInfoDOList.forEach(workOrderInfoDO -> workOrderInfoDO.setWorkOrderId(workOrder.getId()));
|
||||
workOrderInfoDOList.forEach(workOrderInfoDO -> {
|
||||
workOrderInfoDO.setWorkOrderId(workOrder.getId());
|
||||
workOrderInfoDO.setBatch(materialInfoDO.getBatch());
|
||||
});
|
||||
workOrderInfoMapper.insertBatch(workOrderInfoDOList);
|
||||
|
||||
return BeanUtil.copyProperties(workOrder, WorkOrderResp.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int validateWeighing(WorkOrderReq req) {
|
||||
public Map<String, String> validateWeighing(WorkOrderReq req) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("code", "200");
|
||||
log.info("validateWeighing req:{}", req);
|
||||
String configValue = configService.getConfigValue("weight_float_ratio");
|
||||
BigDecimal weightFloat = new BigDecimal("0.06");
|
||||
if (StrUtil.isNotBlank(configValue)) {
|
||||
weightFloat = new BigDecimal(configValue);
|
||||
}
|
||||
|
||||
//计算标准重量
|
||||
MaterialInfoDO materialInfoDO = materialInfoMapper.selectById(req.getMaterialId());
|
||||
BigDecimal standardWeight = materialInfoDO.getUnitWeight().subtract(new BigDecimal(req.getInputQuantity()));
|
||||
CheckUtils.throwIf((materialInfoDO == null || null == materialInfoDO.getMaterialTypeId()), "该物料信息不全,请先维护!");
|
||||
MaterialTypeDO materialTypeDO = materialTypeMapper.selectById(materialInfoDO.getMaterialTypeId());
|
||||
CheckUtils.throwIf((materialTypeDO == null || null == materialTypeDO
|
||||
.getDownFloatRatio() || null == materialTypeDO.getUpFloatRatio()), "该物料品类信息不全,请先维护!");
|
||||
|
||||
//下行浮动范围
|
||||
BigDecimal downFloatRatio = materialTypeDO.getDownFloatRatio();
|
||||
//上行浮动范围
|
||||
BigDecimal upFloatRatio = materialTypeDO.getUpFloatRatio();
|
||||
//计算标准重量
|
||||
BigDecimal standardWeight = new BigDecimal(req.getCalculatedWeight());
|
||||
//电子秤重量
|
||||
BigDecimal electronicWeight = new BigDecimal(req.getAhDeviceWeight());
|
||||
|
||||
// 检查 electronicWeight 是否大于 standardWeight
|
||||
if (electronicWeight.compareTo(standardWeight) <= 0) {
|
||||
log.error("电子秤重量必须大于标准重量");
|
||||
return 500; // 电子秤重量必须大于标准重量
|
||||
}
|
||||
|
||||
// 计算比值:(electronicWeight - standardWeight) / standardWeight
|
||||
|
||||
// 计算比值:(实重 - 标重) / 标重
|
||||
BigDecimal weightDifference = electronicWeight.subtract(standardWeight);
|
||||
BigDecimal ratio = weightDifference.divide(standardWeight, 4, BigDecimal.ROUND_HALF_UP);
|
||||
|
||||
// 检查比值是否超过 6%
|
||||
if (ratio.compareTo(weightFloat) > 0) {
|
||||
log.error("比值超过 6%,当前比值: {}", ratio);
|
||||
return 500; // 比值超过 6%
|
||||
BigDecimal ratio = weightDifference.divide(standardWeight, 4, BigDecimal.ROUND_HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100));
|
||||
log.info("ratio当前比值:{}%", ratio);
|
||||
|
||||
// 检查比值是否超过上行浮动范围
|
||||
if (ratio.compareTo(upFloatRatio) > 0) {
|
||||
log.info("比值超过 {}%", upFloatRatio);
|
||||
map.put("code", "502");
|
||||
map.put("msg", "数量过多,请减少");
|
||||
return map;
|
||||
}
|
||||
|
||||
return 200; // 验证通过
|
||||
// 检查比值是否超过下行浮动范围
|
||||
if (ratio.compareTo(downFloatRatio) < 0) {
|
||||
log.info("比值超过下限 {}%", downFloatRatio);
|
||||
map.put("code", "501");
|
||||
map.put("msg", "数量不足,请添加");
|
||||
return map;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="top.wms.admin.fullWorkOrder.mapper.FullWorkOrderMapper">
|
||||
<select id="selectFullWorkOrderPage" resultType="top.wms.admin.fullWorkOrder.model.resp.FullWorkOrderResp">
|
||||
select
|
||||
f.*,
|
||||
m.material_name materialName,
|
||||
u.username createUserString
|
||||
from
|
||||
sys_full_work_order f
|
||||
left join sys_material_info m on f.material_code = m.encoding
|
||||
left join sys_user u on f.create_user = u.id
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="selectFullWorkOrderExport" resultType="top.wms.admin.fullWorkOrder.model.resp.FullWorkOrderResp">
|
||||
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="top.wms.admin.materialProcess.mapper.MaterialProcessMapper">
|
||||
<!-- 按流程名称批量更新 -->
|
||||
<update id="updateByName">
|
||||
UPDATE sys_material_process
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="list != null and list.size() > 0">
|
||||
process_code = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.processCode != null and item.processCode != ''">
|
||||
WHEN process_name = #{item.processName} THEN #{item.processCode}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE process_code
|
||||
END,
|
||||
update_user = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.updateUser != null">
|
||||
WHEN process_name = #{item.processName} THEN #{item.updateUser}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE update_user
|
||||
END,
|
||||
update_time = NOW()
|
||||
</if>
|
||||
</trim>
|
||||
WHERE process_name IN
|
||||
<foreach collection="list" item="item" open="(" close=")" separator=",">
|
||||
#{item.processName}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<update id="updateByCode">
|
||||
UPDATE sys_material_process
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="list != null and list.size() > 0">
|
||||
process_name = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.processName != null and item.processName != ''">
|
||||
WHEN process_code = #{item.processCode} THEN #{item.processName}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE process_name
|
||||
END,
|
||||
update_user = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.updateUser != null">
|
||||
WHEN process_code = #{item.processCode} THEN #{item.updateUser}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE update_user
|
||||
END,
|
||||
update_time = NOW()
|
||||
</if>
|
||||
</trim>
|
||||
WHERE process_code IN
|
||||
<foreach collection="list" item="item" open="(" close=")" separator=",">
|
||||
#{item.processCode}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<select id="getCodeByMaterial" resultType="java.lang.String">
|
||||
SELECT process_code
|
||||
FROM sys_material_process p
|
||||
left join sys_material_info m on p.id = m.material_process_id
|
||||
WHERE m.encoding = #{materialCode}
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="top.wms.admin.materialType.mapper.MaterialTypeMapper">
|
||||
</mapper>
|
||||
@@ -4,49 +4,129 @@
|
||||
|
||||
<!-- 按物料名称批量更新 -->
|
||||
<update id="updateByName">
|
||||
<foreach collection="list" item="item" separator=";">
|
||||
UPDATE sys_material_info
|
||||
SET
|
||||
<if test="item.encoding != null and item.encoding != ''" >
|
||||
encoding = #{item.encoding},
|
||||
UPDATE sys_material_info
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="list != null and list.size() > 0">
|
||||
encoding = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.encoding != null and item.encoding != ''">
|
||||
WHEN material_name = #{item.materialName} THEN #{item.encoding}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE encoding
|
||||
END,
|
||||
unit_weight = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.unitWeight != null">
|
||||
WHEN material_name = #{item.materialName} THEN #{item.unitWeight}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE unit_weight
|
||||
END,
|
||||
update_user = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.updateUser != null">
|
||||
WHEN material_name = #{item.materialName} THEN #{item.updateUser}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE update_user
|
||||
END,
|
||||
update_time = NOW()
|
||||
</if>
|
||||
<if test="item.unitWeight != null">
|
||||
unit_weight = #{item.unitWeight},
|
||||
</if>
|
||||
<if test="item.materialSpec != null and item.materialSpec != ''">
|
||||
material_spec = #{item.materialSpec},
|
||||
</if>
|
||||
<if test="item.updateTime != null">
|
||||
update_time = NOW(),
|
||||
</if>
|
||||
<if test="item.updateUser != null and item.updateUser != ''">
|
||||
update_user = #{item.updateUser}
|
||||
</if>
|
||||
WHERE material_name = #{item.materialName}
|
||||
</trim>
|
||||
WHERE material_name IN
|
||||
<foreach collection="list" item="item" open="(" close=")" separator=",">
|
||||
#{item.materialName}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<update id="updateByCode">
|
||||
<foreach collection="list" item="item" separator=";">
|
||||
UPDATE sys_material_info
|
||||
SET
|
||||
<if test="item.materialName != null and item.materialName != ''">
|
||||
material_name = #{item.materialName},
|
||||
UPDATE sys_material_info
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="list != null and list.size() > 0">
|
||||
material_name = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.materialName != null and item.materialName != ''">
|
||||
WHEN encoding = #{item.encoding} THEN #{item.materialName}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE material_name
|
||||
END,
|
||||
unit_weight = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.unitWeight != null">
|
||||
WHEN encoding = #{item.encoding} THEN #{item.unitWeight}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE unit_weight
|
||||
END,
|
||||
update_user = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.updateUser != null">
|
||||
WHEN encoding = #{item.encoding} THEN #{item.updateUser}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE update_user
|
||||
END,
|
||||
update_time = NOW()
|
||||
</if>
|
||||
<if test="item.unitWeight != null">
|
||||
unit_weight = #{item.unitWeight},
|
||||
</if>
|
||||
<if test="item.materialSpec != null and item.materialSpec != ''">
|
||||
material_spec = #{item.materialSpec},
|
||||
</if>
|
||||
<if test="item.updateTime != null">
|
||||
update_time = NOW(),
|
||||
</if>
|
||||
<if test="item.updateUser != null and item.updateUser != ''">
|
||||
update_user = #{item.updateUser}
|
||||
</if>
|
||||
WHERE encoding = #{item.encoding}
|
||||
</trim>
|
||||
WHERE encoding IN
|
||||
<foreach collection="list" item="item" open="(" close=")" separator=",">
|
||||
#{item.encoding}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
<update id="updateBatchNull">
|
||||
UPDATE sys_material_info SET batch = null
|
||||
</update>
|
||||
|
||||
<update id="updateBatchByCode">
|
||||
UPDATE sys_material_info
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="list != null and list.size() > 0">
|
||||
batch = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.batch != null and item.batch != ''">
|
||||
WHEN encoding = #{item.encoding} THEN #{item.batch}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE batch
|
||||
END,
|
||||
update_user = CASE
|
||||
<foreach collection="list" item="item" separator="">
|
||||
<if test="item.updateUser != null">
|
||||
WHEN encoding = #{item.encoding} THEN #{item.updateUser}
|
||||
</if>
|
||||
</foreach>
|
||||
ELSE update_user
|
||||
END,
|
||||
update_time = NOW()
|
||||
</if>
|
||||
</trim>
|
||||
WHERE encoding IN
|
||||
<foreach collection="list" item="item" open="(" close=")" separator=",">
|
||||
#{item.encoding}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<select id="selectMaterialInfoPage" resultType="top.wms.admin.material.model.resp.MaterialInfoResp">
|
||||
SELECT
|
||||
mi.*,
|
||||
mt.type_name typeName
|
||||
FROM
|
||||
sys_material_info mi
|
||||
left join sys_material_type mt on mi.material_type_id = mt.id
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
<select id="selectMaterialInfoExport" resultType="top.wms.admin.material.model.resp.MaterialInfoResp">
|
||||
SELECT
|
||||
mi.*,
|
||||
mt.type_name typeName
|
||||
FROM
|
||||
sys_material_info mi
|
||||
left join sys_material_type mt on mi.material_type_id = mt.id
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -26,4 +26,19 @@
|
||||
where wi.work_order_id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectExport" resultType="top.wms.admin.weighManage.model.resp.WorkOrderResp">
|
||||
select
|
||||
w.*,
|
||||
m.material_name,
|
||||
m.encoding,
|
||||
m.photo_url,
|
||||
m.unit_weight,
|
||||
u.card_no,
|
||||
u.username createUserString
|
||||
from sys_work_order w
|
||||
left join sys_material_info m on w.material_id = m.id
|
||||
left join sys_user u on w.create_user = u.id
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-admin</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>wms-plugin</artifactId>
|
||||
<version>3.6.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<description>插件模块(存放代码生成、任务调度等扩展模块)</description>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU LESSER GENERAL PUBLIC LICENSE</name>
|
||||
<url>http://www.gnu.org/licenses/lgpl.html</url>
|
||||
</license>
|
||||
</licenses>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>top.wms</groupId>
|
||||
<artifactId>wms-common</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user