Explorar o código

增加流程版本管理功能,新建流程工单的时候自动查找启用版本的流程

o2sword %!s(int64=5) %!d(string=hai) anos
pai
achega
90d39de2e4

+ 0 - 6
o2server/x_processplatform_assemble_designer/src/main/java/com/x/processplatform/assemble/designer/MessageFactory.java

@@ -42,10 +42,4 @@ public class MessageFactory {
 		title = StringTools.utf8SubString(title, JpaObject.length_255B);
 		MessageConnector.send(MessageConnector.TYPE_PROCESS_DELETE, title, "", process);
 	}
-
-	public static void process_upgrade(Process process) throws Exception {
-		String title = "升级流程平台流程:" + process.getName();
-		title = StringTools.utf8SubString(title, JpaObject.length_255B);
-		MessageConnector.send(MessageConnector.TYPE_PROCESS_UPDATE, title, "", process);
-	}
 }

+ 1 - 0
o2server/x_processplatform_assemble_designer/src/main/java/com/x/processplatform/assemble/designer/jaxrs/process/ActionEnable.java

@@ -55,6 +55,7 @@ class ActionEnable extends BaseAction {
 				}
 			}
 			emc.commit();
+			cacheNotify();
 			Wo wo = new Wo();
 			wo.setValue(true);
 			result.setData(wo);

+ 1 - 1
o2server/x_processplatform_assemble_designer/src/main/java/com/x/processplatform/assemble/designer/jaxrs/process/ActionUpgrade.java

@@ -101,7 +101,7 @@ class ActionUpgrade extends BaseAction {
 			Wo wo = new Wo();
 			wo.setId(newProcess.getId());
 			result.setData(wo);
-			MessageFactory.process_upgrade(newProcess);
+			MessageFactory.process_update(newProcess);
 			return result;
 		}
 	}

+ 1 - 0
o2server/x_processplatform_assemble_designer/src/main/java/com/x/processplatform/assemble/designer/jaxrs/process/ActionUpgradeAll.java

@@ -29,6 +29,7 @@ class ActionUpgradeAll extends BaseAction {
 					}
 				}
 				emc.commit();
