roo00 6 лет назад
Родитель
Сommit
ee08a1282a
72 измененных файлов с 2008 добавлено и 514 удалено
  1. 5 4
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/form/FormAction.java
  2. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/querystat/ActionList.java
  3. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/queryview/ActionList.java
  4. 52 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/read/ActionListWithJob.java
  5. 60 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/read/ActionListWithWork.java
  6. 37 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/read/ReadAction.java
  7. 51 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/readcompleted/ActionListWithJob.java
  8. 60 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/readcompleted/ActionListWithWork.java
  9. 3 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/readcompleted/ActionListWithWorkOrWorkCompleted.java
  10. 36 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/readcompleted/ReadCompletedAction.java
  11. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/task/ActionEdit.java
  12. 61 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/task/ActionListWithWork.java
  13. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/task/ActionReference.java
  14. 19 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/task/TaskAction.java
  15. 51 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ActionListWithJob.java
  16. 60 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ActionListWithWork.java
  17. 3 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ActionListWithWorkOrWorkCompleted.java
  18. 36 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/TaskCompletedAction.java
  19. 15 11
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionAddSplit.java
  20. 83 17
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionGetWithWorkOrWorkCompleted.java
  21. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionManageListNext.java
  22. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionManageListPrev.java
  23. 3 3
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionReroute.java
  24. 17 7
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionRollback.java
  25. 3 3
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/BaseAction.java
  26. 27 9
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/WorkAction.java
  27. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/ActionCreate.java
  28. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/ActionManageListNext.java
  29. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/ActionManageListPrev.java
  30. 87 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/ActionRollback.java
  31. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/BaseAction.java
  32. 19 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/WorkCompletedAction.java
  33. 165 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/ActionListRollbackWithWorkOrWorkCompleted.java
  34. 16 10
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/ActionListWithWorkOrWorkCompleted.java
  35. 3 3
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/BaseAction.java
  36. 21 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/WorkLogAction.java
  37. 1 1
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Attachment.java
  38. 1 1
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Read.java
  39. 1 1
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/ReadCompleted.java
  40. 1 2
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/TaskCompleted.java
  41. 6 0
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Work.java
  42. 15 155
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/WorkCompleted.java
  43. 1 1
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/ActivityType.java
  44. 24 10
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/End.java
  45. 4 4
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/ManualMode.java
  46. 2 2
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/util/ExceptionBeginNotFound.java
  47. 92 43
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/util/WorkLogTree.java
  48. 2 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/ActionApplication.java
  49. 10 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/WorkCompletedJaxrsFilter.java
  50. 2 1
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ActionDelete.java
  51. 78 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ActionGrab.java
  52. 4 3
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ActionProcessing.java
  53. 3 2
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ActionReset.java
  54. 3 3
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ExceptionWorkNotAtManual.java
  55. 3 3
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ExceptionWorkNotGrab.java
  56. 19 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/TaskAction.java
  57. 42 32
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionAddSplit.java
  58. 0 152
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionCallback.java
  59. 248 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionRollback.java
  60. 12 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ExceptionInvalidArrivedWorkLog.java
  61. 12 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ExceptionInvalidFromWorkLog.java
  62. 0 12
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ExceptionInvalidWorkLog.java
  63. 12 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ExceptionSplittingNotRollback.java
  64. 5 5
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/WorkAction.java
  65. 251 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/workcompleted/ActionRollback.java
  66. 7 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/workcompleted/BaseAction.java
  67. 12 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/workcompleted/ExceptionSplittingNotRollback.java
  68. 50 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/workcompleted/WorkCompletedAction.java
  69. 8 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/workcompleted/package-info.java
  70. 1 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/end/EndProcessor.java
  71. 3 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/manual/ManualProcessor.java
  72. 70 0
      o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/config/ConfigAction.java

+ 5 - 4
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/form/FormAction.java

@@ -11,6 +11,7 @@ import javax.ws.rs.container.Suspended;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 
+import com.google.gson.JsonElement;
 import com.x.base.core.project.annotation.JaxrsDescribe;
 import com.x.base.core.project.annotation.JaxrsMethodDescribe;
 import com.x.base.core.project.annotation.JaxrsParameterDescribe;
