Răsfoiți Sursa

Merge branch 'feature/#441' into 'wrdp'

添加AbandonedWorkCompleted接口

See merge request o2oa/o2oa!2605
o2null 5 ani în urmă
părinte
comite
75320a7b4e
12 a modificat fișierele cu 381 adăugiri și 46 ștergeri
  1. 0 28
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/schedule/TestJob.java
  2. 55 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/snap/ActionTypeAbandonedWorkCompleted.java
  3. 19 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/snap/SnapAction.java
  4. 16 0
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Snap.java
  5. 11 0
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/SnapProperties.java
  6. 7 2
      o2server/x_processplatform_core_express/src/main/java/com/x/processplatform/core/express/service/processing/jaxrs/taskcompleted/WrapUpdateNextTaskIdentity.java
  7. 23 9
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/WorkDataHelper.java
  8. 2 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/review/ActionCreateWithWorkCompleted.java
  9. 65 7
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/snap/ActionRestore.java
  10. 95 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/snap/ActionTypeAbandonedWorkCompleted.java
  11. 69 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/snap/BaseAction.java
  12. 19 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/snap/SnapAction.java

+ 0 - 28
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/schedule/TestJob.java

@@ -1,28 +0,0 @@
-package com.x.organization.assemble.authentication.schedule;
-
-import java.util.Date;
-
-import org.quartz.Job;
-import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
-
-import com.x.base.core.container.EntityManagerContainer;
-import com.x.base.core.container.factory.EntityManagerContainerFactory;
-import com.x.base.core.project.logger.Logger;
-import com.x.base.core.project.logger.LoggerFactory;
-
-public class TestJob implements Job {
-
-	private static Logger logger = LoggerFactory.getLogger(TestJob.class);
-
-	@Override
-	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
-		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
-			logger.print("run at {}", new Date());
-		} catch (Exception e) {
-			logger.error(e);
-			throw new JobExecutionException(e);
-		}
-	}
-
-}

+ 55 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/snap/ActionTypeAbandonedWorkCompleted.java

@@ -0,0 +1,55 @@
+package com.x.processplatform.assemble.surface.jaxrs.snap;
+
+import org.apache.commons.lang3.BooleanUtils;
+
+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.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.jaxrs.WoId;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.assemble.surface.ThisApplication;
+import com.x.processplatform.core.entity.content.WorkCompleted;
+
+class ActionTypeAbandonedWorkCompleted extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionTypeAbandonedWorkCompleted.class);
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, String workCompletedId) throws Exception {
+		String job = null;
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			Business business = new Business(emc);
+			WorkCompleted workCompleted = emc.find(workCompletedId, WorkCompleted.class);
+			if (null == workCompleted) {
+				throw new ExceptionEntityNotExist(workCompletedId, WorkCompleted.class);
+			}
+			if (BooleanUtils.isFalse(business.canManageApplicationOrProcess(effectivePerson,
+					workCompleted.getApplication(), workCompleted.getProcess()))) {
+				throw new ExceptionAccessDenied(effectivePerson, workCompleted);
+			}
+			job = workCompleted.getJob();
+		}
+
+		Wo wo = ThisApplication.context().applications()
+				.getQuery(effectivePerson.getDebugger(), x_processplatform_service_processing.class, Applications
+						.joinQueryUri("snap", "workcompleted", workCompletedId, "type", "abandonedworkcompleted"), job)
+				.getData(Wo.class);
+		ActionResult<Wo> result = new ActionResult<>();
+		result.setData(wo);
+		return result;
+
+	}
+
+	public static class Wo extends WoId {
+
+		private static final long serialVersionUID = -2577413577740827608L;
+
+	}
+
+}

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