+				cacheNotify();
 			}
 			wo.setValue(true);
 		}else{

+ 3 - 5
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/factory/element/ProcessFactory.java

@@ -79,7 +79,7 @@ public class ProcessFactory extends ElementFactory {
 				o = (Process) element.getObjectValue();
 			}
 		} else {
-			o = this.restrictEnabledProcess(application.getId(), flag);
+			o = this.restrictProcess(application.getId(), flag);
 			if (null != o) {
 				this.entityManagerContainer().get(Process.class).detach(o);
 				cache.put(new Element(cacheKey, o));
@@ -141,7 +141,7 @@ public class ProcessFactory extends ElementFactory {
 				o = (Process) element.getObjectValue();
 			}
 		} else {
-			o = this.restrictEnabledProcess(application.getId(), flag);
+			o = this.restrictProcess(application.getId(), flag);
 			if (null != o) {
 				cache.put(new Element(cacheKey, o));
 			}
@@ -226,7 +226,7 @@ public class ProcessFactory extends ElementFactory {
 		return null;
 	}
 
-	public Process restrictEnabledProcess(String application, String flag) throws Exception {
+	public Process restrictProcess(String application, String flag) throws Exception {
 		EntityManager em = this.entityManagerContainer().get(Process.class);
 		CriteriaBuilder cb = em.getCriteriaBuilder();
 		CriteriaQuery<Process> cq = cb.createQuery(Process.class);
@@ -235,8 +235,6 @@ public class ProcessFactory extends ElementFactory {
 		p = cb.and(p, cb.or(cb.equal(root.get(Process_.id), flag),
 				cb.equal(root.get(Process_.name), flag),
 				cb.equal(root.get(Process_.alias), flag)));
-		p = cb.and(p, cb.or(cb.isTrue(root.get(Process_.editionEnable)),
-				cb.isNull(root.get(Process_.editionEnable))));
 		cq.select(root).where(p).orderBy(cb.desc(root.get(Process_.editionNumber)));
 		List<Process> list = em.createQuery(cq).getResultList();
 		if(list!=null && !list.isEmpty()){

+ 5 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/process/ActionGetWithProcessWithApplication.java

@@ -11,6 +11,8 @@ import com.x.base.core.project.http.EffectivePerson;
 import com.x.processplatform.assemble.surface.Business;
 import com.x.processplatform.core.entity.element.Application;
 import com.x.processplatform.core.entity.element.Process;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
 
 public class ActionGetWithProcessWithApplication extends BaseAction {
 
@@ -26,6 +28,9 @@ public class ActionGetWithProcessWithApplication extends BaseAction {
 			if (null == process) {
 				throw new ExceptionEntityNotExist(flag, Process.class);
 			}
+			if(StringUtils.isNotEmpty(process.getEdition()) && BooleanUtils.isFalse(process.getEditionEnable())){
+				process = business.process().pickEnabled(process.getApplication(), process.getEdition());
+			}
 			Wo wo = Wo.copier.copy(process);
 			result.setData(wo);
 			return result;

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

@@ -72,6 +72,9 @@ class ActionCreateWithApplicationProcess extends BaseAction {
 			if (null == process) {
 				throw new ExceptionProcessNotExist(processFlag);
 			}
+			if(StringUtils.isNotEmpty(process.getEdition()) && BooleanUtils.isFalse(process.getEditionEnable())){
+				process = business.process().pickEnabled(process.getApplication(), process.getEdition());
+			}
 			List<String> roles = business.organization().role().listWithPerson(effectivePerson);
 			List<String> identities = business.organization().identity().listWithPerson(effectivePerson);
 			List<String> units = business.organization().unit().listWithPersonSupNested(effectivePerson);

+ 380 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionCreateWithApplicationProcessForce.java

@@ -0,0 +1,380 @@
+package com.x.processplatform.assemble.surface.jaxrs.work;
+
+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.JpaObject;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+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.http.TokenType;
+import com.x.base.core.project.jaxrs.WoId;
+import com.x.base.core.project.logger.Audit;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.organization.Unit;
+import com.x.base.core.project.tools.DefaultCharset;
+import com.x.base.core.project.tools.ListTools;
+import com.x.base.core.project.tools.SortTools;
+import com.x.base.core.project.x_processplatform_service_processing;
+import com.x.organization.core.express.Organization;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.assemble.surface.ThisApplication;
+import com.x.processplatform.assemble.surface.WorkControl;
+import com.x.processplatform.core.entity.content.*;
+import com.x.processplatform.core.entity.element.Application;
+import com.x.processplatform.core.entity.element.Process;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/*
+ * 根据应用名称和流程名称进行创建,和直接用process创建基本相同
+ * */
+class ActionCreateWithApplicationProcessForce extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionCreateWithApplicationProcessForce.class);
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String applicationFlag, String processFlag,
+			JsonElement jsonElement) throws Exception {
+		Audit audit = logger.audit(effectivePerson);
+		/* 新建工作id */
+		String workId = "";
+		/* 已存在草稿id */
+		String lastestWorkId = "";
+		String identity = null;
+		List<Wo> wos = new ArrayList<>();
+		ActionResult<List<Wo>> result = new ActionResult<>();
+		Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			Business business = new Business(emc);
+			identity = this.decideCreatorIdentity(business, effectivePerson, wi);
+			Application application = business.application().pick(applicationFlag);
+			if (null == application) {
+				throw new ExceptionApplicationNotExist(applicationFlag);
+			}
+			Process process = business.process().pick(application, processFlag);
+			if (null == process) {
+				throw new ExceptionProcessNotExist(processFlag);
+			}
+			List<String> roles = business.organization().role().listWithPerson(effectivePerson);
+			List<String> identities = business.organization().identity().listWithPerson(effectivePerson);
+			List<String> units = business.organization().unit().listWithPersonSupNested(effectivePerson);
+			if (!business.application().allowRead(effectivePerson, roles, identities, units, application)) {
+				throw new ExceptionApplicationAccessDenied(effectivePerson.getDistinguishedName(), application.getId());
+			}
+			if (BooleanUtils.isTrue(wi.getLatest())) {
+				/* 判断是否是要直接打开之前创建的草稿,草稿的判断标准:有待办无任何已办 */
+				lastestWorkId = this.latest(business, process, identity);
+				workId = lastestWorkId;
+			}
+			if (StringUtils.isEmpty(workId)) {
+				WoId woId = ThisApplication.context().applications()
+						.postQuery(x_processplatform_service_processing.class,
+								"work/process/" + URLEncoder.encode(process.getId(), DefaultCharset.name), wi.getData())
+						.getData(WoId.class);
+				workId = woId.getId();
+			}
+		}
+		/* 设置Work信息 */
+		if (BooleanUtils.isFalse(wi.getLatest()) || (StringUtils.isEmpty(lastestWorkId))) {
+			/* 如果不是草稿那么需要进行设置 */
+			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+				Business business = new Business(emc);
+				Organization organization = business.organization();
+				emc.beginTransaction(Work.class);
+				Work work = emc.find(workId, Work.class);
+				if (null == work) {
+					throw new ExceptionWorkNotExist(workId);
+				}
+				work.setTitle(wi.getTitle());
+				work.setCreatorIdentity(identity);
+				work.setCreatorPerson(organization.person().getWithIdentity(identity));
+				work.setCreatorUnit(organization.unit().getWithIdentity(identity));
+				if (StringUtils.isNotEmpty(work.getCreatorUnit())) {
+					Unit unit = organization.unit().getObject(work.getCreatorUnit());
+					work.setCreatorUnitLevelName(unit.getLevelName());
+				}
+				emc.commit();
+			}
+			/* 驱动工作 */
+			ThisApplication.context().applications().putQuery(x_processplatform_service_processing.class,
+					"work/" + URLEncoder.encode(workId, DefaultCharset.name) + "/processing", null);
+		} else {
+			/* 如果是草稿,准备后面的直接打开 */
+			workId = lastestWorkId;
+		}
+		/* 拼装返回结果 */
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			Business business = new Business(emc);
+			Work work = emc.find(workId, Work.class);
+			if (null == work) {
+				throw new ExceptionWorkNotExist(workId);
+			}
+			List<String> ids = business.workLog().listWithFromActivityTokenForwardNotConnected(work.getActivityToken());
+			/* 先取得没有结束的WorkLog */
+			List<WorkLog> list = emc.list(WorkLog.class, ids);
+			wos = this.refercenceWorkLog(business, list);
+			/* 标识当前用户的待办 */
+			for (Wo o : wos) {
+				o.setCurrentTaskIndex(-1);
+				for (int i = 0; i < o.getTaskList().size(); i++) {
+					WoTask t = o.getTaskList().get(i);
+					if (StringUtils.equals(effectivePerson.getDistinguishedName(), t.getPerson())) {
+						o.setCurrentTaskIndex(i);
+					}
+				}
+			}
+			audit.log(null, "填单");
+		}
+		result.setData(wos);
+		return result;
+	}
+
+	public static class Wi extends GsonPropertyObject {
+
+		@FieldDescribe("直接打开指定人员已经有的草稿,草稿判断:工作没有已办,只有一条此人的待办.")
+		private Boolean latest;
+
+		@FieldDescribe("标题.")
+		private String title;
+
+		@FieldDescribe("启动人员身份.")
+		private String identity;
+
+		@FieldDescribe("工作数据.")
+		private JsonElement data;
+
+		public String getTitle() {
+			return title;
+		}
+
+		public void setTitle(String title) {
+			this.title = title;
+		}
+
+		public String getIdentity() {
+			return identity;
+		}
+
+		public void setIdentity(String identity) {
+			this.identity = identity;
+		}
+
+		public JsonElement getData() {
+			return data;
+		}
+
+		public void setData(JsonElement data) {
+			this.data = data;
+		}
+
+		public Boolean getLatest() {
+			return latest;
+		}
+
+		public void setLatest(Boolean latest) {
+			this.latest = latest;
+		}
+
+	}
+
+	public static class Wo extends WorkLog {
+
+		private static final long serialVersionUID = 1307569946729101786L;
+
+		static WrapCopier<WorkLog, Wo> copier = WrapCopierFactory.wo(WorkLog.class, Wo.class, null,
+				JpaObject.FieldsInvisible);
+
+		@FieldDescribe("排序号")
+		private Long rank;
+
+		@FieldDescribe("已办对象")
+		private List<WoTaskCompleted> taskCompletedList;
+
+		@FieldDescribe("待办对象")
+		private List<WoTask> taskList;
+
+		@FieldDescribe("当前待办序号")
+		private Integer currentTaskIndex;
+
+		public Long getRank() {
+			return rank;
+		}
+
+		public void setRank(Long rank) {
+			this.rank = rank;
+		}
+
+		public Integer getCurrentTaskIndex() {
+			return currentTaskIndex;
+		}
+
+		public void setCurrentTaskIndex(Integer currentTaskIndex) {
+			this.currentTaskIndex = currentTaskIndex;
+		}
+
+		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 static class WoTask extends Task {
+
+		private static final long serialVersionUID = 2279846765261247910L;
+
+		static WrapCopier<Task, WoTask> copier = WrapCopierFactory.wo(Task.class, WoTask.class, null,
+				JpaObject.FieldsInvisible);
+
+		private Long rank;
+
+		private WorkControl control;
+
+		public Long getRank() {
+			return rank;
+		}
+
+		public void setRank(Long rank) {
+			this.rank = rank;
+		}
+
+		public WorkControl getControl() {
+			return control;
+		}
+
+		public void setControl(WorkControl control) {
+			this.control = control;
+		}
+
+	}
+
+	public static class WoTaskCompleted extends TaskCompleted {
+
+		private static final long serialVersionUID = -7253999118308715077L;
+
+		public static WrapCopier<TaskCompleted, WoTaskCompleted> copier = WrapCopierFactory.wo(TaskCompleted.class,
+				WoTaskCompleted.class, null, JpaObject.FieldsInvisible);
+
+		private Long rank;
+
+		private WorkControl control;
+
+		public Long getRank() {
+			return rank;
+		}
+
+		public void setRank(Long rank) {
+			this.rank = rank;
+		}
+
+		public WorkControl getControl() {
+			return control;
+		}
+
+		public void setControl(WorkControl control) {
+			this.control = control;
+		}
+
+	}
+
+	private List<Wo> refercenceWorkLog(Business business, List<WorkLog> list) throws Exception {
+		List<Wo> os = new ArrayList<>();
+		for (WorkLog o : list) {
+			Wo wo = Wo.copier.copy(o);
+			if (BooleanUtils.isNotTrue(o.getConnected())) {
+				this.referenceTask(business, wo);
+			} else {
+				/** 已经完成的不会有待办,返回一个空数组 */
+				wo.setTaskList(new ArrayList<WoTask>());
+			}
+			this.referenceTaskCompleted(business, wo);
+			os.add(wo);
+		}
+		SortTools.asc(os, false, "arrivedTime");
+		return os;
+	}
+
+	private String decideCreatorIdentity(Business business, EffectivePerson effectivePerson, Wi wi) throws Exception {
+		if (TokenType.cipher.equals(effectivePerson.getTokenType())) {
+			return business.organization().identity().get(wi.getIdentity());
+		} else if (StringUtils.isNotEmpty(wi.getIdentity())) {
+			List<String> identities = business.organization().identity()
+					.listWithPerson(effectivePerson.getDistinguishedName());
+			if (ListTools.isEmpty(identities)) {
+				throw new ExceptionNoneIdentity(effectivePerson.getDistinguishedName());
+			} else if (identities.size() == 1) {
+				return identities.get(0);
+			} else {
+				/* 有多个身份需要逐一判断是否包含. */
+				for (String o : identities) {
+					if (StringUtils.equals(o, wi.getIdentity())) {
+						return o;
+					}
+				}
+			}
+		} else {
+			List<String> list = business.organization().identity()
+					.listWithPerson(effectivePerson.getDistinguishedName());
+			if (!list.isEmpty()) {
+				return list.get(0);
+			}
+		}
+		throw new Exception("decideCreatorIdentity error:" + wi.toString());
+	}
+
+	private void referenceTask(Business business, Wo wo) throws Exception {
+		List<String> ids = business.task().listWithActivityToken(wo.getFromActivityToken());
+		List<WoTask> list = WoTask.copier.copy(business.entityManagerContainer().list(Task.class, ids));
+		SortTools.asc(list, false, "startTime");
+		wo.setTaskList(list);
+	}
+
+	private void referenceTaskCompleted(Business business, Wo wo) throws Exception {
+		List<String> ids = business.taskCompleted().listWithActivityToken(wo.getFromActivityToken());
+		List<WoTaskCompleted> list = WoTaskCompleted.copier
+				.copy(business.entityManagerContainer().list(TaskCompleted.class, ids));
+		Collections.sort(list, new Comparator<WoTaskCompleted>() {
+			public int compare(WoTaskCompleted o1, WoTaskCompleted o2) {
+				return ObjectUtils.compare(o1.getCompletedTime(), o2.getCompletedTime(), true);
+			}
+		});
+		/* 补充召回 */
+		List<WoTaskCompleted> results = new ArrayList<>();
+		for (WoTaskCompleted o : list) {
+			results.add(o);
+			if (o.getProcessingType().equals(ProcessingType.retract)) {
+				WoTaskCompleted retract = new WoTaskCompleted();
+				o.copyTo(retract);
+				retract.setRouteName("撤回");
+				retract.setOpinion("撤回");
+				retract.setStartTime(retract.getRetractTime());
+				retract.setCompletedTime(retract.getRetractTime());
+				results.add(retract);
+			}
+		}
+		wo.setTaskCompletedList(results);
+	}
+
+}

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

@@ -204,7 +204,7 @@ public class WorkAction extends StandardJaxrsAction {
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
 	@Path("process/{processFlag}")
-	@JaxrsMethodDescribe(value = "创建工作.", action = ActionCreate.class)
+	@JaxrsMethodDescribe(value = "创建工作(创建启动版本的流程).", action = ActionCreate.class)
 	public void create(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
 			@JaxrsParameterDescribe("流程标识") @PathParam("processFlag") String processFlag, JsonElement jsonElement) {
 		ActionResult<List<ActionCreate.Wo>> result = new ActionResult<>();
@@ -218,7 +218,25 @@ public class WorkAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 
-	@JaxrsMethodDescribe(value = "创建工作.", action = ActionCreateWithApplicationProcess.class)
+	@POST
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	@Path("process/{processFlag}/force")
+	@JaxrsMethodDescribe(value = "创建工作(强制创建存在的流程).", action = ActionCreateForce.class)
+	public void createForce(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+					   @JaxrsParameterDescribe("流程标识") @PathParam("processFlag") String processFlag, JsonElement jsonElement) {
+		ActionResult<List<ActionCreateForce.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionCreateForce().execute(effectivePerson, processFlag, jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, jsonElement);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
+	@JaxrsMethodDescribe(value = "创建工作(创建启动版本的流程).", action = ActionCreateWithApplicationProcess.class)
 	@POST
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
@@ -239,6 +257,27 @@ public class WorkAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 
+	@JaxrsMethodDescribe(value = "创建工作(强制创建存在的流程).", action = ActionCreateWithApplicationProcessForce.class)
+	@POST
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	@Path("application/{applicationFlag}/process/{processFlag}/force")
+	public void createWithApplicationProcessForce(@Suspended final AsyncResponse asyncResponse,
+											 @Context HttpServletRequest request,
+											 @JaxrsParameterDescribe("应用标识") @PathParam("applicationFlag") String applicationFlag,
+											 @JaxrsParameterDescribe("流程标识") @PathParam("processFlag") String processFlag, JsonElement jsonElement) {
+		ActionResult<List<ActionCreateWithApplicationProcessForce.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionCreateWithApplicationProcessForce().execute(effectivePerson, applicationFlag, processFlag,
+					jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, jsonElement);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
 	@JaxrsMethodDescribe(value = "删除工作,需要应用管理权限或者是工作的创建者。", action = ActionDelete.class)
 	@DELETE
 	@Path("{id}")