@@ -36,7 +37,7 @@ public class FormAction extends StandardJaxrsAction {
 	public void getWithWorkOrWorkCompleted(@Suspended final AsyncResponse asyncResponse,
 			@Context HttpServletRequest request,
 			@JaxrsParameterDescribe("工作或完成工作标识") @PathParam("workOrWorkCompleted") String workOrWorkCompleted) {
-		ActionResult<ActionGetWithWorkOrWorkCompleted.Wo> result = new ActionResult<>();
+		ActionResult<JsonElement> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
 		try {
 			result = new ActionGetWithWorkOrWorkCompleted().execute(effectivePerson, workOrWorkCompleted);
@@ -46,16 +47,16 @@ public class FormAction extends StandardJaxrsAction {
 		}
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
-	
+
 	@JaxrsMethodDescribe(value = "根据工作或完成工作标识获取移动表单.", action = ActionGetWithWorkOrWorkCompletedMobile.class)
 	@GET
-	@Path("workorworkcompleted/{workOrWorkCompleted}")
+	@Path("workorworkcompleted/{workOrWorkCompleted}/mobile")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
 	public void getWithWorkOrWorkCompletedMobile(@Suspended final AsyncResponse asyncResponse,
 			@Context HttpServletRequest request,
 			@JaxrsParameterDescribe("工作或完成工作标识") @PathParam("workOrWorkCompleted") String workOrWorkCompleted) {
-		ActionResult<ActionGetWithWorkOrWorkCompletedMobile.Wo> result = new ActionResult<>();
+		ActionResult<JsonElement> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
 		try {
 			result = new ActionGetWithWorkOrWorkCompletedMobile().execute(effectivePerson, workOrWorkCompleted);

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/querystat/ActionList.java

@@ -57,7 +57,7 @@ class ActionList extends BaseAction {
 		if (effectivePerson.isNotManager()
 				&& (!business.organization().person().hasRole(effectivePerson.getDistinguishedName(),
 						OrganizationDefinition.ProcessPlatformManager, OrganizationDefinition.Manager))
-				&& effectivePerson.isNotUser(application.getControllerList())) {
+				&& effectivePerson.isNotPerson(application.getControllerList())) {
 			p = cb.equal(root.get(QueryStat_.creatorPerson), effectivePerson.getDistinguishedName());
 			p = cb.or(p, root.get(QueryStat_.controllerList).in(effectivePerson.getDistinguishedName()));
 			p = cb.or(p,

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/queryview/ActionList.java

@@ -67,7 +67,7 @@ class ActionList extends BaseAction {
 		if (effectivePerson.isNotManager()
 				&& (!business.organization().person().hasRole(effectivePerson,
 						OrganizationDefinition.ProcessPlatformManager, OrganizationDefinition.Manager))
-				&& effectivePerson.isNotUser(application.getControllerList())) {
+				&& effectivePerson.isNotPerson(application.getControllerList())) {
 			p = cb.equal(root.get(QueryView_.creatorPerson), effectivePerson.getDistinguishedName());
 			p = cb.or(p, root.get(QueryView_.controllerList).in(effectivePerson.getDistinguishedName()));
 			p = cb.or(p,

+ 52 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/read/ActionListWithJob.java

@@ -0,0 +1,52 @@
+package com.x.processplatform.assemble.surface.jaxrs.read;
+
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.core.entity.content.Read;
+import com.x.processplatform.core.entity.content.TaskCompleted;
+
+class ActionListWithJob extends BaseAction {
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String job) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+
+			ActionResult<List<Wo>> result = new ActionResult<>();
+
+			Business business = new Business(emc);
+
+			if (!business.readableWithJob(effectivePerson, job)) {
+				throw new ExceptionAccessDenied(effectivePerson);
+			}
+
+			List<Wo> wos = Wo.copier.copy(emc.listEqual(Read.class, Read.job_FIELDNAME, job));
+
+			wos = wos.stream().sorted(Comparator.comparing(Wo::getStartTime, Comparator.nullsLast(Date::compareTo)))
+					.collect(Collectors.toList());
+
+			result.setData(wos);
+
+			return result;
+		}
+	}
+
+	public static class Wo extends Read {
+
+		private static final long serialVersionUID = 2279846765261247910L;
+
+		static WrapCopier<Read, Wo> copier = WrapCopierFactory.wo(Read.class, Wo.class, null,
+				JpaObject.FieldsInvisible);
+
+	}
+}

+ 60 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/read/ActionListWithWork.java

@@ -0,0 +1,60 @@
+package com.x.processplatform.assemble.surface.jaxrs.read;
+
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.tools.ListTools;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.core.entity.content.Read;
+import com.x.processplatform.core.entity.content.Work;
+
+class ActionListWithWork extends BaseAction {
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String workId) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+
+			ActionResult<List<Wo>> result = new ActionResult<>();
+
+			Business business = new Business(emc);
+
+			Work work = emc.fetch(workId, Work.class, ListTools.toList(Work.job_FIELDNAME));
+
+			if (null == work) {
+				throw new ExceptionEntityNotExist(workId, Work.class);
+			}
+
+			if (!business.readableWithJob(effectivePerson, work.getJob())) {
+				throw new ExceptionAccessDenied(effectivePerson);
+			}
+
+			List<Wo> wos = Wo.copier.copy(emc.listEqual(Read.class, Read.work_FIELDNAME, workId));
+
+			wos = wos.stream().sorted(Comparator.comparing(Wo::getStartTime, Comparator.nullsLast(Date::compareTo)))
+					.collect(Collectors.toList());
+
+			result.setData(wos);
+
+			return result;
+		}
+	}
+
+	public static class Wo extends Read {
+
+		private static final long serialVersionUID = 2279846765261247910L;
+
+		static WrapCopier<Read, Wo> copier = WrapCopierFactory.wo(Read.class, Wo.class, null,
+				JpaObject.FieldsInvisible);
+
+	}
+}

+ 37 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/read/ReadAction.java

@@ -34,6 +34,43 @@ import com.x.base.core.project.logger.LoggerFactory;
 public class ReadAction extends StandardJaxrsAction {
 
 	private static Logger logger = LoggerFactory.getLogger(ReadAction.class);
+	
+	@JaxrsMethodDescribe(value = "根据job获取待阅.", action = ActionListWithJob.class)
+	@GET
+	@Path("list/job/{job}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithJob(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("任务标识") @PathParam("job") String job) {
+		ActionResult<List<ActionListWithJob.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithJob().execute(effectivePerson, job);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
+	@JaxrsMethodDescribe(value = "根据work获取待阅.", action = ActionListWithWork.class)
+	@GET
+	@Path("list/work/{work}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithWork(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("工作标识") @PathParam("work") String work) {
+		ActionResult<List<ActionListWithWork.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithWork().execute(effectivePerson, work);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+	
 
 	@JaxrsMethodDescribe(value = "列示当前用户的Read对象,下一页.", action = ActionListNext.class)
 	@GET

+ 51 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/readcompleted/ActionListWithJob.java

@@ -0,0 +1,51 @@
+package com.x.processplatform.assemble.surface.jaxrs.readcompleted;
+
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.core.entity.content.ReadCompleted;
+
+class ActionListWithJob extends BaseAction {
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String job) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+
+			ActionResult<List<Wo>> result = new ActionResult<>();
+
+			Business business = new Business(emc);
+
+			if (!business.readableWithJob(effectivePerson, job)) {
+				throw new ExceptionAccessDenied(effectivePerson);
+			}
+
+			List<Wo> wos = Wo.copier.copy(emc.listEqual(ReadCompleted.class, ReadCompleted.job_FIELDNAME, job));
+
+			wos = wos.stream().sorted(Comparator.comparing(Wo::getStartTime, Comparator.nullsLast(Date::compareTo)))
+					.collect(Collectors.toList());
+
+			result.setData(wos);
+
+			return result;
+		}
+	}
+
+	public static class Wo extends ReadCompleted {
+
+		private static final long serialVersionUID = 2279846765261247910L;
+
+		static WrapCopier<ReadCompleted, Wo> copier = WrapCopierFactory.wo(ReadCompleted.class, Wo.class, null,
+				JpaObject.FieldsInvisible);
+
+	}
+}

+ 60 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/readcompleted/ActionListWithWork.java

@@ -0,0 +1,60 @@
+package com.x.processplatform.assemble.surface.jaxrs.readcompleted;
+
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.tools.ListTools;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.core.entity.content.ReadCompleted;
+import com.x.processplatform.core.entity.content.Work;
+
+class ActionListWithWork extends BaseAction {
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String workId) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+
+			ActionResult<List<Wo>> result = new ActionResult<>();
+
+			Business business = new Business(emc);
+
+			Work work = emc.fetch(workId, Work.class, ListTools.toList(Work.job_FIELDNAME));
+
+			if (null == work) {
+				throw new ExceptionEntityNotExist(workId, Work.class);
+			}
+
+			if (!business.readableWithJob(effectivePerson, work.getJob())) {
+				throw new ExceptionAccessDenied(effectivePerson);
+			}
+
+			List<Wo> wos = Wo.copier.copy(emc.listEqual(ReadCompleted.class, ReadCompleted.work_FIELDNAME, workId));
+
+			wos = wos.stream().sorted(Comparator.comparing(Wo::getStartTime, Comparator.nullsLast(Date::compareTo)))
+					.collect(Collectors.toList());
+
+			result.setData(wos);
+
+			return result;
+		}
+	}
+
+	public static class Wo extends ReadCompleted {
+
+		private static final long serialVersionUID = 2279846765261247910L;
+
+		static WrapCopier<ReadCompleted, Wo> copier = WrapCopierFactory.wo(ReadCompleted.class, Wo.class, null,
+				JpaObject.FieldsInvisible);
+
+	}
+}

+ 3 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/readcompleted/ActionListWithWorkOrWorkCompleted.java

@@ -10,6 +10,7 @@ import com.x.base.core.entity.JpaObject;
 import com.x.base.core.project.bean.WrapCopier;
 import com.x.base.core.project.bean.WrapCopierFactory;
 import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.logger.Logger;
@@ -27,7 +28,8 @@ class ActionListWithWorkOrWorkCompleted extends BaseAction {
 
 			Business business = new Business(emc);
 
-			if (!business.readableWithWorkOrWorkCompleted(effectivePerson, workOrWorkCompleted)) {
+			if (!business.readableWithWorkOrWorkCompleted(effectivePerson, workOrWorkCompleted,
+					new ExceptionEntityNotExist(workOrWorkCompleted))) {
 				throw new ExceptionAccessDenied(effectivePerson);
 			}
 

+ 36 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/readcompleted/ReadCompletedAction.java

@@ -34,6 +34,42 @@ public class ReadCompletedAction extends StandardJaxrsAction {
 
 	private static Logger logger = LoggerFactory.getLogger(ReadCompletedAction.class);
 
+	@JaxrsMethodDescribe(value = "根据job获取已阅.", action = ActionListWithJob.class)
+	@GET
+	@Path("list/job/{job}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithJob(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("任务标识") @PathParam("job") String job) {
+		ActionResult<List<ActionListWithJob.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithJob().execute(effectivePerson, job);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
+	@JaxrsMethodDescribe(value = "根据work获取已阅.", action = ActionListWithWork.class)
+	@GET
+	@Path("list/work/{work}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithWork(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("工作标识") @PathParam("work") String work) {
+		ActionResult<List<ActionListWithWork.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithWork().execute(effectivePerson, work);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
 	@JaxrsMethodDescribe(value = "获取已阅内容,", action = ActionGet.class)
 	@GET
 	@Path("{id}")

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/task/ActionEdit.java

@@ -21,7 +21,7 @@ class ActionEdit extends BaseAction {
 			if (null == task) {
 				throw new ExceptionEntityNotExist(id, Task.class);
 			}
-			if (effectivePerson.isNotUser(task.getPerson()) && effectivePerson.isNotManager()) {
+			if (effectivePerson.isNotPerson(task.getPerson()) && effectivePerson.isNotManager()) {
 				throw new ExceptionAccessDenied(effectivePerson, task);
 			}
 			emc.beginTransaction(Task.class);

+ 61 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/task/ActionListWithWork.java

@@ -0,0 +1,61 @@
+package com.x.processplatform.assemble.surface.jaxrs.task;
+
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityFieldEmpty;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.tools.ListTools;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.core.entity.content.Task;
+import com.x.processplatform.core.entity.content.Work;
+
+class ActionListWithWork extends BaseAction {
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String workId) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+
+			ActionResult<List<Wo>> result = new ActionResult<>();
+
+			Business business = new Business(emc);
+
+			Work work = emc.fetch(workId, Work.class, ListTools.toList(Work.job_FIELDNAME));
+
+			if (null == work) {
+				throw new ExceptionEntityNotExist(workId, Work.class);
+			}
+
+			if (!business.readableWithJob(effectivePerson, work.getJob())) {
+				throw new ExceptionAccessDenied(effectivePerson);
+			}
+
+			List<Wo> wos = Wo.copier.copy(emc.listEqual(Task.class, Task.work_FIELDNAME, workId));
+
+			wos = wos.stream().sorted(Comparator.comparing(Wo::getStartTime, Comparator.nullsLast(Date::compareTo)))
+					.collect(Collectors.toList());
+
+			result.setData(wos);
+
+			return result;
+		}
+	}
+
+	public static class Wo extends Task {
+
+		private static final long serialVersionUID = 2279846765261247910L;
+
+		static WrapCopier<Task, Wo> copier = WrapCopierFactory.wo(Task.class, Wo.class, null,
+				JpaObject.FieldsInvisible);
+
+	}
+}

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/task/ActionReference.java

@@ -37,7 +37,7 @@ class ActionReference extends BaseAction {
 			if (null == task) {
 				throw new ExceptionEntityNotExist(id,Task.class);
 			}
-			if (effectivePerson.isNotUser(effectivePerson.getDistinguishedName()) && effectivePerson.isNotManager()) {
+			if (effectivePerson.isNotPerson(effectivePerson.getDistinguishedName()) && effectivePerson.isNotManager()) {
 				throw new ExceptionAccessDenied(effectivePerson, task);
 			}
 			Wo wo = new Wo();

+ 19 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/task/TaskAction.java

@@ -40,7 +40,7 @@ public class TaskAction extends StandardJaxrsAction {
 	@Path("list/job/{job}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
-	public void listNext(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+	public void listWithJob(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
 			@JaxrsParameterDescribe("任务标识") @PathParam("job") String job) {
 		ActionResult<List<ActionListWithJob.Wo>> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
@@ -53,6 +53,24 @@ public class TaskAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
 
+	@JaxrsMethodDescribe(value = "根据work获取待办.", action = ActionListWithWork.class)
+	@GET
+	@Path("list/work/{work}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithWork(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("工作标识") @PathParam("work") String work) {
+		ActionResult<List<ActionListWithWork.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithWork().execute(effectivePerson, work);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
 	@JaxrsMethodDescribe(value = "列示当前用户创建的Task对象,下一页.", action = ActionListNext.class)
 	@GET
 	@Path("list/{id}/next/{count}")

+ 51 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ActionListWithJob.java

@@ -0,0 +1,51 @@
+package com.x.processplatform.assemble.surface.jaxrs.taskcompleted;
+
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.core.entity.content.TaskCompleted;
+
+class ActionListWithJob extends BaseAction {
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String job) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+
+			ActionResult<List<Wo>> result = new ActionResult<>();
+
+			Business business = new Business(emc);
+
+			if (!business.readableWithJob(effectivePerson, job)) {
+				throw new ExceptionAccessDenied(effectivePerson);
+			}
+
+			List<Wo> wos = Wo.copier.copy(emc.listEqual(TaskCompleted.class, TaskCompleted.job_FIELDNAME, job));
+
+			wos = wos.stream().sorted(Comparator.comparing(Wo::getStartTime, Comparator.nullsLast(Date::compareTo)))
+					.collect(Collectors.toList());
+
+			result.setData(wos);
+
+			return result;
+		}
+	}
+
+	public static class Wo extends TaskCompleted {
+
+		private static final long serialVersionUID = 2279846765261247910L;
+
+		static WrapCopier<TaskCompleted, Wo> copier = WrapCopierFactory.wo(TaskCompleted.class, Wo.class, null,
+				JpaObject.FieldsInvisible);
+
+	}
+}

+ 60 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ActionListWithWork.java

@@ -0,0 +1,60 @@
+package com.x.processplatform.assemble.surface.jaxrs.taskcompleted;
+
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.tools.ListTools;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.core.entity.content.TaskCompleted;
+import com.x.processplatform.core.entity.content.Work;
+
+class ActionListWithWork extends BaseAction {
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String workId) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+
+			ActionResult<List<Wo>> result = new ActionResult<>();
+
+			Business business = new Business(emc);
+
+			Work work = emc.fetch(workId, Work.class, ListTools.toList(Work.job_FIELDNAME));
+
+			if (null == work) {
+				throw new ExceptionEntityNotExist(workId, Work.class);
+			}
+
+			if (!business.readableWithJob(effectivePerson, work.getJob())) {
+				throw new ExceptionAccessDenied(effectivePerson);
+			}
+
+			List<Wo> wos = Wo.copier.copy(emc.listEqual(TaskCompleted.class, TaskCompleted.work_FIELDNAME, workId));
+
+			wos = wos.stream().sorted(Comparator.comparing(Wo::getStartTime, Comparator.nullsLast(Date::compareTo)))
+					.collect(Collectors.toList());
+
+			result.setData(wos);
+
+			return result;
+		}
+	}
+
+	public static class Wo extends TaskCompleted {
+
+		private static final long serialVersionUID = 2279846765261247910L;
+
+		static WrapCopier<TaskCompleted, Wo> copier = WrapCopierFactory.wo(TaskCompleted.class, Wo.class, null,
+				JpaObject.FieldsInvisible);
+
+	}
+}

+ 3 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ActionListWithWorkOrWorkCompleted.java

@@ -10,6 +10,7 @@ import com.x.base.core.entity.JpaObject;
 import com.x.base.core.project.bean.WrapCopier;
 import com.x.base.core.project.bean.WrapCopierFactory;
 import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.logger.Logger;
@@ -27,7 +28,8 @@ class ActionListWithWorkOrWorkCompleted extends BaseAction {
 
 			Business business = new Business(emc);
 
-			if (!business.readableWithWorkOrWorkCompleted(effectivePerson, workOrWorkCompleted)) {
+			if (!business.readableWithWorkOrWorkCompleted(effectivePerson, workOrWorkCompleted,
+					new ExceptionEntityNotExist(workOrWorkCompleted))) {
 				throw new ExceptionAccessDenied(effectivePerson);
 			}
 

+ 36 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/TaskCompletedAction.java

@@ -35,6 +35,42 @@ public class TaskCompletedAction extends StandardJaxrsAction {
 
 	private static Logger logger = LoggerFactory.getLogger(TaskCompletedAction.class);
 
+	@JaxrsMethodDescribe(value = "根据job获取已办.", action = ActionListWithJob.class)
+	@GET
+	@Path("list/job/{job}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithJob(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("任务标识") @PathParam("job") String job) {
+		ActionResult<List<ActionListWithJob.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithJob().execute(effectivePerson, job);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
+	@JaxrsMethodDescribe(value = "根据work获取已办.", action = ActionListWithWork.class)
+	@GET
+	@Path("list/work/{work}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithWork(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("工作标识") @PathParam("work") String work) {
+		ActionResult<List<ActionListWithWork.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithWork().execute(effectivePerson, work);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+	
 	@JaxrsMethodDescribe(value = "获取已办内容,", action = ActionGet.class)
 	@GET
 	@Path("{id}")

+ 15 - 11
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionAddSplit.java

@@ -25,6 +25,7 @@ import com.x.processplatform.core.entity.content.WorkLog;
 import com.x.processplatform.core.entity.element.ActivityType;
 import com.x.processplatform.core.entity.element.Manual;
 import com.x.processplatform.core.entity.element.util.WorkLogTree;
+import com.x.processplatform.core.entity.element.util.WorkLogTree.Node;
 
 class ActionAddSplit extends BaseAction {
 
@@ -56,21 +57,24 @@ class ActionAddSplit extends BaseAction {
 			}
 			WorkLogTree tree = new WorkLogTree(workLogs);
 			WorkLogTree.Node currentNode = tree.find(currentWorkLog);
-			WorkLogTree.Node upSplitNode = currentNode.upTo(ActivityType.split, ActivityType.message,
-					ActivityType.condition, ActivityType.invoke, ActivityType.embed);
-			if (null == upSplitNode) {
-				throw new ExceptionUpSplitNotFound(work.getId());
-			}
 
-			WorkLogTree.Node upManualNode = upSplitNode.upTo(ActivityType.manual, ActivityType.message,
-					ActivityType.condition, ActivityType.invoke, ActivityType.embed);
-			if (null == upManualNode) {
+			WorkLogTree.Nodes upManualNodes = currentNode.upTo(ActivityType.manual, ActivityType.agent,
+					ActivityType.choice, ActivityType.delay, ActivityType.delay, ActivityType.embed,
+					ActivityType.invoke, ActivityType.message, ActivityType.parallel, ActivityType.service,
+					ActivityType.split);
+
+			if (upManualNodes.isEmpty()) {
 				throw new ExceptionUpManualNotFound(work.getId());
 			}
 
-			if (emc.countEqualAndEqual(TaskCompleted.class, TaskCompleted.person_FIELDNAME,
-					effectivePerson.getDistinguishedName(), TaskCompleted.activityToken_FIELDNAME,
-					upManualNode.getWorkLog().getFromActivityToken()) < 1) {
+			for (WorkLogTree.Node o : upManualNodes) {
+
+				if (emc.countEqualAndEqual(TaskCompleted.class, TaskCompleted.person_FIELDNAME,
+						effectivePerson.getDistinguishedName(), TaskCompleted.activityToken_FIELDNAME,
+						o.getWorkLog().getFromActivityToken()) > 0) {
+					break;
+				}
+
 				throw new ExceptionAccessDenied(effectivePerson);
 			}
 

+ 83 - 17
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionGetWithWorkOrWorkCompleted.java

@@ -1,6 +1,7 @@
 package com.x.processplatform.assemble.surface.jaxrs.work;
 
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 
 import javax.persistence.EntityManager;
@@ -14,9 +15,12 @@ import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.entity.JpaObject;
 import com.x.base.core.entity.dataitem.ItemCategory;
+import com.x.base.core.project.Applications;
+import com.x.base.core.project.x_processplatform_service_processing;
 import com.x.base.core.project.bean.WrapCopier;
 import com.x.base.core.project.bean.WrapCopierFactory;
 import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.gson.GsonPropertyObject;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
@@ -24,12 +28,15 @@ import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 import com.x.base.core.project.tools.ListTools;
 import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.assemble.surface.ThisApplication;
+import com.x.processplatform.assemble.surface.jaxrs.work.ActionAddSplit.Wo;
 import com.x.processplatform.core.entity.content.Data;
 import com.x.processplatform.core.entity.content.Read;
 import com.x.processplatform.core.entity.content.Task;
 import com.x.processplatform.core.entity.content.Work;
 import com.x.processplatform.core.entity.content.WorkCompleted;
 import com.x.processplatform.core.entity.element.Activity;
+import com.x.processplatform.core.entity.element.ManualMode;
 import com.x.query.core.entity.Item;
 import com.x.query.core.entity.Item_;
 
@@ -41,7 +48,8 @@ class ActionGetWithWorkOrWorkCompleted extends BaseAction {
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 			ActionResult<Wo> result = new ActionResult<>();
 			Business business = new Business(emc);
-			if (!business.readableWithWorkOrWorkCompleted(effectivePerson, workOrWorkCompleted)) {
+			if (!business.readableWithWorkOrWorkCompleted(effectivePerson, workOrWorkCompleted,
+					new ExceptionEntityNotExist(workOrWorkCompleted))) {
 				throw new ExceptionAccessDenied(effectivePerson);
 			}
 			Wo wo = null;
@@ -64,7 +72,7 @@ class ActionGetWithWorkOrWorkCompleted extends BaseAction {
 			return this.data(business, work.getJob());
 		});
 		CompletableFuture<List<WoTask>> future_task = CompletableFuture.supplyAsync(() -> {
-			return this.tasks(business, work.getJob());
+			return this.tasks(business, work.getId());
 		});
 		CompletableFuture<List<WoRead>> future_read = CompletableFuture.supplyAsync(() -> {
 			return this.reads(business, work.getJob());
@@ -121,16 +129,17 @@ class ActionGetWithWorkOrWorkCompleted extends BaseAction {
 
 	private List<WoTask> tasks(Business business, String workId) {
 		try {
-			return business.entityManagerContainer().fetchEqual(Task.class, WoTask.copier, Task.work_FIELDNAME, workId);
+			return WoTask.copier
+					.copy(business.entityManagerContainer().listEqual(Task.class, Task.work_FIELDNAME, workId));
 		} catch (Exception e) {
 			logger.error(e);
 		}
 		return null;
 	}
 
-	private List<WoRead> reads(Business business, String workId) {
+	private List<WoRead> reads(Business business, String job) {
 		try {
-			return business.entityManagerContainer().fetchEqual(Read.class, WoRead.copier, Read.work_FIELDNAME, workId);
+			return WoRead.copier.copy(business.entityManagerContainer().listEqual(Read.class, Read.job_FIELDNAME, job));
 		} catch (Exception e) {
 			logger.error(e);
 		}
@@ -141,27 +150,44 @@ class ActionGetWithWorkOrWorkCompleted extends BaseAction {
 		WoActivity woActivity = new WoActivity();
 		Activity activity = business.getActivity(work);
 		if (null != activity) {
-			woActivity = WoActivity.copier.copy(activity);
+			activity.copyTo(woActivity);
 		}
 		return woActivity;
 	}
 
 	private void setCurrentTaskIndex(EffectivePerson effectivePerson, Wo wo) {
-		for (int i = 0; i < wo.getTaskList().size(); i++) {
-			if (effectivePerson.isUser(wo.getTaskList().get(i).getPerson())) {
-				wo.setCurrentTaskIndex(i);
+		int loop = 0;
+		for (WoTask task : wo.getTaskList()) {
+			if (effectivePerson.isPerson(task.getPerson())) {
+				wo.setCurrentTaskIndex(loop);
+				/* 发送抢办信号 */
+				if (Objects.equals(ManualMode.grab, wo.getActivity().getManualMode())) {
+					CompletableFuture.runAsync(() -> {
+						try {
+							ThisApplication.context().applications().getQuery(
+									x_processplatform_service_processing.class,
+									Applications.joinQueryUri("task", task.getId(), "grab"));
+						} catch (Exception e) {
+							logger.error(e);
+						}
+					});
+				}
 				break;
 			}
+			loop++;
 		}
 	}
 
 	private void setCurrentReadIndex(EffectivePerson effectivePerson, Wo wo) {
-		for (int i = 0; i < wo.getReadList().size(); i++) {
-			if (effectivePerson.isUser(wo.getReadList().get(i).getPerson())) {
-				wo.setCurrentReadIndex(i);
+		int loop = 0;
+		for (WoRead read : wo.getReadList()) {
+			if (effectivePerson.isPerson(read.getPerson())) {
+				wo.setCurrentReadIndex(loop);
 				break;
 			}
+			loop++;
 		}
+
 	}
 
 	public static class Wo extends GsonPropertyObject {
@@ -180,7 +206,7 @@ class ActionGetWithWorkOrWorkCompleted extends BaseAction {
 		/* 只有work有 */
 		private List<WoTask> taskList;
 		/* 只有work有 */
-		private Integer currentTaskIndex;
+		private Integer currentTaskIndex = -1;
 
 		public JsonElement getWork() {
 			return work;
@@ -262,8 +288,8 @@ class ActionGetWithWorkOrWorkCompleted extends BaseAction {
 
 		private static final long serialVersionUID = 5244996549744746585L;
 
-		static WrapCopier<Task, WoTask> copier = WrapCopierFactory.wo(Task.class, WoTask.class,
-				JpaObject.singularAttributeField(Task.class, true, true), JpaObject.FieldsInvisible);
+		static WrapCopier<Task, WoTask> copier = WrapCopierFactory.wo(Task.class, WoTask.class, null,
+				JpaObject.FieldsInvisible);
 
 	}
 
@@ -271,8 +297,8 @@ class ActionGetWithWorkOrWorkCompleted extends BaseAction {
 
 		private static final long serialVersionUID = 5244996549744746585L;
 
-		static WrapCopier<Read, WoRead> copier = WrapCopierFactory.wo(Read.class, WoRead.class,
-				JpaObject.singularAttributeField(Read.class, true, true), JpaObject.FieldsInvisible);
+		static WrapCopier<Read, WoRead> copier = WrapCopierFactory.wo(Read.class, WoRead.class, null,
+				JpaObject.FieldsInvisible);
 
 	}
 
@@ -291,6 +317,14 @@ class ActionGetWithWorkOrWorkCompleted extends BaseAction {
 
 		private String position;
 
+		private String resetRange;
+
+		private Integer resetCount;
+
+		private Boolean allowReset;
+
+		private ManualMode manualMode;
+
 		public String getName() {
 			return name;
 		}
@@ -331,6 +365,38 @@ class ActionGetWithWorkOrWorkCompleted extends BaseAction {
 			this.id = id;
 		}
 
+		public String getResetRange() {
+			return resetRange;
+		}
+
+		public void setResetRange(String resetRange) {
+			this.resetRange = resetRange;
+		}
+
+		public Integer getResetCount() {
+			return resetCount;
+		}
+
+		public void setResetCount(Integer resetCount) {
+			this.resetCount = resetCount;
+		}
+
+		public Boolean getAllowReset() {
+			return allowReset;
+		}
+
+		public void setAllowReset(Boolean allowReset) {
+			this.allowReset = allowReset;
+		}
+
+		public ManualMode getManualMode() {
+			return manualMode;
+		}
+
+		public void setManualMode(ManualMode manualMode) {
+			this.manualMode = manualMode;
+		}
+
 	}
 
 }

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionManageListNext.java

@@ -35,7 +35,7 @@ class ActionManageListNext extends BaseAction {
 			if (effectivePerson.isManager()
 					|| business.organization().person().hasRole(effectivePerson,
 							OrganizationDefinition.ProcessPlatformManager, OrganizationDefinition.Manager)
-					|| effectivePerson.isUser(application.getControllerList())) {
+					|| effectivePerson.isPerson(application.getControllerList())) {
 				EqualsTerms equalsTerms = new EqualsTerms();
 				equalsTerms.put("application", application.getId());
 				result = this.standardListNext(Wo.copier, id, count,  JpaObject.sequence_FIELDNAME, equalsTerms, null, null, null, null,

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionManageListPrev.java

@@ -35,7 +35,7 @@ class ActionManageListPrev extends BaseAction {
 			if (effectivePerson.isManager()
 					|| business.organization().person().hasRole(effectivePerson,
 							OrganizationDefinition.ProcessPlatformManager, OrganizationDefinition.Manager)
-					|| effectivePerson.isUser(application.getControllerList())) {
+					|| effectivePerson.isPerson(application.getControllerList())) {
 				EqualsTerms equalsTerms = new EqualsTerms();
 				equalsTerms.put("application", application.getId());
 				result = this.standardListPrev(Wo.copier, id, count,  JpaObject.sequence_FIELDNAME, equalsTerms, null, null, null, null,

+ 3 - 3
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionReroute.java

@@ -212,7 +212,7 @@ class ActionReroute extends BaseAction {
 		if ((null != task) || (null != read) || (taskCompletedCount > 0) || (readCompletedCount > 0)
 				|| (reviewCount > 0)) {
 			control.setAllowVisit(true);
-		} else if (effectivePerson.isUser(work.getCreatorPerson())) {
+		} else if (effectivePerson.isPerson(work.getCreatorPerson())) {
 			control.setAllowVisit(true);
 		} else if (business.canManageApplicationOrProcess(effectivePerson, application, process)) {
 			control.setAllowVisit(true);
@@ -265,10 +265,10 @@ class ActionReroute extends BaseAction {
 			control.setAllowReroute(true);
 		} else if (BooleanUtils.isTrue(activity.getAllowReroute())) {
 			/** 如果活动设置了可以调度 */
-			if ((null != process) && effectivePerson.isUser(process.getControllerList())) {
+			if ((null != process) && effectivePerson.isPerson(process.getControllerList())) {
 				/** 如果是流程的管理员那么可以调度 */
 				control.setAllowReroute(true);
-			} else if ((null != application) && effectivePerson.isUser(application.getControllerList())) {
+			} else if ((null != application) && effectivePerson.isPerson(application.getControllerList())) {
 				/** 如果是应用的管理员那么可以调度 */
 				control.setAllowReroute(true);
 			}

+ 17 - 7
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionCallback.java → o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionRollback.java

@@ -18,7 +18,7 @@ import com.x.processplatform.core.entity.content.Work;
 import com.x.processplatform.core.entity.element.Application;
 import com.x.processplatform.core.entity.element.Process;
 
-class ActionCallback extends BaseAction {
+class ActionRollback extends BaseAction {
 
 	ActionResult<Wo> execute(EffectivePerson effectivePerson, String id, JsonElement jsonElement) throws Exception {
 
@@ -31,15 +31,25 @@ class ActionCallback extends BaseAction {
 			if (null == work) {
 				throw new ExceptionEntityNotExist(id, Work.class);
 			}
+
 			Application application = business.application().pick(work.getApplication());
+
+			if (null == application) {
+				throw new ExceptionEntityNotExist(work.getApplication(), Application.class);
+			}
+
 			Process process = business.process().pick(work.getProcess());
 
+			if (null == process) {
+				throw new ExceptionEntityNotExist(work.getProcess(), Process.class);
+			}
+
 			if (!business.canManageApplicationOrProcess(effectivePerson, application, process)) {
 				throw new ExceptionAccessDenied(effectivePerson);
 			}
 
 			Wo wo = ThisApplication.context().applications().putQuery(x_processplatform_service_processing.class,
-					Applications.joinQueryUri("work", work.getId(), "add", "split"), wi).getData(Wo.class);
+					Applications.joinQueryUri("work", work.getId(), "rollback"), wi).getData(Wo.class);
 
 			result.setData(wo);
 			return result;
@@ -49,14 +59,14 @@ class ActionCallback extends BaseAction {
 
 	public static class Wi extends GsonPropertyObject {
 
-		private String workLogId;
+		private String workLog;
 
-		public String getWorkLogId() {
-			return workLogId;
+		public String getWorkLog() {
+			return workLog;
 		}
 
-		public void setWorkLogId(String workLogId) {
-			this.workLogId = workLogId;
+		public void setWorkLog(String workLog) {
+			this.workLog = workLog;
 		}
 
 	}

+ 3 - 3
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/BaseAction.java

@@ -786,7 +786,7 @@ abstract class BaseAction extends StandardJaxrsAction {
 						.count() > 0)
 				|| (reviewCount > 0)) {
 			control.setAllowVisit(true);
-		} else if (effectivePerson.isUser(work.getCreatorPerson())) {
+		} else if (effectivePerson.isPerson(work.getCreatorPerson())) {
 			control.setAllowVisit(true);
 		} else if (business.canManageApplicationOrProcess(effectivePerson, application, process)) {
 			control.setAllowVisit(true);
@@ -847,10 +847,10 @@ abstract class BaseAction extends StandardJaxrsAction {
 					OrganizationDefinition.ProcessPlatformManager)) {
 				/** 有流程管理角色的可以 */
 				control.setAllowReroute(true);
-			} else if ((null != process) && effectivePerson.isUser(process.getControllerList())) {
+			} else if ((null != process) && effectivePerson.isPerson(process.getControllerList())) {
 				/** 如果是流程的管理员那么可以调度 */
 				control.setAllowReroute(true);
-			} else if ((null != application) && effectivePerson.isUser(application.getControllerList())) {
+			} else if ((null != application) && effectivePerson.isPerson(application.getControllerList())) {
 				/** 如果是应用的管理员那么可以调度 */
 				control.setAllowReroute(true);
 			}

+ 27 - 9
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/WorkAction.java

@@ -468,6 +468,26 @@ public class WorkAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
 
+	@JaxrsMethodDescribe(value = "将工作召回。", action = ActionReroute.class)
+	@PUT
+	@Path("{id}/reroute/activity/{activityId}/activitytype/{activityType}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void reroute(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("工作标识") @PathParam("id") String id,
+			@JaxrsParameterDescribe("活动标识") @PathParam("activityId") String activityId,
+			@JaxrsParameterDescribe("活动类型") @PathParam("activityType") ActivityType activityType) {
+		ActionResult<ActionReroute.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionReroute().execute(effectivePerson, id, activityId, activityType);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
 	@JaxrsMethodDescribe(value = "增加一个会签分支", action = ActionAddSplit.class)
 	@PUT
 	@Path("{id}/add/split")
@@ -486,21 +506,19 @@ public class WorkAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
 
-	@JaxrsMethodDescribe(value = "将工作召回。", action = ActionReroute.class)
+	@JaxrsMethodDescribe(value = "回滚工作到指定的workLog", action = ActionRollback.class)
 	@PUT
-	@Path("{id}/reroute/activity/{activityId}/activitytype/{activityType}")
+	@Path("{id}/rollback")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
-	public void reroute(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
-			@JaxrsParameterDescribe("工作标识") @PathParam("id") String id,
-			@JaxrsParameterDescribe("活动标识") @PathParam("activityId") String activityId,
-			@JaxrsParameterDescribe("活动类型") @PathParam("activityType") ActivityType activityType) {
-		ActionResult<ActionReroute.Wo> result = new ActionResult<>();
+	public void rollback(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("工作标识") @PathParam("id") String id, JsonElement jsonElement) {
+		ActionResult<ActionRollback.Wo> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
 		try {
-			result = new ActionReroute().execute(effectivePerson, id, activityId, activityType);
+			result = new ActionRollback().execute(effectivePerson, id, jsonElement);
 		} catch (Exception e) {
-			logger.error(e, effectivePerson, request, null);
+			logger.error(e, effectivePerson, request, jsonElement);
 			result.error(e);
 		}
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/ActionCreate.java

@@ -52,7 +52,7 @@ class ActionCreate extends BaseAction {
 			if ((effectivePerson.isNotManager())
 					&& (!business.organization().person().hasRole(effectivePerson,
 							OrganizationDefinition.ProcessPlatformManager, OrganizationDefinition.Manager))
-					&& effectivePerson.isNotUser(application.getControllerList())) {
+					&& effectivePerson.isNotPerson(application.getControllerList())) {
 				throw new ExceptionAccessDenied(effectivePerson);
 			}
 			emc.beginTransaction(Item.class);

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/ActionManageListNext.java

@@ -36,7 +36,7 @@ class ActionManageListNext extends BaseAction {
 			if (effectivePerson.isManager()
 					|| business.organization().person().hasRole(effectivePerson,
 							OrganizationDefinition.ProcessPlatformManager, OrganizationDefinition.Manager)
-					|| effectivePerson.isUser(application.getControllerList())) {
+					|| effectivePerson.isPerson(application.getControllerList())) {
 				EqualsTerms equalsTerms = new EqualsTerms();
 				equalsTerms.put("application", application.getId());
 				result = this.standardListNext(Wo.copier, id, count,  JpaObject.sequence_FIELDNAME, equalsTerms, null, null, null, null,

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/ActionManageListPrev.java

@@ -36,7 +36,7 @@ class ActionManageListPrev extends BaseAction {
 			if (effectivePerson.isManager()
 					|| business.organization().person().hasRole(effectivePerson,
 							OrganizationDefinition.ProcessPlatformManager, OrganizationDefinition.Manager)
-					|| effectivePerson.isUser(application.getControllerList())) {
+					|| effectivePerson.isPerson(application.getControllerList())) {
 				EqualsTerms equalsTerms = new EqualsTerms();
 				equalsTerms.put("application", application.getId());
 				result = this.standardListPrev(Wo.copier, id, count,  JpaObject.sequence_FIELDNAME, equalsTerms, null, null, null, null,

+ 87 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/ActionRollback.java

@@ -0,0 +1,87 @@
+package com.x.processplatform.assemble.surface.jaxrs.workcompleted;
+
+import com.google.gson.JsonElement;
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.Applications;
+import com.x.base.core.project.x_processplatform_service_processing;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.gson.GsonPropertyObject;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WoId;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.assemble.surface.ThisApplication;
+import com.x.processplatform.core.entity.content.WorkCompleted;
+import com.x.processplatform.core.entity.content.WorkLog;
+import com.x.processplatform.core.entity.element.Application;
+import com.x.processplatform.core.entity.element.Process;
+
+class ActionRollback extends BaseAction {
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, String flag, JsonElement jsonElement) throws Exception {
+
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			ActionResult<Wo> result = new ActionResult<>();
+			Business business = new Business(emc);
+			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
+
+			WorkCompleted workCompleted = emc.flag(flag, WorkCompleted.class);
+			if (null == workCompleted) {
+				throw new ExceptionEntityNotExist(flag, WorkCompleted.class);
+			}
+
+			Application application = business.application().pick(workCompleted.getApplication());
+
+			Process process = business.process().pick(workCompleted.getProcess());
+
+			if (null == application) {
+				throw new ExceptionEntityNotExist(workCompleted.getApplication(), Application.class);
+			}
+
+			if (null == process) {
+				throw new ExceptionEntityNotExist(workCompleted.getProcess(), Process.class);
+			}
+
+			if (!business.canManageApplicationOrProcess(effectivePerson, application, process)) {
+				throw new ExceptionAccessDenied(effectivePerson);
+			}
+
+			WorkLog workLog = emc.find(wi.getWorkLog(), WorkLog.class);
+
+			if (null == workLog) {
+				throw new ExceptionEntityNotExist(wi.getWorkLog(), WorkLog.class);
+			}
+
+			Wo wo = ThisApplication.context().applications()
+					.putQuery(x_processplatform_service_processing.class,
+							Applications.joinQueryUri("workcompleted", workCompleted.getId(), "rollback"), wi)
+					.getData(Wo.class);
+
+			result.setData(wo);
+			return result;
+
+		}
+	}
+
+	public static class Wi extends GsonPropertyObject {
+
+		@FieldDescribe("工作日志")
+		private String workLog;
+
+		public String getWorkLog() {
+			return workLog;
+		}
+
+		public void setWorkLog(String workLog) {
+			this.workLog = workLog;
+		}
+
+	}
+
+	public static class Wo extends WoId {
+	}
+
+}

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/BaseAction.java

@@ -489,7 +489,7 @@ abstract class BaseAction extends StandardJaxrsAction {
 						.count() > 0)
 				|| (reviewCount > 0)) {
 			control.setAllowVisit(true);
-		} else if (effectivePerson.isUser(workCompleted.getCreatorPerson())) {
+		} else if (effectivePerson.isPerson(workCompleted.getCreatorPerson())) {
 			control.setAllowVisit(true);
 		} else if (business.canManageApplicationOrProcess(effectivePerson, application, process)) {
 			control.setAllowVisit(true);

+ 19 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/workcompleted/WorkCompletedAction.java

@@ -9,6 +9,7 @@ import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -500,4 +501,22 @@ public class WorkCompletedAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
 
+	@PUT
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	@Path("{flag}/rollback")
+	@JaxrsMethodDescribe(value = "完成工作重新回滚.", action = ActionRollback.class)
+	public void rollback(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("流程标识") @PathParam("flag") String flag, JsonElement jsonElement) {
+		ActionResult<ActionRollback.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionRollback().execute(effectivePerson, flag, jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, jsonElement);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
 }

+ 165 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/ActionListRollbackWithWorkOrWorkCompleted.java

@@ -0,0 +1,165 @@
+package com.x.processplatform.assemble.surface.jaxrs.worklog;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang.BooleanUtils;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.ListTools;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.core.entity.content.Task;
+import com.x.processplatform.core.entity.content.TaskCompleted;
+import com.x.processplatform.core.entity.content.WorkLog;
+import com.x.processplatform.core.entity.element.ActivityType;
+
+class ActionListRollbackWithWorkOrWorkCompleted extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionListRollbackWithWorkOrWorkCompleted.class);
+
+	private final static String taskCompletedList_FIELDNAME = "taskCompletedList";
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String workOrWorkCompleted) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			ActionResult<List<Wo>> result = new ActionResult<>();
+
+			Business business = new Business(emc);
+
+			if (!business.readableWithWorkOrWorkCompleted(effectivePerson, workOrWorkCompleted,
+					new ExceptionEntityNotExist(workOrWorkCompleted))) {
+				throw new ExceptionAccessDenied(effectivePerson);
+			}
+
+			final String job = business.job().findWithWorkOrWorkCompleted(workOrWorkCompleted);
+
+			CompletableFuture<List<WoTaskCompleted>> future_taskCompleteds = CompletableFuture.supplyAsync(() -> {
+				return this.taskCompleteds(business, job);
+			});
+
+			CompletableFuture<List<Wo>> future_workLogs = CompletableFuture.supplyAsync(() -> {
+				return this.workLogs(business, job);
+			});
+			List<WoTaskCompleted> taskCompleteds = future_taskCompleteds.get();
+			List<Wo> wos = future_workLogs.get();
+			ListTools.groupStick(wos, taskCompleteds, WorkLog.fromActivityToken_FIELDNAME,
+					TaskCompleted.activityToken_FIELDNAME, taskCompletedList_FIELDNAME);
+			result.setData(wos);
+			return result;
+		}
+	}
+
+	private List<WoTaskCompleted> taskCompleteds(Business business, String job) {
+		List<WoTaskCompleted> os = new ArrayList<>();
+		try {
+			os = business.entityManagerContainer()
+					.fetchEqual(TaskCompleted.class, WoTaskCompleted.copier, TaskCompleted.job_FIELDNAME, job).stream()
+					.sorted(Comparator.comparing(TaskCompleted::getStartTime, Comparator.nullsLast(Date::compareTo)))
+					.collect(Collectors.toList());
+		} catch (Exception e) {
+			logger.error(e);
+		}
+		return os;
+	}
+
+	private List<Wo> workLogs(Business business, String job) {
+		List<Wo> os = new ArrayList<>();
+		try {
+			os = business.entityManagerContainer().fetchEqual(WorkLog.class, Wo.copier, WorkLog.job_FIELDNAME, job)
+					.stream()
+					.filter(o -> (!BooleanUtils.isTrue(o.getSplitting()))
+							&& (Objects.equals(o.getArrivedActivityType(), ActivityType.manual)))
+					.sorted(Comparator.comparing(WorkLog::getCreateTime, Comparator.nullsLast(Date::compareTo)))
+					.collect(Collectors.toList());
+		} catch (Exception e) {
+			logger.error(e);
+		}
+		return os;
+	}
+
+	public static class Wo extends WorkLog {
+
+		private static final long serialVersionUID = -7666329770246726197L;
+
+		static WrapCopier<WorkLog, Wo> copier = WrapCopierFactory.wo(WorkLog.class, Wo.class,
+				ListTools.toList(WorkLog.id_FIELDNAME, WorkLog.fromActivity_FIELDNAME,
+						WorkLog.fromActivityType_FIELDNAME, WorkLog.fromActivityName_FIELDNAME,
+						WorkLog.fromActivityAlias_FIELDNAME, WorkLog.fromActivityToken_FIELDNAME,
+						WorkLog.fromTime_FIELDNAME, WorkLog.arrivedActivity_FIELDNAME,
+						WorkLog.arrivedActivityType_FIELDNAME, WorkLog.arrivedActivityName_FIELDNAME,
+						WorkLog.arrivedActivityAlias_FIELDNAME, WorkLog.arrivedActivityToken_FIELDNAME,
+						WorkLog.arrivedTime_FIELDNAME, WorkLog.routeName_FIELDNAME, WorkLog.connected_FIELDNAME,
+						WorkLog.splitting_FIELDNAME),
+				JpaObject.FieldsInvisible);
+
+		private List<WoTask> taskList = new ArrayList<>();
+
+		private List<WoTaskCompleted> taskCompletedList = new ArrayList<>();
+
+		private List<WoRead> readList = new ArrayList<>();
+
+		private List<WoReadCompleted> readCompletedList = new ArrayList<>();
+
+		public List<WoTask> getTaskList() {
+			return taskList;
+		}
+
+		public void setTaskList(List<WoTask> taskList) {
+			this.taskList = taskList;
+		}
+
+		public List<WoTaskCompleted> getTaskCompletedList() {
+			return taskCompletedList;
+		}
+
+		public void setTaskCompletedList(List<WoTaskCompleted> taskCompletedList) {
+			this.taskCompletedList = taskCompletedList;
+		}
+
+		public List<WoRead> getReadList() {
+			return readList;
+		}
+
+		public void setReadList(List<WoRead> readList) {
+			this.readList = readList;
+		}
+
+		public List<WoReadCompleted> getReadCompletedList() {
+			return readCompletedList;
+		}
+
+		public void setReadCompletedList(List<WoReadCompleted> readCompletedList) {
+			this.readCompletedList = readCompletedList;
+		}
+
+	}
+
+	public static class WoTaskCompleted extends TaskCompleted {
+
+		private static final long serialVersionUID = -4432508672641778924L;
+
+		static WrapCopier<TaskCompleted, WoTaskCompleted> copier = WrapCopierFactory.wo(TaskCompleted.class,
+				WoTaskCompleted.class,
+				ListTools.toList(TaskCompleted.id_FIELDNAME, TaskCompleted.person_FIELDNAME,
+						TaskCompleted.unit_FIELDNAME, TaskCompleted.routeName_FIELDNAME,
+						TaskCompleted.opinion_FIELDNAME, TaskCompleted.startTime_FIELDNAME,
+						TaskCompleted.activityName_FIELDNAME, TaskCompleted.completedTime_FIELDNAME,
+						Task.activityToken_FIELDNAME),
+				null);
+	}
+
+}

+ 16 - 10
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/ActionListWithWorkOrWorkCompleted.java

@@ -7,12 +7,15 @@ import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
+import org.apache.commons.lang.BooleanUtils;
+
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.entity.JpaObject;
 import com.x.base.core.project.bean.WrapCopier;
 import com.x.base.core.project.bean.WrapCopierFactory;
 import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.logger.Logger;
@@ -45,7 +48,8 @@ class ActionListWithWorkOrWorkCompleted extends BaseAction {
 
 			Business business = new Business(emc);
 
-			if (!business.readableWithWorkOrWorkCompleted(effectivePerson, workOrWorkCompleted)) {
+			if (!business.readableWithWorkOrWorkCompleted(effectivePerson, workOrWorkCompleted,
+					new ExceptionEntityNotExist(workOrWorkCompleted))) {
 				throw new ExceptionAccessDenied(effectivePerson);
 			}
 
@@ -55,7 +59,7 @@ class ActionListWithWorkOrWorkCompleted extends BaseAction {
 				return this.tasks(business, job);
 			});
 			CompletableFuture<List<WoTaskCompleted>> future_taskCompleteds = CompletableFuture.supplyAsync(() -> {
-				return this.taskCompleted(business, job);
+				return this.taskCompleteds(business, job);
 			});
 			CompletableFuture<List<WoRead>> future_reads = CompletableFuture.supplyAsync(() -> {
 				return this.reads(business, job);
@@ -96,7 +100,7 @@ class ActionListWithWorkOrWorkCompleted extends BaseAction {
 		return os;
 	}
 
-	private List<WoTaskCompleted> taskCompleted(Business business, String job) {
+	private List<WoTaskCompleted> taskCompleteds(Business business, String job) {
 		List<WoTaskCompleted> os = new ArrayList<>();
 		try {
 			os = business.entityManagerContainer()
@@ -137,9 +141,10 @@ class ActionListWithWorkOrWorkCompleted extends BaseAction {
 	private List<Wo> workLogs(Business business, String job) {
 		List<Wo> os = new ArrayList<>();
 		try {
-			os = business.entityManagerContainer().fetchEqual(WorkLog.class, Wo.copier, WorkLog.job_FIELDNAME, job)
-					.stream()
-					.sorted(Comparator.comparing(WorkLog::getCreateTime, Comparator.nullsLast(Date::compareTo)))
+			os = business.entityManagerContainer().fetchEqual(WorkLog.class, Wo.copier, WorkLog.job_FIELDNAME, job);
+			return os.stream()
+					.sorted(Comparator.comparing(Wo::getFromTime, Comparator.nullsLast(Date::compareTo))
+							.thenComparing(Wo::getArrivedTime, Comparator.nullsLast(Date::compareTo)))
 					.collect(Collectors.toList());
 		} catch (Exception e) {
 			logger.error(e);
@@ -211,7 +216,7 @@ class ActionListWithWorkOrWorkCompleted extends BaseAction {
 		static WrapCopier<Task, WoTask> copier = WrapCopierFactory.wo(Task.class, WoTask.class,
 				ListTools.toList(Task.id_FIELDNAME, Task.person_FIELDNAME, Task.unit_FIELDNAME,
 						Task.routeName_FIELDNAME, Task.opinion_FIELDNAME, Task.startTime_FIELDNAME,
-						Task.activityName_FIELDNAME),
+						Task.activityName_FIELDNAME, Task.activityToken_FIELDNAME),
 				null);
 	}
 
@@ -224,7 +229,8 @@ class ActionListWithWorkOrWorkCompleted extends BaseAction {
 				ListTools.toList(TaskCompleted.id_FIELDNAME, TaskCompleted.person_FIELDNAME,
 						TaskCompleted.unit_FIELDNAME, TaskCompleted.routeName_FIELDNAME,
 						TaskCompleted.opinion_FIELDNAME, TaskCompleted.startTime_FIELDNAME,
-						TaskCompleted.activityName_FIELDNAME, TaskCompleted.completedTime_FIELDNAME),
+						TaskCompleted.activityName_FIELDNAME, TaskCompleted.completedTime_FIELDNAME,
+						Task.activityToken_FIELDNAME),
 				null);
 	}
 
@@ -234,7 +240,7 @@ class ActionListWithWorkOrWorkCompleted extends BaseAction {
 
 		static WrapCopier<Read, WoRead> copier = WrapCopierFactory.wo(Read.class, WoRead.class,
 				ListTools.toList(Read.id_FIELDNAME, Read.person_FIELDNAME, Read.unit_FIELDNAME, Read.opinion_FIELDNAME,
-						Read.startTime_FIELDNAME, Read.activityName_FIELDNAME),
+						Read.startTime_FIELDNAME, Read.activityName_FIELDNAME, Task.activityToken_FIELDNAME),
 				null);
 	}
 
@@ -247,7 +253,7 @@ class ActionListWithWorkOrWorkCompleted extends BaseAction {
 				ListTools.toList(ReadCompleted.id_FIELDNAME, ReadCompleted.person_FIELDNAME,
 						ReadCompleted.unit_FIELDNAME, ReadCompleted.opinion_FIELDNAME,
 						ReadCompleted.startTime_FIELDNAME, ReadCompleted.activityName_FIELDNAME,
-						ReadCompleted.completedTime_FIELDNAME),
+						ReadCompleted.completedTime_FIELDNAME, Task.activityToken_FIELDNAME),
 				null);
 	}
 

+ 3 - 3
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/BaseAction.java

@@ -777,7 +777,7 @@ abstract class BaseAction extends StandardJaxrsAction {
 						.count() > 0)
 				|| (reviewCount > 0)) {
 			control.setAllowVisit(true);
-		} else if (effectivePerson.isUser(work.getCreatorPerson())) {
+		} else if (effectivePerson.isPerson(work.getCreatorPerson())) {
 			control.setAllowVisit(true);
 		} else if (business.canManageApplicationOrProcess(effectivePerson, application, process)) {
 			control.setAllowVisit(true);
@@ -842,10 +842,10 @@ abstract class BaseAction extends StandardJaxrsAction {
 			control.setAllowReroute(true);
 		} else if (BooleanUtils.isTrue(activity.getAllowReroute())) {
 			/** 如果活动设置了可以调度 */
-			if ((null != process) && effectivePerson.isUser(process.getControllerList())) {
+			if ((null != process) && effectivePerson.isPerson(process.getControllerList())) {
 				/** 如果是流程的管理员那么可以调度 */
 				control.setAllowReroute(true);
-			} else if ((null != application) && effectivePerson.isUser(application.getControllerList())) {
+			} else if ((null != application) && effectivePerson.isPerson(application.getControllerList())) {
 				/** 如果是应用的管理员那么可以调度 */
 				control.setAllowReroute(true);
 			}

+ 21 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/WorkLogAction.java

@@ -53,7 +53,8 @@ public class WorkLogAction extends StandardJaxrsAction {
 	@Path("list/workorworkcompleted/{workOrWorkCompleted}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
-	public void getWithWork(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+	public void listWithWorkOrWorkCompleted(@Suspended final AsyncResponse asyncResponse,
+			@Context HttpServletRequest request,
 			@JaxrsParameterDescribe("工作或已完成工作标识") @PathParam("workOrWorkCompleted") String workOrWorkCompleted) {
 		ActionResult<List<ActionListWithWorkOrWorkCompleted.Wo>> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
@@ -66,4 +67,23 @@ public class WorkLogAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
 
+	@JaxrsMethodDescribe(value = "获取工作或完成工作可回滚的工作日志.", action = ActionListRollbackWithWorkOrWorkCompleted.class)
+	@GET
+	@Path("list/rollback/workorworkcompleted/{workOrWorkCompleted}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listRollbackWithWorkOrWorkCompleted(@Suspended final AsyncResponse asyncResponse,
+			@Context HttpServletRequest request,
+			@JaxrsParameterDescribe("工作或已完成工作标识") @PathParam("workOrWorkCompleted") String workOrWorkCompleted) {
+		ActionResult<List<ActionListRollbackWithWorkOrWorkCompleted.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListRollbackWithWorkOrWorkCompleted().execute(effectivePerson, workOrWorkCompleted);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
 }

+ 1 - 1
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Attachment.java

@@ -272,7 +272,7 @@ public class Attachment extends StorageObject {
 	private String activityToken;
 
 	public static final String completed_FIELDNAME = "completed";
-	@FieldDescribe("工作是否已经完成.")
+	@FieldDescribe("整个job是否已经完成.")
 	@Column(name = ColumnNamePrefix + completed_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + completed_FIELDNAME)
 	@CheckPersist(allowEmpty = false)

+ 1 - 1
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Read.java

@@ -169,7 +169,7 @@ public class Read extends SliceJpaObject {
 	private String workCompleted;
 
 	public static final String completed_FIELDNAME = "completed";
-	@FieldDescribe("工作是否已经完成.")
+	@FieldDescribe("整个job是否已经完成.")
 	@Column(name = ColumnNamePrefix + completed_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + completed_FIELDNAME)
 	@CheckPersist(allowEmpty = true)

+ 1 - 1
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/ReadCompleted.java

@@ -159,7 +159,7 @@ public class ReadCompleted extends SliceJpaObject {
 	private String workCompleted;
 
 	public static final String completed_FIELDNAME = "completed";
-	@FieldDescribe("工作是否已经完成.")
+	@FieldDescribe("整个job是否已经完成.")
 	@Column(name = ColumnNamePrefix + completed_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + completed_FIELDNAME)
 	@CheckPersist(allowEmpty = true)

+ 1 - 2
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/TaskCompleted.java

@@ -31,7 +31,6 @@ import com.x.base.core.project.tools.StringTools;
 import com.x.processplatform.core.entity.PersistenceProperties;
 import com.x.processplatform.core.entity.element.ActivityType;
 import com.x.processplatform.core.entity.element.Manual;
-import com.x.processplatform.core.entity.element.ManualMode;
 import com.x.processplatform.core.entity.element.Route;
 
 /**
@@ -251,7 +250,7 @@ public class TaskCompleted extends SliceJpaObject {
 	private String work;
 
 	public static final String completed_FIELDNAME = "completed";
-	@FieldDescribe("是否已经完成.")
+	@FieldDescribe("整个job是否已经完成.")
 	@Column(name = ColumnNamePrefix + completed_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + completed_FIELDNAME)
 	@CheckPersist(allowEmpty = true)

+ 6 - 0
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Work.java

@@ -84,6 +84,12 @@ public class Work extends SliceJpaObject {
 		copy.copyTo(this, JpaObject.id_FIELDNAME);
 	}
 
+	public Work(WorkCompleted workCompleted) throws Exception {
+		Work copy = XGsonBuilder.convert(workCompleted, Work.class);
+		copy.copyTo(this, JpaObject.id_FIELDNAME);
+		this.setId(workCompleted.getWork());
+	}
+
 	public void setTitle(String title) {
 		if (StringTools.utf8Length(title) > length_255B) {
 			this.title = StringTools.utf8SubString(this.title, 252) + "...";

+ 15 - 155
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/WorkCompleted.java

@@ -288,8 +288,8 @@ public class WorkCompleted extends SliceJpaObject {
 	@CheckPersist(allowEmpty = true)
 	private String formMobileData;
 
-	@Flag
 	public static final String work_FIELDNAME = "work";
+	@Flag
 	@FieldDescribe("Work Id.")
 	@Column(length = JpaObject.length_id, name = ColumnNamePrefix + work_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + work_FIELDNAME)
@@ -317,160 +317,12 @@ public class WorkCompleted extends SliceJpaObject {
 	@CheckPersist(allowEmpty = false)
 	private Long duration;
 
-	// public static final String extensionString01_FIELDNAME = "extensionString01";
-	// @FieldDescribe("扩充文本字段01.")
-	// @Column(length = length_255B, name = ColumnNamePrefix +
-	// extensionString01_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionString01_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private String extensionString01;
-	//
-	// public static final String extensionString02_FIELDNAME = "extensionString02";
-	// @FieldDescribe("扩充文本字段02.")
-	// @Column(length = length_255B, name = ColumnNamePrefix +
-	// extensionString02_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionString02_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private String extensionString02;
-	//
-	// public static final String extensionString03_FIELDNAME = "extensionString03";
-	// @FieldDescribe("扩充文本字段03.")
-	// @Column(length = length_255B, name = ColumnNamePrefix +
-	// extensionString03_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionString03_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private String extensionString03;
-	//
-	// public static final String extensionString04_FIELDNAME = "extensionString04";
-	// @FieldDescribe("扩充文本字段04.")
-	// @Column(length = length_255B, name = ColumnNamePrefix +
-	// extensionString04_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionString04_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private String extensionString04;
-	//
-	// public static final String extensionString05_FIELDNAME = "extensionString05";
-	// @FieldDescribe("扩充文本字段05.")
-	// @Column(length = length_255B, name = ColumnNamePrefix +
-	// extensionString05_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionString05_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private String extensionString05;
-	//
-	// public static final String extensionString06_FIELDNAME = "extensionString06";
-	// @FieldDescribe("扩充文本字段06.")
-	// @Column(length = length_255B, name = ColumnNamePrefix +
-	// extensionString06_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionString06_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private String extensionString06;
-	//
-	// public static final String extensionString07_FIELDNAME = "extensionString07";
-	// @FieldDescribe("扩充文本字段07.")
-	// @Column(length = length_255B, name = ColumnNamePrefix +
-	// extensionString07_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionString07_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private String extensionString07;
-	//
-	// public static final String extensionString08_FIELDNAME = "extensionString08";
-	// @FieldDescribe("扩充文本字段08.")
-	// @Column(length = length_255B, name = ColumnNamePrefix +
-	// extensionString08_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionString08_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private String extensionString08;
-	//
-	// public static final String extensionString09_FIELDNAME = "extensionString09";
-	// @FieldDescribe("扩充文本字段09.")
-	// @Column(length = length_255B, name = ColumnNamePrefix +
-	// extensionString09_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionString09_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private String extensionString09;
-	//
-	// public static final String extensionString10_FIELDNAME = "extensionString10";
-	// @FieldDescribe("扩充文本字段10.")
-	// @Column(length = length_255B, name = ColumnNamePrefix +
-	// extensionString10_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionString10_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private String extensionString10;
-	//
-	// public static final String extensionDouble01_FIELDNAME = "extensionDouble01";
-	// @FieldDescribe("扩充数字字段01.")
-	// @Column(name = ColumnNamePrefix + extensionDouble01_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionDouble01_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private Double extensionDouble01;
-	//
-	// public static final String extensionDouble02_FIELDNAME = "extensionDouble02";
-	// @FieldDescribe("扩充数字字段02.")
-	// @Column(name = ColumnNamePrefix + extensionDouble02_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionDouble02_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private Double extensionDouble02;
-	//
-	// public static final String extensionDouble03_FIELDNAME = "extensionDouble03";
-	// @FieldDescribe("扩充数字字段03.")
-	// @Column(name = ColumnNamePrefix + extensionDouble03_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionDouble03_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private Double extensionDouble03;
-	//
-	// public static final String extensionDouble04_FIELDNAME = "extensionDouble04";
-	// @FieldDescribe("扩充数字字段04.")
-	// @Column(name = ColumnNamePrefix + extensionDouble04_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionDouble04_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private Double extensionDouble04;
-	//
-	// public static final String extensionDouble05_FIELDNAME = "extensionDouble05";
-	// @FieldDescribe("扩充数字字段05.")
-	// @Column(name = ColumnNamePrefix + extensionDouble05_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionDouble05_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private Double extensionDouble05;
-	//
-	// public static final String extensionBoolean01_FIELDNAME =
-	// "extensionBoolean01";
-	// @FieldDescribe("扩充布尔字段01.")
-	// @Column(name = ColumnNamePrefix + extensionBoolean01_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionBoolean01_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private Boolean extensionBoolean01;
-	//
-	// public static final String extensionBoolean02_FIELDNAME =
-	// "extensionBoolean02";
-	// @FieldDescribe("扩充布尔字段02.")
-	// @Column(name = ColumnNamePrefix + extensionBoolean02_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionBoolean02_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private Boolean extensionBoolean02;
-	//
-	// public static final String extensionBoolean03_FIELDNAME =
-	// "extensionBoolean03";
-	// @FieldDescribe("扩充布尔字段03.")
-	// @Column(name = ColumnNamePrefix + extensionBoolean03_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionBoolean03_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private Boolean extensionBoolean03;
-	//
-	// public static final String extensionBoolean04_FIELDNAME =
-	// "extensionBoolean04";
-	// @FieldDescribe("扩充布尔字段04.")
-	// @Column(name = ColumnNamePrefix + extensionBoolean04_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionBoolean04_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private Boolean extensionBoolean04;
-	//
-	// public static final String extensionBoolean05_FIELDNAME =
-	// "extensionBoolean05";
-	// @FieldDescribe("扩充布尔字段05.")
-	// @Column(name = ColumnNamePrefix + extensionBoolean05_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + extensionBoolean05_FIELDNAME)
-	// @CheckPersist(allowEmpty = true)
-	// private Boolean extensionBoolean05;
+	public static final String allowRollback_FIELDNAME = "allowRollback";
+	@FieldDescribe("完成后是否允许回滚.")
+	@Column(name = ColumnNamePrefix + allowRollback_FIELDNAME)
+	@Index(name = TABLE + IndexNameMiddle + allowRollback_FIELDNAME)
+	@CheckPersist(allowEmpty = true)
+	private Boolean allowRollback;
 
 	public String getJob() {
 		return job;
@@ -664,4 +516,12 @@ public class WorkCompleted extends SliceJpaObject {
 		this.creatorUnitLevelName = creatorUnitLevelName;
 	}
 
+	public Boolean getAllowRollback() {
+		return allowRollback;
+	}
+
+	public void setAllowRollback(Boolean allowRollback) {
+		this.allowRollback = allowRollback;
+	}
+
 }

+ 1 - 1
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/ActivityType.java

@@ -3,7 +3,7 @@ package com.x.processplatform.core.entity.element;
 import com.x.base.core.entity.JpaObject;
 
 public enum ActivityType {
-	agent, begin, cancel, choice, condition, delay, end, embed, invoke, manual, merge, message, parallel, service, split;
+	agent, begin, cancel, choice, delay, end, embed, invoke, manual, merge, message, parallel, service, split;
 
 	public static final int length = JpaObject.length_16B;
 

+ 24 - 10
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/End.java

@@ -114,7 +114,7 @@ public class End extends Activity {
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle
 			+ readIdentityList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle + readIdentityList_FIELDNAME
 					+ JoinIndexNameSuffix))
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ElementColumn(length = length_255B, name = ColumnNamePrefix + readIdentityList_FIELDNAME)
 	@ElementIndex(name = TABLE + IndexNameMiddle + readIdentityList_FIELDNAME + ElementIndexNameSuffix)
 	@CheckPersist(allowEmpty = true)
@@ -124,17 +124,17 @@ public class End extends Activity {
 	@PersistentCollection(fetch = FetchType.EAGER)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle + readUnitList_FIELDNAME, joinIndex = @Index(name = TABLE
 			+ IndexNameMiddle + readUnitList_FIELDNAME + JoinIndexNameSuffix))
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ElementColumn(length = length_255B, name = ColumnNamePrefix + readUnitList_FIELDNAME)
 	@ElementIndex(name = TABLE + IndexNameMiddle + readUnitList_FIELDNAME + ElementIndexNameSuffix)
 	@CheckPersist(allowEmpty = true)
 	private List<String> readUnitList;
-	
+
 	@FieldDescribe("待阅群组名称,存储group,多值.")
 	@PersistentCollection(fetch = FetchType.EAGER)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle + readGroupList_FIELDNAME, joinIndex = @Index(name = TABLE
 			+ IndexNameMiddle + readGroupList_FIELDNAME + JoinIndexNameSuffix))
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ElementColumn(length = length_255B, name = ColumnNamePrefix + readGroupList_FIELDNAME)
 	@ElementIndex(name = TABLE + IndexNameMiddle + readGroupList_FIELDNAME + ElementIndexNameSuffix)
 	@CheckPersist(allowEmpty = true)
@@ -165,7 +165,7 @@ public class End extends Activity {
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle
 			+ readDataPathList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle + readDataPathList_FIELDNAME
 					+ JoinIndexNameSuffix))
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ElementColumn(length = JpaObject.length_255B, name = ColumnNamePrefix + readDataPathList_FIELDNAME)
 	@ElementIndex(name = TABLE + IndexNameMiddle + readDataPathList_FIELDNAME + ElementIndexNameSuffix)
 	@CheckPersist(allowEmpty = true)
@@ -176,7 +176,7 @@ public class End extends Activity {
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle
 			+ reviewIdentityList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
 					+ reviewIdentityList_FIELDNAME + JoinIndexNameSuffix))
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ElementColumn(length = length_255B, name = ColumnNamePrefix + reviewIdentityList_FIELDNAME)
 	@ElementIndex(name = TABLE + IndexNameMiddle + reviewIdentityList_FIELDNAME + ElementIndexNameSuffix)
 	@CheckPersist(allowEmpty = true)
@@ -186,17 +186,17 @@ public class End extends Activity {
 	@PersistentCollection(fetch = FetchType.EAGER)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle + reviewUnitList_FIELDNAME, joinIndex = @Index(name = TABLE
 			+ IndexNameMiddle + reviewUnitList_FIELDNAME + JoinIndexNameSuffix))
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ElementColumn(length = length_255B, name = ColumnNamePrefix + reviewUnitList_FIELDNAME)
 	@ElementIndex(name = TABLE + IndexNameMiddle + reviewUnitList_FIELDNAME + ElementIndexNameSuffix)
 	@CheckPersist(allowEmpty = true)
 	private List<String> reviewUnitList;
-	
+
 	@FieldDescribe("参与人群组名称,存储group,多值.")
 	@PersistentCollection(fetch = FetchType.EAGER)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle + reviewGroupList_FIELDNAME, joinIndex = @Index(name = TABLE
 			+ IndexNameMiddle + reviewGroupList_FIELDNAME + JoinIndexNameSuffix))
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ElementColumn(length = length_255B, name = ColumnNamePrefix + reviewGroupList_FIELDNAME)
 	@ElementIndex(name = TABLE + IndexNameMiddle + reviewGroupList_FIELDNAME + ElementIndexNameSuffix)
 	@CheckPersist(allowEmpty = true)
@@ -227,7 +227,7 @@ public class End extends Activity {
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle
 			+ reviewDataPathList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
 					+ reviewDataPathList_FIELDNAME + JoinIndexNameSuffix))
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ElementColumn(length = JpaObject.length_255B, name = ColumnNamePrefix + reviewDataPathList_FIELDNAME)
 	@ElementIndex(name = TABLE + IndexNameMiddle + reviewDataPathList_FIELDNAME + ElementIndexNameSuffix)
 	@CheckPersist(allowEmpty = true)
@@ -323,6 +323,12 @@ public class End extends Activity {
 	@Index(name = TABLE + IndexNameMiddle + allowRerouteTo_FIELDNAME)
 	private Boolean allowRerouteTo;
 
+	public static final String allowRollback_FIELDNAME = "allowRollback";
+	@FieldDescribe("允许回滚")
+	@CheckPersist(allowEmpty = true)
+	@Column(name = ColumnNamePrefix + allowRollback_FIELDNAME)
+	private Boolean allowRollback;
+
 	public String getName() {
 		return name;
 	}
@@ -603,4 +609,12 @@ public class End extends Activity {
 		this.afterInquireScriptText = afterInquireScriptText;
 	}
 
+	public Boolean getAllowRollback() {
+		return allowRollback;
+	}
+
+	public void setAllowRollback(Boolean allowRollback) {
+		this.allowRollback = allowRollback;
+	}
+
 }

+ 4 - 4
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/ManualMode.java

@@ -3,10 +3,10 @@ package com.x.processplatform.core.entity.element;
 import com.x.base.core.entity.JpaObject;
 
 /**
- * 节点方式,单人活动,并行或者顺序执行
+ * 节点方式,单人活动,并行, 顺序执行, 抢办
  */
 public enum ManualMode {
-	single, parallel, queue;
-	
-	public static final int length=JpaObject.length_16B;
+	single, parallel, queue, grab;
+
+	public static final int length = JpaObject.length_16B;
 }

+ 2 - 2
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/util/ExceptionBeginNotFound.java

@@ -6,7 +6,7 @@ public class ExceptionBeginNotFound extends PromptException {
 
 	private static final long serialVersionUID = 4132300948670472899L;
 
-	ExceptionBeginNotFound(Integer count) {
-		super("没有找到开始节点,开始节点数量:{}.", count);
+	ExceptionBeginNotFound() {
+		super("没有找到开始节点.");
 	}
 }

+ 92 - 43
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/util/WorkLogTree.java

@@ -1,12 +1,12 @@
 package com.x.processplatform.core.entity.element.util;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.Objects;
-import java.util.stream.Collectors;
 
 import org.apache.commons.collections4.ListUtils;
-import org.apache.commons.collections4.list.TreeList;
+import org.apache.commons.collections4.set.ListOrderedSet;
 import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 
@@ -19,49 +19,54 @@ public class WorkLogTree {
 
 	private Node root;
 
-	List<WorkLog> list;
+	public static List<String> RELY_WORKLOG_ITEMS = ListTools.toList(WorkLog.fromActivityToken_FIELDNAME,
+			WorkLog.arrivedActivityToken_FIELDNAME, WorkLog.fromActivityType_FIELDNAME,
+			WorkLog.arrivedActivityType_FIELDNAME, WorkLog.connected_FIELDNAME);
 
 	Nodes nodes = new Nodes();
 
 	public WorkLogTree(List<WorkLog> list) throws Exception {
-		this.list = new ArrayList<WorkLog>(list);
+
+		for (WorkLog o : list) {
+			this.nodes().add(new Node(o));
+		}
+
 		List<String> froms = ListTools.extractProperty(list, WorkLog.fromActivityToken_FIELDNAME, String.class, true,
 				true);
 		List<String> arriveds = ListTools.extractProperty(list, WorkLog.arrivedActivityToken_FIELDNAME, String.class,
 				true, true);
 		List<String> values = ListUtils.subtract(froms, arriveds);
-		List<WorkLog> begins = list.stream()
+		WorkLog begin = list.stream()
 				.filter(o -> BooleanUtils.isTrue(o.getConnected()) && values.contains(o.getFromActivityToken()))
-				.collect(Collectors.toList());
-		if (begins.size() != 1) {
-			throw new ExceptionBeginNotFound(begins.size());
-		}
-		root = new Node();
-		root.workLog = begins.get(0);
-		root.parent = null;
-		this.nodes.add(root);
-		this.sub(root);
+				.findFirst().orElse(null);
+		if (null == begin) {
+			throw new ExceptionBeginNotFound();
+		}
+		root = this.find(begin);
+		for (Node o : nodes) {
+			this.associate();
+		}
 	}
 
-	private void sub(Node node) {
-		node.children = new Nodes();
-		List<WorkLog> os = list.stream()
-				.filter(o -> StringUtils.equals(node.workLog.getArrivedActivityToken(), o.getFromActivityToken()))
-				.collect(Collectors.toList());
-		if (!os.isEmpty()) {
-			for (WorkLog o : os) {
-				list.remove(o);
-				Node child = new Node();
-				child.workLog = o;
-				child.parent = node;
-				node.children.add(child);
-				this.nodes.add(child);
-				sub(child);
-			}
+	private void associate() {
+		for (Node node : nodes) {
+			this.nodes.stream().filter(
+					o -> StringUtils.equals(node.workLog.getFromActivityToken(), o.workLog.getArrivedActivityToken()))
+					.forEach(o -> {
+						node.parent.add(o);
+					});
+			this.nodes.stream().filter(
+					o -> StringUtils.equals(node.workLog.getArrivedActivityToken(), o.workLog.getFromActivityToken()))
+					.forEach(o -> {
+						node.children.add(o);
+					});
 		}
+
 	}
 
-	public static class Nodes extends TreeList<Node> {
+	public static class Nodes extends ListOrderedSet<Node> {
+
+		private static final long serialVersionUID = 4612771613796262398L;
 
 		public boolean onlyManual() {
 			return true;
@@ -76,22 +81,62 @@ public class WorkLogTree {
 			return false;
 		}
 
+		public boolean containsWorkLogWithActivityToken(String activityToken) {
+			for (Node n : this) {
+				if (Objects.equals(n.getWorkLog().getArrivedActivityToken(), activityToken)) {
+					return true;
+				}
+			}
+			return false;
+		}
+
+		public Date latestArrivedTime() {
+			Date date = null;
+			if (!this.isEmpty()) {
+				for (Node n : this) {
+					if (null != n.getWorkLog().getArrivedTime()) {
+						if (null == date) {
+							date = n.getWorkLog().getArrivedTime();
+						} else {
+							date = n.getWorkLog().getArrivedTime().after(date) ? n.getWorkLog().getArrivedTime() : date;
+						}
+					}
+				}
+			}
+			return date;
+		}
 	}
 
 	public static class Node {
 
+		public Node(WorkLog workLog) {
+			this.workLog = workLog;
+		}
+
 		private WorkLog workLog;
-		private Node parent;
+		private Nodes parent = new Nodes();
 		private Nodes children = new Nodes();
 
-		public Node upTo(ActivityType activityType, ActivityType... pass) {
-			Node p = this.parent;
-			List<ActivityType> passActivityTypes = ListTools.toList(pass);
-			while ((p != null) && (!Objects.equals(p.workLog.getArrivedActivityType(), activityType))
-					&& ListTools.contains(passActivityTypes, p.workLog.getFromActivityType())) {
-				p = p.parent;
+		public Nodes upTo(ActivityType activityType, ActivityType... pass) {
+			return this.upTo(activityType, ListTools.toList(pass));
+		}
+
+		public Nodes upTo(ActivityType activityType, List<ActivityType> pass) {
+			Nodes result = new Nodes();
+			this.upTo(activityType, pass, result);
+			return result;
+		}
+
+		private void upTo(ActivityType activityType, List<ActivityType> pass, Nodes result) {
+			for (Node o : this.parent) {
+				if (Objects.equals(o.workLog.getFromActivityType(), activityType)) {
+					result.add(o);
+				} else {
+					if (ListTools.contains(pass, o.workLog.getFromActivityType())) {
+						o.upTo(activityType, pass, result);
+					}
+				}
 			}
-			return p;
 		}
 
 		public WorkLog getWorkLog() {
@@ -150,12 +195,16 @@ public class WorkLogTree {
 	}
 
 	public Nodes up(Node node) {
-		Nodes nodes = new Nodes();
-		if (null != node.parent) {
-			nodes.add(node.parent);
-			nodes.addAll(up(node.parent));
+		Nodes result = new Nodes();
+		this.up(node, result);
+		return result;
+	}
+
+	private void up(Node node, Nodes result) {
+		for (Node o : node.parent) {
+			result.add(o);
+			up(o, result);
 		}
-		return nodes;
 	}
 
 	public Node find(WorkLog workLog) {

+ 2 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/ActionApplication.java

@@ -14,12 +14,14 @@ import com.x.processplatform.service.processing.jaxrs.task.TaskAction;
 import com.x.processplatform.service.processing.jaxrs.taskcompleted.TaskCompletedAction;
 import com.x.processplatform.service.processing.jaxrs.test.TestAction;
 import com.x.processplatform.service.processing.jaxrs.work.WorkAction;
+import com.x.processplatform.service.processing.jaxrs.workcompleted.WorkCompletedAction;
 
 @ApplicationPath("jaxrs")
 public class ActionApplication extends AbstractActionApplication {
 
 	public Set<Class<?>> getClasses() {
 		classes.add(WorkAction.class);
+		classes.add(WorkCompletedAction.class);
 		classes.add(JobAction.class);
 		classes.add(TaskAction.class);
 		classes.add(TaskCompletedAction.class);

+ 10 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/WorkCompletedJaxrsFilter.java

@@ -0,0 +1,10 @@
+package com.x.processplatform.service.processing.jaxrs;
+
+import javax.servlet.annotation.WebFilter;
+
+import com.x.base.core.project.jaxrs.CipherManagerJaxrsFilter;
+
+@WebFilter(urlPatterns = "/jaxrs/workcompleted/*", asyncSupported = true)
+public class WorkCompletedJaxrsFilter extends CipherManagerJaxrsFilter {
+
+}

+ 2 - 1
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ActionDelete.java

@@ -3,6 +3,7 @@ package com.x.processplatform.service.processing.jaxrs.task;
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.entity.annotation.CheckRemoveType;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.jaxrs.WoId;
@@ -16,7 +17,7 @@ class ActionDelete extends BaseAction {
 			ActionResult<Wo> result = new ActionResult<>();
 			Task task = emc.find(id, Task.class);
 			if (null == task) {
-				throw new ExceptionTaskNotExist(id);
+				throw new ExceptionEntityNotExist(id, Task.class);
 			}
 			emc.beginTransaction(Task.class);
 			emc.remove(task, CheckRemoveType.all);

+ 78 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ActionGrab.java

@@ -0,0 +1,78 @@
+package com.x.processplatform.service.processing.jaxrs.task;
+
+import java.util.List;
+import java.util.Objects;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WoId;
+import com.x.base.core.project.tools.ListTools;
+import com.x.processplatform.core.entity.content.Task;
+import com.x.processplatform.core.entity.content.Work;
+import com.x.processplatform.core.entity.element.ActivityType;
+import com.x.processplatform.core.entity.element.Manual;
+import com.x.processplatform.core.entity.element.ManualMode;
+import com.x.processplatform.service.processing.Business;
+import com.x.processplatform.service.processing.MessageFactory;
+
+class ActionGrab extends BaseAction {
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, String id) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			ActionResult<Wo> result = new ActionResult<>();
+			Business business = new Business(emc);
+
+			Task task = emc.find(id, Task.class);
+
+			if (null == task) {
+				throw new ExceptionEntityNotExist(id, Task.class);
+			}
+
+			Work work = emc.find(task.getWork(), Work.class);
+
+			if (null == work) {
+				throw new ExceptionEntityNotExist(task.getWork(), Work.class);
+			}
+
+			if (!Objects.equals(work.getActivityType(), ActivityType.manual)) {
+				throw new ExceptionWorkNotAtManual(work.getId());
+			}
+
+			Manual manual = (Manual) business.element().get(work.getActivity(), ActivityType.manual);
+
+			if (!Objects.equals(manual.getManualMode(), ManualMode.grab)) {
+				throw new ExceptionWorkNotGrab(work.getId());
+			}
+
+			emc.beginTransaction(Task.class);
+			emc.beginTransaction(Work.class);
+
+			for (Task o : this.listTask(business, work)) {
+				if (o != task) {
+					emc.remove(o);
+					MessageFactory.task_delete(o);
+				}
+			}
+
+			work.setManualTaskIdentityList(ListTools.toList(task.getIdentity()));
+
+			emc.commit();
+			Wo wo = new Wo();
+			wo.setId(task.getId());
+			result.setData(wo);
+			return result;
+		}
+	}
+
+	private List<Task> listTask(Business business, Work work) throws Exception {
+		return business.entityManagerContainer().listEqualAndEqual(Task.class, Task.activityToken_FIELDNAME,
+				work.getActivityToken(), Task.work_FIELDNAME, work.getId());
+	}
+
+	public static class Wo extends WoId {
+	}
+
+}

+ 4 - 3
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ActionProcessing.java

@@ -13,6 +13,7 @@ import com.x.base.core.entity.annotation.CheckPersistType;
 import com.x.base.core.entity.annotation.CheckRemoveType;
 import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.config.Config;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.gson.GsonPropertyObject;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
@@ -52,10 +53,10 @@ class ActionProcessing extends BaseAction {
 			ActionResult<Wo> result = new ActionResult<>();
 			Task task = emc.find(id, Task.class);
 			if (null == task) {
-				throw new ExceptionTaskNotExist(id);
+				throw new ExceptionEntityNotExist(id, Task.class);
 			}
 			Manual manual = null;
-			/** 执行办前脚本 */
+			/* 执行办前脚本 */
 			if (Objects.equals(task.getActivityType(), ActivityType.manual)) {
 				manual = business.element().get(task.getActivity(), Manual.class);
 				if (null != manual) {
@@ -90,7 +91,7 @@ class ActionProcessing extends BaseAction {
 			emc.persist(taskCompleted, CheckPersistType.all);
 			emc.remove(task, CheckRemoveType.all);
 			emc.commit();
-			/** 待办执行后脚本 */
+			/* 待办执行后脚本 */
 			if (null != manual) {
 				if (StringUtils.isNotEmpty(manual.getManualAfterTaskScript())
 						|| StringUtils.isNotEmpty(manual.getManualAfterTaskScriptText())) {

+ 3 - 2
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ActionReset.java

@@ -14,6 +14,7 @@ import com.x.base.core.entity.annotation.CheckPersistType;
 import com.x.base.core.entity.annotation.CheckRemoveType;
 import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.config.Config;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.gson.GsonPropertyObject;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
@@ -42,11 +43,11 @@ class ActionReset extends BaseAction {
 			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
 			Task task = emc.find(id, Task.class);
 			if (null == task) {
-				throw new ExceptionTaskNotExist(id);
+				throw new ExceptionEntityNotExist(id, Task.class);
 			}
 			Work work = emc.find(task.getWork(), Work.class);
 			if (null == work) {
-				throw new ExceptionWorkNotExist(task.getWork());
+				throw new ExceptionEntityNotExist(task.getWork(), Work.class);
 			}
 			/* 检查reset人员 */
 			List<String> identites = new ArrayList<>();

+ 3 - 3
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ExceptionTaskNotExist.java → o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ExceptionWorkNotAtManual.java

@@ -2,11 +2,11 @@ package com.x.processplatform.service.processing.jaxrs.task;
 
 import com.x.base.core.project.exception.PromptException;
 
-class ExceptionTaskNotExist extends PromptException {
+class ExceptionWorkNotAtManual extends PromptException {
 
 	private static final long serialVersionUID = -3439770681867963457L;
 
-	ExceptionTaskNotExist(String flag) {
-		super("待办: {} 不存在.", flag);
+	ExceptionWorkNotAtManual(String flag) {
+		super("工作: {} 没有处于人工活动.", flag);
 	}
 }

+ 3 - 3
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ExceptionWorkNotExist.java → o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/ExceptionWorkNotGrab.java

@@ -2,11 +2,11 @@ package com.x.processplatform.service.processing.jaxrs.task;
 
 import com.x.base.core.project.exception.PromptException;
 
-class ExceptionWorkNotExist extends PromptException {
+class ExceptionWorkNotGrab extends PromptException {
 
 	private static final long serialVersionUID = -3439770681867963457L;
 
-	ExceptionWorkNotExist(String flag) {
-		super("工作: {} 不存在.", flag);
+	ExceptionWorkNotGrab(String flag) {
+		super("工作: {} 没有处于人工活动的抢办状态.", flag);
 	}
 }

+ 19 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/task/TaskAction.java

@@ -5,6 +5,7 @@ import java.util.List;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
@@ -33,6 +34,24 @@ public class TaskAction extends StandardJaxrsAction {
 
 	private static Logger logger = LoggerFactory.getLogger(TaskAction.class);
 
+	@JaxrsMethodDescribe(value = "抢办.", action = ActionGrab.class)
+	@GET
+	@Path("{id}/grab")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void grab(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("标识") @PathParam("id") String id) {
+		ActionResult<ActionGrab.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionGrab().execute(effectivePerson, id);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
 	@JaxrsMethodDescribe(value = "保存并继续流转.", action = ActionProcessing.class)
 	@PUT
 	@Path("{id}/processing")

+ 42 - 32
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionAddSplit.java

@@ -1,14 +1,12 @@
 package com.x.processplatform.service.processing.jaxrs.work;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.apache.commons.lang3.StringUtils;
 
 import com.google.gson.JsonElement;
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.entity.annotation.CheckPersistType;
+import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
@@ -20,9 +18,6 @@ import com.x.processplatform.service.processing.Business;
 import com.x.processplatform.service.processing.Processing;
 import com.x.processplatform.service.processing.ProcessingAttributes;
 
-/*
- * 
- */
 class ActionAddSplit extends BaseAction {
 
 	ActionResult<Wo> execute(EffectivePerson effectivePerson, String id, JsonElement jsonElement) throws Exception {
@@ -42,34 +37,46 @@ class ActionAddSplit extends BaseAction {
 			if (StringUtils.isEmpty(wi.getSplitValue())) {
 				throw new ExceptionEmptySplitValue(work.getId());
 			}
-			WorkLog workLog = this.getWorkLogTemplate(business, work);
+
+			WorkLog arrived = this.getWorkLogArrived(business, work);
+
+			if (null == arrived) {
+				throw new ExceptionInvalidArrivedWorkLog(work.getActivityToken());
+			}
+
+			WorkLog from = this.getWorkLogFrom(business, work);
+
+			if (null == from) {
+				throw new ExceptionInvalidFromWorkLog(work.getActivityToken());
+			}
+
 			emc.beginTransaction(Work.class);
 			emc.beginTransaction(WorkLog.class);
+
 			Work workCopy = new Work(work);
-			WorkLog workLogCopy = new WorkLog(workLog);
-			List<String> tokens = new ArrayList<>();
-			String token = StringTools.uniqueToken();
-			for (String str : workCopy.getSplitTokenList()) {
-				if (StringUtils.equals(str, workCopy.getSplitToken())) {
-					tokens.add(token);
-				} else {
-					tokens.add(str);
-				}
-			}
+
+			WorkLog arrivedCopy = new WorkLog(arrived);
+
+			WorkLog fromCopy = new WorkLog(from);
+
+			/* 设置work */
+			arrivedCopy.setWork(workCopy.getId());
+			fromCopy.setWork(workCopy.getId());
+
 			workCopy.setSplitValue(wi.getSplitValue());
-			workCopy.setSplitTokenList(tokens);
-			workCopy.setSplitToken(token);
-			workLogCopy.setSplitValue(wi.getSplitValue());
-			workLogCopy.setSplitTokenList(tokens);
-			workLogCopy.setSplitToken(token);
+			arrivedCopy.setSplitValue(wi.getSplitValue());
+			fromCopy.setSplitValue(wi.getSplitValue());
 			/* 重置到达值 */
 			String activityToken = StringTools.uniqueToken();
 			workCopy.setActivityToken(activityToken);
-			workLogCopy.setArrivedActivityToken(activityToken);
+			arrivedCopy.setArrivedActivityToken(activityToken);
+			fromCopy.setFromActivityToken(activityToken);
+
 			/* 清空处理人会导致重新计算当前环节处理人 */
 			workCopy.getManualTaskIdentityList().clear();
 			emc.persist(workCopy, CheckPersistType.all);
-			emc.persist(workLogCopy, CheckPersistType.all);
+			emc.persist(arrivedCopy, CheckPersistType.all);
+			emc.persist(fromCopy, CheckPersistType.all);
 			emc.commit();
 			Processing processing = new Processing(wi);
 			processing.processing(workCopy.getId());
@@ -80,18 +87,21 @@ class ActionAddSplit extends BaseAction {
 		}
 	}
 
-	private WorkLog getWorkLogTemplate(Business business, Work work) throws Exception {
-		List<WorkLog> os = business.entityManagerContainer().listEqual(WorkLog.class,
-				WorkLog.arrivedActivityToken_FIELDNAME, work.getActivityToken());
-		if (os.size() != 1) {
-			throw new ExceptionInvalidWorkLog(work.getActivityToken(), os.size());
-		} else {
-			return os.get(0);
-		}
+	private WorkLog getWorkLogArrived(Business business, Work work) throws Exception {
+		return business.entityManagerContainer()
+				.listEqual(WorkLog.class, WorkLog.arrivedActivityToken_FIELDNAME, work.getActivityToken()).stream()
+				.findFirst().orElse(null);
+	}
+
+	private WorkLog getWorkLogFrom(Business business, Work work) throws Exception {
+		return business.entityManagerContainer()
+				.listEqual(WorkLog.class, WorkLog.fromActivityToken_FIELDNAME, work.getActivityToken()).stream()
+				.findFirst().orElse(null);
 	}
 
 	public static class Wi extends ProcessingAttributes {
 
+		@FieldDescribe("增加的拆分值")
 		private String splitValue;
 
 		public String getSplitValue() {

+ 0 - 152
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionCallback.java

@@ -1,152 +0,0 @@
-package com.x.processplatform.service.processing.jaxrs.work;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang.BooleanUtils;
-
-import com.google.gson.JsonElement;
-import com.x.base.core.container.EntityManagerContainer;
-import com.x.base.core.container.factory.EntityManagerContainerFactory;
-import com.x.base.core.project.exception.ExceptionEntityNotExist;
-import com.x.base.core.project.http.ActionResult;
-import com.x.base.core.project.http.EffectivePerson;
-import com.x.base.core.project.jaxrs.WoId;
-import com.x.base.core.project.tools.ListTools;
-import com.x.processplatform.core.entity.content.Read;
-import com.x.processplatform.core.entity.content.ReadCompleted;
-import com.x.processplatform.core.entity.content.Review;
-import com.x.processplatform.core.entity.content.Task;
-import com.x.processplatform.core.entity.content.TaskCompleted;
-import com.x.processplatform.core.entity.content.Work;
-import com.x.processplatform.core.entity.content.WorkLog;
-import com.x.processplatform.core.entity.element.util.WorkLogTree;
-import com.x.processplatform.core.entity.element.util.WorkLogTree.Node;
-import com.x.processplatform.core.entity.element.util.WorkLogTree.Nodes;
-import com.x.processplatform.service.processing.Processing;
-import com.x.processplatform.service.processing.ProcessingAttributes;
-
-class ActionCallback extends BaseAction {
-
-	ActionResult<Wo> execute(EffectivePerson effectivePerson, String id, JsonElement jsonElement) throws Exception {
-
-		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
-			ActionResult<Wo> result = new ActionResult<>();
-
-			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
-
-			Work work = emc.find(id, Work.class);
-
-			if (null == work) {
-				throw new ExceptionEntityNotExist(id, Work.class);
-			}
-
-			WorkLog workLog = emc.find(wi.getWorkLogId(), WorkLog.class);
-
-			if (null == workLog) {
-				throw new ExceptionEntityNotExist(wi.getWorkLogId(), WorkLog.class);
-			}
-
-			if (BooleanUtils.isTrue(workLog.getSplitting())) {
-				throw new ExceptionSplittingCannotCallback(work.getId(), workLog.getId());
-			}
-
-			List<WorkLog> workLogs = emc.listEqual(WorkLog.class, WorkLog.job_FIELDNAME, work.getJob());
-
-			WorkLogTree workLogTree = new WorkLogTree(workLogs);
-
-			Node node = workLogTree.find(workLog);
-
-			Nodes nodes = workLogTree.rootTo(node);
-
-			emc.beginTransaction(Work.class);
-			emc.beginTransaction(WorkLog.class);
-			emc.beginTransaction(Task.class);
-			emc.beginTransaction(TaskCompleted.class);
-			emc.beginTransaction(Read.class);
-			emc.beginTransaction(ReadCompleted.class);
-			emc.beginTransaction(Review.class);
-
-			work.setActivityName(workLog.getFromActivityName());
-			work.setActivity(workLog.getFromActivity());
-			work.setActivityAlias(workLog.getFromActivityAlias());
-			work.setActivityArrivedTime(workLog.getFromTime());
-			work.setActivityDescription("");
-			work.setActivityToken(workLog.getFromActivityToken());
-			work.setActivityType(workLog.getFromActivityType());
-
-			workLog.setConnected(false);
-			workLog.setArrivedActivity("");
-			workLog.setArrivedActivityAlias("");
-			workLog.setArrivedActivityName("");
-			workLog.setArrivedActivityToken("");
-			workLog.setArrivedActivityType(null);
-			workLog.setArrivedTime(null);
-			workLog.setDuration(0L);
-
-			List<WorkLog> removeWorkLogs = new ArrayList<>();
-
-			for (WorkLog o : workLogs) {
-				if (!nodes.containsWorkLog(o)) {
-					removeWorkLogs.add(o);
-				}
-			}
-
-			List<String> removeActivityToken = ListTools.extractProperty(removeWorkLogs,
-					WorkLog.fromActivityToken_FIELDNAME, String.class, true, true);
-
-			for (Task o : emc.listEqual(Task.class, Task.work_FIELDNAME, work.getId())) {
-				emc.remove(o);
-			}
-
-			for (TaskCompleted o : emc.listEqual(TaskCompleted.class, TaskCompleted.job_FIELDNAME, work.getJob())) {
-				if (removeActivityToken.contains(o.getActivityToken())) {
-					emc.remove(o);
-				}
-			}
-
-			for (ReadCompleted o : emc.listEqual(ReadCompleted.class, ReadCompleted.job_FIELDNAME, work.getJob())) {
-				if (removeActivityToken.contains(o.getActivityToken())) {
-					emc.remove(o);
-				}
-			}
-
-			for (Read o : emc.listEqual(Read.class, Read.job_FIELDNAME, work.getJob())) {
-				if (removeActivityToken.contains(o.getActivityToken())) {
-					emc.remove(o);
-				}
-			}
-
-			for (WorkLog o : removeWorkLogs) {
-				emc.remove(o);
-			}
-
-			emc.commit();
-
-			Processing processing = new Processing(wi);
-			processing.processing(work.getId());
-			Wo wo = new Wo();
-			wo.setId(work.getId());
-			result.setData(wo);
-			return result;
-		}
-	}
-
-	public static class Wi extends ProcessingAttributes {
-
-		private String workLogId;
-
-		public String getWorkLogId() {
-			return workLogId;
-		}
-
-		public void setWorkLogId(String workLogId) {
-			this.workLogId = workLogId;
-		}
-
-	}
-
-	public static class Wo extends WoId {
-	}
-
-}

+ 248 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionRollback.java

@@ -0,0 +1,248 @@
+package com.x.processplatform.service.processing.jaxrs.work;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import com.google.gson.JsonElement;
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WoId;
+import com.x.processplatform.core.entity.content.Read;
+import com.x.processplatform.core.entity.content.ReadCompleted;
+import com.x.processplatform.core.entity.content.Review;
+import com.x.processplatform.core.entity.content.Task;
+import com.x.processplatform.core.entity.content.TaskCompleted;
+import com.x.processplatform.core.entity.content.Work;
+import com.x.processplatform.core.entity.content.WorkLog;
+import com.x.processplatform.core.entity.content.WorkStatus;
+import com.x.processplatform.core.entity.element.Application;
+import com.x.processplatform.core.entity.element.Process;
+import com.x.processplatform.core.entity.element.util.WorkLogTree;
+import com.x.processplatform.core.entity.element.util.WorkLogTree.Node;
+import com.x.processplatform.core.entity.element.util.WorkLogTree.Nodes;
+import com.x.processplatform.service.processing.Business;
+import com.x.processplatform.service.processing.MessageFactory;
+import com.x.processplatform.service.processing.Processing;
+import com.x.processplatform.service.processing.ProcessingAttributes;
+
+class ActionRollback extends BaseAction {
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, String id, JsonElement jsonElement) throws Exception {
+
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+
+			ActionResult<Wo> result = new ActionResult<>();
+
+			Business business = new Business(emc);
+
+			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
+
+			Work work = emc.find(id, Work.class);
+
+			if (null == work) {
+				throw new ExceptionEntityNotExist(id, Work.class);
+			}
+
+			Application application = business.element().get(work.getApplication(), Application.class);
+
+			if (null == application) {
+				throw new ExceptionEntityNotExist(work.getApplication(), Application.class);
+			}
+
+			Process process = business.element().get(work.getProcess(), Process.class);
+
+			if (null == process) {
+				throw new ExceptionEntityNotExist(work.getProcess(), Process.class);
+			}
+
+			WorkLog workLog = emc.find(wi.getWorkLog(), WorkLog.class);
+
+			if (null == workLog) {
+				throw new ExceptionEntityNotExist(wi.getWorkLog(), WorkLog.class);
+			}
+
+			if (BooleanUtils.isTrue(workLog.getSplitting())) {
+				throw new ExceptionSplittingNotRollback(work.getId(), workLog.getId());
+			}
+
+			List<WorkLog> workLogs = emc.listEqual(WorkLog.class, WorkLog.job_FIELDNAME, workLog.getJob());
+
+			WorkLogTree workLogTree = new WorkLogTree(workLogs);
+
+			Node node = workLogTree.find(workLog);
+
+			Nodes nodes = workLogTree.rootTo(node);
+
+			emc.beginTransaction(Work.class);
+			emc.beginTransaction(WorkLog.class);
+			emc.beginTransaction(Task.class);
+			emc.beginTransaction(TaskCompleted.class);
+			emc.beginTransaction(Read.class);
+			emc.beginTransaction(ReadCompleted.class);
+			emc.beginTransaction(Review.class);
+
+			this.rollbackWork(work, workLog);
+
+			this.disconnectWorkLog(work, workLog);
+
+			this.rollbackTask(business, emc.listEqual(Task.class, Task.job_FIELDNAME, work.getJob()));
+
+			this.rollbackTaskCompleted(business, work, nodes, workLog,
+					emc.listEqual(TaskCompleted.class, TaskCompleted.job_FIELDNAME, work.getJob()));
+
+			this.rollbackRead(business, work, nodes, workLog,
+					emc.listEqual(Read.class, Read.job_FIELDNAME, work.getJob()));
+
+			this.rollbackReadCompleted(business, work, nodes, workLog,
+					emc.listEqual(ReadCompleted.class, ReadCompleted.job_FIELDNAME, work.getJob()));
+
+			this.rollbackReview(business, nodes, emc.listEqual(Review.class, Review.job_FIELDNAME, work.getJob()));
+
+			this.rollbackWorkLog(business, work, nodes, workLogs);
+
+			emc.commit();
+
+			Processing processing = new Processing(wi);
+			processing.processing(work.getId());
+			Wo wo = new Wo();
+			wo.setId(work.getId());
+			result.setData(wo);
+			return result;
+		}
+	}
+
+	private void rollbackWork(Work work, WorkLog workLog) throws Exception {
+		work.setSplitting(false);
+		work.setActivityName(workLog.getFromActivityName());
+		work.setActivity(workLog.getFromActivity());
+		work.setActivityAlias(workLog.getFromActivityAlias());
+		work.setActivityArrivedTime(workLog.getFromTime());
+		work.setActivityDescription("");
+		work.setActivityToken(workLog.getFromActivityToken());
+		work.setActivityType(workLog.getFromActivityType());
+		work.setErrorRetry(0);
+		work.setWorkStatus(WorkStatus.processing);
+	}
+
+	private void disconnectWorkLog(Work work, WorkLog workLog) {
+		workLog.setConnected(false);
+		workLog.setArrivedActivity("");
+		workLog.setArrivedActivityAlias("");
+		workLog.setArrivedActivityName("");
+		workLog.setArrivedActivityToken("");
+		workLog.setArrivedActivityType(null);
+		workLog.setArrivedTime(null);
+		workLog.setDuration(0L);
+		workLog.setWorkCompleted("");
+		workLog.setWork(work.getId());
+	}
+
+	private void rollbackTask(Business business, List<Task> list) throws Exception {
+		for (Task o : list) {
+			business.entityManagerContainer().remove(o);
+			MessageFactory.task_delete(o);
+		}
+	}
+
+	private void rollbackTaskCompleted(Business business, Work work, Nodes nodes, WorkLog workLog,
+			List<TaskCompleted> list) throws Exception {
+		for (TaskCompleted o : list) {
+			if (!nodes.containsWorkLogWithActivityToken(o.getActivityToken())
+					|| StringUtils.equals(o.getActivityToken(), workLog.getFromActivityToken())) {
+				business.entityManagerContainer().remove(o);
+				MessageFactory.taskCompleted_delete(o);
+			} else {
+				o.setCompleted(false);
+				o.setCompletedTime(null);
+				o.setCompletedTimeMonth("");
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
+		}
+	}
+
+	private void rollbackRead(Business business, Work work, Nodes nodes, WorkLog workLog, List<Read> list)
+			throws Exception {
+		for (Read o : list) {
+			if (!nodes.containsWorkLogWithActivityToken(o.getActivityToken())
+					|| StringUtils.equals(o.getActivityToken(), workLog.getFromActivityToken())) {
+				business.entityManagerContainer().remove(o);
+				MessageFactory.read_delete(o);
+			} else {
+				o.setCompleted(false);
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
+		}
+	}
+
+	private void rollbackReadCompleted(Business business, Work work, Nodes nodes, WorkLog workLog,
+			List<ReadCompleted> list) throws Exception {
+		for (ReadCompleted o : list) {
+			if (!nodes.containsWorkLogWithActivityToken(o.getActivityToken())
+					|| StringUtils.equals(o.getActivityToken(), workLog.getFromActivityToken())) {
+				business.entityManagerContainer().remove(o);
+				MessageFactory.readCompleted_delete(o);
+			} else {
+				o.setCompleted(false);
+				o.setCompletedTime(null);
+				o.setCompletedTimeMonth("");
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
+		}
+	}
+
+	private void rollbackReview(Business business, Nodes nodes, List<Review> list) throws Exception {
+		Date date = nodes.latestArrivedTime();
+		if (null != date) {
+			for (Review o : list) {
+				if (null != o.getStartTime() && o.getStartTime().after(date)) {
+					business.entityManagerContainer().remove(o);
+					MessageFactory.review_delete(o);
+				} else {
+					o.setCompleted(false);
+					o.setCompletedTime(null);
+					o.setCompletedTimeMonth("");
+				}
+			}
+		}
+	}
+
+	private void rollbackWorkLog(Business business, Work work, Nodes nodes, List<WorkLog> list) throws Exception {
+		for (WorkLog o : list) {
+			if (!nodes.containsWorkLog(o)) {
+				business.entityManagerContainer().remove(o);
+			} else {
+				o.setCompleted(false);
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
+		}
+	}
+
+	public static class Wi extends ProcessingAttributes {
+
+		@FieldDescribe("工作日志标识")
+		private String workLog;
+
+		public String getWorkLog() {
+			return workLog;
+		}
+
+		public void setWorkLog(String workLog) {
+			this.workLog = workLog;
+		}
+
+	}
+
+	public static class Wo extends WoId {
+	}
+}

+ 12 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ExceptionInvalidArrivedWorkLog.java

@@ -0,0 +1,12 @@
+package com.x.processplatform.service.processing.jaxrs.work;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionInvalidArrivedWorkLog extends PromptException {
+
+	private static final long serialVersionUID = -3439770681867963457L;
+
+	ExceptionInvalidArrivedWorkLog(String work) {
+		super("无法找到指定的到达工作日志, 工作:{}.");
+	}
+}

+ 12 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ExceptionInvalidFromWorkLog.java

@@ -0,0 +1,12 @@
+package com.x.processplatform.service.processing.jaxrs.work;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionInvalidFromWorkLog extends PromptException {
+
+	private static final long serialVersionUID = -3439770681867963457L;
+
+	ExceptionInvalidFromWorkLog(String work) {
+		super("无法找到指定的出发工作日志, 工作:{}.");
+	}
+}

+ 0 - 12
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ExceptionInvalidWorkLog.java

@@ -1,12 +0,0 @@
-package com.x.processplatform.service.processing.jaxrs.work;
-
-import com.x.base.core.project.exception.PromptException;
-
-class ExceptionInvalidWorkLog extends PromptException {
-
-	private static final long serialVersionUID = -3439770681867963457L;
-
-	ExceptionInvalidWorkLog(String activityToken,Integer count) {
-		super("无效工作日志,activityToken:{}, count:{}.", activityToken,count);
-	}
-}

+ 12 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ExceptionSplittingNotRollback.java

@@ -0,0 +1,12 @@
+package com.x.processplatform.service.processing.jaxrs.work;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionSplittingNotRollback extends PromptException {
+
+	private static final long serialVersionUID = -3439770681867963457L;
+
+	ExceptionSplittingNotRollback(String workId, String workLogId) {
+		super("工作无法回滚到处于拆分的状态,work:{}, workLog:{}.", workId, workLogId);
+	}
+}

+ 5 - 5
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/WorkAction.java

@@ -158,17 +158,17 @@ public class WorkAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
 
-	@JaxrsMethodDescribe(value = "回滚指定的工作到指定的workLog.", action = ActionCallback.class)
+	@JaxrsMethodDescribe(value = "回滚指定的工作到指定的workLog.", action = ActionRollback.class)
 	@PUT
-	@Path("{id}/callback")
+	@Path("{id}/rollback")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
-	public void callback(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+	public void rollback(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
 			@JaxrsParameterDescribe("工作标识") @PathParam("id") String id, JsonElement jsonElement) {
-		ActionResult<ActionCallback.Wo> result = new ActionResult<>();
+		ActionResult<ActionRollback.Wo> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
 		try {
-			result = new ActionCallback().execute(effectivePerson, id, jsonElement);
+			result = new ActionRollback().execute(effectivePerson, id, jsonElement);
 		} catch (Exception e) {
 			logger.error(e, effectivePerson, request, null);
 			result.error(e);

+ 251 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/workcompleted/ActionRollback.java

@@ -0,0 +1,251 @@
+package com.x.processplatform.service.processing.jaxrs.workcompleted;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import com.google.gson.JsonElement;
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.annotation.CheckPersistType;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WoId;
+import com.x.processplatform.core.entity.content.Attachment;
+import com.x.processplatform.core.entity.content.Read;
+import com.x.processplatform.core.entity.content.ReadCompleted;
+import com.x.processplatform.core.entity.content.Review;
+import com.x.processplatform.core.entity.content.TaskCompleted;
+import com.x.processplatform.core.entity.content.Work;
+import com.x.processplatform.core.entity.content.WorkCompleted;
+import com.x.processplatform.core.entity.content.WorkLog;
+import com.x.processplatform.core.entity.content.WorkStatus;
+import com.x.processplatform.core.entity.element.Application;
+import com.x.processplatform.core.entity.element.Process;
+import com.x.processplatform.core.entity.element.util.WorkLogTree;
+import com.x.processplatform.core.entity.element.util.WorkLogTree.Node;
+import com.x.processplatform.core.entity.element.util.WorkLogTree.Nodes;
+import com.x.processplatform.service.processing.Business;
+import com.x.processplatform.service.processing.Processing;
+import com.x.processplatform.service.processing.ProcessingAttributes;
+
+class ActionRollback extends BaseAction {
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, String flag, JsonElement jsonElement) throws Exception {
+
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+
+			ActionResult<Wo> result = new ActionResult<>();
+
+			Business business = new Business(emc);
+
+			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
+
+			WorkCompleted workCompleted = emc.flag(flag, WorkCompleted.class);
+
+			if (null == workCompleted) {
+				throw new ExceptionEntityNotExist(flag, WorkCompleted.class);
+			}
+
+			Application application = business.element().get(workCompleted.getApplication(), Application.class);
+
+			if (null == application) {
+				throw new ExceptionEntityNotExist(workCompleted.getApplication(), Application.class);
+			}
+
+			Process process = business.element().get(workCompleted.getProcess(), Process.class);
+
+			if (null == process) {
+				throw new ExceptionEntityNotExist(workCompleted.getProcess(), Process.class);
+			}
+
+			WorkLog workLog = emc.find(wi.getWorkLog(), WorkLog.class);
+
+			if (null == workLog) {
+				throw new ExceptionEntityNotExist(wi.getWorkLog(), WorkLog.class);
+			}
+
+			if (BooleanUtils.isTrue(workLog.getSplitting())) {
+				throw new ExceptionSplittingNotRollback(workCompleted.getId(), workLog.getId());
+			}
+
+			List<WorkLog> workLogs = emc.listEqual(WorkLog.class, WorkLog.job_FIELDNAME, workLog.getJob());
+
+			WorkLogTree workLogTree = new WorkLogTree(workLogs);
+
+			Node node = workLogTree.find(workLog);
+
+			Nodes nodes = workLogTree.rootTo(node);
+
+			emc.beginTransaction(Work.class);
+			emc.beginTransaction(WorkCompleted.class);
+			emc.beginTransaction(WorkLog.class);
+			emc.beginTransaction(Attachment.class);
+			emc.beginTransaction(TaskCompleted.class);
+			emc.beginTransaction(Read.class);
+			emc.beginTransaction(ReadCompleted.class);
+			emc.beginTransaction(Review.class);
+
+			Work work = this.createWork(workCompleted, workLog);
+			emc.persist(work, CheckPersistType.all);
+
+			this.disconnectWorkLog(work, workLog);
+
+			this.rollbackTaskCompleted(business, work, nodes, workLog,
+					emc.listEqual(TaskCompleted.class, TaskCompleted.job_FIELDNAME, work.getJob()));
+
+			this.rollbackRead(business, work, nodes, workLog,
+					emc.listEqual(Read.class, Read.job_FIELDNAME, work.getJob()));
+
+			this.rollbackReadCompleted(business, work, nodes, workLog,
+					emc.listEqual(ReadCompleted.class, ReadCompleted.job_FIELDNAME, work.getJob()));
+
+			this.rollbackReview(business, work, nodes,
+					emc.listEqual(Review.class, Review.job_FIELDNAME, work.getJob()));
+
+			this.rollbackWorkLog(business, work, nodes, workLogs);
+
+			this.rollbackAttachment(business, work,
+					emc.listEqual(Attachment.class, Attachment.job_FIELDNAME, work.getJob()));
+
+			emc.remove(workCompleted);
+
+			emc.commit();
+
+			Processing processing = new Processing(wi);
+			processing.processing(work.getId());
+			Wo wo = new Wo();
+			wo.setId(work.getId());
+			result.setData(wo);
+			return result;
+		}
+	}
+
+	private Work createWork(WorkCompleted workCompleted, WorkLog workLog) throws Exception {
+		Work work = new Work(workCompleted);
+		work.setSplitting(false);
+		work.setActivityName(workLog.getFromActivityName());
+		work.setActivity(workLog.getFromActivity());
+		work.setActivityAlias(workLog.getFromActivityAlias());
+		work.setActivityArrivedTime(workLog.getFromTime());
+		work.setActivityDescription("");
+		work.setActivityToken(workLog.getFromActivityToken());
+		work.setActivityType(workLog.getFromActivityType());
+		work.setErrorRetry(0);
+		work.setWorkStatus(WorkStatus.processing);
+		return work;
+	}
+
+	private void disconnectWorkLog(Work work, WorkLog workLog) {
+		workLog.setConnected(false);
+		workLog.setArrivedActivity("");
+		workLog.setArrivedActivityAlias("");
+		workLog.setArrivedActivityName("");
+		workLog.setArrivedActivityToken("");
+		workLog.setArrivedActivityType(null);
+		workLog.setArrivedTime(null);
+		workLog.setDuration(0L);
+		workLog.setWorkCompleted("");
+		workLog.setWork(work.getId());
+	}
+
+	private void rollbackTaskCompleted(Business business, Work work, Nodes nodes, WorkLog workLog,
+			List<TaskCompleted> list) throws Exception {
+		for (TaskCompleted o : list) {
+			if (!nodes.containsWorkLogWithActivityToken(o.getActivityToken())
+					|| StringUtils.equals(o.getActivityToken(), workLog.getFromActivityToken())) {
+				business.entityManagerContainer().remove(o);
+			} else {
+				o.setCompleted(false);
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
+		}
+	}
+
+	private void rollbackRead(Business business, Work work, Nodes nodes, WorkLog workLog, List<Read> list)
+			throws Exception {
+		for (Read o : list) {
+			if (!nodes.containsWorkLogWithActivityToken(o.getActivityToken())
+					|| StringUtils.equals(o.getActivityToken(), workLog.getFromActivityToken())) {
+				business.entityManagerContainer().remove(o);
+			} else {
+				o.setCompleted(false);
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
+		}
+	}
+
+	private void rollbackReadCompleted(Business business, Work work, Nodes nodes, WorkLog workLog,
+			List<ReadCompleted> list) throws Exception {
+		for (ReadCompleted o : list) {
+			if (!nodes.containsWorkLogWithActivityToken(o.getActivityToken())
+					|| StringUtils.equals(o.getActivityToken(), workLog.getFromActivityToken())) {
+				business.entityManagerContainer().remove(o);
+			} else {
+				o.setCompleted(false);
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
+		}
+	}
+
+	private void rollbackReview(Business business, Work work, Nodes nodes, List<Review> list) throws Exception {
+		Date date = nodes.latestArrivedTime();
+		if (null != date) {
+			for (Review o : list) {
+				if (null != o.getStartTime() && o.getStartTime().after(date)) {
+					business.entityManagerContainer().remove(o);
+				} else {
+					o.setCompleted(false);
+					o.setWorkCompleted("");
+					o.setWork(work.getId());
+				}
+			}
+		}
+	}
+
+	private void rollbackAttachment(Business business, Work work, List<Attachment> list) throws Exception {
+		for (Attachment o : list) {
+			o.setCompleted(false);
+			o.setWork(work.getId());
+			o.setWorkCompleted("");
+		}
+	}
+
+	private void rollbackWorkLog(Business business, Work work, Nodes nodes, List<WorkLog> list) throws Exception {
+		for (WorkLog o : list) {
+			if (!nodes.containsWorkLog(o)) {
+				business.entityManagerContainer().remove(o);
+			} else {
+				o.setCompleted(false);
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
+		}
+	}
+
+	public static class Wi extends ProcessingAttributes {
+
+		@FieldDescribe("工作日志标识")
+		private String workLog;
+
+		public String getWorkLog() {
+			return workLog;
+		}
+
+		public void setWorkLog(String workLog) {
+			this.workLog = workLog;
+		}
+
+	}
+
+	public static class Wo extends WoId {
+	}
+
+}

+ 7 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/workcompleted/BaseAction.java

@@ -0,0 +1,7 @@
+package com.x.processplatform.service.processing.jaxrs.workcompleted;
+
+import com.x.base.core.project.jaxrs.StandardJaxrsAction;
+
+abstract class BaseAction extends StandardJaxrsAction {
+
+}

+ 12 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/workcompleted/ExceptionSplittingNotRollback.java

@@ -0,0 +1,12 @@
+package com.x.processplatform.service.processing.jaxrs.workcompleted;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionSplittingNotRollback extends PromptException {
+
+	private static final long serialVersionUID = -3439770681867963457L;
+
+	ExceptionSplittingNotRollback(String workId, String workLogId) {
+		super("工作无法回滚到处于拆分的状态,work:{}, workLog:{}.", workId, workLogId);
+	}
+}

+ 50 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/workcompleted/WorkCompletedAction.java

@@ -0,0 +1,50 @@
+package com.x.processplatform.service.processing.jaxrs.workcompleted;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+
+import com.google.gson.JsonElement;
+import com.x.base.core.project.annotation.JaxrsDescribe;
+import com.x.base.core.project.annotation.JaxrsMethodDescribe;
+import com.x.base.core.project.annotation.JaxrsParameterDescribe;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.http.HttpMediaType;
+import com.x.base.core.project.jaxrs.ResponseFactory;
+import com.x.base.core.project.jaxrs.StandardJaxrsAction;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+
+@Path("workcompleted")
+@JaxrsDescribe("完成工作")
+public class WorkCompletedAction extends StandardJaxrsAction {
+
+	private static Logger logger = LoggerFactory.getLogger(WorkCompletedAction.class);
+
+	@JaxrsMethodDescribe(value = "回滚指定的完成工作到指定的workLog.", action = ActionRollback.class)
+	@PUT
+	@Path("{flag}/rollback")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void rollback(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("完成工作") @PathParam("flag") String flag, JsonElement jsonElement) {
+		ActionResult<ActionRollback.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionRollback().execute(effectivePerson, flag, jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
+}

+ 8 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/workcompleted/package-info.java

@@ -0,0 +1,8 @@
+/**
+ * 
+ */
+/**
+ * @author zhour
+ *
+ */
+package com.x.processplatform.service.processing.jaxrs.workcompleted;

+ 1 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/end/EndProcessor.java

@@ -51,6 +51,7 @@ public class EndProcessor extends AbstractEndProcessor {
 				.sorted(Comparator.comparing(Work::getCreateTime, Comparator.nullsLast(Date::compareTo))).findFirst()
 				.get();
 		WorkCompleted workCompleted = this.createWorkCompleted(oldest);
+		workCompleted.setAllowRollback(end.getAllowRollback());
 		aeiObjects.getCreateWorkCompleteds().add(workCompleted);
 		aeiObjects.getTasks().stream().forEach(o -> aeiObjects.getDeleteTasks().add(o));
 		aeiObjects.getHints().stream().forEach(o -> aeiObjects.getDeleteHints().add(o));

+ 3 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/manual/ManualProcessor.java

@@ -197,6 +197,9 @@ public class ManualProcessor extends AbstractManualProcessor {
 		case queue:
 			passThrough = this.queue(aeiObjects, manual);
 			break;
+		case grab:
+			passThrough = this.single(aeiObjects, manual);
+			break;
 		default:
 			throw new ExceptionManualModeError(manual.getId());
 		}

+ 70 - 0
o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/config/ConfigAction.java

@@ -218,4 +218,74 @@ public class ConfigAction extends StandardJaxrsAction {
 		}
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
+
+	@JaxrsMethodDescribe(value = "获取钉钉配置.", action = ActionGetDingding.class)
+	@GET
+	@Path("dingding")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void getDingding(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request) {
+		ActionResult<ActionGetDingding.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionGetDingding().execute(effectivePerson);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
+	@JaxrsMethodDescribe(value = "更新钉钉配置.", action = ActionSetDingding.class)
+	@PUT
+	@Path("dingding")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void setDingding(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			JsonElement jsonElement) {
+		ActionResult<ActionSetDingding.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionSetDingding().execute(effectivePerson, jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, jsonElement);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
+	@JaxrsMethodDescribe(value = "获取企业微信配置.", action = ActionGetQiyeweixin.class)
+	@GET
+	@Path("qiyeweixin")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void getQiyeweixin(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request) {
+		ActionResult<ActionGetQiyeweixin.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionGetQiyeweixin().execute(effectivePerson);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
+	@JaxrsMethodDescribe(value = "更新企业微信配置.", action = ActionSetQiyeweixin.class)
+	@PUT
+	@Path("qiyeweixin")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void setQiyeweixin(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			JsonElement jsonElement) {
+		ActionResult<ActionSetQiyeweixin.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionSetQiyeweixin().execute(effectivePerson, jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, jsonElement);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
 }