Merge branch 'feature/REQ-3300' into 'master'

Feature/req 3300

See merge request universal/infrastructure/backend/nanopart!111
This commit is contained in:
徐大伟 2025-02-28 05:52:58 +00:00
commit 9ba1c18b38
118 changed files with 11361 additions and 13 deletions

View File

@ -40,6 +40,9 @@ public class BlackUserSyncJob extends IJobHandler{
@Resource
private BlackAndWhiteListService blackAndWhiteListService;
@Resource
private BlackProducer blackProducer;
/**
* 定时任务执行逻辑
* 这具数据比较少一直性发个几百条我问题不在
@ -79,7 +82,7 @@ public class BlackUserSyncJob extends IJobHandler{
blackList.forEach(item -> sends.add(item.getParam()));
String jsonStr = JSONUtil.toJsonStr(sends);
if(Objects.nonNull(blackModuleEnum) && Objects.nonNull(event)){
BlackProducer.send(event, jsonStr);
blackProducer.send(event, jsonStr);
}
});
return ReturnT.SUCCESS;

View File

@ -11,13 +11,16 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Slf4j
@Service
public class BlackProducer implements InitializingBean {
private static EventProducer<?> eventProducer;
public static void send(MQEventEnum mqEventEnum, String data) {
public class BlackProducer {
@Resource
private EventProducer<?> eventProducer;
public void send(MQEventEnum mqEventEnum, String data) {
if(mqEventEnum == null){
throw new ServiceException("无法正确发送mq: mqEventEnum不能为空");
}
@ -33,10 +36,4 @@ public class BlackProducer implements InitializingBean {
.data(data)
.build());
}
@Override
public void afterPropertiesSet() {
eventProducer = SpringUtil.getBean(EventProducer.class);
}
}

View File

@ -56,6 +56,11 @@
<artifactId>axzo-test-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.pokonyan</groupId>
<artifactId>pokonyan</artifactId>
@ -133,6 +138,18 @@
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.nanopart</groupId>
<artifactId>visa-api</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.nanopart</groupId>
<artifactId>visa-server</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.im.center</groupId>
<artifactId>im-center-api</artifactId>

View File

@ -1,20 +1,23 @@
package cn.axzo.nanopart;
import cn.axzo.nanopart.config.RocketMQEventConfiguration;
import cn.azxo.framework.common.logger.MethodAroundLogAspect;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
@ComponentScan(value = {"cn.axzo.nanopart","cn.axzo.basics"})
@MapperScan(value = {"cn.axzo.**.mapper"})
@SpringBootApplication
@EnableFeignClients(basePackages = {
"cn.axzo"
})
@EnableAspectJAutoProxy()
@Import(RocketMQEventConfiguration.class)
@Import({RocketMQEventConfiguration.class, MethodAroundLogAspect.class})
public class NanopartApplication {
public static void main(String[] args) {
SpringApplication.run(NanopartApplication.class, args);

View File

@ -69,6 +69,11 @@ public class FeignConfig implements RequestInterceptor, EnvironmentAware {
private String dataCollectionUrl;
@Value("${attendanceUrl:http://dev-app.axzo.cn/attendance}")
private String attendanceApi;
@Value("${thorUrl:http://dev-app.axzo.cn/thor}")
private String thorUrl;
@Value("${orgGateway:http://dev-app.axzo.cn/org-gateway}")
private String orgGatewayUrl;
private static String POD_NAMESPACE;
static {
@ -107,6 +112,8 @@ public class FeignConfig implements RequestInterceptor, EnvironmentAware {
url = url.replace("http://karma:8080", karmaEnvUrl);
url = url.replace("http://data-collection:21200", dataCollectionUrl);
url = url.replace("http://attendance:8080", attendanceApi);
url = url.replace("http://thor:8080", thorUrl);
url = url.replace("http://org-gateway:8080", orgGatewayUrl);
String profile = environment.getProperty("spring.profiles.active");
if(Objects.equals(profile, "test") && url.contains("dev-app.axzo.cn")) {
url = url.replace("dev-app", "test-api");

View File

@ -242,4 +242,48 @@ public class RocketMQEventConfiguration {
super.onEvent(message, eventConsumer);
}
}
/**
* 变洽签业务消费单据日志
*/
@Slf4j
@Component
@RocketMQMessageListener(topic = "topic_nanopart_${spring.profiles.active}",
consumerGroup = "GID_visa_change_log_${spring.application.name}_${spring.profiles.active}",
consumeMode = ConsumeMode.ORDERLY,
nameServer = "${rocketmq.name-server}"
)
public static class VisaChangeLogListener extends BaseListener implements RocketMQListener<MessageExt> {
@Autowired
private EventConsumer eventConsumer;
@Override
public void onMessage(MessageExt message) {
log.info("VisaChangeLogListener onMessage nanopart, message:{}", JSON.toJSONString(message));
super.onEvent(message, eventConsumer);
}
}
// /**
// * IM 事件处理
// */
// @Slf4j
// @Component
// @RocketMQMessageListener(topic = "topic_im_center_${spring.profiles.active}",
// consumerGroup = "GID_im_${spring.application.name}_${spring.profiles.active}",
// consumeMode = ConsumeMode.ORDERLY,
// nameServer = "${rocketmq.name-server}"
// )
// public static class ImCenterListener extends BaseListener implements RocketMQListener<MessageExt> {
//
// @Autowired
// private EventConsumer eventConsumer;
//
// @Override
// public void onMessage(MessageExt message) {
// log.info("ImCenterListener onMessage nanopart, message:{}", JSON.toJSONString(message));
// super.onEvent(message, eventConsumer);
// }
// }
}

View File