@@ -69,6 +69,25 @@ public class SnapAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 
+	@JaxrsMethodDescribe(value = "对已完成工作进行快照,并标记为废弃", action = ActionTypeAbandonedWorkCompleted.class)
+	@GET
+	@Path("workcompleted/{workCompletedId}/type/abandonedworkcompleted")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void typeAbandonedWorkCompleted(@Suspended final AsyncResponse asyncResponse,
+			@Context HttpServletRequest request,
+			@JaxrsParameterDescribe("工作标识") @PathParam("workCompletedId") String workCompletedId) {
+		ActionResult<ActionTypeAbandonedWorkCompleted.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionTypeAbandonedWorkCompleted().execute(effectivePerson, workCompletedId);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
 	@JaxrsMethodDescribe(value = "挂起工作", action = ActionTypeSuspend.class)
 	@GET
 	@Path("work/{workId}/type/suspend")

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

@@ -44,6 +44,8 @@ public class Snap extends SliceJpaObject {
 
 	public static final String TYPE_ABANDONED = "abandoned";
 
+	public static final String TYPE_ABANDONEDWORKCOMPLETED = "abandonedWorkCompleted";
+
 	public String getId() {
 		return id;
 	}
@@ -108,6 +110,20 @@ public class Snap extends SliceJpaObject {
 		this.setActivityType(work.getActivityType());
 	}
 
+	public Snap(WorkCompleted workCompleted) {
+		this.setTitle(workCompleted.getTitle());
+		this.setJob(workCompleted.getJob());
+		this.setApplication(workCompleted.getApplication());
+		this.setApplicationName(workCompleted.getApplicationName());
+		this.setApplicationAlias(workCompleted.getApplicationAlias());
+		this.setProcess(workCompleted.getProcess());
+		this.setProcessName(workCompleted.getProcessName());
+		this.setProcessAlias(workCompleted.getProcessAlias());
+		this.setCreatorIdentity(workCompleted.getCreatorIdentity());
+		this.setCreatorPerson(workCompleted.getCreatorPerson());
+		this.setCreatorUnit(workCompleted.getCreatorUnit());
+	}
+
 	public SnapProperties getProperties() {
 		if (null == this.properties) {
 			this.properties = new SnapProperties();

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

@@ -22,6 +22,9 @@ public class SnapProperties extends JsonProperties {
 	@FieldDescribe("工作")
 	private List<Work> workList = new ArrayList<>();
 
+	@FieldDescribe("已完成工作")
+	private WorkCompleted workCompleted;
+
 	@FieldDescribe("待办")
 	private List<Task> taskList = new ArrayList<>();
 
@@ -183,4 +186,12 @@ public class SnapProperties extends JsonProperties {
 		documentVersionList = documentVersionList;
 	}
 
+	public WorkCompleted getWorkCompleted() {
+		return workCompleted;
+	}
+
+	public void setWorkCompleted(WorkCompleted workCompleted) {
+		this.workCompleted = workCompleted;
+	}
+
 }

+ 7 - 2
o2server/x_processplatform_core_express/src/main/java/com/x/processplatform/core/express/service/processing/jaxrs/taskcompleted/WrapUpdateNextTaskIdentity.java

@@ -3,17 +3,22 @@ package com.x.processplatform.core.express.service.processing.jaxrs.taskcomplete
 import java.util.ArrayList;
 import java.util.List;
 
+import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.gson.GsonPropertyObject;
 
 public class WrapUpdateNextTaskIdentity extends GsonPropertyObject {
 
+	private static final long serialVersionUID = -597948505960097189L;
+
+	@FieldDescribe("后续环节待办人")
 	private List<String> nextTaskIdentityList = new ArrayList<>();
 
+	@FieldDescribe("已办标识")
 	private List<String> taskCompletedList = new ArrayList<>();
 
 	public List<String> getNextTaskIdentityList() {
 		if (null == this.nextTaskIdentityList) {
-			this.nextTaskIdentityList = new ArrayList<String>();
+			this.nextTaskIdentityList = new ArrayList<>();
 		}
 		return nextTaskIdentityList;
 	}
@@ -24,7 +29,7 @@ public class WrapUpdateNextTaskIdentity extends GsonPropertyObject {
 
 	public List<String> getTaskCompletedList() {
 		if (null == this.taskCompletedList) {
-			this.taskCompletedList = new ArrayList<String>();
+			this.taskCompletedList = new ArrayList<>();
 		}
 		return taskCompletedList;
 	}

+ 23 - 9
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/WorkDataHelper.java

@@ -15,11 +15,13 @@ import org.apache.commons.lang3.StringUtils;
 import com.google.gson.Gson;
 import com.google.gson.JsonElement;
 import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.entity.dataitem.DataItem;
 import com.x.base.core.entity.dataitem.DataItemConverter;
 import com.x.base.core.entity.dataitem.ItemCategory;
 import com.x.base.core.project.gson.XGsonBuilder;
 import com.x.processplatform.core.entity.content.Data;
 import com.x.processplatform.core.entity.content.Work;
+import com.x.processplatform.core.entity.content.WorkCompleted;
 import com.x.query.core.entity.Item;
 import com.x.query.core.entity.Item_;
 
@@ -43,7 +45,22 @@ public class WorkDataHelper {
 			throw new Exception("can not create DataHelper job is empty.");
 		}
 		this.emc = emc;
-		this.converter = new DataItemConverter<Item>(Item.class);
+		this.converter = new DataItemConverter<>(Item.class);
+		this.gson = XGsonBuilder.instance();
+		this.items = this.load();
+	}
+
+	public WorkDataHelper(EntityManagerContainer emc, WorkCompleted workCompleted) throws Exception {
+		if ((null == emc) || (null == workCompleted)) {
+			throw new Exception("create instance error.");
+		}
+		this.job = workCompleted.getJob();
+		this.distributeFactor = workCompleted.getDistributeFactor();
+		if (StringUtils.isEmpty(this.job)) {
+			throw new Exception("can not create DataHelper job is empty.");
+		}
+		this.emc = emc;
+		this.converter = new DataItemConverter<>(Item.class);
 		this.gson = XGsonBuilder.instance();
 		this.items = this.load();
 	}
@@ -53,11 +70,10 @@ public class WorkDataHelper {
 		CriteriaBuilder cb = em.getCriteriaBuilder();
 		CriteriaQuery<Item> cq = cb.createQuery(Item.class);
 		Root<Item> root = cq.from(Item.class);
-		Path<String> path = root.get(Item.bundle_FIELDNAME);
+		Path<String> path = root.get(DataItem.bundle_FIELDNAME);
 		Predicate p = cb.equal(path, this.job);
 		p = cb.and(p, cb.equal(root.get(Item_.itemCategory), ItemCategory.pp));
-		List<Item> list = em.createQuery(cq.where(p)).getResultList();
-		return list;
+		return em.createQuery(cq.where(p)).getResultList();
 	}
 
 	public Data get() throws Exception {
@@ -69,7 +85,7 @@ public class WorkDataHelper {
 				if (jsonElement.isJsonObject()) {
 					return gson.fromJson(jsonElement, Data.class);
 				} else {
-					/* 如果不是Object强制返回一个Map对象 */
+					// 如果不是Object强制返回一个Map对象
 					return new Data();
 				}
 			}
@@ -80,13 +96,11 @@ public class WorkDataHelper {
 
 	public boolean update(JsonElement jsonElement) throws Exception {
 		if (jsonElement.isJsonNull()) {
-			// throw new Exception("can not update data null.");
-			/** 如果是空数据就不更新,避免数据被清空 */
+			// 如果是空数据就不更新,避免数据被清空
 			return false;
 		}
 		if (jsonElement.isJsonPrimitive()) {
-			// throw new Exception("can not update data primitive.");
-			/** 如果是空数据就不更新,避免数据被清空 */
+			// 如果是空数据就不更新,避免数据被清空 */
 			return false;
 		}
 		if (jsonElement.isJsonObject()) {

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

@@ -9,6 +9,7 @@ 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.executor.ProcessPlatformExecutorFactory;
 import com.x.base.core.project.gson.GsonPropertyObject;
@@ -79,6 +80,7 @@ class ActionCreateWithWorkCompleted extends BaseAction {
 
 	public static class Wi extends GsonPropertyObject {
 
+		@FieldDescribe("已完成工作标识")
 		private String workCompleted;
 
 		private List<String> personList = new ArrayList<>();

+ 65 - 7
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/snap/ActionRestore.java

@@ -1,10 +1,13 @@
 package com.x.processplatform.service.processing.jaxrs.snap;
 
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.commons.lang3.BooleanUtils;
+
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.entity.annotation.CheckPersistType;
@@ -28,6 +31,7 @@ import com.x.processplatform.core.entity.content.Snap;
 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.WorkCompleted;
 import com.x.processplatform.core.entity.content.WorkLog;
 import com.x.processplatform.service.processing.Business;
 import com.x.processplatform.service.processing.ThisApplication;
@@ -66,14 +70,28 @@ class ActionRestore extends BaseAction {
 				if (null == snap) {
 					throw new ExceptionEntityNotExist(id, Snap.class);
 				}
-				CompletableFuture.allOf(deleteItem(business, snap.getJob()), deleteWork(business, snap.getJob()),
-						deleteTask(business, snap.getJob()), deleteTaskCompleted(business, snap.getJob()),
-						deleteRead(business, snap.getJob()), deleteReadCompleted(business, snap.getJob()),
-						deleteReview(business, snap.getJob()), deleteWorkLog(business, snap.getJob()),
-						deleteRecord(business, snap.getJob()), deleteAttachment(business, snap.getJob()),
-						deleteDocumentVersion(business, snap.getJob())).get();
+				if (Objects.equals(Snap.TYPE_ABANDONEDWORKCOMPLETED, snap.getType())) {
+					CompletableFuture.allOf(deleteItem(business, snap.getJob()),
+							deleteWorkCompleted(business, snap.getJob()), deleteTask(business, snap.getJob()),
+							deleteTaskCompleted(business, snap.getJob()), deleteRead(business, snap.getJob()),
+							deleteReadCompleted(business, snap.getJob()), deleteReview(business, snap.getJob()),
+							deleteWorkLog(business, snap.getJob()), deleteRecord(business, snap.getJob()),
+							deleteAttachment(business, snap.getJob()), deleteDocumentVersion(business, snap.getJob()))
+							.get();
+				} else {
+					CompletableFuture.allOf(deleteItem(business, snap.getJob()), deleteWork(business, snap.getJob()),
+							deleteTask(business, snap.getJob()), deleteTaskCompleted(business, snap.getJob()),
+							deleteRead(business, snap.getJob()), deleteReadCompleted(business, snap.getJob()),
+							deleteReview(business, snap.getJob()), deleteWorkLog(business, snap.getJob()),
+							deleteRecord(business, snap.getJob()), deleteAttachment(business, snap.getJob()),
+							deleteDocumentVersion(business, snap.getJob())).get();
+				}
 				emc.commit();
-				restore(business, snap);
+				if (Objects.equals(Snap.TYPE_ABANDONEDWORKCOMPLETED, snap.getType())) {
+					restoreWorkCompleted(business, snap);
+				} else {
+					restore(business, snap);
+				}
 				emc.commit();
 				emc.beginTransaction(Snap.class);
 				emc.remove(snap, CheckRemoveType.all);
@@ -159,6 +177,46 @@ class ActionRestore extends BaseAction {
 			attachment(business, snap);
 			emc.commit();
 		}
+
+		private void restoreWorkCompleted(Business business, Snap snap) throws Exception {
+			EntityManagerContainer emc = business.entityManagerContainer();
+			emc.beginTransaction(WorkCompleted.class);
+			emc.beginTransaction(TaskCompleted.class);
+			emc.beginTransaction(Read.class);
+			emc.beginTransaction(ReadCompleted.class);
+			emc.beginTransaction(Review.class);
+			emc.beginTransaction(WorkLog.class);
+			emc.beginTransaction(Record.class);
+			emc.beginTransaction(Item.class);
+			emc.beginTransaction(Attachment.class);
+			for (TaskCompleted o : snap.getProperties().getTaskCompletedList()) {
+				emc.persist(o, CheckPersistType.all);
+			}
+			for (Read o : snap.getProperties().getReadList()) {
+				emc.persist(o, CheckPersistType.all);
+			}
+			for (ReadCompleted o : snap.getProperties().getReadCompletedList()) {
+				emc.persist(o, CheckPersistType.all);
+			}
+			for (Review o : snap.getProperties().getReviewList()) {
+				emc.persist(o, CheckPersistType.all);
+			}
+			for (WorkLog o : snap.getProperties().getWorkLogList()) {
+				emc.persist(o, CheckPersistType.all);
+			}
+			for (Record o : snap.getProperties().getRecordList()) {
+				emc.persist(o, CheckPersistType.all);
+			}
+			for (Attachment o : snap.getProperties().getAttachmentList()) {
+				emc.persist(o, CheckPersistType.all);
+			}
+			emc.persist(snap.getProperties().getWorkCompleted(), CheckPersistType.all);
+			if (BooleanUtils.isNotTrue(snap.getProperties().getWorkCompleted().getMerged())) {
+				WorkDataHelper workDataHelper = new WorkDataHelper(emc, snap.getProperties().getWorkCompleted());
+				workDataHelper.update(snap.getProperties().getData());
+			}
+			emc.commit();
+		}
 	}
 
 	public static class Wo extends WoId {

+ 95 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/snap/ActionTypeAbandonedWorkCompleted.java

@@ -0,0 +1,95 @@
+package com.x.processplatform.service.processing.jaxrs.snap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+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.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.executor.ProcessPlatformExecutorFactory;
+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.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+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.Record;
+import com.x.processplatform.core.entity.content.Review;
+import com.x.processplatform.core.entity.content.Snap;
+import com.x.processplatform.core.entity.content.TaskCompleted;
+import com.x.processplatform.core.entity.content.WorkCompleted;
+import com.x.processplatform.core.entity.content.WorkLog;
+import com.x.processplatform.service.processing.Business;
+import com.x.query.core.entity.Item;
+
+class ActionTypeAbandonedWorkCompleted extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionTypeAbandonedWorkCompleted.class);
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, String workCompletedId) throws Exception {
+		String job = null;
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			WorkCompleted workCompleted = emc.find(workCompletedId, WorkCompleted.class);
+			if (null == workCompleted) {
+				throw new ExceptionEntityNotExist(workCompletedId, WorkCompleted.class);
+			}
+			job = workCompleted.getJob();
+		}
+		return ProcessPlatformExecutorFactory.get(job).submit(new CallableImpl(workCompletedId)).get(300,
+				TimeUnit.SECONDS);
+	}
+
+	public class CallableImpl implements Callable<ActionResult<Wo>> {
+
+		private String id;
+
+		public CallableImpl(String id) {
+			this.id = id;
+		}
+
+		public ActionResult<Wo> call() throws Exception {
+			ActionResult<Wo> result = new ActionResult<>();
+			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+				Business business = new Business(emc);
+				WorkCompleted workCompleted = emc.find(id, WorkCompleted.class);
+				if (null == workCompleted) {
+					throw new ExceptionEntityNotExist(id, WorkCompleted.class);
+				}
+				Snap snap = new Snap(workCompleted);
+				List<Item> items = new ArrayList<>();
+				List<TaskCompleted> taskCompleteds = new ArrayList<>();
+				List<Read> reads = new ArrayList<>();
+				List<ReadCompleted> readCompleteds = new ArrayList<>();
+				List<Review> reviews = new ArrayList<>();
+				List<WorkLog> workLogs = new ArrayList<>();
+				List<Record> records = new ArrayList<>();
+				List<Attachment> attachments = new ArrayList<>();
+				snap.setProperties(snap(business, workCompleted.getJob(), items, workCompleted, taskCompleteds, reads,
+						readCompleteds, reviews, workLogs, records, attachments));
+				snap.setType(Snap.TYPE_ABANDONEDWORKCOMPLETED);
+				emc.beginTransaction(Snap.class);
+				emc.persist(snap, CheckPersistType.all);
+				emc.commit();
+				clean(business, items, workCompleted, taskCompleteds, reads, readCompleteds, reviews, workLogs, records,
+						attachments);
+				emc.commit();
+				Wo wo = new Wo();
+				wo.setId(snap.getId());
+				result.setData(wo);
+				return result;
+			}
+		}
+	}
+
+	public static class Wo extends WoId {
+
+		private static final long serialVersionUID = -2577413577740827608L;
+
+	}
+
+}

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

@@ -1,5 +1,6 @@
 package com.x.processplatform.service.processing.jaxrs.snap;
 
+import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.List;
@@ -7,6 +8,8 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
 
+import org.apache.commons.lang3.BooleanUtils;
+
 import com.google.gson.JsonElement;
 import com.x.base.core.entity.dataitem.DataItem;
 import com.x.base.core.entity.dataitem.DataItemConverter;
@@ -26,6 +29,7 @@ import com.x.processplatform.core.entity.content.SnapProperties;
 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.WorkCompleted;
 import com.x.processplatform.core.entity.content.WorkLog;
 import com.x.processplatform.service.processing.Business;
 import com.x.query.core.entity.Item;
@@ -55,6 +59,35 @@ abstract class BaseAction extends StandardJaxrsAction {
 		return properties;
 	}
 
+	protected SnapProperties snap(Business business, String job, List<Item> items, WorkCompleted workCompleted,
+			List<TaskCompleted> taskCompleteds, List<Read> reads, List<ReadCompleted> readCompleteds,
+			List<Review> reviews, List<WorkLog> workLogs, List<Record> records, List<Attachment> attachments) {
+		SnapProperties properties = new SnapProperties();
+		properties.setJob(job);
+		properties.setWorkCompleted(workCompleted);
+		properties.setTitle(workCompleted.getTitle());
+		List<CompletableFuture<Void>> futures = new ArrayList<>();
+		futures.add(mergeTaskCompleted(business, job, properties, taskCompleteds));
+		futures.add(mergeRead(business, job, properties, reads));
+		futures.add(mergeReadCompleted(business, job, properties, readCompleteds));
+		futures.add(mergeReview(business, job, properties, reviews));
+		futures.add(mergeWorkLog(business, job, properties, workLogs));
+		futures.add(mergeRecord(business, job, properties, records));
+		futures.add(mergeAttachment(business, job, properties, attachments));
+		if (BooleanUtils.isNotTrue(workCompleted.getMerged())) {
+			futures.add(mergeItem(business, job, properties, items));
+		}
+		CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0]));
+//		CompletableFuture.allOf(mergeItem(business, job, properties, items),
+//				mergeTaskCompleted(business, job, properties, taskCompleteds),
+//				mergeRead(business, job, properties, reads),
+//				mergeReadCompleted(business, job, properties, readCompleteds),
+//				mergeReview(business, job, properties, reviews), mergeWorkLog(business, job, properties, workLogs),
+//				mergeRecord(business, job, properties, records),
+//				mergeAttachment(business, job, properties, attachments)).get();
+		return properties;
+	}
+
 	protected void clean(Business business, List<Item> items, List<Work> works, List<Task> tasks,
 			List<TaskCompleted> taskCompleteds, List<Read> reads, List<ReadCompleted> readCompleteds,
 			List<Review> reviews, List<WorkLog> workLogs, List<Record> records, List<Attachment> attachments,
@@ -68,6 +101,17 @@ abstract class BaseAction extends StandardJaxrsAction {
 				.get();
 	}
 
+	protected void clean(Business business, List<Item> items, WorkCompleted workCompleted,
+			List<TaskCompleted> taskCompleteds, List<Read> reads, List<ReadCompleted> readCompleteds,
+			List<Review> reviews, List<WorkLog> workLogs, List<Record> records, List<Attachment> attachments)
+			throws InterruptedException, ExecutionException {
+		CompletableFuture.allOf(deleteItem(business, items), deleteWork(business, workCompleted),
+				deleteTaskCompleted(business, taskCompleteds), deleteRead(business, reads),
+				deleteReadCompleted(business, readCompleteds), deleteReview(business, reviews),
+				deleteWorkLog(business, workLogs), deleteRecord(business, records),
+				deleteAttachment(business, attachments)).get();
+	}
+
 	private CompletableFuture<Void> mergeItem(Business business, String job, SnapProperties snapProperties,
 			List<Item> items) {
 		return CompletableFuture.runAsync(() -> {
@@ -270,6 +314,17 @@ abstract class BaseAction extends StandardJaxrsAction {
 		});
 	}
 
+	private CompletableFuture<Void> deleteWork(Business business, WorkCompleted workCompleted) {
+		return CompletableFuture.runAsync(() -> {
+			try {
+				business.entityManagerContainer().beginTransaction(WorkCompleted.class);
+				business.entityManagerContainer().remove(workCompleted);
+			} catch (Exception e) {
+				logger.error(e);
+			}
+		});
+	}
+
 	private CompletableFuture<Void> deleteTask(Business business, List<Task> tasks) {
 		return CompletableFuture.runAsync(() -> {
 			try {
@@ -413,6 +468,20 @@ abstract class BaseAction extends StandardJaxrsAction {
 		});
 	}
 
+	protected CompletableFuture<Void> deleteWorkCompleted(Business business, String job) {
+		return CompletableFuture.runAsync(() -> {
+			try {
+				business.entityManagerContainer().beginTransaction(WorkCompleted.class);
+				for (WorkCompleted o : business.entityManagerContainer().listEqual(WorkCompleted.class,
+						WorkCompleted.job_FIELDNAME, job)) {
+					business.entityManagerContainer().remove(o);
+				}
+			} catch (Exception e) {
+				logger.error(e);
+			}
+		});
+	}
+
 	protected CompletableFuture<Void> deleteTask(Business business, String job) {
 		return CompletableFuture.runAsync(() -> {
 			try {

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

@@ -83,6 +83,25 @@ public class SnapAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 
+	@JaxrsMethodDescribe(value = "废弃已完成工作", action = ActionTypeAbandonedWorkCompleted.class)
+	@GET
+	@Path("workcompleted/{workCompletedId}/type/abandonedworkcompleted")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void typeAbandonedWorkCompleted(@Suspended final AsyncResponse asyncResponse,
+			@Context HttpServletRequest request,
+			@JaxrsParameterDescribe("已完成工作标识") @PathParam("workCompletedId") String workCompletedId) {
+		ActionResult<ActionTypeAbandonedWorkCompleted.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionTypeAbandonedWorkCompleted().execute(effectivePerson, workCompletedId);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
 	@JaxrsMethodDescribe(value = "删除快照", action = ActionDelete.class)
 	@DELETE
 	@Path("{id}")