From 509410de9af6f79c5c078dd70cf802f72887c992 Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Wed, 8 Jan 2025 10:41:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(web):=20=E9=80=82=E9=85=8Dflowable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gringotts-frontend/components/constants.js | 8 +- gringotts-frontend/pages/index/tab-check.js | 20 +- gringotts-web/pom.xml | 4 + .../eshore/gringotts/web/WebApplication.java | 10 +- .../base/entity/CheckingNeededEntity.java | 8 +- .../domain/base/service/CheckingService.java | 6 - .../controller/CheckOrderController.java | 88 +++++---- .../domain/flowable/CheckRoleAssessor.java | 28 +++ .../web/domain/flowable/UserAssessor.java | 31 +++ .../repository/AuthenticationRepository.java | 13 ++ .../repository/ConfirmationRepository.java | 15 +- .../web/domain/repository/WareRepository.java | 13 ++ .../domain/service/AuthenticationService.java | 178 +++++++++--------- .../web/domain/service/CheckOrderService.java | 82 -------- .../domain/service/ConfirmationService.java | 159 +++++++--------- .../web/domain/service/WareService.java | 133 ++++++------- 16 files changed, 412 insertions(+), 384 deletions(-) create mode 100644 gringotts-web/src/main/java/com/eshore/gringotts/web/domain/flowable/CheckRoleAssessor.java create mode 100644 gringotts-web/src/main/java/com/eshore/gringotts/web/domain/flowable/UserAssessor.java delete mode 100644 gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/CheckOrderService.java diff --git a/gringotts-frontend/components/constants.js b/gringotts-frontend/components/constants.js index 74d48f5..efa067d 100644 --- a/gringotts-frontend/components/constants.js +++ b/gringotts-frontend/components/constants.js @@ -261,13 +261,13 @@ export const permissionStateMapping = [ export const checkTypeMapping = [ mappingItem('确权审查', 'CONFIRMATION', 'bg-blue-500'), mappingItem('授权审查', 'AUTHENTICATION', 'bg-purple-500'), - mappingItem('上架审查', 'MARKET', 'bg-green-500'), + mappingItem('上架审查', 'WARE', 'bg-green-500'), ] export const checkOverMapping = [ - mappingItem('进行中', 'CHECKING', 'bg-warning'), - mappingItem('已撤销', 'RETRACT', 'bg-primary'), - mappingItem('已办结', 'OVER', 'bg-success'), + mappingItem('进行中', 'RUNNING', 'bg-warning'), + mappingItem('已撤销', 'TERMINAL', 'bg-primary'), + mappingItem('已办结', 'COMPLETED', 'bg-success'), ] function api(method, url) { diff --git a/gringotts-frontend/pages/index/tab-check.js b/gringotts-frontend/pages/index/tab-check.js index d0af8c4..ae4e96a 100644 --- a/gringotts-frontend/pages/index/tab-check.js +++ b/gringotts-frontend/pages/index/tab-check.js @@ -31,7 +31,7 @@ export function tabCheck() { stringField('modifiedUsername', '最后操作人', 100), operationField('操作', undefined, [ { - visibleOn: "${type === 'CONFIRMATION' && state === 'CHECKING'}", + visibleOn: "${type === 'CONFIRMATION' && state === 'RUNNING'}", type: 'action', label: '处理', level: 'link', @@ -43,7 +43,7 @@ export function tabCheck() { label: '同意', actionType: 'ajax', close: true, - api: apiGet('${base}/check_order/operation/${checkOrderId}/APPLY'), + api: apiGet('${base}/check_order/approve/${instanceId}'), reload: 'check_order_list', }, { @@ -51,7 +51,7 @@ export function tabCheck() { label: '拒绝', actionType: 'ajax', close: true, - api: apiGet('${base}/check_order/operation/${checkOrderId}/REJECT'), + api: apiGet('${base}/check_order/reject/${instanceId}'), reload: 'check_order_list', }, ], @@ -65,7 +65,7 @@ export function tabCheck() { ...confirmationDetailDialog('parameters.confirmationId'), }, { - visibleOn: "${type === 'AUTHENTICATION' && state === 'CHECKING'}", + visibleOn: "${type === 'AUTHENTICATION' && state === 'RUNNING'}", type: 'action', label: '处理', level: 'link', @@ -77,7 +77,7 @@ export function tabCheck() { label: '同意', actionType: 'ajax', close: true, - api: apiGet('${base}/check_order/operation/${checkOrderId}/APPLY'), + api: apiGet('${base}/check_order/approve/${instanceId}'), reload: 'check_order_list', }, { @@ -85,7 +85,7 @@ export function tabCheck() { label: '拒绝', actionType: 'ajax', close: true, - api: apiGet('${base}/check_order/operation/${checkOrderId}/REJECT'), + api: apiGet('${base}/check_order/reject/${instanceId}'), reload: 'check_order_list', }, ], @@ -99,7 +99,7 @@ export function tabCheck() { ...authenticationDetailDialog('parameters.authenticationId'), }, { - visibleOn: "${type === 'MARKET' && state === 'CHECKING'}", + visibleOn: "${type === 'WARE' && state === 'RUNNING'}", type: 'action', label: '处理', level: 'link', @@ -111,7 +111,7 @@ export function tabCheck() { label: '同意', actionType: 'ajax', close: true, - api: apiGet('${base}/check_order/operation/${checkOrderId}/APPLY'), + api: apiGet('${base}/check_order/approve/${instanceId}'), reload: 'check_order_list', }, { @@ -119,14 +119,14 @@ export function tabCheck() { label: '拒绝', actionType: 'ajax', close: true, - api: apiGet('${base}/check_order/operation/${checkOrderId}/REJECT'), + api: apiGet('${base}/check_order/reject/${instanceId}'), reload: 'check_order_list', }, ], ), }, { - visibleOn: "${type === 'MARKET' && state !== NORMAL}", + visibleOn: "${type === 'WARE' && state !== NORMAL}", type: 'action', label: '查看', level: 'link', diff --git a/gringotts-web/pom.xml b/gringotts-web/pom.xml index 5fad3e2..8a6a2b2 100644 --- a/gringotts-web/pom.xml +++ b/gringotts-web/pom.xml @@ -20,6 +20,10 @@ com.eshore gringotts-forest + + com.lanyuanxiaoyao + flowable-spring-boot-jpa-starter + org.springframework.boot spring-boot-starter-data-jpa diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/WebApplication.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/WebApplication.java index c6063f1..7676f40 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/WebApplication.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/WebApplication.java @@ -8,6 +8,7 @@ import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; @@ -21,7 +22,14 @@ import org.springframework.scheduling.annotation.EnableAsync; * @author lanyuanxiaoyao * @date 2024-11-14 */ -@SpringBootApplication(scanBasePackages = {"com.eshore.gringotts"}) +@SpringBootApplication(scanBasePackages = { + "com.eshore.gringotts", + "com.lanyuanxiaoyao.flowable.jpa" +}) +@EntityScan({ + "com.eshore.gringotts.web.domain.entity", + "com.lanyuanxiaoyao.flowable.jpa.entity" +}) @EnableFenix @EnableJpaAuditing @EnableAsync diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/base/entity/CheckingNeededEntity.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/base/entity/CheckingNeededEntity.java index f978ad5..1427b05 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/base/entity/CheckingNeededEntity.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/base/entity/CheckingNeededEntity.java @@ -1,14 +1,10 @@ package com.eshore.gringotts.web.domain.base.entity; -import com.eshore.gringotts.web.domain.entity.CheckOrder; -import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.EntityListeners; import javax.persistence.EnumType; import javax.persistence.Enumerated; -import javax.persistence.FetchType; import javax.persistence.MappedSuperclass; -import javax.persistence.OneToOne; import lombok.Getter; import lombok.Setter; import lombok.ToString; @@ -26,9 +22,7 @@ public class CheckingNeededEntity extends LogicDeleteEntity { @Enumerated(EnumType.STRING) private State state = State.DRAFT; - @OneToOne(cascade = CascadeType.DETACH, fetch = FetchType.LAZY) - @ToString.Exclude - private CheckOrder order; + private String flowableInstanceId; public enum State { /** diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/base/service/CheckingService.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/base/service/CheckingService.java index 14c22f8..1aa0adb 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/base/service/CheckingService.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/base/service/CheckingService.java @@ -2,10 +2,8 @@ package com.eshore.gringotts.web.domain.base.service; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity; import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; -import com.eshore.gringotts.web.domain.entity.CheckOrder; import com.eshore.gringotts.web.domain.service.UserService; import javax.persistence.EntityManager; -import org.eclipse.collections.api.map.ImmutableMap; /** * 需要审查 @@ -21,8 +19,4 @@ public abstract class CheckingService extends abstract public void submit(Long id) throws Exception; abstract public void retract(Long id) throws Exception; - - abstract public void onChecked(CheckOrder order, CheckOrder.Operation operation, ImmutableMap parameters); - - abstract public ImmutableMap archive(ENTITY entity); } diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/CheckOrderController.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/CheckOrderController.java index 24dab6f..cbf2b8f 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/CheckOrderController.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/CheckOrderController.java @@ -3,18 +3,19 @@ package com.eshore.gringotts.web.domain.controller; import com.eshore.gringotts.web.configuration.amis.AmisResponse; import com.eshore.gringotts.web.domain.base.controller.ListController; import com.eshore.gringotts.web.domain.base.controller.query.Query; -import com.eshore.gringotts.web.domain.entity.CheckOrder; -import com.eshore.gringotts.web.domain.service.CheckOrderService; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.eshore.gringotts.web.domain.entity.User; +import com.eshore.gringotts.web.domain.service.UserService; +import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; +import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; +import com.lanyuanxiaoyao.flowable.jpa.SpringFlowableManager; import java.time.LocalDateTime; import lombok.Data; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.factory.Maps; import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.map.ImmutableMap; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -32,55 +33,76 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("check_order") public class CheckOrderController implements ListController { - private final CheckOrderService checkOrderService; - private final ObjectMapper mapper; + private final UserService userService; + private final SpringFlowableManager flowableManager; - public CheckOrderController(CheckOrderService checkOrderService, Jackson2ObjectMapperBuilder builder) { - this.checkOrderService = checkOrderService; - this.mapper = builder.build(); + public CheckOrderController(UserService userService, SpringFlowableManager flowableManager) { + this.userService = userService; + this.flowableManager = flowableManager; } @GetMapping("/list") @Override public AmisResponse> list() throws Exception { - return AmisResponse.responseSuccess(checkOrderService.list().collect(this::toListItem)); + User user = userService.currentLoginUser(); + return AmisResponse.responseSuccess( + Lists.immutable.ofAll(flowableManager.listInstances( + (root, query, builder) -> { + if (User.isAdministrator(user)) { + return null; + } + return builder.or( + builder.like(root.get("extra"), user.getRole().name()), + builder.like(root.get("extra"), user.getId().toString()) + ); + } + )).collect(this::toListItem) + ); } @PostMapping("/list") @Override public AmisResponse> list(@RequestBody Query query) throws Exception { - return AmisResponse.responseSuccess(checkOrderService.list().collect(this::toListItem)); + throw new UnsupportedOperationException(); + } + + @GetMapping("/approve/{instanceId}") + public AmisResponse approve(@PathVariable String instanceId) { + flowableManager.approve(instanceId); + return AmisResponse.responseSuccess(); + } + + @GetMapping("/reject/{instanceId}") + public AmisResponse reject(@PathVariable String instanceId) { + flowableManager.reject(instanceId); + return AmisResponse.responseSuccess(); } @SneakyThrows - private ListItem toListItem(CheckOrder order) { + private ListItem toListItem(FlowableInstance instance) { + FlowableNode node = flowableManager.getNode(instance.getCurrentNodeId()); ListItem item = new ListItem(); - item.setCheckOrderId(order.getId()); - item.setDescription(order.getDescription()); - item.setType(order.getType()); - item.setParameters(mapper.readValue(order.getParameters(), new TypeReference<>() {})); - item.setState(order.getState()); - item.setCreatedUsername(order.getCreatedUser().getUsername()); - item.setCreatedTime(order.getCreatedTime()); - item.setModifiedUsername(order.getModifiedUser().getUsername()); - item.setModifiedTime(order.getModifiedTime()); + item.setInstanceId(instance.getInstanceId()); + item.setName(node.getName()); + item.setDescription(node.getDescription()); + item.setType(instance.getMetadata().getStringOrDefault("type", "unknown")); + item.setParameters(Maps.immutable.ofAll(instance.getMetadata().getMetadata())); + item.setState(instance.getStatus()); + item.setCreatedUsername(instance.getMetadata().getStringOrDefault("createdUsername", "")); + item.setCreatedTime(instance.getCreatedTime()); + item.setModifiedUsername(instance.getMetadata().getStringOrDefault("modifiedUsername", "")); + item.setModifiedTime(instance.getUpdatedTime()); return item; } - @GetMapping("/operation/{id}/{operation}") - public AmisResponse operation(@PathVariable Long id, @PathVariable CheckOrder.Operation operation) throws JsonProcessingException { - log.info("id:{}, operation:{}", id, operation); - checkOrderService.operation(id, operation); - return AmisResponse.responseSuccess(); - } - @Data public static final class ListItem { - private Long checkOrderId; + private String instanceId; + private String name; private String description; - private CheckOrder.Type type; + private String type; private ImmutableMap parameters; - private CheckOrder.State state; + private FlowableInstance.Status state; private LocalDateTime createdTime; private String createdUsername; private LocalDateTime modifiedTime; diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/flowable/CheckRoleAssessor.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/flowable/CheckRoleAssessor.java new file mode 100644 index 0000000..553fa21 --- /dev/null +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/flowable/CheckRoleAssessor.java @@ -0,0 +1,28 @@ +package com.eshore.gringotts.web.domain.flowable; + +import com.eshore.gringotts.web.domain.entity.User; +import com.eshore.gringotts.web.domain.service.UserService; +import com.lanyuanxiaoyao.flowable.core.model.FlowableAccessor; +import com.lanyuanxiaoyao.flowable.core.model.FlowableAction; +import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; +import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; +import org.springframework.stereotype.Service; + +/** + * @author lanyuanxiaoyao + * @version 20250106 + */ +@Service +public class CheckRoleAssessor implements FlowableAccessor { + private final UserService userService; + + public CheckRoleAssessor(UserService userService) { + this.userService = userService; + } + + @Override + public boolean access(FlowableInstance flowableInstance, FlowableNode flowableNode, FlowableAction flowableAction) { + User.Role role = userService.currentLoginUser().getRole(); + return User.Role.ADMINISTRATOR.equals(role) || User.Role.CHECKER.equals(role); + } +} diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/flowable/UserAssessor.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/flowable/UserAssessor.java new file mode 100644 index 0000000..59d8e4c --- /dev/null +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/flowable/UserAssessor.java @@ -0,0 +1,31 @@ +package com.eshore.gringotts.web.domain.flowable; + +import cn.hutool.core.util.NumberUtil; +import com.eshore.gringotts.web.domain.service.UserService; +import com.lanyuanxiaoyao.flowable.core.model.FlowableAccessor; +import com.lanyuanxiaoyao.flowable.core.model.FlowableAction; +import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; +import com.lanyuanxiaoyao.flowable.core.model.FlowableMetadata; +import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; +import org.springframework.stereotype.Service; + +/** + * @author lanyuanxiaoyao + * @version 20250106 + */ +@Service +public class UserAssessor implements FlowableAccessor { + public static final String KEY = "user_access_key"; + + private final UserService userService; + + public UserAssessor(UserService userService) { + this.userService = userService; + } + + @Override + public boolean access(FlowableInstance flowableInstance, FlowableNode flowableNode, FlowableAction flowableAction) { + FlowableMetadata metadata = flowableInstance.getMetadata(); + return NumberUtil.equals(userService.currentLoginUser().getId(), metadata.getLong(KEY)); + } +} diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/AuthenticationRepository.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/AuthenticationRepository.java index 36db649..ed8880c 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/AuthenticationRepository.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/AuthenticationRepository.java @@ -4,9 +4,12 @@ import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; import com.eshore.gringotts.web.domain.entity.Authentication; import java.util.List; import java.util.Optional; +import javax.transaction.Transactional; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; /** @@ -27,4 +30,14 @@ public interface AuthenticationRepository extends SimpleRepository findOne(Specification specification); + + @Transactional + @Modifying + @Query("update Authentication confirmation set confirmation.state = ?2 where confirmation.id = ?1 and confirmation.deleted = false") + void updateStateById(Long id, Authentication.State state); + + @Transactional + @Modifying + @Query("update Authentication confirmation set confirmation.flowableInstanceId = ?2 where confirmation.id = ?1 and confirmation.deleted = false") + void updateInstanceIdById(Long id, String instanceId); } diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/ConfirmationRepository.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/ConfirmationRepository.java index e62f06b..08f9f19 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/ConfirmationRepository.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/ConfirmationRepository.java @@ -4,9 +4,12 @@ import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; import com.eshore.gringotts.web.domain.entity.Confirmation; import java.util.List; import java.util.Optional; +import javax.transaction.Transactional; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; /** @@ -28,5 +31,15 @@ public interface ConfirmationRepository extends SimpleRepository findOne(Specification specification); - Boolean existsByTarget_Id(Long id); + @Transactional + @Modifying + @Query("update Confirmation confirmation set confirmation.state = ?2 where confirmation.id = ?1 and confirmation.deleted = false") + void updateStateById(Long id, Confirmation.State state); + + @Transactional + @Modifying + @Query("update Confirmation confirmation set confirmation.flowableInstanceId = ?2 where confirmation.id = ?1 and confirmation.deleted = false") + void updateInstanceIdById(Long id, String instanceId); + + Boolean existsByTarget_Id(Long targetId); } diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/WareRepository.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/WareRepository.java index 681228d..3b88cdb 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/WareRepository.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/WareRepository.java @@ -4,9 +4,12 @@ import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; import com.eshore.gringotts.web.domain.entity.Ware; import java.util.List; import java.util.Optional; +import javax.transaction.Transactional; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @SuppressWarnings("NullableProblems") @@ -23,4 +26,14 @@ public interface WareRepository extends SimpleRepository { @Override @EntityGraph(value = "ware.detail", type = EntityGraph.EntityGraphType.FETCH) Optional findOne(Specification specification); + + @Transactional + @Modifying + @Query("update Ware ware set ware.state = ?2 where ware.id = ?1 and ware.deleted = false") + void updateStateById(Long id, Ware.State state); + + @Transactional + @Modifying + @Query("update Ware ware set ware.flowableInstanceId = ?2 where ware.id = ?1 and ware.deleted = false") + void updateInstanceIdById(Long id, String instanceId); } \ No newline at end of file diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/AuthenticationService.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/AuthenticationService.java index 3facfc2..ea27759 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/AuthenticationService.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/AuthenticationService.java @@ -1,29 +1,32 @@ package com.eshore.gringotts.web.domain.service; +import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity; import com.eshore.gringotts.web.domain.base.service.CheckingService; import com.eshore.gringotts.web.domain.entity.Authentication; import com.eshore.gringotts.web.domain.entity.Authentication_; -import com.eshore.gringotts.web.domain.entity.CheckOrder; -import com.eshore.gringotts.web.domain.entity.CheckOrder_; +import com.eshore.gringotts.web.domain.entity.Confirmation; import com.eshore.gringotts.web.domain.entity.User; +import com.eshore.gringotts.web.domain.flowable.CheckRoleAssessor; +import com.eshore.gringotts.web.domain.flowable.UserAssessor; import com.eshore.gringotts.web.domain.repository.AuthenticationRepository; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.lanyuanxiaoyao.flowable.core.model.FlowableAction; +import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; +import com.lanyuanxiaoyao.flowable.core.model.FlowableListener; +import com.lanyuanxiaoyao.flowable.core.model.FlowableMetadata; +import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; +import com.lanyuanxiaoyao.flowable.jpa.SpringFlowableManager; import javax.persistence.EntityManager; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; -import javax.transaction.Transactional; import lombok.extern.slf4j.Slf4j; import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.factory.Maps; import org.eclipse.collections.api.list.ImmutableList; -import org.eclipse.collections.api.map.ImmutableMap; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; /** @@ -31,19 +34,38 @@ import org.springframework.stereotype.Service; * @date 2024-12-02 */ @Slf4j -@Service("com.eshore.gringotts.web.domain.service.AuthenticationService") +@Service public class AuthenticationService extends CheckingService { + private static final String AUTHENTICATION_FLOW_ID = "4ba86acd-1420-450b-98f9-0ed41772fe53"; + private final AuthenticationRepository authenticationRepository; private final UserService userService; - private final CheckOrderService checkOrderService; - private final ObjectMapper mapper; + private final SpringFlowableManager flowableManager; - public AuthenticationService(AuthenticationRepository repository, UserService userService, EntityManager manager, CheckOrderService checkOrderService, Jackson2ObjectMapperBuilder builder) { + public AuthenticationService(AuthenticationRepository repository, UserService userService, EntityManager manager, SpringFlowableManager flowableManager) { super(repository, userService, manager); this.authenticationRepository = repository; this.userService = userService; - this.checkOrderService = checkOrderService; - this.mapper = builder.build(); + + this.flowableManager = flowableManager; + FlowableNode userCheckNode = FlowableNode.builder() + .nodeId(AUTHENTICATION_FLOW_ID) + .name("用户审查") + .description("用户审查") + .listeners(Lists.mutable.of(AuthenticationService.AuthenticationFlowUserCheckListener.class.getName())) + .accessor(UserAssessor.class.getName()) + .targets(Maps.mutable.of( + FlowableAction.APPROVE, "f087b0e4-0efa-4b26-945f-642436aa4aef" + )) + .build(); + FlowableNode roleCheckNode = FlowableNode.builder() + .nodeId("f087b0e4-0efa-4b26-945f-642436aa4aef") + .name("授权审查") + .description("授权审查") + .listeners(Lists.mutable.of(AuthenticationService.AuthenticationFlowRoleCheckListener.class.getName())) + .accessor(CheckRoleAssessor.class.getName()) + .build(); + flowableManager.create(userCheckNode, roleCheckNode); } @Override @@ -53,15 +75,7 @@ public class AuthenticationService extends CheckingService { return Lists.immutable.empty(); } return Lists.immutable.of(builder.or( - builder.equal(root.get(Authentication_.createdUser), loginUser), - builder.and( - builder.equal(root.get(Authentication_.order).get(CheckOrder_.target), CheckOrder.Target.ROLE), - builder.equal(root.get(Authentication_.order).get(CheckOrder_.targetRole), loginUser.getRole()) - ), - builder.and( - builder.equal(root.get(Authentication_.order).get(CheckOrder_.target), CheckOrder.Target.USER), - builder.equal(root.get(Authentication_.order).get(CheckOrder_.targetUser), loginUser) - ) + builder.equal(root.get(Authentication_.createdUser), loginUser) )); } @@ -82,73 +96,29 @@ public class AuthenticationService extends CheckingService { return super.save(entity); } - @Transactional(rollbackOn = Throwable.class) @Override - public void submit(Long id) throws JsonProcessingException { + public void submit(Long id) throws Exception { + User user = userService.currentLoginUser(); Authentication authentication = detailOrThrow(id); - authentication.setState(CheckingNeededEntity.State.OWNER_CHECKING); - Long orderId = checkOrderService.save(new CheckOrder( - "authentication_owner_check", - StrUtil.format("数据资源「{}」的授权申请", authentication.getTarget().getName()), - CheckOrder.Type.AUTHENTICATION, - mapper.writeValueAsString(Maps.immutable.of("authenticationId", authentication.getId())), - "com.eshore.gringotts.web.domain.service.AuthenticationService", - authentication.getCreatedUser() - )); - CheckOrder order = checkOrderService.detailOrThrow(orderId); - authentication.setOrder(order); - save(authentication); - } - - @Transactional(rollbackOn = Throwable.class) - @Override - public void retract(Long id) { - Authentication authentication = detailOrThrow(id); - authentication.setState(Authentication.State.DRAFT); - save(authentication); - - CheckOrder order = authentication.getOrder(); - order.setState(CheckOrder.State.RETRACT); - checkOrderService.save(order); + String instanceId = flowableManager.start( + AUTHENTICATION_FLOW_ID, + MapUtil.builder() + .put("authenticationId", id) + .put("type", "AUTHENTICATION") + .put("createdUsername", user.getUsername()) + .put("modifiedUsername", user.getUsername()) + .put(UserAssessor.KEY, authentication.getTarget().getCreatedUser().getId()) + .build(), + authentication.getTarget().getCreatedUser().getId().toString() + ); + authenticationRepository.updateInstanceIdById(id, instanceId); + authenticationRepository.updateStateById(id, Confirmation.State.CHECKING); } @Override - @Transactional(rollbackOn = Throwable.class) - public void onChecked(CheckOrder order, CheckOrder.Operation operation, ImmutableMap parameters) { - Long id = (Long) parameters.get("authenticationId"); + public void retract(Long id) throws Exception { Authentication authentication = detailOrThrow(id); - if (StrUtil.equals(order.getKeyword(), "authentication_owner_check")) { - switch (operation) { - case APPLY: - authentication.setState(Authentication.State.CHECKING); - order.setKeyword("authentication_checker_check"); - order.setTarget(CheckOrder.Target.ROLE); - order.setTargetRole(User.Role.CHECKER); - break; - case REJECT: - authentication.setState(Authentication.State.DRAFT); - order.setState(CheckOrder.State.OVER); - break; - } - } else if (StrUtil.equals(order.getKeyword(), "authentication_checker_check")) { - switch (operation) { - case APPLY: - authentication.setState(Authentication.State.NORMAL); - order.setState(CheckOrder.State.OVER); - break; - case REJECT: - authentication.setState(Authentication.State.DRAFT); - order.setState(CheckOrder.State.OVER); - break; - } - } - save(authentication); - checkOrderService.save(order); - } - - @Override - public ImmutableMap archive(Authentication authentication) { - return null; + flowableManager.terminal(authentication.getFlowableInstanceId()); } public static final class AuthenticationDuplicatedException extends RuntimeException { @@ -156,4 +126,44 @@ public class AuthenticationService extends CheckingService { super("数据资源已绑定该账号的授权申请,无法再次申请"); } } + + @Component + public static final class AuthenticationFlowUserCheckListener extends FlowableListener.AbstractFlowableListener { + private final AuthenticationRepository authenticationRepository; + + public AuthenticationFlowUserCheckListener(AuthenticationRepository authenticationRepository) { + this.authenticationRepository = authenticationRepository; + } + + @Override + public void onActionComplete(FlowableInstance instance, FlowableNode node, FlowableAction action) { + FlowableMetadata metadata = instance.getMetadata(); + Long authenticationId = metadata.getLong("authenticationId"); + if (FlowableAction.APPROVE.equals(action)) { + instance.setExtra(User.Role.CHECKER.name()); + } else { + authenticationRepository.updateStateById(authenticationId, Confirmation.State.DRAFT); + } + } + } + + @Component + public static final class AuthenticationFlowRoleCheckListener extends FlowableListener.AbstractFlowableListener { + private final AuthenticationRepository authenticationRepository; + + public AuthenticationFlowRoleCheckListener(AuthenticationRepository authenticationRepository) { + this.authenticationRepository = authenticationRepository; + } + + @Override + public void onActionComplete(FlowableInstance instance, FlowableNode node, FlowableAction action) { + FlowableMetadata metadata = instance.getMetadata(); + Long authenticationId = metadata.getLong("authenticationId"); + if (FlowableAction.APPROVE.equals(action)) { + authenticationRepository.updateStateById(authenticationId, CheckingNeededEntity.State.NORMAL); + } else { + authenticationRepository.updateStateById(authenticationId, Confirmation.State.DRAFT); + } + } + } } diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/CheckOrderService.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/CheckOrderService.java deleted file mode 100644 index 70714df..0000000 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/CheckOrderService.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.eshore.gringotts.web.domain.service; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.eshore.gringotts.web.domain.base.service.CheckingService; -import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport; -import com.eshore.gringotts.web.domain.entity.CheckOrder; -import com.eshore.gringotts.web.domain.entity.CheckOrder_; -import com.eshore.gringotts.web.domain.entity.User; -import com.eshore.gringotts.web.domain.repository.CheckOrderRepository; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; -import lombok.extern.slf4j.Slf4j; -import org.eclipse.collections.api.factory.Lists; -import org.eclipse.collections.api.list.ImmutableList; -import org.eclipse.collections.api.map.ImmutableMap; -import org.springframework.context.ApplicationContext; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; -import org.springframework.stereotype.Service; - -/** - * @author lanyuanxiaoyao - * @date 2024-11-29 - */ -@Slf4j -@Service -public class CheckOrderService extends SimpleServiceSupport { - private final ApplicationContext applicationContext; - private final ObjectMapper mapper; - private final CheckOrderRepository checkOrderRepository; - private final UserService userService; - - public CheckOrderService(CheckOrderRepository repository, UserService userService, ApplicationContext applicationContext, Jackson2ObjectMapperBuilder builder) { - super(repository, userService); - this.applicationContext = applicationContext; - this.mapper = builder.build(); - this.checkOrderRepository = repository; - this.userService = userService; - } - - @Override - protected ImmutableList listPredicate(Root root, CriteriaQuery query, CriteriaBuilder builder) { - User user = userService.currentLoginUser(); - if (User.isAdministrator(user)) { - return Lists.immutable.empty(); - } - return Lists.immutable.of(builder.or( - builder.equal(root.get(CheckOrder_.createdUser), user), - builder.and( - builder.equal(root.get(CheckOrder_.target), CheckOrder.Target.USER), - builder.equal(root.get(CheckOrder_.targetUser), user) - ), - builder.and( - builder.equal(root.get(CheckOrder_.target), CheckOrder.Target.ROLE), - builder.equal(root.get(CheckOrder_.targetRole), user.getRole()) - ) - )); - } - - public void operation(Long id, CheckOrder.Operation operation) throws JsonProcessingException { - CheckOrder order = detailOrThrow(id); - CheckingService service = applicationContext.getBean(order.getTargetClass(), CheckingService.class); - if (ObjectUtil.isNull(service)) { - throw new RuntimeException(StrUtil.format("名为「{}」的服务未找到", order.getTargetClass())); - } - ImmutableMap parameters = mapper.readValue(order.getParameters(), new TypeReference<>() {}); - service.onChecked(order, operation, parameters); - } - - public void retract(Long id) { - checkOrderRepository.overById(id, CheckOrder.State.RETRACT, userService.currentLoginUser()); - } - - public void over(Long id) { - checkOrderRepository.overById(id, CheckOrder.State.OVER, userService.currentLoginUser()); - } -} diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/ConfirmationService.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/ConfirmationService.java index 34e2a85..6c9ed59 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/ConfirmationService.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/ConfirmationService.java @@ -1,31 +1,28 @@ package com.eshore.gringotts.web.domain.service; +import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity; import com.eshore.gringotts.web.domain.base.service.CheckingService; -import com.eshore.gringotts.web.domain.entity.CheckOrder; -import com.eshore.gringotts.web.domain.entity.CheckOrder_; import com.eshore.gringotts.web.domain.entity.Confirmation; import com.eshore.gringotts.web.domain.entity.Confirmation_; import com.eshore.gringotts.web.domain.entity.User; +import com.eshore.gringotts.web.domain.flowable.CheckRoleAssessor; import com.eshore.gringotts.web.domain.repository.ConfirmationRepository; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.lanyuanxiaoyao.flowable.core.model.FlowableAction; +import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; +import com.lanyuanxiaoyao.flowable.core.model.FlowableListener; +import com.lanyuanxiaoyao.flowable.core.model.FlowableMetadata; +import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; +import com.lanyuanxiaoyao.flowable.jpa.SpringFlowableManager; import javax.persistence.EntityManager; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; -import javax.transaction.Transactional; import lombok.extern.slf4j.Slf4j; import org.eclipse.collections.api.factory.Lists; -import org.eclipse.collections.api.factory.Maps; import org.eclipse.collections.api.list.ImmutableList; -import org.eclipse.collections.api.map.ImmutableMap; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; /** @@ -33,17 +30,26 @@ import org.springframework.stereotype.Service; * @date 2024-11-26 */ @Slf4j -@Service("com.eshore.gringotts.web.domain.service.ConfirmationService") +@Service public class ConfirmationService extends CheckingService { - private final ConfirmationRepository confirmationRepository; - private final CheckOrderService checkOrderService; - private final ObjectMapper mapper; + private static final String CONFIRMATION_FLOW_ID = "69d8ded5-35fd-4f03-b11a-be0ed91a4b8b"; - public ConfirmationService(ConfirmationRepository confirmationRepository, UserService userService, EntityManager entityManager, CheckOrderService checkOrderService, Jackson2ObjectMapperBuilder builder) { + private final ConfirmationRepository confirmationRepository; + private final SpringFlowableManager flowableManager; + + public ConfirmationService(ConfirmationRepository confirmationRepository, UserService userService, EntityManager entityManager, SpringFlowableManager flowableManager) { super(confirmationRepository, userService, entityManager); this.confirmationRepository = confirmationRepository; - this.checkOrderService = checkOrderService; - this.mapper = builder.build(); + + this.flowableManager = flowableManager; + FlowableNode node = FlowableNode.builder() + .nodeId(CONFIRMATION_FLOW_ID) + .name("确权审查") + .description("确权审查") + .listeners(Lists.mutable.of(ConfirmationService.ConfirmationFlowRoleCheckListener.class.getName())) + .accessor(CheckRoleAssessor.class.getName()) + .build(); + flowableManager.create(node); } @Override @@ -52,25 +58,34 @@ public class ConfirmationService extends CheckingService { if (User.isAdministrator(loginUser)) { return Lists.immutable.empty(); } - Join orderJoin = root.join(Confirmation_.order, JoinType.LEFT); return Lists.immutable.of(builder.or( - builder.equal(root.get(Confirmation_.createdUser), loginUser), - builder.and( - builder.isNotNull(orderJoin), - builder.or( - builder.and( - builder.equal(orderJoin.get(CheckOrder_.target), CheckOrder.Target.ROLE), - builder.equal(orderJoin.get(CheckOrder_.targetRole), loginUser.getRole()) - ), - builder.and( - builder.equal(orderJoin.get(CheckOrder_.target), CheckOrder.Target.USER), - builder.equal(orderJoin.get(CheckOrder_.targetUser), loginUser) - ) - ) - ) + builder.equal(root.get(Confirmation_.createdUser), loginUser) )); } + @Override + public void submit(Long id) throws Exception { + User user = userService.currentLoginUser(); + String instanceId = flowableManager.start( + CONFIRMATION_FLOW_ID, + MapUtil.builder() + .put("confirmationId", id) + .put("type", "CONFIRMATION") + .put("createdUsername", user.getUsername()) + .put("modifiedUsername", user.getUsername()) + .build(), + User.Role.CHECKER.name() + ); + confirmationRepository.updateInstanceIdById(id, instanceId); + confirmationRepository.updateStateById(id, Confirmation.State.CHECKING); + } + + @Override + public void retract(Long id) throws Exception { + Confirmation confirmation = detailOrThrow(id); + flowableManager.terminal(confirmation.getFlowableInstanceId()); + } + @Override public Long save(Confirmation entity) { if (ObjectUtil.isNull(entity.getId()) && confirmationRepository.existsByTarget_Id(entity.getTarget().getId())) { @@ -79,65 +94,29 @@ public class ConfirmationService extends CheckingService { return super.save(entity); } - @Transactional(rollbackOn = Throwable.class) - @Override - public void submit(Long id) throws JsonProcessingException { - Confirmation confirmation = detailOrThrow(id); - confirmation.setState(Confirmation.State.CHECKING); - Long orderId = checkOrderService.save(new CheckOrder( - "confirmation_check", - StrUtil.format("数据资源「{}」的确权申请", confirmation.getTarget().getName()), - CheckOrder.Type.CONFIRMATION, - mapper.writeValueAsString(Maps.immutable.of("confirmationId", confirmation.getId())), - "com.eshore.gringotts.web.domain.service.ConfirmationService", - User.Role.CHECKER - )); - CheckOrder order = checkOrderService.detailOrThrow(orderId); - confirmation.setOrder(order); - save(confirmation); - } - - @Transactional(rollbackOn = Throwable.class) - @Override - public void retract(Long id) { - Confirmation confirmation = detailOrThrow(id); - confirmation.setState(CheckingNeededEntity.State.DRAFT); - save(confirmation); - - CheckOrder order = confirmation.getOrder(); - order.setState(CheckOrder.State.RETRACT); - checkOrderService.save(order); - } - - @Override - @Transactional(rollbackOn = Throwable.class) - public void onChecked(CheckOrder order, CheckOrder.Operation operation, ImmutableMap parameters) { - if (StrUtil.equals(order.getKeyword(), "confirmation_check")) { - Long id = (Long) parameters.get("confirmationId"); - Confirmation confirmation = detailOrThrow(id); - switch (operation) { - case APPLY: - confirmation.setState(Confirmation.State.NORMAL); - order.setState(CheckOrder.State.OVER); - break; - case REJECT: - confirmation.setState(Confirmation.State.DRAFT); - order.setState(CheckOrder.State.OVER); - break; - } - save(confirmation); - checkOrderService.save(order); - } - } - - @Override - public ImmutableMap archive(Confirmation confirmation) { - return null; - } - public static final class ConfirmationDuplicatedException extends RuntimeException { public ConfirmationDuplicatedException() { super("数据资源已绑定确权申请,无法再次申请"); } } + + @Component + public static final class ConfirmationFlowRoleCheckListener extends FlowableListener.AbstractFlowableListener { + private final ConfirmationRepository confirmationRepository; + + public ConfirmationFlowRoleCheckListener(ConfirmationRepository confirmationRepository) { + this.confirmationRepository = confirmationRepository; + } + + @Override + public void onActionComplete(FlowableInstance instance, FlowableNode node, FlowableAction action) { + FlowableMetadata metadata = instance.getMetadata(); + Long confirmationId = metadata.getLong("confirmationId"); + if (action == FlowableAction.APPROVE) { + confirmationRepository.updateStateById(confirmationId, Confirmation.State.NORMAL); + } else { + confirmationRepository.updateStateById(confirmationId, Confirmation.State.DRAFT); + } + } + } } diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/WareService.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/WareService.java index 4305326..e34b185 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/WareService.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/WareService.java @@ -1,21 +1,22 @@ package com.eshore.gringotts.web.domain.service; -import cn.hutool.core.util.StrUtil; +import cn.hutool.core.map.MapUtil; import com.eshore.gringotts.web.domain.base.service.CheckingService; -import com.eshore.gringotts.web.domain.entity.CheckOrder; import com.eshore.gringotts.web.domain.entity.User; import com.eshore.gringotts.web.domain.entity.Ware; +import com.eshore.gringotts.web.domain.flowable.UserAssessor; import com.eshore.gringotts.web.domain.repository.WareRepository; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.lanyuanxiaoyao.flowable.core.model.FlowableAction; +import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; +import com.lanyuanxiaoyao.flowable.core.model.FlowableListener; +import com.lanyuanxiaoyao.flowable.core.model.FlowableMetadata; +import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; +import com.lanyuanxiaoyao.flowable.jpa.SpringFlowableManager; import javax.persistence.EntityManager; -import javax.transaction.Transactional; import lombok.extern.slf4j.Slf4j; import org.eclipse.collections.api.factory.Lists; -import org.eclipse.collections.api.factory.Maps; import org.eclipse.collections.api.list.ImmutableList; -import org.eclipse.collections.api.map.ImmutableMap; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; /** @@ -23,17 +24,28 @@ import org.springframework.stereotype.Service; * @date 2024-12-13 */ @Slf4j -@Service("com.eshore.gringotts.web.domain.service.WareService") +@Service public class WareService extends CheckingService { - private final WareRepository wareRepository; - private final CheckOrderService checkOrderService; - private final ObjectMapper mapper; + private static final String WARE_FLOW_ID = "870e7376-1713-48ed-9e60-e602981c6ecc"; - public WareService(WareRepository repository, UserService userService, EntityManager entityManager, CheckOrderService checkOrderService, Jackson2ObjectMapperBuilder builder) { + private final WareRepository wareRepository; + private final UserService userService; + private final SpringFlowableManager flowableManager; + + public WareService(WareRepository repository, UserService userService, EntityManager entityManager, SpringFlowableManager flowableManager) { super(repository, userService, entityManager); this.wareRepository = repository; - this.checkOrderService = checkOrderService; - this.mapper = builder.build(); + this.userService = userService; + + this.flowableManager = flowableManager; + FlowableNode node = FlowableNode.builder() + .nodeId(WARE_FLOW_ID) + .name("上架审查") + .description("上架审查") + .listeners(Lists.mutable.of(WareService.WareFlowUserCheckListener.class.getName())) + .accessor(UserAssessor.class.getName()) + .build(); + flowableManager.create(node); } public ImmutableList listPublic() { @@ -42,59 +54,48 @@ public class WareService extends CheckingService { ); } - @Transactional(rollbackOn = Throwable.class) @Override - public void onChecked(CheckOrder order, CheckOrder.Operation operation, ImmutableMap parameters) { - if (StrUtil.equals(order.getKeyword(), "ware_check")) { - Long wareId = (Long) parameters.get("wareId"); - Ware ware = detailOrThrow(wareId); - switch (operation) { - case APPLY: - ware.setState(Ware.State.NORMAL); - order.setState(CheckOrder.State.OVER); - break; - case REJECT: - ware.setState(Ware.State.DRAFT); - order.setState(CheckOrder.State.OVER); - break; + public void submit(Long id) throws Exception { + User user = userService.currentLoginUser(); + Ware ware = detailOrThrow(id); + String instanceId = flowableManager.start( + WARE_FLOW_ID, + MapUtil.builder() + .put("wareId", id) + .put("type", "WARE") + .put("createdUsername", user.getUsername()) + .put("modifiedUsername", user.getUsername()) + .put(UserAssessor.KEY, ware.getResource().getCreatedUser().getId()) + .build(), + ware.getResource().getCreatedUser().getId().toString() + ); + wareRepository.updateInstanceIdById(id, instanceId); + wareRepository.updateStateById(id, Ware.State.CHECKING); + } + + @Override + public void retract(Long id) throws Exception { + Ware ware = detailOrThrow(id); + flowableManager.terminal(ware.getFlowableInstanceId()); + } + + @Component + public static final class WareFlowUserCheckListener extends FlowableListener.AbstractFlowableListener { + private final WareRepository wareRepository; + + public WareFlowUserCheckListener(WareRepository wareRepository) { + this.wareRepository = wareRepository; + } + + @Override + public void onActionComplete(FlowableInstance instance, FlowableNode node, FlowableAction action) { + FlowableMetadata metadata = instance.getMetadata(); + Long wareId = metadata.getLong("wareId"); + if (FlowableAction.APPROVE.equals(action)) { + wareRepository.updateStateById(wareId, Ware.State.NORMAL); + } else { + wareRepository.updateStateById(wareId, Ware.State.DRAFT); } - save(ware); - checkOrderService.save(order); } } - - @Override - public ImmutableMap archive(Ware ware) { - return null; - } - - @Transactional(rollbackOn = Throwable.class) - @Override - public void submit(Long id) throws JsonProcessingException { - Ware ware = detailOrThrow(id); - ware.setState(Ware.State.CHECKING); - Long orderId = checkOrderService.save(new CheckOrder( - "ware_check", - StrUtil.format("数据资源「{}」的上架申请", ware.getName()), - CheckOrder.Type.MARKET, - mapper.writeValueAsString(Maps.immutable.of("wareId", ware.getId())), - "com.eshore.gringotts.web.domain.service.WareService", - User.Role.CHECKER - )); - CheckOrder order = checkOrderService.detailOrThrow(orderId); - ware.setOrder(order); - save(ware); - } - - @Transactional(rollbackOn = Throwable.class) - @Override - public void retract(Long id) { - Ware ware = detailOrThrow(id); - ware.setState(Ware.State.DRAFT); - save(ware); - - CheckOrder order = ware.getOrder(); - order.setState(CheckOrder.State.RETRACT); - checkOrderService.save(order); - } }