@ -2,6 +2,7 @@ package cn.axzo.nanopart.config.exception;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.pokonyan.exception.BusinessException;
import cn.axzo.workflow.common.exception.WorkflowEngineException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.util.CollectionUtils;
@ -37,13 +38,13 @@ public class ExceptionAdviceHandler {
}
@ExceptionHandler(cn.axzo.framework.domain.ServiceException.class)
public ApiResult<Void> domainServiceExceptionHandler(cn.axzo.framework.domain.ServiceException e){
public ApiResult<Void> domainServiceExceptionHandler(cn.axzo.framework.domain.ServiceException e) {
log.warn("业务异常", e);
return ApiResult.err(e.getMessage());
}
@ExceptionHandler(BusinessException.class)
public ApiResult<Void> businessExceptionHandler(BusinessException e){
public ApiResult<Void> businessExceptionHandler(BusinessException e) {
log.warn("业务异常", e);
return ApiResult.err(e.getErrorMsg());
}
@ -60,4 +61,10 @@ public class ExceptionAdviceHandler {
return ApiResult.err(objectErrorDefaultMessage);
}
@ExceptionHandler(WorkflowEngineException.class)
public ApiResult<Void> workflowExceptionHandler(WorkflowEngineException e) {
log.warn("业务异常", e);
return ApiResult.err(e.getMessage());
}
}

View File

@ -14,6 +14,9 @@ spring:
main:
allow-bean-definition-overriding: true
server:
shutdown: graceful
arthas:
app-name: ${spring.application.name}
agent-id: ${ARTHAS_AGENT_ID:${spring.profiles.active}-${spring.application.name}}

View File

@ -24,6 +24,7 @@
<mapstruct.version>1.4.2.Final</mapstruct.version>
<poi.version>5.2.2</poi.version>
<easyexcel.version>3.3.3</easyexcel.version>
<feign-httpclient.version>11.8</feign-httpclient.version>
</properties>
<modules>
@ -34,6 +35,7 @@
<module>op</module>
<module>banner</module>
<module>dictionary</module>
<module>visa</module>
</modules>
<dependencyManagement>
@ -53,6 +55,12 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>${feign-httpclient.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

108
visa/pom.xml Normal file
View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.axzo.nanopart</groupId>
<artifactId>nanopart</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>cn.axzo.nanopart</groupId>
<artifactId>visa</artifactId>
<packaging>pom</packaging>
<name>visa</name>
<properties>
<axzo-bom.version>2.0.0-SNAPSHOT</axzo-bom.version>
<axzo-dependencies.version>2.0.0-SNAPSHOT</axzo-dependencies.version>
<lombok.version>1.18.22</lombok.version>
<mapstruct.version>1.4.2.Final</mapstruct.version>
<workflow-engine.version>1.5.2-SNAPSHOT</workflow-engine.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- 导入axzo通用api依赖 -->
<dependency>
<groupId>cn.axzo.infra</groupId>
<artifactId>axzo-bom</artifactId>
<version>${axzo-bom.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>cn.axzo.infra</groupId>
<artifactId>axzo-dependencies</artifactId>
<version>${axzo-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>cn.axzo.workflow</groupId>
<artifactId>workflow-engine-spring-boot-starter</artifactId>
<version>${workflow-engine.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- for test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- maven-compiler-plugin 插件,解决 Lombok + MapStruct 组合 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>axzo</id>
<name>axzo repository</name>
<url>https://nexus.axzo.cn/repository/axzo/</url>
</repository>
</repositories>
<modules>
<module>visa-api</module>
<module>visa-server</module>
</modules>
</project>

50
visa/visa-api/pom.xml Normal file
View File

@ -0,0 +1,50 @@
<?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>
<artifactId>visa</artifactId>
<groupId>cn.axzo.nanopart</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>visa-api</artifactId>
<packaging>jar</packaging>
<name>visa-api</name>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-common-domain</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.framework.rocketmq</groupId>
<artifactId>axzo-common-rocketmq</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.maokai</groupId>
<artifactId>maokai-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>cn.axzo.workflow</groupId>
<artifactId>workflow-engine-common</artifactId>
<version>${workflow-engine.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,177 @@
package cn.axzo.nanopart.visa.api.changerecord;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.nanopart.visa.api.request.ChangeRecordButtonOperationReq;
import cn.axzo.nanopart.visa.api.request.ChangeStatusRequest;
import cn.axzo.nanopart.visa.api.request.CheckVisaWithVisaIdReq;
import cn.axzo.nanopart.visa.api.request.FetchVisaAllConfirmReq;
import cn.axzo.nanopart.visa.api.request.GetBillIfRelatedReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveCreateReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveOnlyReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeDiscussCreateReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeExportReq;
import cn.axzo.nanopart.visa.api.request.VisaChangePageSearchReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeTempCreateReq;
import cn.axzo.nanopart.visa.api.request.VisaDetailByIdRequest;
import cn.axzo.nanopart.visa.api.request.VisaInitiatorListReq;
import cn.axzo.nanopart.visa.api.request.VisaSearchReq;
import cn.axzo.nanopart.visa.api.response.VisaChangeDiscussCreateResp;
import cn.axzo.nanopart.visa.api.response.VisaChangeInitiatorResp;
import cn.axzo.nanopart.visa.api.response.VisaChangePageSearchResp;
import cn.axzo.nanopart.visa.api.response.VisaDetailByIdResponse;
import cn.axzo.nanopart.visa.api.response.VisaSearchResp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录
*/
@FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
public interface ChangeRecordApi {
/**
* 暂存变更签证记录
*
* @param req {@link VisaChangeTempCreateReq} 签证变更表单数据
* @return 签证变更记录id
*/
@PostMapping("/api/visa/change/tempCreate")
ApiResult<Long> tempCreateVisaChangeRecord(@RequestBody VisaChangeTempCreateReq req);
/**
* 创建群聊洽商变更签证
*
* @param req {@link VisaChangeDiscussCreateReq}
* @return 签证变更记录id
*/
@PostMapping("/api/visa/change/discussCreate")
ApiResult<VisaChangeDiscussCreateResp> discussCreateVisaChangeRecord(@RequestBody VisaChangeDiscussCreateReq req);
/**
* 发起变更签证审批
*
* @param req {@link VisaChangeApproveCreateReq} 签证变更表单数据域审批人信息
* @return 签证变更记录id
*/
@PostMapping("/api/visa/change/approveCreate")
ApiResult<Long> approveCreateVisaChangeRecord(@RequestBody @Validated VisaChangeApproveCreateReq req);
/**
* 变签状态变更
*/
@PostMapping("/api/visa/changeStatus")
ApiResult<Boolean> changeStatus(@RequestBody @Valid ChangeStatusRequest request);
/**
* 变签详情
*/
@PostMapping("/api/visa/visaDetailById")
ApiResult<VisaDetailByIdResponse> visaDetailById(@RequestBody @Valid VisaDetailByIdRequest request);
/**
* 分页搜索
*
* @param req {@link VisaChangePageSearchReq} 筛查条件
* @return 分页记录
*/
@PostMapping("/api/visa/change/page")
ApiPageResult<VisaChangePageSearchResp> pageSearchVisaChangeRecord(@RequestBody @Validated VisaChangePageSearchReq req);
/**
* 导出
*
* @param req {@link VisaChangeExportReq} 筛选条件和导出字段
* @return void
*/
@PostMapping("/api/visa/change/export")
ApiResult<Void> exportVisaChangeRecord(@RequestBody @Validated VisaChangeExportReq req);
/**
* 获取发起人列表
*
* @param req {@link VisaInitiatorListReq}
* @return 发起人列表
*/
@PostMapping("/api/visa/change/initiator/list")
ApiResult<List<VisaChangeInitiatorResp>> listInitiator(@RequestBody @Validated VisaInitiatorListReq req);
/**
* IM 变洽签群中点击提交审批前拉取对应的确认人列表
*
* @return
*/
@PostMapping("/api/visa/change/confirm/list")
ApiResult<List<VisaChangeApproveCreateReq.ApprovePersonInfo>> getVisaAllConfirm(@Validated @RequestBody FetchVisaAllConfirmReq req);
/**
* IM 变洽签群提交审批按钮
*
* @return
*/
@PostMapping("/api/visa/change/approve/only/create")
ApiResult<Long> approveCreateOnlyVisaChangeRecord(@Validated @RequestBody VisaChangeApproveOnlyReq req);
/**
* IM 变洽签群废止按钮
*
* @return
*/
@PostMapping("/api/visa/change/record/forbid")
ApiResult<Void> forbidChangeRecord(@Validated @RequestBody ChangeRecordButtonOperationReq req);
/**
* IM 变洽签群重新发起按钮
*
* @return
*/
@PostMapping("/api/visa/change/reDecision")
ApiResult<Void> reDecisionChangeRecord(@Validated @RequestBody ChangeRecordButtonOperationReq req);
/**
* IM 变洽签群发起执行按钮
*
* @param req
* @return
*/
@PostMapping("/api/visa/change/execute")
ApiResult<Void> executeChangeRecord(@Validated @RequestBody ChangeRecordButtonOperationReq req);
/**
* 变洽签删除按钮
*
* @return void
*/
@PostMapping("/api/visa/change/delete")
ApiResult<Void> deleteChangeRecord(@Validated @RequestBody ChangeRecordButtonOperationReq req);
/**
* 校验
*/
@PostMapping("/api/visa/change/checkVisaWithVisaId")
ApiResult<Void> checkVisaWithVisaId(@Validated @RequestBody CheckVisaWithVisaIdReq req);
/**
* 获取子单据的关联状态
*
* @param req {@link GetBillIfRelatedReq}
* @return Map<billId, relationStatus> true:关联 false:不关联
*/
@PostMapping("/api/visa/change/getBillIfRelated")
ApiResult<Map<String, Boolean>> getBillIfRelated(@RequestBody @Validated GetBillIfRelatedReq req);
/**
* 查询单据
*/
@PostMapping("/api/visa/change/list")
ApiPageResult<VisaSearchResp> list(@RequestBody @Validated VisaSearchReq req);
}

View File

@ -0,0 +1,26 @@
package cn.axzo.nanopart.visa.api.changerecord;
import cn.axzo.framework.domain.web.result.ApiListResult;
import cn.axzo.nanopart.visa.api.response.FetchVisaLogByVisaIdResponse;
import cn.axzo.nanopart.visa.api.request.FetchVisaLogByVisaIdRequest;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录操作日志
*/
@FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
public interface ChangeRecordLogApi {
/**
* 根据变签Id,获取变签日志
*/
@PostMapping("/api/visa/log/fetchVisaLogByVisaId")
ApiListResult<FetchVisaLogByVisaIdResponse> fetchVisaLogByVisaId(@RequestBody @Valid FetchVisaLogByVisaIdRequest req);
}

View File

@ -0,0 +1,42 @@
package cn.axzo.nanopart.visa.api.changerecord;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.nanopart.visa.api.request.ChangeRecordAppendAttachReq;
import cn.axzo.nanopart.visa.api.request.ImGroupOperationReq;
import cn.axzo.nanopart.visa.api.request.ImGroupTipsQueryReq;
import cn.axzo.nanopart.visa.api.request.VisaRelationReq;
import cn.axzo.nanopart.visa.api.response.ImGroupTipsResp;
import cn.axzo.nanopart.visa.api.response.VisaRelationResp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录内容关系表
*/
@FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
public interface ChangeRecordRelationApi {
@PostMapping("/api/visa/relation/list")
ApiResult<List<VisaRelationResp>> listByVisaId(@Validated @RequestBody VisaRelationReq req) ;
@PostMapping("/api/visa/relation/im/operation")
ApiResult<Boolean> saveImOperationParticipate(@Validated @RequestBody ImGroupOperationReq req);
@PostMapping("/api/visa/relation/im/tips")
ApiResult<ImGroupTipsResp> queryImGroupTips(@Validated @RequestBody ImGroupTipsQueryReq req);
/**
* 变洽签追加附件
*
* @param req
* @return
*/
@PostMapping("/api/visa/relation/attach/append")
ApiResult<Void> appendAttachment(@Validated @RequestBody ChangeRecordAppendAttachReq req);
}

View File

@ -0,0 +1,9 @@
package cn.axzo.nanopart.visa.api.config;
import cn.axzo.nanopart.visa.api.constant.VisaConstant;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients(VisaConstant.BASIC_FEIGN_PACKAGE)
public class VisaApiAutoConfiguration {
}

View File

@ -0,0 +1,75 @@
package cn.axzo.nanopart.visa.api.constant;
/**
* 变洽签 API 基础包路径
*
* @author wangli
* @since 2025-01-14 17:20
*/
public interface VisaConstant {
String BASIC_FEIGN_PACKAGE = "cn.axzo.visa.api";
/**
* 用于在流程作用域外识别变洽签的单据类型
*/
String WORKFLOW_VAR_VISA_TYPE_KEY = "visa-type";
/**
* 用于发送待办的变量名
*/
String WORKFLOW_PENDING_TOPIC = "topic";
String WORKFLOW_PENDING_INITIATOR_NAME = "initiatorName";
String MSG_CENTER_APP_CODE = "nanopart-visa";
/**
* IM 群的扩展信息变洽签 ID
*/
String IM_GROUP_BIZ_INFO_VISA_ID = "visaId";
/**
* IM 群扩展信息变洽签单据类型
*/
String IM_GROUP_BIZ_INFO_VISA_TYPE = "visaType";
/**
* IM 群扩展信息群主 workspaceId
*/
String IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID = "initiatorWorkspaceId";
// **************** 业务传入审批的表单项组件的唯一的 KEY *****************
// 单号
String FORM_FIELD_NO = "no";
// 提出时间
String FORM_FIELD_HAPPEN_TIME = "happenTime";
// 主题
String FORM_FIELD_TOPIC = "topic";
// 工作台名称
String FORM_FIELD_WORKSPACE_NAME = "workspaceName";
// 关联工程
String FORM_FIELD_RELATION_PROJECT = "relationProject";
// 关联专业
String FORM_FIELD_RELATION_PROFESSIONAL = "relationProfessional";
// 发生原因
String FORM_FIELD_REASON = "reason";
// 发生区域
String FORM_FIELD_RELATION_AREA = "relationArea";
// 发生内容及说明
String FORM_FIELD_CONTEXT_DESCRIPTION = "contextDescription";
String FORM_FIELD_CONTEXT = "context";
String FORM_FIELD_DESCRIPTION = "description";
// 相关单位和人员
String FORM_FIELD_UNIT_PERSON = "unitPerson";
String FORM_FIELD_UNIT = "unit";
String FORM_FIELD_PERSON = "person";
// 变更金额
String FORM_FIELD_AMOUNT_CHANGE = "amountChange";
// 关联的任务单单据
String FORM_FIELD_RELATION_TASK_ORDER = "relationTaskOrders";
// 关联的整改单单据
String FORM_FIELD_RELATION_RECTIFICATION_ORDER = "relationRectificationOrders";
// 关联的变更单单据
String FORM_FIELD_RELATION_VISA_ORDER = "relationVisaOrders";
// 附件
String FORM_FIELD_ATTACH = "attach";
// ***************** IM-Group-Tips ******************
String IM_GROUP_OWNER_TIPS = "群成员共计%d人收到回复%d人其中%d人同意%d人拒绝。";
String IM_GROUP_PARTICIPATE_TIPS = "由 %s 提交的【%s】需要你处理是否同意";
String IM_GROUP_PARTICIPATE_TIPS_OPERATED = "你已%s由 %s 提交的【%s】";
}

View File

@ -0,0 +1,31 @@
package cn.axzo.nanopart.visa.api.enums;
import cn.axzo.framework.rocketmq.Event;
import lombok.Getter;
/**
* @Author zr
* @Date 2024/3/19 18:01
* @Description
**/
@Getter
public enum MQEventEnum {
VISA_CHANGE_LOG("nanopart", "visa-change-log", "变洽签单据日志")
;
private final String model;
private final String tag;
private final String desc;
private final Event.EventCode eventCode;
MQEventEnum(String model, String tag, String desc) {
this.eventCode = Event.EventCode.builder()
.module(model)
.name(tag)
.build();
this.model = model;
this.tag = tag;
this.desc = desc;
}
}

View File

@ -0,0 +1,26 @@
package cn.axzo.nanopart.visa.api.enums;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 变更签证单据类型
* @author xudawei
* @since 2025/01/20
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum VisaBillTypeEnum {
TASK("task", "任务单"),
RECTIFY("rectify", "整改单"),
DESIGN_VISA("design_visa", "设计变更单"),
;
private String code;
private String desc;
}

View File

@ -0,0 +1,213 @@
package cn.axzo.nanopart.visa.api.enums;
import cn.axzo.framework.domain.ServiceException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 按钮枚举
*
* @author xudawei
* @since 2025-01-15
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum VisaButtonTypeEnum {
UPDATE("update", "编辑",55),
DELETE("delete", "删除",50),
FORBID("forbid", "作废",5),
EXECUTE("execute", "发起执行",40),
REDECISION("redecision", "重新发起",0),
TO_APPROVE("to_approve", "提交审批",30),
AGAIN_TO_APPROVE("again_to_approve", "重新提交审批",20),
AGREE("agree", "同意",0),
REJECT("reject", "拒绝",0),
UPLOAD_FILE("upload_file", "上传附件",25),
CHAT_GROUP_RECORD("chat_group_record", "查看洽商记录",15),
APPROVAL_RECORD("approval_record", "查看审批记录",10),
TO_HANDLE("to_handle", "去处理", 35),
PRINT("print", "打印",45),
DETAIL("detail", "详情",0),
;
private String code;
private String desc;
/**
* 倒序-数值越大排序越靠前
* 中间新增按钮-步数为5
*/
private int orderBy;
//分页列表页Map,key:角色+单据状态value功能权限的按钮列表
private static Map<String, Set<VisaButtonTypeEnum>> bizTypeBtnMap = Maps.newHashMap();
static {
// 发起人不同状态按钮权限-详情页
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.TO_REPORT.name(), Sets.newHashSet(UPDATE, DELETE));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.REPORT_FROM_APPROVE.name(), Sets.newHashSet(UPDATE, FORBID));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(UPDATE, EXECUTE, TO_APPROVE, FORBID, CHAT_GROUP_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.DECIDING_FROM_APPROVE.name(), Sets.newHashSet(UPDATE, EXECUTE, TO_APPROVE, FORBID, CHAT_GROUP_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.EXECUTING.name(), Sets.newHashSet(UPDATE, TO_APPROVE, FORBID, CHAT_GROUP_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.APPROVING.name(), Sets.newHashSet(UPLOAD_FILE, FORBID, CHAT_GROUP_RECORD, APPROVAL_RECORD,PRINT));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.COMPLETED.name(), Sets.newHashSet(UPLOAD_FILE, CHAT_GROUP_RECORD, APPROVAL_RECORD,PRINT));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(CHAT_GROUP_RECORD, APPROVAL_RECORD));
// 决策人不同状态按钮权限-详情页
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(UPDATE, CHAT_GROUP_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.DECIDING_FROM_APPROVE.name(), Sets.newHashSet(UPDATE, CHAT_GROUP_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.EXECUTING.name(), Sets.newHashSet(UPDATE, CHAT_GROUP_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.APPROVING.name(), Sets.newHashSet(UPLOAD_FILE, CHAT_GROUP_RECORD, APPROVAL_RECORD,PRINT));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.COMPLETED.name(), Sets.newHashSet(UPLOAD_FILE, CHAT_GROUP_RECORD, APPROVAL_RECORD,PRINT));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(CHAT_GROUP_RECORD, APPROVAL_RECORD));
//审核人不同状态按钮权限-详情页
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.APPROVE.name() + VisaStatusEnum.APPROVING.name(), Sets.newHashSet(TO_HANDLE, CHAT_GROUP_RECORD,PRINT));
//其他不同状态按钮权限-详情页
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(CHAT_GROUP_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.DECIDING_FROM_APPROVE.name(), Sets.newHashSet(CHAT_GROUP_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.EXECUTING.name(), Sets.newHashSet(CHAT_GROUP_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.APPROVING.name(), Sets.newHashSet(PRINT, CHAT_GROUP_RECORD, APPROVAL_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.COMPLETED.name(), Sets.newHashSet(PRINT, CHAT_GROUP_RECORD, APPROVAL_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(CHAT_GROUP_RECORD, APPROVAL_RECORD));
//[打印]按钮是通过OMS统一配置故此处不处理
}
//分页列表页Map,key:角色+单据状态value功能权限的按钮列表
private static Map<String, Set<VisaButtonTypeEnum>> bizTypeBtnMapWhenPage = Maps.newHashMap();
static {
// 发起人不同状态按钮权限-分页列表页
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.TO_REPORT.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.REPORT_FROM_APPROVE.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.DECIDING_FROM_APPROVE.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.EXECUTING.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.APPROVING.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.COMPLETED.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(DETAIL));
// 确认人不同状态按钮权限-分页列表页
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.TO_REPORT.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.REPORT_FROM_APPROVE.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.DECIDING_FROM_APPROVE.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.EXECUTING.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.APPROVING.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.COMPLETED.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(DETAIL));
// 其他人不同状态按钮权限-分页列表页
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.TO_REPORT.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.REPORT_FROM_APPROVE.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.DECIDING_FROM_APPROVE.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.EXECUTING.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.APPROVING.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.COMPLETED.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(DETAIL));
}
/**
* 根据角色集合与单据状态获取按钮权限
*/
public static Set<VisaButtonTypeEnum> fetchBtnSetByBizTypeAndStatus(Set<VisaConfirmBizTypeEnum> bizTypeSet, VisaStatusEnum status) {
Set<VisaButtonTypeEnum> returnBtnSet = Sets.newHashSet();
if (Objects.isNull(status)) {
return Sets.newHashSet();
}
if (CollectionUtils.isEmpty(bizTypeSet)) {
bizTypeSet.add(VisaConfirmBizTypeEnum.OTHER);
}
bizTypeSet.stream()
.filter(item -> Objects.nonNull(item))
.forEach(item -> {
returnBtnSet.addAll(fetchBtnSetByBizTypeAndStatus(item, status));
});
return returnBtnSet;
}
/**
* 根据角色与单据状态获取按钮权限
*/
public static Set<VisaButtonTypeEnum> fetchBtnSetByBizTypeAndStatus(VisaConfirmBizTypeEnum bizTypeSet, VisaStatusEnum status) {
if (Objects.isNull(bizTypeSet) || Objects.isNull(status)) {
return Sets.newHashSet();
}
switch (bizTypeSet) {
case CREATE:
case CONFIRM:
case OTHER:
case APPROVE:
Set<VisaButtonTypeEnum> buttonTypeEnumSet = bizTypeBtnMap.get(bizTypeSet.name() + status.name());
return CollectionUtils.isNotEmpty(buttonTypeEnumSet) ? buttonTypeEnumSet : Sets.newHashSet();
default:
throw new ServiceException("单据确认业务类型不匹配");
}
}
/**
* 根据角色与单据状态获取按钮权限
*/
public static Set<VisaButtonTypeEnum> fetchBtnsByBizTypeAndStatusWhenPage(Set<VisaConfirmBizTypeEnum> bizTypeSet, VisaStatusEnum status) {
if (Objects.isNull(bizTypeSet) || Objects.isNull(status)) {
return Sets.newHashSet();
}
Set<VisaButtonTypeEnum> returnBtnSet = Sets.newHashSet();
bizTypeSet.stream().filter(Objects::nonNull).forEach(item -> {
switch (item) {
case CREATE:
case CONFIRM:
case OTHER:
case APPROVE:
Set<VisaButtonTypeEnum> buttonTypeEnumSet = bizTypeBtnMapWhenPage.get(item.name() + status.name());
returnBtnSet.addAll(CollectionUtils.isNotEmpty(buttonTypeEnumSet) ? buttonTypeEnumSet : Sets.newHashSet());
break;
default:
throw new ServiceException("单据确认业务类型不匹配");
}
});
return returnBtnSet;
}
public static Set<VisaButtonTypeEnum> all() {
return Sets.newHashSet(VisaButtonTypeEnum.values());
}
/**
* 按照orderBy排序-前端要求
*/
public static List<VisaButtonTypeEnum> sort(Set<VisaButtonTypeEnum> btnSet) {
if (CollectionUtils.isEmpty(btnSet)) {
return Lists.newArrayList();
}
return Lists.newArrayList(btnSet).stream()
.sorted(Comparator.comparing(VisaButtonTypeEnum::getOrderBy).reversed())
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,44 @@
package cn.axzo.nanopart.visa.api.enums;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/1/16 17:10
*/
@Getter
public enum VisaChangeFieldEnum {
NO("no", "单号"),
TYPE("type", "单据类型"),
STATUS("status", "单据状态"),
TOPIC("topic", "主题"),
AMOUNT_CHANGE("amountChange", "金额变化"),
INITIATOR("initiator", "发起人"),
CREATE_AT("happenTime", "提出时间"),
APPROVAL_COMPLETE_TIME("approvalCompleteTime", "审批通过时间"),
RELATION_PROJECT("relationProject", "所属工程"),
;
private final String value;
private final String desc;
VisaChangeFieldEnum(String value, String desc) {
this.value = value;
this.desc = desc;
}
public static VisaChangeFieldEnum getByName(String name) {
if (StringUtils.isBlank(name)) {
return null;
}
for (VisaChangeFieldEnum value : values()) {
if (value.value.equals(name)) {
return value;
}
}
return null;
}
}

View File

@ -0,0 +1,44 @@
package cn.axzo.nanopart.visa.api.enums;
import com.google.common.collect.Sets;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Set;
/**
* 业务类型
* @author xudawei
* @since 2025-01-17
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum VisaConfirmBizTypeEnum {
CONFIRM("CONFIRM", "确认"),
CREATE("CREATE", "创建"),
APPROVE("APPROVE", "审核"),
OTHER("OTHER", "其他"),
;
private String code;
private String desc;
/**
* 确认与创建
*/
private static Set<VisaConfirmBizTypeEnum> confirmCreate = Sets.newHashSet(CONFIRM, CREATE);
/**
* 确认
*/
private static Set<VisaConfirmBizTypeEnum> confirm = Sets.newHashSet(CONFIRM);
/**
* 创建
*/
private static Set<VisaConfirmBizTypeEnum> create = Sets.newHashSet(CREATE);
}

View File

@ -0,0 +1,65 @@
package cn.axzo.nanopart.visa.api.enums;
import com.google.common.collect.Sets;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
import java.util.Set;
/**
* 变签日志类型
* @author xudawei
* @since 2025-01-15
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum VisaLogTypeEnum {
CHAT_GROUP("chat_group", "发起群聊洽商","发起群聊洽商","%s发起群聊洽商"),
EDIT_FORM("edit_form", "编辑表单","%s编辑表单","%s编辑表单"),
EDIT_AMOUNT("edit_amount", "编辑金额变化","%s编辑金额变化","原值:金额变化:%s;<br> 新值:金额变化:%s;"),
UPLOAD_FILE("upload_file", "上传附件","%s上传附件","%s上传%d个附件%s"),
DELETE_UPLOAD_FILE("delete_upload_file", "删除附件","%s删除附件","%s删除%d个附件%s"),
TO_EXECUTE("to_execute", "发起执行","发起执行", "%s发起执行"),
TO_APPRROVE("to_apprrove", "发起审批","发起%s审批", "%s发起%s审批"),
APPROVED_AGRESS("approved_agress", "审批流:某审批人审批通过","%s审批通过", "%s审批通过"),
FORBIDED("forbided", "单据作废","单据废止", "%s操作废止单据"),
REVERT_APPROVE("revert_approve", "审批流:撤回审批","审批流程撤回", "%s撤回审批流程"),
REJECT_APPROVE("reject_approve", "审批流:已驳回","%s驳回审批", "%s已驳回原因为%s"),
TRANSMIT_APPROVE("transmit_approve", "审批流操作:转交","审批人变更", "%s将审批转交至%s原因为%s"),
FALLBACK_APPROVE("fallback_approve", "审批流操作:回退","%s回退审批", "%s回退审批至审批节点%s"),
APPROVE_COMPLETED("approved_completed", "审批流:审批通过","%s通过", "%s流程已完成"),
;
/**
* 审批不通过的日志集合
*/
private static final Set<VisaLogTypeEnum> approveNotAgree = Sets.newHashSet(REVERT_APPROVE, REJECT_APPROVE, FALLBACK_APPROVE);
/**
* 审批不通过的日志集合
*/
// private static final Set<VisaLogTypeEnum> approveNotAgree = Sets.newHashSet(EDIT_FORM, EDIT_AMOUNT, UPLOAD_FILE, DELETE_UPLOAD_FILE, APPROVED_AGRESS);
private String code;
private String action;
private String title;
private String content;
// private boolean
/**
* 是否审批不通过
*/
public static boolean isApproveNotAgree(VisaLogTypeEnum logType) {
return Objects.nonNull(logType) && approveNotAgree.contains(logType);
}
}

View File

@ -0,0 +1,42 @@
package cn.axzo.nanopart.visa.api.enums;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
/**
* 变洽签业务的 relation 表数据行的类型枚举
*
* @author wangli
* @since 2025-01-16 09:42
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum VisaRelationFieldEnum {
//发生内容及说明相关单位及人员单据附件审批记录
CONTENT_DESCRIPTION("content_description", "发生内容及说明"),
TASK_ORDER("task_order", "任务单"),
RECTIFICATION_ORDER("rectification_order", "整改单"),
VISA_ORDER("visa_order", "变洽签变更单"),
ATTACHMENT("attachment", "附件"),
PROCESS_INSTANCE_OF_VISA("process_instance_of_visa", "变洽签审批实例"),
PROCESS_INSTANCE_OF_ESS("process_instance_of_ess", "用印审批实例"),
ORDER("order", "单据"),
IM_GROUP_PARTICIPATE("im_group_participate", "im群聊参与人"),
;
private final String code;
private final String desc;
/**
* 是否附件类型
* @param name 枚举的名称
* @return true:是附件类型;false不是附件类型
*/
public static boolean isAttach(String name) {
if (StringUtils.isBlank(name)) {
return false;
}
return VisaRelationFieldEnum.ATTACHMENT.name().equals(name);
}
}

View File

@ -0,0 +1,22 @@
package cn.axzo.nanopart.visa.api.enums;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/1/20 16:21
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum VisaRelationVarTypeEnum {
STRING("string"),
LONG("long"),
JSON("json");
private final String type;
}

View File

@ -0,0 +1,72 @@
package cn.axzo.nanopart.visa.api.enums;
import com.google.common.collect.Sets;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* 签证业务状态
*
* @author xudawei
* @since 2025-01-15
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum VisaStatusEnum {
TO_REPORT("to_report", "待提报", null),
DECIDING("deciding", "决策中", VisaLogTypeEnum.CHAT_GROUP),
EXECUTING("executing","执行中", VisaLogTypeEnum.TO_EXECUTE),
APPROVING("approving","审批中", VisaLogTypeEnum.TO_APPRROVE),
COMPLETED("completed","已完成",VisaLogTypeEnum.APPROVE_COMPLETED),
FORBIDED("forbided","已废除",VisaLogTypeEnum.FORBIDED),
REPORT_FROM_APPROVE("report_from_approve","审批不通过到待提报", null),
DECIDING_FROM_APPROVE("deciding_from_approve","审批不通过到决策中", null),
;
/**
* 可以编辑变更签证单的状态
*/
private static Set<VisaStatusEnum> editFormStatus = Sets.newHashSet(DECIDING, EXECUTING, DECIDING_FROM_APPROVE);
/**
* 无效状态集合审批不通过到待提报/已废除
*/
private static Set<VisaStatusEnum> detailPageInvalidStatus = Sets.newHashSet(REPORT_FROM_APPROVE, FORBIDED);
private final String code;
private final String desc;
private final VisaLogTypeEnum logType;
/**
* 是否编辑变更签证单的状态
*/
public static boolean isEditForm(VisaStatusEnum status) {
if (Objects.isNull(status)) {
return false;
}
return editFormStatus.contains(status);
}
/**
* 获取所有的状态枚举
*/
public static List<VisaStatusEnum> allStatus() {
return Arrays.asList(VisaStatusEnum.values());
}
/**
* 无效状态集合审批不通过到待提报/已废除
*/
public static Set<VisaStatusEnum> detailPageInvalidStatus() {
return detailPageInvalidStatus;
}
}

View File

@ -0,0 +1,45 @@
package cn.axzo.nanopart.visa.api.enums;
import com.google.common.collect.Sets;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Set;
/**
* 签证业务类型
*
* @author wangli
* @since 2025-01-15 16:00
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum VisaTypeEnum {
DESIGN_CHANGE("bgqz01","design_change", "设计变更"),
TECHNOLOGY_APPROVED("bgqz02","technology_approved", "技术核定"),
PROJECT_VISA("bgqz03", "project_visa","工程签证");
private final String processDefinitionKey;
private final String code;
private final String desc;
private static final Set<VisaTypeEnum> changeApprovedSet = Sets.newHashSet(DESIGN_CHANGE, TECHNOLOGY_APPROVED);
private static final Set<VisaTypeEnum> projectVisaSet = Sets.newHashSet(PROJECT_VISA);
/**
* 设计变更/技术核定
*/
public static Set<VisaTypeEnum> fetchChangeApprovedSet() {
return changeApprovedSet;
}
/**
* 工程签证
*/
public static Set<VisaTypeEnum> fetchProjectVisaSet() {
return projectVisaSet;
}
}

View File

@ -0,0 +1,52 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* @author xudawei
* @date 2025/01/16
* @desc 添加变签日志
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class AddVisaLogRequest {
/**
* 变签Id
*/
@NotNull(message = "变签Id不能为空")
private Long visaId;
/**
* 日志类型
*/
@NotNull(message = "日志类型不能为空")
private VisaLogTypeEnum logType;
/**
* 操作人Id
*/
@NotNull(message = "操作人Id不能为空")
private Long personId;
/**
* 操作人单位Id
*/
@NotNull(message = "操作人单位Id不能为空")
private Long ouId;
/**
* 操作人项目Id
*/
@NotNull(message = "操作人项目Id不能为空")
private Long workspaceId;
}

View File

@ -0,0 +1,41 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.workflow.common.model.dto.UploadFieldDTO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 变洽签增加附件
*
* @author wangli
* @since 2025-02-08 14:19
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ChangeRecordAppendAttachReq {
/**
* 变洽签主键 ID
*/
@NotNull(message = "变洽签主键 ID")
private Long visaId;
/**
* 新增的附件
*/
private List<UploadFieldDTO> attach;
private Long operatorPersonId;
private Long operatorOuId;
private Long workspaceId;
}

View File

@ -0,0 +1,50 @@
package cn.axzo.nanopart.visa.api.request;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* 变洽签废止
*
* @author wangli
* @since 2025-02-05 20:26
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ChangeRecordButtonOperationReq {
/**
* 变洽签主键 ID
*/
@NotNull(message = "变洽签 ID 不能为空")
private Long visaId;
/**
* IM ID
*/
private Long imGroupId;
/**
* 操作人 personId
*/
@NotNull(message = "操作人 personId 不能为空")
private Long operatorPersonId;
/**
* 操作人 ouId
*/
@NotNull(message = "操作人 ouId 不能为空")
private Long operatorOuId;
/**
* 操作人 workspaceId
*/
@NotNull(message = "操作人 workspaceId 不能为空")
private Long operatorWorkspaceId;
}

View File

@ -0,0 +1,97 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.framework.domain.ServiceException;
import cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.response.VisaDetailByIdResponse;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
/**
* @author xudawei
* @date 2025/01/16
* @desc 变签Id获取变签日志
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ChangeStatusRequest {
/**
* 变签Id
*/
@NotNull(message = "变签Id不能为空")
private Long visaId;
/**
* 更新成状态
*/
@NotNull(message = "更新成状态不能为空")
private VisaStatusEnum updateStatus;
/**
* 操作人Id
*/
@NotNull(message = "操作人Id不能为空")
private Long personId;
/**
* 操作人单位Id
*/
@NotNull(message = "操作人单位Id不能为空")
private Long ouId;
/**
* 操作人项目Id
*/
@NotNull(message = "操作人项目Id不能为空")
private Long workspaceId;
/**
* 日志类型,
* 审批不通过(已驳回已撤回已中止) 才需要传这个信息
* 1 REVERT_APPROVE("revert_approve", "审批流:撤回审批","审批流程撤回", "%s撤回审批流程"),
* 2 REJECT_APPROVE("reject_approve", "审批流:已驳回","%s驳回审批", "%s已驳回原因为%s"),
* 3 FALLBACK_APPROVE("fallback_approve", "审批流操作:回退","%s回退审批", "%s回退审批至审批节点%s"),
*/
private VisaLogTypeEnum logType;
/**
* 新的金额,只有在[决策中执行中] -> [审批中]编辑表单是才用操作日志记录金额变更
*/
private BigDecimal newAmountChange;
/**
* 原金额
*/
private BigDecimal oldAmountChange;
/**
* 新的附件
*/
private List<VisaDetailByIdResponse.VisaUploadFile> newAttach;
/**
* 原的附件
*/
private List<VisaDetailByIdResponse.VisaUploadFile> oldAttach;
/**
* 是否编辑表单
* true:编辑表单
* false:非编辑表单
*/
private boolean editFormFlag = true;
public void check() {
if (Objects.nonNull(logType) && !VisaLogTypeEnum.isApproveNotAgree(logType)) {
throw new ServiceException("不是审核不通过日志");
}
}
}

View File

@ -0,0 +1,61 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.nanopart.visa.api.response.VisaDetailByIdResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.apache.commons.collections4.CollectionUtils;
/**
* @author xudawei@axzo.cn
* @version 1.0
* @date 2025/1/16 11:53
*/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class CheckVisaWithVisaIdReq {
/**
* 变更单号Id编辑和详情时传入{@code creatFormData}互斥使用
*/
// @NotNull(message = "变更签证单据Id不能为空")
private Long visaId;
/**
* 创建单据状态下的表单数据创建时传入{@code visaId}互斥使用
*/
private VisaChangeTempCreateReq creatFormData;
/**
* 校验
*/
public void check(VisaDetailByIdResponse response) {
AssertUtil.notNull(response.getRelationWorkspaceId(), "关联项目不能为空");
AssertUtil.notNull(response.getType(), "单据类型不能为空");
AssertUtil.notEmpty(response.getNo(), "单号不能为空");
AssertUtil.notEmpty(response.getTopic(), "主题不能为空");
AssertUtil.notNull(response.getRelationProject(), "关联工程不能为空");
AssertUtil.notEmpty(response.getHappenTime(), "提出时间不能为空");
AssertUtil.notEmpty(response.getReason(), "发生原因不能为空");
// AssertUtil.notEmpty(response.getRelationProfessionalList(), "专业不能为空");
if (CollectionUtils.isNotEmpty(response.getRelationOuAndPersonList())) {
response.getRelationOuAndPersonList().forEach(item -> {
AssertUtil.notEmpty(item.getRelationPersonList(), "确认人不能为空");
});
}
}
public void check() {
AssertUtil.notNull(this.getCreatFormData().getRelationWorkspaceId(), "关联项目不能为空");
AssertUtil.notNull(this.getCreatFormData().getType(), "单据类型不能为空");
AssertUtil.notEmpty(this.getCreatFormData().getNo(), "单号不能为空");
AssertUtil.notEmpty(this.getCreatFormData().getTopic(), "主题不能为空");
AssertUtil.notNull(this.getCreatFormData().getRelationProject(), "关联工程不能为空");
AssertUtil.notNull(this.getCreatFormData().getHappenTime(), "提出时间不能为空");
AssertUtil.notEmpty(this.getCreatFormData().getReason(), "发生原因不能为空");
}
}

View File

@ -0,0 +1,27 @@
package cn.axzo.nanopart.visa.api.request;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* 拉取指定已存在变洽签的确认人全部列表
*
* @author wangli
* @since 2025-02-06 13:56
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class FetchVisaAllConfirmReq {
/**
* 变洽签 ID
*/
@NotNull(message = "变洽签 ID 不能为空")
private Long visaId;
}

View File

@ -0,0 +1,26 @@
package cn.axzo.nanopart.visa.api.request;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* @author xudawei
* @date 2025/01/16
* @desc 变签Id获取变签日志
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class FetchVisaLogByVisaIdRequest {
/**
* 变签Id
*/
@NotNull(message = "变签Id不能为空")
private Long visaId;
}

View File

@ -0,0 +1,49 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.nanopart.visa.api.enums.VisaBillTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/2/18 11:09
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class GetBillIfRelatedReq {
/**
* 主单据类型
*
* @see VisaTypeEnum
*/
@NotNull(message = "type不能为空")
private VisaTypeEnum visaType;
/**
* 子单据类型
*
* @see VisaBillTypeEnum
*/
@NotNull(message = "billType不能为空")
private VisaBillTypeEnum billType;
/**
* 子单据id
* <p>
* {@code billType}{@link VisaBillTypeEnum#TASK}为任务单号<br>
* {@code billType}{@link VisaBillTypeEnum#RECTIFY}为整改单id<br>
* {@code billType}{@link VisaBillTypeEnum#DESIGN_VISA}为设计变更单id}
* </p>
*/
private List<String> billIds;
}

View File

@ -0,0 +1,24 @@
package cn.axzo.nanopart.visa.api.request;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* IM 群成员投票操作的清除
*
* @author wangli
* @since 2025-02-07 15:39
*/
@EqualsAndHashCode(callSuper = true)
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class ImGroupOperationClearReq extends ImGroupOperationReq{
private Boolean clearAll;
}

View File

@ -0,0 +1,56 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.nanopart.visa.api.enums.VisaButtonTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import javax.validation.constraints.NotNull;
/**
* Im 群聊中的操作
*
* @author wangli
* @since 2025-02-05 17:30
*/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class ImGroupOperationReq {
/**
* 变洽签 ID
*/
@NotNull(message = "变洽签 ID 不能为空")
private Long visaId;
/**
* IM ID
*/
@NotNull(message = "IM 群 ID 不能为空")
private Long imGroupId;
/**
* 操作类型
*/
@NotNull(message = "按钮类型不能为空")
private VisaButtonTypeEnum buttonType;
/**
* 操作人 OuId
*/
@NotNull(message = "操作人 OuId 不能为空")
private Long operatorOuId;
/**
* 操作人workspaceId
*/
@NotNull(message = "操作人 WorkspaceId 不能为空")
private Long operatorWorkspaceId;
/**
* 操作人peronId
*/
@NotNull(message = "操作人 PersonId 不能为空")
private Long operatorPersonId;
}

View File

@ -0,0 +1,60 @@
package cn.axzo.nanopart.visa.api.request;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* 用于查询 IM 群聊的中每个人的上方提示横条
*
* @author wangli
* @since 2025-02-05 16:56
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ImGroupTipsQueryReq {
/**
* IM 群的额外扩展信息变洽签的 ID
*/
@NotNull(message = "变洽签 ID 不能为空")
private Long visaId;
/**
* IM ID
*/
@NotNull(message = "IM 群 ID 不能为空")
private Long groupId;
/**
* 当前登录人是否是群主
*/
@NotNull(message = "群主标识不能为空")
private Boolean isGroupOwner;
/**
* 当前群成员总数, 包含群主
*/
private Integer groupTotalPersonCount;
/**
* 群成员的 PersonId
*/
@NotNull(message = "群成员的 PersonId 不能为空")
private Long personId;
/**
* 群成员的 OuId
*/
@NotNull(message = "群成员的 OuId 不能为空")
private Long ouId;
/**
* 群成员的 workspaceId
*/
private Long workspaceId;
}

View File

@ -0,0 +1,80 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.maokai.common.enums.SaasCooperateShipCooperateTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import javax.validation.constraints.NotBlank;
import java.util.List;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/1/16 13:33
*/
@EqualsAndHashCode(callSuper = true)
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class VisaChangeApproveCreateReq extends VisaChangeTempCreateReq {
/**
* 需要设置审批人的节点标识
*/
@NotBlank(message = "待设置审批人的节点为空")
private String activityId;
/**
* 审批人信息
*/
private List<ApprovePersonInfo> approvePersonInfoList;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class ApprovePersonInfo {
/**
* 单位类型 1施工单位 2建设单位 3监理单位 4劳务分包 5专业分包 9项目内班组 13设计单位
*
* @see cn.axzo.maokai.common.enums.SaasCooperateShipCooperateTypeEnum
*/
private SaasCooperateShipCooperateTypeEnum type;
/**
* 项目id
*/
private Long workspaceId;
/**
* 单位id
*/
private Long ouId;
/**
* 节点 Id
*/
private Long nodeId;
/**
* 审批人personId列表
*/
private Long personId;
/**
* 主要用于回显审批人的姓名
*/
private String realName;
/**
* 主要用于回显审批人头像
*/
private String avatarUrl;
}
}

View File

@ -0,0 +1,47 @@
package cn.axzo.nanopart.visa.api.request;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 通过 IM 群聊中发起的审批入参模型
*
* @author wangli
* @since 2025-02-06 13:59
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisaChangeApproveOnlyReq {
/**
* 变洽签 ID
*/
@NotNull(message = "变洽签 ID 不能为空")
private Long visaId;
/**
* 需要设置审批人的节点标识
*/
@NotBlank(message = "待设置审批人的节点为空")
private String activityId;
/**
* 审批人信息
*/
private List<VisaChangeApproveCreateReq.ApprovePersonInfo> approvePersonInfoList;
private Long operatorPersonId;
private Long operatorOuId;
private Long operatorWorkspaceId;
}

View File

@ -0,0 +1,61 @@
package cn.axzo.nanopart.visa.api.request;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.util.List;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/1/16 11:55
*/
@EqualsAndHashCode(callSuper = true)
@Data
@SuperBuilder
@NoArgsConstructor
public class VisaChangeDiscussCreateReq extends VisaChangeTempCreateReq {
/**
* 群聊人员信息
*/
private List<DiscussPersonInfo> discussPersonInfoList;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class DiscussPersonInfo {
/**
* 单位类型 1施工单位 2建设单位 3监理单位 4劳务分包 5专业分包 9项目内班组 13设计单位
*
* @see cn.axzo.maokai.common.enums.SaasCooperateShipCooperateTypeEnum
*/
private Integer type;
/**
* 项目id
*/
private Long workspaceId;
/**
* 单位id
*/
private Long unitId;
/**
* 群聊成员personId列表
*/
private Long personId;
/**
* 是否群主即发起人
*/
private Boolean isAdmin;
}
}

View File

@ -0,0 +1,39 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.nanopart.visa.api.enums.VisaChangeFieldEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/1/16 17:38
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisaChangeExportReq {
/**
* 筛选条件
*/
private VisaChangePageSearchReq filter;
/**
* 导出字段
*/
private List<VisaChangeFieldEnum> fields;
/*操作人信息*/
private Long personId;
private Long identityId;
private Integer identityType;
private Long workspaceId;
private Long ouId;
private String terminal;
}

View File

@ -0,0 +1,159 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/1/16 15:46
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisaChangePageSearchReq {
/**
* 项目id
*/
@NotNull(message = "项目id不能为空")
@Min(value = 1, message = "项目id不合法")
private Long workspaceId;
/**
* 单据类型
* <p>
* DESIGN_CHANGE设计变更
* TECHNOLOGY_APPROVED技术核定
* PROJECT_VISA工程签证
* </p>
*
* @see VisaTypeEnum
*/
private VisaTypeEnum type;
/**
* 单号或主题
* <p>
* 单号精确搜索主题模糊搜索
* </p>
*/
private String keyword;
/**
* 所属工程
*/
private Long projectId;
/**
* 发起人
*/
private List<Long> initiators;
/**
* 状态
*/
private List<VisaStatusEnum> statuses;
/**
* 变更金额区间
* <p>
* 0最小值 1最大值
* 当最小最大值均为正值表示增加均为负值表示减少
* 元素均为0表示金额不变
* </p>
*/
private List<BigDecimal> amountChange;
/**
* 提出时间区间
* 0起始时间 1结束时间
*/
private List<Date> happenTime;
/**
* 审批完成时间区间
* 0起始时间 1结束时间
*/
private List<Date> approveCompletedDate;
private Long page;
private Long pageSize;
/**
* 当前登录人的personId
*/
private Long currentPersonId;
/**
* 当前登录人的项目Id
*/
private Long currentWorkspaceId;
/**
* 当前登录人的单位Id
*/
private Long currentOuId;
/**
* 变更签证Id集合
*/
private Collection<Long> visaIds;
/**
* 变更签证Id集合-权限
*/
private Collection<Long> permissionVisaIds;
/**
* 是否需要主单据即是否被其他单据关联信息
*/
private Boolean needRelatedBill = false;
/**
* 变更签证Id
*/
private Long visaId;
/**
* 调用场景
* <p>
* PAGE: 分页列表页面调用
* SELECT: 选择器页面调用
* </p>
*/
private FromEnum from;
/**
* 主单据类型
* <p>
* 仅当{@code from}{@link FromEnum#SELECT}{@code needRelatedBill}{@code true}该字段才有效且不能为空
* </p>
*/
private VisaTypeEnum visaType;
public static enum FromEnum {
PAGE("分页列表页面调用"),
SELECT("选择器页面调用");
private final String desc;
FromEnum(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
}
}

View File

@ -0,0 +1,258 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.maokai.common.enums.SaasCooperateShipCooperateTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaBillTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import cn.axzo.workflow.common.model.dto.UploadFieldDTO;
import com.alibaba.fastjson.JSONArray;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/1/16 11:53
*/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class VisaChangeTempCreateReq {
/**
* 变更单号Id
*/
private Long id;
/**
* 单号
*/
@NotBlank(message = "请输入单号")
@Size(max = 100, message = "单号长度不能超过100个字符")
private String no;
/**
* 主题
*/
@NotBlank(message = "请输入主题")
@Size(max = 100, message = "主题长度不能超过100个字符")
private String topic;
/**
* 项目
*/
@NotNull(message = "关联项目不能为空")
@Min(value = 1, message = "关联项目不能为空")
private Long relationWorkspaceId;
/**
* 工程
*/
@NotNull(message = "请选择工程")
@Min(value = 1, message = "请选择工程")
private Long relationProject;
/**
* 工程名称
*/
@NotBlank(message = "工程名称不能为空")
private String relationProjectName;
/**
* 区域集合
* 示例
* <pre>
* [
* {"areaId": 249556},
* {"areaId": 249555}
* ]
* </pre>
*/
private JSONArray relationArea;
/**
* 提出时间
*/
@NotNull(message = "请选择提出时间")
private Date happenTime;
/**
* 专业集合
* 示例
* <pre>
* [
* {"code":"code1"},
* {"code":"code2"},
* ]
* </pre>
*/
// @NotNull(message = "请选择专业")
private JSONArray relationProfessional;
/**
* 发生原因
*/
@NotBlank(message = "请填写发生原因")
@Size(max = 500, message = "发生原因长度不能超过500个字符")
private String reason;
/**
* 单据类型
*/
@NotNull(message = "请选择变更签证类型")
private VisaTypeEnum type;
/**
* 相关单位及人员
*/
private List<RelationUnitAndPerson> relationUnitAndPersonList;
/**
* 发生内容说明
*/
private List<ChangeContextAndDescription> changeContextAndDescriptionList;
/**
* 有符号的变更金额
*/
private BigDecimal amountChange;
/**
* 关联的单据key: 单据类型value: 单据id集合
* <p>
* TASK 任务单 RECTIFY 整改单 DESIGN_VISA变更单
* 只有变更签证类型即{@code type}技术核定工程签证时才可能会有关联变更单
* </p>
*
* @see VisaBillTypeEnum
*/
private Map<String, List<OrderSimpleModel>> relationOrderMap;
/**
* 附件json列表
* <p>
* {
* "fileUrl": "http://www.baidu.com/img1.jpeg",
* "fileKey": "jskjksjgnaqkjkgag",
* "fileName": "附件1.jpg"
* }
* </p>
*/
@Size(max = 30, message = "最多支持上传30个附件已超出请重新选择")
private List<UploadFieldDTO> attach;
private Long operatorOuId;
private Integer operatorOuType;
private Long operatorNodeId;
/**
* 操作人peronId
*/
private Long operatorPersonId;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class OrderSimpleModel {
/**
* 单据主键 ID
*/
private Long id;
/**
* 单据编号
*/
private String no;
/**
* 单据名称
*/
private String name;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class RelationUnitAndPerson {
/**
* 单位类型 1施工单位 2建设单位 3监理单位 4劳务分包 5专业分包 9项目内班组 13设计单位
*
* @see cn.axzo.maokai.common.enums.SaasCooperateShipCooperateTypeEnum
*/
private SaasCooperateShipCooperateTypeEnum type;
/**
* 单位 ID
*/
private Long ouId;
/**
* 确认人所在部门节点id或项目内班组节点id
*/
private Long nodeId;
/**
* 确认人personId
*/
private Long personId;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class ChangeContextAndDescription {
/**
* 内容类型1图片 2图纸批注
*/
private Integer type;
/**
* 图片或图纸url
*/
private String fileUrl;
/**
* 图片或图纸key
*/
private String fileKey;
/**
* 图片或图纸名称
*/
private String fileName;
/**
* 图纸批注id{@code type}为2时使用
*/
private Long annotationId;
/**
* 图纸图框id{@code type}为2时使用
*/
private Long borderId;
/**
* 内容说明
*/
private String text;
}
}

View File

@ -0,0 +1,44 @@
package cn.axzo.nanopart.visa.api.request;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* @author xudawei
* @date 2025/01/16
* @desc 变签Id获取变签日志
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class VisaDetailByIdRequest {
/**
* 变签Id
*/
@NotNull(message = "变签Id不能为空")
private Long visaId;
/**
* 人员Id
*/
private Long personId;
private Long workspaceId;
private Long ouId;
private Long projectId;
/**
* 是否需要btnList
* true:需要, 则personId/ouId/workspaceId 必填需要查询确认人信息
* false:不需要
*/
private boolean needBtnList = true;
}

View File

@ -0,0 +1,36 @@
package cn.axzo.nanopart.visa.api.request;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/1/22 9:41
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisaInitiatorListReq {
@NotNull(message = "workspaceId不能为空")
private Long workspaceId;
/**
* 当前登录人的personId
*/
private Long currentPersonId;
/**
* 当前登录人的项目Id
*/
private Long currentWorkspaceId;
/**
* 当前登录人的单位Id
*/
private Long currentOuId;
}

View File

@ -0,0 +1,36 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.nanopart.visa.api.enums.VisaRelationFieldEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
/**
* 变洽签关联数据查询入参模型
*
* @author wangli
* @since 2025-01-16 10:46
*/
@Data
@Accessors(chain = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisaRelationReq {
/**
* 变洽签单据 ID
*/
@NotNull(message = "变洽签单据 ID不能为空")
private Long visaId;
/**
* 关联表中指定类型
* 可为空则查询所有关联的数据
*/
private VisaRelationFieldEnum fieldEnum;
}

View File

@ -0,0 +1,81 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.core.domain.PageRequest;
import cn.axzo.framework.domain.ServiceException;
import cn.axzo.nanopart.visa.api.enums.VisaBillTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.util.StringUtils;
import java.util.Objects;
/**
* @author xudawei
* @date 2025/01/16
* @desc 变签Id获取变签日志
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class VisaSearchReq extends PageRequest {
/**
* 变签Id
*/
private Long visaId;
/**
* 项目Id
*/
private Long workspaceId;
/**
* 变签编号
*/
private String visaNo;
/**
* 单据类型,任务单:TASK;整改单:RECTIFY;变更单:VISA
*/
private VisaBillTypeEnum billType;
/**
* 单据Id
*/
private Long billId;
/**
* 单据编号
*/
private String billNo;
/**
* 校验
*/
public void check() {
if (Objects.isNull(this.getBillId())
&& Objects.isNull(this.getBillNo())
&& Objects.isNull(this.getBillType())
&& Objects.isNull(this.getVisaId())
&& !StringUtils.hasText(this.getVisaNo())) {
throw new ServiceException("参数不合法");
}
repairPage();
}
/**
* 修复page
*/
public void repairPage() {
if (Objects.isNull(this.page)) {
this.setPage(1);
}
if (Objects.isNull(this.pageSize)) {
this.setPageSize(20);
}
}
}

View File

@ -0,0 +1,36 @@
package cn.axzo.nanopart.visa.api.response;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author xudawei
* @date 2025/01/16
* @desc 变签Id获取变签日志
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class FetchVisaLogByVisaIdResponse {
/**
* 操作标题
*/
private String title;
/**
* 操作内容
*/
private String content;
/**
* 创建时间
*/
private Date createAt;
}

View File

@ -0,0 +1,29 @@
package cn.axzo.nanopart.visa.api.response;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* IM 群聊中的按钮
*
* @author wangli
* @since 2025-02-05 16:47
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ImGroupButton {
/**
* 按钮文案
*/
private String name;
/**
* 按钮类型
*/
private String type;
}

View File

@ -0,0 +1,36 @@
package cn.axzo.nanopart.visa.api.response;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* IM 群聊上方横条
*
* @author wangli
* @since 2025-02-05 16:37
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ImGroupTipsResp {
private VisaStatusEnum status;
private String statusText;
private String tipsText;
private List<ImGroupButton> buttonList;
private VisaTypeEnum visaType;
private String visaTypeText;
}

View File

@ -0,0 +1,33 @@
package cn.axzo.nanopart.visa.api.response;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/2/10 14:17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisaChangeDiscussCreateResp {
/**
* 变洽签单据id
*/
private Long visaId;
/**
* 群聊id
*/
private Long imGroupId;
/**
* 群聊名称
*/
private String imGroupName;
}

View File

@ -0,0 +1,64 @@
package cn.axzo.nanopart.visa.api.response;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/1/16 18:43
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisaChangeInitiatorResp {
/**
* 发起人personId
*/
private Long personId;
/**
* 发起人姓名
*/
private String name;
/**
* 发起人头像
*/
private String avatar;
/**
* 岗位id
*/
private Long jobId;
/**
* 岗位名称
*/
private String jobName;
/**
* 岗位编码
*/
private String jobCode;
/**
* 单位id
*/
private Long ouId;
/**
* 所属单位节点id或班组节点id
*/
private Long nodeId;
/**
* 所属单位名称或班组名称
*/
private String unitOrTeamName;
}

View File

@ -0,0 +1,155 @@
package cn.axzo.nanopart.visa.api.response;
import cn.axzo.nanopart.visa.api.enums.VisaButtonTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;
import java.util.Set;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/1/16 16:29
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisaChangePageSearchResp {
private Long id;
/**
* 单号
*/
private String no;
/**
* 主题
*/
private String topic;
/**
* 项目
*/
private Long relationWorkspaceId;
/**
* 工程
*/
private Long relationProject;
/**
* 工程名称
*/
private String relationProjectName;
/**
* 提出时间
*/
private Date happenTime;
/**
* 最终审批时间
*/
private Date approvalCompleteTime;
/**
* 单据类型
* <p>
* DESIGN_CHANGE: 设计变更
* TECHNOLOGY_APPROVED: 技术核定
* PROJECT_VISA: 工程签证
* </p>
*
* @see VisaTypeEnum
*/
private VisaTypeEnum type;
/**
* 单据类型描述
*/
private String typeDesc;
/**
* 状态
* <p>
* TO_REPORT: 待提报
* DECIDING: 决策中
* EXECUTING: 执行中
* APPROVING: 审批中
* COMPLETED: 已完成
* FORBIDED: 已废除
* </p>
*
* @see VisaStatusEnum
*/
private VisaStatusEnum status;
/**
* 状态描述
*/
private String statusDesc;
/**
* 有符号的变更金额
*/
private BigDecimal amountChange;
/**
* 发起人
*/
private VisaChangeInitiatorResp initiator;
/**
* 发生原因
*/
private String reason;
/**
* 是否被其他变更签证单单据关联
*/
private Boolean isRelated;
/**
* 操作按钮
* <p>
* UPDATE: 编辑
* DETAIL: 详情
* UPLOAD_FILE: 上传附件
* APPROVE_RECORD: 查看审批记录
* </p>
*
* @see VisaButtonTypeEnum
*/
private Set<VisaButtonTypeEnum> operateBtnSet;
public String getTypeDesc() {
if (Objects.isNull(type)) {
return null;
}
return type.getDesc();
}
public String getStatusDesc() {
if (Objects.isNull(status)) {
return null;
}
if (VisaStatusEnum.REPORT_FROM_APPROVE.equals(status)) {
return VisaStatusEnum.TO_REPORT.getDesc();
}
if (VisaStatusEnum.DECIDING_FROM_APPROVE.equals(status)) {
return VisaStatusEnum.DECIDING.getDesc();
}
return status.getDesc();
}
}

View File

@ -0,0 +1,613 @@
package cn.axzo.nanopart.visa.api.response;
import cn.axzo.maokai.common.enums.SaasCooperateShipCooperateTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaButtonTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import cn.axzo.nanopart.visa.api.request.VisaChangeTempCreateReq;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author xudawei
* @date 2025/01/16
* @desc 变签Id获取变签日志
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class VisaDetailByIdResponse {
/**
* 变签Id
*/
private Long visaId;
/**
* 单号
*/
private String no;
/**
* 单据类型
*/
private VisaTypeEnum type;
/**
* 发生原因
*/
private String reason;
/**
* 发起人姓名
*/
private String createName;
/**
* 发起人头像
*/
private String createAvatarUrl;
/**
* 发起人岗位名称
*/
private String createJobName;
/**
* 发起人岗位code
*/
private String createJobCode;
/**
* 发起人单位名称
*/
private String createOuName;
/**
* 发起人单位Id
*/
private Long createOuId;
/**
* 发起人Id
*/
private Long createBy;
/**
* 所属工程
*/
private Long relationProject;
/**
* 所属工程名称
*/
private String relationProjectName;
/**
* 主题
*/
private String topic;
/**
* 项目
*/
private Long relationWorkspaceId;
/**
* 项目名称
*/
private String relationWorkspaceName;
/**
* 区域集合
*/
private List<RelationAreaDetail> relationAreaList;
/**
* 区域集合名称
*/
private String relationAreaName;
/**
* 提出时间
*/
private String happenTime;
/**
* 最终审批时间
*/
private String approvalCompleteTime;
/**
* 专业集合
*/
private List<RelationProfessionalDetail> relationProfessionalList;
/**
* 专业集合名称
*/
private String relationProfessionalName;
/**
* 相关单位及人员
*/
private List<RelationOuAndPerson> relationOuAndPersonList;
/**
* 发生内容说明
*/
private List<VisaChangeTempCreateReq.ChangeContextAndDescription> changeContextAndDescriptionList;
/**
* 有符号的变更金额
*/
private String amountChange;
/**
* 附件
*/
private List<VisaUploadFile> attach;
/**
* 按钮
*/
private List<VisaButtonTypeEnum> btnList;
/**
* 任务单
*/
private List<String> relationTaskList;
/**
* 整改单
*/
private List<String> relationRectifyList;
/**
* 变更单
*/
private List<String> relationVisaList;
/**
* 关联无效的变更单
*/
private List<String> relationInvalidVisaList;
/**
* 状态
*/
private VisaStatusEnum status;
/**
* 群组ID
*/
private Long imGroupId;
/**
* 最终审批ID
*/
private String approvalId;
/**
* 最终审批状态
*/
private String approvalStatus;
/**
* 当前登录人的personId
*/
private Long currentPersonId;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class RelationOuAndPerson {
/**
* 相关单位
*/
private RelationUnit relationOu;
/**
* 相关确认人
*/
private List<RelationPerson> relationPersonList;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class RelationUnit {
/**
* 类型
*/
private String type;
/**
* 单位id
*/
private Long ouId;
/**
* 单位名称
*/
private String ouName;
/**
* 节点Id
*/
private Long nodeId;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class RelationPerson {
/**
* 类型
*/
private SaasCooperateShipCooperateTypeEnum type;
/**
* 单位id
*/
private Long ouId;
/**
* 确认人名称
*/
private String realName;
/**
* 头像
*/
private String avatarUrl;
/**
* 节点id
*/
private Long nodeId;
/**
* 确认人personId
*/
private Long personId;
/**
* 项目Id
*/
private Long workspaceId;
/**
* 工程Id
*/
private Long projectId;
/**
* 岗位Id
*/
private Long jobId;
/**
* 岗位名称
*/
private String jobName;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class ChangeContextAndDescription {
/**
* 内容类型1图片 2图纸批注
*/
private Integer Type;
/**
* 图片或图纸
*/
private String imgUrl;
/**
* 内容说明
*/
private String text;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class RelationProfessional {
/**
* code
*/
private String code;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class RelationProfessionalDetail {
/**
* code
*/
private String code;
/**
* 构建专业集合-对象集合
*/
public static List<VisaDetailByIdResponse.RelationProfessionalDetail> buildProfessionWithObject(JSONArray relationProfessional) {
if (CollectionUtils.isEmpty(relationProfessional)) {
return Lists.newArrayList();
}
List<VisaDetailByIdResponse.RelationProfessionalDetail> professionalList = relationProfessional.toJavaList(VisaDetailByIdResponse.RelationProfessionalDetail.class);
if (CollectionUtils.isEmpty(professionalList)) {
return Lists.newArrayList();
}
List<RelationProfessionalDetail> filter = professionalList.stream().filter(item -> Objects.nonNull(item) && StringUtils.isNotBlank(item.getCode())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(filter)) {
return Lists.newArrayList();
}
return filter;
}
/**
* 构建专业集合-code集合
*/
public static Set<String> buildProfessionWithCode(JSONArray relationProfessional) {
List<RelationProfessionalDetail> relationProfessionalDetails = RelationProfessionalDetail.buildProfessionWithObject(relationProfessional);
if (CollectionUtils.isEmpty(relationProfessionalDetails)) {
return Sets.newHashSet();
}
return relationProfessionalDetails.stream()
.filter(item -> Objects.nonNull(item) && StringUtils.isNotBlank(item.getCode()))
.map(RelationProfessionalDetail::getCode).collect(Collectors.toSet());
}
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class RelationAreaDetail {
/**
* id
*/
private Long areaId;
public static List<VisaDetailByIdResponse.RelationAreaDetail> buildAreaWithObject(JSONArray relationArea) {
if (CollectionUtils.isEmpty(relationArea)) {
return Lists.newArrayList();
}
List<VisaDetailByIdResponse.RelationAreaDetail> relationAreaList = relationArea.toJavaList(VisaDetailByIdResponse.RelationAreaDetail.class);
if (CollectionUtils.isEmpty(relationAreaList)) {
return Lists.newArrayList();
}
List<RelationAreaDetail> filter = relationAreaList.stream().filter(item -> Objects.nonNull(item) && Objects.nonNull(item.getAreaId())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(filter)) {
return Lists.newArrayList();
}
return filter;
}
public static List<Long> buildAreaWithId(JSONArray relationArea) {
List<VisaDetailByIdResponse.RelationAreaDetail> areaDetailList = RelationAreaDetail.buildAreaWithObject(relationArea);
if (CollectionUtils.isEmpty(areaDetailList)) {
return Lists.newArrayList();
}
return areaDetailList.stream().map(VisaDetailByIdResponse.RelationAreaDetail::getAreaId).collect(Collectors.toList());
}
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class RelationRectifyOrder {
/**
* 整改单id
*/
private Long id;
/**
* 整改单号
*/
private String rectifyNo;
/**
* 名称
*/
private String name;
/**
* 开始时间
*/
private String startTime;
/**
* 结束时间
*/
private String endTime;
/**
* 共计天数
*/
private String totalDays;
/**
* 发起人
*/
private String createName;
/**
* 发起人Id
*/
private Long createBy;
/**
* 发起人岗位名称
*/
private String createJobName;
/**
* 发起人岗位Id
*/
private Long createJobId;
/**
* 发起人单位名称
*/
private String createOuName;
/**
* 发起人单位Id
*/
private String createOuId;
/**
* 责任人
*/
private String rectifierName;
/**
* 责任人Id
*/
private Long rectifier;
/**
* 责任人岗位名称
*/
private String rectifierJobName;
/**
* 责任人岗位Id
*/
private Long rectifierJobId;
/**
* 责任人单位名称
*/
private String rectifierOuName;
/**
* 责任人单位Id
*/
private String rectifierOuId;
/**
* 销项人
*/
private String verifierName;
/**
* 销项人Id
*/
private Long verifier;
/**
* 销项人岗位名称
*/
private String verifierJobName;
/**
* 销项人岗位Id
*/
private Long verifierJobId;
/**
* 销项人单位名称
*/
private String verifierOuName;
/**
* 销项人单位Id
*/
private String verifierOuId;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class RelationVisaDetail {
/**
* 主题
*/
private String topic;
/**
* 单号
*/
private String no;
/**
* 有符号的变更金额
*/
private String amountChange;
/**
* 发起人
*/
private String createName;
/**
* 提出时间
*/
private Date happenTime;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class VisaUploadFile {
/**
* 文件Url
*/
private String fileUrl;
/**
* 文件key
*/
private String fileKey;
/**
* 文件名称
*/
private String fileName;
/**
* 创建集合
*/
public static List<VisaUploadFile> createListByJson(List<JSONObject> jsonObjectList) {
if (CollectionUtils.isEmpty(jsonObjectList)) {
return Lists.newArrayList();
}
List<VisaUploadFile> fileDtoList = Lists.newArrayList();
for(JSONObject json : jsonObjectList) {
fileDtoList.add(json.toJavaObject(VisaUploadFile.class));
}
return fileDtoList;
}
}
}

View File

@ -0,0 +1,58 @@
package cn.axzo.nanopart.visa.api.response;
import cn.axzo.nanopart.visa.api.enums.VisaRelationFieldEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* 变洽签关联的行数据相应模型
*
* @author wangli
* @since 2025-01-16 09:50
*/
@Data
@Accessors(chain = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisaRelationResp {
private Long id;
/**
* 变洽签主单据编号
*/
private String visaId;
/**
* 变洽签单据关联的行数据类型
* {@link VisaRelationFieldEnum}
*/
private String varName;
/**
* 数据类型的扩展内容
*/
private String varExt;
/**
* 数据值的 java 类型
*/
private String varType;
/**
* 数据值
*/
private String content;
/**
* 数据值的一些额外描述
*/
private String contentExt;
/**
* 创建时间
*/
private Date createAt;
}

View File

@ -0,0 +1,144 @@
package cn.axzo.nanopart.visa.api.response;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
import java.util.List;
/**
* @author xudawei@axzo.cn
* @date 2025/2/18
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisaSearchResp {
/**
* 变更单据Id
*/
private Long visaId;
/**
* 单据号
*/
private String no;
/**
* 主题
*/
private String topic;
/**
* 项目
*/
private Long relationWorkspaceId;
/**
* 工程
*/
private Long relationProject;
/**
* 区域集合
* 示例
* <pre>
* [
* {"areaId": 249556},
* {"areaId": 249555}
* ]
* </pre>
*/
private List<VisaDetailByIdResponse.RelationAreaDetail> relationArea;
/**
* 专业集合
* 示例
* <pre>
* [
* {"code":"code1"},
* {"code":"code2"},
* ]
* </pre>
*/
private List<VisaDetailByIdResponse.RelationProfessionalDetail> relationProfessional;
/**
* 提出时间
*/
private Date happenTime;
/**
* 有符号的变更金额
*/
private String amountChange;
/**
* 发生原因
*/
private String reason;
/**
* 单据类型
*/
private VisaTypeEnum type;
/**
* 状态
*/
private VisaStatusEnum status;
/**
* 最终审批ID
*/
private String approvalId;
/**
* 最终审批状态
*/
private String approvalStatus;
/**
* 最终审批时间
*/
private Date approvalCompleteTime;
/**
* IM群组ID
*/
private Long imGroupId;
/**
* 额外信息
*/
private JSONObject extra;
/**
* 创建人id
*/
private Long createBy;
/**
* 修改人id
*/
private Long updateBy;
/**
* 创建时间
*/
protected Date createAt;
/**
* 修改时间
*/
protected Date updateAt;
}

View File

@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.axzo.nanopart.visa.api.config.VisaApiAutoConfiguration

132
visa/visa-server/pom.xml Normal file
View File

@ -0,0 +1,132 @@
<?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">
<parent>
<groupId>cn.axzo.nanopart</groupId>
<artifactId>visa</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>visa-server</artifactId>
<packaging>jar</packaging>
<name>visa-server</name>
<dependencies>
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-web-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-consumer-spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-processor-spring-boot-starter</artifactId>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-mybatisplus-spring-boot-starter</artifactId>
</dependency>
<!-- swagger-yapi -->
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-swagger-yapi-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-logger-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.framework.rocketmq</groupId>
<artifactId>axzo-common-rocketmq</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.pokonyan</groupId>
<artifactId>pokonyan</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.workflow</groupId>
<artifactId>workflow-engine-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.maokai</groupId>
<artifactId>maokai-api</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.nanopart</groupId>
<artifactId>visa-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>cn.axzo.basics</groupId>
<artifactId>basics-profiles-api</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.maokai</groupId>
<artifactId>maokai-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>cn.axzo</groupId>
<artifactId>thor-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.apollo</groupId>
<artifactId>apollo-api</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.basics</groupId>
<artifactId>basics-domainless-api</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.org</groupId>
<artifactId>org-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>cn.axzo.karma</groupId>
<artifactId>karma-api</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.platform</groupId>
<artifactId>axzo-log-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.digital</groupId>
<artifactId>digital-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,53 @@
package cn.axzo.nanopart.visa.server.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
/**
* nacos 动态更新的对象
*
* @author wangli
* @since 2025-02-07 16:03
*/
@Data
@Component
@RefreshScope
public class RefreshableConfiguration {
/**
* IM 群创建成功后发送卡片模板
*/
@Value("${visa.im.card:261c7fa3db344fb69f3553f695a5a19c}")
private String imGroupCardTemplateCode;
/**
* 变更签证洽商通知
* IM 群添加成员给新成员发送的通知
*/
@Value("${visa.im.notice.addMember:2a4fe042020f4dd783b73fdbb6e6ac98}")
private String imGroupAddMemberNoticeTemplateCode;
/**
* 配合上面的通知发送使用
*/
@Value("${visa.im.event.addMember:visaNegotiation}")
private String imGroupAddMemberNoticeEventCode;
/**
* 相关单位确认人人数限制
*/
@Value("${visa.verifyPersonLimit: 8}")
private Integer verifyPersonLimit;
/**
* 关联变更单个数限制
*/
@Value("${visa.verifyVisaLimit: 5}")
private Integer verifyVisaLimit;
/**
* 发生内容及说明数量限制
*/
@Value("${visa.verifyChangeContextLimit: 50}")
private Integer verifyChangeContextLimit;
}

View File

@ -0,0 +1,184 @@
package cn.axzo.nanopart.visa.server.controller;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.framework.domain.web.result.PageData;
import cn.axzo.nanopart.visa.api.changerecord.ChangeRecordApi;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.request.ChangeRecordButtonOperationReq;
import cn.axzo.nanopart.visa.api.request.ChangeStatusRequest;
import cn.axzo.nanopart.visa.api.request.CheckVisaWithVisaIdReq;
import cn.axzo.nanopart.visa.api.request.FetchVisaAllConfirmReq;
import cn.axzo.nanopart.visa.api.request.GetBillIfRelatedReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveCreateReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveOnlyReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeDiscussCreateReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeExportReq;
import cn.axzo.nanopart.visa.api.request.VisaChangePageSearchReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeTempCreateReq;
import cn.axzo.nanopart.visa.api.request.VisaDetailByIdRequest;
import cn.axzo.nanopart.visa.api.request.VisaInitiatorListReq;
import cn.axzo.nanopart.visa.api.request.VisaSearchReq;
import cn.axzo.nanopart.visa.api.response.VisaChangeDiscussCreateResp;
import cn.axzo.nanopart.visa.api.response.VisaChangeInitiatorResp;
import cn.axzo.nanopart.visa.api.response.VisaChangePageSearchResp;
import cn.axzo.nanopart.visa.api.response.VisaDetailByIdResponse;
import cn.axzo.nanopart.visa.api.response.VisaSearchResp;
import cn.axzo.nanopart.visa.server.service.ChangeRecordBillService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordConfirmService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录
*/
@Slf4j
@RestController
@RequiredArgsConstructor
public class ChangeRecordController implements ChangeRecordApi {
@Autowired
private ChangeRecordService changeRecordService;
@Autowired
private ChangeRecordConfirmService changeRecordConfirmService;
@Autowired
private ChangeRecordBillService changeRecordBillService;
@Override
public ApiResult<Long> tempCreateVisaChangeRecord(VisaChangeTempCreateReq req) {
return ApiResult.ok(changeRecordService.tempCreateVisaChangeRecord(req));
}
@Override
public ApiResult<Void> checkVisaWithVisaId(CheckVisaWithVisaIdReq req) {
changeRecordService.checkVisaWithVisaId(req);
return ApiResult.ok();
}
@Override
public ApiResult<VisaChangeDiscussCreateResp> discussCreateVisaChangeRecord(VisaChangeDiscussCreateReq req) {
return ApiResult.ok(changeRecordService.discussCreateVisaChangeRecord(req));
}
@Override
public ApiResult<Long> approveCreateVisaChangeRecord(VisaChangeApproveCreateReq req) {
return ApiResult.ok(changeRecordService.approveCreateVisaChangeRecord(req));
}
/**
* 变签状态变更
*/
@Override
public ApiResult<Boolean> changeStatus(@RequestBody @Valid ChangeStatusRequest request) {
return ApiResult.ok(changeRecordService.changeStatus(request));
}
/**
* 变签详情
*/
@Override
public ApiResult<VisaDetailByIdResponse> visaDetailById(@RequestBody @Valid VisaDetailByIdRequest req) {
VisaDetailByIdResponse resp = changeRecordService.detailById(req.getVisaId());
if (req.isNeedBtnList()) {
// resp.setBtnList(VisaButtonTypeEnum.sort(VisaButtonTypeEnum.all()));
resp.setBtnList(changeRecordConfirmService.fetchBtnsByCondition(req.getVisaId(), req.getPersonId(), req.getOuId(), req.getWorkspaceId(), resp.getStatus(), resp.getApprovalId()));
}
return ApiResult.ok(resp);
}
@Override
public ApiPageResult<VisaChangePageSearchResp> pageSearchVisaChangeRecord(VisaChangePageSearchReq req) {
//重新赋值属性,待提报:TO_REPORT/REPORT_FROM_APPROVE,决策中:DECIDING/DECIDING_FROM_APPROVE
this.rechangeAttr(req);
PageData<VisaChangePageSearchResp> pageData = changeRecordService.page(req);
return ApiPageResult.ok(pageData.getList(), pageData.getTotalCount(), pageData.getPage(), pageData.getPageSize());
}
@Override
public ApiPageResult<VisaSearchResp> list(VisaSearchReq req) {
PageData<VisaSearchResp> page = changeRecordService.list(req);
return ApiPageResult.ok(page.getList(), page.getTotalCount(), page.getPage(), page.getPageSize());
}
/**
* 重新赋值属性
* 待提报:TO_REPORT/REPORT_FROM_APPROVE
* 决策中:DECIDING/DECIDING_FROM_APPROVE
*/
private void rechangeAttr(VisaChangePageSearchReq req) {
if (Objects.nonNull(req) && CollectionUtils.isNotEmpty(req.getStatuses()) && req.getStatuses().contains(VisaStatusEnum.TO_REPORT)) {
req.getStatuses().add(VisaStatusEnum.REPORT_FROM_APPROVE);
}
if (Objects.nonNull(req) && CollectionUtils.isNotEmpty(req.getStatuses()) && req.getStatuses().contains(VisaStatusEnum.DECIDING)) {
req.getStatuses().add(VisaStatusEnum.DECIDING_FROM_APPROVE);
}
}
@Override
public ApiResult<Void> exportVisaChangeRecord(VisaChangeExportReq req) {
changeRecordService.export(req);
return ApiResult.ok();
}
@Override
public ApiResult<List<VisaChangeInitiatorResp>> listInitiator(VisaInitiatorListReq req) {
return ApiResult.ok(changeRecordService.listInitiator(req));
}
@Override
public ApiResult<List<VisaChangeApproveCreateReq.ApprovePersonInfo>> getVisaAllConfirm(FetchVisaAllConfirmReq req) {
return ApiResult.ok(changeRecordConfirmService.listAllConfirmByVisaId(req.getVisaId()));
}
@Override
public ApiResult<Long> approveCreateOnlyVisaChangeRecord(VisaChangeApproveOnlyReq req) {
return ApiResult.ok(changeRecordService.approveCreateOnlyVisaChangeRecord(req));
}
@Override
public ApiResult<Void> forbidChangeRecord(ChangeRecordButtonOperationReq req) {
changeRecordService.forbid(req);
return ApiResult.ok();
}
@Override
public ApiResult<Void> reDecisionChangeRecord(ChangeRecordButtonOperationReq req) {
changeRecordService.reDecision(req);
return ApiResult.ok();
}
@Override
public ApiResult<Void> executeChangeRecord(ChangeRecordButtonOperationReq req) {
changeRecordService.doExecute(req);
return ApiResult.ok();
}
@Override
public ApiResult<Void> deleteChangeRecord(ChangeRecordButtonOperationReq req) {
changeRecordService.delete(req);
return ApiResult.ok();
}
@Override
public ApiResult<Map<String, Boolean>> getBillIfRelated(GetBillIfRelatedReq req) {
return ApiResult.ok(changeRecordBillService.getBillIfRelated(req));
}
}

View File

@ -0,0 +1,39 @@
package cn.axzo.nanopart.visa.server.controller;
import cn.axzo.framework.domain.web.result.ApiListResult;
import cn.axzo.nanopart.visa.api.changerecord.ChangeRecordLogApi;
import cn.axzo.nanopart.visa.api.request.FetchVisaLogByVisaIdRequest;
import cn.axzo.nanopart.visa.api.response.FetchVisaLogByVisaIdResponse;
import cn.axzo.nanopart.visa.server.service.ChangeRecordLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录操作日志
*/
@Slf4j
@RestController
public class ChangeRecordLogController implements ChangeRecordLogApi {
@Autowired
private ChangeRecordLogService changeRecordLogService;
/**
* 根据变签Id,获取变签日志
*/
@Override
public ApiListResult<FetchVisaLogByVisaIdResponse> fetchVisaLogByVisaId(@RequestBody @Valid FetchVisaLogByVisaIdRequest req) {
List<FetchVisaLogByVisaIdResponse> responseList = changeRecordLogService.fetchVisaLogByVisaId(req.getVisaId());
return ApiListResult.ok(responseList);
}
}

View File

@ -0,0 +1,69 @@
package cn.axzo.nanopart.visa.server.controller;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.nanopart.visa.api.changerecord.ChangeRecordRelationApi;
import cn.axzo.nanopart.visa.api.request.ChangeRecordAppendAttachReq;
import cn.axzo.nanopart.visa.api.request.ImGroupOperationReq;
import cn.axzo.nanopart.visa.api.request.ImGroupTipsQueryReq;
import cn.axzo.nanopart.visa.api.request.VisaRelationReq;
import cn.axzo.nanopart.visa.api.response.ImGroupTipsResp;
import cn.axzo.nanopart.visa.api.response.VisaRelationResp;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordRelation;
import cn.axzo.nanopart.visa.server.dto.VisaRelationDto;
import cn.axzo.nanopart.visa.server.service.ChangeRecordRelationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录内容关系表ø
*/
@Slf4j
@RestController
@RequiredArgsConstructor
public class ChangeRecordRelationController implements ChangeRecordRelationApi {
private final ChangeRecordRelationService changeRecordRelationService;
@Override
public ApiResult<List<VisaRelationResp>> listByVisaId(VisaRelationReq req) {
return ApiResult.ok(changeRecordRelationService.findByCondition(VisaRelationDto.builder()
.visaId(req.getVisaId())
.varName(Objects.nonNull(req.getFieldEnum()) ? req.getFieldEnum().name() : null)
.build())
.stream().sorted(Comparator.comparing(ChangeRecordRelation::getCreateAt))
.map(i -> VisaRelationResp.builder()
.id(i.getId())
.visaId(String.valueOf(i.getVisaId()))
.varName(i.getVarName())
.varExt(i.getVarExt())
.varType(i.getVarType())
.content(i.getContent())
.contentExt(i.getContentExt())
.createAt(i.getCreateAt())
.build()).collect(Collectors.toList()));
}
@Override
public ApiResult<Boolean> saveImOperationParticipate(ImGroupOperationReq req) {
return ApiResult.ok(changeRecordRelationService.saveImOperationParticipate(req));
}
@Override
public ApiResult<ImGroupTipsResp> queryImGroupTips(ImGroupTipsQueryReq req) {
return ApiResult.ok(changeRecordRelationService.queryImGroupTips(req));
}
@Override
public ApiResult<Void> appendAttachment(ChangeRecordAppendAttachReq req) {
changeRecordRelationService.appendAttachment(req);
return ApiResult.ok();
}
}

View File

@ -0,0 +1,158 @@
package cn.axzo.nanopart.visa.server.domain;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName(value = "visa_change_record", autoResultMap = true)
public class ChangeRecord extends BaseEntity<ChangeRecord> {
/**
* 单据号
*/
@TableField(value = "no")
private String no;
/**
* 主题
*/
@TableField(value = "topic")
private String topic;
/**
* 项目
*/
@TableField(value = "relation_workspaceId")
private Long relationWorkspaceId;
/**
* 工程
*/
@TableField(value = "relation_project")
private Long relationProject;
/**
* 区域集合
* 示例
* <pre>
* [
* {"areaId": 249556},
* {"areaId": 249555}
* ]
* </pre>
*/
@TableField(value = "relation_area", typeHandler = FastjsonTypeHandler.class)
private JSONArray relationArea;
/**
* 专业集合
* 示例
* <pre>
* [
* {"code":"code1"},
* {"code":"code2"},
* ]
* </pre>
*/
@TableField(value = "relation_professional", typeHandler = FastjsonTypeHandler.class)
private JSONArray relationProfessional;
/**
* 提出时间
*/
@TableField(value = "happen_time")
private Date happenTime;
/**
* 有符号的变更金额
*/
@TableField(value = "amount_change")
private BigDecimal amountChange;
/**
* 发生原因
*/
@TableField(value = "reason")
private String reason;
/**
* 单据类型
*/
@TableField(value = "type")
private VisaTypeEnum type;
/**
* 状态
*/
@TableField(value = "status")
private VisaStatusEnum status;
/**
* 最终审批ID
*/
@TableField(value = "approval_id")
private String approvalId;
/**
* 最终审批状态
*/
@TableField(value = "approval_status")
private String approvalStatus;
/**
* 最终审批时间
*/
@TableField(value = "approval_complete_time", updateStrategy = FieldStrategy.IGNORED)
private Date approvalCompleteTime;
/**
* IM群组ID
*/
@TableField(value = "im_group_id")
private Long imGroupId;
/**
* 额外信息
*/
@TableField(value = "extra", typeHandler = FastjsonTypeHandler.class)
private JSONObject extra;
/**
* 创建人id
*/
@TableField(value = "create_by")
private Long createBy;
/**
* 修改人id
*/
@TableField(value = "update_by")
private Long updateBy;
}

View File

@ -0,0 +1,87 @@
package cn.axzo.nanopart.visa.server.domain;
import cn.axzo.nanopart.visa.api.enums.VisaBillTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author xudawei
* @date 2025/01/20
* @desc 变更签证记录单据关系表
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName(value = "visa_change_record_bill", autoResultMap = true)
public class ChangeRecordBill extends BaseEntity<ChangeRecordBill> {
/**
* 变更签证记录id
*/
@TableField(value = "visa_id")
private Long visaId;
/**
* 变更签证单据类型
*/
@TableField(value = "visa_type")
private VisaTypeEnum visaType;
/**
* 单据id
*/
@TableField(value = "bill_id")
private Long billId;
/**
* 单据编号
*/
@TableField(value = "bill_no")
private String billNo;
/**
* 单据类型
*/
@TableField(value = "bill_type")
private VisaBillTypeEnum billType;
/**
* 单据被关联状态
* true 1 被关联
* false 0 未关联
*/
@TableField(value = "relation_status")
private Boolean relationStatus;
/**
* 额外信息
*/
@TableField(value = "extra", typeHandler = FastjsonTypeHandler.class)
private JSONObject extra;
/**
* 创建人id
*/
@TableField(value = "create_by")
private Long createBy;
/**
* 修改人id
*/
@TableField(value = "update_by")
private Long updateBy;
}

View File

@ -0,0 +1,105 @@
package cn.axzo.nanopart.visa.server.domain;
import cn.axzo.maokai.common.enums.SaasCooperateShipCooperateTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.nanopart.visa.api.enums.VisaConfirmBizTypeEnum;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录确认
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName(value = "visa_change_record_confirm", autoResultMap = true)
public class ChangeRecordConfirm extends BaseEntity<ChangeRecordConfirm> {
/**
* 变更签id
*/
@TableField(value = "visa_id")
private Long visaId;
/**
* 类型
*/
@TableField(value = "type")
private SaasCooperateShipCooperateTypeEnum type;
/**
* 业务类型,CONFIRM:确认;CREATE:创建
*/
@TableField(value = "biz_type")
private VisaConfirmBizTypeEnum bizType;
/**
* 业务类型,CONFIRM:确认;CREATE:创建
*/
@TableField(value = "visa_type")
private VisaTypeEnum visaType;
/**
* 确认人
*/
@TableField(value = "person_id")
private Long personId;
/**
* 确认单位
*/
@TableField(value = "ou_id")
private Long ouId;
/**
* 确认项目
*/
@TableField(value = "workspace_id")
private Long workspaceId;
/**
* 确认工程
*/
@TableField(value = "project_id")
private Long projectId;
/**
* 确认节点
*/
@TableField(value = "node_id")
private Long nodeId;
/**
* 额外信息
*/
@TableField(value = "extra",typeHandler = FastjsonTypeHandler.class)
private JSONObject extra;
/**
* 创建人id
*/
@TableField(value = "create_by")
private Long createBy;
/**
* 修改人id
*/
@TableField(value = "update_by")
private Long updateBy;
}

View File

@ -0,0 +1,66 @@
package cn.axzo.nanopart.visa.server.domain;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录操作日志
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName(value = "visa_change_record_log", autoResultMap = true)
public class ChangeRecordLog extends BaseEntity<ChangeRecordLog> {
/**
* 变更签证记录id
*/
@TableField(value = "visa_id")
private Long visaId;
/**
* 操作动作
*/
@TableField(value = "action")
private String action;
/**
* 操作标题
*/
@TableField(value = "title")
private String title;
/**
* 操作内容
*/
@TableField(value = "content")
private String content;
/**
* 排序
*/
@TableField(value = "order_by")
private Integer orderBy;
/**
* 创建人id
*/
@TableField(value = "create_by")
private Long createBy;
}

View File

@ -0,0 +1,74 @@
package cn.axzo.nanopart.visa.server.domain;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录内容关系表
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "visa_change_record_relation", autoResultMap = true)
public class ChangeRecordRelation extends BaseEntity<ChangeRecordRelation> {
/**
* 变更签证记录id
*/
@TableField(value = "visa_id")
private Long visaId;
/**
* 关联的内容名称发生内容及说明相关单位及人员单据附件审批记录
*/
@TableField(value = "var_name")
private String varName;
/**
* 扩展内容名称
*/
@TableField(value = "var_ext")
private String varExt;
/**
* 值类型
*/
@TableField(value = "var_type")
private String varType;
/**
* 内容值
*/
@TableField(value = "content")
private String content;
/**
* 内容描述
*/
@TableField(value = "content_ext")
private String contentExt;
/**
* 创建人id
*/
@TableField(value = "create_by")
private Long createBy;
/**
* 修改人id
*/
@TableField(value = "update_by")
private Long updateBy;
}

View File

@ -0,0 +1,55 @@
package cn.axzo.nanopart.visa.server.dto;
import cn.axzo.nanopart.visa.api.enums.VisaRelationFieldEnum;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.server.domain.ChangeRecord;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordRelation;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import java.util.List;
import java.util.stream.Collectors;
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class VisaAddLogContext {
/**
* 人员Id
*/
private Long personId;
/**
* 项目Id
*/
private Long workspaceId;
/**
* 单位id
*/
private Long ouId;
private VisaStatusEnum status;
private ChangeRecord changeRecord;
private List<ChangeRecordRelation> relationList;
/**
* 获取附件集合
*/
public List<JSONObject> getAttachList() {
if (CollectionUtils.isEmpty(relationList)) {
return Lists.newArrayList();
}
return relationList.stream()
.filter(item -> VisaRelationFieldEnum.isAttach(item.getVarName()))
.map(item -> JSONObject.parseObject(item.getContent())).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,70 @@
package cn.axzo.nanopart.visa.server.dto;
import cn.axzo.nanopart.visa.api.enums.VisaBillTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author xudawei
* @date 2025/01/17
* @desc 变更签证记录确认
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class VisaBillDto {
/**
* 变更签证记录id
*/
private Long visaId;
/**
* 变更签证单据类型
*/
private VisaTypeEnum visaType;
/**
* 单据id
*/
private Long billId;
/**
* 单据编号
*/
private String billNo;
/**
* 单据类型
*/
private VisaBillTypeEnum billType;
/**
* 额外信息
*/
private JSONObject extra;
/**
* 创建人id
*/
private Long createBy;
/**
* 修改人id
*/
private Long updateBy;
/**
* 单据被关联状态
* true 1 被关联
* false 0 未关联
*/
private Boolean relationStatus;
}

View File

@ -0,0 +1,156 @@
package cn.axzo.nanopart.visa.server.dto;
import cn.axzo.karma.client.feign.tyr.response.MergeMatchDataResp;
import cn.axzo.maokai.common.enums.SaasCooperateShipCooperateTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaConfirmBizTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.apache.commons.collections.CollectionUtils;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author xudawei
* @date 2025/01/17
* @desc 变更签证记录确认
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class VisaConfirmDto {
/**
* 变更签id
*/
private Long visaId;
private Collection<Long> visaIds;
/**
* 类型
*/
private SaasCooperateShipCooperateTypeEnum type;
/**
* 业务类型,CONFIRM:确认;CREATE:创建
*/
private VisaConfirmBizTypeEnum bizType;
/**
* 确认人
*/
private Long personId;
/**
* 确认人集合
*/
private Collection<Long> personIds;
/**
* 确认单位
*/
private Long ouId;
/**
* 确认单位集合
*/
private Collection<Long> ouIds;
/**
* 确认项目
*/
private Long workspaceId;
/**
* 确认项目集合
*/
private Collection<Long> workspaceIds;
/**
* 确认工程
*/
private Long projectId;
/**
* 确认工程集合
*/
private Collection<Long> projectIds;
/**
* 确认节点
*/
private Long nodeId;
/**
* 确认节点集合
*/
private Collection<Long> nodeIds;
private Long operator;
/**
* 变更签证类型集合
*/
private Set<VisaTypeEnum> visaTypes;
/**
* 变更签证类型
*/
private VisaTypeEnum visaType;
/**
* 根据DataItem创建Dto
*/
public static VisaConfirmDto create(List<MergeMatchDataResp.DataItem> dataItems, Set<VisaTypeEnum> visaTypes) {
VisaConfirmDto dto = new VisaConfirmDto();
if (CollectionUtils.isNotEmpty(dataItems)) {
Collection<Long> personIds = dataItems.stream()
.filter(item -> CollectionUtils.isNotEmpty(item.getPersonIds()))
.flatMap(item -> item.getPersonIds().stream()).collect(Collectors.toSet());
if (CollectionUtils.isNotEmpty(personIds)) {
dto.setPersonIds(personIds);
}
Collection<Long> ouIds = dataItems.stream()
.filter(item -> Objects.nonNull(item.getOuId()))
.map(item -> item.getOuId()).collect(Collectors.toSet());
if (CollectionUtils.isNotEmpty(ouIds)) {
dto.setOuIds(ouIds);
}
Collection<Long> workspaceIds = dataItems.stream()
.filter(item -> Objects.nonNull(item.getWorkspaceId()))
.map(item -> item.getWorkspaceId()).collect(Collectors.toSet());
if (CollectionUtils.isNotEmpty(workspaceIds)) {
dto.setWorkspaceIds(workspaceIds);
}
Set<Long> nodeIds = dataItems.stream()
.filter(item -> Objects.nonNull(item.getNodeId()))
.map(item -> item.getNodeId()).collect(Collectors.toSet());
if (CollectionUtils.isNotEmpty(nodeIds)) {
dto.setNodeIds(nodeIds);
}
Collection<Long> projectIds = dataItems.stream()
.filter(item -> CollectionUtils.isNotEmpty(item.getProjectIds()))
.flatMap(item -> item.getProjectIds().stream()).collect(Collectors.toSet());
if (CollectionUtils.isNotEmpty(projectIds)) {
dto.setProjectIds(projectIds);
}
}
dto.setVisaTypes(visaTypes);
return dto;
}
}

View File

@ -0,0 +1,77 @@
package cn.axzo.nanopart.visa.server.dto;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/1/23 10:19
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisaExportDto {
/**
* 单据号
*/
@ExcelProperty("单号")
private String no;
/**
* 单据类型
*/
@ExcelProperty("单据类型")
private String type;
/**
* 状态
*/
@ExcelProperty("单据状态")
private String status;
/**
* 主题
*/
@ExcelProperty("主题")
private String topic;
/**
* 有符号的变更金额
*/
@ExcelProperty("金额变化")
private BigDecimal amountChange;
/**
* 发起人
*/
@ExcelProperty("发起人")
private String initiator;
/**
* 提出时间
*/
@ExcelProperty("提出时间")
private Date happenTime;
/**
* 最终审批时间
*/
@ExcelProperty("审批通过时间")
private Date approvalCompleteTime;
/**
* 工程
*/
@ExcelProperty("所属工程")
private String relationProject;
}

View File

@ -0,0 +1,31 @@
package cn.axzo.nanopart.visa.server.dto;
import cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author xudawei
* @date 2025/01/21
* @desc 变更签证记录日志确认
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class VisaLogDto {
/**
* 变更签证Id
*/
private Long visaId;
/**
* 类型
*/
private VisaLogTypeEnum logType;
}

View File

@ -0,0 +1,163 @@
package cn.axzo.nanopart.visa.server.dto;
import cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.response.VisaDetailByIdResponse;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author xudawei
* @date 2025/01/21
* @desc 变更签证记录日志确认
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class VisaLogParam {
/**
* 人员Id
*/
private Long personId;
/**
* 单位Id
*/
private Long ouId;
/**
* 项目Id
*/
private Long workspaceId;
/**
* 原变更金额
*/
private BigDecimal oldAmountChange;
/**
* 新变更金额
*/
private BigDecimal newAmountChange;
/**
* 上传文件
*/
private List<String> uploadAttach;
/**
* 删除文件
*/
private List<String> deleteAttach;
/**
* 日志类型
*/
private VisaLogTypeEnum logType;
/**
* 原因:审批流的驳回原因/转交原因
*/
private String reason;
/**
* 审批流转交给的用户
*/
private String transmitTo;
/**
* 新状态
*/
private VisaStatusEnum newStatus;
/**
* 原状态
*/
private VisaStatusEnum oldStatus;
/**
* 获取删除附件信息
*/
public static List<String> deleteAttach(List<JSONObject> oldAttach, List<JSONObject> newAttach) {
return fetchChangeAttach(oldAttach, newAttach);
}
/**
* 获取删除附件信息
*/
public static List<String> deleteAttachWithObject(List<VisaDetailByIdResponse.VisaUploadFile> oldAttach, List<VisaDetailByIdResponse.VisaUploadFile> newAttach) {
return fetchChangeAttachWithObject(oldAttach, newAttach);
}
/**
* 获取上传的附件信息
*/
public static List<String> uploadAttach(List<JSONObject> newAttach, List<JSONObject> oldAttach) {
return fetchChangeAttach(newAttach, oldAttach);
}
/**
* 获取上传的附件信息
*/
public static List<String> uploadAttachWithObject(List<VisaDetailByIdResponse.VisaUploadFile> newAttach, List<VisaDetailByIdResponse.VisaUploadFile> oldAttach) {
return fetchChangeAttachWithObject(newAttach, oldAttach);
}
/**
* 获取变动的附件信息
* 计算集合的单差集即只返回集合1中有但是集合2中没有的元素例如
* subtractToList([1,2,3,4],[2,3,4,5]) - [1]
*/
private static List<String> fetchChangeAttach(List<JSONObject> compareFir, List<JSONObject> compareSec) {
if (CollectionUtils.isEmpty(compareFir)) {
return Lists.newArrayList();
}
List<VisaDetailByIdResponse.VisaUploadFile> oldFileDtoList = VisaDetailByIdResponse.VisaUploadFile.createListByJson(compareFir);
if (CollectionUtils.isEmpty(compareSec)) {
return oldFileDtoList.stream().map(VisaDetailByIdResponse.VisaUploadFile::getFileName).collect(Collectors.toList());
}
List<VisaDetailByIdResponse.VisaUploadFile> newFileDtoList = VisaDetailByIdResponse.VisaUploadFile.createListByJson(compareSec);
return fetchChangeAttachWithObject(oldFileDtoList, newFileDtoList);
}
/**
* 获取变动的附件信息
* 计算集合的单差集即只返回集合1中有但是集合2中没有的元素例如
* subtractToList([1,2,3,4],[2,3,4,5]) - [1]
*/
private static List<String> fetchChangeAttachWithObject(List<VisaDetailByIdResponse.VisaUploadFile> compareFir, List<VisaDetailByIdResponse.VisaUploadFile> compareSec) {
if (CollectionUtils.isEmpty(compareFir)) {
return Lists.newArrayList();
}
if (CollectionUtils.isEmpty(compareSec)) {
return compareFir.stream().map(VisaDetailByIdResponse.VisaUploadFile::getFileName).collect(Collectors.toList());
}
Collection<VisaDetailByIdResponse.VisaUploadFile> substractList = CollUtil.subtractToList(compareFir, compareSec);
if (CollectionUtils.isEmpty(substractList)) {
return Lists.newArrayList();
}
return substractList.stream().map(VisaDetailByIdResponse.VisaUploadFile::getFileName).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,46 @@
package cn.axzo.nanopart.visa.server.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author xudawei
* @date 2025/01/21
* @desc 变更签证记录内容关系表
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class VisaRelationDto {
/**
* 变更签证记录id
*/
private Long visaId;
/**
* 类型
*/
private String varName;
/**
* 内容
*/
private String content;
/**
* 内容扩展
*/
private String contentExt;
/**
* 创建人
*/
private Long createBy;
}

View File

@ -0,0 +1,15 @@
package cn.axzo.nanopart.visa.server.mapper;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordBill;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录单据关系表
*/
@Mapper
public interface ChangeRecordBillDao extends BaseMapper<ChangeRecordBill> {
}

View File

@ -0,0 +1,15 @@
package cn.axzo.nanopart.visa.server.mapper;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordConfirm;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录确认
*/
@Mapper
public interface ChangeRecordConfirmDao extends BaseMapper<ChangeRecordConfirm> {
}

View File

@ -0,0 +1,15 @@
package cn.axzo.nanopart.visa.server.mapper;
import cn.axzo.nanopart.visa.server.domain.ChangeRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录
*/
@Mapper
public interface ChangeRecordDao extends BaseMapper<ChangeRecord> {
}

View File

@ -0,0 +1,15 @@
package cn.axzo.nanopart.visa.server.mapper;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录操作日志
*/
@Mapper
public interface ChangeRecordLogDao extends BaseMapper<ChangeRecordLog> {
}

View File

@ -0,0 +1,15 @@
package cn.axzo.nanopart.visa.server.mapper;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordRelation;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author xudawei
* @date 2025/01/15
* @desc 变更签证记录内容关系表
*/
@Mapper
public interface ChangeRecordRelationDao extends BaseMapper<ChangeRecordRelation> {
}

View File

@ -0,0 +1,108 @@
package cn.axzo.nanopart.visa.server.mq.listener.im;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import cn.axzo.im.center.api.vo.group.GroupInfo;
import cn.axzo.im.center.api.vo.group.GroupMemberInfo;
import cn.axzo.im.center.api.vo.mq.GroupMembersChangeMessage;
import cn.axzo.msg.center.api.MessageAPIV3;
import cn.axzo.msg.center.api.request.v3.MessageSendReqV3;
import cn.axzo.msg.center.service.dto.PersonV3DTO;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import cn.axzo.nanopart.visa.server.config.RefreshableConfiguration;
import cn.axzo.nanopart.visa.server.rpc.VisaProfileGateway;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.groovy.util.Maps;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import static cn.axzo.im.center.api.enums.MqEventType.GROUP_ADD_MEMBERS;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_VISA_ID;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_VISA_TYPE;
/**
* 监听 IM 添加群成员的广播事件
*
* @author wangli
* @since 2025-02-07 13:53
*/
@Slf4j
@Component
public class ImGroupAddMembersEventHandler implements EventHandler, InitializingBean {
@Autowired
private EventConsumer eventConsumer;
@Resource
private RefreshableConfiguration refreshableConfiguration;
@Resource
private MessageAPIV3 noticeApi;
@Resource
private VisaProfileGateway visaProfileGateway;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
if (Objects.isNull(event) || Objects.isNull(event.getEventCode())) {
log.warn("illegal event code: {}", JSON.toJSONString(event));
return;
}
log.info("receive add member event, push notice : {}", JSON.toJSONString(event));
GroupMembersChangeMessage groupMembersChangeMessage = event.normalizedData(GroupMembersChangeMessage.class);
GroupInfo group = groupMembersChangeMessage.getGroup();
AssertUtil.notNull(group, "im group is null");
GroupMemberInfo member = groupMembersChangeMessage.getMember();
AssertUtil.notNull(member, "im member is null");
Map<Long, PersonProfileDto> profileMap = visaProfileGateway.getProfileMap(Lists.newArrayList(group.getOwnerPersonId(), member.getPersonId()));
Long visaId = Long.valueOf(group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, 0).toString());
String visaType = (String) group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_VISA_TYPE, "");
Long workspaceId = Long.valueOf(group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID, 0).toString());
PersonProfileDto memberProfile = profileMap.getOrDefault(member.getPersonId(), null);
PersonProfileDto ownerProfile = profileMap.getOrDefault(group.getOwnerPersonId(), null);
if (Objects.nonNull(memberProfile) && Objects.nonNull(ownerProfile)) {
MessageSendReqV3 notice = new MessageSendReqV3();
notice.setSender(PersonV3DTO.builder().build());
notice.setReceivers(Lists.newArrayList(PersonV3DTO.builder()
.id(member.getPersonId())
.name(memberProfile.getRealName())
.imReceiveModel(new PersonV3DTO.ReceiveModel(member.getPersonOuId(), workspaceId))
.build()));
notice.setBizEventMappingCode(refreshableConfiguration.getImGroupAddMemberNoticeEventCode());
notice.setBizCode(String.valueOf(visaId));
notice.setBizExtParams(new JSONObject(Maps.of(
"visaId", visaId,
"initiatorName", ownerProfile.getRealName(),
"visaType", StringUtils.isNotBlank(visaType) ? VisaTypeEnum.valueOf(visaType).getDesc() : "",
"topic", group.getName())));
notice.setRouterParams(new JSONObject(Maps.of(
"visaId", visaId,
"ouId", member.getPersonOuId(),
"workspaceId", workspaceId
)));
noticeApi.send(notice);
}
log.info("receive add member event, push notice success!");
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(GROUP_ADD_MEMBERS.getEventCode(), this);
}
}

View File

@ -0,0 +1,41 @@
package cn.axzo.nanopart.visa.server.mq.listener.im;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Objects;
import static cn.axzo.im.center.api.enums.MqEventType.GROUP_DISMISSED;
/**
* 监听 IM 群解散的广播事件
*
* @author wangli
* @since 2025-02-07 13:53
*/
@Slf4j
@Component
public class ImGroupDismissedEventHandler implements EventHandler, InitializingBean {
@Autowired
private EventConsumer eventConsumer;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
if (Objects.isNull(event) || Objects.isNull(event.getEventCode())) {
log.warn("illegal event code: {}", JSON.toJSONString(event));
return;
}
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(GROUP_DISMISSED.getEventCode(), this);
}
}

View File

@ -0,0 +1,73 @@
package cn.axzo.nanopart.visa.server.mq.listener.im;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import cn.axzo.im.center.api.vo.group.GroupInfo;
import cn.axzo.im.center.api.vo.group.GroupMemberInfo;
import cn.axzo.im.center.api.vo.mq.GroupMembersChangeMessage;
import cn.axzo.nanopart.visa.api.request.ImGroupOperationClearReq;
import cn.axzo.nanopart.visa.server.service.ChangeRecordRelationService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Objects;
import static cn.axzo.im.center.api.enums.MqEventType.GROUP_REMOVE_MEMBERS;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_VISA_ID;
/**
* 监听 IM 群成员被移除的广播事件
*
* @author wangli
* @since 2025-02-07 13:53
*/
@Slf4j
@Component
public class ImGroupRemoveMembersEventHandler implements EventHandler, InitializingBean {
@Autowired
private EventConsumer eventConsumer;
@Resource
private ChangeRecordRelationService changeRecordRelationService;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
if (Objects.isNull(event) || Objects.isNull(event.getEventCode())) {
log.warn("illegal event code: {}", JSON.toJSONString(event));
return;
}
log.info("receive remove member event: {}", JSON.toJSONString(event));
GroupMembersChangeMessage groupMembersChangeMessage = event.normalizedData(GroupMembersChangeMessage.class);
GroupInfo group = groupMembersChangeMessage.getGroup();
AssertUtil.notNull(group, "im group is null");
GroupMemberInfo member = groupMembersChangeMessage.getMember();
AssertUtil.notNull(member, "im member is null");
// 移除该群成员的投票信息
removeMemberVote(group, member);
log.info("receive remove member event handle success!");
}
private void removeMemberVote(GroupInfo group, GroupMemberInfo member) {
Long visaId = Long.valueOf(group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, 0).toString());
changeRecordRelationService.clearImOperationParticipate(ImGroupOperationClearReq.builder()
.clearAll(false)
.imGroupId(group.getTid())
.visaId(visaId)
.operatorPersonId(member.getPersonId())
.operatorOuId(member.getPersonOuId())
.build());
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(GROUP_REMOVE_MEMBERS.getEventCode(), this);
}
}

View File

@ -0,0 +1,161 @@
package cn.axzo.nanopart.visa.server.mq.listener.im;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import cn.axzo.im.center.api.vo.PersonAccountAttribute;
import cn.axzo.im.center.api.vo.group.GroupInfo;
import cn.axzo.im.center.api.vo.group.GroupMemberInfo;
import cn.axzo.im.center.api.vo.mq.GroupChangedMessage;
import cn.axzo.im.center.api.vo.req.GroupGetOwnerRequest;
import cn.axzo.im.center.api.vo.req.SendChatMessageRequest;
import cn.axzo.im.center.api.vo.resp.GroupGetOwnerResponse;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.maokai.api.vo.response.OrganizationalUnitVO;
import cn.axzo.msg.center.service.dto.PeerPerson;
import cn.axzo.msg.center.service.pending.request.CardSendRequest;
import cn.axzo.nanopart.visa.api.enums.VisaConfirmBizTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import cn.axzo.nanopart.visa.server.config.RefreshableConfiguration;
import cn.axzo.nanopart.visa.server.domain.ChangeRecord;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordConfirm;
import cn.axzo.nanopart.visa.server.dto.VisaConfirmDto;
import cn.axzo.nanopart.visa.server.rpc.MsgCenterGateway;
import cn.axzo.nanopart.visa.server.rpc.OrganizationalUnitGateway;
import cn.axzo.nanopart.visa.server.rpc.VisaProfileGateway;
import cn.axzo.nanopart.visa.server.service.ChangeRecordConfirmService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordService;
import cn.axzo.nanopart.visa.server.service.VisaHelper;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.groovy.util.Maps;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static cn.axzo.im.center.api.enums.MqEventType.GROUP_CREATED;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_VISA_ID;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_VISA_TYPE;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.MSG_CENTER_APP_CODE;
/**
* 监听 IM 群创建的广播事件
*
* @author wangli
* @since 2025-02-07 13:53
*/
@Slf4j
@Component
public class ImGroupsCreatedEventHandler implements EventHandler, InitializingBean {
@Autowired
private EventConsumer eventConsumer;
@Resource
private MsgCenterGateway msgCenterGateway;
@Resource
private RefreshableConfiguration refreshableConfiguration;
@Resource
private OrganizationalUnitGateway organizationalUnitGateway;
@Resource
private ChangeRecordService changeRecordService;
@Resource
private ChangeRecordConfirmService changeRecordConfirmService;
@Resource
private VisaProfileGateway visaProfileGateway;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
if (Objects.isNull(event) || Objects.isNull(event.getEventCode())) {
log.warn("illegal event code: {}", JSON.toJSONString(event));
return;
}
log.info("receive create im group event: {}", JSON.toJSONString(event));
GroupChangedMessage groupChangedMessage = event.normalizedData(GroupChangedMessage.class);
GroupInfo group = groupChangedMessage.getGroup();
AssertUtil.notNull(group, "group info is null");
try {
// 转移到创建群聊立即发送卡片
// sendCardAndMsgToImGroup(group);
} catch (Exception e) {
log.error("send msg to im group error: {}", e.getMessage(), e);
throw e;
}
log.info("receive create im group event, handle success: {}", JSON.toJSONString(event));
}
private void sendCardAndMsgToImGroup(GroupInfo group) {
Map<String, Object> bizGroupInfo = group.getBizGroupInfo();
HashSet<String> imReceiveAccounts = Sets.newHashSet(String.valueOf(group.getTid()));
GroupGetOwnerRequest ownerRequest = new GroupGetOwnerRequest();
ownerRequest.setTid(group.getTid());
GroupGetOwnerResponse groupOwner = msgCenterGateway.getGroupOwner(ownerRequest);
AssertUtil.isTrue(Objects.nonNull(groupOwner) && Objects.nonNull(groupOwner.getOwner()), "im group owner is null");
GroupMemberInfo owner = groupOwner.getOwner();
Long visaId = Long.valueOf(bizGroupInfo.getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, 0).toString());
String visaType = (String) bizGroupInfo.getOrDefault(IM_GROUP_BIZ_INFO_VISA_TYPE, "");
Long ownerWorkspaceId = Long.valueOf(bizGroupInfo.getOrDefault(IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID, 0).toString());
ChangeRecord visa = changeRecordService.getById(visaId);
AssertUtil.notNull(visa, "visa record is null");
List<ChangeRecordConfirm> creators = changeRecordConfirmService.findByCondition(VisaConfirmDto.builder()
.visaId(visaId)
.bizType(VisaConfirmBizTypeEnum.CREATE)
.build());
AssertUtil.notEmpty(creators, "visa creator is null");
// 发送卡片
CardSendRequest cardRequest = new CardSendRequest();
cardRequest.setAppCode(MSG_CENTER_APP_CODE);
cardRequest.setTemplateCode(refreshableConfiguration.getImGroupCardTemplateCode());
cardRequest.setBizCode(IM_GROUP_BIZ_INFO_VISA_ID + ":" + visaId);
cardRequest.setSender(PeerPerson.create(owner.getPersonId(), owner.getPersonOuId(), ownerWorkspaceId));
cardRequest.setImSenderAccountAppType(AppTypeEnum.CMP);
cardRequest.setImReceiveAccounts(imReceiveAccounts);
ChangeRecordConfirm creator = creators.get(0);
OrganizationalUnitVO unitInfo = organizationalUnitGateway.getUnitInfo(creator.getOuId());
PersonProfileDto profile = visaProfileGateway.getProfile(creator.getPersonId());
cardRequest.setBizParam(new JSONObject(Maps.of(
"topic", group.getName(),
"reason", visa.getReason(),
"initiatorName", profile.getRealName(),
"initiatorUnitName", unitInfo.getName(),
"visaType", StringUtils.isNotBlank(visaType) ? VisaTypeEnum.valueOf(visaType).getDesc() : "",
"amountChange", VisaHelper.buildChangeAmount(visa.getAmountChange())
)));
msgCenterGateway.sendCardToCroup(cardRequest);
// 普通群消息
SendChatMessageRequest msgRequest = new SendChatMessageRequest();
msgRequest.setAsTextMessage(group.getName() + ",请各位审阅");
msgRequest.setImReceiveAccounts(imReceiveAccounts);
msgRequest.setSender(PersonAccountAttribute.builder()
.personId(String.valueOf(owner.getPersonId()))
.ouId(owner.getPersonOuId())
.workspaceId(ownerWorkspaceId)
.appType(AppTypeEnum.CMP)
.build());
msgRequest.setBizId(IM_GROUP_BIZ_INFO_VISA_ID + ":" + visaId);
msgCenterGateway.sendMsgToGroup(msgRequest);
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(GROUP_CREATED.getEventCode(), this);
}
}

View File

@ -0,0 +1,35 @@
package cn.axzo.nanopart.visa.server.mq.listener.visa;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import cn.axzo.nanopart.visa.api.enums.MQEventEnum;
import cn.axzo.nanopart.visa.server.mq.producer.VisaChangeLogPayload;
import cn.axzo.nanopart.visa.server.service.ChangeRecordLogService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
/**
* 添加处理变洽签日志的逻辑
*
* @author wangli
* @since 2025-02-08 11:18
*/
@Component
@AllArgsConstructor
public class ChangeRecordLogEventHandle implements EventHandler, InitializingBean {
private final EventConsumer eventConsumer;
private final ChangeRecordLogService changeRecordLogService;
@Override
public void onEvent(Event event, EventConsumer.Context context) {
VisaChangeLogPayload log = event.normalizedData(VisaChangeLogPayload.class);
changeRecordLogService.addLog(log.createRecordLogByPayload());
}
@Override
public void afterPropertiesSet() {
eventConsumer.registerHandler(MQEventEnum.VISA_CHANGE_LOG.getEventCode(), this);
}
}

View File

@ -0,0 +1,53 @@
package cn.axzo.nanopart.visa.server.mq.listener.workflow;
import cn.axzo.framework.rocketmq.EventProducer;
import cn.axzo.maokai.api.vo.request.OrgNodeUserBriefInfoListReq;
import cn.axzo.maokai.api.vo.response.OrgNodeUserBriefInfoResp;
import cn.axzo.nanopart.visa.server.rpc.VisaOrganizationalNodeUserGateway;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import com.google.common.collect.Lists;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Objects;
/**
* @author wangli
* @since 2025-01-20 10:18
*/
public abstract class BasicLogSupport {
protected final EventProducer eventProducer;
protected final VisaOrganizationalNodeUserGateway visaOrganizationalNodeUserGateway;
protected BasicLogSupport(EventProducer eventProducer, VisaOrganizationalNodeUserGateway visaOrganizationalNodeUserGateway) {
this.eventProducer = eventProducer;
this.visaOrganizationalNodeUserGateway = visaOrganizationalNodeUserGateway;
}
protected String buildLogUserInfo(BpmnTaskDelegateAssigner assigner) {
OrgNodeUserBriefInfoResp oneUserInfo = getOneUserInfo(assigner);
return buildLogUserInfo(oneUserInfo);
}
protected String buildLogUserInfo(OrgNodeUserBriefInfoResp user) {
String userInfo = "";
if (Objects.nonNull(user)) {
userInfo = user.getRealName() + "" + user.getJob().getName() + "-" + user.getOrganizationalUnitName() + "";
}
return userInfo;
}
protected OrgNodeUserBriefInfoResp getOneUserInfo(BpmnTaskDelegateAssigner assigner) {
if (Objects.isNull(assigner)) {
return null;
}
List<OrgNodeUserBriefInfoResp> users = visaOrganizationalNodeUserGateway.listOrgNodeUsers(OrgNodeUserBriefInfoListReq.builder()
.workspaceId(Long.valueOf(assigner.getTenantId()))
.ouId(Long.valueOf(assigner.getOuId()))
.personIds(Lists.newArrayList(Long.valueOf(assigner.getPersonId())))
.needUnit(true)
.needJob(true)
.build());
return CollectionUtils.isEmpty(users) ? null : users.get(0);
}
}

View File

@ -0,0 +1,200 @@
package cn.axzo.nanopart.visa.server.mq.listener.workflow.process;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventProducer;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import cn.axzo.nanopart.visa.api.request.ChangeStatusRequest;
import cn.axzo.nanopart.visa.server.domain.ChangeRecord;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordLog;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordRelation;
import cn.axzo.nanopart.visa.server.mq.listener.workflow.BasicLogSupport;
import cn.axzo.nanopart.visa.server.mq.producer.VisaChangeLogPayload;
import cn.axzo.nanopart.visa.server.rpc.VisaOrganizationalNodeUserGateway;
import cn.axzo.nanopart.visa.server.service.ChangeRecordBillService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordRelationService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordService;
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.common.model.response.mq.ProcessInstanceDTO;
import cn.axzo.workflow.starter.handler.ProcessInstanceEventHandler;
import com.google.common.collect.Lists;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.WORKFLOW_VAR_VISA_TYPE_KEY;
import static cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum.REJECT_APPROVE;
import static cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum.REVERT_APPROVE;
import static cn.axzo.nanopart.visa.api.enums.VisaRelationFieldEnum.PROCESS_INSTANCE_OF_VISA;
import static cn.axzo.nanopart.visa.api.enums.VisaTypeEnum.DESIGN_CHANGE;
import static cn.axzo.nanopart.visa.api.enums.VisaTypeEnum.PROJECT_VISA;
import static cn.axzo.nanopart.visa.api.enums.VisaTypeEnum.TECHNOLOGY_APPROVED;
/**
* 工作流广播的实例维度的所有事件类型
*
* @author wangli
* @since 2025-01-17 11:35
*/
@Component
public class ProcessInstanceAllEventHandler extends BasicLogSupport implements ProcessInstanceEventHandler {
protected final ChangeRecordService changeRecordService;
protected final ChangeRecordRelationService changeRecordRelationService;
protected final ChangeRecordBillService changeRecordBillService;
public static List<String> SUPPORTED_DEFINITION_KEYS = Lists.newArrayList(
DESIGN_CHANGE.getProcessDefinitionKey(),
TECHNOLOGY_APPROVED.getProcessDefinitionKey(),
PROJECT_VISA.getProcessDefinitionKey()
);
public ProcessInstanceAllEventHandler(EventProducer eventProducer,
VisaOrganizationalNodeUserGateway visaOrganizationalNodeUserGateway,
ChangeRecordService changeRecordService,
ChangeRecordRelationService changeRecordRelationService,
ChangeRecordBillService changeRecordBillService) {
super(eventProducer, visaOrganizationalNodeUserGateway);
this.changeRecordService = changeRecordService;
this.changeRecordRelationService = changeRecordRelationService;
this.changeRecordBillService = changeRecordBillService;
}
@Override
public int getOrder() {
return Integer.MIN_VALUE;
}
@Override
public boolean accept(ProcessInstanceDTO dto, Event event, EventConsumer.Context context) {
return SUPPORTED_DEFINITION_KEYS.contains(dto.getProcessDefinitionKey());
}
@Override
public void onCreated(ProcessInstanceDTO dto) {
ProcessInstanceEventHandler.super.onCreated(dto);
}
private String parseVisaType(ProcessInstanceDTO dto) {
String visaType = (String) dto.getVariables().getOrDefault(WORKFLOW_VAR_VISA_TYPE_KEY, "");
return StringUtils.hasText(visaType) ? VisaTypeEnum.valueOf(visaType).getDesc() : "";
}
@Override
public void onCompleted(ProcessInstanceDTO dto) {
String visaTypeDesc = parseVisaType(dto);
updateChangeRecordApprovalStatus(dto, BpmnProcessInstanceResultEnum.APPROVED);
}
/**
* 流程撤回
*
* @param dto
*/
@Override
public void onCancelled(ProcessInstanceDTO dto) {
BpmnTaskDelegateAssigner initiator = dto.getInitiator();
String visaTypeDesc = parseVisaType(dto);
ChangeRecordLog log = ChangeRecordLog.builder()
.visaId(Long.valueOf(dto.getBusinessKey()))
.action(dto.getType().getTag())
.title(String.format(REVERT_APPROVE.getTitle(), visaTypeDesc))
.content(String.format(REVERT_APPROVE.getContent(), buildLogUserInfo(initiator)))
.build();
eventProducer.send(VisaChangeLogPayload.form(log));
updateChangeRecordApprovalStatus(dto, BpmnProcessInstanceResultEnum.CANCELLED);
}
/**
* 流程驳回
*
* @param dto
*/
@Override
public void onRejected(ProcessInstanceDTO dto) {
BpmnTaskDelegateAssigner lastOperationAssigner = dto.getLastOperationAssigner();
ChangeRecordLog log = ChangeRecordLog.builder()
.visaId(Long.valueOf(dto.getBusinessKey()))
.action(dto.getType().getTag())
.title(String.format(REJECT_APPROVE.getTitle(), lastOperationAssigner.getAssignerName()))
.content(String.format(REJECT_APPROVE.getContent(), buildLogUserInfo(lastOperationAssigner), dto.getReason()))
.build();
eventProducer.send(VisaChangeLogPayload.form(log));
updateChangeRecordApprovalStatus(dto, BpmnProcessInstanceResultEnum.REJECTED);
}
@Override
public void onAborted(ProcessInstanceDTO dto) {
ProcessInstanceEventHandler.super.onAborted(dto);
updateChangeRecordApprovalStatus(dto, BpmnProcessInstanceResultEnum.ABORTED);
}
private void updateChangeRecordApprovalStatus(ProcessInstanceDTO dto, BpmnProcessInstanceResultEnum resultEnum) {
// 更新主表审批状态信息
Long visaId = Long.valueOf(dto.getBusinessKey());
changeRecordService.lambdaQuery()
.eq(ChangeRecord::getId, visaId)
.eq(ChangeRecord::getApprovalId, dto.getProcessInstanceId())
.eq(ChangeRecord::getIsDelete, 0)
.oneOpt()
.ifPresent(changeRecord -> {
if (Objects.equals(resultEnum, BpmnProcessInstanceResultEnum.APPROVED)) {
changeRecord.setApprovalStatus(resultEnum.getStatus());
changeRecord.setApprovalCompleteTime(new Date());
} else {
changeRecord.setApprovalId("");
changeRecord.setApprovalStatus("");
changeRecord.setApprovalCompleteTime(null);
}
changeRecordService.updateById(changeRecord);
});
// 更新关联表审批信息
changeRecordRelationService.lambdaQuery()
.eq(ChangeRecordRelation::getVisaId, visaId)
.eq(ChangeRecordRelation::getVarName, PROCESS_INSTANCE_OF_VISA.name())
.eq(ChangeRecordRelation::getContent, dto.getProcessInstanceId())
.oneOpt()
.ifPresent(changeRecordRelation -> {
changeRecordRelation.setContentExt(resultEnum.getStatus());
changeRecordRelationService.updateById(changeRecordRelation);
});
ChangeRecord visa = changeRecordService.getById(visaId);
BpmnTaskDelegateAssigner lastOperationAssigner = dto.getLastOperationAssigner();
if (Objects.equals(resultEnum, BpmnProcessInstanceResultEnum.APPROVED)) {
changeRecordService.changeStatus(ChangeStatusRequest.builder()
.visaId(visaId)
.personId(Long.valueOf(lastOperationAssigner.getPersonId()))
.ouId(Long.valueOf(lastOperationAssigner.getOuId()))
.workspaceId(Long.valueOf(lastOperationAssigner.getTenantId()))
.updateStatus(VisaStatusEnum.COMPLETED)
.editFormFlag(false)
.build());
return;
}
// 回退到待提报或决策中
changeRecordService.changeStatus(ChangeStatusRequest.builder()
.visaId(visaId)
.personId(Long.valueOf(lastOperationAssigner.getPersonId()))
.ouId(Long.valueOf(lastOperationAssigner.getOuId()))
.workspaceId(Long.valueOf(lastOperationAssigner.getTenantId()))
.updateStatus(Objects.isNull(visa.getImGroupId()) ? VisaStatusEnum.REPORT_FROM_APPROVE : VisaStatusEnum.DECIDING_FROM_APPROVE)
.editFormFlag(false)
.build());
// 取消当前主单据关联的其他单据的关联状态
changeRecordBillService.billRelationStatus(visaId, false);
// 取消图纸绑定关系
changeRecordService.syncDrawAnnotationUnBindRelation(visaId);
}
}

View File

@ -0,0 +1,94 @@
package cn.axzo.nanopart.visa.server.mq.listener.workflow.task;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventProducer;
import cn.axzo.maokai.api.vo.response.OrgNodeUserBriefInfoResp;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordLog;
import cn.axzo.nanopart.visa.server.mq.listener.workflow.BasicLogSupport;
import cn.axzo.nanopart.visa.server.mq.producer.VisaChangeLogPayload;
import cn.axzo.nanopart.visa.server.rpc.VisaOrganizationalNodeUserGateway;
import cn.axzo.workflow.common.model.response.mq.ProcessTaskDTO;
import cn.axzo.workflow.starter.handler.ProcessTaskEventHandler;
import org.springframework.stereotype.Component;
import java.util.Objects;
import static cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum.APPROVED_AGRESS;
import static cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum.TRANSMIT_APPROVE;
import static cn.axzo.nanopart.visa.server.mq.listener.workflow.process.ProcessInstanceAllEventHandler.SUPPORTED_DEFINITION_KEYS;
/**
* 工作流广播的任务维度的所有事件类型
*
* @author wangli
* @since 2025-01-17 11:34
*/
@Component
public class ProcessTaskAllEventHandler extends BasicLogSupport implements ProcessTaskEventHandler {
public ProcessTaskAllEventHandler(EventProducer eventProducer, VisaOrganizationalNodeUserGateway visaOrganizationalNodeUserGateway) {
super(eventProducer, visaOrganizationalNodeUserGateway);
}
@Override
public int getOrder() {
return Integer.MAX_VALUE;
}
@Override
public boolean accept(ProcessTaskDTO dto, Event event, EventConsumer.Context context) {
return SUPPORTED_DEFINITION_KEYS.contains(dto.getProcessDefinitionKey());
}
@Override
public void onAssigned(ProcessTaskDTO dto) {
ProcessTaskEventHandler.super.onAssigned(dto);
}
@Override
public void onCreated(ProcessTaskDTO dto) {
ProcessTaskEventHandler.super.onCreated(dto);
}
/**
* 任务通过
*
* @param dto
*/
@Override
public void onCompleted(ProcessTaskDTO dto) {
if (Objects.nonNull(dto.getApprover())
&& Objects.equals(dto.getInitiator().getPersonId(), dto.getApprover().getPersonId())) {
return;
}
OrgNodeUserBriefInfoResp user = getOneUserInfo(dto.getApprover());
ChangeRecordLog log = ChangeRecordLog.builder()
.visaId(Long.valueOf(dto.getBusinessKey()))
.action(dto.getType().getTag())
.title(String.format(APPROVED_AGRESS.getTitle(), Objects.isNull(user) ? "" : user.getRealName()))
.content(String.format(APPROVED_AGRESS.getContent(), Objects.isNull(user) ? "系统自动通过" : buildLogUserInfo(user)))
.build();
eventProducer.send(VisaChangeLogPayload.form(log));
}
@Override
public void onDeleted(ProcessTaskDTO dto) {
ProcessTaskEventHandler.super.onDeleted(dto);
}
@Override
public void onTransfer(ProcessTaskDTO dto) {
ChangeRecordLog log = ChangeRecordLog.builder()
.visaId(Long.valueOf(dto.getBusinessKey()))
.action(dto.getType().getTag())
.title(String.format(TRANSMIT_APPROVE.getTitle()))
.content(String.format(TRANSMIT_APPROVE.getContent(),
buildLogUserInfo(dto.getApprover()),
buildLogUserInfo(dto.getTransferTargetApprover()),
dto.getAdvice()))
.build();
eventProducer.send(VisaChangeLogPayload.form(log));
}
}

View File

@ -0,0 +1,63 @@
package cn.axzo.nanopart.visa.server.mq.producer;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.nanopart.visa.api.enums.MQEventEnum;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordLog;
import cn.axzo.nanopart.visa.server.utils.Constants;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
import java.util.Date;
/**
* 变洽签单据日志 MQ Payload
*
* @author wangli
* @since 2025-01-17 16:34
*/
@Slf4j
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class VisaChangeLogPayload implements Serializable {
private Long visaId;
private String action;
private String title;
private String content;
private Date operateTime;
private Long personId;
private Integer orderBy;
public static Event form(ChangeRecordLog log) {
VisaChangeLogPayload payload = VisaChangeLogPayload.builder()
.visaId(log.getVisaId())
.action(log.getAction())
.title(log.getTitle())
.content(log.getContent())
.personId(log.getCreateBy())
.orderBy(Constants.APPROVE_ORDER_BY)
.build();
return Event.builder()
.eventCode(MQEventEnum.VISA_CHANGE_LOG.getEventCode())
.shardingKey(String.valueOf(payload.getVisaId()))
.targetId(String.valueOf(payload.getVisaId()))
.targetType(log.getAction())
.data(payload)
.build();
}
public ChangeRecordLog createRecordLogByPayload() {
return ChangeRecordLog.builder()
.visaId(this.getVisaId())
.action(this.getAction())
.title(this.getTitle())
.content(this.getContent())
.orderBy(this.getOrderBy())
.build();
}
}

View File

@ -0,0 +1,15 @@
package cn.axzo.nanopart.visa.server.mq.producer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 变洽签单据日志 MQ 生产者
*
* @author wangli
* @since 2025-01-17 16:33
*/
@Component
@Slf4j
public class VisaChangeLogProducer {
}

View File

@ -0,0 +1,74 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.apollo.api.ApolloConstructionAreaApi;
import cn.axzo.apollo.api.res.ConstructionAreaInfo;
import cn.axzo.apollo.core.web.Result;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author xudawei@axzo.cn
* @date 2025/01/20
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ApolloConstructionAreaGateway {
private final ApolloConstructionAreaApi apolloConstructionAreaApi;
public List<ConstructionAreaInfo> getAllConstructionAreaByIds(List<Long> areaIds) {
try {
if (CollectionUtils.isEmpty(areaIds)) {
return Lists.newArrayList();
}
log.info("ApolloConstructionAreaGateway getAllConstructionAreaByIds,params:{}", JSON.toJSONString(areaIds));
Result<List<ConstructionAreaInfo>> result = apolloConstructionAreaApi.getAllConstructionAreaByIds(areaIds);
log.info("ApolloConstructionAreaGateway getAllConstructionAreaByIds,result:{}", JSON.toJSONString(result));
return result.getData();
} catch (Exception e) {
log.warn("ApolloConstructionAreaGateway getAllConstructionAreaByIds exception", e);
throw e;
}
}
public List<ConstructionAreaInfo> getConstructionAreaByIds(List<Long> areaIds) {
try {
if (CollectionUtils.isEmpty(areaIds)) {
return Lists.newArrayList();
}
log.info("ApolloConstructionAreaGateway getConstructionAreaByIds,params:{}", JSON.toJSONString(areaIds));
Result<List<ConstructionAreaInfo>> result = apolloConstructionAreaApi.getConstructionAreaByIds(areaIds);
log.info("ApolloConstructionAreaGateway getAllConstructionAreaByIds,result:{}", JSON.toJSONString(result));
return result.getData();
} catch (Exception e) {
log.warn("ApolloConstructionAreaGateway getConstructionAreaByIds exception", e);
throw e;
}
}
public String generateAreaFullNameByAreaIds(List<Long> areaIds) {
try {
if (CollectionUtils.isEmpty(areaIds)) {
return "";
}
log.info("ApolloConstructionAreaGateway generateAreaFullNameByAreaIds,params:{}", JSON.toJSONString(areaIds));
Result<String> result = apolloConstructionAreaApi.generateAreaFullNameByAreaIds(areaIds);
log.info("ApolloConstructionAreaGateway generateAreaFullNameByAreaIds,result:{}", JSON.toJSONString(result));
return result.getData();
} catch (Exception e) {
log.warn("ApolloConstructionAreaGateway generateAreaFullNameByAreaIds exception", e);
throw e;
}
}
}

View File

@ -0,0 +1,28 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.apollo.api.ApolloTaskOrderApi;
import cn.axzo.apollo.api.req.QueryOrderToBasicReq;
import cn.axzo.apollo.api.res.TaskOrderToBasicRes;
import cn.axzo.apollo.core.domain.PageResult;
import cn.axzo.nanopart.visa.server.utils.RpcUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/2/12 11:18
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ApolloTaskOrderApiGateway {
private final ApolloTaskOrderApi apolloTaskOrderApi;
public PageResult<TaskOrderToBasicRes> pageOrderByForBasic(QueryOrderToBasicReq req) {
return RpcUtil.rpcResultProcessor(() -> apolloTaskOrderApi.pageOrderByForBasic(req),
"Page query task orders", req);
}
}

View File

@ -0,0 +1,42 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.foundation.result.ApiResult;
import cn.axzo.karma.client.feign.tyr.DataObjectApi;
import cn.axzo.karma.client.feign.tyr.request.MatchDataObjectReq;
import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp;
import cn.axzo.karma.client.feign.tyr.response.MergeMatchDataResp;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Objects;
/**
* @author xudawei@axzo.cn
* @date 2025/02/05
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class DataObjectApiGateway {
private final DataObjectApi dataObjectApi;
public MatchDataObjectResp match(MatchDataObjectReq req) {
if (Objects.isNull(req)) {
return MatchDataObjectResp.builder().build();
}
try {
log.info("DataObjectApiGateway match, params:{}", JSON.toJSONString(req));
ApiResult<MatchDataObjectResp> match = dataObjectApi.match(req);
log.info("DataObjectApiGateway match, result:{}", JSON.toJSONString(match));
return match.getData();
} catch (Exception e) {
log.warn("DataObjectApiGateway match exception", e);
throw e;
}
}
}

View File

@ -0,0 +1,45 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.nanopart.visa.server.utils.RpcUtil;
import cn.axzo.thor.client.enums.DrawingAnnotationBizEnum;
import cn.axzo.thor.client.feign.DrawingAnnotationApi;
import cn.axzo.thor.client.model.BindDrawingAnnotationDTO;
import cn.axzo.thor.client.model.UnbindDrawingAnnotationDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Set;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/2/19 20:09
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class DrawingAnnotationApiGateway {
private final DrawingAnnotationApi drawingAnnotationApi;
public void bindBusiness(Long visasId, Set<Long> annotationIds) {
BindDrawingAnnotationDTO bindDrawingAnnotationDTO = BindDrawingAnnotationDTO.builder()
.drawingAnnotationIds(annotationIds)
.businessType(DrawingAnnotationBizEnum.VISA_CHANGE)
.businessId(String.valueOf(visasId))
.build();
RpcUtil.rpcCommonProcessor(()->drawingAnnotationApi.bindBusiness(bindDrawingAnnotationDTO),
"sync visa and drawing annotation bind relation to thor", bindDrawingAnnotationDTO);
}
public void unbindBusiness(Long visasId, Set<Long> annotationIds) {
UnbindDrawingAnnotationDTO unbindDrawingAnnotationDTO = UnbindDrawingAnnotationDTO.builder()
.drawingAnnotationIds(annotationIds)
.businessType(DrawingAnnotationBizEnum.VISA_CHANGE)
.businessId(String.valueOf(visasId))
.build();
RpcUtil.rpcCommonProcessor(()->drawingAnnotationApi.unbindBusiness(unbindDrawingAnnotationDTO),
"sync visa and drawing annotation unbind relation to thor", unbindDrawingAnnotationDTO);
}
}

View File

@ -0,0 +1,37 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.pokonyan.util.RpcUtil;
import cn.axzo.thor.client.feign.DrawingMajorApi;
import cn.axzo.thor.client.model.DrawingMajorResp;
import cn.axzo.thor.client.model.ListDrawingMajorReq;
import cn.azxo.framework.common.logger.MethodAroundLog;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Set;
/**
* @author xudawei@axzo.cn
* @date 2025/01/20
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class DrawingMajorGateway {
private final DrawingMajorApi drawingMajorApi;
/**
* 获取专业
*/
@MethodAroundLog(target = "thor", source = "nanopart", value = "获取专业")
public List<DrawingMajorResp> list(Long projectId, Set<String> majorCodes, Boolean includeDrawingType) {
ListDrawingMajorReq req = new ListDrawingMajorReq();
req.setProjectId(projectId);
req.setMajorCodes(majorCodes);
req.setIncludeDrawingType(includeDrawingType);
return RpcUtil.rpcCommonProcessor(() -> drawingMajorApi.list(req), "drawingMajorApi#list", req);
}
}

View File

@ -0,0 +1,50 @@
package cn.axzo.nanopart.visa.server.rpc;
/**
* @author xudawei@axzo.cn
* @date 2025/2/12
* @description 日志RPC
*/
import cn.axzo.log.platform.client.feign.LogApi;
import cn.axzo.log.platform.client.model.req.LogAddReq;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 日志RPC
* @author xudawei@axzo.cn
* @since 2025-02-05 15:08
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class LogApiGateway {
private final LogApi logApi;
public void addLog(LogAddReq req) {
try {
log.info("LogApiGateway-addLog, req: {}", JSONUtil.toJsonStr(req));
CommonResponse<String> stringCommonResponse = logApi.addLog(req);
log.info("LogApiGateway-addLog, result: {}", JSONUtil.toJsonStr(stringCommonResponse));
} catch (Exception e) {
log.warn("LogApiGateway-addLog Exception", e);
}
}
public void addLog(String scene, String level, List<String> tags, String msg) {
logApi.addLog(LogAddReq.builder()
.scene(scene)
.level(level)
.tags(tags)
.message(msg)
.build());
}
}

View File

@ -0,0 +1,101 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.im.center.api.feign.GroupApi;
import cn.axzo.im.center.api.feign.MessageApi;
import cn.axzo.im.center.api.vo.req.GroupCreateRequest;
import cn.axzo.im.center.api.vo.req.GroupDismissRequest;
import cn.axzo.im.center.api.vo.req.GroupGetMembersRequest;
import cn.axzo.im.center.api.vo.req.GroupGetOwnerRequest;
import cn.axzo.im.center.api.vo.req.SendChatMessageRequest;
import cn.axzo.im.center.api.vo.resp.GroupCreateResponse;
import cn.axzo.im.center.api.vo.resp.GroupGetMembersResponse;
import cn.axzo.im.center.api.vo.resp.GroupGetOwnerResponse;
import cn.axzo.msg.center.service.pending.card.CardClient;
import cn.axzo.msg.center.service.pending.request.CardSendRequest;
import cn.axzo.msg.center.service.pending.request.CardUpdateStateRequest;
import cn.axzo.msg.center.service.pending.response.CardSendResponse;
import cn.azxo.framework.common.logger.MethodAroundLog;
import cn.azxo.framework.common.model.CommonResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Objects;
/**
* Message / IM 防腐层
*
* @author wangli
* @since 2025-02-05 15:08
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class MsgCenterGateway {
private final GroupApi groupApi;
private final MessageApi messageApi;
private final CardClient cardClient;
@MethodAroundLog(target = "imCenter", source = "nanopart", value = "创建 IM 群聊")
public GroupCreateResponse createImGroup(GroupCreateRequest request) {
ApiResult<GroupCreateResponse> group = groupApi.createGroup(request);
if(group.isSuccess() && Objects.nonNull(group.getData())) {
return group.getData();
}
AssertUtil.isTrue(group.isSuccess(), group.getMsg());
return null;
}
@MethodAroundLog(target = "imCenter", source = "nanopart", value = "解散 IM 群聊")
public void dismissImGroup(GroupDismissRequest request) {
groupApi.dismissGroup(request);
}
@MethodAroundLog(target = "imCenter", source = "nanopart", value = "获取指定 IM 群成员信息")
public GroupGetMembersResponse getMembers(GroupGetMembersRequest request) {
ApiResult<GroupGetMembersResponse> members = groupApi.getMembers(request);
if(members.isSuccess() && Objects.nonNull(members.getData())) {
return members.getData();
}
AssertUtil.isTrue(members.isSuccess(), members.getMsg());
return null;
}
@MethodAroundLog(target = "imCenter", source = "nanopart", value = "获取指定 IM 群群主信息")
public GroupGetOwnerResponse getGroupOwner(GroupGetOwnerRequest request) {
ApiResult<GroupGetOwnerResponse> owner = groupApi.getOwner(request);
if(owner.isSuccess() && Objects.nonNull(owner.getData())) {
return owner.getData();
}
AssertUtil.isTrue(owner.isSuccess(), owner.getMsg());
return null;
}
@MethodAroundLog(target = "imCenter", source = "nanopart", value = "发送普通消息到群消息")
public Long sendMsgToGroup(SendChatMessageRequest request) {
ApiResult<Long> mesageId = messageApi.sendChatMessage(request);
if(mesageId.isSuccess() && Objects.nonNull(mesageId.getData())) {
return mesageId.getData();
}
AssertUtil.isTrue(mesageId.isSuccess(), mesageId.getMsg());
return null;
}
@MethodAroundLog(target = "imCenter", source = "nanopart", value = "发送卡片消息到群消息")
public CardSendResponse sendCardToCroup(CardSendRequest request) {
CommonResponse<CardSendResponse> sendCard = cardClient.send(request);
if (Objects.nonNull(sendCard) && sendCard.getCode() == 200) {
return sendCard.getData();
}
AssertUtil.isTrue(sendCard.getCode() == 200, sendCard.getMsg());
return null;
}
@MethodAroundLog(target = "imCenter", source = "nanopart", value = "更新 IM 群内卡片状态")
public void updateCardState(CardUpdateStateRequest request) {
cardClient.updateState(request);
}
}

View File

@ -0,0 +1,58 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.maokai.api.client.OrganizationalUnitApi;
import cn.axzo.maokai.api.vo.request.OrganizationalUnitQuery;
import cn.axzo.maokai.api.vo.response.OrganizationalUnitVO;
import cn.azxo.framework.common.logger.MethodAroundLog;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
/**
* @author xudawei
* @date 2025/01/21
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class OrganizationalUnitGateway {
private final OrganizationalUnitApi organizationalUnitApi;
@MethodAroundLog(target = "maokai", source = "nanopart", value = "获取单位信息")
public OrganizationalUnitVO getUnitInfo(Long unitId) {
ApiResult<OrganizationalUnitVO> unitResponse = organizationalUnitApi.getById(unitId);
if (unitResponse.isSuccess() && Objects.nonNull(unitResponse.getData())) {
return unitResponse.getData();
}
AssertUtil.isTrue(unitResponse.isSuccess(), unitResponse.getMsg());
return null;
}
/**
* 获取单位集合
*/
@MethodAroundLog(target = "maokai", source = "nanopart", value = "获取单位集合")
public List<OrganizationalUnitVO> list(OrganizationalUnitQuery query) {
if (Objects.isNull(query)) {
return Lists.newArrayList();
}
try {
log.info("OrganizationalUnitGateway list, params:{}", JSON.toJSONString(query));
ApiResult<List<OrganizationalUnitVO>> list = organizationalUnitApi.list(query);
log.info("OrganizationalUnitGateway list, result:{}", JSON.toJSONString(list));
List<OrganizationalUnitVO> data = list.getData();
return data;
} catch (Exception e) {
log.warn("OrganizationalUnitGateway list exception", e);
throw e;
}
}
}

View File

@ -0,0 +1,29 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.digital.RectifyApi;
import cn.axzo.digital.req.ListRectifyOrderReq;
import cn.axzo.digital.resp.RectifyOrderResp;
import cn.axzo.nanopart.visa.server.utils.RpcUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/2/12 11:37
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class RectifyApiGateway {
private final RectifyApi rectifyApi;
public List<RectifyOrderResp> listRectifyOrders(ListRectifyOrderReq req) {
return RpcUtil.rpcApiResultProcessor(() -> rectifyApi.listRectifyOrders(req),
"Get rectify orders by ids", req);
}
}

View File

@ -0,0 +1,34 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.maokai.api.client.CooperateShipQueryApi;
import cn.axzo.maokai.api.vo.request.CooperateShipQueryReq;
import cn.axzo.maokai.api.vo.response.CooperateShipResp;
import cn.axzo.nanopart.visa.server.utils.RpcUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* @author chenwenjian
* @version 1.0
* @date 2024/4/9 11:20
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class VisaCooperateShipGateway {
private final CooperateShipQueryApi cooperateShipQueryApi;
public List<CooperateShipResp> genericQuery(CooperateShipQueryReq req) {
if (Objects.isNull(req)) {
return Collections.emptyList();
}
return RpcUtil.rpcApiListResultProcessor(() -> cooperateShipQueryApi.genericQuery(req),
"协同关系树查询");
}
}

View File

@ -0,0 +1,29 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.maokai.api.client.OrganizationalNodeApi;
import cn.axzo.maokai.api.vo.response.OrganizationalNodeVO;
import cn.axzo.pokonyan.util.RpcUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* TODO
*
* @author wangli
* @since 2025-02-28 11:11
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class VisaOrganizationalNodeGateway {
@Resource
private OrganizationalNodeApi organizationalNodeApi;
public OrganizationalNodeVO getNode(Long nodeId) {
return RpcUtil.rpcApiResultProcessor(() -> organizationalNodeApi.getNode(nodeId), "", nodeId);
}
}

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