初始化代码

This commit is contained in:
amos wong
2025-05-10 20:57:52 +08:00
commit 14d5ff0598
539 changed files with 44824 additions and 0 deletions

42
.gitignore vendored Normal file
View File

@@ -0,0 +1,42 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
#日志文件
logs

View File

@@ -0,0 +1,46 @@
FROM deepinnet-k8s-images-registry.cn-hangzhou.cr.aliyuncs.com/deepinnet/rdc-base:no-java
#FROM deepinnet-k8s-image-registry.cn-hangzhou.cr.aliyuncs.com/deepinnet/openjdk:8-jdk-alpine
#FROM openjdk:8-jdk-alpine
ARG jdk_versions="1.8"
RUN for version in ${jdk_versions}; \
do \
cd /tmp && \
wget -q https://rdc-public-software.oss-cn-hangzhou.aliyuncs.com/jdk/jdk${version}.tar.gz && \
mkdir -p /jdk/jdk${version} && \
tar xf jdk${version}.tar.gz -C /jdk/jdk${version} --strip-components 1 && \
ln -s /jdk/jdk${version} /jdk/jdk${version}/jvm && \
rm -f jdk${version}.tar.gz; \
done
RUN export JAVA_HOME=/jdk/jdk1.8 && \
export PATH=$JAVA_HOME/bin:$PATH && \
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
##
ENV BUILD_APP_NAME tptradeprod
ENV SPRING_PROFILE dev
ARG APP_JAR=tptradeprod.jar
RUN mkdir -p /home/$BUILD_APP_NAME/target
RUN echo "#!/bin/bash" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "cd /home/$BUILD_APP_NAME/target/" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "tar -xvf /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.tgz" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "chmod 777 /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.jar" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "exec /jdk/jdk1.8/bin/java -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=${SPRING_PROFILE} -jar /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.jar" >> /home/$BUILD_APP_NAME/start.sh
RUN chmod +x /home/$BUILD_APP_NAME/*.sh
###
ADD $APP_JAR /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.tgz
WORKDIR /home/$BUILD_APP_NAME
ENTRYPOINT ["/bin/sh", "/home/tptradeprod/start.sh"]
EXPOSE 8080

View File

@@ -0,0 +1,46 @@
FROM shendu-prod-registry.cn-hangzhou.cr.aliyuncs.com/deepinnet/rdc-base:no-java
#FROM deepinnet-k8s-image-registry.cn-hangzhou.cr.aliyuncs.com/deepinnet/openjdk:8-jdk-alpine
#FROM openjdk:8-jdk-alpine
ARG jdk_versions="11"
RUN for version in ${jdk_versions}; \
do \
cd /tmp && \
wget -q https://rdc-public-software.oss-cn-hangzhou.aliyuncs.com/jdk/jdk${version}.tar.gz && \
mkdir -p /jdk/jdk${version} && \
tar xf jdk${version}.tar.gz -C /jdk/jdk${version} --strip-components 1 && \
ln -s /jdk/jdk${version} /jdk/jdk${version}/jvm && \
rm -f jdk${version}.tar.gz; \
done
RUN export JAVA_HOME=/jdk/jdk${jdk_versions} && \
export PATH=$JAVA_HOME/bin:$PATH && \
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
##
ENV BUILD_APP_NAME tptradeprod
ENV SPRING_PROFILE pre
ARG APP_JAR=tptradeprod.jar
RUN mkdir -p /home/$BUILD_APP_NAME/target
RUN echo "#!/bin/bash" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "cd /home/$BUILD_APP_NAME/target/" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "tar -xvf /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.tgz" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "chmod 777 /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.jar" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "exec /jdk/jdk${jdk_versions}/bin/java -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=${SPRING_PROFILE} -jar /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.jar" >> /home/$BUILD_APP_NAME/start.sh
RUN chmod +x /home/$BUILD_APP_NAME/*.sh
###
ADD $APP_JAR /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.tgz
WORKDIR /home/$BUILD_APP_NAME
ENTRYPOINT ["/bin/sh", "/home/tptradeprod/start.sh"]
EXPOSE 8080

View File

@@ -0,0 +1,46 @@
FROM shendu-prod-registry.cn-hangzhou.cr.aliyuncs.com/deepinnet/rdc-base:no-java
#FROM deepinnet-k8s-image-registry.cn-hangzhou.cr.aliyuncs.com/deepinnet/openjdk:8-jdk-alpine
#FROM openjdk:8-jdk-alpine
ARG jdk_versions="11"
RUN for version in ${jdk_versions}; \
do \
cd /tmp && \
wget -q https://rdc-public-software.oss-cn-hangzhou.aliyuncs.com/jdk/jdk${version}.tar.gz && \
mkdir -p /jdk/jdk${version} && \
tar xf jdk${version}.tar.gz -C /jdk/jdk${version} --strip-components 1 && \
ln -s /jdk/jdk${version} /jdk/jdk${version}/jvm && \
rm -f jdk${version}.tar.gz; \
done
RUN export JAVA_HOME=/jdk/jdk${jdk_versions} && \
export PATH=$JAVA_HOME/bin:$PATH && \
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
##
ENV BUILD_APP_NAME tptradeprod
ENV SPRING_PROFILE prod
ARG APP_JAR=tptradeprod.jar
RUN mkdir -p /home/$BUILD_APP_NAME/target
RUN echo "#!/bin/bash" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "cd /home/$BUILD_APP_NAME/target/" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "tar -xvf /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.tgz" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "chmod 777 /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.jar" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "exec /jdk/jdk${jdk_versions}/bin/java -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=${SPRING_PROFILE} -jar /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.jar" >> /home/$BUILD_APP_NAME/start.sh
RUN chmod +x /home/$BUILD_APP_NAME/*.sh
###
ADD $APP_JAR /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.tgz
WORKDIR /home/$BUILD_APP_NAME
ENTRYPOINT ["/bin/sh", "/home/tptradeprod/start.sh"]
EXPOSE 8080

View File

@@ -0,0 +1,46 @@
FROM deepinnet-k8s-images-registry.cn-hangzhou.cr.aliyuncs.com/deepinnet/rdc-base:no-java
#FROM deepinnet-k8s-image-registry.cn-hangzhou.cr.aliyuncs.com/deepinnet/openjdk:8-jdk-alpine
#FROM openjdk:8-jdk-alpine
ARG jdk_versions="11"
RUN for version in ${jdk_versions}; \
do \
cd /tmp && \
wget -q https://rdc-public-software.oss-cn-hangzhou.aliyuncs.com/jdk/jdk${version}.tar.gz && \
mkdir -p /jdk/jdk${version} && \
tar xf jdk${version}.tar.gz -C /jdk/jdk${version} --strip-components 1 && \
ln -s /jdk/jdk${version} /jdk/jdk${version}/jvm && \
rm -f jdk${version}.tar.gz; \
done
RUN export JAVA_HOME=/jdk/jdk${jdk_versions} && \
export PATH=$JAVA_HOME/bin:$PATH && \
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
##
ENV BUILD_APP_NAME tptradeprod
ENV SPRING_PROFILE test
ARG APP_JAR=tptradeprod.jar
RUN mkdir -p /home/$BUILD_APP_NAME/target
RUN echo "#!/bin/bash" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "cd /home/$BUILD_APP_NAME/target/" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "tar -xvf /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.tgz" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "chmod 777 /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.jar" >> /home/$BUILD_APP_NAME/start.sh
RUN echo "exec /jdk/jdk${jdk_versions}/bin/java -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=${SPRING_PROFILE} -jar /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.jar" >> /home/$BUILD_APP_NAME/start.sh
RUN chmod +x /home/$BUILD_APP_NAME/*.sh
###
ADD $APP_JAR /home/$BUILD_APP_NAME/target/$BUILD_APP_NAME.tgz
WORKDIR /home/$BUILD_APP_NAME
ENTRYPOINT ["/bin/sh", "/home/tptradeprod/start.sh"]
EXPOSE 8080

30
README.md Normal file
View File

@@ -0,0 +1,30 @@
## 命名规则:
groupId:统一使用com.deepinnet
<br/>
artifactIddeepinnet-应用名
包命名规范com.deepinnet.应用名.模块名
<br/>
举例com.deepinnet.tptradeprod.biz
## 项目分层说明:
- tptradeprod-app-starterSpringBoot应用启动类
- tptradeprod-biz业务层
- tptradeprod-biz-service-impl业务层的实现具体业务流程编排
- tptradeprod-common通用层
- tptradeprod-common-dal仓储层
- tptradeprod-common-service
- tptradeprod-common-service-facade需要向外界暴露的领域服务
- tptradeprod-common-service-integration集成的第三方接口
- tptradeprod-common-util工具
- tptradeprod-core领域层
- tptradeprod-core-service本系统内使用的service接口
- tptradeprod-core-model领域模型
## 各模块依赖关系:
- biz负责业务流程编排依赖于common-service-facade、common-service-integration、
common-service-util、core-service
- core-service本系统内的服务 不需要向外暴露依赖core-model、
common-dal、common-util

440
pom.xml Normal file
View File

@@ -0,0 +1,440 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>tptradeprod-api</module>
<module>tptradeprod-app-starter</module>
<module>tptradeprod-biz</module>
<module>tptradeprod-common</module>
<module>tptradeprod-core</module>
</modules>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--spring相关依赖-->
<spring.boot.version>2.6.11</spring.boot.version>
<spring.cloud.version>2021.0.4</spring.cloud.version>
<spring.cloud.alibaba.version>2021.0.4.0</spring.cloud.alibaba.version>
<spring-data-redis.version>2.6.0</spring-data-redis.version>
<!--中间件相关依赖-->
<mysql.version>8.0.28</mysql.version>
<druid.version>1.2.17</druid.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version>
<rocketmq.version>2.3.0</rocketmq.version>
<jedis.verision>3.6.3</jedis.verision>
<dubbo.version>3.1.4</dubbo.version>
<schedulerx2.version>1.7.9</schedulerx2.version>
<schedulerx-plugin-kubernetes>1.0.1</schedulerx-plugin-kubernetes>
<liteflow.version>2.11.2</liteflow.version>
<!--第三方库-->
<lombok.version>1.18.24</lombok.version>
<jackson.version>2.13.4</jackson.version>
<common-lang3.version>3.12.0</common-lang3.version>
<commons-collections4.version>4.4</commons-collections4.version>
<hutool-all.version>5.8.21</hutool-all.version>
<hutool.version>5.8.21</hutool.version>
<knife.version>3.0.3</knife.version>
<bcprov-jdk15on.version>1.70</bcprov-jdk15on.version>
<jasypt.version>3.0.5</jasypt.version>
<mapstruct.version>1.5.0.Final</mapstruct.version>
<guava.version>32.1.1-jre</guava.version>
<curator.version>2.6.0</curator.version>
<perf4j.version>0.9.16</perf4j.version>
<commons-io.version>2.4</commons-io.version>
<aliyun-oss.version>3.15.1</aliyun-oss.version>
<!-- redssion -->
<redssion-spring-boot-starter.version>3.18.0</redssion-spring-boot-starter.version>
<!-- 深度智联内部二方包 -->
<!--<deepinnet-common-boot-starter-version>1.0.0.20230327-RELEASE</deepinnet-common-boot-starter-version>-->
<tp-common-lang-version>1.0.0.20231218.1-SNAPSHOT</tp-common-lang-version>
<deepinnet-common-boot-starter-version>1.0.0.20240227</deepinnet-common-boot-starter-version>
<tptradecore-common-service-facade-version>1.0.0.20241014.1-SNAPSHOT</tptradecore-common-service-facade-version>
<tpcommoncore-common-service-facade-version>1.0.0.20240730-RELEASE</tpcommoncore-common-service-facade-version>
<tpbaseopcore-common-service-facade-version>20240628.0.0-RELEASE</tpbaseopcore-common-service-facade-version>
<tpconfigcore-common-service-facade-version>1.0.0.2024011602-SNAPSHOT</tpconfigcore-common-service-facade-version>
<tpproductcore-common-service-facade-version>202407.0.0-RELEASE</tpproductcore-common-service-facade-version>
<!--本项目各模块的版本-->
<tptradeprod.version>1.0-SNAPSHOT</tptradeprod.version>
<tptradeprod-common-service-facade-version>1.0.0.20240730.1-RELEASE</tptradeprod-common-service-facade-version>
</properties>
<dependencyManagement>
<dependencies>
<!-- 引入deepinnet-common-boot-starter -->
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>deepinnet-common-boot-starter</artifactId>
<version>${deepinnet-common-boot-starter-version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tp-common-lang</artifactId>
<version>${tp-common-lang-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--中间件相关依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-common-service-integration</artifactId>
<version>${tptradeprod.version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tpcommoncore-common-service-facade</artifactId>
<version>${tpcommoncore-common-service-facade-version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-common-util</artifactId>
<version>${tptradeprod.version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-biz-service-impl</artifactId>
<version>${tptradeprod.version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-api</artifactId>
<version>${tptradeprod.version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-core-service</artifactId>
<version>${tptradeprod.version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-common-dal</artifactId>
<version>${tptradeprod.version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-core-model</artifactId>
<version>${tptradeprod.version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-common-service-facade</artifactId>
<version>${tptradeprod-common-service-facade-version}</version>
</dependency>
<!--深度内部的二方包-->
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tpconfigcore-common-service-facade</artifactId>
<version>${tpconfigcore-common-service-facade-version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradecore-common-service-facade</artifactId>
<version>${tptradecore-common-service-facade-version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tpproductcore-common-service-facade</artifactId>
<version>${tpproductcore-common-service-facade-version}</version>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tpbaseopcore-common-service-facade</artifactId>
<version>${tpbaseopcore-common-service-facade-version}</version>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId>
<version>${liteflow.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>${jasypt.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!--dubbo-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.perf4j</groupId>
<artifactId>perf4j</artifactId>
<version>${perf4j.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${bcprov-jdk15on.version}</version>
</dependency>
<!-- oss -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun-oss.version}</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>${rocketmq.version}</version>
</dependency>
<!-- knife -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife.version}</version>
</dependency>
<!--schedulerx2-->
<dependency>
<groupId>com.aliyun.schedulerx</groupId>
<artifactId>schedulerx2-spring-boot-starter</artifactId>
<version>${schedulerx2.version}</version>
<!--如果用的是logback需要把log4j和log4j2排除掉 -->
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.aliyun.schedulerx</groupId>
<artifactId>schedulerx2-plugin-kubernetes</artifactId>
<version>${schedulerx-plugin-kubernetes}</version>
</dependency>
<!--redssion-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>${redssion-spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>com.ibuscloud</groupId>
<artifactId>pubtrans-rating-common-facade</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 引入deepinnet-common-boot-starter -->
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>deepinnet-common-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!--jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${common-lang3.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

31
tptradeprod-api/pom.xml Normal file
View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>tptradeprod-api</artifactId>
<properties>
<biz-service-impl.version>1.0-SNAPSHOT</biz-service-impl.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-biz-service-impl</artifactId>
<version>${biz-service-impl.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,41 @@
package com.deepinnet.tptradeprod.controller;
//import com.deepinnet.tpcommoncore.common.service.template.email.TpEmailDispatchTimeoutStaffTemplate;
import com.deepinnet.tpcommoncore.common.service.template.sms.user.TpSmsVerifyCodeTemplate;
import com.deepinnet.tptradeprod.common.service.integration.client.email.TpEmailClient;
import com.deepinnet.tptradeprod.common.service.integration.client.sms.TpSmsClient;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @author amos wong
* @create 2023/11/9 14:40
* @Description
*/
@RestController
@RequestMapping("/message")
public class SmsTestController {
@Resource
private TpSmsClient smsClient;
@Resource
private TpEmailClient emailClient;
@PostMapping("/send/sms")
public void sendSms() {
TpSmsVerifyCodeTemplate verifyCodeTemplate = new TpSmsVerifyCodeTemplate();
verifyCodeTemplate.setCode("110119");
smsClient.sendSms("15668049807", verifyCodeTemplate);
}
@PostMapping("/send/email")
public void sendEmail() {
// TpEmailDispatchTimeoutStaffTemplate dispatchTimeoutTemplate = new TpEmailDispatchTimeoutStaffTemplate();
// dispatchTimeoutTemplate.setOrderNo(System.currentTimeMillis() + "");
// dispatchTimeoutTemplate.setOrderTime(System.currentTimeMillis() + "");
// emailClient.sendEmail("wangbiao@deepinnet.com", dispatchTimeoutTemplate);
}
}

View File

@@ -0,0 +1,51 @@
package com.deepinnet.tptradeprod.controller;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.service.facade.TpContractAcceptanceFacade;
import com.deepinnet.tptradeprod.common.vo.*;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @author amos wong
* @create 2024/1/15 17:41
* @Description
*/
@RestController
@RequestMapping(value = "/contract")
@RequiredArgsConstructor
public class TpContractTestController {
@Resource
private TpContractAcceptanceFacade contractAcceptanceFacade;
@ApiOperation("是否能够退票的校验")
@PostMapping("/available/refund/check")
public TpResult<Boolean> checkAvailableRefund(@RequestBody TpProdRefundAvailableCheckDTO checkDTO) {
return contractAcceptanceFacade.checkRefundAvailable(checkDTO);
}
@PostMapping("/calculate/amount")
public TpResult<TpProdCalculateRefundAmountVO> calculateAmount(@RequestBody TpProdCalculateRefundAmountDTO refundAmountDTO) {
return contractAcceptanceFacade.calculateRefundAmount(refundAmountDTO);
}
@PostMapping("/refund")
public TpResult<String> refund(@RequestBody TpProdRefundApplyDTO refundApplyDTO) {
return contractAcceptanceFacade.refundTicket(refundApplyDTO);
}
@PostMapping("/available/vouchers")
public TpResult<TpProdQueryAvailableRefundVoucherVO> getAvailableVouchers(@RequestBody TpProdQueryAvailableRefundVoucherDTO availableVoucherDTO) {
return contractAcceptanceFacade.queryAvailableRefundVoucherList(availableVoucherDTO);
}
@PostMapping("/refund/button")
public TpResult<Boolean> checkRefundTicketButtonShowable(@RequestBody TpProdShowRefundButtonCheckDTO showRefundButtonCheckDTO) {
return contractAcceptanceFacade.checkRefundTicketButtonShowable(showRefundButtonCheckDTO);
}
}

View File

@@ -0,0 +1,151 @@
package com.deepinnet.tptradeprod.controller;
import com.deepinnet.tenant.util.CommonTenantIdUtil;
import com.deepinnet.tp.common.lang.model.TpUserDetail;
import com.deepinnet.tp.common.lang.page.CommonPage;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tp.common.lang.util.UserDetailUtils;
import com.deepinnet.tptradecore.common.dto.order.TpOrderChangePriceDTO;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.model.TpMessageEntity;
import com.deepinnet.tptradeprod.common.service.facade.TpOrderAcceptanceFacade;
import com.deepinnet.tptradeprod.common.vo.*;
import com.deepinnet.tptradeprod.core.compoment.TpChangePriceAndPayModeComponent;
import com.deepinnet.tptradeprod.core.handler.TpPayMessageHandler;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
@Api(tags = "订单接口")
@RestController
@RequestMapping("/order")
@RequiredArgsConstructor
public class TpOrderProdController {
@DubboReference
private TpOrderAcceptanceFacade orderAcceptanceFacade;
@Resource
private TpPayMessageHandler payMessageHandler;
private final TpChangePriceAndPayModeComponent tpChangePriceAndPayModeComponent;
@ApiOperation("[订单] => [创建订单]")
@PostMapping("/create")
public TpResult<TpProdOrderCreateVO> createOrder(@RequestBody TpProdOrderCreateDTO dto) {
return orderAcceptanceFacade.createOrder(dto);
}
@ApiOperation("[订单] => [支付订单]")
@PostMapping("/prepay")
public TpResult<TpProdOrderPayVO> payOrder(@RequestBody TpProdOrderPayDTO dto) {
return orderAcceptanceFacade.payOrder(dto);
}
@ApiOperation("[订单] => [订单详情]")
@PostMapping("/detail")
public TpResult<TpProdOrderDetailVO> orderDetail(@RequestBody TpProdOrderQueryDTO dto) {
return orderAcceptanceFacade.getOrderDetail(dto);
}
@ApiOperation("[订单] => [订单列表]")
@PostMapping("/list")
public TpResult<CommonPage<TpOrderListVO>> orderList(@RequestBody TpProdOrderListQueryDTO dto) {
return orderAcceptanceFacade.getOrderList(dto);
}
@ApiOperation("[乘客] => [新增乘客]")
@PostMapping("/passenger/save")
public TpResult<String> savePassenger(@RequestBody TpUserPassengerDTO dto) {
return orderAcceptanceFacade.savePassenger(dto);
}
@ApiOperation("[乘客] => [编辑乘客]")
@PostMapping("/passenger/edit")
public TpResult<Boolean> editPassenger(@RequestBody TpUserPassengerDTO dto) {
return orderAcceptanceFacade.editPassenger(dto);
}
@ApiOperation("[乘客] => [删除乘客]")
@PostMapping("/passenger/del")
public TpResult<Boolean> delPassenger(@RequestBody TpUserPassengerQueryDTO dto) {
return orderAcceptanceFacade.delPassenger(dto);
}
@ApiOperation("[乘客] => [乘客列表]")
@PostMapping("/passenger/list")
public TpResult<List<TpUserPassengerVO>> passengerList(@RequestBody TpUserPassengerQueryDTO dto) {
return orderAcceptanceFacade.passengerList(dto);
}
@ApiOperation("支付订单")
@PostMapping("/paid")
public TpResult<TpProdOrderPaidVO> paid(@RequestBody TpProdOrderPaidDTO dto) {
return orderAcceptanceFacade.paid(dto);
}
@PostMapping("/paid/message")
public void paidMessage(@RequestBody TpMessageEntity messageEntity) {
payMessageHandler.handle(messageEntity);
}
@PostMapping("/test/syncTrip")
public void syncTrip(@RequestBody TpProdOrderQueryDTO dto) {
orderAcceptanceFacade.manualSyncTrip(dto);
}
@GetMapping("/changePriceTest")
public void changePriceTest() {
TpOrderChangePriceDTO tpOrderChangePriceDTO = new TpOrderChangePriceDTO();
tpOrderChangePriceDTO.setOriginalOrderNo("0000000000001");
tpOrderChangePriceDTO.setTenantId("test");
tpOrderChangePriceDTO.setPricingAmount("1888.00");
tpOrderChangePriceDTO.setChangeAmount("888.00");
tpOrderChangePriceDTO.setOperatorUser("001");
tpOrderChangePriceDTO.setOperatorName("juju");
tpChangePriceAndPayModeComponent.execute(tpOrderChangePriceDTO);
}
@ApiOperation("改签订单")
@PostMapping("/endorse")
public TpResult<TpProdOrderEndorseCreateVO> endorse(@RequestBody TpProdOrderCreateDTO dto) {
String tenantId = CommonTenantIdUtil.getTenantId();
dto.setTenantId(tenantId);
// 获取当前用户信息
dto.setUserNo("21875");
TpOrderPlacerVO tpOrderPlacerDTO = Optional.ofNullable(dto.getOrderPlacer()).orElse(new TpOrderPlacerVO());
tpOrderPlacerDTO.setPlacerNo("21875");
tpOrderPlacerDTO.setPlacerName("13142096520");
tpOrderPlacerDTO.setPlacerContact("13142096520");
dto.setOrderPlacer(tpOrderPlacerDTO);
return orderAcceptanceFacade.endorseOrder(dto);
}
@ApiOperation("改签订单")
@PostMapping("/reschedule")
public TpResult<TpProdOrderCreateVO> reschedule(@RequestBody TpProdOrderRescheduleDTO dto) {
TpProdOrderCreateDTO createOrderDto = dto.getCreateOrderDto();
dto.setTenantId("1000293");
dto.getCreateOrderDto().setTenantId("1000293");
// 获取当前用户信息
createOrderDto.setUserNo("21875");
createOrderDto.setUsername("13142096520");
TpOrderPlacerVO tpOrderPlacerDTO = Optional.ofNullable(createOrderDto.getOrderPlacer()).orElse(new TpOrderPlacerVO());
tpOrderPlacerDTO.setPlacerNo("21875");
tpOrderPlacerDTO.setPlacerName("13142096520");
tpOrderPlacerDTO.setPlacerContact("13142096520");
return orderAcceptanceFacade.rescheduleOrder(dto);
}
}

View File

@@ -0,0 +1,30 @@
package com.deepinnet.tptradeprod.controller;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.service.facade.*;
import com.deepinnet.tptradeprod.common.vo.*;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.*;
/**
* @author amos wong
* @create 2023/9/13 17:23
* @Description
*/
@RestController
@RequestMapping("/payment")
@RequiredArgsConstructor
public class TpPaymentController {
@DubboReference
private TpPaymentAcceptanceFacade paymentAcceptanceFacade;
@ApiOperation("查询支付结果")
@PostMapping("/pay/result")
public TpResult<TpProdQueryPayResultVO> queryPayResult(@RequestBody TpProdQueryPayResultDTO dto) {
return paymentAcceptanceFacade.queryPayResult(dto);
}
}

View File

@@ -0,0 +1,137 @@
package com.deepinnet.tptradeprod.controller;
import cn.hutool.core.date.*;
import cn.hutool.core.util.*;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpbaseopcore.common.dto.route.*;
import com.deepinnet.tpproductcore.common.dto.rule.*;
import com.deepinnet.tpproductcore.common.enums.TpRuleExpressionGroupEnum;
import com.deepinnet.tptradeprod.common.enums.TpProdOrderTicketTypeEnum;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.deepinnet.tptradeprod.common.service.integration.client.*;
import com.google.common.collect.Lists;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.List;
/**
* <p>
* 规则测试接口
* </p>
*
* @author chenjiaju
* @since 2023/9/20
*/
@Api(tags = "规则线路接口")
@RestController
@RequestMapping("/rule")
@RequiredArgsConstructor
public class TpRuleProdController {
@Resource
private TpBizRuleClient bizRuleClient;
@Resource
private TpRouteClient routeClient;
@ApiOperation("[规则接口] => [限购规则]")
@PostMapping("/buyLimitRule")
public TpResult<Boolean> buyLimitRule() {
// 当前订单票数
int currentOrderTickets = 0;
int currentDayUserTickets = 100;
TpBuyCountLimitParamDTO tpBuyCountLimitParamDTO = new TpBuyCountLimitParamDTO();
tpBuyCountLimitParamDTO.setDayBuyCount(currentDayUserTickets);
tpBuyCountLimitParamDTO.setOrderBuyCount(currentOrderTickets);
List<String> ruleList = Lists.newArrayList();
ruleList.add("if(\"day\".equals(\"order\"))" +
"{ return orderBuyCount <= 5}" +
" if(\"day\".equals(\"day\"))" +
"{ return dayBuyCount + orderBuyCount <= 5;} " +
"return false;");
TpRuleExecuteDTO<TpBuyCountLimitParamDTO> tpRuleExecuteDTO = new TpRuleExecuteDTO<>();
// 设置表达式入参
tpRuleExecuteDTO.setParameter(tpBuyCountLimitParamDTO);
// 设置购买的规则表达式
tpRuleExecuteDTO.setRuleList(ruleList);
tpRuleExecuteDTO.setRuleExpressionGroup(TpRuleExpressionGroupEnum.BUY_COUNT);
TpRuleExecuteResultVO<Boolean> resultVO = bizRuleClient.executeRule(tpRuleExecuteDTO);
if (!resultVO.getResult()) {
LogUtil.error("当前用户:{}, 购买票数量超过限制", "USER_001");
throw new TpTradeProdException(TpTradeProdErrorCode.USER_BUY_LIMIT_ERROR);
}
return TpResult.success(Boolean.TRUE);
}
@ApiOperation("[规则接口] => [放票规则]")
@GetMapping("/ticketRule")
public TpResult<Boolean> ticketRule(@RequestParam(defaultValue = "day") @NotBlank String ticketType) {
TpProdOrderTicketTypeEnum ticketTypeEnum = TpProdOrderTicketTypeEnum.getEnum(ticketType);
if (ObjectUtil.isNull(ticketTypeEnum)) {
LogUtil.error("票类型错误, {}", ticketType);
throw new TpTradeProdException(TpTradeProdErrorCode.TICKET_TYPE_ERROR);
}
// 设置最早放票时间
TpTicketBuyParamDTO tpTicketBuyParamDTO = new TpTicketBuyParamDTO();
// 2023-09-22 00:00:00
tpTicketBuyParamDTO.setStartTime(DateUtil.offset(DateUtil.date(), DateField.DAY_OF_WEEK, 2).toString());
TpRuleExecuteDTO<TpTicketBuyParamDTO> tpRuleExecuteDTO = new TpRuleExecuteDTO<>();
List<String> ruleList = Lists.newArrayList();
// 日票
if (StrUtil.equals(TpProdOrderTicketTypeEnum.DAY.getTicketType(), ticketType)) {
ruleList.add("return new Date().getTime() >= startTime - (3 * 86400000);");
}
// 周票
if (StrUtil.equals(TpProdOrderTicketTypeEnum.WEEK.getTicketType(), ticketType)) {
ruleList.add("import com.deepinnet.tp.common.lang.util.TpMoney;\n import java.time.LocalDate;\n import java.lang.String; \n return LocalDate.now().getDayOfWeek().getValue() >= 3");
ruleList.add("return new Date().getTime() >= startTime - (3 * 86400000);");
}
// 月票
if (StrUtil.equals(TpProdOrderTicketTypeEnum.MONTH.getTicketType(), ticketType)) {
ruleList.add("import com.deepinnet.tp.common.lang.util.TpMoney;\n import java.time.LocalDate;\n import java.lang.String; \n return LocalDate.now().getDayOfMonth() >= 3");
ruleList.add("return new Date().getTime() >= startTime - (3 * 86400000);");
}
tpRuleExecuteDTO.setRuleList(ruleList);
tpRuleExecuteDTO.setParameter(tpTicketBuyParamDTO);
TpRuleExecuteResultVO<Boolean> resultVO = bizRuleClient.executeRule(tpRuleExecuteDTO);
if (!resultVO.getResult()) {
LogUtil.error("当前时间暂不能购买");
throw new TpTradeProdException(TpTradeProdErrorCode.USER_BUY_TIME_ERROR);
}
return TpResult.success(Boolean.TRUE);
}
@ApiOperation("[线路接口] => [线路详情]")
@PostMapping("/routeDetail")
public TpResult<RouteDetail2CDTO> routeDetail() {
RouteDetail2CDTO routeDetail = routeClient.getRouteDetail2C("DZGJ1695179273514", "test");
return TpResult.success(routeDetail);
}
@ApiOperation("[线路接口] => [班次详情]")
@PostMapping("/shuttleDetail")
public TpResult<ShuttleRouteStationTimeDTO> shuttleDetail() {
ShuttleRouteStationTimeDTO shuttleRouteStationTimeDTO = routeClient.queryRouteStationInShuttle("DZGJ1695179273514", null, null, "test");
return TpResult.success(shuttleRouteStationTimeDTO);
}
}

View File

@@ -0,0 +1,61 @@
package com.deepinnet.tptradeprod.controller;
import com.deepinnet.tptradeprod.biz.task.TpScheduleTaskService;
import com.deepinnet.tptradeprod.biz.task.worker.AbstractBaseTaskWorker;
import com.deepinnet.tptradeprod.common.enums.task.TpScheduleTaskTypeEnum;
import com.deepinnet.tptradeprod.core.model.task.TpScheduleTask;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author amos wong
* @create 2023/12/22 15:20
* @Description
*/
@RestController
@RequestMapping("/task")
@RequiredArgsConstructor
public class TpScheduleTaskTestController implements InitializingBean {
@Resource
private Map<String, AbstractBaseTaskWorker> taskWorkerMap;
@Resource
private TpScheduleTaskService scheduleTaskService;
private final Map<TpScheduleTaskTypeEnum, AbstractBaseTaskWorker> scheduleTypeWorkerMap = new ConcurrentHashMap<>();
@Override
public void afterPropertiesSet() throws Exception {
taskWorkerMap
.values()
.parallelStream()
.forEach(taskWorker -> scheduleTypeWorkerMap.put(taskWorker.getTaskType(), taskWorker));
}
@PostMapping("/manualExecute")
public String manualExecuteTask(Long taskId) {
TpScheduleTask scheduleTask = scheduleTaskService.getTaskById(taskId);
if (scheduleTask == null) {
return "fail";
}
AbstractBaseTaskWorker taskWorker = scheduleTypeWorkerMap.get(TpScheduleTaskTypeEnum.getByType(scheduleTask.getTaskType()));
if (taskWorker == null) {
return "fail";
}
try {
taskWorker.doCommit(scheduleTask);
return "success";
} catch (Exception e) {
e.printStackTrace();
return "fail";
}
}
}

View File

@@ -0,0 +1,27 @@
package com.deepinnet.tptradeprod.controller;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.service.facade.TpVoucherAcceptanceFacade;
import com.deepinnet.tptradeprod.common.vo.TpQueryAvailableRescheduleVoucherDTO;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @author amos wong
* @create 2024/7/5 11:34
* @Description
*/
@RestController
@RequestMapping("/voucher")
public class TpVoucherTestController {
@Resource
private TpVoucherAcceptanceFacade voucherAcceptanceFacade;
@PostMapping("/available/reschedule")
public TpResult<TpQueryAvailableRescheduleVoucherDTO> getAvailableRescheduleVoucherList(@RequestBody TpProdQueryAvailableRescheduleVoucherDTO queryDTO) {
return voucherAcceptanceFacade.queryAvailableRescheduleVoucherList(queryDTO);
}
}

View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>tptradeprod-app-starter</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-biz-service-impl</artifactId>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.jsonzou</groupId>
<artifactId>jmockdata</artifactId>
<version>4.3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--dubbo-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
</dependency>
<!-- knife -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<finalName>tptradeprod</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.6</version>
<configuration>
<mainClass>com.deepinnet.tptradeprod.ApplicationStarter</mainClass>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<!--可以把依赖的包都打包到生成的Jar包中-->
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 测试需要的插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>${argLine} -Djacoco.agent.destfile=target/jacoco.exec</argLine>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<executions>
<execution>
<id>report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.yml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

View File

@@ -0,0 +1,23 @@
package com.deepinnet.tptradeprod;
import cn.hutool.extra.spring.EnableSpringUtil;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@MapperScan({"com.deepinnet.tptradeprod.common.dal.dao"})
@EnableDubbo(scanBasePackages = "com.deepinnet")
@EnableScheduling
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableSpringUtil
public class ApplicationStarter {
public static void main(String[] args) {
SpringApplication.run(ApplicationStarter.class, args);
}
}

View File

@@ -0,0 +1,100 @@
package com.deepinnet.tptradeprod.advise;
import com.deepinnet.tp.common.lang.exception.TpException;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.rpc.RpcException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;
import javax.validation.*;
import java.util.stream.Collectors;
/**
* Description: 全局异常统一处理
* <p>
* Date: 2022/11/2
* Author: lijunheng
*/
@Slf4j
@RestControllerAdvice
public class GlobalControllerAdvise {
/**
* RPC异常处理
*/
@ExceptionHandler(RpcException.class)
public TpResult RpcExceptionHandler(RpcException e) {
log.error("RPC服务异常", e);
return TpResult.fail(TpTradeProdErrorCode.INTERNAL_SERVER_ERROR.getCode(), TpTradeProdErrorCode.INTERNAL_SERVER_ERROR.getDesc());
}
/**
* 处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public TpResult methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";"));
return TpResult.fail(TpTradeProdErrorCode.ILLEGAL_PARAMS.getCode(), message);
}
/**
* 处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常
*/
@ExceptionHandler(BindException.class)
public TpResult bindExceptionHandler(BindException e) {
log.error("系统业务异常", e);
String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";"));
return TpResult.fail(TpTradeProdErrorCode.ILLEGAL_PARAMS.getCode(), message);
}
/**
* 处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是ConstraintViolationException
*/
@ExceptionHandler(ConstraintViolationException.class)
public TpResult constraintViolationExceptionHandler(ConstraintViolationException e) {
log.error("系统业务异常", e);
String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(";"));
return TpResult.fail(TpTradeProdErrorCode.ILLEGAL_PARAMS.getCode(), message);
}
/**
* 系统具体异常提示
*
* @param e
* @return
*/
@ExceptionHandler(TpTradeProdException.class)
public TpResult tradeProdExceptionHandler(TpTradeProdException e) {
log.error("系统业务异常", e);
return TpResult.fail(e.getErrorCode().getCode(), e.getMessage());
}
/**
* 系统具体异常提示
*
* @param e
* @return
*/
@ExceptionHandler(TpException.class)
public TpResult tpExceptionHandler(TpException e) {
log.error("系统业务异常", e);
return TpResult.fail(e.getErrorCode(), e.getMessage());
}
/**
* 内部兜底异常处理
*
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public TpResult exceptionHandler(Exception e) {
log.error("系统异常", e);
return TpResult.fail(TpTradeProdErrorCode.INTERNAL_SERVER_ERROR.getCode(), TpTradeProdErrorCode.INTERNAL_SERVER_ERROR.getDesc());
}
}

View File

@@ -0,0 +1,88 @@
package com.deepinnet.tptradeprod.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;
/**
* Knife Configuration
*
* @author chenjiaju
* @version 2023/08/18
*/
@Configuration
@EnableSwagger2
public class Knife4jConfiguration {
@Bean(value = "docketBean")
public Docket docketBean() {
//指定使用Swagger2规范
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.title("tptradeprod-接口文档")
//描述字段支持Markdown语法
.description("# tptradeprod-Rest API")
.termsOfServiceUrl("http://localhost:8080/")
.contact(new Contact("chenjiaju", "http://localhost:8080","ccc-ju@outlook.com"))
.version("1.0")
.build())
//分组名称
.groupName("tptradeprod")
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.deepinnet"))
.paths(PathSelectors.any())
.build();
}
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
}

View File

@@ -0,0 +1,43 @@
package com.deepinnet.tptradeprod.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.apache.rocketmq.spring.support.RocketMQMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.messaging.converter.CompositeMessageConverter;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.MessageConverter;
import java.util.List;
/**
* RocketMQ序列化器处理
*
* @author tianxincoord@163.com
* @since 2022/5/13
*/
@Configuration
public class RocketMQConfig {
/**
* 解决RocketMQ Jackson不支持Java时间类型配置
*/
@Bean
@Primary
public RocketMQMessageConverter createRocketMQMessageConverter() {
RocketMQMessageConverter converter = new RocketMQMessageConverter();
CompositeMessageConverter compositeMessageConverter = (CompositeMessageConverter) converter.getMessageConverter();
List<MessageConverter> messageConverterList = compositeMessageConverter.getConverters();
for (MessageConverter messageConverter : messageConverterList) {
if (messageConverter instanceof MappingJackson2MessageConverter) {
MappingJackson2MessageConverter jackson2MessageConverter = (MappingJackson2MessageConverter) messageConverter;
ObjectMapper objectMapper = jackson2MessageConverter.getObjectMapper();
// 增加Java8时间模块支持实体类可以传递LocalDate/LocalDateTime
objectMapper.registerModules(new JavaTimeModule());
}
}
return converter;
}
}

View File

@@ -0,0 +1,34 @@
package com.deepinnet.tptradeprod.config;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import javax.validation.Validation;
import javax.validation.Validator;
@Configuration
public class ValidatorConfig {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
postProcessor.setBeforeExistingAdvisors(false);
postProcessor.setProxyTargetClass(true);
postProcessor.setValidator(validator());
return postProcessor;
}
/**
* 开启快速失败模式,一旦失败立即抛出异常
*/
@Bean
public Validator validator() {
return Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(true)
.buildValidatorFactory()
.getValidator();
}
}

View File

@@ -0,0 +1,43 @@
spring:
redis:
host: 192.168.3.200
port: 6379
password: ENC(ao+A54rgdnsZ/wIydpBlnxYqM34u5B4O)
# dubbo
dubbo:
application:
name: ${spring.application.name}
registry:
address: nacos://192.168.3.200:8848
parameters:
namespace: ${spring.cloud.nacos.discovery.namespace}
protocol:
port: 20880
provider:
timeout: 3000
retries: 0
check: false
consumer:
timeout: 3000
retries: 0
check: false
# 打印日志的配置
logging:
level:
com:
alibaba:
cloud:
nacos:
client: debug
message:
consumerGroup: GID_${spring.application.name}-consumer-group-${spring.profiles.active}
delayConsumerGroup: GID_${spring.application.name}-delay-consumer-group-${spring.profiles.active}
pos:
guolang:
url: http://posdemo3.hzgolong.com:41001/api/pos/notice
secretKey: 141dd8dd814b20baf326daa1f563b5ec

View File

@@ -0,0 +1,86 @@
spring:
redis:
host: 192.168.3.200
port: 6379
password: ENC(ao+A54rgdnsZ/wIydpBlnxYqM34u5B4O)
autoconfigure:
exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
url: jdbc:mysql://rm-bp193v7i846v01k442o.mysql.rds.aliyuncs.com:3306/tp_order-env-dev?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
# 内网地址
#url: jdbc:mysql://rm-bp193v7i846v01k44.mysql.rds.aliyuncs.com:3306/ins?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: tp_deepinnet_dev
password: B%dkLnXRt@nWjeUA
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
filters: stat,wall
initialSize: 5
keepAlive: true
maxActive: 20
maxPoolPreparedStatementPerConnectionSize: 20
maxWait: 60000
minEvictableIdleTimeMillis: 300000
minIdle: 5
poolPreparedStatements: true
testOnBorrow: true
testOnReturn: true
testWhileIdle: true
timeBetweenEvictionRunsMillis: 60000
useGlobalDataSourceStat: true
validationQuery: SELECT 1
stat-view-servlet:
enabled: true
url-pattern: /druid/*
# dubbo
dubbo:
application:
name: ${spring.application.name}
registry:
address: nacos://192.168.3.200:8848
parameters:
namespace: ${spring.cloud.nacos.discovery.namespace}
protocol:
port: 20880
provider:
timeout: 30000
retries: 0
check: false
consumer:
timeout: 30000
retries: 0
check: false
#MQ
rocketmq:
name-server: 192.168.3.200:9876
# name-server: rmq-cn-zvp2yd8rt03-vpc.cn-hangzhou.rmq.aliyuncs.com:8080
producer:
group: ${spring.application.name}-provider-group
access-key: ENC(1tdvMPxo2WaCW3exv64HG7LQHgg/T/zdUsubpXmYHjU=)
secret-key: ENC(SIbQF8Bjxfgf6ehjLtwj5azXCl2tEV79XcRL2IbEQHU=)
enable-msg-trace: true
arthas:
agent-id: ${spring.application.name}
tunnel-server: ws://192.168.3.200:10077/ws
# 打印日志的配置
logging:
level:
com:
alibaba:
cloud:
nacos:
client: debug
message:
consumerGroup: GID_${spring.application.name}-consumer-group-${spring.profiles.active}
delayConsumerGroup: GID_${spring.application.name}-delay-consumer-group-${spring.profiles.active}
pos:
guolang:
url: http://posdemo3.hzgolong.com:41001/api/pos/notice
secretKey: 141dd8dd814b20baf326daa1f563b5ec

View File

@@ -0,0 +1,88 @@
spring:
redis:
host: r-bp1ev5drg1lfxkny1p.redis.rds.aliyuncs.com
port: 6379
username: ENC(SCb67WmqS3xLcOWcrGfpRpEszS+bfTEuwycZPawDOPo=)
password: ENC(Va6APbdZCz2kBtKJQIVb97XY4KM6t6qXRnIO5IGY/+U=)
database: 0
autoconfigure:
exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
url: jdbc:mysql://rm-bp13l2n5s8gvc0g7a.mysql.rds.aliyuncs.com:3306/tp_order-env-prod?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: ENC(SSQ+shVgs44I1MYoh21T5197DmHjJBBiDcyfXcePf1M=)
password: ENC(rkHZZpYsDbG+npIGG/P4RAGMf9ySzKDmtiwcTDGoliA=)
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
filters: stat,wall
initialSize: 5
keepAlive: true
maxActive: 20
maxPoolPreparedStatementPerConnectionSize: 20
maxWait: 60000
minEvictableIdleTimeMillis: 300000
minIdle: 5
poolPreparedStatements: true
testOnBorrow: true
testOnReturn: true
testWhileIdle: true
timeBetweenEvictionRunsMillis: 60000
useGlobalDataSourceStat: true
validationQuery: SELECT 1
stat-view-servlet:
enabled: true
url-pattern: /druid/*
# dubbo
dubbo:
application:
name: ${spring.application.name}
registry:
address: nacos://192.168.3.200:8848
parameters:
namespace: ${spring.cloud.nacos.discovery.namespace}
protocol:
port: 20880
provider:
timeout: 5000
retries: 0
check: false
consumer:
timeout: 5000
retries: 0
check: false
# 打印日志的配置
logging:
level:
com:
alibaba:
cloud:
nacos:
client: debug
#MQ
rocketmq:
name-server: ep-bp1ie6850ec21aa6c1cd.epsrv-bp1g2k84c7kid2igyiun.cn-hangzhou.privatelink.aliyuncs.com:8080
producer:
group: GID_${spring.application.name}-provider-group-${spring.profiles.active}
access-key: ENC(kIlPWF9cvjyrFjCGo+XO6y43TzYf99t0W3M/eOdi8wI=)
secret-key: ENC(ZWjaBSFtTZh7asRax8+mC1eGf+uSAuLVvUimRr1QB/4=)
enable-msg-trace: true
consumer:
group: GID_${spring.application.name}-consumer-group-${spring.profiles.active}
access-key: ENC(kIlPWF9cvjyrFjCGo+XO6y43TzYf99t0W3M/eOdi8wI=)
secret-key: ENC(ZWjaBSFtTZh7asRax8+mC1eGf+uSAuLVvUimRr1QB/4=)
mybatis-plus:
mapper-locations: classpath*:mybatis/mapper/*/*Mapper.xml
message:
consumerGroup: GID_${spring.application.name}-consumer-group-${spring.profiles.active}
delayConsumerGroup: GID_${spring.application.name}-delay-consumer-group-${spring.profiles.active}
pos:
guolang:
url: http://10.0.30.157:41001/api/pos/notice
secretKey: 246dd25f10552ba553912d018f4df26f

View File

@@ -0,0 +1,88 @@
spring:
redis:
host: r-bp1ev5drg1lfxkny1p.redis.rds.aliyuncs.com
port: 6379
username: ENC(SCb67WmqS3xLcOWcrGfpRpEszS+bfTEuwycZPawDOPo=)
password: ENC(Va6APbdZCz2kBtKJQIVb97XY4KM6t6qXRnIO5IGY/+U=)
database: 1
autoconfigure:
exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
url: jdbc:mysql://rm-bp13l2n5s8gvc0g7a.mysql.rds.aliyuncs.com:3306/tp_order-env-prod?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: ENC(SSQ+shVgs44I1MYoh21T5197DmHjJBBiDcyfXcePf1M=)
password: ENC(rkHZZpYsDbG+npIGG/P4RAGMf9ySzKDmtiwcTDGoliA=)
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
filters: stat,wall
initialSize: 5
keepAlive: true
maxActive: 20
maxPoolPreparedStatementPerConnectionSize: 20
maxWait: 60000
minEvictableIdleTimeMillis: 300000
minIdle: 5
poolPreparedStatements: true
testOnBorrow: true
testOnReturn: true
testWhileIdle: true
timeBetweenEvictionRunsMillis: 60000
useGlobalDataSourceStat: true
validationQuery: SELECT 1
stat-view-servlet:
enabled: true
url-pattern: /druid/*
# dubbo
dubbo:
application:
name: ${spring.application.name}
registry:
address: nacos://192.168.3.200:8848
parameters:
namespace: ${spring.cloud.nacos.discovery.namespace}
protocol:
port: 20880
provider:
timeout: 5000
retries: 0
check: false
consumer:
timeout: 5000
retries: 0
check: false
# 打印日志的配置
logging:
level:
com:
alibaba:
cloud:
nacos:
client: debug
#MQ
rocketmq:
name-server: ep-bp1ie6850ec21aa6c1cd.epsrv-bp1g2k84c7kid2igyiun.cn-hangzhou.privatelink.aliyuncs.com:8080
producer:
group: GID_${spring.application.name}-provider-group-${spring.profiles.active}
access-key: ENC(kIlPWF9cvjyrFjCGo+XO6y43TzYf99t0W3M/eOdi8wI=)
secret-key: ENC(ZWjaBSFtTZh7asRax8+mC1eGf+uSAuLVvUimRr1QB/4=)
enable-msg-trace: true
consumer:
group: GID_${spring.application.name}-consumer-group-${spring.profiles.active}
access-key: ENC(kIlPWF9cvjyrFjCGo+XO6y43TzYf99t0W3M/eOdi8wI=)
secret-key: ENC(ZWjaBSFtTZh7asRax8+mC1eGf+uSAuLVvUimRr1QB/4=)
mybatis-plus:
mapper-locations: classpath*:mybatis/mapper/*/*Mapper.xml
message:
consumerGroup: GID_${spring.application.name}-consumer-group-${spring.profiles.active}
delayConsumerGroup: GID_${spring.application.name}-delay-consumer-group-${spring.profiles.active}
pos:
guolang:
url: http://10.0.30.157:41001/api/pos/notice
secretKey: 246dd25f10552ba553912d018f4df26f

View File

@@ -0,0 +1,93 @@
spring:
redis:
host: r-bp1jtsv1a3ougumlzw.redis.rds.aliyuncs.com
port: 6379
username: ENC(9d6KFkbMHm78VQO26J2gNbV9UGuiDZJL)
password: ENC(08E69p0zaGkABm5yj/nV4B3UWGoQeBhWvc7F5JbTp3g=)
database: 1
autoconfigure:
exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
# 公网地址 记得替换地址和密码!!!
url: jdbc:mysql://rm-bp193v7i846v01k442o.mysql.rds.aliyuncs.com:3306/tp_order-env-test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
# 内网地址
#url: jdbc:mysql://rm-bp193v7i846v01k44.mysql.rds.aliyuncs.com:3306/ins?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: tp_deepinnet_test
password: 20230424MnfFfdWZsyH2KvuF
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
filters: stat,wall
initialSize: 5
keepAlive: true
maxActive: 20
maxPoolPreparedStatementPerConnectionSize: 20
maxWait: 60000
minEvictableIdleTimeMillis: 300000
minIdle: 5
poolPreparedStatements: true
testOnBorrow: true
testOnReturn: true
testWhileIdle: true
timeBetweenEvictionRunsMillis: 60000
useGlobalDataSourceStat: true
validationQuery: SELECT 1
stat-view-servlet:
enabled: true
url-pattern: /druid/*
# dubbo
dubbo:
application:
name: ${spring.application.name}
registry:
address: nacos://192.168.3.200:8848
parameters:
namespace: ${spring.cloud.nacos.discovery.namespace}
protocol:
port: 20880
provider:
timeout: 10000
retries: 0
check: false
consumer:
timeout: 10000
retries: 0
check: false
# 打印日志的配置
logging:
level:
com:
alibaba:
cloud:
nacos:
client: debug
#MQ
rocketmq:
name-server: rmq-cn-lbj3h31640b-vpc.cn-hangzhou.rmq.aliyuncs.com:8080
producer:
group: ${spring.application.name}-provider-group
access-key: ENC(1g0pNKHGlvtuY4YKgOlGr/MH2BbcDNu0+qPTvjR/EIo=)
secret-key: ENC(MeO1kHiQbBCu4qPRFcCWlgGzbKNl6rOg7YyXxCDNH0M=)
enable-msg-trace: true
consumer:
group: ${spring.application.name}-consumer-group
mybatis-plus:
mapper-locations: classpath*:mybatis/mapper/*/*Mapper.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
sql:
print: true
message:
consumerGroup: GID_${spring.application.name}-consumer-group-${spring.profiles.active}
delayConsumerGroup: GID_${spring.application.name}-delay-consumer-group-${spring.profiles.active}
pos:
guolang:
url: http://posdemo3.hzgolong.com:41001/api/pos/notice
secretKey: 141dd8dd814b20baf326daa1f563b5ec

View File

@@ -0,0 +1,61 @@
# oss配置
oss:
accessSecret: ENC(ys+mbFnF71afPL22YUWw0P0B/RSRMh8vgOswK7KhFIq5tq3/SAZQQg==)
accessKey: ENC(NaC4iCnLX+bUXi5ifbwjJQXenTTsKE5xpt7QXQs0nMPxzCfgxzQfVQ==)
# 文件过期时间 3600 * 1000 默认1个小时 (毫秒)
expireMilliSecond: 3600000
spring:
# 防止 Knife4j 2.0及以上版本访问报错
mvc:
pathmatch:
matching-strategy: ant_path_matcher
jasypt:
encryptor:
# 自定义加密盐值(密钥)
password: shendu188
# 加密算法设置
algorithm: PBEWithMD5AndDES
iv-generator-classname: org.jasypt.iv.NoIvGenerator
message:
trans-pay-topic: TP_TRADECORE_EVENT_TOPIC-${spring.profiles.active}
delay-topic: TP_TRADECORE_DELAY_EVENT_TOPIC-${spring.profiles.active}
liteflow:
#规则文件路径
rule-source: config/flow.el.xml
#-----------------以下非必须-----------------
#liteflow是否开启默认为true
enable: true
#liteflow的banner打印是否开启默认为true
print-banner: false
#异步线程最长的等待时间(只用于when)默认值为15000
when-max-wait-time: 15000
#异步线程最长的等待时间(只用于when)默认值为MILLISECONDS毫秒
when-max-wait-time-unit: MILLISECONDS
#when节点全局异步线程池最大线程数默认为16
when-max-workers: 128
#when节点全局异步线程池等待队列数默认为512
when-queue-limit: 512
#是否在启动的时候就解析规则默认为true
parse-on-start: true
#全局重试次数默认为0
retry-count: 0
#是否支持不同类型的加载方式混用默认为false
support-multiple-type: false
#是否打印执行中过程中的日志默认为true
print-execution-log: false
#是否开启本地文件监听默认为false
enable-monitor-file: false
#简易监控配置选项
monitor:
#监控是否开启,默认不开启
enable-log: false
#监控队列存储大小默认值为200
queue-limit: 200
#监控一开始延迟多少执行默认值为300000毫秒也就是5分钟
delay: 300000
#监控日志打印每过多少时间执行一次默认值为300000毫秒也就是5分钟
period: 300000

View File

@@ -0,0 +1,23 @@
server:
port: 8080
spring:
application:
name: tptradeprod
# nacos
cloud:
nacos:
# 注册中心的配置
discovery:
server-addr: http://192.168.3.200:8848
namespace: tp_dev
group: DEFAULT_GROUP
register-enabled: false
config:
import-check:
enabled: false
server-addr: http://192.168.3.200:8848
refresh-enabled: true
namespace: ${spring.cloud.nacos.discovery.namespace}
name: ${spring.application.name}
file-extension: properties

View File

@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread][%X{traceId}][BizType:%X{bizType}] %-5level %logger{36} - %msg%n"/>
<!--dev文件路径src同级目录logs,如果上级目录不存在会自动创建-->
<property name="LOG_FILE_PATH" value="./logs/tptradeprod" />
<!-- 控制台输出 -->
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 按照每天生成系统默认日志文件 -->
<appender name="defaultAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE_PATH}/common-default.log</file>
<encoder charset="UTF-8">
<!--格式化输出:%d表示日期%thread表示线程%-5level级别从左显示五个字符宽度%logger{36}logger是class的全名,后面的数字代表限制最长的字符,%msg日志消息%n换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread][%X{traceId}][Tenant-Id:%X{Tenant-Id}][BizType:%X{bizType}] %-5level %logger{36}:%L - %msg%n</pattern>
</encoder>
<!--滚动策略按照时间滚动-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily 文件名称 -->
<fileNamePattern>${LOG_FILE_PATH}/common-default.log.%d{yyyy-MM-dd}</fileNamePattern>
</rollingPolicy>
</appender>
<!-- 按照每天生成系统默认日志文件 -->
<appender name="dalAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE_PATH}/common-dal.log</file>
<encoder charset="UTF-8">
<!--格式化输出:%d表示日期%thread表示线程%-5level级别从左显示五个字符宽度%logger{36}logger是class的全名,后面的数字代表限制最长的字符,%msg日志消息%n换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread][%X{traceId}][Tenant-Id:%X{Tenant-Id}][BizType:%X{bizType}] %-5level %logger{36}:%L - %msg%n</pattern>
</encoder>
<!--滚动策略按照时间滚动-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily 文件名称 -->
<fileNamePattern>${LOG_FILE_PATH}/common-dal.log.%d{yyyy-MM-dd}</fileNamePattern>
</rollingPolicy>
</appender>
<!-- 按照每天生成业务摘要日志文件 -->
<appender name="bizDigestAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE_PATH}/biz-digest.log</file>
<encoder charset="UTF-8">
<!--格式化输出:%d表示日期%thread表示线程%-5level级别从左显示五个字符宽度%logger{36}logger是class的全名,后面的数字代表限制最长的字符,%msg日志消息%n换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread][%X{traceId}][Tenant-Id:%X{Tenant-Id}][BizType:%X{bizType}] %-5level %logger{36}:%L - %msg%n</pattern>
</encoder>
<!--滚动策略按照时间滚动-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily 文件名称 -->
<fileNamePattern>${LOG_FILE_PATH}/biz-digest.log.%d{yyyy-MM-dd}</fileNamePattern>
</rollingPolicy>
</appender>
<!-- 按照每天生成消息日志文件 -->
<appender name="messageAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE_PATH}/message.log</file>
<encoder charset="UTF-8">
<!--格式化输出:%d表示日期%thread表示线程%-5level级别从左显示五个字符宽度%logger{36}logger是class的全名,后面的数字代表限制最长的字符,%msg日志消息%n换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread][%X{traceId}][Tenant-Id:%X{Tenant-Id}][BizType:%X{bizType}] %-5level %logger{36}:%L - %msg%n</pattern>
</encoder>
<!--滚动策略按照时间滚动-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily 文件名称 -->
<fileNamePattern>${LOG_FILE_PATH}/message.log.%d{yyyy-MM-dd}</fileNamePattern>
</rollingPolicy>
</appender>
<!-- 按照每天生成定时任务的日志文件 -->
<appender name="scheduleTaskAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE_PATH}/task.log</file>
<encoder charset="UTF-8">
<!--格式化输出:%d表示日期%thread表示线程%-5level级别从左显示五个字符宽度%logger{36}logger是class的全名,后面的数字代表限制最长的字符,%msg日志消息%n换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread][%X{traceId}][Tenant-Id:%X{Tenant-Id}][BizType:%X{bizType}] %-5level %logger{36}:%L - %msg%n</pattern>
</encoder>
<!--滚动策略按照时间滚动-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily 文件名称 -->
<fileNamePattern>${LOG_FILE_PATH}/task.log.%d{yyyy-MM-dd}</fileNamePattern>
</rollingPolicy>
</appender>
<!-- 按照每天生成二方/三方集成日志文件 -->
<appender name="integrationAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE_PATH}/integration.log</file>
<encoder charset="UTF-8">
<!--格式化输出:%d表示日期%thread表示线程%-5level级别从左显示五个字符宽度%logger{36}logger是class的全名,后面的数字代表限制最长的字符,%msg日志消息%n换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread][%X{traceId}][Tenant-Id:%X{Tenant-Id}][BizType:%X{bizType}] %-5level %logger{36}:%L - %msg%n</pattern>
</encoder>
<!--滚动策略按照时间滚动-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily 文件名称 -->
<fileNamePattern>${LOG_FILE_PATH}/integration.log.%d{yyyy-MM-dd}</fileNamePattern>
</rollingPolicy>
</appender>
<!-- 按照每天生成错误日志文件 -->
<appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE_PATH}/common-error.log</file>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder charset="UTF-8">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread][%X{traceId}][Tenant-Id:%X{Tenant-Id}][BizType:%X{bizType}] %-5level %logger{36}:%L - %msg%n</pattern>
</encoder>
<!--输出日志到src同级目录logs中的error.log文件中-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}/common-error.log.%d{yyyy-MM-dd}</fileNamePattern>
</rollingPolicy>
</appender>
<logger name="BIZ-DIGEST-LOG" level="info" additivity="false">
<appender-ref ref="bizDigestAppender" />
</logger>
<logger name="MESSAGE-LOG" level="info" additivity="false">
<appender-ref ref="messageAppender" />
</logger>
<logger name="SCHEDULE-TASK-LOG" level="info" additivity="false">
<appender-ref ref="scheduleTaskAppender" />
</logger>
<logger name="INTEGRATION-LOG" level="info" additivity="false">
<appender-ref ref="integrationAppender" />
</logger>
<logger name="DAL-LOG" level="info" additivity="false">
<appender-ref ref="dalAppender" />
</logger>
<root level="INFO">
<appender-ref ref="consoleAppender" />
<appender-ref ref="defaultAppender" />
<appender-ref ref="errorAppender" />
</root>
</configuration>

View File

@@ -0,0 +1,102 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import com.deepinnet.tpproductcore.common.dto.rule.TpRuleExecuteDTO;
import com.deepinnet.tptradeprod.common.service.integration.client.TpBizRuleClient;
import com.deepinnet.tpproductcore.common.vo.TpSalesUnitVO;
import com.deepinnet.tptradeprod.common.service.integration.client.TpProductSalesUnitClient;
import com.deepinnet.tpproductcore.common.dto.rule.TpRuleExecuteBatchResultVO;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.util.TestUtils;
import org.junit.jupiter.params.provider.ValueSource;
import com.deepinnet.tpproductcore.common.qto.TpSalesUnitQueryDTO;
import com.deepinnet.tpproductcore.common.qto.product.TpProductQueryDTO;
import lombok.SneakyThrows;
import com.deepinnet.tpproductcore.common.dto.rule.TpRuleExecuteResultVO;
import com.deepinnet.tpproductcore.common.dto.product.TpProdDetailDTO;
import com.yomahub.liteflow.core.NodeComponent;
import java.math.BigDecimal;
import com.deepinnet.tptradecore.common.dto.order.TpOrderCountQueryDTO;
import com.deepinnet.tpproductcore.common.dto.rule.TpRuleExecuteDTO;
import com.deepinnet.tptradeprod.common.dto.TpOrderStationDTO;
import com.deepinnet.tptradeprod.common.service.integration.client.TpProductClient;
import com.deepinnet.tptradecore.common.dto.order.TpUserTicketsQueryDTO;
import lombok.extern.slf4j.Slf4j;
import lombok.extern.java.Log;
import com.util.TestResult;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.JSONObject;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Assertions;
import cn.hutool.core.bean.BeanUtil;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
@Log
public class TpPlaceOrderProductCheckNodeTest {
@InjectMocks
private TpPlaceOrderProductCheckNode tpPlaceOrderProductCheckNode=new TpPlaceOrderProductCheckNode(null,null, null, null);
@Mock
private TpProductClient tpProductClient;
@Mock
private TpProductSalesUnitClient tpProductSalesUnitClient;
@Mock
private TpOrderClient tpOrderClient;
@Mock
private TpBizRuleClient bizRuleClient;
@BeforeEach
public void setUp() throws Exception {
MockitoAnnotations.openMocks(this);
}
@ParameterizedTest
@ValueSource(strings = {"/com/deepinnet/tptradeprod/biz/service/flow/node/check/TpPlaceOrderProductCheckNode/process.json"})
public void processTest(String str) {
JSONObject arg= TestUtils.getTestArg(str);
Integer integerArg = arg.getInteger("Integer");
TpRuleExecuteResultVO tpRuleExecuteResultVO = JSONObject.parseObject(arg.getString("TpRuleExecuteResultVO<R>"),TpRuleExecuteResultVO.class);
TpRuleExecuteBatchResultVO tpRuleExecuteBatchResultVO = JSONObject.parseObject(arg.getString("TpRuleExecuteBatchResultVO<R>"),TpRuleExecuteBatchResultVO.class);
Long longArg = arg.getLong("Long");
NodeComponent bindCmp = JSONObject.parseObject(arg.getString("NodeComponent"),NodeComponent.class);
List tpSalesUnitVOList = JSONObject.parseArray(arg.getString("List<TpSalesUnitVO>"),TpSalesUnitVO.class);
TpProdDetailDTO tpProdDetailDTO = JSONObject.parseObject(arg.getString("TpProdDetailDTO"),TpProdDetailDTO.class);
when(tpProductClient.getProduct(any(TpProductQueryDTO.class))).thenReturn(tpProdDetailDTO);
when(tpProductSalesUnitClient.listTpSalesUnit(any(TpSalesUnitQueryDTO.class))).thenReturn(tpSalesUnitVOList);
when(tpOrderClient.getUserBuyTickets(any(TpUserTicketsQueryDTO.class))).thenReturn(integerArg);
when(tpOrderClient.orderCount(any(TpOrderCountQueryDTO.class))).thenReturn(longArg);
when(bizRuleClient.executeRule(any(TpRuleExecuteDTO.class))).thenReturn(tpRuleExecuteResultVO);
when(bizRuleClient.batchExecuteBizRule(any(List.class))).thenReturn(tpRuleExecuteBatchResultVO);
tpPlaceOrderProductCheckNode.process(bindCmp);
}
@ParameterizedTest
@ValueSource(strings = {"/com/deepinnet/tptradeprod/biz/service/flow/node/check/TpPlaceOrderProductCheckNode/checkRestrictTime.json"})
public void checkRestrictTimeTest(String str) {
JSONObject arg= TestUtils.getTestArg(str);
List charterBusStations = JSONObject.parseArray(arg.getString("List<TpOrderStationDTO>"),TpOrderStationDTO.class);
String pricingType = arg.getString("String");
Boolean restrictTime = arg.getBoolean("Boolean");
tpPlaceOrderProductCheckNode.checkRestrictTime(restrictTime,pricingType,charterBusStations);
}
}

View File

@@ -0,0 +1,76 @@
package com.deepinnet.tptradeprod.core.component;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONUtil;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tptradecore.common.enums.order.TpOrderChangeApplyStatusEnum;
import com.deepinnet.tptradecore.common.enums.order.TpOrderChangeTypeEnum;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.service.facade.TpOrderChangeAcceptanceFacade;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderChangeApplyListVO;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
/**
* <p>
* 同步行程测试
* </p>
*
* @author chenjiaju
* @since 2023/12/6
*/
@SpringBootTest
@TestPropertySource(properties = {"spring.profiles.active=local"})
public class TpOrderChangeApplyTest {
@Resource
private TpOrderChangeAcceptanceFacade tpOrderChangeAcceptanceFacade;
@Test
public void testCreateOrderChangeApply() {
TpProdOrderChangeApplyCreatedDTO createdDTO = TpProdOrderChangeApplyCreatedDTO.builder()
.orderNo("11111111")
.originalOrderNo("123456787")
.applyTime(DateUtil.current())
.applyType(TpOrderChangeTypeEnum.ORDER_CREATE.getType())
.applyStatus(TpOrderChangeApplyStatusEnum.WAITING_APPROVED.getType())
.tenantId("1000293").build();
TpResult<Boolean> createApplyFlag = tpOrderChangeAcceptanceFacade.createOrderChangeApply(createdDTO);
System.err.println(JSONUtil.toJsonStr(createApplyFlag));
Assert.notNull(createApplyFlag, "创建申请单失败");
}
@Test
public void testGetLatestOrderChangeApplyDetail() {
TpProdOrderChangeApplyListDTO createdDTO = TpProdOrderChangeApplyListDTO.builder()
.orderNo("20240220006000037023")
.tenantId("1000293").build();
TpResult<TpProdOrderChangeApplyListVO> latestOrderChangeApplyDetail = tpOrderChangeAcceptanceFacade.getLatestOrderChangeApplyDetail(createdDTO);
System.err.println(JSONUtil.toJsonStr(latestOrderChangeApplyDetail));
}
@Test
public void testListOrderChangeApplyHistory() {
TpProdOrderChangeApplyListDTO createdDTO = TpProdOrderChangeApplyListDTO.builder()
.originalOrderNo("20240227006000038170")
.tenantId("1000293").build();
TpResult<List<TpProdOrderChangeApplyListVO>> latestOrderChangeApplyDetail = tpOrderChangeAcceptanceFacade.listOrderChangeApplyHistory(createdDTO);
System.err.println(JSONUtil.toJsonStr(latestOrderChangeApplyDetail));
}
}

View File

@@ -0,0 +1,131 @@
package com.deepinnet.tptradeprod.core.component;
import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONUtil;
import com.deepinnet.tp.common.lang.page.CommonPage;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tptradecore.common.enums.audit.TpAuditBizObjectTypeEnum;
import com.deepinnet.tptradecore.common.enums.audit.TpAuditStatusEnum;
import com.deepinnet.tptradecore.common.enums.audit.TpAuditTypeEnum;
import com.deepinnet.tptradecore.common.enums.order.TpOrderReductionServiceChargeTypeEnum;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.enums.TpOrderAuditConfirmTypeEnum;
import com.deepinnet.tptradeprod.common.service.facade.TpOrderAuditAcceptanceFacade;
import com.deepinnet.tptradeprod.common.service.integration.client.TpAuditClient;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderAuditConfirmOrderVO;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderRscConfirmVO;
import com.deepinnet.tptradeprod.common.vo.audit.TpProdAuditLatestDetailDTO;
import com.deepinnet.tptradeprod.common.vo.audit.TpProdAuditListVO;
import com.deepinnet.tptradeprod.common.vo.audit.TpProdAuditVO;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import javax.annotation.Resource;
import java.util.Arrays;
import static com.deepinnet.tptradecore.common.enums.order.TpOrderChangeApplyStatusEnum.APPROVED_SUCCESS;
import static com.deepinnet.tptradecore.common.enums.order.TpOrderChangeApplyStatusEnum.APPROVED_TIMEOUT;
/**
* <p>
* 同步行程测试
* </p>
*
* @author chenjiaju
* @since 2023/12/6
*/
@SpringBootTest
@TestPropertySource(properties = {"spring.profiles.active=local"})
public class TpOrderConfirmTest {
@Resource
private TpOrderAuditAcceptanceFacade tpOrderAuditAcceptanceFacade;
@Resource
private TpAuditClient tpAuditClient;
@Test
public void testGetOrderAuditLatestDetail() {
TpProdAuditLatestDetailDTO queryDetailDTO = TpProdAuditLatestDetailDTO.builder().build();
queryDetailDTO.setTenantId("1000293");
queryDetailDTO.setBizObjectNo("20231226012000014323");
queryDetailDTO.setBizObjType(TpAuditBizObjectTypeEnum.ORDER_CHANGE_APPLY.getType());
queryDetailDTO.setAuditStatuses(Arrays.asList(TpAuditStatusEnum.WAITING_APPROVED.getType()));
TpProdAuditVO auditVO = tpAuditClient.getLatestAuditDetail(queryDetailDTO);
System.err.println(JSONUtil.toJsonStr(auditVO));
Assert.notNull(auditVO, "查询最近一条有效的审核单失败");
}
@Test
public void testGetOrderAuditConfirmOrderDetail() {
TpProdOrderConfirmViewDTO dto = TpProdOrderConfirmViewDTO.builder()
.tenantId("1000293")
.orderAuditConfirmType(TpOrderAuditConfirmTypeEnum.ORDER_CHANGE.getCode())
.orderNo("20231226012000014323")
.build();
TpResult<TpProdOrderAuditConfirmOrderVO> tpResult = tpOrderAuditAcceptanceFacade.getOrderAuditConfirmOrderDetail(dto);
System.err.println(JSONUtil.toJsonStr(tpResult));
}
@Test
public void testConfirmOrder() {
TpProdOrderAuditConfirmDTO dto =new TpProdOrderAuditConfirmDTO() ;
dto.setOrderNo("20240220006000037023");
dto.setOriginalOrderNo("20240220006000037023");
dto.setTenantId("1000293");
dto.setOrderAuditConfirmType(TpOrderAuditConfirmTypeEnum.ORDER_CHANGE.getCode());
dto.setAuditStatus(APPROVED_SUCCESS.getType());
dto.setReductionServiceChargeType(TpOrderReductionServiceChargeTypeEnum.SINGLE_REDUCTION.getBizType());
dto.setAuditResult("选择免手续费审核测试通过-华侨");
dto.setOperatorNo("sysadmin");
dto.setOperatorName("sysadmin");
TpResult<Boolean> tpResult = tpOrderAuditAcceptanceFacade.confirmOrder(dto);
System.err.println(JSONUtil.toJsonStr(tpResult));
}
@Test
public void testReduceServiceChargeConfirm() {
TpProdOrderServiceChargeReduceConfirmDTO dto =new TpProdOrderServiceChargeReduceConfirmDTO() ;
dto.setOrderNo("20240221006000038000");
dto.setOriginalOrderNo("20240220006000037023");
dto.setTenantId("1000293");
dto.setAuditNo("20240221014000037005");
dto.setAuditStatus(APPROVED_SUCCESS.getType());
dto.setAuditResult("审核测试huaqiao");
dto.setOperatorNo("1004603");
dto.setOperatorName("shenduTest");
TpResult<Boolean> tpResult = tpOrderAuditAcceptanceFacade.reduceServiceChargeConfirm(dto);
System.err.println(JSONUtil.toJsonStr(tpResult));
}
@Test
public void testPageAuditList() {
TpProdAuditOrderListPagedQueryDTO dto = TpProdAuditOrderListPagedQueryDTO.builder()
.tenantId("1000293")
.originalOrderNo("20240221006000038023")
.orderNo("20240220006000037023")
.auditTypes(Arrays.asList(TpAuditTypeEnum.CHARTER_BUS_ORDER_CANCEL_RSC_APPROVAL.getBizType(),TpAuditTypeEnum.CHARTER_BUS_ORDER_CHANGE_RSC_APPROVAL.getBizType()))
// .orgCodes(Arrays.asList("1111"))
.build();
dto.setPageSize(30);
TpResult<CommonPage<TpProdAuditListVO>> tpResult = tpOrderAuditAcceptanceFacade.pageAuditList(dto);
System.err.println(JSONUtil.toJsonStr(tpResult));
}
@Test
public void testGetOrderRefundInfoForRscConfirm() {
TpProdOrderRscConfirmQueryDTO dto = TpProdOrderRscConfirmQueryDTO.builder()
.tenantId("1000293")
.originalOrderNo("20240221006000038023")
.build();
TpResult<TpProdOrderRscConfirmVO> tpResult = tpOrderAuditAcceptanceFacade.getOrderRefundInfoForRscConfirm(dto);
System.err.println(JSONUtil.toJsonStr(tpResult));
}
}

View File

@@ -0,0 +1,39 @@
package com.deepinnet.tptradeprod.core.component;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderManualDispatchDTO;
import com.deepinnet.tptradeprod.common.service.facade.TpOrderDispatchAcceptanceFacade;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import javax.annotation.Resource;
/**
* <p>
* 同步行程测试
* </p>
*
* @author chenjiaju
* @since 2023/12/6
*/
@SpringBootTest
@TestPropertySource(properties = {"spring.profiles.active=local"})
public class TpOrderDispatchOrderTest {
@Resource
private TpOrderDispatchAcceptanceFacade tpOrderDispatchAcceptanceFacade;
@Test
public void testManualDispatchOrder() {
TpProdOrderManualDispatchDTO dto = TpProdOrderManualDispatchDTO.builder()
.tenantId("1000293")
.orderNo("20231213006000011514")
.targetOrgNo("1000301")
.build();
tpOrderDispatchAcceptanceFacade.dispatchOrder(dto);
}
}

View File

@@ -0,0 +1,65 @@
package com.deepinnet.tptradeprod.core.component;
import cn.hutool.core.collection.ListUtil;
import com.deepinnet.tptradecore.common.enums.order.TpOrderModulesEnum;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderQueryDTO;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.deepinnet.tptradeprod.core.compoment.TpOrderSyncTripComponent;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import javax.annotation.Resource;
/**
* <p>
* 同步行程测试
* </p>
*
* @author chenjiaju
* @since 2023/12/6
*/
@SpringBootTest
@TestPropertySource(properties = {"spring.profiles.active=local"})
public class TpOrderSyncTripComponentTest {
@Resource
private TpOrderSyncTripComponent tpOrderSyncTripComponent;
@Resource
private TpOrderClient tpOrderClient;
@Test
public void testExecuteSync() {
TpProdOrderDetailVO orderDetail = tpOrderClient.getOrderDetail(TpProdOrderQueryDTO.builder()
.originalOrderNo("20231208006000011223")
.tenantId("test")
.needModules(ListUtil.toList(TpOrderModulesEnum.ORDER_TRAVEL_TRIP.getModule(), TpOrderModulesEnum.ORDER_SUBJECT_ITEM.getModule())).build());
tpOrderSyncTripComponent.createSync(orderDetail, "test");
}
@Test
public void updateExecuteSync() {
TpProdOrderDetailVO nowOrder = tpOrderClient.getOrderDetail(TpProdOrderQueryDTO.builder()
.orderNo("20231208006000011224")
.tenantId("test")
.needModules(ListUtil.toList(TpOrderModulesEnum.ORDER_TRAVEL_TRIP.getModule(), TpOrderModulesEnum.ORDER_SUBJECT_ITEM.getModule())).build());
TpProdOrderDetailVO oldOrder = tpOrderClient.getOrderDetail(TpProdOrderQueryDTO.builder()
.orderNo("20231208006000011223")
.tenantId("test")
.needModules(ListUtil.toList(TpOrderModulesEnum.ORDER_TRAVEL_TRIP.getModule(), TpOrderModulesEnum.ORDER_SUBJECT_ITEM.getModule())).build());
tpOrderSyncTripComponent.updateSync(nowOrder, oldOrder, "test");
}
@Test
public void cancelExecuteSync() {
TpProdOrderDetailVO orderDetail = tpOrderClient.getOrderDetail(TpProdOrderQueryDTO.builder()
.originalOrderNo("20231204006000011048")
.tenantId("test")
.needModules(ListUtil.toList(TpOrderModulesEnum.ORDER_TRAVEL_TRIP.getModule(), TpOrderModulesEnum.ORDER_SUBJECT_ITEM.getModule())).build());
tpOrderSyncTripComponent.cancelSync(orderDetail, "test");
}
}

View File

@@ -0,0 +1,41 @@
package com.deepinnet.tptradeprod.core.component;
import cn.hutool.core.lang.Assert;
import com.deepinnet.tp.common.lang.page.CommonPage;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.service.facade.TpVoucherAcceptanceFacade;
import com.deepinnet.tptradeprod.common.vo.TpProdMngVerificationRecordVO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import java.util.List;
/**
* <p>
* 同步行程测试
* </p>
*
* @author chenjiaju
* @since 2023/12/6
*/
@SpringBootTest
@TestPropertySource(properties = {"spring.profiles.active=local"})
public class TpVoucherVerficationRecodeTest {
@DubboReference
private TpVoucherAcceptanceFacade tpVoucherAcceptanceFacade;
@Test
public void queryMngVerificationRecords(){
TpProdMngVerificationRecordQueryDTO queryDTO = new TpProdMngVerificationRecordQueryDTO();
queryDTO.setTenantId("1000293");
queryDTO.setProductCategoryNo("04-33010003");
TpResult<CommonPage<TpProdMngVerificationRecordVO>> result = tpVoucherAcceptanceFacade.queryMngVerificationRecords(queryDTO);
System.out.println(result.getData().toString());
Assert.isTrue(result.isSuccess());
}
}

View File

@@ -0,0 +1,35 @@
package com.deepinnet.tptradeprod.facade;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tp.common.lang.util.JsonUtil;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderChangeApplyListDTO;
import com.deepinnet.tptradeprod.common.service.facade.TpOrderChangeAcceptanceFacade;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderChangeApplyListVO;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import javax.annotation.Resource;
/**
* Description:
* Date: 2024/6/14
* Author: lijunheng
*/
@SpringBootTest
@TestPropertySource(properties = {"spring.profiles.active=local"})
public class TpOrderChangeAcceptanceFacadeTest {
@Resource
private TpOrderChangeAcceptanceFacade orderChangeAcceptanceFacade;
@Test
public void testGetOrderEndTripChangeChargeRecord() {
TpProdOrderChangeApplyListDTO dto = new TpProdOrderChangeApplyListDTO();
dto.setOrderNo("20240607006000049093");
dto.setOriginalOrderNo("20240607006000049091");
dto.setTenantId("1000293");
TpResult<TpProdOrderChangeApplyListVO> orderEndTripChangeChargeRecord = orderChangeAcceptanceFacade.getOrderEndTripChangeChargeRecord(dto);
System.out.println(JsonUtil.toJsonStr(orderEndTripChangeChargeRecord));
}
}

View File

@@ -0,0 +1,39 @@
package com.util;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 单测结果
*/
public class TestResult {
/**
* 单测执行是否成功
*/
private boolean success = true;
/**
* 校验失败的字段和值列表第一个元素为单测结果第二个元素为期望结果定义在json文件的ExpectedResult字段中
*/
private Map<String, List<Object>> uncommonFields = new HashMap<>();
public Map<String, List<Object>> getUncommonFields() {
return uncommonFields;
}
public boolean isSuccess() {
return success;
}
public TestResult() {
}
public void setSuccess(boolean success) {
this.success = success;
}
public void setUncommonFields(Map<String, List<Object>> uncommonFields) {
this.uncommonFields = uncommonFields;
}
}

View File

@@ -0,0 +1,17 @@
package com.util;
import cn.hutool.core.util.StrUtil;
import java.util.ArrayList;
import java.util.List;
public class TestStrUtils {
public static void main(String[] args) {
String msgTemplate = "该订单属于专属承运公司订单,仅能派给以下公司:{}";
List<String> specialTargetOrgNoList = new ArrayList<>();
specialTargetOrgNoList.add("123");
specialTargetOrgNoList.add("986");
System.err.println(StrUtil.format(msgTemplate,StrUtil.join(",",specialTargetOrgNoList)));
}
}

View File

@@ -0,0 +1,113 @@
package com.util;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONReader;
import lombok.SneakyThrows;
import java.math.BigDecimal;
public class TestUtils {
/**
* 读取json文件
* @param path
* @return
*/
public static JSONObject getTestArg(String path) {
String s = new JSONReader(
new BufferedReader(new InputStreamReader(TestUtils.class.getResourceAsStream(path))))
.readString();
return JSONObject.parseObject(s);
}
/**
* 判断source与target的所有公共字段的值是否相同
*
* @param source 待检测对象1
* @param target 待检测对象2
* @param ignoreProperties 不需要检测的字段
* @return 判断结果如果为true则证明所有字段的值都相同
*/
public static TestResult isCommonFieldsEqual(Object source, Object target, String...ignoreProperties) {
TestResult result = new TestResult();
if (null == source && null == target) {
result.setSuccess(true);
return result;
}
if (null == source || null == target) {
result.setSuccess(false);
return result;
}
if (source instanceof List && target instanceof List) {
// 快速失败
if (((List<?>) source).size() != ((List<?>) target).size()) {
result.setSuccess(false);
return result;
}
// 遍历比对
for(int i = 0;i<((List<?>) source).size();i++) {
Object o1 = ((List<?>) source).get(i);
Object o2 = ((List<?>) target).get(i);
build(o1, o2, result, ignoreProperties);
}
} else {
build(source, target, result, ignoreProperties);
}
return result;
}
private static void build(Object source, Object target, TestResult result, String[] ignoreProperties) {
Map<String, Object> sourceFieldsMap = BeanUtil.beanToMap(source);
Map<String, Object> targetFieldsMap = BeanUtil.beanToMap(target);
Set<String> sourceFields = sourceFieldsMap.keySet();
sourceFields.removeAll(Arrays.asList(ignoreProperties));
for (String field : sourceFields) {
if(ObjectUtil.notEqual(sourceFieldsMap.get(field), targetFieldsMap.get(field))){
result.setSuccess(false);
List<Object> fields = new ArrayList<>(2);
fields.add(sourceFieldsMap.get(field));
fields.add(targetFieldsMap.get(field));
result.getUncommonFields().put(field, fields);
}
}
}
public static JSONObject flatten(JSONObject json) {
JSONObject result = new JSONObject();
flatten("", json, result);
return result;
}
@SneakyThrows
private static void flatten(String prefix, JSONObject json, JSONObject result) {
Iterator<String> keys = json.keySet().iterator();
while (keys.hasNext()) {
String key = keys.next();
Object value = json.get(key);
if (value instanceof JSONObject) {
flatten(prefix + key + ".", (JSONObject) value, result);
} else if (value instanceof Integer) {
result.put(prefix + key, ((Integer) value).longValue()); // 将整数转换为Long类型
} else if (value instanceof Short) {
result.put(prefix + key, ((Short) value).longValue()); // 将整数转换为Long类型
} else if (value instanceof Float) {
result.put(prefix + key, BigDecimal.valueOf((Float) value)); // 将整数转换为Long类型
} else if (value instanceof Double) {
result.put(prefix + key, BigDecimal.valueOf((Double) value)); // 将整数转换为Long类型
} else if (value instanceof BigDecimal) {
result.put(prefix + key, value); // 将整数转换为Long类型
} else {
result.put(prefix + key, value);
}
}
}}

View File

@@ -0,0 +1,68 @@
{
"List<TpOrderStationDTO>":[
{
"tripNo":"test",
"pickUpLocationCode":"test",
"pickUpLocation":"test",
"stationCount":1,
"pickUpLng":"test",
"pickUpLat":"test",
"pickUpTime":"1702958314098",
"dropOffLocationCode":"test",
"dropOffLocation":"test",
"dropOffLng":"test",
"dropOffLat":"test",
"dropOffTime":"1703001514000",
"miles":"test",
"duration":86300000,
"tripType":"test",
"pathPoints":[
{
"locationName":"test",
"lng":"test",
"lat":"test",
"index":1,
"bizData":{
"test":{}
}
}
],
"bizData":{
"test":{}
}
},
{
"tripNo":"test",
"pickUpLocationCode":"test",
"pickUpLocation":"test",
"stationCount":1,
"pickUpLng":"test",
"pickUpLat":"test",
"pickUpTime":"1702958314098",
"dropOffLocationCode":"test",
"dropOffLocation":"test",
"dropOffLng":"test",
"dropOffLat":"test",
"dropOffTime":"1703001514000",
"miles":"test",
"duration":11,
"tripType":"test",
"pathPoints":[
{
"locationName":"test",
"lng":"test",
"lat":"test",
"index":1,
"bizData":{
"test":{}
}
}
],
"bizData":{
"test":{}
}
}
],
"String":"within_city_single_trip_chartered_bus",
"Boolean":false
}

View File

@@ -0,0 +1,649 @@
{
"Integer":1,
"List<TpSalesUnitVO>":[
{
"id":1,
"code":"test",
"productCode":"test",
"status":"test",
"availableQuantity":1,
"tenantId":"test",
"salesUnitElementList":[
{
"id":1,
"code":"test",
"salesUnitCode":"test",
"value":"test",
"description":"test",
"unitCode":"test",
"unitName":"test",
"tenantId":"test"
}
],
"busSpecification":{
"id":1,
"code":"test",
"name":"test",
"length":1.0,
"carrierOrg":[
[
{
"orgCode":"test",
"name":"test"
}
]
],
"approvedPassengerCapacity":1,
"seatsNum":1,
"desc":"test",
"pictureUrl":"test",
"maxMileage":1.0,
"remarks":"test",
"gmtCreated":1702958047521,
"gmtModified":1702958047521,
"tenantId":"test",
"isDeleted":1,
"bizData":"test"
},
"basePrice":{
"miles":1,
"duration":1,
"price":1
}
}
],
"TpRuleExecuteResultVO<R>":{
"success":true,
"msg":"test",
"result":{}
},
"TpRuleExecuteBatchResultVO<R>":{
"success":true,
"msg":"test",
"resultList":[
{
"success":true,
"msg":"test",
"result":{}
}
]
},
"Long":1,
"NodeComponent":{
"LOG":{
"log":{},
"liteflowConfig":{
"enable":true,
"ruleSource":"test",
"ruleSourceExtData":"test",
"ruleSourceExtDataMap":{
"test":"test"
},
"slotSize":1,
"threadExecutorClass":"test",
"whenMaxWaitSeconds":1,
"whenMaxWaitTime":1,
"whenMaxWaitTimeUnit":"NANOSECONDS",
"whenThreadPoolIsolate":true,
"enableLog":true,
"queueLimit":1,
"delay":1,
"period":1,
"whenMaxWorkers":1,
"whenQueueLimit":1,
"parseOnStart":true,
"supportMultipleType":true,
"retryCount":1,
"nodeExecutorClass":"test",
"requestIdGeneratorClass":"test",
"printBanner":true,
"mainExecutorWorks":1,
"mainExecutorClass":"test",
"printExecutionLog":true,
"enableMonitorFile":true,
"parallelLoopExecutorClass":"test",
"parallelMaxWorkers":1,
"parallelQueueLimit":1,
"fallbackCmpEnable":true
}
},
"monitorBus":{
"liteflowConfig":{
"enable":true,
"ruleSource":"test",
"ruleSourceExtData":"test",
"ruleSourceExtDataMap":{
"test":"test"
},
"slotSize":1,
"threadExecutorClass":"test",
"whenMaxWaitSeconds":1,
"whenMaxWaitTime":1,
"whenMaxWaitTimeUnit":"NANOSECONDS",
"whenThreadPoolIsolate":true,
"enableLog":true,
"queueLimit":1,
"delay":1,
"period":1,
"whenMaxWorkers":1,
"whenQueueLimit":1,
"parseOnStart":true,
"supportMultipleType":true,
"retryCount":1,
"nodeExecutorClass":"test",
"requestIdGeneratorClass":"test",
"printBanner":true,
"mainExecutorWorks":1,
"mainExecutorClass":"test",
"printExecutionLog":true,
"enableMonitorFile":true,
"parallelLoopExecutorClass":"test",
"parallelMaxWorkers":1,
"parallelQueueLimit":1,
"fallbackCmpEnable":true
},
"LOG":{
"log":{},
"liteflowConfig":{
"enable":true,
"ruleSource":"test",
"ruleSourceExtData":"test",
"ruleSourceExtDataMap":{
"test":"test"
},
"slotSize":1,
"threadExecutorClass":"test",
"whenMaxWaitSeconds":1,
"whenMaxWaitTime":1,
"whenMaxWaitTimeUnit":"NANOSECONDS",
"whenThreadPoolIsolate":true,
"enableLog":true,
"queueLimit":1,
"delay":1,
"period":1,
"whenMaxWorkers":1,
"whenQueueLimit":1,
"parseOnStart":true,
"supportMultipleType":true,
"retryCount":1,
"nodeExecutorClass":"test",
"requestIdGeneratorClass":"test",
"printBanner":true,
"mainExecutorWorks":1,
"mainExecutorClass":"test",
"printExecutionLog":true,
"enableMonitorFile":true,
"parallelLoopExecutorClass":"test",
"parallelMaxWorkers":1,
"parallelQueueLimit":1,
"fallbackCmpEnable":true
}
},
"statisticsMap":{
"table":[
{
"hash":1,
"key":{},
"val":{},
"next":{
}
}
],
"nextTable":[
{
"hash":1,
"key":{},
"val":{},
"next":{
}
}
],
"baseCount":1,
"sizeCtl":1,
"transferIndex":1,
"cellsBusy":1,
"counterCells":[
{
"value":1
}
],
"keySet":[
{}
],
"values":[
{}
],
"entrySet":[
{}
]
},
"printLogScheduler":{}
},
"nodeId":"test",
"name":"test",
"type":"COMMON",
"self":{
},
"retryCount":1,
"isRollback":true,
"retryForExceptions":[
null
],
"refNodeTL":{
"disableIgnoreNullValueSemantics":true,
"threadLocalHashCode":1
},
"slotIndexTL":{
"disableIgnoreNullValueSemantics":true,
"threadLocalHashCode":1
},
"isEndTL":{
"disableIgnoreNullValueSemantics":true,
"threadLocalHashCode":1
}
},
"TpProdDetailDTO":{
"bizType":"CHARTER_BUS",
"extendAttributes":{
"supportRefund":true,
"orderExpiredTime":1,
"orderPayType":"FULL_PAY",
"prepayRate":1,
"needConfirmOrder":true,
"supportModifyPrice":true,
"maxUpRate":1,
"supportCoupon":true,
"supportModifyOrderPayType":true,
"needRefundServiceFee":true,
"supportChangeTrip":true,
"supportChangeTripTimes":1,
"restrictTimeSingleDaySingleAndRoundTrip":true,
"orderIsForceReminderText":true,
"orderForceReminderText":"test",
"tripChangeNeedConfirmBySalesman":true,
"orderCanCancelAfterPayment":true,
"orderCancellationNeedSalesmanConfirm":true,
"salesmanApplyFullRefundAfterOrderCanceled":true
},
"productExtraAttributes":{
"routeCode":"test",
"ticketType":[
"test"
],
"ticketQuantity":1,
"ticketPriceType":[
"test"
],
"checkTicketType":[
"test"
],
"minTicketPrice":"test",
"departureType":"test",
"pricingType":"test",
"ecoData":"test"
},
"routeDetailDTO":{
"routeBase":{
"routeCode":"test",
"orgCode":"test",
"orgAllPaths":[
{
"orgCode":"test",
"name":"test"
}
],
"frontCategoryCode":[
"test"
],
"routeName":"test",
"goBackType":"test",
"departureType":"test",
"status":"test",
"carMachineRouteNumber":"test",
"carPosRouteNumber":"test",
"specialText":"test",
"draft":true,
"syncStatus":"test",
"syncRouteStatus":"test",
"syncAction":"test",
"gmtCreated":1702958047512,
"gmtModified":1702958047512,
"tenantId":"test",
"isDeleted":1,
"bizData":"test"
},
"goRouteStationDetails":[
{
"routeCode":"test",
"goBackType":"test",
"station":{
"stationCode":"test",
"name":"test",
"road":"test",
"orientation":"test",
"district":"test",
"wgsLongitude":"test",
"wgsLatitude":"test",
"gcjLongitude":"test",
"gcjLatitude":"test",
"desc":"test",
"resourceFrom":"test",
"gmtCreated":1702958047514,
"gmtModified":1702958047514,
"tenantId":"test",
"isDeleted":1,
"bizData":"test"
},
"resourceFrom":"test",
"order":1,
"trace":"test",
"stationMark":"test",
"distance":1.0,
"costTime":1,
"gmtCreated":1702958047514,
"gmtModified":1702958047514,
"tenantId":"test",
"isDeleted":1,
"bizData":"test"
}
],
"backRouteStationDetails":[
{
"routeCode":"test",
"goBackType":"test",
"station":{
"stationCode":"test",
"name":"test",
"road":"test",
"orientation":"test",
"district":"test",
"wgsLongitude":"test",
"wgsLatitude":"test",
"gcjLongitude":"test",
"gcjLatitude":"test",
"desc":"test",
"resourceFrom":"test",
"gmtCreated":1702958047514,
"gmtModified":1702958047514,
"tenantId":"test",
"isDeleted":1,
"bizData":"test"
},
"resourceFrom":"test",
"order":1,
"trace":"test",
"stationMark":"test",
"distance":1.0,
"costTime":1,
"gmtCreated":1702958047514,
"gmtModified":1702958047514,
"tenantId":"test",
"isDeleted":1,
"bizData":"test"
}
],
"goRollTimes":[
{
"routeCode":"test",
"firstTime":"test",
"lastTime":"test",
"intervalTime":1,
"goBackType":"test",
"order":1
}
],
"backRollTimes":[
{
"routeCode":"test",
"firstTime":"test",
"lastTime":"test",
"intervalTime":1,
"goBackType":"test",
"order":1
}
],
"serviceTime":{
"routeCode":"test",
"dateType":"test",
"specificDateList":"test"
},
"routeServiceObjs":[
{
"routeCode":"test",
"serviceObjType":"test",
"serviceObjCode":"test",
"gmtCreated":1702958047515,
"gmtModified":1702958047515,
"tenantId":"test",
"isDeleted":1,
"bizData":"test"
}
],
"tenantId":"test"
},
"backCategories":[
{
"parentCode":"test",
"parentName":"test",
"code":"test",
"name":"test",
"type":"test",
"level":1,
"sort":1,
"status":"test",
"rootCode":"test",
"imageUrl":"test",
"leaf":1,
"childrenCategories":[
null
]
}
],
"frontCategories":[
{
"parentCode":"test",
"parentName":"test",
"code":"test",
"name":"test",
"type":"test",
"level":1,
"sort":1,
"status":"test",
"rootCode":"test",
"imageUrl":"test",
"leaf":1,
"childrenCategories":[
null
]
}
],
"priceUnits":[
{
"id":1,
"name":"test",
"type":"test",
"priceUnitFixed":{
"id":1,
"price":1,
"unitCode":"test",
"unitName":"test",
"tenantId":"test",
"bizData":"test"
},
"priceUnitRuleList":[
{
"id":1,
"name":"test",
"ruleCode":"test",
"priceUnitRuleFactorValues":[
{
"id":1,
"factorCode":"test",
"priceUnitRuleCode":"test",
"unitCode":"test",
"unitName":"test",
"factorValue":"test",
"factorValueType":"test",
"tenantId":"test",
"bizData":"test"
}
],
"expression":"test",
"sort":1,
"ruleGroupCode":"test",
"tenantId":"test",
"bizData":"test"
}
],
"code":"test",
"salesUnitCode":"test",
"tenantId":"test"
}
],
"salesUnits":[
{
"code":"test",
"productCode":"test",
"status":"test",
"expression":"test",
"tenantId":"test",
"salesUnitElementList":[
{
"id":1,
"code":"test",
"salesUnitCode":"test",
"value":"test",
"description":"test",
"unit":{
"code":"test",
"name":"test",
"tenantId":"test"
},
"tenantId":"test",
"bizData":"test"
}
],
"priceUnits":[
{
"id":1,
"name":"test",
"type":"test",
"priceUnitFixed":{
"id":1,
"price":1,
"unitCode":"test",
"unitName":"test",
"tenantId":"test",
"bizData":"test"
},
"priceUnitRuleList":[
{
"id":1,
"name":"test",
"ruleCode":"test",
"priceUnitRuleFactorValues":[
{
"id":1,
"factorCode":"test",
"priceUnitRuleCode":"test",
"unitCode":"test",
"unitName":"test",
"factorValue":"test",
"factorValueType":"test",
"tenantId":"test",
"bizData":"test"
}
],
"expression":"test",
"sort":1,
"ruleGroupCode":"test",
"tenantId":"test",
"bizData":"test"
}
],
"code":"test",
"salesUnitCode":"test",
"tenantId":"test"
}
]
}
],
"rules":[
{
"id":1,
"code":"test",
"name":"test",
"bizType":"test",
"expression":"test",
"targetObjType":"test",
"targetObjId":"test",
"ruleGroup":"test",
"tenantId":"test",
"ruleEnum":"NO_LIMIT",
"factorValues":[
{
"id":1,
"factorCode":"test",
"ruleId":1,
"ruleCode":"test",
"unit":{
"code":"test",
"name":"test",
"tenantId":"test"
},
"factorValue":"test",
"factorValueType":"test",
"tenantId":"test",
"bizData":"test"
}
],
"effectTimeStart":1,
"effectTimeEnd":1
}
],
"serviceObjects":[
{
"serviceObjectCode":"test",
"serviceObjectName":"test",
"serviceObjectType":"test",
"payType":"test",
"resourceItems":[
{
"code":"test",
"name":"test",
"type":"test",
"value":"test",
"tenantId":"test"
}
],
"logoImageUrl":"test",
"contactName":"test",
"contactPhone":"test",
"address":{
"provinceCode":"test",
"provinceName":"test",
"cityCode":"test",
"cityName":"test",
"districtCode":"test",
"districtName":"test",
"streetCode":"test",
"streetName":"test",
"address":"test",
"fullAddress":"test",
"tenantId":"test"
},
"tenantId":"test"
}
],
"productCode":"test",
"routeCode":"test",
"productName":"test",
"formalFlag":"test",
"status":"test",
"backCategoryCode":"test",
"bizData":{
"test":{}
},
"tenantId":"test"
}
}

19
tptradeprod-biz/pom.xml Normal file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>tptradeprod-biz</artifactId>
<packaging>pom</packaging>
<modules>
<module>tptradeprod-biz-service-impl</module>
</modules>
</project>

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-biz</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>tptradeprod-biz-service-impl</artifactId>
<dependencies>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-common-service-integration</artifactId>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-common-util</artifactId>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradeprod-core-service</artifactId>
</dependency>
<dependency>
<groupId>com.deepinnet</groupId>
<artifactId>tptradecore-common-service-facade</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.jsonzou</groupId>
<artifactId>jmockdata</artifactId>
<version>4.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.25</version>
</dependency>
<dependency>
<groupId>com.github.dadiyang</groupId>
<artifactId>equator</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,44 @@
package com.deepinnet.tptradeprod.biz.advice;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.log.LogFormatHelper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class IntegrationClientInterceptor {
private static final Logger INTEGRATION_LOG = LoggerFactory.getLogger("INTEGRATION-LOG");
@Pointcut("execution(* com.deepinnet.*.common.service.integration..*.*(..))")
public void pointCut() {
}
@Around("pointCut()")
public Object integrationClientHandle(ProceedingJoinPoint pj) throws Throwable {
boolean res = true;
Long startTime = System.currentTimeMillis();
String className = pj.getTarget().getClass().getSimpleName();
String methodName = pj.getSignature().getName();
Object proceed;
Throwable ex = null;
try {
proceed = pj.proceed();
return proceed;
} catch (Throwable e) {
res = false;
ex = e;
throw e;
} finally {
LogUtil.info(INTEGRATION_LOG, "{}",
LogFormatHelper.logFormat(startTime, className, methodName, res, ex));
}
}
}

View File

@@ -0,0 +1,44 @@
package com.deepinnet.tptradeprod.biz.advice;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.log.LogFormatHelper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* @author chenjiaju
* @version 2023/1/6
*/
@Aspect
@Component
public class MessageLogInterceptor {
private static final Logger MESSAGE_LOG = LoggerFactory.getLogger("MESSAGE-LOG");
@Pointcut("execution(* com.deepinnet.tptradeprod.core.handler.TpMessageHandler.handle(..))")
public void pointCut() {
}
@Around("pointCut()")
public Object messageLogHandle(ProceedingJoinPoint pj) throws Throwable {
Long startTime = System.currentTimeMillis();
boolean isSuccess = true;
try {
return pj.proceed();
} catch (Exception e) {
isSuccess = false;
throw e;
} finally {
Long endTime = System.currentTimeMillis();
String log = LogFormatHelper.generateMessageConsumeLog(pj, isSuccess, endTime - startTime);
LogUtil.info(MESSAGE_LOG, "{}", log);
}
}
}

View File

@@ -0,0 +1,77 @@
package com.deepinnet.tptradeprod.biz.advice;
import com.deepinnet.tp.common.lang.exception.TpException;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.log.LogFormatHelper;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.*;
import org.springframework.stereotype.Component;
/**
* @author amos wong
* @create 2022-11-14 15:00
* <p>
* 异常处理切面
*/
@Component
@Aspect
public class RpcExceptionHandleAspect {
private static final String TPTRADEPROD_CORE_SIMPLE_NAME = "TpTradeProdException";
private static final Logger REQUEST_LOG = LoggerFactory.getLogger("REQUEST-LOG");
private static final Logger BIZ_DIGEST_LOG = LoggerFactory.getLogger("BIZ-DIGEST-LOG");
@Pointcut(value = "@within(org.apache.dubbo.config.annotation.DubboService)")
private void myPointcut() {
}
@Around(value = "myPointcut()")
private Object around(ProceedingJoinPoint joinPoint) {
Long startTime = System.currentTimeMillis();
String className = joinPoint.getTarget().getClass().getSimpleName();
String methodName = joinPoint.getSignature().getName();
boolean isSuccess = true;
Throwable ex = null;
try {
LogUtil.info(REQUEST_LOG, "{},{},{}", className, methodName, joinPoint.getArgs());
Object proceedResult = joinPoint.proceed();
if (proceedResult instanceof TpResult) {
TpResult result = (TpResult) proceedResult;
if (!result.isSuccess()) {
isSuccess = false;
}
}
return proceedResult;
} catch (Throwable e) {
ex = e;
LogUtil.error("RPC服务调用异常", e);
// 业务异常
if (e instanceof TpTradeProdException) {
TpTradeProdException exception = (TpTradeProdException) e;
// ATTENTION如果是幂等异常需要返回成功但是要带上异常信息
TpTradeProdErrorCode errorCode = exception.getErrorCode();
if (TpTradeProdErrorCode.IDEMPOTENT_REQUEST_ERROR == errorCode) {
return new TpResult<>(true, TpTradeProdErrorCode.IDEMPOTENT_REQUEST_ERROR.getCode(), TpTradeProdErrorCode.IDEMPOTENT_REQUEST_ERROR.getDesc(), TPTRADEPROD_CORE_SIMPLE_NAME);
}
return TpResult.fail(errorCode.getCode(), exception.getMessage(), TPTRADEPROD_CORE_SIMPLE_NAME);
} else if (e instanceof IllegalArgumentException) {
return TpResult.fail(TpTradeProdErrorCode.ILLEGAL_PARAMS.getCode(), TpTradeProdErrorCode.ILLEGAL_PARAMS.getDesc(), TPTRADEPROD_CORE_SIMPLE_NAME);
} else if (e instanceof TpException) {
return TpResult.fail(((TpException) e).getErrorCode(), e.getMessage(), TPTRADEPROD_CORE_SIMPLE_NAME);
} else {
// 未知异常
return TpResult.fail(TpTradeProdErrorCode.INTERNAL_SERVER_ERROR.getCode(), TpTradeProdErrorCode.INTERNAL_SERVER_ERROR.getDesc(), TPTRADEPROD_CORE_SIMPLE_NAME);
}
} finally {
LogUtil.info(BIZ_DIGEST_LOG, "{}", LogFormatHelper.logFormat(startTime, className, methodName, isSuccess, ex));
}
}
}

View File

@@ -0,0 +1,31 @@
package com.deepinnet.tptradeprod.biz.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* <p>
* 线程池配置
* </p>
*
* @author chenjiaju
* @since 2024/2/2
*/
@Configuration
public class ThreadPoolConfig {
@Bean
public ThreadPoolTaskExecutor queryPositionFlagThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(Runtime.getRuntime().availableProcessors() * 2);
executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 3 + 1);
executor.setKeepAliveSeconds(10);
executor.setQueueCapacity(128);
executor.setThreadNamePrefix("query-position-flag-task-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
return executor;
}
}

View File

@@ -0,0 +1,98 @@
package com.deepinnet.tptradeprod.biz.constants;
/**
* <p>
* 计算公式枚举
* </p>
*
* @author chenjiaju
* @since 2024/2/2
*/
public class TpOrderCalcFormula {
/**
* 行程结束 应退金额(手续费)
*/
public final static String ORDER_END_NEED_REFUND_AMOUNT_WITH_SERVICE_CHARGE = "应退金额=已付金额-订单金额-手续费";
/**
* 行程结束 应退金额(无手续费)
*/
public final static String ORDER_END_NEED_REFUND_AMOUNT_WITHOUT_SERVICE_CHARGE = "应退金额=已付金额-订单金额";
/**
* 取消 退款中 有手续费
*/
public final static String ORDER_CANCEL_REFUNDING_WITH_SERVICE_CHARGE = "应退金额=已付金额-手续费";
/**
* 取消 退款中 无手续费
*/
public final static String ORDER_CANCEL_REFUNDING_WITHOUT_SERVICE_CHARGE = "应退金额=已付金额";
/**
* 行程结束 已退款 实付金额(手续费)
*/
public final static String ORDER_END_REFUNDED_AMOUNT_WITH_SERVICE_CHARGE = "应退金额=已付金额-订单金额-手续费";
/**
* 行程结束 已退款 实付金额(无手续费)
*/
public final static String ORDER_END_REFUNDED_AMOUNT_WITHOUT_SERVICE_CHARGE = "已退金额=已付金额-订单金额";
/**
* 取消 应退(手续费)
*/
public final static String ORDER_CANCEL_NEED_REFUND_AMOUNT_WITH_SERVICE_CHARGE = "应退金额=已付金额-手续费";
/**
* 取消 应退(无手续费)
*/
public final static String ORDER_CANCEL_NEED_REFUND_AMOUNT_WITHOUT_SERVICE_CHARGE = "应退金额=已付金额";
/**
* 取消 已退金额(手续费)
*/
public final static String ORDER_CANCEL_REFUNDED_AMOUNT_WITH_SERVICE_CHARGE = "已退金额=已付金额-手续费";
/**
* 取消 已退金额(无手续费)
*/
public final static String ORDER_CANCEL_REFUNDED_AMOUNT_WITHOUT_SERVICE_CHARGE = "已退金额=已付金额";
/**
* 取消 应付
*/
public final static String ORDER_CANCEL_NEED_PAY_AMOUNT_WITH_SERVICE_CHARGE = "应付金额=手续费-已付金额";
/**
* 取消 实付金额
*/
public final static String ORDER_CANCEL_PAID_AMOUNT_WITH_SERVICE_CHARGE = "实付金额=手续费-已支付订金金额";
/**
* 应付尾款(手续费)
*/
public final static String ORDER_NEED_PAY_BALANCE_AMOUNT_WITH_SERVICE_CHARGE = "应付尾款=订单金额-已付金额+手续费";
/**
* 应付尾款(无手续费)
*/
public final static String ORDER_NEED_PAY_BALANCE_AMOUNT_WITHOUT_SERVICE_CHARGE = "应付尾款=订单金额-已付金额";
/**
* 实付金额(手续费)
*/
public final static String ORDER_ACTUAL_PAID_AMOUNT_WITH_SERVICE_CHARGE = "实付金额=订单金额+手续费";
/**
* 实付金额(无手续费)
*/
public final static String ORDER_ACTUAL_PAID_AMOUNT_WITHOUT_SERVICE_CHARGE = "实付金额=订单金额";
/**
* 订单结束 不退不补 实付金额
*/
public final static String ORDER_ACTUAL_PAID_AMOUNT_WITHOUT_BALANCE_WITHOUT_SERVICE_CHARGE = "实付金额=已支付订金金额";
}

View File

@@ -0,0 +1,23 @@
package com.deepinnet.tptradeprod.biz.constants;
import lombok.Data;
/**
* <p>
* 列表查询常量类
* </p>
*
* @author chenjiaju
* @since 2024/3/13
*/
@Data
public class TpOrderListQueryConstants {
public final static Integer NEED_PAY_STATUS = 1;
public final static Integer NEED_VERIFY_STATUS = 2;
public final static Integer REFUND_STATUS = 3;
}

View File

@@ -0,0 +1,16 @@
package com.deepinnet.tptradeprod.biz.constants;
/**
* @author amos wong
* @create 2023/10/17 10:39
* @Description
*/
public class TpTradeProdConstants {
public static final Integer DEFAULT_TIME_OUT_INTERVAL = 15 * 60 * 1000;
public static final String ORDER_AUDIT_CONFIRM = "order_audit_confirm";
public static final String MIDDLE_HORIZONTAL = "-";
}

View File

@@ -0,0 +1,21 @@
package com.deepinnet.tptradeprod.biz.converter;
import com.deepinnet.tpproductcore.common.vo.TpSalesUnitCarPoolVO;
import com.deepinnet.tptradeprod.common.vo.TpProdSalesUnitCarpoolVO;
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;
/**
* <p>
* 售卖单元开线信息转换器
* </p>
*
* @author chenjiaju
* @since 2024/5/24
*/
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
public interface TpSaleUnitCarpoolConvert {
TpProdSalesUnitCarpoolVO productSaleUnit2productSaleUnitCarpool(TpSalesUnitCarPoolVO carPoolVO);
}

View File

@@ -0,0 +1,165 @@
package com.deepinnet.tptradeprod.biz.log;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.deepinnet.tp.common.lang.exception.TpException;
import com.deepinnet.tptradecore.common.exception.TpTradeCoreException;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import org.aspectj.lang.ProceedingJoinPoint;
import java.text.MessageFormat;
public class LogFormatHelper {
/**
* 日志格式
* [类名,方法名,执行结果,耗时,异常类名,异常码,异常信息]
*/
private static final String LOG_PATTERN = "[%s,%s,%s,%sms,%s,%s,%s]";
/**
* 消息消费日志
*/
private static final String MESSAGE_CONSUME_LOG_PATTERN = "[{0},{1},{2},{3},{4},{5},{6},{7}ms]";
/**
* 占位符
*/
private static final String PLACE_HOLDER = "null";
/**
* topic
*/
private static final String TOPIC = "topic";
/**
* tenantId
*/
private static final String TENANT_ID = "tenantId";
/**
* TAG
*/
private static final String TAG = "tag";
/**
* consumerGroup
*/
private static final String CONSUMER_GROUP = "consumerGroup";
/**
* messageKey
*/
private static final String MESSAGE_KEY = "messageKey";
/**
* message
*/
private static final String MESSAGE = "message";
public static String logFormat(Long startTime, String className, String methodName, Boolean isSuccess, Throwable ex) {
Long endTime = System.currentTimeMillis();
if (ex instanceof TpTradeProdException) {
TpTradeProdException e = (TpTradeProdException) ex;
return String.format(
LOG_PATTERN,
className,
methodName,
isSuccess,
(endTime - startTime),
ex.getClass().getSimpleName(),
e.getErrorCode(),
e.getMessage());
} else if (ex instanceof TpTradeCoreException) {
TpTradeCoreException e = (TpTradeCoreException) ex;
return String.format(
LOG_PATTERN,
className,
methodName,
isSuccess,
(endTime - startTime),
ex.getClass().getSimpleName(),
e.getErrorCode(),
e.getMessage());
} else if (ex instanceof TpException) {
TpException e = (TpException) ex;
return String.format(
LOG_PATTERN,
className,
methodName,
isSuccess,
(endTime - startTime),
ex.getClass().getSimpleName(),
e.getErrorCode(),
e.getMessage());
} else if (ex != null) {
return String.format(
LOG_PATTERN,
className,
methodName,
isSuccess,
(endTime - startTime),
ex.getClass().getSimpleName(),
PLACE_HOLDER,
ex.getMessage());
} else {
return String.format(
LOG_PATTERN,
className,
methodName,
isSuccess,
(endTime - startTime),
PLACE_HOLDER,
PLACE_HOLDER,
PLACE_HOLDER);
}
}
public static String generateMessageConsumeLog(ProceedingJoinPoint pj, Boolean isSuccess, Long costTime) {
// 请求参数转换为JSONObject
JSONObject argsJson = getJSONObject(pj.getArgs());
// tenantId
String tenantId = getField(argsJson, TENANT_ID);
// topic
String topic = getField(argsJson, TOPIC);
// tag
String tag = getField(argsJson, TAG);
// consumerGroup
String consumerGroup = getField(argsJson, CONSUMER_GROUP);
// message
String message = getField(argsJson, MESSAGE);
// messageKey
String messageKey = getField(argsJson, MESSAGE_KEY);
return MessageFormat.format(MESSAGE_CONSUME_LOG_PATTERN, tenantId, topic, tag, consumerGroup, message, isSuccess, messageKey, costTime.toString());
}
private static JSONObject getJSONObject(Object[] args) {
JSONObject result = new JSONObject();
// 请求参数为空
if (ObjectUtil.isNull(args) || args.length == 0) {
return result;
}
// 请求参数为对象
JSONArray jsonArray = JSONArray.parseArray(JSONObject.toJSONString(args));
Object o = jsonArray.get(0);
if (o instanceof JSONObject) {
result = (JSONObject) o;
}
return result;
}
private static String getField(JSONObject jsonObject, String field) {
String result = PLACE_HOLDER;
if (jsonObject.containsKey(field)) {
result = String.valueOf(jsonObject.get(field));
}
return result;
}
}

View File

@@ -0,0 +1,168 @@
package com.deepinnet.tptradeprod.biz.service.flow.changeorder;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpproductcore.common.dto.product.TpProdDetailDTO;
import com.deepinnet.tpproductcore.common.dto.rule.TpBizRuleDTO;
import com.deepinnet.tpproductcore.common.dto.rule.TpChangeOrderChargeParamDTO;
import com.deepinnet.tpproductcore.common.dto.rule.TpRuleExecuteDTO;
import com.deepinnet.tpproductcore.common.dto.rule.TpRuleExecuteResultVO;
import com.deepinnet.tpproductcore.common.dto.rule.result.TpCharterChangeOrderChargeResult;
import com.deepinnet.tpproductcore.common.enums.TpRuleExpressionGroupEnum;
import com.deepinnet.tptradecore.common.dto.order.TpOrderChargeRecordDTO;
import com.deepinnet.tptradecore.common.enums.order.TpAuditOrChangePriceBizTypeEnum;
import com.deepinnet.tptradecore.common.enums.order.TpOrderTripTypeEnum;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpOrderStationDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.enums.TpOrderStatusEnum;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.deepinnet.tptradeprod.common.service.integration.client.TpBizRuleClient;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.google.common.collect.Lists;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.deepinnet.tptradeprod.common.enums.TpOrderStatusEnum.*;
/**
* <p>
* 修改订单记录手续费节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "changeOrderRecordServiceChargeNode", name = "修改订单记录手续费节点")
@LiteflowCmpDefine
@RequiredArgsConstructor
public class TpChangeOrderRecordServiceChargeNode {
private final List<TpOrderStatusEnum> CAN_RECORD_SERVICE_CHARGE_STATUS = Lists.newArrayList(ORDER_NEED_CONFIRM, ORDER_CONFIRMED, ORDER_NEED_DISPATCH, ORDER_DISPATCHED, ORDER_DEPOSIT_PAID);
private final TpBizRuleClient tpBizRuleClient;
private final TpOrderClient tpOrderClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 修改订单记录手续费节点");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
// 产品信息
TpProdDetailDTO productDTO = userPlaceOrderContext.getProductDTO();
//原订单信息
TpProdOrderDetailVO oldOrder = userPlaceOrderContext.getOrderDetailVO();
//更改订单信息
TpProdOrderCreateDTO newOder = userPlaceOrderContext.getCreateDTO();
// 使用老订单状态判断
TpOrderStatusEnum orderStatusEnum = getTpOrderStatusEnumByStatus(oldOrder.getStatus(), oldOrder.getType());
if (!CAN_RECORD_SERVICE_CHARGE_STATUS.contains(orderStatusEnum)) {
LogUtil.info("当前变更订单无需记录手续费...");
return;
}
// 新订单的应付金额
BigDecimal newPayableAmount = new BigDecimal(newOder.getPayableAmount());
// 老订单的应付金额
BigDecimal oldPayableAmount = new BigDecimal(oldOrder.getPayableAmount());
// 新订单的应付金额大于老订单的应付金额, 无需记录手续费
if (newPayableAmount.compareTo(oldPayableAmount) >= 0) {
LogUtil.info("新订单应付金额: {}, 老订单应付金额:{}, 无需支付手续费", newOder.getPayableAmount(), oldOrder.getPayableAmount());
return;
}
// 需要记录手续费的情况,计算手续费
BigDecimal currentChangeServiceCharge = null;
BigDecimal chargeRate = null;
// 待确认订单无需记录手续费
// 执行规则入参
if (oldOrder.getStatus().compareTo(ORDER_NEED_CONFIRM.getStatus()) > 0) {
TpRuleExecuteDTO<TpChangeOrderChargeParamDTO> changeRuleDTO = getChangeRuleDTO(userPlaceOrderContext.getTenantId(), productDTO, oldPayableAmount.subtract(newPayableAmount), newOder.getCharterBusStations(), DateUtil.current());
TpRuleExecuteResultVO<TpCharterChangeOrderChargeResult> executeRuleResult = tpBizRuleClient.executeRule(changeRuleDTO);
if (!executeRuleResult.getSuccess()) {
LogUtil.error("当前变更订单手续费执行失败, 入参:{}", JSONObject.toJSONString(changeRuleDTO));
throw new TpTradeProdException(TpTradeProdErrorCode.RULE_EXECUTE_ERROR);
}
if (executeRuleResult.getResult() == null || ObjectUtil.isNull(executeRuleResult.getResult().getChargeAmount())) {
LogUtil.warn("变更订单手续费为空");
return;
}
currentChangeServiceCharge = executeRuleResult.getResult().getChargeAmount().getMoney().getAmount().setScale(2, RoundingMode.DOWN);
chargeRate = executeRuleResult.getResult().getChargeRate();
}
tpOrderClient.updateChargeRecord(buildUpdateChargeRecordParams(newOder, currentChangeServiceCharge, chargeRate));
}
private TpOrderChargeRecordDTO buildUpdateChargeRecordParams(TpProdOrderCreateDTO newOrder, BigDecimal serviceCharge, BigDecimal chargeRate) {
TpOrderChargeRecordDTO tpOrderChargeRecordDTO = new TpOrderChargeRecordDTO();
tpOrderChargeRecordDTO.setOrderNo(newOrder.getOrderNo());
tpOrderChargeRecordDTO.setOriginalOrderNo(newOrder.getOriginalOrderNo());
tpOrderChargeRecordDTO.setBizType(TpAuditOrChangePriceBizTypeEnum.CHANGE_ORDER.getBizType());
tpOrderChargeRecordDTO.setServiceCharge(ObjectUtil.isNull(serviceCharge) ? null : serviceCharge.toString());
tpOrderChargeRecordDTO.setServiceChargeRate(ObjectUtil.isNull(chargeRate) ? null : chargeRate.toString());
tpOrderChargeRecordDTO.setTenantId(newOrder.getTenantId());
return tpOrderChargeRecordDTO;
}
private static TpRuleExecuteDTO<TpChangeOrderChargeParamDTO> getChangeRuleDTO(String tenantId, TpProdDetailDTO productDetail, BigDecimal subtractMoney, List<TpOrderStationDTO> charterBusStations, Long orderTime) {
// 找到发车时间最早的时间
Long pickUpTime;
if (charterBusStations.size() == 1) {
pickUpTime = Convert.toLong(charterBusStations.get(0).getPickUpTime());
} else {
List<TpOrderStationDTO> goTrip = charterBusStations.stream().filter(station -> StrUtil.equals(station.getTripType(), TpOrderTripTypeEnum.GO.getCode())).collect(Collectors.toList());
pickUpTime = Convert.toLong(goTrip.get(0).getPickUpTime());
}
// 将产品信息对应的规则信息转换成Map
Map<String, List<TpBizRuleDTO>> rulesMap = productDetail.getRules().stream().collect(Collectors.groupingBy(TpBizRuleDTO::getRuleGroup));
// 找到对应的变更手续费的规则
List<TpBizRuleDTO> changeRules = rulesMap.get(TpRuleExpressionGroupEnum.CHANGE_ORDER_CHARGE.getCode());
List<String> rules = Lists.newArrayList();
changeRules.forEach(rule -> rules.add(rule.getExpression()));
// 构建执行入参
TpChangeOrderChargeParamDTO param = new TpChangeOrderChargeParamDTO();
param.setOrderPriceChange(subtractMoney);
// 发车时间
param.setDepartureTime(pickUpTime);
param.setOccurTime(orderTime);
TpRuleExecuteDTO<TpChangeOrderChargeParamDTO> ruleExecuteDTO = new TpRuleExecuteDTO<>();
ruleExecuteDTO.setRuleList(rules);
ruleExecuteDTO.setParameter(param);
ruleExecuteDTO.setRuleExpressionGroup(TpRuleExpressionGroupEnum.CHANGE_ORDER_CHARGE);
ruleExecuteDTO.setTenantId(tenantId);
return ruleExecuteDTO;
}
}

View File

@@ -0,0 +1,49 @@
package com.deepinnet.tptradeprod.biz.service.flow.changeorder;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradecore.common.dto.order.TpOrderPushStatusDTO;
import com.deepinnet.tptradecore.common.enums.order.TpOrderPushStatusEnum;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.enums.TpOrderStatusEnum;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import javax.annotation.Resource;
/**
* <p>
*
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "orderChangeNeedAudit", name = "订单变更是否需要审核")
@LiteflowCmpDefine(value = NodeTypeEnum.IF)
public class TpOrderChangNeedAuditNode {
@Resource
private TpOrderClient orderClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_IF)
public boolean process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 判断是否需要业务员确认审核");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderDetailVO orderDetailVO = userPlaceOrderContext.getOrderDetailVO();
if (TpOrderStatusEnum.ORDER_NEED_CONFIRM.equals(TpOrderStatusEnum.getTpOrderStatusEnumByStatus(orderDetailVO.getStatus(), orderDetailVO.getType()))) {
//订单状态需要流转到待确认
orderClient.pushOrderStatus(TpOrderPushStatusDTO.builder()
.orderNo(userPlaceOrderContext.getCreateDTO().getOrderNo())
.tenantId(userPlaceOrderContext.getTenantId())
.tpOrderPushStatusEnum(TpOrderPushStatusEnum.ORDER_NEED_CONFIRM).build());
return false;
}
return userPlaceOrderContext.getChangeOrderNeedAudit();
}
}

View File

@@ -0,0 +1,297 @@
package com.deepinnet.tptradeprod.biz.service.flow.changeorder;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradecore.common.dto.order.TpOrderPushStatusDTO;
import com.deepinnet.tptradecore.common.enums.order.*;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.enums.TpOrderSceneEnum;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.deepinnet.tptradeprod.common.service.facade.TpOrderChangeAcceptanceFacade;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.vo.*;
import com.github.dadiyang.equator.Equator;
import com.github.dadiyang.equator.FieldInfo;
import com.github.dadiyang.equator.GetterBaseEquator;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.deepinnet.tptradecore.common.enums.order.TpOrderChangeItemFactorEnum.*;
import static com.deepinnet.tptradecore.common.enums.order.TpOrderChangeItemTypeEnum.*;
import static com.deepinnet.tptradecore.common.enums.order.TpOrderTripTypeEnum.BACK;
import static com.deepinnet.tptradecore.common.enums.order.TpOrderTripTypeEnum.GO;
/**
* <p>
* 创建订单节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "orderDiffNode", name = "订单差异对比 & 提交审核 & 订单状态推进")
@LiteflowCmpDefine
@RequiredArgsConstructor
public class TpOrderDiffNode {
@Resource
private TpOrderClient tpOrderClient;
private static final Map<String, TpOrderChangeItemFactorEnum> DIFF_MAP = Maps.newHashMapWithExpectedSize(16);
private static final List<TpOrderTripTypeEnum> TRIP_TYPE_ENUMS = Lists.newArrayList(GO, BACK);
static {
DIFF_MAP.put("start_time", START_TIME);//出发时间
DIFF_MAP.put("return_time", RETURN_TIME);//返回时间
DIFF_MAP.put("pickUpLocation", GO_ON_POINT);//上车点
DIFF_MAP.put("dropOffLocation", DROP_OFF_POINT);//下车点
// DIFF_MAP.put("", WAY_POINT);//途径点
// DIFF_MAP.put("", TRIP_TYPE);//包车类型
DIFF_MAP.put("days", RENTAL_DAYS);//用车天数
DIFF_MAP.put("passengerCount", PASSENGER_COUNT);//乘车人数
//DIFF_MAP.put("name", CAR_INFO);//车辆信息
//DIFF_MAP.put("count", CAR_NUM);//车辆数量
DIFF_MAP.put("includeDriverExpenses", DRIVER_FEE);//司机费用
DIFF_MAP.put("miles", MILES);//里程
DIFF_MAP.put("duration", DURATION);//耗时
}
/**
* 途径点对比器
*/
private static final Equator WAY_EQUATOR = new GetterBaseEquator(Lists.newArrayList("locationName"), null, true);
@Resource
private TpOrderChangeAcceptanceFacade orderChangeAcceptanceFacade;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 订单变更对比 & 提交审核");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
//原订单信息
TpProdOrderDetailVO oldOrder = userPlaceOrderContext.getOrderDetailVO();
//更改订单信息
TpProdOrderCreateDTO newOder = userPlaceOrderContext.getCreateDTO();
String tenantId = userPlaceOrderContext.getTenantId();
String originalOrderNo = userPlaceOrderContext.getCreateDTO().getOriginalOrderNo();
String orderNo = userPlaceOrderContext.getCreateDTO().getOrderNo();
TpProdOrderChangeApplyCreatedDTO tpOrderChangeApplyDTO = TpProdOrderChangeApplyCreatedDTO.builder().build();
//fixme 暂时没有是否自动审核的配置项
Boolean autoAudit = Boolean.FALSE;
tpOrderChangeApplyDTO.setAutoAudit(autoAudit);
tpOrderChangeApplyDTO.setOrderNo(orderNo);
tpOrderChangeApplyDTO.setOriginalOrderNo(originalOrderNo);
if (autoAudit) {
tpOrderChangeApplyDTO.setApplyStatus(TpOrderChangeApplyStatusEnum.APPROVED_SUCCESS.getType());
} else {
tpOrderChangeApplyDTO.setApplyStatus(TpOrderChangeApplyStatusEnum.WAITING_APPROVED.getType());
}
tpOrderChangeApplyDTO.setApplyTime(System.currentTimeMillis());
tpOrderChangeApplyDTO.setApplyType(TpOrderChangeTypeEnum.ORDER_CHANGE.getType());
//申请人信息
TpOrderPlacerVO orderPlacer = newOder.getOrderPlacer();
TpProdOrderChangeApplicantCreatedDTO tpOrderChangeApplicantDTO = new TpProdOrderChangeApplicantCreatedDTO();
if (newOder.getIsBackend()) {
tpOrderChangeApplicantDTO.setApplicantNo(userPlaceOrderContext.getBackendUserNo());
tpOrderChangeApplyDTO.setOrderScene(TpOrderSceneEnum.SALESMAN_OPERATE.getCode());
} else {
tpOrderChangeApplicantDTO.setApplicantNo(orderPlacer.getPlacerNo());
tpOrderChangeApplicantDTO.setApplicantName(newOder.getOrderRequirementUser().getRequirementContactName());
tpOrderChangeApplicantDTO.setApplicantPhone(newOder.getOrderRequirementUser().getRequirementContact());
tpOrderChangeApplyDTO.setOrderScene(TpOrderSceneEnum.USER_OPERATE.getCode());
}
tpOrderChangeApplyDTO.setOrderChangeApplicant(tpOrderChangeApplicantDTO);
tpOrderChangeApplyDTO.setTenantId(tenantId);
List<TpProdOrderChangeItemCreatedDTO> orderChangeItemDTOS = Lists.newCopyOnWriteArrayList();
//判断行程类型是否变更
if (!oldOrder.getProductCategoryNo().equals(newOder.getProductCategoryNo())) {
TpProdOrderChangeItemCreatedDTO tpOrderChangeItemDTO = new TpProdOrderChangeItemCreatedDTO();
tpOrderChangeItemDTO.setOrderNo(originalOrderNo);
tpOrderChangeItemDTO.setItemType(TRIP_ROUND_CHANGED.getType());
TpProdOrderChangeItemFactorCreatedDTO tpOrderChangeItemFactorDTO = new TpProdOrderChangeItemFactorCreatedDTO();
tpOrderChangeItemFactorDTO.setFactorCode(TRIP_TYPE.getType());
tpOrderChangeItemFactorDTO.setFactorName(TRIP_TYPE.getDesc());
tpOrderChangeItemFactorDTO.setOrderNo(originalOrderNo);
tpOrderChangeItemFactorDTO.setBeforeValue(oldOrder.getProductCategoryNo());
tpOrderChangeItemFactorDTO.setAfterValue(newOder.getProductCategoryNo());
tpOrderChangeItemFactorDTO.setTenantId(tenantId);
tpOrderChangeItemDTO.setItemFactors(Lists.newArrayList(tpOrderChangeItemFactorDTO));
tpOrderChangeItemDTO.setTenantId(tenantId);
orderChangeItemDTOS.add(tpOrderChangeItemDTO);
}
//找出差异项 标的项 根据行程类型
List<TpOrderSubjectItemDTO> newOderSubjectItemList = newOder.getOrderSubjectItem();
List<TpOrderSubjectItemVO> oldOrderSubjectItemList = oldOrder.getOrderSubjectItem();
//行程单
List<TpOrderStationDTO> newTrip = newOder.getCharterBusStations();
List<TpOrderTravelTripVO> oldTrip = oldOrder.getTpOrderTravelTrips();
for (TpOrderTripTypeEnum tripTypeEnum : TRIP_TYPE_ENUMS) {
Collection<TpOrderSubjectItemDTO> newItemList = CollectionUtil.filterNew(newOderSubjectItemList, tpOrderSubjectItemDTO -> tripTypeEnum.getCode().equals(tpOrderSubjectItemDTO.getTripType()));
Collection<TpOrderSubjectItemVO> oldItemList = CollectionUtil.filterNew(oldOrderSubjectItemList, tpOrderSubjectItemVO -> tripTypeEnum.getCode().equals(tpOrderSubjectItemVO.getTripType()));
List<TpProdOrderChangeItemFactorCreatedDTO> tpOrderChangeItemFactorDTOS = Lists.newArrayList();
if (!(CollectionUtil.isEmpty(newItemList) && CollectionUtil.isEmpty(oldItemList))) {
String newCarInfo = newItemList.stream().map(newItem -> newItem.getName() + "||" + newItem.getCount()).collect(Collectors.joining(";"));
String oldCarInfo = oldItemList.stream().map(oldItem -> oldItem.getName() + "||" + oldItem.getCount()).collect(Collectors.joining(";"));
if (!StrUtil.equals(newCarInfo, oldCarInfo)) {
TpProdOrderChangeItemFactorCreatedDTO tpOrderChangeItemFactorDTO = new TpProdOrderChangeItemFactorCreatedDTO();
tpOrderChangeItemFactorDTO.setFactorCode(CAR_INFO.getType());
tpOrderChangeItemFactorDTO.setFactorName(CAR_INFO.getDesc());
//tpOrderChangeItemFactorDTO.setFactorType();
tpOrderChangeItemFactorDTO.setOrderNo(originalOrderNo);
tpOrderChangeItemFactorDTO.setBeforeValue(oldCarInfo);
tpOrderChangeItemFactorDTO.setAfterValue(newCarInfo);
tpOrderChangeItemFactorDTO.setTenantId(tenantId);
tpOrderChangeItemFactorDTOS.add(tpOrderChangeItemFactorDTO);
}
}
// TpOrderSubjectItemDTO newItem = CollectionUtil.findOne(newOderSubjectItem, tpOrderSubjectItemDTO -> tripTypeEnum.getCode().equals(tpOrderSubjectItemDTO.getTripType()));
// TpOrderSubjectItemVO oldItem = CollectionUtil.findOne(oldOrderSubjectItem, tpOrderSubjectItemVO -> tripTypeEnum.getCode().equals(tpOrderSubjectItemVO.getTripType()));
//
// if (newItem == null && oldItem == null) {
// break;
// }
//TpOrderStationDTO newTripItem = CollectionUtil.findOne(newTrip, tpOrderStationDTO -> tripTypeEnum.getCode().equals(tpOrderStationDTO.getTripType()));
//TpOrderTravelTripVO oldTripItem = CollectionUtil.findOne(oldTrip, tpOrderTravelTripVO -> tripTypeEnum.getCode().equals(tpOrderTravelTripVO.getTripType()));
// TpOrderStationDTO newTripItem = newItemList.get(0) == null ? new TpOrderStationDTO() : CollectionUtil.findOne(newTrip, tpOrderStationDTO -> tripTypeEnum.getCode().equals(tpOrderStationDTO.getTripType()));
// TpOrderTravelTripVO oldTripItem = oldItemList.get(0) == null ? new TpOrderTravelTripVO() : CollectionUtil.findOne(oldTrip, tpOrderTravelTripVO -> tripTypeEnum.getCode().equals(tpOrderTravelTripVO.getTripType()));
TpOrderStationDTO newTripItem = CollectionUtil.findOne(newTrip, tpOrderStationDTO -> tripTypeEnum.getCode().equals(tpOrderStationDTO.getTripType()));
TpOrderTravelTripVO oldTripItem = CollectionUtil.findOne(oldTrip, tpOrderTravelTripVO -> tripTypeEnum.getCode().equals(tpOrderTravelTripVO.getTripType()));
newTripItem = newTripItem == null ? new TpOrderStationDTO() : newTripItem;
oldTripItem = oldTripItem == null ? new TpOrderTravelTripVO() : oldTripItem;
Equator equator = new GetterBaseEquator();
// 获取不同的属性
TpOrderSubjectItemDTO newOrderSubjectItem = CollectionUtil.isEmpty(newItemList) ? new TpOrderSubjectItemDTO() : CollectionUtil.findOne(newItemList, tpOrderSubjectItemDTO -> tpOrderSubjectItemDTO.getTripType().equals(tripTypeEnum.getCode()));
TpOrderSubjectItemVO oldOrderSubjectItem = CollectionUtil.isEmpty(oldItemList) ? new TpOrderSubjectItemVO() : CollectionUtil.findOne(oldItemList, tpOrderSubjectItemVO -> tpOrderSubjectItemVO.getTripType().equals(tripTypeEnum.getCode()));
List<FieldInfo> subjectItemDiff = equator.getDiffFields(newOrderSubjectItem, oldOrderSubjectItem);
List<FieldInfo> busStationsDiff = equator.getDiffFields(newTripItem, oldTripItem);
TpProdOrderChangeItemCreatedDTO tpOrderChangeItemDTO = new TpProdOrderChangeItemCreatedDTO();
tpOrderChangeItemDTO.setOrderNo(originalOrderNo);
tpOrderChangeItemDTO.setTenantId(tenantId);
tpOrderChangeItemDTO.setItemType(tripTypeEnum == GO ? GO_TRIP_CHANGED.getType() : BACK_TRIP_CHANGED.getType());
//行程对比
for (FieldInfo fieldInfo : subjectItemDiff) {
TpOrderChangeItemFactorEnum factorEnum = DIFF_MAP.get(fieldInfo.getFieldName());
if (factorEnum != null) {
TpProdOrderChangeItemFactorCreatedDTO tpOrderChangeItemFactorDTO = new TpProdOrderChangeItemFactorCreatedDTO();
tpOrderChangeItemFactorDTO.setFactorCode(factorEnum.getType());
tpOrderChangeItemFactorDTO.setFactorName(factorEnum.getDesc());
//tpOrderChangeItemFactorDTO.setFactorType();
tpOrderChangeItemFactorDTO.setOrderNo(originalOrderNo);
tpOrderChangeItemFactorDTO.setBeforeValue(fieldInfo.getSecondVal() == null ? null : fieldInfo.getSecondVal().toString());
tpOrderChangeItemFactorDTO.setAfterValue(fieldInfo.getFirstVal() == null ? null : fieldInfo.getFirstVal().toString());
tpOrderChangeItemFactorDTO.setTenantId(tenantId);
tpOrderChangeItemFactorDTOS.add(tpOrderChangeItemFactorDTO);
}
}
for (FieldInfo fieldInfo : busStationsDiff) {
TpOrderChangeItemFactorEnum factorEnum = DIFF_MAP.get(fieldInfo.getFieldName());
if (factorEnum != null) {
TpProdOrderChangeItemFactorCreatedDTO tpOrderChangeItemFactorDTO = new TpProdOrderChangeItemFactorCreatedDTO();
tpOrderChangeItemFactorDTO.setFactorCode(factorEnum.getType());
tpOrderChangeItemFactorDTO.setFactorName(factorEnum.getDesc());
//tpOrderChangeItemFactorDTO.setFactorType();
tpOrderChangeItemFactorDTO.setOrderNo(originalOrderNo);
tpOrderChangeItemFactorDTO.setBeforeValue(fieldInfo.getSecondVal() == null ? null : fieldInfo.getSecondVal().toString());
tpOrderChangeItemFactorDTO.setAfterValue(fieldInfo.getFirstVal() == null ? null : fieldInfo.getFirstVal().toString());
tpOrderChangeItemFactorDTO.setTenantId(tenantId);
tpOrderChangeItemFactorDTOS.add(tpOrderChangeItemFactorDTO);
}
}
//途径点对比
String newWayTrip = CollectionUtil.isEmpty(newTripItem.getPathPoints()) ? "" : newTripItem.getPathPoints().stream().sorted(Comparator.comparing(TpTravelTripPathPointDTO::getIndex)).skip(1).limit(newTripItem.getPathPoints().size() - 2).map(TpTravelTripPathPointDTO::getLocationName).collect(Collectors.joining(";"));
String oldWayTrip = CollectionUtil.isEmpty(oldTripItem.getTripPositions()) ? "" : oldTripItem.getTripPositions().stream().sorted(Comparator.comparing(TpOrderTripPositionVO::getIndex)).skip(1).limit(oldTripItem.getTripPositions().size() - 2).map(TpOrderTripPositionVO::getLocationName).collect(Collectors.joining(";"));
if (!StrUtil.equals(newWayTrip, oldWayTrip)) {
TpProdOrderChangeItemFactorCreatedDTO tpOrderChangeItemFactorDTO = new TpProdOrderChangeItemFactorCreatedDTO();
tpOrderChangeItemFactorDTO.setFactorCode(WAY_POINT.getType());
tpOrderChangeItemFactorDTO.setFactorName(WAY_POINT.getDesc());
//tpOrderChangeItemFactorDTO.setFactorType("");
tpOrderChangeItemFactorDTO.setOrderNo(originalOrderNo);
tpOrderChangeItemFactorDTO.setBeforeValue(oldWayTrip);
tpOrderChangeItemFactorDTO.setAfterValue(newWayTrip);
tpOrderChangeItemFactorDTO.setTenantId(tenantId);
tpOrderChangeItemFactorDTOS.add(tpOrderChangeItemFactorDTO);
}
// Map<Integer, TpTravelTripPathPointDTO> newWayTrip = CollStreamUtil.toIdentityMap(pathPoints, TpTravelTripPathPointDTO::getIndex);
// Map<Integer, TpOrderTripPositionVO> oldWayTrip = CollStreamUtil.toIdentityMap(tripPositions, TpOrderTripPositionVO::getIndex);
// int size = Math.max(newWayTrip.size(), oldWayTrip.size());
// for (int i = 0; i < size; i++) {
// List<FieldInfo> diffFields = WAY_EQUATOR.getDiffFields(newWayTrip.get(i), oldWayTrip.get(i));
// if (CollectionUtil.isNotEmpty(diffFields)) {
// TpProdOrderChangeItemFactorCreatedDTO tpOrderChangeItemFactorDTO = new TpProdOrderChangeItemFactorCreatedDTO();
// tpOrderChangeItemFactorDTO.setFactorCode(WAY_POINT.getType());
// tpOrderChangeItemFactorDTO.setFactorName(WAY_POINT.getDesc());
// //tpOrderChangeItemFactorDTO.setFactorType("");
// tpOrderChangeItemFactorDTO.setOrderNo(originalOrderNo);
// FieldInfo fieldInfo = diffFields.get(0);
// tpOrderChangeItemFactorDTO.setBeforeValue(fieldInfo.getSecondVal() == null ? null : fieldInfo.getSecondVal().toString());
// tpOrderChangeItemFactorDTO.setAfterValue(fieldInfo.getFirstVal() == null ? null : fieldInfo.getFirstVal().toString());
// tpOrderChangeItemFactorDTO.setSortIndex(newWayTrip.get(i).getIndex());
// tpOrderChangeItemFactorDTO.setTenantId(tenantId);
// tpOrderChangeItemFactorDTOS.add(tpOrderChangeItemFactorDTO);
// }
// }
tpOrderChangeItemDTO.setItemFactors(tpOrderChangeItemFactorDTOS);
orderChangeItemDTOS.add(tpOrderChangeItemDTO);
}
tpOrderChangeApplyDTO.setOrderChangeItems(orderChangeItemDTOS);
TpResult<Boolean> orderChangeApply = orderChangeAcceptanceFacade.createOrderChangeApply(tpOrderChangeApplyDTO);
if (!orderChangeApply.getData()) {
LogUtil.error("订单申请单创建流程失败, 订单编号:{}, 创建入参:{}", userPlaceOrderContext.getOrderNo(), JSONObject.toJSONString(tpOrderChangeApplicantDTO));
throw new TpTradeProdException(TpTradeProdErrorCode.CREATE_ORDER_ERROR);
}
//订单状态需要流转到变更-审核中
tpOrderClient.pushOrderStatus(TpOrderPushStatusDTO.builder()
.orderNo(userPlaceOrderContext.getCreateDTO().getOrderNo())
.tenantId(userPlaceOrderContext.getTenantId())
.tpOrderPushStatusEnum(TpOrderPushStatusEnum.ORDER_CHANGE_AUDITING).build());
}
}

View File

@@ -0,0 +1,86 @@
package com.deepinnet.tptradeprod.biz.service.flow.changeorder;
import cn.hutool.core.util.NumberUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpproductcore.common.dto.product.TpProdDetailDTO;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.enums.TpOrderPayModeEnum;
import com.deepinnet.tptradeprod.common.enums.TpOrderStatusEnum;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderCreateVO;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.google.common.collect.Lists;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
/**
* <p>
* 创建订单节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "prepareOrderNode", name = "订单准备")
@LiteflowCmpDefine
@RequiredArgsConstructor
public class TpPrepareOrderNode {
private final static List<TpOrderStatusEnum> PAY_AMOUNT_STATUS = Lists.newArrayList();
static {
PAY_AMOUNT_STATUS.add(TpOrderStatusEnum.ORDER_NEED_DISPATCH);
PAY_AMOUNT_STATUS.add(TpOrderStatusEnum.ORDER_DEPOSIT_PAID);
PAY_AMOUNT_STATUS.add(TpOrderStatusEnum.ORDER_DISPATCHED);
}
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 订单准备");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
TpProdOrderDetailVO parentOrderDetail = userPlaceOrderContext.getOrderDetailVO();
String orderNo = createDTO.getOrderNo();
createDTO.setParentOrderNo(orderNo);
createDTO.setOrderNo(null);
TpProdOrderDetailVO orderDetailVO = userPlaceOrderContext.getOrderDetailVO();
createDTO.setPayMode(orderDetailVO.getPayMode());
createDTO.setOrderTime(orderDetailVO.getOrderTime());
if (PAY_AMOUNT_STATUS.contains(TpOrderStatusEnum.getTpOrderStatusEnumByStatus(orderDetailVO.getStatus(), orderDetailVO.getType()))) {
createDTO.setPayAmount(orderDetailVO.getPayAmount());
} else {
String payMode = createDTO.getPayMode();
if (Objects.equals(TpOrderPayModeEnum.PAY_BEFORE_ALL.getPayMode(), payMode)) {
createDTO.setPayAmount(createDTO.getPayableAmount());
}
if (Objects.equals(TpOrderPayModeEnum.PAY_BEFORE.getPayMode(), payMode)) {
TpProdDetailDTO productDTO = userPlaceOrderContext.getProductDTO();
BigDecimal prepayRate = productDTO.getExtendAttributes().getPrepayRate();
createDTO.setPayAmount(NumberUtil.mul(new BigDecimal(createDTO.getPayableAmount()), prepayRate).toString());
}
if (Objects.equals(TpOrderPayModeEnum.PAY_AFTER.getPayMode(), payMode)) {
createDTO.setPayAmount("0");
}
}
//拿到老的行程单id放到新的里面去
// List<TpOrderTravelTripVO> tpOrderTravelTrips = orderDetailVO.getTpOrderTravelTrips();
// Map<String, TpOrderTravelTripVO> oldTripMap = CollStreamUtil.toIdentityMap(tpOrderTravelTrips, TpOrderTravelTripVO::getTripType);
// List<TpOrderStationDTO> charterBusStations = createDTO.getCharterBusStations();
// charterBusStations.forEach(charterBusStation -> charterBusStation.setTripNo(oldTripMap.get(charterBusStation.getTripType()).getTripNo()));
// 塞入并行询价的内部价金额
createDTO.getTpOrderPriceRecords().forEach(priceRecord -> priceRecord.setInternalInquireAmount(userPlaceOrderContext.getInternalPrice()));
// 塞入原始下单人
createDTO.setOrderPlacer(parentOrderDetail.getOrderPlacer());
}
}

View File

@@ -0,0 +1,46 @@
package com.deepinnet.tptradeprod.biz.service.flow.changeorder;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderChangeApplyListDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderChangeApplyClient;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
/**
* <p>
* 创建订单节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "queryOrderChangeAuditNode", name = "查询审批信息")
@LiteflowCmpDefine
@RequiredArgsConstructor
public class TpQueryOrderChangeAuditNode {
private final TpOrderChangeApplyClient orderChangeClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 查询订单变更审批记录");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO order = userPlaceOrderContext.getCreateDTO();
TpProdOrderChangeApplyListDTO query = new TpProdOrderChangeApplyListDTO();
query.setOriginalOrderNo(order.getOriginalOrderNo());
query.setTenantId(order.getTenantId());
userPlaceOrderContext.setOrderChangeApplyList(orderChangeClient.listOrderChangeApplyHistory(query));
}
}

View File

@@ -0,0 +1,81 @@
package com.deepinnet.tptradeprod.biz.service.flow.changeorder;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderQueryDTO;
import com.deepinnet.tptradeprod.common.enums.TpOrderStatusEnum;
import com.deepinnet.tptradeprod.common.enums.TpOrderTypeEnum;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.google.common.collect.Lists;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
import java.util.List;
import java.util.Objects;
import static com.deepinnet.tptradecore.common.enums.order.TpOrderModulesEnum.*;
import static com.deepinnet.tptradeprod.common.enums.TpOrderStatusEnum.*;
/**
* <p>
* 创建订单节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "queryOrderNode", name = "查询原订单信息")
@LiteflowCmpDefine
@RequiredArgsConstructor
public class TpQueryOrderNode {
private final TpOrderClient orderClient;
private final List<TpOrderStatusEnum> CAN_CHANGE_STATUS = Lists.newArrayList(ORDER_NEED_CONFIRM, ORDER_CONFIRMED, ORDER_REJECTED, ORDER_DEPOSIT_NEED_PAY, ORDER_NEED_DISPATCH, ORDER_DISPATCHED, ORDER_DEPOSIT_PAID);
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 查询订单信息");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO order = userPlaceOrderContext.getCreateDTO();
//查询订单信息
TpProdOrderQueryDTO query = new TpProdOrderQueryDTO();
query.setOriginalOrderNo(order.getOriginalOrderNo());
query.setTenantId(userPlaceOrderContext.getTenantId());
query.setUserNo(order.getUserNo());
query.setNeedModules(Lists.newArrayList(ORDER_SUBJECT_ITEM.getModule(), ORDER_TRAVEL_TRIP.getModule(), ORDER_PLACER.getModule()));
TpProdOrderDetailVO orderDetail = orderClient.getOrderDetail(query);
if (orderDetail == null) {
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_NOT_FOUND);
}
if (!Objects.equals(orderDetail.getType(), TpOrderTypeEnum.PACKING_ORDER.getType())) {//包车订单才允许修改
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_CHANGE_ERROR_NOT_ALLOW_TYPE);
}
TpOrderStatusEnum orderStatusEnum = getTpOrderStatusEnumByStatus(orderDetail.getStatus(), orderDetail.getType());
//订单状态
if (!CAN_CHANGE_STATUS.contains(orderStatusEnum)) {
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_CHANGE_ERROR_NOT_ALLOW_STATUS);
}
Long expireTime = orderDetail.getExpireTime();
if (expireTime <= System.currentTimeMillis()) {
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_CHANGE_ERROR_NOT_ALLOW_TIME);
}
userPlaceOrderContext.setOrderDetailVO(orderDetail);
// 塞入当前操作后台人员
userPlaceOrderContext.setBackendUserNo(order.getOrderPlacer().getBackendPlacerNo());
}
}

View File

@@ -0,0 +1,248 @@
package com.deepinnet.tptradeprod.biz.service.flow.constants;
/**
* @author amos
* @since 2023-10-16 星期五
**/
public class LiteFlowConstant {
public static final String REFUND_TICKET_FLOW = "refundTicketFlow";
public static final String CALCULATE_REFUND_TICKET_AMOUNT_FLOW = "calculateRefundTicketAmountFlow";
public static final String REFUND_AVAILABLE_CHECK_FLOW = "refundAvailableCheckFlow";
public static final String REFUND_BUTTON_SHOWABLE_FLOW = "refundButtonShowableFlow";
public static final String QUERY_AVAILABLE_REFUND_VOUCHERS = "queryAvailableRefundVouchers";
public static final String QUERY_AVAILABLE_RESCHEDULE_VOUCHERS = "queryAvailableRescheduleVouchers";
public static final String USER_PLACE_ORDER_FLOW = "userPlaceOrderFlow";
public static final String USER_CHANGE_ORDER_FLOW = "userChangeOrderFlow";
public static final String USER_PLACE_ORDER_CUSTOM_BUS_FLOW = "userPlaceOrderCustomBusFlow";
public static final String USER_PLACE_ORDER_CHARTER_BUS_FLOW = "userPlaceOrderCharterBusFlow";
public static final String USER_PLACE_ORDER_CARPOOL_BUS_FLOW = "userPlaceOrderCarpoolBusFlow";
public static final String USER_PAID_ORDER_FLOW = "userPaidOrderFlow";
public static final String USER_RESCHEDULE_FLOW = "userRescheduleFlow";
public static final String USER_CHARTER_BUS_PAID_ORDER_FLOW = "userCharterBusPaidOrderFlow";
public static final String USER_CARPOOL_BUS_PAID_ORDER_FLOW = "userCarpoolBusPaidOrderFlow";
public static final String USER_CHARTER_BUS_CANCEL_ORDER_FLOW = "userCharterBusCancelOrderFlow";
/**
* 先付后享
*/
public static final String USER_PAY_BEFORE_USE_FLOW = "userPayBeforeUseFlow";
/**
* 先享后付
*/
public static final String USER_PAY_AFTER_USE_FLOW = "userPayAfterUseFlow";
/**
* 待确认取消订单
*/
public static final String USER_CANCEL_ORDER_NEED_CONFIRM_FLOW = "userCancelOrderNeedConfirmFlow";
/**
* 订金已支付取消订单
*/
public static final String USER_CANCEL_ORDER_PAID_FLOW = "userCancelOrderPaidFlow";
/**
* 订单确认审核流程
*/
public static final String ORDER_AUDIT_CONFIRM_FLOW = "orderAuditConfirmFlow";
/**
* 新订单确认审核流程
*/
public static final String ORDER_CREATE_AUDIT_CONFIRM_FLOW = "orderCreateAuditConfirmFlow";
/**
* 订单取消确认审核流程
*/
public static final String ORDER_CANCEL_AUDIT_CONFIRM_FLOW = "orderCancelAuditConfirmFlow";
/**
* 订单变更确认审核流程
*/
public static final String ORDER_CHANGE_AUDIT_CONFIRM_FLOW = "orderChangeAuditConfirmFlow";
/**
* 订单取消减免服务费审核确认拒绝流程
*/
public static final String ORDER_CANCEL_SERVICE_CHARGE_REDUCE_APPROVED_REJECT_FLOW = "orderCancelServiceChargeReduceApprovedRejectFlow";
/**
* 订单取消减免服务费审核确认超时流程
*/
public static final String ORDER_CANCEL_SERVICE_CHARGE_REDUCE_APPROVED_TIMEOUT_FLOW = "orderCancelServiceChargeReduceApprovedTimeOutFlow";
/**
* 订单取消减免服务费审核确认通过流程
*/
public static final String ORDER_CANCEL_SERVICE_CHARGE_REDUCE_APPROVED_SUCCESS_FLOW = "orderCancelServiceChargeReduceApprovedSuccessFlow";
/**
* 订单变更减免服务费审核确认拒绝流程
*/
public static final String ORDER_CHANGE_SERVICE_CHARGE_REDUCE_APPROVED_REJECT_FLOW = "orderChangeServiceChargeReduceApprovedRejectFlow";
/**
* 订单变更减免服务费审核确认超时流程
*/
public static final String ORDER_CHANGE_SERVICE_CHARGE_REDUCE_APPROVED_TIMEOUT_FLOW = "orderChangeServiceChargeReduceApprovedTimeOutFlow";
/**
* 订单变更减免服务费审核确认通过流程
*/
public static final String ORDER_CHANGE_SERVICE_CHARGE_REDUCE_APPROVED_SUCCESS_FLOW = "orderChangeServiceChargeReduceApprovedSuccessFlow";
public static final String ORDER_APPLY_CREATE_FLOW = "orderApplyCreateFlow";
public static final String ORDER_CHANGE_APPLY_CREATE_FLOW = "orderChangeApplyCreateFlow";
public static final String ORDER_CREATE_APPLY_CREATE_FLOW = "orderCreateApplyCreateFlow";
public static final String ORDER_CANCEL_APPLY_CREATE_FLOW = "orderCancelApplyCreateFlow";
public static final String ORDER_END_CHARGE_CONFIRM_FLOW = "orderEndChargeConfirmFlow";
public static final String ORDER_SERVICE_CHARGE_REDUCE_FLOW = "orderServiceChargeReduceConfirmFlow";
/**
* 订金支付流程
*/
public static final String USER_DEPOSIT_PAID_FLOW = "userCharterBusDepositPaidFlow";
/**
* 尾款支付流程
*/
public static final String USER_BALANCE_PAID_FLOW = "userCharterBusBalancePaidFlow";
/**
* 首次审核 确认通过 流程
*/
public static final String ORDER_AUDIT_FIRST_CONFIRM_FLOW = "orderAuditFirstConfirmFlow";
/**
* 变更审核确认流程
*/
public static final String ORDER_AUDIT_CHANGE_CONFIRM_FLOW = "orderAuditChangeConfirmNoneReductionFlow";
/**
* 变更审核确认流程
*/
public static final String ORDER_AUDIT_CANCEL_CONFIRM_FLOW = "orderAuditCancelConfirmFlow";
/**
* 创建审核确认通过流程
*/
public static String ORDER_CREATE_CONFIRM_APPROVED_SUCCESS_FLOW = "orderCreateConfirmApprovedSuccessFlow";
/**
* 取消审核确认无全额退款流程
*/
public static String ORDER_CANCEL_CONFIRM_APPROVED_NON_FULL_REDUCTION_FLOW = "orderCancelConfirmApprovedNonFullReductionFlow";
/**
* 取消审核确认有全额退款流程
*/
public static String ORDER_CANCEL_CONFIRM_APPROVED_FULL_REDUCTION_FLOW = "orderCancelConfirmApprovedFullReductionFlow";
/**
* 变更审核确认审批通过流程-减免单次变更手续费
*/
public static String ORDER_CHANGE_CONFIRM_APPROVED_SUCCESS_SINGLE_REDUCTION_FLOW = "orderChangeConfirmApprovedSuccessSingleReductionFlow";
/**
* 变更审核确认审批通过流程-不减免手续费
*/
public static String ORDER_CHANGE_CONFIRM_APPROVED_SUCCESS_NONE_REDUCTION_FLOW = "orderChangeConfirmApprovedSuccessNoneReductionFlow";
/**
* 取消审核确认审批拒绝流程
*/
public static String ORDER_CANCEL_CONFIRM_APPROVED_REJECT_FLOW = "orderCancelConfirmApprovedRejectFlow";
/**
* 变更审核确认审批拒绝流程
*/
public static String ORDER_CHANGE_CONFIRM_APPROVED_REJECT_FLOW = "orderChangeConfirmApprovedRejectFlow";
/**
* 创建审核确认审批拒绝流程
*/
public static String ORDER_CREATE_CONFIRM_APPROVED_REJECT_FLOW = "orderCreateConfirmApprovedRejectFlow";
/**
* 创建审核确认审批拒绝流程
*/
public static String ORDER_CREATE_CONFIRM_APPROVED_TIMEOUT_FLOW = "orderCreateConfirmApprovedTimeOutFlow";
/**
* 变更审核确认审批拒绝流程
*/
public static String ORDER_CHANGE_CONFIRM_APPROVED_TIMEOUT_FLOW = "orderChangeConfirmApprovedTimeOutFlow";
/**
* 取消审核确认审批拒绝流程
*/
public static String ORDER_CANCEL_CONFIRM_APPROVED_TIMEOUT_FLOW = "orderCancelApprovedTimeOutFlow";
/**
* 订单取消服务费减免审核确认流程
*/
public static String ORDER_CANCEL_SERVICE_CHARGE_REDUCE_CONFIRM_FLOW = "orderCancelServiceChargeReduceConfirmFlow";
/**
* 订单变更服务费减免审核确认流程
*/
public static String ORDER_CHANGE_SERVICE_CHARGE_REDUCE_CONFIRM_FLOW = "orderChangeServiceChargeReduceConfirmFlow";
public static String ORDER_CANCEL_APPROVED_TIMEOUT_NON_RSC_FLOW = "orderCancelApprovedTimeOutNonRscFlow";
public static String ORDER_CANCEL_APPROVED_TIMEOUT_FULL_RSC_FLOW = "orderCancelApprovedTimeOutFullRscFlow";
/**
* 手动同步行程流程
*/
public static String ORDER_MANUAL_SYNC_TRIP_FLOW = "orderManualSyncTripFlow";
/**
* 取消同步节点
*/
public static String ORDER_CANCEL_SYNC_TRIP_NODE = "orderManualSyncTripCancelNode";
/**
* 更新同步节点
*/
public static String ORDER_UPDATE_SYNC_TRIP_NODE = "orderManualSyncTripUpdateNode";
/**
* 创建同步节点
*/
public static String ORDER_CREATE_SYNC_TRIP_NODE = "orderManualSyncTripCreateNode";
}

View File

@@ -0,0 +1,39 @@
package com.deepinnet.tptradeprod.biz.service.flow.constants;
/**
* @author chenjiaju
* @since 2024-01-3 09:56:07
**/
public class TpOrderBizErrorConstant {
public static final String CREATE_ORDER_ERROR = "CREATE_ORDER_ERROR";
public static final String REFUND_ERROR = "REFUND_ERROR";
public static final String REFUND_CHECK_ERROR = "REFUND_CHECK_ERROR";
public static final String REFUND_BUTTON_SHOWABLE_ERROR = "REFUND_BUTTON_SHOWABLE_ERROR";
public static final String QUERY_AVAILABLE_REFUND_VOUCHER = "QUERY_AVAILABLE_REFUND_VOUCHER";
public static final String QUERY_AVAILABLE_RESCHEDULE_VOUCHER = "QUERY_AVAILABLE_RESCHEDULE_VOUCHER";
public static final String CALCULATE_REFUND_AMOUNT_ERROR = "CALCULATE_REFUND_AMOUNT_ERROR";
public static final String CONFIRM_ORDER_ERROR = "CONFIRM_ORDER_ERROR";
public static final String REDUCE_SERVICE_CHARGE_ERROR = "REDUCE_SERVICE_CHARGE_ERROR";
public static final String CREATE_ORDER_CHANGE_APPLY_ERROR = "CREATE_ORDER_CHANGE_APPLY_ERROR";
public static final String PAID_ERROR = "PAID_ERROR";
public static final String CHARTER_BUS_CANCEL_ORDER_ERROR = "CHARTER_BUS_CANCEL_ORDER_ERROR";
public static final String CHANGE_ORDER_ERROR = "CHANGE_ORDER_ERROR";
public static final String MANUAL_SYNC_TRIP_ERROR = "MANUAL_SYNC_TRIP_ERROR";
public static final String RESCHEDULE_ORDER_ERROR = "RESCHEDULE_ORDER_ERROR";
}

View File

@@ -0,0 +1,55 @@
package com.deepinnet.tptradeprod.biz.service.flow.context;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderAuditConfirmDTO;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderChangeApplyDetailVO;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.deepinnet.tptradeprod.common.vo.audit.TpProdAuditVO;
import lombok.Data;
/**
* <p>
* 订单审核确认上下文信息
* </p>
*
* @author xiehuaqiao
* @since 2023/11/21
*/
@Data
public class TpOrderAuditConfirmContext {
/**
* 订单确认审核请求对象
*/
private TpProdOrderAuditConfirmDTO confirmDTO;
/**
* 审核单详情信息
*/
private TpProdAuditVO tpProdAuditVO;
/**
* 全额退手续费审批单
*/
private TpProdAuditVO rscAuditVO;
/**
* 订单变更审核单详情信息
*/
private TpProdOrderChangeApplyDetailVO orderChangeApplyVO;
/**
* 订单详情信息
*/
private TpProdOrderDetailVO orderDetailVO;
/**
* 当前订单
*/
private TpProdOrderDetailVO nowOrder;
/**
* 父订单
*/
private TpProdOrderDetailVO parentOrder;
}

View File

@@ -0,0 +1,37 @@
package com.deepinnet.tptradeprod.biz.service.flow.context;
import com.deepinnet.tpconfigcore.common.vo.TpConfigItemVO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderChangeApplyCreatedDTO;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderChangeApplyDetailVO;
import lombok.Data;
import java.util.List;
/**
* <p>
* 订单变更申请单创建上下文信息
* </p>
*
* @author xiehuaqiao
* @since 2023/11/21
*/
@Data
public class TpOrderChangeApplyCreateContext {
/**
* 订单变更申请单创建入参
*/
private TpProdOrderChangeApplyCreatedDTO orderChangeApplyCreatedDTO;
/**
* 已经创建且有效的订单变更申请单,如果有不允许在创建
*/
private TpProdOrderChangeApplyDetailVO originOrderChangeApplyVO;
/**
* 已经创建的订单变更审核单
*/
private TpProdOrderChangeApplyDetailVO newOrderChangeApplyVO;
}

View File

@@ -0,0 +1,26 @@
package com.deepinnet.tptradeprod.biz.service.flow.context;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import lombok.Data;
/**
* <p>
*
* </p>
*
* @author chenjiaju
* @since 2024/1/10
*/
@Data
public class TpOrderManualSyncTripContext {
private String originalOrderNo;
private String tenantId;
private TpProdOrderDetailVO currentOrderDetail;
private TpProdOrderDetailVO parentOrderDetail;
}

View File

@@ -0,0 +1,29 @@
package com.deepinnet.tptradeprod.biz.service.flow.context;
import com.deepinnet.tptradeprod.common.dto.*;
import lombok.Data;
/**
* @author amos wong
* @create 2024/7/5 15:34
* @Description
*/
@Data
public class TpOrderRescheduleContext {
private String orderNo;
private String productCode;
private String tenantId;
/**
* 改签需要失效的凭证列表
*/
private TpProdOrderRescheduleInvalidVoucherDTO needInvalidVoucherDTO;
/**
* 改签支付成功参数
*/
private TpProdReschedulePaidSuccessDTO reschedulePaidSuccessDTO;
}

View File

@@ -0,0 +1,58 @@
package com.deepinnet.tptradeprod.biz.service.flow.context;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderAuditConfirmDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderServiceChargeReduceConfirmDTO;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderChangeApplyDetailVO;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.deepinnet.tptradeprod.common.vo.audit.TpProdAuditVO;
import lombok.Data;
/**
* <p>
* 订单全额减免服务费审批上下文
* </p>
*
* @author xiehuaqiao
* @since 2023/11/21
*/
@Data
public class TpOrderServiceChargeReduceContext {
/**
* 全额减免服务费审批入参对象
*/
private TpProdOrderServiceChargeReduceConfirmDTO reduceDTO;
/**
* 审核单详情信息
*/
private TpProdAuditVO tpProdAuditVO;
/**
* 首次审核确认时业务员的选择数据
*/
private TpProdOrderAuditConfirmDTO confirmDTO;
/**
* 订单变更审核单详情信息
*/
private TpProdOrderChangeApplyDetailVO orderChangeApplyVO;
/**
* 订单详情信息
*/
private TpProdOrderDetailVO orderDetailVO;
/**
* 当前订单
*/
private TpProdOrderDetailVO nowOrder;
/**
* 父订单
*/
private TpProdOrderDetailVO parentOrder;
}

View File

@@ -0,0 +1,29 @@
package com.deepinnet.tptradeprod.biz.service.flow.context;
import com.deepinnet.tptradeprod.common.dto.TpProdRefundApplyDTO;
import lombok.Data;
/**
* @author amos wong
* @create 2023/10/16 14:38
* @Description
*/
@Data
public class TpRefundTicketApplyContext {
/**
* 申请退票的入参
*/
private TpProdRefundApplyDTO refundApplyDTO;
/**
* 退票申请单号
*/
private String refundApplyOrderNo;
/**
* 退款结果
*/
private Boolean refundResult;
}

View File

@@ -0,0 +1,40 @@
package com.deepinnet.tptradeprod.biz.service.flow.context;
import com.deepinnet.tpproductcore.common.dto.product.TpProdDetailDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdVoucherDTO;
import com.deepinnet.tptradeprod.common.vo.*;
import lombok.Data;
import java.util.List;
/**
* @author amos wong
* @create 2024/7/17 17:21
* @Description
*/
@Data
public class TpRescheduleOrderContext {
private String orderNo;
private String tenantId;
private String productCode;
private Long applyTime;
private List<String> voucherNos;
private TpProdOrderDetailVO orderDetailVO;
private List<TpProdVoucherDTO> voucherList;
private TpProdDetailDTO prodDetailDTO;
private List<String> ruleExpressionList;
private TpQueryAvailableRescheduleVoucherDTO rescheduleVoucherDTO;
private String processType;
}

View File

@@ -0,0 +1,24 @@
package com.deepinnet.tptradeprod.biz.service.flow.context;
import com.deepinnet.tpcommoncore.common.service.template.email.TpEmailBaseTemplate;
import lombok.Data;
/**
* @author amos wong
* @create 2023/11/13 14:47
* @Description
*/
@Data
public class TpSendEmailContext {
/**
* 收件箱
*/
private String receiveEmail;
/**
* 邮件模板
*/
private TpEmailBaseTemplate emailTemplate;
}

View File

@@ -0,0 +1,24 @@
package com.deepinnet.tptradeprod.biz.service.flow.context;
import com.deepinnet.tpcommoncore.common.service.template.sms.user.TpSmsBaseTemplate;
import lombok.Data;
/**
* @author amos wong
* @create 2023/11/13 14:47
* @Description
*/
@Data
public class TpSendSmsContext {
/**
* 待发送的手机号
*/
private String mobile;
/**
* 短信模板
*/
private TpSmsBaseTemplate smsTemplate;
}

View File

@@ -0,0 +1,43 @@
package com.deepinnet.tptradeprod.biz.service.flow.context;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import lombok.Data;
/**
* <p>
* 用户取消订单下文信息
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@Data
public class TpUserCancelOrderContext {
/**
* 订单编号
*/
private String orderNo;
/**
* 租户ID
*/
private String tenantId;
/**
* 是否为B端用户操作
* true-B端用户操作 | false-C端用户操作
*/
private Boolean backendUserOperation = Boolean.FALSE;
/**
* 后台操作人员编号
*/
private String backendUserNo;
/**
* 订单详情
*/
private TpProdOrderDetailVO orderDetail;
}

View File

@@ -0,0 +1,121 @@
package com.deepinnet.tptradeprod.biz.service.flow.context;
import com.deepinnet.tpproductcore.common.dto.product.TpProdDetailDTO;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.vo.*;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* <p>
* 用户下单上下文信息
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@Data
public class TpUserPlaceOrderContext {
/**
* 订单编号
*/
private String orderNo;
/**
* 租户ID
*/
private String tenantId;
/**
* 用户
*/
private String userNo;
/**
* 支付时间
*/
private Long payTime;
/**
* 业务类型
*/
private String bizType;
/**
* 需支付金额
*/
private String payAmount;
/**
* 收银台地址
*/
private String payCashierUrl;
/**
* 是否自动审核(无需审核时自动审核)
*/
private Boolean autoAudit;
/**
* 是否是变更订单
*/
private boolean isChangeOrder;
/**
* 订单变更是否需要审核
*/
private Boolean changeOrderNeedAudit;
/**
* 订金支付比例
*/
private BigDecimal percentage;
/**
* 创建订单dto
*/
private TpProdOrderCreateDTO createDTO;
/**
* 产品详情dto
*/
private TpProdDetailDTO productDTO;
/**
* 订单详情
*/
private TpProdOrderDetailVO orderDetailVO;
/**
* 内部价
*/
private String internalPrice;
/**
* 后台人员编号
*/
private String backendUserNo;
/**
* 订单改签上下文
*/
private TpOrderRescheduleContext orderRescheduleContext;
/**
* 订单变更审核记录
*/
private List<TpProdOrderChangeApplyListVO> orderChangeApplyList;
/**
* 改签参数
*/
private TpProdOrderRescheduleDTO orderRescheduleDTO;
/**
* 处理流程类型
*/
private String processType;
}

View File

@@ -0,0 +1,599 @@
package com.deepinnet.tptradeprod.biz.service.flow.manager;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpbaseopcore.common.dto.account.AccountDTO;
import com.deepinnet.tpproductcore.common.dto.product.TpProdDetailDTO;
import com.deepinnet.tptradecore.common.dto.order.TpOrderChargeRecordDTO;
import com.deepinnet.tptradecore.common.dto.order.TpOrderPushStatusDTO;
import com.deepinnet.tptradecore.common.enums.order.*;
import com.deepinnet.tptradeprod.biz.service.flow.constants.LiteFlowConstant;
import com.deepinnet.tptradeprod.biz.service.flow.context.*;
import com.deepinnet.tptradeprod.biz.service.flow.refundTicket.context.*;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.enums.*;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.deepinnet.tptradeprod.common.service.integration.client.TpAccountClient;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.vo.*;
import com.google.common.collect.Lists;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import static com.deepinnet.tptradeprod.biz.service.flow.constants.TpOrderBizErrorConstant.*;
/**
* @author amos wong
* @create 2023/10/16 14:22
* @Description
*/
@Service
public class LiteFlowManager {
@Resource
private FlowExecutor flowExecutor;
@Resource
private RedissonClient redissonClient;
@Resource
private TpOrderClient tpOrderClient;
@Resource
private TpAccountClient tpAccountClient;
public String refundTicket(TpProdRefundApplyDTO refundApplyDTO) {
TpRefundTicketCommonContext commonContext = new TpRefundTicketCommonContext();
TpRefundTicketApplyContext context = new TpRefundTicketApplyContext();
TpRefundTicketCommonRequest commonRequest = new TpRefundTicketCommonRequest();
commonRequest.setOrderNo(refundApplyDTO.getOrderNo());
commonRequest.setTenantId(refundApplyDTO.getTenantId());
commonRequest.setUserNo(refundApplyDTO.getUserNo());
commonRequest.setApplyTime(refundApplyDTO.getApplyTime());
commonRequest.setProductCategoryNo(refundApplyDTO.getProductCategoryNo());
commonRequest.setProductNo(refundApplyDTO.getProductCode());
commonRequest.setTripType(refundApplyDTO.getTripType());
context.setRefundApplyDTO(refundApplyDTO);
commonContext.setProcessType(TpFlowProcessTypeEnum.REFUND_TICKET);
commonContext.setRefundTicketApplyContext(context);
commonContext.setCommonRequest(commonRequest);
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.REFUND_TICKET_FLOW, null, commonContext);
checkResponseResult(response, REFUND_ERROR);
return context.getRefundApplyOrderNo();
}
public TpProdCalculateRefundAmountVO calculateRefundTicketAmount(TpProdCalculateRefundAmountDTO calculateRefundAmountDTO) {
TpRefundTicketCommonContext commonContext = new TpRefundTicketCommonContext();
TpCalculateRefundAmountContext context = new TpCalculateRefundAmountContext();
context.setCalculateRefundAmountDTO(calculateRefundAmountDTO);
TpRefundTicketCommonRequest commonRequest = new TpRefundTicketCommonRequest();
commonRequest.setOrderNo(calculateRefundAmountDTO.getOrderNo());
commonRequest.setTenantId(calculateRefundAmountDTO.getTenantId());
commonRequest.setUserNo(calculateRefundAmountDTO.getUserNo());
commonRequest.setProductNo(calculateRefundAmountDTO.getProductNo());
commonRequest.setTripType(calculateRefundAmountDTO.getTripType());
commonContext.setCalculateRefundAmountContext(context);
commonContext.setProcessType(TpFlowProcessTypeEnum.CALCULATE_REFUND_AMOUNT);
commonContext.setCommonRequest(commonRequest);
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.CALCULATE_REFUND_TICKET_AMOUNT_FLOW, null, commonContext);
checkResponseResult(response, CALCULATE_REFUND_AMOUNT_ERROR);
return context.getCalculateRefundAmountVO();
}
public Boolean refundAvailableCheck(TpProdRefundAvailableCheckDTO refundAvailableCheckDTO) {
TpRefundTicketCommonContext commonContext = new TpRefundTicketCommonContext();
TpRefundTicketCheckContext checkContext = new TpRefundTicketCheckContext();
checkContext.setRefundAvailableCheckDTO(refundAvailableCheckDTO);
TpRefundTicketCommonRequest commonRequest = new TpRefundTicketCommonRequest();
commonRequest.setProductNo(refundAvailableCheckDTO.getProductCode());
commonRequest.setUserNo(refundAvailableCheckDTO.getUserNo());
commonRequest.setTenantId(refundAvailableCheckDTO.getTenantId());
commonRequest.setOrderNo(refundAvailableCheckDTO.getOrderNo());
commonRequest.setApplyTime(System.currentTimeMillis());
commonContext.setProcessType(TpFlowProcessTypeEnum.REFUND_TICKET_CHECK);
commonContext.setRefundTicketCheckContext(checkContext);
commonContext.setCommonRequest(commonRequest);
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.REFUND_AVAILABLE_CHECK_FLOW, null, commonContext);
checkResponseResult(response, REFUND_CHECK_ERROR);
return response.isSuccess();
}
public TpQueryAvailableRescheduleVoucherDTO queryAvailableRescheduleVoucherList(TpProdQueryAvailableRescheduleVoucherDTO queryAvailableRescheduleVoucherDTO) {
TpRescheduleOrderContext rescheduleOrderContext = new TpRescheduleOrderContext();
rescheduleOrderContext.setOrderNo(queryAvailableRescheduleVoucherDTO.getOrderNo());
rescheduleOrderContext.setTenantId(queryAvailableRescheduleVoucherDTO.getTenantId());
rescheduleOrderContext.setProductCode(queryAvailableRescheduleVoucherDTO.getProductCode());
rescheduleOrderContext.setTenantId(queryAvailableRescheduleVoucherDTO.getTenantId());
rescheduleOrderContext.setApplyTime(queryAvailableRescheduleVoucherDTO.getApplyTime());
rescheduleOrderContext.setOrderDetailVO(queryAvailableRescheduleVoucherDTO.getOrderDetailVO());
rescheduleOrderContext.setProcessType(queryAvailableRescheduleVoucherDTO.getProcessType());
rescheduleOrderContext.setVoucherNos(queryAvailableRescheduleVoucherDTO.getVoucherNos());
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.QUERY_AVAILABLE_RESCHEDULE_VOUCHERS, null, rescheduleOrderContext);
checkResponseResult(response, QUERY_AVAILABLE_RESCHEDULE_VOUCHER);
return rescheduleOrderContext.getRescheduleVoucherDTO();
}
public Boolean checkRefundTicketButtonShowable(TpProdShowRefundButtonCheckDTO showRefundButtonCheckDTO) {
TpRefundTicketCommonContext commonContext = new TpRefundTicketCommonContext();
TpRefundTicketButtonShowableContext showableContext = new TpRefundTicketButtonShowableContext();
showableContext.setShowRefundButtonCheckDTO(showRefundButtonCheckDTO);
TpRefundTicketCommonRequest commonRequest = new TpRefundTicketCommonRequest();
commonRequest.setProductNo(showRefundButtonCheckDTO.getProductCode());
commonRequest.setUserNo(showRefundButtonCheckDTO.getUserNo());
commonRequest.setTenantId(showRefundButtonCheckDTO.getTenantId());
commonRequest.setOrderNo(showRefundButtonCheckDTO.getOrderNo());
commonRequest.setApplyTime(System.currentTimeMillis());
commonContext.setProcessType(TpFlowProcessTypeEnum.REFUND_BUTTON_SHOWABLE);
commonContext.setTicketButtonShowableContext(showableContext);
commonContext.setCommonRequest(commonRequest);
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.REFUND_BUTTON_SHOWABLE_FLOW, null, commonContext);
checkResponseResult(response, REFUND_BUTTON_SHOWABLE_ERROR);
return commonContext.getTicketButtonShowableContext().getShowable();
}
public List<TpProdVoucherDTO> queryAvailableRefundVouchers(TpProdQueryAvailableRefundVoucherDTO queryDTO) {
TpRefundTicketCommonContext commonContext = new TpRefundTicketCommonContext();
TpQueryAvailableVoucherContext queryAvailableVoucherContext = new TpQueryAvailableVoucherContext();
queryAvailableVoucherContext.setQueryDTO(queryDTO);
TpRefundTicketCommonRequest commonRequest = new TpRefundTicketCommonRequest();
commonRequest.setProductNo(queryDTO.getProductNo());
commonRequest.setApplyTime(System.currentTimeMillis());
commonRequest.setTenantId(queryDTO.getTenantId());
commonRequest.setOrderNo(queryDTO.getOrderNo());
commonContext.setCommonRequest(commonRequest);
commonContext.setProcessType(TpFlowProcessTypeEnum.QUERY_AVAILABLE_REFUND_VOUCHER);
commonContext.setQueryAvailableVoucherContext(queryAvailableVoucherContext);
commonContext.setCommonRequest(commonRequest);
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.QUERY_AVAILABLE_REFUND_VOUCHERS, null, commonContext);
List<TpProdVoucherDTO> availableRefundVoucherList = queryAvailableVoucherContext.getAvailableRefundVoucherList();
List<TpProdVoucherDTO> needRemoveVoucherList = Lists.newArrayList();
List<Boolean> ruleCheckResultList = queryAvailableVoucherContext.getRuleCheckResultList();
if (CollectionUtils.isEmpty(availableRefundVoucherList)) {
return null;
}
// 不需要经过规则域的退票时间校验
if (CollectionUtils.isEmpty(ruleCheckResultList)) {
return availableRefundVoucherList;
}
for (int i = 0; i < ruleCheckResultList.size(); i++) {
Boolean checkResult = ruleCheckResultList.get(i);
if (!checkResult) {
TpProdVoucherDTO voucherDTO = availableRefundVoucherList.get(i);
needRemoveVoucherList.add(voucherDTO);
}
}
if (CollectionUtils.isNotEmpty(needRemoveVoucherList)) {
availableRefundVoucherList.removeAll(needRemoveVoucherList);
}
return availableRefundVoucherList;
}
/**
* 创建订单流程执行入口
* <p>
* 流程一: 下单 -> 产品信息校验 -> 是否需要询价 -> 是 —> 创建订单 -> 冻结库存 -> 结束
* </p>
* <p>
* 流程二: 下单 -> 产品信息校验 -> 是否需要询价 -> 否 -> 创建订单 -> 冻结库存 -> 推进订单支付状态 -> 生成凭证 -> 扣减库存 -> 结束
* </p>
*
* @param createDTO 创建订单参数
* @return 创建订单后返回订单编号
*/
public TpProdOrderCreateVO createOrder(TpProdOrderCreateDTO createDTO) {
TpUserPlaceOrderContext tpUserPlaceOrderContext = new TpUserPlaceOrderContext();
tpUserPlaceOrderContext.setCreateDTO(createDTO);
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.USER_PLACE_ORDER_FLOW, null, tpUserPlaceOrderContext);
// 校验执行结果
checkResponseResult(response, CREATE_ORDER_ERROR);
TpProdOrderCreateVO tpProdOrderCreateVO = new TpProdOrderCreateVO();
tpProdOrderCreateVO.setOrderNo(createDTO.getOrderNo());
tpProdOrderCreateVO.setOriginalOrderNo(createDTO.getOriginalOrderNo());
tpProdOrderCreateVO.setFee(createDTO.getPayAmount());
tpProdOrderCreateVO.setPayableAmount(createDTO.getPayableAmount());
tpProdOrderCreateVO.setCreateTime(createDTO.getOrderTime());
tpProdOrderCreateVO.setPayCashierUrl(tpUserPlaceOrderContext.getPayCashierUrl());
return tpProdOrderCreateVO;
}
/**
* 订单确认审核执行入口
*
* @param confirmDTO 创建订单参数
* @return 创建订单后返回订单编号
*/
public Boolean confirmOrder(TpProdOrderAuditConfirmDTO confirmDTO) {
String lockBizNo = confirmDTO.getOriginalOrderNo() + ":" + confirmDTO.getTenantId() + ":co";
RLock lock = redissonClient.getLock(lockBizNo);
boolean tryLock = lock.tryLock();
// 判断是否获取到当锁
if (!tryLock) {
LogUtil.error("重复提交:{}", JSONObject.toJSONString(confirmDTO));
throw new TpTradeProdException(TpTradeProdErrorCode.IDEMPOTENT_REQUEST_ERROR);
}
try {
LogUtil.info("获取到订单审核锁,锁定业务单号:{}", lockBizNo);
if (StrUtil.isEmpty(confirmDTO.getReductionServiceChargeType())) {
confirmDTO.setReductionServiceChargeType(TpOrderReductionServiceChargeTypeEnum.NON_REDUCTION.getBizType());
}
TpOrderAuditConfirmContext tpOrderAuditConfirmContext = new TpOrderAuditConfirmContext();
tpOrderAuditConfirmContext.setConfirmDTO(confirmDTO);
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.ORDER_AUDIT_CONFIRM_FLOW, null, tpOrderAuditConfirmContext, new TpSendSmsContext());
// 校验执行结果
checkResponseResult(response, CONFIRM_ORDER_ERROR);
return Boolean.TRUE;
} catch (Exception e) {
LogUtil.error("订单确认审核失败:", e);
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_AUDIT_CONFIRM_ERROR);
} finally {
// 释放锁
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
/**
* 减免手续费处理流程
*
* @param reduceDTO 创建订单参数
* @return 处理结果
*/
public Boolean reduceFullServiceCharge(TpProdOrderServiceChargeReduceConfirmDTO reduceDTO) {
String lockBizNo = reduceDTO.getOriginalOrderNo() + ":" + reduceDTO.getTenantId() + ":rsc";
RLock lock = redissonClient.getLock(lockBizNo);
boolean tryLock = lock.tryLock();
// 判断是否获取到当锁
if (!tryLock) {
LogUtil.error("重复提交:{}", JSONObject.toJSONString(reduceDTO));
throw new TpTradeProdException(TpTradeProdErrorCode.IDEMPOTENT_REQUEST_ERROR);
}
try {
LogUtil.info("获取到锁,锁定对象:{}", lockBizNo);
TpOrderServiceChargeReduceContext serviceChargeReduceContext = new TpOrderServiceChargeReduceContext();
serviceChargeReduceContext.setReduceDTO(reduceDTO);
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.ORDER_SERVICE_CHARGE_REDUCE_FLOW, null, serviceChargeReduceContext);
// 校验执行结果
checkResponseResult(response, REDUCE_SERVICE_CHARGE_ERROR);
return Boolean.TRUE;
} catch (Exception e) {
LogUtil.error("全额减免服务费审核处理失败:", e);
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_FULL_RSC_AUDIT_CONFIRM_ERROR);
} finally {
// 释放锁
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
public Boolean createOrderChangeApply(TpProdOrderChangeApplyCreatedDTO orderChangeApplyCreatedDTO) {
String lockBizNo = orderChangeApplyCreatedDTO.getOriginalOrderNo() + ":" + orderChangeApplyCreatedDTO.getApplyType();
RLock lock = redissonClient.getLock(lockBizNo);
boolean tryLock = lock.tryLock();
// 判断是否获取到当锁
if (!tryLock) {
LogUtil.error("重复提交:{}", JSONObject.toJSONString(orderChangeApplyCreatedDTO));
throw new TpTradeProdException(TpTradeProdErrorCode.IDEMPOTENT_REQUEST_ERROR);
}
try {
LogUtil.info("创单组件获取到锁,锁定对象:{}", lockBizNo);
if (StrUtil.isEmpty(orderChangeApplyCreatedDTO.getApplyStatus())) {
orderChangeApplyCreatedDTO.setApplyStatus(TpOrderChangeApplyStatusEnum.WAITING_APPROVED.getType());
}
if (orderChangeApplyCreatedDTO.getApplyTime() == null) {
orderChangeApplyCreatedDTO.setApplyTime(DateUtil.current());
}
if (orderChangeApplyCreatedDTO.getOrderChangeApplicant() == null) {
TpProdOrderChangeApplicantCreatedDTO orderChangeApplicant = new TpProdOrderChangeApplicantCreatedDTO();
orderChangeApplicant.setApplicantNo("sysadmin");
orderChangeApplicant.setApplicantName("sysadmin");
orderChangeApplyCreatedDTO.setOrderChangeApplicant(orderChangeApplicant);
}
//如果是B端用户填充名称、手机号
if (StrUtil.equals(orderChangeApplyCreatedDTO.getOrderScene(), TpOrderSceneEnum.SALESMAN_OPERATE.getCode())) {
TpProdOrderChangeApplicantCreatedDTO orderChangeApplicantCreatedDTO = orderChangeApplyCreatedDTO.getOrderChangeApplicant();
AccountDTO accountDTO = tpAccountClient.getByAccountId(Long.parseLong(orderChangeApplicantCreatedDTO.getApplicantNo()));
if (accountDTO != null) {
orderChangeApplicantCreatedDTO.setApplicantName(accountDTO.getName());
orderChangeApplicantCreatedDTO.setApplicantPhone(accountDTO.getPhone());
}
}
TpOrderChangeApplyCreateContext orderChangeApplyCreateContext = new TpOrderChangeApplyCreateContext();
orderChangeApplyCreateContext.setOrderChangeApplyCreatedDTO(orderChangeApplyCreatedDTO);
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.ORDER_APPLY_CREATE_FLOW, null, orderChangeApplyCreateContext);
// 校验执行结果
checkResponseResult(response, CREATE_ORDER_CHANGE_APPLY_ERROR);
return Boolean.TRUE;
} catch (Exception e) {
LogUtil.error("创建订单变更申请单失败:", e);
return Boolean.FALSE;
} finally {
// 释放锁
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
/**
* 用户支付成功执行流程入口
* 流程:推进订单支付状态 -> 生成凭证 -> 扣减库存 -> 结束
*
* @param tpProdOrderPaidDTO 支付成功入参
*/
public void paid(TpProdOrderPaidDTO tpProdOrderPaidDTO, TpProdOrderDetailVO orderDetail, TpProdDetailDTO productDetailDTO) {
TpUserPlaceOrderContext tpUserPlaceOrderContext = buildPaidFlowContext(tpProdOrderPaidDTO, orderDetail, productDetailDTO);
TpOrderTypeEnum orderBizTypeEnum = TpOrderTypeEnum.getBizTypeByCode(orderDetail.getType());
if (ObjectUtil.isNull(orderBizTypeEnum)) {
LogUtil.error("未知的业务类型");
throw new TpTradeProdException(TpTradeProdErrorCode.PRODUCT_BUSINESS_TYPE_ERROR);
}
LiteflowResponse response;
switch (orderBizTypeEnum) {
case CUSTOMIZED_ORDER:
response = flowExecutor.execute2Resp(LiteFlowConstant.USER_PAID_ORDER_FLOW, null, tpUserPlaceOrderContext);
break;
case PACKING_ORDER:
response = flowExecutor.execute2Resp(LiteFlowConstant.USER_CHARTER_BUS_PAID_ORDER_FLOW, null, tpUserPlaceOrderContext);
break;
case CARPOOL_ORDER:
response = flowExecutor.execute2Resp(LiteFlowConstant.USER_CARPOOL_BUS_PAID_ORDER_FLOW, null, tpUserPlaceOrderContext);
break;
default:
LogUtil.error("当前订单:{}, 类型错误, 未分配流程引擎", orderDetail.getOrderNo());
throw new TpTradeProdException(TpTradeProdErrorCode.PRODUCT_BUSINESS_TYPE_ERROR);
}
// 校验执行结果
checkResponseResult(response, PAID_ERROR);
}
@NotNull
private static TpUserPlaceOrderContext buildPaidFlowContext(TpProdOrderPaidDTO tpProdOrderPaidDTO, TpProdOrderDetailVO orderDetail, TpProdDetailDTO productDetailDTO) {
TpUserPlaceOrderContext tpUserPlaceOrderContext = new TpUserPlaceOrderContext();
tpUserPlaceOrderContext.setOrderNo(orderDetail.getOrderNo());
tpUserPlaceOrderContext.setTenantId(tpProdOrderPaidDTO.getTenantId());
tpUserPlaceOrderContext.setPayTime(tpProdOrderPaidDTO.getPayTime());
tpUserPlaceOrderContext.setBizType(tpProdOrderPaidDTO.getBizType());
tpUserPlaceOrderContext.setOrderDetailVO(orderDetail);
tpUserPlaceOrderContext.setProductDTO(productDetailDTO);
return tpUserPlaceOrderContext;
}
/**
* 预约包车取消订单
*
* @param dto 取消订单入参
*/
public Boolean charterBusCancelOrder(TpOrderCancelDTO dto) {
// 查询订单详情 查询包车订单
TpProdOrderDetailVO orderDetail = tpOrderClient.getOrderDetail(TpProdOrderQueryDTO.builder()
.originalOrderNo(dto.getOriginalOrderNo())
.tenantId(dto.getTenantId())
.needModules(ListUtil.toList(TpOrderModulesEnum.ORDER_TRAVEL_TRIP.getModule(), TpOrderModulesEnum.ORDER_PLACER.getModule(), TpOrderModulesEnum.ORDER_REQUIREMENT_USER.getModule())).build());
if (orderDetail.getStatus().compareTo(TpOrderStatusEnum.ORDER_CHANGE_AUDITED.getStatus()) <= 0
&& orderDetail.getStatus().compareTo(TpOrderStatusEnum.ORDER_TRIP_START.getStatus()) >= 0) {
LogUtil.error("当前订单:{}, 无法取消, 订单状态:{}", orderDetail.getOrderNo(), orderDetail.getStatus());
throw new TpTradeProdException(TpTradeProdErrorCode.INVALID_ORDER_STATUS);
}
Long expireTime = orderDetail.getExpireTime();
if (expireTime <= System.currentTimeMillis()) {
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_CANCEL_ERROR_NOT_ALLOW_TIME);
}
// 当前订单如为待确认,取消订单无需判断是否需审核,直接更改为取消
if (ObjectUtil.equals(orderDetail.getStatus(), TpOrderStatusEnum.ORDER_NEED_CONFIRM.getStatus())
|| ObjectUtil.equals(orderDetail.getStatus(), TpOrderStatusEnum.ORDER_DEPOSIT_NEED_PAY.getStatus())) {
// 新增取消的价格记录
tpOrderClient.saveChargeRecord(buildSaveChargeRecordDTO(orderDetail, dto.getTenantId()));
// 取消订单
tpOrderClient.pushOrderStatus(TpOrderPushStatusDTO.builder()
.orderNo(orderDetail.getOrderNo())
.tenantId(dto.getTenantId())
.tpOrderPushStatusEnum(TpOrderPushStatusEnum.ORDER_CANCELED).build());
return Boolean.TRUE;
}
TpUserCancelOrderContext tpUserCancelOrderContext = new TpUserCancelOrderContext();
tpUserCancelOrderContext.setOrderNo(orderDetail.getOrderNo());
tpUserCancelOrderContext.setOrderDetail(orderDetail);
tpUserCancelOrderContext.setBackendUserOperation(dto.getBackendUserOperation());
tpUserCancelOrderContext.setBackendUserNo(dto.getBackendUserNo());
tpUserCancelOrderContext.setTenantId(dto.getTenantId());
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.USER_CHARTER_BUS_CANCEL_ORDER_FLOW, null, tpUserCancelOrderContext);
// 校验执行结果
checkResponseResult(response, CHARTER_BUS_CANCEL_ORDER_ERROR);
return Boolean.TRUE;
}
private static TpOrderChargeRecordDTO buildSaveChargeRecordDTO(TpProdOrderDetailVO orderDetail, String tenantId) {
TpOrderChargeRecordDTO tpOrderChargeRecordDTO = new TpOrderChargeRecordDTO();
tpOrderChargeRecordDTO.setOrderNo(orderDetail.getOrderNo());
tpOrderChargeRecordDTO.setOriginalOrderNo(orderDetail.getOriginalOrderNo());
tpOrderChargeRecordDTO.setBizType(TpAuditOrChangePriceBizTypeEnum.CANCEL_ORDER.getBizType());
tpOrderChargeRecordDTO.setTenantId(tenantId);
return tpOrderChargeRecordDTO;
}
public TpProdOrderEndorseCreateVO changeOrder(TpProdOrderCreateDTO createDTO) {
TpUserPlaceOrderContext tpUserPlaceOrderContext = new TpUserPlaceOrderContext();
tpUserPlaceOrderContext.setCreateDTO(createDTO);
tpUserPlaceOrderContext.setOrderNo(createDTO.getOrderNo());
tpUserPlaceOrderContext.setTenantId(createDTO.getTenantId());
tpUserPlaceOrderContext.setUserNo(createDTO.getUserNo());
tpUserPlaceOrderContext.setPayAmount(createDTO.getPayAmount());
tpUserPlaceOrderContext.setChangeOrder(true);
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.USER_CHANGE_ORDER_FLOW, null, tpUserPlaceOrderContext);
// 校验执行结果
checkResponseResult(response, CHANGE_ORDER_ERROR);
TpProdOrderEndorseCreateVO tpProdOrderEndorseCreateVO = new TpProdOrderEndorseCreateVO();
tpProdOrderEndorseCreateVO.setOrderNo(tpUserPlaceOrderContext.getOrderNo());
tpProdOrderEndorseCreateVO.setOriginalOrderNo(createDTO.getOriginalOrderNo());
tpProdOrderEndorseCreateVO.setFee(createDTO.getPayAmount());
tpProdOrderEndorseCreateVO.setCreateTime(createDTO.getOrderTime());
tpProdOrderEndorseCreateVO.setPayCashierUrl(tpUserPlaceOrderContext.getPayCashierUrl());
return tpProdOrderEndorseCreateVO;
}
private TpOrderChargeRecordDTO buildRemoveChargeRecord(String orderNo, String tenantId, String bizType) {
TpOrderChargeRecordDTO tpOrderChargeRecordDTO = new TpOrderChargeRecordDTO();
tpOrderChargeRecordDTO.setOrderNo(orderNo);
tpOrderChargeRecordDTO.setBizType(bizType);
tpOrderChargeRecordDTO.setTenantId(tenantId);
return tpOrderChargeRecordDTO;
}
private void checkResponseResult(LiteflowResponse response, String bizError) {
if (!response.isSuccess()) {
Exception cause = response.getCause();
LogUtil.error("异常堆栈信息:{}", cause);
if (cause instanceof TpTradeProdException) {
throw (TpTradeProdException) cause;
} else {
exceptionBizCheck(bizError);
}
}
}
private static void exceptionBizCheck(String bizError) {
switch (bizError) {
case CREATE_ORDER_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.BUY_ERROR);
case REFUND_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.REFUND_ERROR);
case CALCULATE_REFUND_AMOUNT_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.CALCULATE_REFUND_AMOUNT_ERROR);
case REFUND_CHECK_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.REFUND_CHECK_ERROR);
case REFUND_BUTTON_SHOWABLE_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.REFUND_BUTTON_SHOWABLE_ERROR);
case CONFIRM_ORDER_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_AUDIT_CONFIRM_ERROR);
case REDUCE_SERVICE_CHARGE_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.REDUCE_SERVICE_CHARGE_ERROR);
case CREATE_ORDER_CHANGE_APPLY_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.CREATE_ORDER_CHANGE_APPLY_ERROR);
case PAID_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.PAY_MESSAGE_CONSUME_ERROR);
case CHARTER_BUS_CANCEL_ORDER_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_CANCEL_ERROR);
case CHANGE_ORDER_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_CHANGE_ERROR);
case MANUAL_SYNC_TRIP_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.TRIP_SYNC_ERROR);
case RESCHEDULE_ORDER_ERROR:
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_RESCHEDULE_ERROR);
default:
throw new TpTradeProdException(TpTradeProdErrorCode.INTERNAL_SERVER_ERROR);
}
}
/**
* 手动同步行程
*
* @param dto 查询参数
* @return 是否同步成功
*/
public Boolean manualSyncTrip(TpProdOrderQueryDTO dto) {
TpOrderManualSyncTripContext syncTripContext = new TpOrderManualSyncTripContext();
syncTripContext.setOriginalOrderNo(dto.getOriginalOrderNo());
syncTripContext.setTenantId(dto.getTenantId());
// 查询订单详情 查询包车订单
TpProdOrderDetailVO orderDetail = tpOrderClient.getOrderDetail(TpProdOrderQueryDTO.builder()
.originalOrderNo(dto.getOriginalOrderNo())
.tenantId(dto.getTenantId())
.needModules(ListUtil.toList(TpOrderModulesEnum.ORDER_TRAVEL_TRIP.getModule(), TpOrderModulesEnum.ORDER_SUBJECT_ITEM.getModule())).build());
syncTripContext.setCurrentOrderDetail(orderDetail);
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.ORDER_MANUAL_SYNC_TRIP_FLOW, null, syncTripContext);
// 校验执行结果
checkResponseResult(response, MANUAL_SYNC_TRIP_ERROR);
return Boolean.TRUE;
}
/**
* 定制公交改签订单
* @param dto 改签参数
* @return 改签后结果返回
*/
public TpProdOrderCreateVO rescheduleOrder(TpProdOrderRescheduleDTO dto) {
TpProdOrderCreateDTO createDTO = dto.getCreateOrderDto();
TpUserPlaceOrderContext userPlaceOrderContext = new TpUserPlaceOrderContext();
userPlaceOrderContext.setCreateDTO(createDTO);
userPlaceOrderContext.setOrderDetailVO(dto.getOrderDetail());
userPlaceOrderContext.setOrderRescheduleDTO(dto);
userPlaceOrderContext.setTenantId(dto.getTenantId());
userPlaceOrderContext.setProcessType(TpFlowProcessTypeEnum.CONFIRM_RESCHEDULE_ORDER.getCode());
LiteflowResponse response = flowExecutor.execute2Resp(LiteFlowConstant.USER_RESCHEDULE_FLOW, null, userPlaceOrderContext);
// 校验执行结果
checkResponseResult(response, RESCHEDULE_ORDER_ERROR);
TpProdOrderCreateVO tpProdOrderCreateVO = new TpProdOrderCreateVO();
tpProdOrderCreateVO.setOrderNo(createDTO.getOrderNo());
tpProdOrderCreateVO.setOriginalOrderNo(createDTO.getOriginalOrderNo());
tpProdOrderCreateVO.setFee(createDTO.getPayAmount());
tpProdOrderCreateVO.setPayableAmount(createDTO.getPayableAmount());
tpProdOrderCreateVO.setCreateTime(createDTO.getOrderTime());
return tpProdOrderCreateVO;
}
}

View File

@@ -0,0 +1,52 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderPriceRecordDTO;
import com.deepinnet.tptradeprod.core.compoment.TpCharterBusInquireComponent;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
import java.util.List;
/**
* <p>
* 预约包车询价节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "charterBusInquireCheckNode", name = "预约包车询价节点")
@LiteflowCmpDefine
@RequiredArgsConstructor
public class TpCharterBusInquireCheckNode {
private final TpCharterBusInquireComponent tpCharterBusInquireComponent;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 预约包车询价");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
List<TpProdOrderPriceRecordDTO> tpProdOrderPriceRecordDTOS = checkPrice(createDTO);
// 询价 & 价格校验
createDTO.setTpOrderPriceRecords(tpProdOrderPriceRecordDTOS);
// 设置支付比例
userPlaceOrderContext.setPercentage(tpProdOrderPriceRecordDTOS.get(0).getPayPercentage());
}
private List<TpProdOrderPriceRecordDTO> checkPrice(TpProdOrderCreateDTO createDTO) {
return tpCharterBusInquireComponent.execute(createDTO);
}
}

View File

@@ -0,0 +1,46 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import com.alibaba.fastjson2.JSONObject;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.core.compoment.TpCharterBusInquireComponent;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
import java.util.List;
/**
* <p>
* 预约包车内部询价节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "charterBusInternalPriceInquireNode", name = "预约包车内部询价节点")
@LiteflowCmpDefine
@RequiredArgsConstructor
public class TpCharterBusInternalPriceInquireNode {
private final TpCharterBusInquireComponent tpCharterBusInquireComponent;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 预约包车内部询价节点");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
userPlaceOrderContext.setInternalPrice(getInternalPrice(createDTO));
}
private String getInternalPrice(TpProdOrderCreateDTO createDTO) {
return tpCharterBusInquireComponent.inquireInternalPrice(JSONObject.toJSONString(createDTO.getInquireParams()));
}
}

View File

@@ -0,0 +1,44 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderPriceRecordDTO;
import com.deepinnet.tptradeprod.core.compoment.TpInquireComponent;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.RequiredArgsConstructor;
import java.math.BigDecimal;
import java.util.List;
/**
* <p>
* 公开线路免费票判断节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "freeTicketCheckNode", name = "公开线路免费票判断节点")
@LiteflowCmpDefine(value = NodeTypeEnum.IF)
@RequiredArgsConstructor
public class TpFreeTicketCheckNode {
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_IF)
public boolean process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 公开线路免费票判断节点");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
// 询价后判断价格是否为0
// 如果为0说明该票折扣后为0元无需拉收银台
return new BigDecimal(createDTO.getPayAmount()).compareTo(BigDecimal.ZERO) == 0 ? Boolean.TRUE : Boolean.FALSE;
}
}

View File

@@ -0,0 +1,47 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderPriceRecordDTO;
import com.deepinnet.tptradeprod.core.compoment.TpInquireComponent;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
import java.util.List;
/**
* <p>
* 询价节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "inquireCheckNode", name = "询价节点")
@LiteflowCmpDefine
@RequiredArgsConstructor
public class TpInquireCheckNode {
private final TpInquireComponent tpInquireComponent;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 询价");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
// 询价 & 价格校验
createDTO.setTpOrderPriceRecords(checkPrice(createDTO));
}
private List<TpProdOrderPriceRecordDTO> checkPrice(TpProdOrderCreateDTO createDTO) {
return tpInquireComponent.execute(createDTO);
}
}

View File

@@ -0,0 +1,74 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradecore.common.enums.order.TpOrderModulesEnum;
import com.deepinnet.tptradeprod.biz.service.flow.constants.LiteFlowConstant;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpOrderAuditConfirmContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderAuditConfirmDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderQueryDTO;
import com.deepinnet.tptradeprod.common.enums.TpOrderStatusEnum;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.RequiredArgsConstructor;
/**
* <p>
* 审核改价后判断当前订单状态
* 1.首次审核成功
* 2.变更订单
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "orderAuditCheckOrderStatusNode", name = "审核改价后判断当前订单状态")
@LiteflowCmpDefine(value = NodeTypeEnum.SWITCH)
@RequiredArgsConstructor
public class TpOrderAuditCheckOrderStatusNode {
private final TpOrderClient tpOrderClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_SWITCH)
public String process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 审核改价后判断当前订单状态");
TpOrderAuditConfirmContext auditConfirmContext = bindCmp.getContextBean(TpOrderAuditConfirmContext.class);
TpProdOrderAuditConfirmDTO confirmDTO = auditConfirmContext.getConfirmDTO();
// 查询订单详情,并查询标的项及行程单
TpProdOrderDetailVO orderDetail = tpOrderClient.getOrderDetail(TpProdOrderQueryDTO.builder()
.originalOrderNo(confirmDTO.getOriginalOrderNo())
.tenantId(confirmDTO.getTenantId())
.needModules(ListUtil.toList(TpOrderModulesEnum.ORDER_TRAVEL_TRIP.getModule(), TpOrderModulesEnum.ORDER_SUBJECT_ITEM.getModule())).build());
auditConfirmContext.setOrderDetailVO(orderDetail);
// 首次确认后流程
if (ObjectUtil.equals(orderDetail.getStatus(), TpOrderStatusEnum.ORDER_CONFIRMED.getStatus())) {
return LiteFlowConstant.ORDER_AUDIT_FIRST_CONFIRM_FLOW;
}
// 变更后流程
if (StrUtil.isNotEmpty(orderDetail.getParentOrderNo()) && ObjectUtil.equals(orderDetail.getStatus(), TpOrderStatusEnum.ORDER_CHANGE_AUDITED.getStatus())) {
return LiteFlowConstant.ORDER_AUDIT_CHANGE_CONFIRM_FLOW;
}
// 订单取消后流程
if (ObjectUtil.equals(orderDetail.getStatus(), TpOrderStatusEnum.ORDER_CANCEL_AUDITED.getStatus())) {
return LiteFlowConstant.ORDER_AUDIT_CANCEL_CONFIRM_FLOW;
}
return null;
}
}

View File

@@ -0,0 +1,65 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.core.util.ObjectUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.constants.LiteFlowConstant;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.enums.TpOrderTypeEnum;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.RequiredArgsConstructor;
import static com.deepinnet.tptradeprod.common.enums.TpOrderTypeEnum.CUSTOMIZED_ORDER;
/**
* <p>
* 业务类型校验节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "orderBusinessTypeCheckNode", name = "判断业务类型")
@LiteflowCmpDefine(value = NodeTypeEnum.SWITCH)
@RequiredArgsConstructor
public class TpOrderBusinessTypeCheckNode {
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_SWITCH)
public String process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 判断产品业务类型");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
TpOrderTypeEnum bizType = TpOrderTypeEnum.getBizTypeByCode(createDTO.getType());
if (ObjectUtil.isNull(bizType)) {
LogUtil.error("未知的业务类型");
throw new TpTradeProdException(TpTradeProdErrorCode.PRODUCT_BUSINESS_TYPE_ERROR);
}
switch (bizType){
case CUSTOMIZED_ORDER:
// 定制公交
return LiteFlowConstant.USER_PLACE_ORDER_CUSTOM_BUS_FLOW;
case PACKING_ORDER:
// 预约包车
return LiteFlowConstant.USER_PLACE_ORDER_CHARTER_BUS_FLOW;
case CARPOOL_ORDER:
// 拼车
return LiteFlowConstant.USER_PLACE_ORDER_CARPOOL_BUS_FLOW;
default:
LogUtil.error("当前业务类型不在定义范围内");
throw new TpTradeProdException(TpTradeProdErrorCode.PRODUCT_BUSINESS_TYPE_ERROR);
}
}
}

View File

@@ -0,0 +1,40 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserCancelOrderContext;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.RequiredArgsConstructor;
/**
* <p>
* 取消订单判断是否需审核
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "cancelCheckIsAuditNode", name = "取消订单判断是否需审核")
@LiteflowCmpDefine(value = NodeTypeEnum.IF)
@RequiredArgsConstructor
public class TpOrderCancelCheckIsAuditNode {
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_IF)
public boolean process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 取消订单判断是否需审核");
TpUserCancelOrderContext userCancelOrderContext = bindCmp.getContextBean(TpUserCancelOrderContext.class);
TpProdOrderDetailVO orderDetail = userCancelOrderContext.getOrderDetail();
// TODO 查询产品详情判断是否需审核,默认需审核
return Boolean.TRUE;
}
}

View File

@@ -0,0 +1,70 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.core.util.ObjectUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradecore.common.enums.order.TpOrderModulesEnum;
import com.deepinnet.tptradeprod.biz.service.flow.constants.LiteFlowConstant;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserCancelOrderContext;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderQueryDTO;
import com.deepinnet.tptradeprod.common.enums.TpOrderPayModeEnum;
import com.deepinnet.tptradeprod.common.enums.TpOrderStatusEnum;
import com.deepinnet.tptradeprod.common.enums.TpOrderTypeEnum;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.google.common.collect.Lists;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.RequiredArgsConstructor;
/**
* <p>
* 取消订单校验状态节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "cancelOrderCheckStatusNode", name = "取消订单校验状态节点")
@LiteflowCmpDefine(value = NodeTypeEnum.SWITCH)
@RequiredArgsConstructor
public class TpOrderCancelCheckStatusNode {
private final TpOrderClient tpOrderClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_SWITCH)
public String process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 取消订单校验状态节点");
TpUserCancelOrderContext tpUserCancelOrderContext = bindCmp.getContextBean(TpUserCancelOrderContext.class);
// 判断当前订单是 直接取消 / 退款 / 还是支付
TpProdOrderDetailVO orderDetail = tpOrderClient.getOrderDetail(TpProdOrderQueryDTO.builder()
.orderNo(tpUserCancelOrderContext.getOrderNo())
.tenantId(tpUserCancelOrderContext.getTenantId()).build());
// 待确认取消订单
if (ObjectUtil.equal(orderDetail.getStatus(), TpOrderStatusEnum.ORDER_NEED_CONFIRM.getStatus())) {
return LiteFlowConstant.USER_CANCEL_ORDER_NEED_CONFIRM_FLOW;
}
// 已支付取消订单
if (ObjectUtil.equal(orderDetail.getStatus(), TpOrderStatusEnum.ORDER_DEPOSIT_PAID.getStatus())
|| ObjectUtil.equal(orderDetail.getStatus(), TpOrderStatusEnum.ORDER_NEED_DISPATCH.getStatus())
|| ObjectUtil.equal(orderDetail.getStatus(), TpOrderStatusEnum.ORDER_DISPATCHED.getStatus())) {
return LiteFlowConstant.USER_CANCEL_ORDER_PAID_FLOW;
}
LogUtil.error("当前订单:{}, 状态:{}, 无法取消", tpUserCancelOrderContext.getOrderNo(), orderDetail.getStatus());
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_CANCEL_ERROR);
}
}

View File

@@ -0,0 +1,39 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.core.util.StrUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.enums.TpOrderSourceEnum;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.RequiredArgsConstructor;
/**
* <p>
* 判断订单来源是否为POS机预约
* </p>
*
* @author chenjiaju
* @since 2024/5/20
*/
@LiteflowComponent(value = "carpoolCheckPosSourceNode", name = "判断订单来源是否为POS机预约")
@LiteflowCmpDefine(value = NodeTypeEnum.IF)
@RequiredArgsConstructor
public class TpOrderCarpoolCheckPosSourceNode {
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_IF)
public boolean process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 判断订单来源是否为POS机预约");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
return StrUtil.equals(createDTO.getSource(), TpOrderSourceEnum.POS.getType());
}
}

View File

@@ -0,0 +1,72 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradecore.common.dto.order.TpOrderPushStatusDTO;
import com.deepinnet.tptradecore.common.enums.order.TpOrderPayModeEnum;
import com.deepinnet.tptradecore.common.enums.order.TpOrderPushStatusEnum;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpOrderAuditConfirmContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderAuditConfirmDTO;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.deepinnet.tptradeprod.core.compoment.TpOrderSyncTripComponent;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.annotation.LiteflowRetry;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import javax.annotation.Resource;
/**
* <p>
* 订单首次确认审核通过判断支付模式
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "firstConfirmedCheckPayModeNode", name = "订单首次确认审核通过判断支付模式")
@LiteflowCmpDefine
@LiteflowRetry(retry = 3)
public class TpOrderFirstConfirmedCheckPayModeNode {
@Resource
private TpOrderClient tpOrderClient;
@Resource
private TpOrderSyncTripComponent tpOrderSyncTripComponent;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 订单首次确认审核通过判断支付模式");
TpOrderAuditConfirmContext auditConfirmContext = bindCmp.getContextBean(TpOrderAuditConfirmContext.class);
TpProdOrderAuditConfirmDTO confirmDTO = auditConfirmContext.getConfirmDTO();
TpProdOrderDetailVO orderDetailVO = auditConfirmContext.getOrderDetailVO();
TpOrderPushStatusEnum needPushStatusEnum = null;
// 先享后付,推进到待派车
if (StrUtil.equals(orderDetailVO.getPayMode(), TpOrderPayModeEnum.PAY_AFTER.getPayMode())) {
needPushStatusEnum = TpOrderPushStatusEnum.ORDER_NEED_DISPATCH;
} else {
needPushStatusEnum = TpOrderPushStatusEnum.ORDER_DEPOSIT_NEED_PAY;
}
// 推进订单状态
tpOrderClient.pushOrderStatus(TpOrderPushStatusDTO.builder()
.orderNo(orderDetailVO.getOrderNo())
.tenantId(confirmDTO.getTenantId())
.tpOrderPushStatusEnum(needPushStatusEnum).build());
// 同步主数据
if (ObjectUtil.equals(needPushStatusEnum.getStatus(), TpOrderPushStatusEnum.ORDER_NEED_DISPATCH.getStatus())) {
// 行程单同步主数据组件
tpOrderSyncTripComponent.createSync(orderDetailVO, confirmDTO.getTenantId());
}
}
}

View File

@@ -0,0 +1,42 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpproductcore.common.dto.product.TpProdDetailDTO;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.RequiredArgsConstructor;
/**
* <p>
*
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "orderIsNeedConfirmCheckNode", name = "判断是否需要业务员确认审核")
@LiteflowCmpDefine(value = NodeTypeEnum.IF)
@RequiredArgsConstructor
public class TpOrderIsNeedConfirmCheckNode {
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_IF)
public boolean process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 判断是否需要业务员确认审核");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdDetailDTO productDTO = userPlaceOrderContext.getProductDTO();
// TODO bizCode
// 默认需要业务员审核,默认非自动审核
userPlaceOrderContext.setAutoAudit(Boolean.FALSE);
return Boolean.TRUE;
}
}

View File

@@ -0,0 +1,59 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpproductcore.common.dto.product.TpProdDetailDTO;
import com.deepinnet.tpproductcore.common.dto.serviceobject.TpServiceObjectDTO;
import com.deepinnet.tpproductcore.common.enums.PayTypeEnum;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.RequiredArgsConstructor;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 免费票校验节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "orderIsNeedInquireCheckNode", name = "判断是否为免费票")
@LiteflowCmpDefine(value = NodeTypeEnum.IF)
@RequiredArgsConstructor
public class TpOrderIsNeedInquireCheckNode {
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_IF)
public boolean process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 判断是否为免费票(免费票无需询价)");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
TpProdDetailDTO productDTO = userPlaceOrderContext.getProductDTO();
// 校验当前品的服务对象的支付方式
if (StrUtil.isNotEmpty(createDTO.getOrderPlacer().getServiceObjectCode()) && CollUtil.isNotEmpty(productDTO.getServiceObjects())) {
// 查询用户对应的企业线路是否为免费票,免费票不询价
List<TpServiceObjectDTO> filterResult = productDTO.getServiceObjects().stream().filter(serviceObject -> StrUtil.equals(createDTO.getOrderPlacer().getServiceObjectCode(), serviceObject.getServiceObjectCode())
&& StrUtil.equalsIgnoreCase(PayTypeEnum.FREE.getCode(), serviceObject.getPayType())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(filterResult)) {
LogUtil.warn("当前线路:{}, 服务对象:{}, 免费票, 不予询价", createDTO.getRoutes().get(0).getRouteNo(), createDTO.getOrderPlacer().getServiceObjectCode());
return Boolean.FALSE;
}
}
// 需要询价
return Boolean.TRUE;
}
}

View File

@@ -0,0 +1,91 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradecore.common.enums.order.TpOrderModulesEnum;
import com.deepinnet.tptradeprod.biz.service.flow.constants.LiteFlowConstant;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpOrderManualSyncTripContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderQueryDTO;
import com.deepinnet.tptradeprod.common.enums.TpOrderStatusEnum;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.RequiredArgsConstructor;
/**
* <p>
* 订单手动同步行程校验节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "orderManualSyncTripCheckNode", name = "订单手动同步行程校验节点")
@LiteflowCmpDefine(value = NodeTypeEnum.SWITCH)
@RequiredArgsConstructor
public class TpOrderManualSyncTripCheckNode {
private final TpOrderClient tpOrderClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_SWITCH)
public String process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 订单手动同步行程校验节点");
TpOrderManualSyncTripContext syncTripContext = bindCmp.getContextBean(TpOrderManualSyncTripContext.class);
TpProdOrderDetailVO nowOrder = syncTripContext.getCurrentOrderDetail();
// 判断父订单是否存在
TpProdOrderDetailVO parentOrder = null;
if (StrUtil.isNotEmpty(nowOrder.getParentOrderNo())) {
parentOrder = tpOrderClient.getOrderDetail(TpProdOrderQueryDTO.builder()
.orderNo(nowOrder.getParentOrderNo())
.tenantId(syncTripContext.getTenantId())
.needModules(ListUtil.toList(TpOrderModulesEnum.ORDER_TRAVEL_TRIP.getModule(), TpOrderModulesEnum.ORDER_SUBJECT_ITEM.getModule())).build());
syncTripContext.setParentOrderDetail(parentOrder);
}
// 判断是否为取消订单
if (ObjectUtil.equals(nowOrder.getStatus(), TpOrderStatusEnum.ORDER_CANCELED.getStatus())
|| ObjectUtil.equals(nowOrder.getStatus(), TpOrderStatusEnum.ORDER_CANCEL_NEED_PAY.getStatus())
|| ObjectUtil.equals(nowOrder.getStatus(), TpOrderStatusEnum.ORDER_CANCEL_REFUNDING.getStatus())
|| ObjectUtil.equals(nowOrder.getStatus(), TpOrderStatusEnum.ORDER_CANCEL_REFUNDED.getStatus())) {
LogUtil.info("当前订单:{}, 源订单:{}, 同步行程[取消]", nowOrder.getOrderNo(), nowOrder.getOriginalOrderNo());
// 取消同步主数据
return LiteFlowConstant.ORDER_CANCEL_SYNC_TRIP_NODE;
}
// 判断父订单状态 只有待派车状态下进入更新订单
if (ObjectUtil.isNotNull(parentOrder)
&& (ObjectUtil.equals(parentOrder.getStatus(), TpOrderStatusEnum.ORDER_NEED_DISPATCH.getStatus())
|| ObjectUtil.equals(parentOrder.getStatus(), TpOrderStatusEnum.ORDER_DISPATCHED.getStatus()))) {
LogUtil.info("当前订单:{}, 源订单:{}, 同步行程[更新]", nowOrder.getOrderNo(), nowOrder.getOriginalOrderNo());
// 更新同步主数据
return LiteFlowConstant.ORDER_UPDATE_SYNC_TRIP_NODE;
}
if (ObjectUtil.equals(nowOrder.getStatus(), TpOrderStatusEnum.ORDER_NEED_DISPATCH.getStatus())) {
LogUtil.info("当前订单:{}, 源订单:{}, 同步行程[创建]", nowOrder.getOrderNo(), nowOrder.getOriginalOrderNo());
// 创建行程同步主数据
return LiteFlowConstant.ORDER_CREATE_SYNC_TRIP_NODE;
}
LogUtil.error("当前订单:{}, 无需同步主数据", nowOrder.getOrderNo());
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_TRIP_NOT_NEED_SYNC_ERROR);
}
}

View File

@@ -0,0 +1,56 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradecore.common.enums.TpBizTypeEnum;
import com.deepinnet.tptradeprod.biz.service.flow.constants.LiteFlowConstant;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.enums.TpOrderTypeEnum;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.RequiredArgsConstructor;
/**
* <p>
* 支付判断业务类型校验节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "orderPaidBizTypeCheckNode", name = "预约包车支付类型判断(订金支付 / 尾款支付)")
@LiteflowCmpDefine(value = NodeTypeEnum.SWITCH)
@RequiredArgsConstructor
public class TpOrderPaidBizTypeCheckNode {
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_SWITCH)
public String process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 预约包车支付类型判断(订金支付 / 尾款支付)");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
// 校验当前品的业务类型
if (StrUtil.equals(userPlaceOrderContext.getBizType(), TpBizTypeEnum.DEPOSIT_PAY.getCode())) {
// 订金支付
return LiteFlowConstant.USER_DEPOSIT_PAID_FLOW;
}
if (StrUtil.equals(userPlaceOrderContext.getBizType(), TpBizTypeEnum.BALANCE_PAY.getCode())) {
// 尾款支付
return LiteFlowConstant.USER_BALANCE_PAID_FLOW;
}
LogUtil.error("当前业务类型不在定义范围内");
throw new TpTradeProdException(TpTradeProdErrorCode.PRODUCT_BUSINESS_TYPE_ERROR);
}
}

View File

@@ -0,0 +1,60 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.core.util.StrUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpproductcore.common.dto.product.TpProdDetailDTO;
import com.deepinnet.tpproductcore.common.enums.TpOrderPayTypeEnum;
import com.deepinnet.tptradeprod.biz.service.flow.constants.LiteFlowConstant;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.enums.TpOrderPayModeEnum;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.RequiredArgsConstructor;
/**
* <p>
* 付款模式校验节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "orderPayModeCheckNode", name = "付款模式校验节点")
@LiteflowCmpDefine(value = NodeTypeEnum.SWITCH)
@RequiredArgsConstructor
public class TpOrderPayModeCheckNode {
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_SWITCH)
public String process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 付款模式校验节点");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
// 塞入并行询价的内部价金额
createDTO.getTpOrderPriceRecords().forEach(priceRecord -> {
priceRecord.setInternalInquireAmount(userPlaceOrderContext.getInternalPrice());
});
TpProdDetailDTO productDTO = userPlaceOrderContext.getProductDTO();
TpOrderPayTypeEnum orderPayType = productDTO.getExtendAttributes().getOrderPayType();
// 目前写死先付后享
if (StrUtil.equals(orderPayType.getCode(), TpOrderPayTypeEnum.FULL_PAY.getCode()) || StrUtil.equals(orderPayType.getCode(), TpOrderPayTypeEnum.PAY_DEPOSIT.getCode())) {
// 先付后享
createDTO.setPayMode(StrUtil.equals(orderPayType.getCode(), TpOrderPayTypeEnum.FULL_PAY.getCode()) ? TpOrderPayModeEnum.PAY_BEFORE_ALL.getPayMode() : TpOrderPayModeEnum.PAY_BEFORE.getPayMode());
return LiteFlowConstant.USER_PAY_BEFORE_USE_FLOW;
} else {
// 先享后付
createDTO.setPayMode(TpOrderPayModeEnum.PAY_AFTER.getPayMode());
return LiteFlowConstant.USER_PAY_AFTER_USE_FLOW;
}
}
}

View File

@@ -0,0 +1,719 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpbaseopcore.common.dto.org.OrgNameCodeDTO;
import com.deepinnet.tpproductcore.common.dto.category.TpCategoryDTO;
import com.deepinnet.tpproductcore.common.dto.product.TpProdDetailDTO;
import com.deepinnet.tpproductcore.common.dto.product.TpProductExtendAttributesDTO;
import com.deepinnet.tpproductcore.common.dto.product.TpProductExtraAttributesDTO;
import com.deepinnet.tpproductcore.common.dto.rule.*;
import com.deepinnet.tpproductcore.common.dto.rule.result.TpReservationTimeResult;
import com.deepinnet.tpproductcore.common.enums.*;
import com.deepinnet.tpproductcore.common.qto.TpSalesUnitCarPoolListQueryDTO;
import com.deepinnet.tpproductcore.common.qto.TpSalesUnitQueryDTO;
import com.deepinnet.tpproductcore.common.qto.product.TpProductQueryDTO;
import com.deepinnet.tpproductcore.common.vo.TpSalesUnitCarPoolVO;
import com.deepinnet.tpproductcore.common.vo.TpSalesUnitElementVO;
import com.deepinnet.tpproductcore.common.vo.TpSalesUnitVO;
import com.deepinnet.tptradecore.common.dto.order.TpOrderSwipeQueryDTO;
import com.deepinnet.tptradecore.common.dto.order.TpUserTicketsQueryDTO;
import com.deepinnet.tptradecore.common.enums.order.TpOrderChangeApplyStatusEnum;
import com.deepinnet.tptradecore.common.enums.order.TpOrderTripTypeEnum;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.enums.TpOrderSourceEnum;
import com.deepinnet.tptradeprod.common.enums.TpOrderTypeEnum;
import com.deepinnet.tptradeprod.common.enums.TpProdOrderTicketTypeEnum;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.deepinnet.tptradeprod.common.service.integration.client.*;
import com.google.common.collect.Lists;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* <p>
* 产品校验节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "placeOrderProductCheckNode", name = "产品校验")
@LiteflowCmpDefine
@RequiredArgsConstructor
public class TpPlaceOrderProductCheckNode {
private static final int ONE_DAY_MILLISECOND = 86400000;
private final TpProductClient tpProductClient;
private final TpProductSalesUnitClient tpProductSalesUnitClient;
private final TpOrderClient tpOrderClient;
private final TpBizRuleClient bizRuleClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 产品校验");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
TpProdDetailDTO productDetailDTO = checkProduct(createDTO, userPlaceOrderContext);
userPlaceOrderContext.setProductDTO(productDetailDTO);
if (userPlaceOrderContext.getOrderRescheduleDTO() != null) {
checkRescheduleTicketCount(userPlaceOrderContext);
}
}
private void checkRescheduleTicketCount(TpUserPlaceOrderContext userPlaceOrderContext) {
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
TpProdOrderRescheduleDTO orderRescheduleDTO = userPlaceOrderContext.getOrderRescheduleDTO();
// 判断选择改签的票数量与改签后的数量是否一致
int totalCount = createDTO.getOrderSubjectItem().stream().mapToInt(TpOrderSubjectItemDTO::getCount).sum();
int invalidCount = orderRescheduleDTO.getInvalidVoucherDTOs().stream().mapToInt(TpProdInvalidVoucherDTO::getInvalidPassengerCount).sum();
if (invalidCount != totalCount) {
LogUtil.error("选择改签的票数量与改签后的数量不一致,请检查改签参数:{}", userPlaceOrderContext.getOrderRescheduleDTO());
throw new TpTradeProdException(TpTradeProdErrorCode.RESCHEDULE_TICKET_COUNT_ERROR);
}
}
private TpProdDetailDTO checkProduct(TpProdOrderCreateDTO dto, TpUserPlaceOrderContext userPlaceOrderContext) {
TpProdDetailDTO product = queryProduct(dto.getProductNo(), dto.getTenantId());
LogUtil.info("查询到的产品详情:{}", JSONObject.toJSONString(product));
TpProductExtendAttributesDTO extendAttributes = product.getExtendAttributes();
TpProductExtraAttributesDTO productExtraAttributes = product.getProductExtraAttributes();
// 公共校验
publicParamsSetAndCheck(dto, product);
// 规则为空校验
if (CollUtil.isEmpty(product.getRules())) {
LogUtil.warn("rules empty, productNo:{}", dto.getProductNo());
return product;
}
Map<String, List<TpBizRuleDTO>> rulesMap = product.getRules().stream().collect(Collectors.groupingBy(TpBizRuleDTO::getRuleGroup));
// 定制公交
if (StrUtil.equals(product.getBizType(), TpProductBizTypeEnum.CUSTOM_BUS.getCode())) {
LogUtil.info("定制公交判断逻辑");
checkCustomBusProduct(dto, product, rulesMap);
}
// 预约包车
if (StrUtil.equals(product.getBizType(), TpProductBizTypeEnum.CHARTER_BUS.getCode())) {
boolean changeOrder = userPlaceOrderContext.isChangeOrder();
// 最早 / 最晚预约时间规则校验
if (!changeOrder) {
checkCharterBusProduct(dto, rulesMap, product);
}
// 是否可跨天校验,仅单天单程和单天往返包车需要校验
checkRestrictTime(extendAttributes.getRestrictTimeSingleDaySingleAndRoundTrip(), productExtraAttributes.getPricingType(), dto.getCharterBusStations());
// 订单过期时间
setOrderCloseExpireTime(dto, rulesMap);
// 订单变更数据读取
if (changeOrder){
//上车时间校验
List<TpOrderStationDTO> charterBusStations = dto.getCharterBusStations();
long now = System.currentTimeMillis();
charterBusStations.forEach(charterBusStation -> {
Long pickUpTime = Convert.toLong(charterBusStation.getPickUpTime());
Assert.isTrue(pickUpTime > now, () -> new TpTradeProdException(TpTradeProdErrorCode.CURRENT_TIME_ERROR));
});
Boolean supportChangeTrip = extendAttributes.getSupportChangeTrip();
if (supportChangeTrip != null) {
if (!supportChangeTrip){
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_CHANGE_NOT_ALLOW);
}
}
Integer changeTripTimesRule = extendAttributes.getSupportChangeTripTimes();
if (changeTripTimesRule != null){
if (changeTripTimesRule == 0) {
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_CHANGE_OVER_TIMES);
} else {
long alreadyChangeCount = userPlaceOrderContext.getOrderChangeApplyList()
.stream()
.filter(e -> Objects.equals(e.getApplyStatus(), TpOrderChangeApplyStatusEnum.APPROVED_SUCCESS.getType()))
.count();
// TpOrderCountQueryDTO query = new TpOrderCountQueryDTO();
// query.setOriginalOrderNo(dto.getOriginalOrderNo());
// query.setTenantId(dto.getTenantId());
// Long orderCount = tpOrderClient.orderCount(query);
if (changeTripTimesRule < alreadyChangeCount) {
throw new TpTradeProdException(TpTradeProdErrorCode.ORDER_CHANGE_OVER_TIMES);
}
} }
userPlaceOrderContext.setChangeOrderNeedAudit(extendAttributes.getTripChangeNeedConfirmBySalesman() == null || extendAttributes.getTripChangeNeedConfirmBySalesman());
}
}
return product;
}
/**
* 包车是否可跨天校验
* @param restrictTime
* @param pricingType
* @param charterBusStations
*/
protected static void checkRestrictTime(Boolean restrictTime, String pricingType, List<TpOrderStationDTO> charterBusStations) {
if (hasRestrictAndIsInCitySingleOrRoundTrip(restrictTime, pricingType)) {
if (restrictTime) {
validateSameDay(charterBusStations);
} else {
validateTotalDuration(charterBusStations);
}
}
}
private static void validateSameDay(List<TpOrderStationDTO> charterBusStations) {
Set<Long> timeSet = charterBusStations.stream()
.flatMap(p -> Stream.of(
DateUtil.beginOfDay(new Date(Convert.toLong(p.getPickUpTime()))).getTime(),
DateUtil.beginOfDay(new Date(Convert.toLong(p.getDropOffTime()))).getTime()
))
.collect(Collectors.toSet());
if (timeSet.size() > 1) {
handleValidationFailure(charterBusStations, "不可跨天,限制当晚 24点前结束");
}
}
private static void validateTotalDuration(List<TpOrderStationDTO> charterBusStations) {
Long totalDuration = charterBusStations.stream()
.map(TpOrderStationDTO::getDuration)
.reduce(Long::sum)
.orElse(0L);
if (totalDuration > ONE_DAY_MILLISECOND) {
handleValidationFailure(charterBusStations, "可跨天,限制行驶时长 24小时");
}
}
private static void handleValidationFailure(List<TpOrderStationDTO> charterBusStations, String message) {
LogUtil.error("[包车订单是否可跨天]规则执行失败, 当前入参:{}, 原因:{}", JSONObject.toJSONString(charterBusStations), message);
throw new TpTradeProdException(TpTradeProdErrorCode.RULE_EXECUTE_ERROR, "校验失败,原因:" + message);
}
/**
* 有跨天校验,且包车类型为市内单程或市内往返
* @param restrictTimeSingleDaySingleAndRoundTrip
* @param pricingType
* @return
*/
private static boolean hasRestrictAndIsInCitySingleOrRoundTrip(Boolean restrictTimeSingleDaySingleAndRoundTrip, String pricingType) {
return restrictTimeSingleDaySingleAndRoundTrip != null && (Objects.equals(pricingType, TpCharteredBusPricingTypeEnum.IN_CITY_ONE_WAY_SAME_DAY.getBackType()) || Objects.equals(pricingType, TpCharteredBusPricingTypeEnum.IN_CITY_ROUND_TRIP_SAME_DAY.getBackType()));
}
private void setOrderCloseExpireTime(TpProdOrderCreateDTO dto, Map<String, List<TpBizRuleDTO>> rulesMap) {
List<TpOrderStationDTO> charterBusStations = dto.getCharterBusStations();
Long pickUpTime;
if (charterBusStations.size() == 1) {
pickUpTime = Convert.toLong(charterBusStations.get(0).getPickUpTime());
} else {
List<TpOrderStationDTO> goTrip = charterBusStations.stream().filter(station -> StrUtil.equals(station.getTripType(), TpOrderTripTypeEnum.GO.getCode())).collect(Collectors.toList());
pickUpTime = Convert.toLong(goTrip.get(0).getPickUpTime());
}
TpRuleExecuteDTO<Object> orderCloseRuleExecuteDTO = new TpRuleExecuteDTO<>();
List<TpBizRuleDTO> orderCloseRules = rulesMap.get(TpRuleExpressionGroupEnum.ORDER_CANCEL_TIME.getCode());
if (CollUtil.isEmpty(orderCloseRules)) {
LogUtil.warn("当前产品:{}, 未配置订单过期时间规则", dto.getProductNo());
dto.setExpireTime(pickUpTime);
return;
}
List<String> rules = Lists.newArrayList();
orderCloseRules.forEach(rule -> rules.add(rule.getExpression()));
orderCloseRuleExecuteDTO.setRuleList(rules);
orderCloseRuleExecuteDTO.setRuleExpressionGroup(TpRuleExpressionGroupEnum.ORDER_CANCEL_TIME);
orderCloseRuleExecuteDTO.setTenantId(dto.getTenantId());
TpRuleExecuteResultVO<Long> ruleExecuteResult = bizRuleClient.executeRule(orderCloseRuleExecuteDTO);
if (!ruleExecuteResult.getSuccess()) {
LogUtil.error("[订单过期时间]规则执行失败, 当前入参:{}", JSONObject.toJSONString(ruleExecuteResult));
throw new TpTradeProdException(TpTradeProdErrorCode.RULE_EXECUTE_ERROR);
}
// 订单塞入过期时间
dto.setExpireTime(pickUpTime - ruleExecuteResult.getResult());
}
private void checkCharterBusProduct(TpProdOrderCreateDTO dto, Map<String, List<TpBizRuleDTO>> rulesMap, TpProdDetailDTO product) {
List<TpBizRuleDTO> buyRules = rulesMap.get(TpRuleExpressionGroupEnum.RESERVATION_TIME.getCode());
if (CollUtil.isEmpty(buyRules)) {
LogUtil.warn("当前产品:{}, 未配置[包车订单预约时间]规则", dto.getProductNo());
return;
}
List<String> rules = Lists.newArrayList();
buyRules.forEach(rule -> rules.add(rule.getExpression()));
TpRuleExecuteDTO<TpReservationTimeParam> reservationTimeParam = getTpReservationTimeParamTpRuleExecuteDTO(dto, product, rules);
TpRuleExecuteResultVO<TpReservationTimeResult> reservationTimeResult = bizRuleClient.executeRule(reservationTimeParam);
if (!reservationTimeResult.getSuccess()) {
LogUtil.error("[包车订单预约时间]规则执行失败, 当前入参:{}", JSONObject.toJSONString(reservationTimeParam));
throw new TpTradeProdException(TpTradeProdErrorCode.RULE_EXECUTE_ERROR);
}
List<TpOrderStationDTO> charterBusStations = dto.getCharterBusStations();
// 如果是单程
Long pickUpTime;
if (charterBusStations.size() == 1) {
pickUpTime = Convert.toLong(charterBusStations.get(0).getPickUpTime());
} else {
List<TpOrderStationDTO> goTrip = charterBusStations.stream().filter(station -> StrUtil.equals(station.getTripType(), TpOrderTripTypeEnum.GO.getCode())).collect(Collectors.toList());
pickUpTime = Convert.toLong(goTrip.get(0).getPickUpTime());
}
TpReservationTimeResult timeResult = reservationTimeResult.getResult();
long currentTimeStamp = DateUtil.current();
long reservationTime = pickUpTime - currentTimeStamp;
if (reservationTime < timeResult.getEarliestTime() || reservationTime > timeResult.getLatestTime()) {
LogUtil.error("当前时间:{}, 早于最早预约时间:{}, 最晚预约时间, 暂不可预约", pickUpTime, timeResult.getEarliestTime(), timeResult.getEarliestTime());
throw new TpTradeProdException(TpTradeProdErrorCode.CURRENT_TIME_BOOK_ERROR);
}
}
@NotNull
private static TpRuleExecuteDTO<TpReservationTimeParam> getTpReservationTimeParamTpRuleExecuteDTO(TpProdOrderCreateDTO dto, TpProdDetailDTO product, List<String> rules) {
TpReservationTimeParam tpReservationLatestTimeParam = new TpReservationTimeParam();
// 预约包车 定价类型
tpReservationLatestTimeParam.setPricingType(TpCharteredBusPricingTypeEnum.getEnumByBackType(product.getProductExtraAttributes().getPricingType()));
// 规则入参
TpRuleExecuteDTO<TpReservationTimeParam> reservationTimeParam = new TpRuleExecuteDTO<>();
reservationTimeParam.setParameter(tpReservationLatestTimeParam);
reservationTimeParam.setRuleList(rules);
reservationTimeParam.setTenantId(dto.getTenantId());
reservationTimeParam.setRuleExpressionGroup(TpRuleExpressionGroupEnum.RESERVATION_TIME);
return reservationTimeParam;
}
private void publicParamsSetAndCheck(TpProdOrderCreateDTO dto, TpProdDetailDTO product) {
// 校验是否非正式版本
checkFormalFlagAndRoute(product);
// 售卖单元校验 / 组装售卖单元 [经讨论,不校验]
// checkSalesUnit(dto);
// 主子订单根据业务判断 目前一期暂时只有主订单
dto.setMain(1);
dto.setOutRequestNo(dto.getOutRequestNo() + dto.getUserNo() + dto.getProductNo());
dto.setProductName(product.getProductName());
}
private void checkCustomBusProduct(TpProdOrderCreateDTO dto, TpProdDetailDTO product, Map<String, List<TpBizRuleDTO>> rulesMap) {
// 校验当前流水号是否重复
checkSwipeCardNoExist(dto);
// 干掉售卖单元校验
// checkSalesUnit(dto);
// 塞入一级类目
buildCategory(dto, product);
if (ObjectUtil.isNull(product.getRouteDetailDTO())) {
LogUtil.error("线路信息不存在, 线路编码:{}", product.getRouteCode());
throw new TpTradeProdException(TpTradeProdErrorCode.ROUTE_NOT_EXIST_ERROR);
}
// 校验线路是否正确
if (!StrUtil.equals(dto.getRoutes().get(0).getRouteNo(), product.getRouteCode())) {
LogUtil.error("线路信息比对不一致, 传入线路:{}, 查询线路:{}", dto.getRoutes().get(0).getRouteNo(), product.getRouteCode());
throw new TpTradeProdException(TpTradeProdErrorCode.ROUTE_COMPARE_ERROR);
}
//判断班次发车时,班次不存在直接报错
checkDepartureType(dto, product);
// 校验限购
checkBuyLimitRules(dto, rulesMap);
// 放票规则 产品端修改放票规则批量校验
// cjj fixme 规则暂未到位
checkTicketTypeRule(dto, rulesMap, product);
// 产品配置项配置的订单过期时间
Long orderExpiredTime = product.getExtendAttributes().getOrderExpiredTime();
// 订单过期时间
dto.setExpireTime(DateUtil.offsetMillisecond(DateUtil.date(), Convert.toInt(orderExpiredTime)).getTime());
// 线路所属车队
List<OrgNameCodeDTO> orgAllPath = product.getRouteDetailDTO().getRouteBase().getOrgAllPaths();
dto.getRoutes().forEach(route -> route.setBelongFleet(CollUtil.isEmpty(orgAllPath) ? null : orgAllPath.stream().map(OrgNameCodeDTO::getName).collect(Collectors.joining("-"))));
// 查询拼车线路当前时候可以预约
checkCarpoolPreSaleEndTime(dto);
}
private void checkCarpoolPreSaleEndTime(TpProdOrderCreateDTO dto) {
if (ObjectUtil.equals(dto.getType(), TpOrderTypeEnum.CARPOOL_ORDER.getType())) {
List<String> itemNos = dto.getOrderSubjectItem().stream().map(TpOrderSubjectItemDTO::getItemNo).collect(Collectors.toList());
TpSalesUnitCarPoolListQueryDTO queryDTO = new TpSalesUnitCarPoolListQueryDTO();
queryDTO.setSalesUnitCodeList(itemNos);
queryDTO.setTenantId(dto.getTenantId());
TpSalesUnitCarPoolVO tpSalesUnitCarPoolVO = tpProductSalesUnitClient.listCarpools(queryDTO).get(0);
// 如果当前时间大于预售结束时间,则不允许预约
if (DateUtil.current() > tpSalesUnitCarPoolVO.getPreSaleEndTime()) {
LogUtil.error("当前时间:{}, 超过预约结束时间:{}, 不能预约", DateUtil.current(), tpSalesUnitCarPoolVO.getPreSaleEndTime());
throw new TpTradeProdException(TpTradeProdErrorCode.CURRENT_TIME_BOOK_ERROR);
}
}
}
private void checkSwipeCardNoExist(TpProdOrderCreateDTO dto) {
if (ObjectUtil.notEqual(TpOrderTypeEnum.CARPOOL_ORDER.getType(), dto.getType()) && StrUtil.isEmpty(dto.getSwipeCardNo())
|| ObjectUtil.notEqual(TpOrderSourceEnum.POS.getType(), dto.getSource())) {
return;
}
TpOrderSwipeQueryDTO tpOrderSwipeQueryDTO = new TpOrderSwipeQueryDTO();
tpOrderSwipeQueryDTO.setSwipeCardNo(dto.getSwipeCardNo());
tpOrderSwipeQueryDTO.setTenantId(dto.getTenantId());
boolean isExist = tpOrderClient.querySwipeCardNoExist(tpOrderSwipeQueryDTO);
if (isExist) {
LogUtil.error("当前刷卡流水流水号已使用, swipeCardNo:{}", dto.getSwipeCardNo());
throw new TpTradeProdException(TpTradeProdErrorCode.CARPOOL_SWIPE_CARD_NO_EXIST_ERROR);
}
}
private static void checkDepartureType(TpProdOrderCreateDTO dto, TpProdDetailDTO product) {
if (StrUtil.equals(DepartureTypeEnum.SHUTTLE.getCode(), product.getRouteDetailDTO().getRouteBase().getDepartureType()) && ObjectUtil.isNull(dto.getRoutes().get(0).getTpOrderRouteShuttle())) {
LogUtil.error("产品:{}, 线路:{}, 发车方式为:{}, 传入班次不存在", product.getProductCode(), product.getRouteCode(), product.getRouteDetailDTO().getRouteBase().getDepartureType());
throw new TpTradeProdException(TpTradeProdErrorCode.ILLEGAL_PARAMS);
}
}
private void buildCategory(TpProdOrderCreateDTO dto, TpProdDetailDTO product) {
// 查询类目
List<TpCategoryDTO> categories = product.getFrontCategories();
List<TpCategoryDTO> oneLevelCategory = categories.stream().filter(category -> ObjectUtil.equal(category.getLevel(), 1)).collect(Collectors.toList());
// 有一级类目情况下直接设置一级类目
if (CollUtil.isNotEmpty(oneLevelCategory)) {
dto.setProductCategoryNo(oneLevelCategory.get(0).getCode());
dto.setProductCategory(oneLevelCategory.get(0).getName());
} else {
List<TpCategoryDTO> secondLevelCategory = categories.stream().filter(category -> ObjectUtil.equal(category.getLevel(), 2)).collect(Collectors.toList());
if (CollUtil.isEmpty(secondLevelCategory)) {
LogUtil.error("当前产品:{}, 无一级类目、二级类目节点", product.getProductCode());
throw new TpTradeProdException(TpTradeProdErrorCode.PRODUCT_CATEGORY_ERROR);
}
dto.setProductCategoryNo(secondLevelCategory.get(0).getParentCode());
dto.setProductCategory(secondLevelCategory.get(0).getParentName());
}
}
private void checkTicketTypeRule(TpProdOrderCreateDTO dto, Map<String, List<TpBizRuleDTO>> rulesMap, TpProdDetailDTO product) {
TpProdOrderTicketTypeEnum ticketTypeEnum = TpProdOrderTicketTypeEnum.getEnum(dto.getTicketType());
if (ObjectUtil.isNull(ticketTypeEnum)) {
LogUtil.error("票类型错误, {}", dto.getTicketType());
throw new TpTradeProdException(TpTradeProdErrorCode.TICKET_TYPE_ERROR);
}
// 校验当前班次是否小于当前时间,小于等于当前时间无法购买
checkBuyShuttle(dto);
List<String> ruleExpressions = product.getRuleExpressions(TpRuleExpressionGroupEnum.getByCode(ticketTypeEnum.getTicketRuleCode()));
if (CollectionUtil.isEmpty(ruleExpressions)) {
LogUtil.warn("{}, 放票时间未做限制", ticketTypeEnum.getTicketTypeDesc());
return;
}
if (ObjectUtil.equals(TpOrderTypeEnum.CUSTOMIZED_ORDER.getType(), dto.getType())) {
List<TpRuleExecuteDTO<TpTicketBuyParamDTO>> batchExecuteRuleDTOs = Lists.newArrayList();
buildTicketBatchRuleDTO(dto, rulesMap, ticketTypeEnum, batchExecuteRuleDTOs);
// 使用批量执行规则方法
// TpRuleExecuteResultVO<Boolean> resultVO = bizRuleClient.executeRule(tpRuleExecuteDTO);
TpRuleExecuteBatchResultVO<Boolean> resultVO = bizRuleClient.batchExecuteBizRule(batchExecuteRuleDTOs);
resultVO.getResultList().forEach(ruleResult -> {
if (!ruleResult.getResult()) {
LogUtil.error("当前时间暂不能购买");
throw new TpTradeProdException(TpTradeProdErrorCode.USER_BUY_TIME_ERROR);
}
});
}
}
private static void checkBuyShuttle(TpProdOrderCreateDTO dto) {
Map<String, List<TpOrderSubjectItemDTO>> subjectItemByTripTypeMap = dto.getOrderSubjectItem().stream().collect(Collectors.groupingBy(TpOrderSubjectItemDTO::getTripType));
subjectItemByTripTypeMap.forEach((k, v) -> {
// 构建售卖单元组成要素
List<TpOrderSubjectItemElementDTO> itemElementDTOList = Lists.newArrayList();
v.forEach(orderSubjectItemDTO -> itemElementDTOList.addAll(orderSubjectItemDTO.getSubjectItemElements()));
// 校验当前购买班次是否可购买(本地校验)
Map<String, List<TpOrderSubjectItemElementDTO>> itemCodeMapList = itemElementDTOList.stream()
.collect(Collectors.groupingBy(TpOrderSubjectItemElementDTO::getElementCode));
dto.getRoutes().forEach(route -> itemCodeMapList.get(TpFactorCodeEnum.DATE.getCode()).forEach(date -> {
if (CollUtil.isNotEmpty(route.getTpOrderRouteShuttle())) {
route.getTpOrderRouteShuttle().forEach(shuttle -> {
if (StrUtil.equals(shuttle.getTripType(), k)) {
long buyTime = DateUtil.parse(date.getElementValue() + shuttle.getShuttleTime().replace(StrUtil.COLON, "") + "00").getTime();
// 当前时间 >= 购买日期的班次时间
if (DateUtil.current() >= buyTime) {
LogUtil.error("当前时间暂不能购买, 购买班次时间:{}, 当前时间:{}", buyTime, DateUtil.current());
throw new TpTradeProdException(TpTradeProdErrorCode.USER_BUY_TIME_ERROR);
}
}
});
}
}));
});
}
private static void buildTicketBatchRuleDTO(TpProdOrderCreateDTO dto, Map<String, List<TpBizRuleDTO>> rulesMap, TpProdOrderTicketTypeEnum ticketTypeEnum, List<TpRuleExecuteDTO<TpTicketBuyParamDTO>> batchExecuteRuleDTOs) {
// key 为班次编号value 为班次信息
Map<String, TpOrderRouteShuttleDTO> shuttleDTOMap = dto.getRoutes().stream()
.filter(Objects::nonNull) // 确保TpOrderRouteDTO对象非null
.filter(routeDTO -> CollUtil.isNotEmpty(routeDTO.getTpOrderRouteShuttle())) // 确保getTpOrderRouteShuttle()返回的列表非null
.flatMap(routeDTO -> routeDTO.getTpOrderRouteShuttle().stream()) // 将列表转换为流
.collect(Collectors.toMap(
TpOrderRouteShuttleDTO::getShuttleNo, // 键映射函数
Function.identity(), // 值映射函数
(existing, replacement) -> existing, // 合并函数,如果有重复的键,则保留已存在的值
HashMap::new // 创建一个新的HashMap
));
// 遍历售卖单元
dto.getOrderSubjectItem().forEach(subjectItem -> {
List<TpOrderSubjectItemElementDTO> ticketTypeElement = subjectItem.getSubjectItemElements().stream().filter(e -> StrUtil.equals(e.getElementCode(), TpFactorCodeEnum.TICKET_TYPE.getCode())).collect(Collectors.toList());
if (CollUtil.isEmpty(ticketTypeElement)) {
LogUtil.error("当前线路未配置票类型");
throw new TpTradeProdException(TpTradeProdErrorCode.TICKET_TYPE_NOT_EXIST);
}
// 班次编号
String shuttleCode = subjectItem.getSubjectItemElements().stream()
.filter(Objects::nonNull) // 确保元素集合不为空
.filter(item -> Objects.equals(item.getElementCode(), TpFactorCodeEnum.SHUTTLE_CODE.getCode())) // 确保elementCode为包次 code
.findFirst()
.map(TpOrderSubjectItemElementDTO::getElementValue) // 映射到elementValue即班次编号
.orElse(null); // 如果没有找到或流为空则返回null
// 购票规则枚举
TpRuleExpressionGroupEnum expressionGroupEnum = getTpRuleExpressionGroupEnum(ticketTypeElement.get(0));
// 构建购票规则请求参数
subjectItem.getSubjectItemElements().forEach(element -> {
if (StrUtil.equals(element.getElementCode(), TpFactorCodeEnum.DATE.getCode())) {
// 构建规则入参
TpTicketBuyParamDTO tpTicketBuyParamDTO = buildTicketBuyParamDTO(element, shuttleDTOMap, shuttleCode);
// 获取放票时间
TpRuleExecuteDTO<TpTicketBuyParamDTO> tpRuleExecuteDTO = new TpRuleExecuteDTO<>();
List<TpBizRuleDTO> dayRules = rulesMap.get(ticketTypeEnum.getTicketRuleCode());
List<String> ruleList = Lists.newArrayList();
dayRules.forEach(dayRule -> ruleList.add(dayRule.getExpression()));
tpRuleExecuteDTO.setRuleList(ruleList);
tpRuleExecuteDTO.setParameter(tpTicketBuyParamDTO);
tpRuleExecuteDTO.setRuleExpressionGroup(expressionGroupEnum);
batchExecuteRuleDTOs.add(tpRuleExecuteDTO);
}
});
});
}
@NotNull
private static TpTicketBuyParamDTO buildTicketBuyParamDTO(TpOrderSubjectItemElementDTO element, Map<String, TpOrderRouteShuttleDTO> shuttleDTOMap, String shuttleCode) {
TpTicketBuyParamDTO tpTicketBuyParamDTO = new TpTicketBuyParamDTO();
// 放票日期
String salesUnitElementDate = element.getElementValue();
TpOrderRouteShuttleDTO tpOrderRouteShuttleDTO = shuttleDTOMap.get(shuttleCode);
if (tpOrderRouteShuttleDTO != null) {
tpTicketBuyParamDTO.setStartTime(salesUnitElementDate, tpOrderRouteShuttleDTO.getShuttleTime());
} else {
tpTicketBuyParamDTO.setStartTime(salesUnitElementDate);
}
return tpTicketBuyParamDTO;
}
private static TpRuleExpressionGroupEnum getTpRuleExpressionGroupEnum(TpOrderSubjectItemElementDTO tpOrderSubjectItemElementDTO) {
if (StrUtil.equals(tpOrderSubjectItemElementDTO.getElementValue(), TicketTypeEnum.SINGLE_RIDE.getType())) {
return TpRuleExpressionGroupEnum.TIMES_TICKET_RELEASE;
}
if (StrUtil.equals(tpOrderSubjectItemElementDTO.getElementValue(), TicketTypeEnum.WEEKLY.getType())) {
return TpRuleExpressionGroupEnum.WEEK_TICKET_RELEASE;
}
if (StrUtil.equals(tpOrderSubjectItemElementDTO.getElementValue(), TicketTypeEnum.MONTHLY.getType())) {
return TpRuleExpressionGroupEnum.MONTH_TICKET_RELEASE;
}
if (StrUtil.equals(tpOrderSubjectItemElementDTO.getElementValue(), TicketTypeEnum.SEMESTER.getType())) {
return TpRuleExpressionGroupEnum.SEMESTER_TICKET_RELEASE;
}
if (StrUtil.equals(tpOrderSubjectItemElementDTO.getElementValue(), TicketTypeEnum.DAY_RANGE.getType())) {
return TpRuleExpressionGroupEnum.DAY_RANGE_TICKET_RELEASE;
}
return null;
}
private void checkBuyLimitRules(TpProdOrderCreateDTO dto, Map<String, List<TpBizRuleDTO>> rulesMap) {
if (CollUtil.isEmpty(rulesMap.get(TpRuleExpressionGroupEnum.BUY_COUNT.getCode()))) {
LogUtil.warn("未配置购买限制规则");
return;
}
// 当前订单票数
int currentOrderTickets = dto.getOrderSubjectItem().stream().mapToInt(TpOrderSubjectItemDTO::getCount).sum();
List<TpBizRuleDTO> buyRules = rulesMap.get(TpRuleExpressionGroupEnum.BUY_COUNT.getCode());
int currentDayUserTickets = queryUserBuyTickets(dto);
// int currentDayUserTickets = 0;
TpBuyCountLimitParamDTO tpBuyCountLimitParamDTO = new TpBuyCountLimitParamDTO();
tpBuyCountLimitParamDTO.setDayBuyCount(currentDayUserTickets);
tpBuyCountLimitParamDTO.setOrderBuyCount(currentOrderTickets);
List<String> ruleList = Lists.newArrayList();
buyRules.forEach(rule -> ruleList.add(rule.getExpression()));
TpRuleExecuteDTO<TpBuyCountLimitParamDTO> tpRuleExecuteDTO = new TpRuleExecuteDTO<>();
// 设置表达式入参
tpRuleExecuteDTO.setParameter(tpBuyCountLimitParamDTO);
// 设置购买的规则表达式
tpRuleExecuteDTO.setRuleList(ruleList);
tpRuleExecuteDTO.setRuleExpressionGroup(TpRuleExpressionGroupEnum.BUY_COUNT);
TpRuleExecuteResultVO<Boolean> resultVO = bizRuleClient.executeRule(tpRuleExecuteDTO);
if (!resultVO.getResult()) {
LogUtil.error("当前用户:{}, 购买票数量超过限制", dto.getUserNo());
throw new TpTradeProdException(TpTradeProdErrorCode.USER_BUY_LIMIT_ERROR);
}
}
private int queryUserBuyTickets(TpProdOrderCreateDTO dto) {
TpUserTicketsQueryDTO ticketsQueryDTO = new TpUserTicketsQueryDTO();
ticketsQueryDTO.setUserNo(dto.getUserNo());
ticketsQueryDTO.setTenantId(dto.getTenantId());
ticketsQueryDTO.setCategoryNo(dto.getProductCategoryNo());
ticketsQueryDTO.setOrderStartTime(DateUtil.beginOfDay(DateUtil.date()).getTime());
ticketsQueryDTO.setOrderEndTime(DateUtil.endOfDay(DateUtil.date()).getTime());
return tpOrderClient.getUserBuyTickets(ticketsQueryDTO);
}
private static void checkFormalFlagAndRoute(TpProdDetailDTO product) {
if (!StrUtil.equals(product.getFormalFlag(), FormalFlagEnum.FORMAL.getCode())) {
LogUtil.error("当前产品为非正式版标识: {}", product.getFormalFlag());
throw new TpTradeProdException(TpTradeProdErrorCode.PRODUCT_FORMAL_FLAG_ERROR);
}
}
private void checkSalesUnit(TpProdOrderCreateDTO dto) {
// 查询售卖单元
List<TpSalesUnitVO> tpSalesUnitVOS = querySalesUnit(dto.getProductNo(), CollUtil.isEmpty(dto.getRoutes()) ? null : dto.getRoutes().get(0).getRouteNo(), dto.getTenantId());
LogUtil.info("查询的售卖单元为:{}", JSONObject.toJSONString(tpSalesUnitVOS));
// 售卖单元转为Map
Map<String, TpSalesUnitVO> saleUnitMap = tpSalesUnitVOS.stream().collect(Collectors.toMap(TpSalesUnitVO::getCode, Function.identity()));
List<String> salesUnit = tpSalesUnitVOS.stream().map(TpSalesUnitVO::getCode).collect(Collectors.toList());
// 判断售卖单元并塞入售卖单元的组成要素
dto.getOrderSubjectItem().forEach(subjectItem -> {
if (!salesUnit.contains(subjectItem.getItemNo())) {
LogUtil.error("售卖单元:{}, 不存在", subjectItem.getItemNo());
throw new TpTradeProdException(TpTradeProdErrorCode.SALE_UNIT_NOT_EXIST_ERROR);
}
List<TpSalesUnitElementVO> salesUnitElementList = saleUnitMap.get(subjectItem.getItemNo()).getSalesUnitElementList();
if (CollUtil.isEmpty(salesUnitElementList)) {
LogUtil.error("售卖单元:{}, 下没有对应的组成要素", subjectItem.getItemNo());
throw new TpTradeProdException(TpTradeProdErrorCode.SALES_UNIT_ELEMENTS_NOT_EXIST_ERROR);
}
checkSalesUnitElements(subjectItem, salesUnitElementList);
});
}
private void checkSalesUnitElements(TpOrderSubjectItemDTO subjectItem, List<TpSalesUnitElementVO> salesUnitElementList) {
Map<String, TpSalesUnitElementVO> elementMap = salesUnitElementList.stream().collect(Collectors.toMap(TpSalesUnitElementVO::getCode, Function.identity(), (k1, k2) -> k2));
subjectItem.getSubjectItemElements().forEach(itemElement -> {
TpSalesUnitElementVO tpSalesUnitElementVO = elementMap.get(itemElement.getElementCode());
if (ObjectUtil.isNull(tpSalesUnitElementVO)) {
LogUtil.error("组成要素:{}, 不存在", itemElement.getElementCode());
throw new TpTradeProdException(TpTradeProdErrorCode.SALES_UNIT_ELEMENTS_NOT_EXIST_ERROR);
}
itemElement.setItemNo(subjectItem.getItemNo());
itemElement.setElementCode(tpSalesUnitElementVO.getCode());
itemElement.setElementName(tpSalesUnitElementVO.getDescription());
itemElement.setElementValue(tpSalesUnitElementVO.getValue());
itemElement.setElementUnit(tpSalesUnitElementVO.getUnitCode());
});
}
private List<TpSalesUnitVO> querySalesUnit(String productNo, String routeNo, String tenantId) {
TpSalesUnitQueryDTO tpSalesUnitQueryDTO = new TpSalesUnitQueryDTO();
tpSalesUnitQueryDTO.setTenantId(tenantId);
tpSalesUnitQueryDTO.setProductCode(productNo);
tpSalesUnitQueryDTO.setRouteCode(routeNo);
return tpProductSalesUnitClient.listTpSalesUnit(tpSalesUnitQueryDTO);
}
private TpProdDetailDTO queryProduct(String productNo, String tenantId) {
TpProductQueryDTO tpProductQueryDTO = new TpProductQueryDTO();
tpProductQueryDTO.setProductCode(productNo);
tpProductQueryDTO.setFormalFlag(FormalFlagEnum.FORMAL.getCode());
tpProductQueryDTO.setTenantId(tenantId);
tpProductQueryDTO.setNeedProperties(Lists.newArrayList(
NeedPropertiesEnum.SERVICE_OBJECT.getCode(),
//NeedPropertiesEnum.SUBJECT_ITEM.getCode(),
NeedPropertiesEnum.SALES_UNIT.getCode(),
NeedPropertiesEnum.BIZ_RULE.getCode(),
NeedPropertiesEnum.ROUTE.getCode(),
NeedPropertiesEnum.FRONT_CATEGORY.getCode(),
NeedPropertiesEnum.BACK_CATEGORY.getCode(),
//NeedPropertiesEnum.PRICE_UNIT.getCode()
//NeedPropertiesEnum.INVENTORY.getCode()
NeedPropertiesEnum.EXTEND_ATTRIBUTE.getCode()
));
return tpProductClient.getProduct(tpProductQueryDTO);
}
}

View File

@@ -0,0 +1,124 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderPriceRecordDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderRescheduleDTO;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderRescheduleInfoDTO;
import com.deepinnet.tptradeprod.common.service.integration.convert.TpOrderConverter;
import com.deepinnet.tptradeprod.common.vo.TpOrderPriceRecordVO;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderPriceRecordDetailVO;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* <p>
* 改签询价节点
* </p>
*
* @author chenjiaju
* @since 2023/7/20
*/
@LiteflowComponent(value = "rescheduleInquireCheckNode", name = "改签询价节点")
@LiteflowCmpDefine
@RequiredArgsConstructor
public class TpRescheduleInquireCheckNode {
private final TpOrderConverter orderConverter;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 改签询价节点");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
// 创建订单参数
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
// 改签原始订单详情
TpProdOrderDetailVO orderDetailVO = userPlaceOrderContext.getOrderDetailVO();
// 改签信息
TpProdOrderRescheduleDTO orderRescheduleDTO = userPlaceOrderContext.getOrderRescheduleDTO();
// 询价 & 价格校验
createDTO.setTpOrderPriceRecords(checkPrice(orderDetailVO, orderRescheduleDTO, createDTO));
}
/**
* 在这里构建询价信息 产品侧未收拢,订单侧临时收拢售卖单元替换
* @param oldOrderDetailVO 改签原始订单详情
* @param orderRescheduleDTO 改签信息
* @return 询价结果
*/
private List<TpProdOrderPriceRecordDTO> checkPrice(TpProdOrderDetailVO oldOrderDetailVO, TpProdOrderRescheduleDTO orderRescheduleDTO, TpProdOrderCreateDTO createDTO) {
// 根据报价记录构建询价信息
List<TpOrderPriceRecordVO> orderPriceRecordList = oldOrderDetailVO.getOrderPriceRecord();
Assert.notEmpty(orderPriceRecordList, "原订单历史询价信息为空");
List<TpProdOrderRescheduleInfoDTO> rescheduleInfos = Lists.newArrayList();
orderRescheduleDTO.getRescheduleRecords().forEach(record -> rescheduleInfos.addAll(record.getOrderRescheduleInfos()));
// 构建旧售卖单元与新售卖单元Map
Map<String, String> oldSaleUnitMappingNewSaleUnit = rescheduleInfos.stream()
.collect(Collectors.toMap(TpProdOrderRescheduleInfoDTO::getSubjectItemNo, TpProdOrderRescheduleInfoDTO::getRescheduleSubjectItemNo, (k1, k2) -> k2));
// 替换售卖单元编号
// 订单记录改签的价格信息替换
BigDecimal discountAmount = BigDecimal.ZERO;
BigDecimal originalAmount = BigDecimal.ZERO;
for (TpOrderPriceRecordVO priceRecord : orderPriceRecordList) {
for (TpProdOrderPriceRecordDetailVO priceDetail : priceRecord.getOrderPriceRecordDetails()) {
String newSaleUnitNo = oldSaleUnitMappingNewSaleUnit.get(priceDetail.getItemNo());
List<TpProdOrderRescheduleInfoDTO> rescheduleInfosByReSubjectItemNo = rescheduleInfos.stream().filter(info -> info.getRescheduleSubjectItemNo().equals(newSaleUnitNo)).collect(Collectors.toList());
BigDecimal singleDiscountAmount = new BigDecimal(priceDetail.getSingleDiscountAmount());
BigDecimal singleOriginalAmount = new BigDecimal(priceDetail.getSingleOriginalAmount());
// 实名制
if (StrUtil.isNotBlank(newSaleUnitNo)){
priceDetail.setItemNo(newSaleUnitNo);
// 拉了一坨粑粑
if (oldOrderDetailVO.getIdentityVerificat() == 1) {
for (TpProdOrderRescheduleInfoDTO rescheduleInfo : rescheduleInfosByReSubjectItemNo) {
if (StrUtil.equals(priceDetail.getPassengerType(), rescheduleInfo.getPassengerType())) {
discountAmount = discountAmount.add(singleDiscountAmount.multiply(new BigDecimal(rescheduleInfo.getPassengerCount())));
originalAmount = originalAmount.add(singleOriginalAmount.multiply(new BigDecimal(rescheduleInfo.getPassengerCount())));
}
}
}
// 非实名
if (oldOrderDetailVO.getIdentityVerificat() == 0) {
priceDetail.setItemNo(newSaleUnitNo);
Map<String, TpProdOrderRescheduleInfoDTO> rescheduleInfoDTOMap = rescheduleInfosByReSubjectItemNo.stream().collect(Collectors.toMap(TpProdOrderRescheduleInfoDTO::getRescheduleSubjectItemNo, Function.identity()));
discountAmount = discountAmount.add(singleDiscountAmount.multiply(new BigDecimal(rescheduleInfoDTOMap.get(newSaleUnitNo).getPassengerCount())));
originalAmount = originalAmount.add(singleOriginalAmount.multiply(new BigDecimal(rescheduleInfoDTOMap.get(newSaleUnitNo).getPassengerCount())));
}
}
}
}
createDTO.setOriginalAmount(originalAmount.setScale(2, RoundingMode.DOWN).toString());
createDTO.setPayAmount(discountAmount.setScale(2, RoundingMode.DOWN).toString());
LogUtil.info("替换后询价信息:{}", JSONUtil.toJsonStr(orderPriceRecordList));
return orderConverter.convert2OrderPriceDTO(orderPriceRecordList);
}
}

View File

@@ -0,0 +1,63 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.json.JSONUtil;
import com.deepinnet.tp.common.lang.result.TpResult;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.context.*;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.enums.TpFlowProcessTypeEnum;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.deepinnet.tptradeprod.common.service.facade.TpVoucherAcceptanceFacade;
import com.deepinnet.tptradeprod.common.vo.TpQueryAvailableRescheduleVoucherDTO;
import com.yomahub.liteflow.annotation.*;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import org.apache.commons.collections4.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
@LiteflowComponent(value = "invalidVoucherCheckNode", name = "改签失效凭证校验节点")
@LiteflowCmpDefine
@LiteflowRetry(retry = 3)
public class TpRescheduleVoucherInvalidCheckNode {
@Resource
private TpVoucherAcceptanceFacade voucherAcceptanceFacade;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点:改签失效凭证校验节点");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
List<TpProdInvalidVoucherDTO> invalidVoucherDTOs = userPlaceOrderContext.getOrderRescheduleDTO().getInvalidVoucherDTOs();
List<String> voucherNos = invalidVoucherDTOs
.stream()
.distinct()
.map(TpProdInvalidVoucherDTO::getVoucherNo)
.collect(Collectors.toList());
TpProdQueryAvailableRescheduleVoucherDTO queryDTO = new TpProdQueryAvailableRescheduleVoucherDTO();
queryDTO.setProductCode(userPlaceOrderContext.getOrderDetailVO().getProductNo());
queryDTO.setApplyTime(System.currentTimeMillis());
queryDTO.setTenantId(userPlaceOrderContext.getTenantId());
queryDTO.setOrderDetailVO(userPlaceOrderContext.getOrderDetailVO());
queryDTO.setProcessType(TpFlowProcessTypeEnum.CONFIRM_RESCHEDULE_ORDER.getCode());
queryDTO.setVoucherNos(voucherNos);
TpResult<TpQueryAvailableRescheduleVoucherDTO> result = voucherAcceptanceFacade.queryAvailableRescheduleVoucherList(queryDTO);
if (!result.isSuccess()) {
LogUtil.error("改签失效凭证节点校验失败,当前选中的凭证不支持改签,上下文为:{}", JSONUtil.toJsonStr(userPlaceOrderContext));
throw new TpTradeProdException(TpTradeProdErrorCode.RESCHEDULE_INVALID_VOUCHER_PROCESS_ERROR, TpTradeProdErrorCode.RESCHEDULE_INVALID_VOUCHER_PROCESS_ERROR.getDesc());
}
List<TpAvailableRescheduleVoucherDTO> voucherList = result.getData().getVoucherList();
if (CollectionUtils.isEmpty(voucherList) || voucherList.size() != voucherNos.size()) {
LogUtil.error("待改签的凭证对应的发车时间不支持改签,上下文为:{}", JSONUtil.toJsonStr(userPlaceOrderContext));
throw new TpTradeProdException(TpTradeProdErrorCode.RESCHEDULE_INVALID_VOUCHER_PROCESS_ERROR, TpTradeProdErrorCode.RESCHEDULE_INVALID_VOUCHER_PROCESS_ERROR.getDesc());
}
}
}

View File

@@ -0,0 +1,155 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.check;
import cn.hutool.json.JSONUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpbaseopcore.common.dto.route.RouteRollTimeDetailDTO;
import com.deepinnet.tpproductcore.common.dto.rule.*;
import com.deepinnet.tpproductcore.common.enums.TpRuleExpressionGroupEnum;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpRescheduleOrderContext;
import com.deepinnet.tptradeprod.biz.util.*;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.deepinnet.tptradeprod.common.service.integration.client.*;
import com.deepinnet.tptradeprod.common.vo.*;
import com.google.common.collect.Lists;
import com.yomahub.liteflow.annotation.*;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
@LiteflowComponent(value = "rescheduleVoucherTimeCheckNode", name = "改签订单凭证时间校验节点")
@LiteflowCmpDefine
public class TpRescheduleVoucherTimeCheckNode {
@Resource
private TpBizRuleClient bizRuleClient;
@Resource
private TpRouteClient routeClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 改签订单凭证时间校验节点");
TpRescheduleOrderContext rescheduleOrderContext = bindCmp.getContextBean(TpRescheduleOrderContext.class);
TpProdOrderDetailVO orderDetailVO = rescheduleOrderContext.getOrderDetailVO();
List<TpProdVoucherDTO> voucherList = rescheduleOrderContext.getVoucherList();
Long applyTime = rescheduleOrderContext.getApplyTime();
List<String> expressionList = rescheduleOrderContext.getRuleExpressionList();
String tenantId = rescheduleOrderContext.getTenantId();
List<Long> firstShuttleDepartureTimeList = calculateFirstShuttleDepartureTime(voucherList, orderDetailVO, tenantId);
// 20240718 与开阳确认批量接口返回的list是严格按照入参的顺序返回的
List<Boolean> resultList = rescheduleTicketTimeRuleCheck(firstShuttleDepartureTimeList, expressionList, applyTime, tenantId);
List<TpProdVoucherDTO> invalidRescheduleVouchers = Lists.newArrayList();
for (int i = 0; i < resultList.size(); i++) {
TpProdVoucherDTO voucherDTO = voucherList.get(i);
if (!resultList.get(i)) {
invalidRescheduleVouchers.add(voucherDTO);
}
}
voucherList.removeAll(invalidRescheduleVouchers);
if (CollectionUtils.isEmpty(voucherList)) {
LogUtil.error("当前订单不存在支持改签的凭证,只有未核销的次票支持改签,订单号:{}", rescheduleOrderContext.getOrderNo());
throw new TpTradeProdException(TpTradeProdErrorCode.NOT_FOUND_AVAILABLE_RESCHEDULE_VOUCHER);
}
TpQueryAvailableRescheduleVoucherDTO rescheduleVoucherDTO = buildAvailableRescheduleVoucherVO(voucherList, orderDetailVO, voucherList.get(0).getType());
rescheduleOrderContext.setRescheduleVoucherDTO(rescheduleVoucherDTO);
}
private TpQueryAvailableRescheduleVoucherDTO buildAvailableRescheduleVoucherVO(List<TpProdVoucherDTO> availableVoucherList, TpProdOrderDetailVO orderDetailVO, String voucherType) {
List<TpAvailableRescheduleVoucherDTO> availableRescheduleVouchers = Lists.newArrayList();
availableVoucherList.forEach(v -> {
Integer availableRescheduleCount = TpVoucherUtil.calculateRefundPassengerCount(v);
TpAvailableRescheduleVoucherDTO availableRescheduleVoucher = new TpAvailableRescheduleVoucherDTO();
availableRescheduleVoucher.setSalesUnitCode(v.getSalesUnitCode());
availableRescheduleVoucher.setPassenger(v.getPassenger());
availableRescheduleVoucher.setVoucherNo(v.getVoucherNo());
availableRescheduleVoucher.setTripType(v.getTripType());
availableRescheduleVoucher.setOrderNo(v.getOrderNo());
availableRescheduleVoucher.setType(v.getType());
availableRescheduleVoucher.setAvailableReschedulePassengerCount(availableRescheduleCount);
availableRescheduleVouchers.add(availableRescheduleVoucher);
});
List<String> tripTypes = availableVoucherList.stream()
.map(TpProdVoucherDTO::getTripType)
.distinct()
.collect(Collectors.toList());
TpQueryAvailableRescheduleVoucherDTO queryVO = new TpQueryAvailableRescheduleVoucherDTO();
queryVO.setVoucherList(availableRescheduleVouchers);
queryVO.setVoucherType(voucherType);
queryVO.setTripTypes(tripTypes);
queryVO.setTpOrderRoute(orderDetailVO.getTpOrderRoutes().get(0));
return queryVO;
}
/**
* 改签时间规则校验
*/
private List<Boolean> rescheduleTicketTimeRuleCheck(List<Long> departureTimeList, List<String> expressionList, Long applyTime, String tenantId) {
List<TpRuleExecuteDTO<TpRescheduleParamDTO>> executeDTOs = Lists.newArrayList();
for (Long departureTime : departureTimeList) {
TpRuleExecuteDTO<TpRescheduleParamDTO> executeDTO = new TpRuleExecuteDTO<>();
TpRescheduleParamDTO rescheduleParamDTO = new TpRescheduleParamDTO();
rescheduleParamDTO.setRescheduleTime(System.currentTimeMillis());
rescheduleParamDTO.setDepartureTime(departureTime);
executeDTO.setParameter(rescheduleParamDTO);
executeDTO.setRuleList(expressionList);
executeDTO.setRuleExpressionGroup(TpRuleExpressionGroupEnum.RESCHEDULE_RESTRICTION);
executeDTO.setTenantId(tenantId);
executeDTOs.add(executeDTO);
}
TpRuleExecuteBatchResultVO<Boolean> executeResultVO = bizRuleClient.batchExecuteBizRule(executeDTOs);
List<TpRuleExecuteResultVO<Boolean>> resultList = executeResultVO.getResultList();
if (CollectionUtils.isEmpty(resultList)) {
LogUtil.error("改签时间规则校验失败,结果返回为空,入参:{}", JSONUtil.toJsonStr(executeDTOs));
throw new TpTradeProdException(TpTradeProdErrorCode.NOT_SUPPORT_RESCHEDULE_TIME);
}
List<Boolean> res = resultList.stream().map(TpRuleExecuteResultVO::getResult).collect(Collectors.toList());
LogUtil.info("判断凭证发车时间能否改签,调用规则域结果为:{},入参为:{}", JSONUtil.toJsonStr(executeResultVO), JSONUtil.toJsonStr(executeDTOs));
return res;
}
private List<Long> calculateFirstShuttleDepartureTime(List<TpProdVoucherDTO> voucherList, TpProdOrderDetailVO orderDetail, String tenantId) {
List<TpOrderRouteVO> orderRoutes = orderDetail.getTpOrderRoutes();
Assert.notEmpty(orderRoutes, "线路信息不能为空");
TpOrderRouteVO routeVO = orderRoutes.get(0);
List<Long> departureTimeList = Lists.newArrayList();
// 有班次,普通班车
if (routeVO.getTpOrderRouteShuttle() != null) {
List<TpOrderRouteShuttleVO> orderRouteShuttleList = routeVO.getTpOrderRouteShuttle();
Map<String, List<TpOrderRouteShuttleVO>> orderRouteShuttleMap = orderRouteShuttleList.stream()
.collect(Collectors.groupingBy(TpOrderRouteShuttleVO::getShuttleNo));
voucherList.forEach(voucherDTO -> {
TpOrderRouteShuttleVO routeShuttle = orderRouteShuttleMap.get(voucherDTO.getShuttleId()).get(0);
Long departureTime = TimeConvertUtil.convertDateAndTime2Timestamp(voucherDTO.getEffectiveStartTime(), routeShuttle.getShuttleTime());
departureTimeList.add(departureTime);
});
} else {
// 滚动发车
RouteRollTimeDetailDTO routeRollTimeDetail = routeClient.getRouteRollTime(routeVO.getRouteNo(), tenantId);
Assert.notNull(routeRollTimeDetail, "线路详情不能为空");
String roundTrip = routeVO.getRoundTrip();
return TpVoucherUtil.calculateRollTimeRouteVoucherDepartureTime(roundTrip, voucherList, routeRollTimeDetail);
}
return departureTimeList;
}
}

View File

@@ -0,0 +1,74 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.execute;
import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpproductcore.common.dto.inventory.TpInventoryOperationDTO;
import com.deepinnet.tpproductcore.common.enums.*;
import com.deepinnet.tptradeprod.biz.service.flow.refundTicket.context.TpRefundTicketCommonContext;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.service.integration.client.TpInventoryClient;
import com.google.common.collect.Lists;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import org.apache.commons.collections4.CollectionUtils;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @author amos wong
* @create 2023/10/16 15:38
* @Description
*/
/*@LiteflowComponent(value = "deductToRollbackInventoryNode", name = "回滚已扣减库存节点")
@LiteflowCmpDefine
@LiteflowRetry(retry = 3)*/
@Deprecated
public class BatchDeductToRollbackInventoryNode {
//@Resource
private TpInventoryClient inventoryClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
TpRefundTicketCommonContext commonContext = bindCmp.getContextBean(TpRefundTicketCommonContext.class);
LogUtil.info("执行批量扣减库存节点,入参为:{}", JSONUtil.toJsonStr(commonContext));
List<TpProdRefundApplyOrderDTO> refundApplyOrderList = commonContext.getRefundApplyOrderDTOs();
TpProdRefundApplyDTO refundApplyDTO = commonContext.getRefundTicketApplyContext().getRefundApplyDTO();
Assert.notEmpty(refundApplyOrderList, "退票申请单不存在");
Assert.isTrue(refundApplyOrderList.size() == 1, "同一个退票申请单号查询到多笔退票申请单");
TpProdRefundApplyOrderDTO refundApplyOrderDTO = refundApplyOrderList.get(0);
List<TpRefundSubjectItemDTO> refundSubjectItemDTOs = refundApplyOrderDTO.getSubjectItemList();
List<TpInventoryOperationDTO> operationDTOs = Lists.newArrayList();
Map<String, Integer> refundItemMap;
// 实名认证
if (CollectionUtils.isNotEmpty(refundApplyDTO.getRealNameTicketRefundChoiceDTOs())) {
refundItemMap = refundSubjectItemDTOs.stream().collect(Collectors.groupingBy(TpRefundSubjectItemDTO::getSubjectItemId, Collectors.collectingAndThen(Collectors.toList(), List::size)));
} else {
refundItemMap = refundSubjectItemDTOs.stream().collect(Collectors.groupingBy(TpRefundSubjectItemDTO::getSubjectItemId, Collectors.summingInt(TpRefundSubjectItemDTO::getQuantity)));
}
AtomicInteger sequence = new AtomicInteger(0);
refundItemMap.forEach((itemNo, count) -> {
TpInventoryOperationDTO operationDTO = new TpInventoryOperationDTO();
operationDTO.setCarrierCode(itemNo);
operationDTO.setBizType(TpInventoryBizTypeEnum.ORDER.getType());
operationDTO.setBizNo(refundApplyOrderDTO.getRefundApplyOrderNo());
operationDTO.setOperationInventoryCount(count);
operationDTO.setOperationType(TpInventoryOperationTypeEnum.DEDUCT_TO_ROLLBACK.getType());
operationDTO.setTransactionNo(refundApplyOrderDTO.getRefundApplyOrderNo() + sequence);
operationDTO.setTenantId(refundApplyDTO.getTenantId());
operationDTOs.add(operationDTO);
sequence.incrementAndGet();
});
inventoryClient.batchOperateInventory(operationDTOs);
}
}

View File

@@ -0,0 +1,812 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.execute;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.*;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.*;
import cn.hutool.json.JSONUtil;
import com.deepinnet.tp.common.lang.constants.GlobalConstants;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpbaseopcore.common.constants.RouteConstants;
import com.deepinnet.tpbaseopcore.common.dto.route.RouteRollTimeDetailDTO;
import com.deepinnet.tpbaseopcore.common.dto.time.RollTimeDTO;
import com.deepinnet.tpproductcore.common.dto.product.*;
import com.deepinnet.tpproductcore.common.dto.rule.*;
import com.deepinnet.tpproductcore.common.dto.rule.result.TpTicketShowStartTimeResult;
import com.deepinnet.tpproductcore.common.enums.*;
import com.deepinnet.tpproductcore.common.utils.TicketDateRangeParser;
import com.deepinnet.tptradecore.common.enums.order.TpOrderModulesEnum;
import com.deepinnet.tptradecore.common.enums.voucher.*;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.*;
import com.deepinnet.tptradeprod.common.enums.*;
import com.deepinnet.tptradeprod.common.error.TpTradeProdErrorCode;
import com.deepinnet.tptradeprod.common.exception.TpTradeProdException;
import com.deepinnet.tptradeprod.common.service.integration.client.*;
import com.deepinnet.tptradeprod.common.service.integration.convert.TpBizRuleConvert;
import com.deepinnet.tptradeprod.common.util.constants.BizDataKeyConstants;
import com.deepinnet.tptradeprod.common.vo.*;
import com.google.common.collect.*;
import com.yomahub.liteflow.annotation.*;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.*;
import org.springframework.util.Assert;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* <p>
* 构建凭证节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "buildVoucherNode", name = "生成凭证节点")
@LiteflowCmpDefine
@LiteflowRetry(retry = 3)
@RequiredArgsConstructor
public class TpBuildVoucherNode {
private final TpOrderClient tpOrderClient;
private final TpVoucherClient tpVoucherClient;
private final TpBizRuleClient bizRuleClient;
private final TpRouteClient routeClient;
private final TpBizRuleConvert bizRuleConvert;
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern(GlobalConstants.TIME_FORMAT);
private static final String EVERY_DAY_LAST_TIME = "23:59";
private static final String EVERY_DAY_EARLIEST_TIME = "00:00";
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 生成凭证");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdDetailDTO productDetailDTO = userPlaceOrderContext.getProductDTO();
TpProdOrderDetailVO orderDetail;
String processType = userPlaceOrderContext.getProcessType();
// 确认改签接口需要重新查询最新的订单详情
if (StringUtils.equals(processType, TpFlowProcessTypeEnum.CONFIRM_RESCHEDULE_ORDER.getCode())) {
TpProdOrderQueryDTO orderQueryDTO = new TpProdOrderQueryDTO();
orderQueryDTO.setOrderNo(userPlaceOrderContext.getOrderNo());
orderQueryDTO.setTenantId(userPlaceOrderContext.getTenantId());
orderQueryDTO.setNeedModules(Lists.newArrayList(TpOrderModulesEnum.ORDER_ROUTE_INFO.getModule(), TpOrderModulesEnum.ORDER_SUBJECT_ITEM.getModule(), TpOrderModulesEnum.ORDER_TRAVEL_TRIP.getModule()));
orderDetail = tpOrderClient.getOrderDetail(orderQueryDTO);
} else {
// 订单查询
orderDetail = userPlaceOrderContext.getOrderDetailVO();
}
// 塞入订单详情
userPlaceOrderContext.setOrderDetailVO(orderDetail);
List<TpBizRuleDTO> rules = productDetailDTO.getRules();
Assert.notEmpty(rules, "产品的规则列表不能为空");
// 每个乘客每天限制乘车次数
List<TpBizRuleDTO> allNeedSaveRules = Lists.newArrayList();
Map<String, List<TpBizRuleDTO>> bizRuleMap = rules.stream().collect(Collectors.groupingBy(TpBizRuleDTO::getRuleGroup));
List<TpBizRuleDTO> ticketCheckRules = bizRuleMap.get(TpRuleExpressionGroupEnum.TICKET_CHECK.getCode());
Assert.notEmpty(ticketCheckRules, "凭证检票规则不能为空");
allNeedSaveRules.addAll(ticketCheckRules);
// 处理普通单程车票
Map<String, Integer> perTicketTotalAvailableCountMap;
if (!StringUtils.equals(orderDetail.getTripType(), TpTripTypeEnum.ROUND.getCode())) {
Integer perTicketTotalAvailableCount = getSingleTripPerTicketTotalAvailableCount(orderDetail, bizRuleMap, allNeedSaveRules, userPlaceOrderContext);
perTicketTotalAvailableCountMap = Maps.newHashMap();
perTicketTotalAvailableCountMap.put(orderDetail.getTripType(), perTicketTotalAvailableCount);
} else {
perTicketTotalAvailableCountMap = getRoundTripPerTicketTotalAvailableCount(orderDetail, bizRuleMap, allNeedSaveRules, userPlaceOrderContext);
}
// 构建凭证
TpProdVoucherCreateDTO tpProdVoucherCreateDTO = buildVoucherCreateDTO(userPlaceOrderContext.getTenantId(), orderDetail, perTicketTotalAvailableCountMap, productDetailDTO, allNeedSaveRules);
// 生成凭证
tpVoucherClient.generateVoucher(tpProdVoucherCreateDTO);
}
private Map<String, Integer> getRoundTripPerTicketTotalAvailableCount(TpProdOrderDetailVO orderDetail, Map<String, List<TpBizRuleDTO>> bizRuleMap, List<TpBizRuleDTO> allNeedSaveRules, TpUserPlaceOrderContext userPlaceOrderContext) {
if (!StringUtils.equals(orderDetail.getTicketType(), TpProdOrderTicketTypeEnum.DAY.getTicketType())) {
LogUtil.error("当前车票类型不允许购买往返程,订单编号:{},车票类型:{}", orderDetail.getOrderNo(), orderDetail.getTicketType());
throw new TpTradeProdException(TpTradeProdErrorCode.ROUND_TRIP_NOT_SUPPORT_TICKET_TYPE, TpTradeProdErrorCode.ROUND_TRIP_NOT_SUPPORT_TICKET_TYPE.getDesc());
}
List<TpBizRuleDTO> everyDayCountRules = bizRuleMap.get(TpRuleExpressionGroupEnum.SINGLE_TICKET_TRIPS_LIMIT.getCode());
Assert.notEmpty(everyDayCountRules, "次票的每天每个乘客乘车次数限制规则不能为空");
allNeedSaveRules.addAll(everyDayCountRules);
List<String> everyDayCountExpressionList = everyDayCountRules.stream().map(TpBizRuleDTO::getExpression).collect(Collectors.toList());
Optional<TpOrderSubjectItemVO> goOptional = orderDetail.getOrderSubjectItem().stream()
.filter(i -> StringUtils.equals(i.getTripType(), TpTripTypeEnum.GO.getCode()))
.findFirst();
Optional<TpOrderSubjectItemVO> backOptional = orderDetail.getOrderSubjectItem().stream()
.filter(i -> StringUtils.equals(i.getTripType(), TpTripTypeEnum.BACK.getCode()))
.findFirst();
if (goOptional.isEmpty() || backOptional.isEmpty()) {
LogUtil.error("往返程车票去程标的项或者返程标的项不存在, 标的项信息为:{}", JSONUtil.toJsonStr(orderDetail.getOrderSubjectItem()));
throw new TpTradeProdException(TpTradeProdErrorCode.RESCHEDULE_NOT_FOUND_TRIP_TYPE_SUBJECT_ITEM);
}
Integer goPassengerCount = goOptional.get().getCount();
Integer backPassengerCount = backOptional.get().getCount();
// 获取每张票的总的可用次数,次票调用每日每天限乘次数规则即可
return getRoundTripDayTicketPerTicketTotalAvailableCount(everyDayCountExpressionList, goPassengerCount, backPassengerCount, userPlaceOrderContext.getTenantId());
}
private Integer getSingleTripPerTicketTotalAvailableCount(TpProdOrderDetailVO orderDetail, Map<String, List<TpBizRuleDTO>> bizRuleMap, List<TpBizRuleDTO> allNeedSaveRules, TpUserPlaceOrderContext userPlaceOrderContext) {
// 乘车人数
Integer passengerCount = Objects.equals(orderDetail.getIdentityVerificat(), TpProdOrderIdentityFlagEnum.NOT_REAL_NAME_ORDER.getIdentityFlag()) ? orderDetail.getOrderSubjectItem().get(0).getCount() : 1;
Integer perTicketTotalAvailableCount;
if (StringUtils.equals(orderDetail.getTicketType(), TpProdOrderTicketTypeEnum.DAY.getTicketType())) {
List<TpBizRuleDTO> everyDayCountRules = bizRuleMap.get(TpRuleExpressionGroupEnum.SINGLE_TICKET_TRIPS_LIMIT.getCode());
Assert.notEmpty(everyDayCountRules, "次票的每天每个乘客乘车次数限制规则不能为空");
allNeedSaveRules.addAll(everyDayCountRules);
List<String> everyDayCountExpressionList = everyDayCountRules.stream().map(TpBizRuleDTO::getExpression).collect(Collectors.toList());
// 获取每张票的总的可用次数,日票调用每日每天限乘次数规则即可
perTicketTotalAvailableCount = getDayTicketPerTicketTotalAvailableCount(everyDayCountExpressionList, passengerCount, userPlaceOrderContext.getTenantId());
// 非日票需要调用获取票可用总次数的接口
} else if (StringUtils.equals(orderDetail.getTicketType(), TpProdOrderTicketTypeEnum.WEEK.getTicketType())) {
// 周票总可用次数
perTicketTotalAvailableCount = getPerTicketTotalAvailableCount(bizRuleMap, allNeedSaveRules, passengerCount, TpRuleExpressionGroupEnum.WEEK_TICKET_USE_LIMIT, TpRuleExpressionGroupEnum.WEEK_TICKET_TRIPS_LIMIT, userPlaceOrderContext.getTenantId());
} else if (StringUtils.equals(orderDetail.getTicketType(), TpProdOrderTicketTypeEnum.MONTH.getTicketType())) {
// 月票总可用次数
perTicketTotalAvailableCount = getPerTicketTotalAvailableCount(bizRuleMap, allNeedSaveRules, passengerCount, TpRuleExpressionGroupEnum.MONTH_TICKET_USE_LIMIT, TpRuleExpressionGroupEnum.MONTH_TICKET_TRIPS_LIMIT, userPlaceOrderContext.getTenantId());
} else if (StringUtils.equals(orderDetail.getTicketType(), TpProdOrderTicketTypeEnum.TERM.getTicketType())) {
perTicketTotalAvailableCount = getPerTicketTotalAvailableCount(bizRuleMap, allNeedSaveRules, passengerCount, TpRuleExpressionGroupEnum.SEMESTER_TICKET_USE_LIMIT, TpRuleExpressionGroupEnum.SEMESTER_TICKET_TRIPS_LIMIT, userPlaceOrderContext.getTenantId());
} else if (StringUtils.equals(orderDetail.getTicketType(), TpProdOrderTicketTypeEnum.DAY_RANGE.getTicketType())) {
perTicketTotalAvailableCount = getPerTicketTotalAvailableCount(bizRuleMap, allNeedSaveRules, passengerCount, TpRuleExpressionGroupEnum.DAY_RANGE_TICKET_USE_LIMIT, TpRuleExpressionGroupEnum.DAY_RANGE_TICKET_TRIPS_LIMIT, userPlaceOrderContext.getTenantId());
} else {
LogUtil.error("支付成功生成凭证时错误,原因为:当前用户购买了不支持的票种类型,订单编号为:{}", orderDetail.getOrderNo());
throw new TpTradeProdException(TpTradeProdErrorCode.INVALID_TICKET_TYPE);
}
return perTicketTotalAvailableCount;
}
private Integer getPerTicketTotalAvailableCount(Map<String, List<TpBizRuleDTO>> bizRuleMap, List<TpBizRuleDTO> allNeedSaveRules, Integer passengerCount,
TpRuleExpressionGroupEnum everyDayCountRuleGroup, TpRuleExpressionGroupEnum totalCountRuleGroup, String tenantId) {
// 先保存每天总可用次数的规则
List<TpBizRuleDTO> everyDayAvailableCountRules = bizRuleMap.get(everyDayCountRuleGroup.getCode());
Assert.notEmpty(everyDayAvailableCountRules, "每天可用次数规则不能为空");
allNeedSaveRules.addAll(everyDayAvailableCountRules);
// 获取总可用次数的规则
List<TpBizRuleDTO> totalCountBizRules = bizRuleMap.get(totalCountRuleGroup.getCode());
Assert.notEmpty(totalCountBizRules, "总可用次数规则不能为空");
allNeedSaveRules.addAll(totalCountBizRules);
List<String> totalCountExpressionList = totalCountBizRules.stream().map(TpBizRuleDTO::getExpression).collect(Collectors.toList());
return getNonDailyTicketPerTicketTotalAvailableCount(totalCountExpressionList, passengerCount, totalCountRuleGroup, tenantId);
}
private TpProdOrderDetailVO queryOrderDetail(String orderNo, String tenantId) {
List<String> modules = Lists.newArrayList();
modules.add(TpOrderModulesEnum.ORDER_SUBJECT_ITEM.getModule());
modules.add(TpOrderModulesEnum.ORDER_ROUTE_INFO.getModule());
modules.add(TpOrderModulesEnum.ORDER_TRAVEL_TRIP.getModule());
return tpOrderClient.getOrderDetail(TpProdOrderQueryDTO.builder()
.orderNo(orderNo)
.tenantId(tenantId)
.needModules(modules).build());
}
/**
* 获取日票的总可用次数
*
* @param expressionList 规则表达式,取每天每个乘客可乘坐次数规则
* @param passengerCount 乘客人数
* @return
*/
private Integer getDayTicketPerTicketTotalAvailableCount(List<String> expressionList, Integer passengerCount, String tenantId) {
TpRuleExecuteDTO<TpRollShuttleTripsParamDTO> ruleExecuteDTO = new TpRuleExecuteDTO<>();
TpRollShuttleTripsParamDTO checkParamDTO = new TpRollShuttleTripsParamDTO();
ruleExecuteDTO.setRuleList(expressionList);
ruleExecuteDTO.setParameter(checkParamDTO);
ruleExecuteDTO.setTenantId(tenantId);
checkParamDTO.setPassengerCount(passengerCount);
ruleExecuteDTO.setRuleExpressionGroup(TpRuleExpressionGroupEnum.SINGLE_TICKET_TRIPS_LIMIT);
TpRuleExecuteResultVO<Integer> executeResult = bizRuleClient.executeRule(ruleExecuteDTO);
return executeResult.getResult();
}
private Map<String, Integer> getRoundTripDayTicketPerTicketTotalAvailableCount(List<String> expressionList, Integer goPassengerCount, Integer backPassengerCount, String tenantId) {
List<TpRuleExecuteDTO<TpRollShuttleTripsParamDTO>> executeDTOs = Lists.newArrayList();
TpRuleExecuteDTO<TpRollShuttleTripsParamDTO> goRuleExecuteDTO = new TpRuleExecuteDTO<>();
TpRollShuttleTripsParamDTO checkParamDTO = new TpRollShuttleTripsParamDTO();
goRuleExecuteDTO.setRuleList(expressionList);
goRuleExecuteDTO.setParameter(checkParamDTO);
goRuleExecuteDTO.setTenantId(tenantId);
checkParamDTO.setPassengerCount(goPassengerCount);
goRuleExecuteDTO.setRuleExpressionGroup(TpRuleExpressionGroupEnum.SINGLE_TICKET_TRIPS_LIMIT);
executeDTOs.add(goRuleExecuteDTO);
TpRuleExecuteDTO<TpRollShuttleTripsParamDTO> backRuleExecuteDTO = new TpRuleExecuteDTO<>();
TpRollShuttleTripsParamDTO backCheckParamDTO = new TpRollShuttleTripsParamDTO();
backRuleExecuteDTO.setRuleList(expressionList);
backRuleExecuteDTO.setParameter(backCheckParamDTO);
backRuleExecuteDTO.setTenantId(tenantId);
backCheckParamDTO.setPassengerCount(backPassengerCount);
backRuleExecuteDTO.setRuleExpressionGroup(TpRuleExpressionGroupEnum.SINGLE_TICKET_TRIPS_LIMIT);
executeDTOs.add(backRuleExecuteDTO);
TpRuleExecuteBatchResultVO<Integer> executeBatchResultVO = bizRuleClient.batchExecuteBizRule(executeDTOs);
List<TpRuleExecuteResultVO<Integer>> resultList = executeBatchResultVO.getResultList();
if (CollectionUtils.isEmpty(resultList)) {
LogUtil.error("总检票次数规则校验失败,结果返回为空,入参:{}", JSONUtil.toJsonStr(executeDTOs));
throw new TpTradeProdException(TpTradeProdErrorCode.INVALID_REFUND_TIME);
}
Map<String, Integer> resMap = new HashMap<>();
resMap.put(TpTripTypeEnum.GO.getCode(), resultList.get(0).getResult());
resMap.put(TpTripTypeEnum.BACK.getCode(), resultList.get(1).getResult());
return resMap;
}
/**
* 获取非日票的总可用次数
*
* @param expressionList 规则表达式,取周票、月票、学期票总可用次数规则
* @param passengerCount 乘客人数
* @return
*/
private Integer getNonDailyTicketPerTicketTotalAvailableCount(List<String> expressionList, Integer passengerCount, TpRuleExpressionGroupEnum ruleGroup, String tenantId) {
TpRuleExecuteDTO<TpTicketTripsParamDTO> ruleExecuteDTO = new TpRuleExecuteDTO<>();
TpTicketTripsParamDTO ticketTripsParamDTO = new TpTicketTripsParamDTO();
ruleExecuteDTO.setRuleList(expressionList);
ruleExecuteDTO.setParameter(ticketTripsParamDTO);
ruleExecuteDTO.setTenantId(tenantId);
ticketTripsParamDTO.setPassengerCount(passengerCount);
ruleExecuteDTO.setRuleExpressionGroup(ruleGroup);
TpRuleExecuteResultVO<Integer> executeResult = bizRuleClient.executeRule(ruleExecuteDTO);
return executeResult.getResult();
}
private Long ticketCheckTimeRule(List<String> expressionList, String earliestCheckTime, String tenantId) {
Long earliestAvailableCheckTime = convertCheckTime2Timestamp(earliestCheckTime);
TpRuleExecuteDTO<TpTicketCheckParamDTO> ruleExecuteDTO = new TpRuleExecuteDTO<>();
TpTicketCheckParamDTO checkParamDTO = new TpTicketCheckParamDTO();
checkParamDTO.setDepartureTime(earliestAvailableCheckTime);
ruleExecuteDTO.setRuleList(expressionList);
ruleExecuteDTO.setParameter(checkParamDTO);
ruleExecuteDTO.setTenantId(tenantId);
ruleExecuteDTO.setRuleExpressionGroup(TpRuleExpressionGroupEnum.TICKET_CHECK);
LogUtil.info("请求规则域执行规则的接口,规则为:验票时间段校验规则,入参为:{}", JSONUtil.toJsonStr(ruleExecuteDTO));
TpRuleExecuteResultVO<TpTicketShowStartTimeResult> executeResult = bizRuleClient.executeRule(ruleExecuteDTO);
return executeResult.getResult().getShowTime();
}
private List<TpTicketShowStartTimeResult> batchExecuteTicketCheckTimeRule(List<String> expressionList, List<Long> earliestCheckTimeList, String tenantId) {
List<TpRuleExecuteDTO<TpTicketCheckParamDTO>> ruleExecuteDTOs = Lists.newArrayList();
earliestCheckTimeList.forEach(earliestCheckTime -> {
TpRuleExecuteDTO<TpTicketCheckParamDTO> ruleExecuteDTO = new TpRuleExecuteDTO<>();
TpTicketCheckParamDTO checkParamDTO = new TpTicketCheckParamDTO();
checkParamDTO.setDepartureTime(earliestCheckTime);
ruleExecuteDTO.setRuleList(expressionList);
ruleExecuteDTO.setParameter(checkParamDTO);
ruleExecuteDTO.setTenantId(tenantId);
ruleExecuteDTO.setRuleExpressionGroup(TpRuleExpressionGroupEnum.TICKET_CHECK);
ruleExecuteDTOs.add(ruleExecuteDTO);
});
LogUtil.info("请求规则域执行规则的接口,规则为:验票时间段校验规则,入参为:{}", JSONUtil.toJsonStr(ruleExecuteDTOs));
TpRuleExecuteBatchResultVO<TpTicketShowStartTimeResult> batchExecuteResult = bizRuleClient.batchExecuteBizRule(ruleExecuteDTOs);
List<TpTicketShowStartTimeResult> executeRes = Lists.newArrayList();
batchExecuteResult.getResultList().forEach(res -> {
Boolean success = res.getSuccess();
if (!success) {
LogUtil.error("批量执行检票规则失败,结果为:{}", JSONUtil.toJsonStr(batchExecuteResult));
throw new TpTradeProdException(TpTradeProdErrorCode.BATCH_EXECUTE_RULE_ERROR);
}
executeRes.add(res.getResult());
});
return executeRes;
}
private static Long convertCheckTime2Timestamp(String checkTime) {
// 最早检票时间08:00
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(GlobalConstants.TIME_FORMAT);
LocalTime curTime = LocalTime.parse(checkTime, formatter);
// 非日票,发车时间取当天的时间
LocalDateTime localDateTime = LocalDateTime.of(LocalDate.now(), curTime);
return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
private static Map<String, Long> batchConvertCheckTime2Timestamp(List<String> checkTimeList) {
Map<String, Long> checkTimeMap = Maps.newHashMap();
for (String checkTime : checkTimeList) {
Long checkTimestamp = convertCheckTime2Timestamp(checkTime);
checkTimeMap.put(checkTime, checkTimestamp);
}
return checkTimeMap;
}
private TpProdVoucherCreateDTO buildVoucherCreateDTO(String tenantId, TpProdOrderDetailVO orderDetail, Map<String, Integer> perTicketTotalAvailableCountMap,
TpProdDetailDTO productDetailDTO, List<TpBizRuleDTO> allNeedSaveRules) {
TpProdVoucherCreateDTO tpProdVoucherCreateDTO = new TpProdVoucherCreateDTO();
tpProdVoucherCreateDTO.setUserNo(orderDetail.getUserNo());
tpProdVoucherCreateDTO.setOrderNo(orderDetail.getOrderNo());
tpProdVoucherCreateDTO.setRouteId(CollUtil.isNotEmpty(orderDetail.getTpOrderRoutes()) ? orderDetail.getTpOrderRoutes().get(0).getRouteNo() : null);
tpProdVoucherCreateDTO.setRouteName(CollUtil.isNotEmpty(orderDetail.getTpOrderRoutes()) ? orderDetail.getTpOrderRoutes().get(0).getRouteName() : null);
List<TpUserTicketChoiceDTO> ticketChoiceDTOs = Lists.newArrayList();
TpOrderRouteVO orderRoute = orderDetail.getTpOrderRoutes().get(0);
List<TpOrderRouteShuttleVO> orderRouteShuttleList = orderRoute.getTpOrderRouteShuttle();
List<String> tripTypeList = orderDetail.getTpOrderTravelTrips()
.stream()
.map(TpOrderTravelTripVO::getTripType)
.distinct()
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(orderRouteShuttleList)) {
orderRouteShuttleList.forEach(shuttle -> {
TpUserTicketChoiceDTO choiceDTO = new TpUserTicketChoiceDTO();
choiceDTO.setShuttleId(getShuttleNo(shuttle));
choiceDTO.setShuttleName(getShuttleName(shuttle));
choiceDTO.setTripType(shuttle.getTripType());
ticketChoiceDTOs.add(choiceDTO);
});
} else {
tripTypeList.forEach(tripType -> {
TpUserTicketChoiceDTO choiceDTO = new TpUserTicketChoiceDTO();
choiceDTO.setTripType(tripType);
ticketChoiceDTOs.add(choiceDTO);
});
}
tpProdVoucherCreateDTO.setTicketChoiceDTOs(ticketChoiceDTOs);
tpProdVoucherCreateDTO.setVoucherType(orderDetail.getTicketType());
tpProdVoucherCreateDTO.setRequiredRealName(BooleanUtil.toBoolean(String.valueOf(orderDetail.getIdentityVerificat())));
tpProdVoucherCreateDTO.setValidationTypes(productDetailDTO.getProductExtraAttributes().getCheckTicketType());
tpProdVoucherCreateDTO.setTenantId(tenantId);
tpProdVoucherCreateDTO.setProductCategoryNo(orderDetail.getProductCategoryNo());
tpProdVoucherCreateDTO.setProductCategoryName(orderDetail.getProductCategory());
// 设置凭证的有效日期以及乘客信息
buildVoucherEffectiveDateAndPassenger(tenantId, orderDetail, tpProdVoucherCreateDTO, ticketChoiceDTOs, perTicketTotalAvailableCountMap);
// 调用产品规则获取凭证的最早检票时间和最晚检票时间
setValidCheckTime(tpProdVoucherCreateDTO, orderDetail, ticketChoiceDTOs, productDetailDTO, allNeedSaveRules, tenantId);
// 设置凭证的有效时间(有效日期+具体最早和最晚检票时间),这里需要上面的有效日期+最早和最晚检票时间
setVoucherEffectiveTime(tpProdVoucherCreateDTO);
// 调用产品规则查询凭证核销和展示的规则
setBizRules(tpProdVoucherCreateDTO, allNeedSaveRules);
// 如果需要一次性全部核销,则打上标签
TpProductExtendAttributesDTO extendAttributes = productDetailDTO.getExtendAttributes();
NonRealNameTicketVerificationRules nonRealNameTicketVerificationRule = extendAttributes.getNonRealNameTicketVerificationRule();
LogUtil.info("读取到的产品拓展属性为:{}", JSONUtil.toJsonStr(productDetailDTO.getExtendAttributes()));
boolean needOneTimeVerificationConfig = nonRealNameTicketVerificationRule == NonRealNameTicketVerificationRules.WHOLE_ORDER;
boolean needOneTimeVerification = needOneTimeVerificationConfig && !tpProdVoucherCreateDTO.getRequiredRealName() && StringUtils.equals(orderDetail.getTicketType(), TpVoucherTypeEnum.DAY.getCode());
if (needOneTimeVerification) {
Map<String, Object> bizData = new HashMap<>();
bizData.put(BizDataKeyConstants.ONE_TIME_VERIFICATION_TICKET, true);
tpProdVoucherCreateDTO.setBizData(bizData);
}
// 判断拼车业务是线下POS机预约/线上预约
if (Objects.equals(orderDetail.getType(), TpOrderTypeEnum.CARPOOL_ORDER.getType()) && StringUtils.equals(orderDetail.getSource(), TpOrderSourceEnum.POS.getType())) {
tpProdVoucherCreateDTO.setChannel(TpVoucherChannelEnum.OFFLINE_VILLAGE.getCode());
} else {
tpProdVoucherCreateDTO.setChannel(TpVoucherChannelEnum.ONLINE.getCode());
}
return tpProdVoucherCreateDTO;
}
private void setBizRules(TpProdVoucherCreateDTO voucherCreateDTO, List<TpBizRuleDTO> allNeedSaveRules) {
voucherCreateDTO.setBizRuleDTOs(bizRuleConvert.convert2ProdBizRuleList(allNeedSaveRules));
}
private void setVoucherEffectiveTime(TpProdVoucherCreateDTO createDTO) {
if (createDTO.getRequiredRealName()) {
createDTO.getTicketChoiceDTOs().forEach(choiceDTO -> {
List<TpVoucherPurchaseInfoDTO> voucherPurchaseInfoList = choiceDTO.getVoucherPurchaseInfoList();
voucherPurchaseInfoList.forEach(purchaseInfo -> {
String earliestCheckTime = purchaseInfo.getEarliestCheckTime();
String latestCheckTime = purchaseInfo.getLatestCheckTime();
Long effectiveStartDate = purchaseInfo.getEffectiveStartTime();
Long effectiveEndDate = purchaseInfo.getEffectiveEndTime();
Long effectiveStartTime = calculateEffectiveTime(earliestCheckTime, effectiveStartDate);
Long effectiveEndTime = calculateEffectiveTime(latestCheckTime, effectiveEndDate);
purchaseInfo.setEffectiveStartTime(effectiveStartTime);
purchaseInfo.setEffectiveEndTime(effectiveEndTime);
});
});
} else {
createDTO.getTicketChoiceDTOs().forEach(choice -> {
List<TpVoucherNonRealNameDTO> nonRealNameDTOs = choice.getNonRealNameDTOs();
nonRealNameDTOs.forEach(nonRealNameDTO -> {
String earliestCheckTime = nonRealNameDTO.getEarliestCheckTime();
String latestCheckTime = nonRealNameDTO.getLatestCheckTime();
Long effectiveStartDate = nonRealNameDTO.getEffectiveStartTime();
Long effectiveEndDate = nonRealNameDTO.getEffectiveEndTime();
Long effectiveStartTime = calculateEffectiveTime(earliestCheckTime, effectiveStartDate);
Long effectiveEndTime = calculateEffectiveTime(latestCheckTime, effectiveEndDate);
nonRealNameDTO.setEffectiveStartTime(effectiveStartTime);
nonRealNameDTO.setEffectiveEndTime(effectiveEndTime);
});
});
}
}
private Long calculateEffectiveTime(String checkTime, Long effectiveDate) {
LocalTime earliestCheckTimeLocalTime = LocalTime.parse(checkTime, TIME_FORMAT);
LocalDateTime effectiveDateTime = LocalDateTimeUtil.of(effectiveDate);
return LocalDateTimeUtil.toEpochMilli(LocalDateTime.of(effectiveDateTime.toLocalDate(), earliestCheckTimeLocalTime));
}
@Nullable
private static String getShuttleNo(TpOrderRouteShuttleVO routeShuttle) {
if (routeShuttle == null) {
return null;
}
return routeShuttle.getShuttleNo();
}
@Nullable
private static String getShuttleName(TpOrderRouteShuttleVO routeShuttle) {
if (routeShuttle == null) {
return null;
}
return routeShuttle.getShuttleName();
}
private void buildVoucherEffectiveDateAndPassenger(String tenantId, TpProdOrderDetailVO orderDetail, TpProdVoucherCreateDTO tpProdVoucherCreateDTO, List<TpUserTicketChoiceDTO> ticketChoiceDTOs,
Map<String, Integer> perTicketTotalAvailableCountMap) {
if (ObjectUtil.equal(orderDetail.getIdentityVerificat(), TpProdOrderIdentityFlagEnum.REAL_NAME_ORDER.getIdentityFlag())) {
setVoucherRealName(tenantId, orderDetail, tpProdVoucherCreateDTO, ticketChoiceDTOs, perTicketTotalAvailableCountMap);
} else {
setVoucherNotRealName(orderDetail, tpProdVoucherCreateDTO, ticketChoiceDTOs, perTicketTotalAvailableCountMap);
}
}
private void setValidCheckTime(TpProdVoucherCreateDTO createDTO, TpProdOrderDetailVO orderDetail, List<TpUserTicketChoiceDTO> ticketChoiceDTOs, TpProdDetailDTO productDetailDTO, List<TpBizRuleDTO> allNeedSaveRules, String tenantId) {
// 一期最晚检票时间是班车到点预估时间+60分钟 60分钟是写死的没有配置成规则
List<TpOrderTravelTripVO> orderTravelTrips = orderDetail.getTpOrderTravelTrips();
Assert.notEmpty(orderTravelTrips, "订单关联的行程单不能为空");
List<TpOrderRouteVO> orderRoutes = orderDetail.getTpOrderRoutes();
Assert.notEmpty(orderRoutes, "线路信息不能为空");
TpOrderRouteVO routeVO = orderRoutes.get(0);
TpProductExtendAttributesDTO extendAttributes = productDetailDTO.getExtendAttributes();
Integer ticketVerificationEndTime = extendAttributes.getTicketVerificationEndTime();
if (ticketVerificationEndTime == null) {
// 如果该配置不存在默认延迟60分钟
ticketVerificationEndTime = 60;
}
// 有班次,普通班车
if (CollectionUtils.isNotEmpty(routeVO.getTpOrderRouteShuttle())) {
// 最早检票时间:取下单时的班次时间。滚动发车取首班时间
// 班次发车时间
Map<String, List<TpOrderTravelTripVO>> travelTripMap = orderTravelTrips.stream().collect(Collectors.groupingBy(TpOrderTravelTripVO::getTripType));
Map<String, TpUserTicketChoiceDTO> choiceTripTypeMap = ticketChoiceDTOs.stream().collect(Collectors.toMap(TpUserTicketChoiceDTO::getTripType, Function.identity()));
List<String> routeShuttleTimeList = routeVO.getTpOrderRouteShuttle().stream()
.map(TpOrderRouteShuttleVO::getShuttleTime)
.distinct()
.collect(Collectors.toList());
Map<String, Long> routeShuttleTimeMap = batchConvertCheckTime2Timestamp(routeShuttleTimeList);
List<Long> routeShuttleTimestampList = new ArrayList<>(routeShuttleTimeMap.values());
Map<Long, String> earliestCheckTimeMap = batchCalculateEarliestCheckTime(routeShuttleTimestampList, allNeedSaveRules, tenantId);
for (TpOrderRouteShuttleVO routeShuttle : routeVO.getTpOrderRouteShuttle()) {
List<TpOrderTravelTripVO> travelTripList = travelTripMap.get(routeShuttle.getTripType());
TpUserTicketChoiceDTO choiceDTO = choiceTripTypeMap.get(routeShuttle.getTripType());
if (createDTO.getRequiredRealName()) {
List<TpVoucherPurchaseInfoDTO> voucherPurchaseInfoList = choiceDTO.getVoucherPurchaseInfoList();
// 相同行程类型的最早和最晚检票时间是一样的
for (TpVoucherPurchaseInfoDTO purchaseInfoDTO : voucherPurchaseInfoList) {
Long routeShuttleTimestamp = routeShuttleTimeMap.get(routeShuttle.getShuttleTime());
String earliestCheckTime = earliestCheckTimeMap.get(routeShuttleTimestamp);
// 行程单会根据乘客进行拆分,除了乘客信息外其他信息都一样
String latestCheckTime = calculateLatestCheckTime(travelTripList.get(0).getEndTime(), ticketVerificationEndTime);
purchaseInfoDTO.setEarliestCheckTime(earliestCheckTime);
purchaseInfoDTO.setLatestCheckTime(latestCheckTime);
}
} else {
List<TpVoucherNonRealNameDTO> nonRealNameDTOs = choiceDTO.getNonRealNameDTOs();
// 相同行程类型的最早和最晚检票时间是一样的
for (TpVoucherNonRealNameDTO nonRealNameDTO : nonRealNameDTOs) {
Long routeShuttleTimestamp = routeShuttleTimeMap.get(routeShuttle.getShuttleTime());
String earliestCheckTime = earliestCheckTimeMap.get(routeShuttleTimestamp);
// 行程单会根据乘客进行拆分,除了乘客信息外其他信息都一样
String latestCheckTime = calculateLatestCheckTime(travelTripList.get(0).getEndTime(), ticketVerificationEndTime);
nonRealNameDTO.setEarliestCheckTime(earliestCheckTime);
nonRealNameDTO.setLatestCheckTime(latestCheckTime);
}
}
}
} else {
// 滚动发车
RouteRollTimeDetailDTO routeRollTimeDetail = routeClient.getRouteRollTime(routeVO.getRouteNo(), createDTO.getTenantId());
Assert.notNull(routeRollTimeDetail, "滚动发车对应的发车时间不能为空");
String roundTrip = routeVO.getRoundTrip();
if (StringUtils.equals(roundTrip, RouteConstants.GO)) {
List<RollTimeDTO> goRollTimes = routeRollTimeDetail.getGoRollTimes();
Assert.notEmpty(goRollTimes, "去程时间不能为空");
List<RollTimeDTO> sortedRollTimes = goRollTimes.stream().sorted(Comparator.comparing(RollTimeDTO::getOrder)).collect(Collectors.toList());
String earliestCheckTime = calculateEarliestCheckTime(sortedRollTimes.get(0).getFirstTime(), allNeedSaveRules, tenantId);
String latestCheckTime = calculateLatestCheckTime(sortedRollTimes.get(sortedRollTimes.size() - 1).getLastTime(), ticketVerificationEndTime);
assembleCheckTime(createDTO, ticketChoiceDTOs, earliestCheckTime, latestCheckTime);
} else if (StringUtils.equals(roundTrip, RouteConstants.BACK)) {
List<RollTimeDTO> backRollTimes = routeRollTimeDetail.getBackRollTimes();
Assert.notEmpty(backRollTimes, "返程时间不能为空");
List<RollTimeDTO> sortedRollTimes = backRollTimes.stream().sorted(Comparator.comparing(RollTimeDTO::getOrder)).collect(Collectors.toList());
String earliestCheckTime = calculateEarliestCheckTime(sortedRollTimes.get(0).getFirstTime(), allNeedSaveRules, tenantId);
String latestCheckTime = calculateLatestCheckTime(sortedRollTimes.get(sortedRollTimes.size() - 1).getLastTime(), ticketVerificationEndTime);
assembleCheckTime(createDTO, ticketChoiceDTOs, earliestCheckTime, latestCheckTime);
} else {
// 往返程
for (TpUserTicketChoiceDTO choice : ticketChoiceDTOs) {
if (StringUtils.equals(choice.getTripType(), RouteConstants.GO)) {
List<RollTimeDTO> goRollTimes = routeRollTimeDetail.getGoRollTimes();
Assert.notEmpty(goRollTimes, "去程时间不能为空");
List<RollTimeDTO> sortedRollTimes = goRollTimes.stream().sorted(Comparator.comparing(RollTimeDTO::getOrder)).collect(Collectors.toList());
assembleRoundTripCheckTime(createDTO, allNeedSaveRules, tenantId, choice, sortedRollTimes, ticketVerificationEndTime);
} else {
List<RollTimeDTO> backRollTimes = routeRollTimeDetail.getBackRollTimes();
Assert.notEmpty(backRollTimes, "返程时间不能为空");
List<RollTimeDTO> sortedRollTimes = backRollTimes.stream().sorted(Comparator.comparing(RollTimeDTO::getOrder)).collect(Collectors.toList());
assembleRoundTripCheckTime(createDTO, allNeedSaveRules, tenantId, choice, sortedRollTimes, ticketVerificationEndTime);
}
}
}
}
}
private void assembleCheckTime(TpProdVoucherCreateDTO createDTO, List<TpUserTicketChoiceDTO> ticketChoiceDTOs, String earliestCheckTime, String latestCheckTime) {
if (createDTO.getRequiredRealName()) {
ticketChoiceDTOs.forEach(choice -> {
List<TpVoucherPurchaseInfoDTO> voucherPurchaseInfoList = choice.getVoucherPurchaseInfoList();
voucherPurchaseInfoList.forEach(purchaseInfoDTO -> {
purchaseInfoDTO.setEarliestCheckTime(earliestCheckTime);
purchaseInfoDTO.setLatestCheckTime(latestCheckTime);
});
});
} else {
ticketChoiceDTOs.forEach(choice -> {
List<TpVoucherNonRealNameDTO> nonRealNameDTOs = choice.getNonRealNameDTOs();
nonRealNameDTOs.forEach(nonRealNameDTO -> {
nonRealNameDTO.setEarliestCheckTime(earliestCheckTime);
nonRealNameDTO.setLatestCheckTime(latestCheckTime);
});
});
}
}
private void assembleRoundTripCheckTime(TpProdVoucherCreateDTO createDTO, List<TpBizRuleDTO> allNeedSaveRules, String tenantId,
TpUserTicketChoiceDTO choice, List<RollTimeDTO> sortedRollTimes, Integer ticketVerificationEndTime) {
// 往返程同一种行程类型的最早和最晚检票时间一定是一样的
String roundEarliestCheckTime = calculateEarliestCheckTime(sortedRollTimes.get(0).getFirstTime(), allNeedSaveRules, tenantId);
String roundLatestCheckTime = calculateLatestCheckTime(sortedRollTimes.get(sortedRollTimes.size() - 1).getLastTime(), ticketVerificationEndTime);
List<TpVoucherPurchaseInfoDTO> voucherPurchaseInfoList = choice.getVoucherPurchaseInfoList();
if (createDTO.getRequiredRealName()) {
voucherPurchaseInfoList.forEach(purchaseInfoDTO -> {
purchaseInfoDTO.setEarliestCheckTime(roundEarliestCheckTime);
purchaseInfoDTO.setLatestCheckTime(roundLatestCheckTime);
});
} else {
List<TpVoucherNonRealNameDTO> nonRealNameDTOs = choice.getNonRealNameDTOs();
nonRealNameDTOs.forEach(nonRealNameDTO -> {
nonRealNameDTO.setEarliestCheckTime(roundEarliestCheckTime);
nonRealNameDTO.setLatestCheckTime(roundLatestCheckTime);
});
}
}
private String calculateEarliestCheckTime(String busDepartureTime, List<TpBizRuleDTO> allNeedSaveRules, String tenantId) {
Map<String, List<TpBizRuleDTO>> bizRuleMap = allNeedSaveRules.stream().collect(Collectors.groupingBy(TpBizRuleDTO::getRuleGroup));
List<TpBizRuleDTO> ticketCheckRules = bizRuleMap.get(TpRuleExpressionGroupEnum.TICKET_CHECK.getCode());
Assert.notEmpty(ticketCheckRules, "凭证检票规则不能为空");
// 调用产品域的规则来计算最早检票时间,最早检票时间为班次发车时间-后台配置的分钟
List<String> expressionList = ticketCheckRules.stream().map(TpBizRuleDTO::getExpression).collect(Collectors.toList());
Long earliestCheckTimestamp = ticketCheckTimeRule(expressionList, busDepartureTime, tenantId);
// 兜底措施-最早检票时间不能小于当天的00:00
Long currentDayEarliestTime = convertCheckTime2Timestamp(EVERY_DAY_EARLIEST_TIME);
if (earliestCheckTimestamp <= currentDayEarliestTime) {
return EVERY_DAY_EARLIEST_TIME;
}
return DateTime.of(earliestCheckTimestamp).toLocalDateTime().format(TIME_FORMAT);
}
private Map<Long, String> batchCalculateEarliestCheckTime(List<Long> busDepartureTimes, List<TpBizRuleDTO> allNeedSaveRules, String tenantId) {
Map<String, List<TpBizRuleDTO>> bizRuleMap = allNeedSaveRules.stream().collect(Collectors.groupingBy(TpBizRuleDTO::getRuleGroup));
List<TpBizRuleDTO> ticketCheckRules = bizRuleMap.get(TpRuleExpressionGroupEnum.TICKET_CHECK.getCode());
Assert.notEmpty(ticketCheckRules, "凭证检票规则不能为空");
// 调用产品域的规则来计算最早检票时间,最早检票时间为班次发车时间-后台配置的分钟
List<String> expressionList = ticketCheckRules.stream().map(TpBizRuleDTO::getExpression).collect(Collectors.toList());
List<TpTicketShowStartTimeResult> earliestCheckTimestampList = batchExecuteTicketCheckTimeRule(expressionList, busDepartureTimes, tenantId);
Map<Long, String> earliestCheckTimeMap = new HashMap<>();
for (TpTicketShowStartTimeResult showStartTimeResult : earliestCheckTimestampList) {
// 兜底措施-最早检票时间不能小于当天的00:00
Long currentDayEarliestTime = convertCheckTime2Timestamp(EVERY_DAY_EARLIEST_TIME);
if (showStartTimeResult.getShowTime() <= currentDayEarliestTime) {
earliestCheckTimeMap.put(showStartTimeResult.getDepartureTime(), EVERY_DAY_EARLIEST_TIME);
} else {
String earliestCheckTime = DateTime.of(showStartTimeResult.getShowTime()).toLocalDateTime().format(TIME_FORMAT);
earliestCheckTimeMap.put(showStartTimeResult.getDepartureTime(), earliestCheckTime);
}
}
return earliestCheckTimeMap;
}
/**
* 最晚检票时间的计算规则:目的地到达时间+后台配置的延迟时间
*
* @param endTime
* @return
*/
private String calculateLatestCheckTime(String endTime, int delayMinutes) {
LocalTime originalEndTime = LocalTime.parse(endTime, TIME_FORMAT);
LocalTime latestEndTime = LocalTime.parse(endTime, TIME_FORMAT).plusMinutes(delayMinutes);
if (originalEndTime.isAfter(latestEndTime)) {
return EVERY_DAY_LAST_TIME;
}
return latestEndTime.format(TIME_FORMAT);
}
private void setVoucherRealName(String tenantId, TpProdOrderDetailVO orderDetail, TpProdVoucherCreateDTO tpProdVoucherCreateDTO, List<TpUserTicketChoiceDTO> ticketChoiceDTOs,
Map<String, Integer> roundTripPerTicketTotalAvailableCountMap) {
Map<String, List<TpOrderSubjectItemVO>> subjectItemMap = orderDetail.getOrderSubjectItem()
.stream()
.collect(Collectors.groupingBy(TpOrderSubjectItemVO::getTripType));
ticketChoiceDTOs.forEach(choice -> {
List<TpVoucherPurchaseInfoDTO> voucherPurchaseInfoList = Lists.newArrayList();
// 当前行程类型对应的标的项,如去程对应的标的项
List<TpOrderSubjectItemVO> curTripTypeSubjectItems = subjectItemMap.get(choice.getTripType());
Integer perTicketTotalAvailableCount = roundTripPerTicketTotalAvailableCountMap.get(choice.getTripType());
curTripTypeSubjectItems.forEach(subjectItem -> {
TpVoucherPurchaseInfoDTO tpVoucherPurchaseInfoDTO = new TpVoucherPurchaseInfoDTO();
// 计算凭证的生失效时间
Pair<Long, Long> rangeEffectiveTime = calculateTicketEffectiveTime(subjectItem, tpProdVoucherCreateDTO.getVoucherType());
tpVoucherPurchaseInfoDTO.setEffectiveStartTime(rangeEffectiveTime.getKey());
tpVoucherPurchaseInfoDTO.setEffectiveEndTime(rangeEffectiveTime.getValue());
// 构建凭证所需乘客信息
TpVoucherPassengerDTO tpVoucherPassengerDTO = buildVoucherPassenger(tenantId, subjectItem);
tpVoucherPurchaseInfoDTO.setSalesUnitCode(subjectItem.getItemNo());
tpVoucherPurchaseInfoDTO.setPassengerInfo(tpVoucherPassengerDTO);
tpVoucherPurchaseInfoDTO.setTotalAvailableCount(perTicketTotalAvailableCount);
// 乘客信息塞入列表
voucherPurchaseInfoList.add(tpVoucherPurchaseInfoDTO);
});
choice.setVoucherPurchaseInfoList(voucherPurchaseInfoList);
});
}
@NotNull
private static TpVoucherPassengerDTO buildVoucherPassenger(String tenantId, TpOrderSubjectItemVO subjectItem) {
TpVoucherPassengerDTO tpVoucherPassengerDTO = new TpVoucherPassengerDTO();
TpOrderPassengerVO passenger = subjectItem.getPassenger();
tpVoucherPassengerDTO.setPassengerNo(passenger.getPassengerNo());
tpVoucherPassengerDTO.setPassengerType(passenger.getPassengerType());
tpVoucherPassengerDTO.setName(passenger.getPassengerName());
tpVoucherPassengerDTO.setCertType(passenger.getIdentificationType());
tpVoucherPassengerDTO.setCertNo(passenger.getIdentificationNumber());
tpVoucherPassengerDTO.setContactInfo(passenger.getPassengerContact());
tpVoucherPassengerDTO.setTenantId(tenantId);
tpVoucherPassengerDTO.setBizData(passenger.getBizData());
return tpVoucherPassengerDTO;
}
private Pair<Long, Long> calculateTicketEffectiveTime(TpOrderSubjectItemVO subjectItem, String voucherType) {
// 凭证类型转化为产品域的票据类型
String ticketType = convertVoucherType2TicketType(voucherType);
Assert.hasText(ticketType, "票类型不能为空");
// 取出标的项组成要素中的时间表达
List<TpOrderSubjectItemElementVO> orderItemElements = subjectItem.getOrderItemElements();
List<TpOrderSubjectItemElementVO> dateElements = orderItemElements
.stream()
.filter(element -> StringUtils.equals(element.getElementCode(), TpFactorCodeEnum.DATE.getCode()))
.collect(Collectors.toList());
Assert.isTrue(CollectionUtils.isNotEmpty(dateElements) && dateElements.size() == 1, "日期要素为空或者不唯一");
TpOrderSubjectItemElementVO curDateElement = dateElements.get(0);
// 计算票的生失效时间范围
TicketDateRangeParser.DateRange ticketEffectiveDateRange = TicketDateRangeParser.parseTicketDates(ticketType, curDateElement.getElementValue());
LocalDate startDate = ticketEffectiveDateRange.getStartDate();
LocalDate endDate = ticketEffectiveDateRange.getEndDate();
return new Pair<>(LocalDateTimeUtil.toEpochMilli(startDate), LocalDateTimeUtil.toEpochMilli(endDate));
}
private void setVoucherNotRealName(TpProdOrderDetailVO orderDetail, TpProdVoucherCreateDTO tpProdVoucherCreateDTO, List<TpUserTicketChoiceDTO> ticketChoiceDTOs,
Map<String, Integer> perTicketTotalAvailableCountMap) {
Map<String, List<TpOrderSubjectItemVO>> subjectItemMap = orderDetail.getOrderSubjectItem()
.stream()
.collect(Collectors.groupingBy(TpOrderSubjectItemVO::getTripType));
ticketChoiceDTOs.forEach(choice -> {
List<TpVoucherNonRealNameDTO> voucherNonRealNameDTOs = Lists.newArrayList();
// 当前行程类型对应的标的项,如去程对应的标的项
List<TpOrderSubjectItemVO> curTripTypeSubjectItems = subjectItemMap.get(choice.getTripType());
Integer perTicketTotalAvailableCount = perTicketTotalAvailableCountMap.get(choice.getTripType());
curTripTypeSubjectItems.forEach(subjectItem -> {
TpVoucherNonRealNameDTO tpVoucherNonRealNameDTO = new TpVoucherNonRealNameDTO();
// 取出标的项组成要素中的时间表达
Pair<Long, Long> voucherEffectiveTimeRange = calculateTicketEffectiveTime(subjectItem, tpProdVoucherCreateDTO.getVoucherType());
tpVoucherNonRealNameDTO.setEffectiveStartTime(voucherEffectiveTimeRange.getKey());
tpVoucherNonRealNameDTO.setEffectiveEndTime(voucherEffectiveTimeRange.getValue());
// 取出标的项中的票数量
tpVoucherNonRealNameDTO.setPassengerCount(subjectItem.getCount());
tpVoucherNonRealNameDTO.setTicketCount(perTicketTotalAvailableCount);
tpVoucherNonRealNameDTO.setSalesUnitCode(subjectItem.getItemNo());
voucherNonRealNameDTOs.add(tpVoucherNonRealNameDTO);
choice.setNonRealNameDTOs(voucherNonRealNameDTOs);
});
});
}
public String convertVoucherType2TicketType(String voucherType) {
if (StringUtils.equals(voucherType, TpProdOrderTicketTypeEnum.DAY.getTicketType())) {
return TicketTypeEnum.SINGLE_RIDE.getType();
} else if (StringUtils.equals(voucherType, TpProdOrderTicketTypeEnum.WEEK.getTicketType())) {
return TicketTypeEnum.WEEKLY.getType();
} else if (StringUtils.equals(voucherType, TpProdOrderTicketTypeEnum.MONTH.getTicketType())) {
return TicketTypeEnum.MONTHLY.getType();
} else if (StringUtils.equals(voucherType, TpProdOrderTicketTypeEnum.TERM.getTicketType())) {
return TicketTypeEnum.SEMESTER.getType();
} else if (StringUtils.equals(voucherType, TpProdOrderTicketTypeEnum.DAY_RANGE.getTicketType())) {
return TicketTypeEnum.DAY_RANGE.getType();
} else {
return null;
}
}
}

View File

@@ -0,0 +1,47 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.execute;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradecore.common.dto.order.TpDepositOrderDTO;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.annotation.LiteflowRetry;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
/**
* <p>
* 创建订金订单节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "createDepositOrderNode", name = "创建订金订单节点")
@LiteflowCmpDefine
@LiteflowRetry(retry = 3)
@RequiredArgsConstructor
public class TpCreateDepositOrderNode {
private final TpOrderClient tpOrderClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 创建订金订单节点");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
// 创建订金订单节点
tpOrderClient.createDepositOrder(TpDepositOrderDTO.builder()
.orderNo(userPlaceOrderContext.getOrderNo())
.payAmount(userPlaceOrderContext.getPayAmount())
.payPercentage(userPlaceOrderContext.getPercentage())
.tenantId(userPlaceOrderContext.getTenantId()).build());
}
}

View File

@@ -0,0 +1,51 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.execute;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderCreateVO;
import com.deepinnet.tptradeprod.core.compoment.TpCreateOrderComponent;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.annotation.LiteflowRetry;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
/**
* <p>
* 创建订单节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "createOrderNode", name = "创建订单节点")
@LiteflowCmpDefine
@LiteflowRetry(retry = 3)
@RequiredArgsConstructor
public class TpCreateOrderNode {
private final TpCreateOrderComponent tpCreateOrderComponent;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 创建订单");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
// 创建订单组件
TpProdOrderCreateVO createOrderVO = tpCreateOrderComponent.execute(createDTO);
createDTO.setOrderNo(createOrderVO.getOrderNo());
createDTO.setOriginalOrderNo(createOrderVO.getOriginalOrderNo());
userPlaceOrderContext.setOrderNo(createOrderVO.getOrderNo());
// 需支付金额
userPlaceOrderContext.setPayAmount(createDTO.getPayAmount());
userPlaceOrderContext.setTenantId(createDTO.getTenantId());
}
}

View File

@@ -0,0 +1,43 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.execute;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpproductcore.common.enums.TpInventoryOperationTypeEnum;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.vo.TpProdOrderDetailVO;
import com.deepinnet.tptradeprod.core.factory.TpOperatorInventoryStrategyFactory;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.annotation.LiteflowRetry;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import javax.annotation.Resource;
/**
* <p>
* 冻结库存节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "deductInventoryNode", name = "扣减库存节点")
@LiteflowCmpDefine
@LiteflowRetry(retry = 3)
public class TpDeductInventoryNode {
@Resource
private TpOperatorInventoryStrategyFactory tpOperatorInventoryStrategyFactory;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 扣减库存");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderDetailVO orderDetailVO = userPlaceOrderContext.getOrderDetailVO();
tpOperatorInventoryStrategyFactory.operationStrategyMap.get(TpInventoryOperationTypeEnum.FREEZE_TO_DEDUCT).operatorInventory(orderDetailVO, userPlaceOrderContext.getTenantId());
}
}

View File

@@ -0,0 +1,63 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.execute;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradecore.common.enums.TpBizTypeEnum;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.model.PaySuccessMessageEntity;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.deepinnet.tptradeprod.common.service.integration.client.mq.constants.MessageConstants;
import com.deepinnet.tptradeprod.common.service.integration.client.mq.constants.MessageSysConstants;
import com.deepinnet.tptradeprod.common.service.integration.client.mq.entity.BaseMessageEntity;
import com.deepinnet.tptradeprod.common.service.integration.client.mq.template.MessageClient;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.annotation.LiteflowRetry;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import lombok.RequiredArgsConstructor;
import java.time.LocalDateTime;
/**
* <p>
* 免费票发送同步消息
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "freeOrderPaidSendSyncMessageNode", name = "免费票发送同步消息节点")
@LiteflowCmpDefine
@LiteflowRetry(retry = 3)
@RequiredArgsConstructor
public class TpFreeOrderPaidSendSyncMessageNode {
private final MessageClient messageClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 免费票发送同步消息节点");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
BaseMessageEntity messageEntity = new BaseMessageEntity();
messageEntity.setKey(userPlaceOrderContext.getOrderNo());
messageEntity.setSource(MessageSysConstants.SOURCE_TRANS);
messageEntity.setSendTime(LocalDateTime.now());
PaySuccessMessageEntity payOrderSuccessEntity = new PaySuccessMessageEntity();
payOrderSuccessEntity.setBizType(TpBizTypeEnum.CUSTOM_BUS_PAY.getCode());
payOrderSuccessEntity.setOrderNo(userPlaceOrderContext.getOrderNo());
payOrderSuccessEntity.setPayTime(DateUtil.current());
payOrderSuccessEntity.setTenantId(userPlaceOrderContext.getTenantId());
String body = JSONUtil.toJsonStr(payOrderSuccessEntity);
messageEntity.setBody(body);
messageClient.send(messageClient.getMessageTopic(), MessageConstants.EVENT_CODE_TRANS_PAY_SUCCESS, messageEntity);
}
}

View File

@@ -0,0 +1,43 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.execute;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tpproductcore.common.enums.TpInventoryOperationTypeEnum;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.dto.TpProdOrderCreateDTO;
import com.deepinnet.tptradeprod.core.factory.TpOperatorInventoryStrategyFactory;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.annotation.LiteflowRetry;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import javax.annotation.Resource;
/**
* <p>
* 冻结库存节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "freezeInventoryNode", name = "冻结库存节点")
@LiteflowCmpDefine
@LiteflowRetry(retry = 3)
public class TpFreezeInventoryNode {
@Resource
private TpOperatorInventoryStrategyFactory tpOperatorInventoryStrategyFactory;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 冻结库存");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
TpProdOrderCreateDTO createDTO = userPlaceOrderContext.getCreateDTO();
tpOperatorInventoryStrategyFactory.operationStrategyMap.get(TpInventoryOperationTypeEnum.FREEZE).operatorInventory(createDTO, createDTO.getTenantId());
}
}

View File

@@ -0,0 +1,45 @@
package com.deepinnet.tptradeprod.biz.service.flow.node.execute;
import com.deepinnet.tp.common.lang.util.LogUtil;
import com.deepinnet.tptradecore.common.dto.order.TpOrderPushStatusDTO;
import com.deepinnet.tptradecore.common.enums.order.TpOrderPushStatusEnum;
import com.deepinnet.tptradeprod.biz.service.flow.context.TpUserPlaceOrderContext;
import com.deepinnet.tptradeprod.common.service.integration.client.TpOrderClient;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.annotation.LiteflowRetry;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import javax.annotation.Resource;
/**
* <p>
* 订单状态推进为待支付节点
* </p>
*
* @author chenjiaju
* @since 2023/10/16
*/
@LiteflowComponent(value = "needPayOrderStatusNode", name = "订单状态推进为待支付节点")
@LiteflowCmpDefine
@LiteflowRetry(retry = 3)
public class TpNeedPayOrderStatusNode {
@Resource
private TpOrderClient tpOrderClient;
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
LogUtil.info("---------------------------当前节点: 订单状态推进为待支付节点");
TpUserPlaceOrderContext userPlaceOrderContext = bindCmp.getContextBean(TpUserPlaceOrderContext.class);
tpOrderClient.pushOrderStatus(TpOrderPushStatusDTO.builder()
.orderNo(userPlaceOrderContext.getOrderNo())
.tenantId(userPlaceOrderContext.getTenantId())
.tpOrderPushStatusEnum(TpOrderPushStatusEnum.NEED_PAY_PUSH_STATUS).build());
}
}

Some files were not shown because too many files have changed in this diff Show More