提交 b77fdb3f 编写于 作者: Z zhourui

增加extend.add 服务

上级 44c3c2df
package com.x.base.core.project.exception;
public class ExceptionDeprecatedAction extends LanguagePromptException {
private static final long serialVersionUID = 8181296584823275140L;
public static String defaultMessage = "action is deprecated, see {}.";
public ExceptionDeprecatedAction(String action) {
super(defaultMessage, action);
}
}
package com.x.base.core.project.processplatform;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.lang3.StringUtils;
import com.google.gson.Gson;
import com.x.base.core.project.gson.GsonPropertyObject;
import com.x.base.core.project.tools.ListTools;
public class ManualTaskIdentityMatrix extends GsonPropertyObject {
private static final long serialVersionUID = 5107066526414421883L;
private Matrix matrix = new Matrix();
public static ManualTaskIdentityMatrix concreteSingleRow(List<String> list) {
ManualTaskIdentityMatrix manualTaskIdentityMatrix = new ManualTaskIdentityMatrix();
Row row = new Row();
for (String str : list) {
if (StringUtils.isNotBlank(str)) {
row.add(str);
}
}
if (!row.isEmpty()) {
manualTaskIdentityMatrix.matrix.add(row);
}
return manualTaskIdentityMatrix;
}
public static ManualTaskIdentityMatrix concreteMultiRow(List<String> list) {
ManualTaskIdentityMatrix manualTaskIdentityMatrix = new ManualTaskIdentityMatrix();
for (String str : list) {
if (StringUtils.isNotBlank(str)) {
Row row = new Row();
row.add(str);
manualTaskIdentityMatrix.matrix.add(row);
}
}
return manualTaskIdentityMatrix;
}
public ManualTaskIdentityMatrix extend(String identity, boolean replace, List<String> list) {
for (Row row : matrix) {
int idx = row.indexOf(identity);
if (idx > 0) {
row.addAll(idx + 1, list);
if (replace) {
row.remove(idx);
}
break;
}
}
return this;
}
public ManualTaskIdentityMatrix extend(String identity, boolean replace, String... arr) {
return this.extend(identity, replace, Arrays.asList(arr));
}
public ManualTaskIdentityMatrix add(String identity, boolean after, boolean replace, List<String> list) {
int rowpos = 0;
int colpos = -1;
for (Row row : matrix) {
colpos = row.indexOf(identity);
if (colpos > -1) {
break;
} else {
rowpos++;
}
}
if (replace && (colpos > -1)) {
matrix.get(rowpos).remove(colpos);
}
if (after) {
rowpos++;
}
for (String str : list) {
Row row = new Row();
row.add(str);
matrix.add(rowpos++, row);
}
compact();
return this;
}
public ManualTaskIdentityMatrix add(String identity, boolean after, boolean replace, String... arr) {
return this.add(identity, after, replace, Arrays.asList(arr));
}
public void clear() {
this.matrix.clear();
}
public boolean isEmpty() {
compact();
return matrix.isEmpty();
}
public ManualTaskIdentityMatrix remove(String identity) {
matrix.stream().forEach(row -> row.remove(identity));
compact();
return this;
}
public ManualTaskIdentityMatrix remove(Collection<String> identities) {
matrix.stream().forEach(row -> row.removeAll(identities));
compact();
return this;
}
/**
* 工作处理完成,如果在行中有用户直接删除行
*
* @param identity
* @return
*/
public List<String> completed(String identity) {
List<String> list = new ArrayList<>();
matrix.stream().forEach(row -> {
if (row.contains(identity)) {
list.addAll(row);
row.clear();
}
});
compact();
return ListTools.trim(list, true, true);
}
/**
* 工作处理完成,如果在行中有用户直接删除行
*
* @param identities
* @return
*/
public List<String> completed(List<String> identities) {
List<String> list = new ArrayList<>();
matrix.stream().forEach(row -> {
if (!ListUtils.intersection(identities, row).isEmpty()) {
list.addAll(row);
row.clear();
}
});
compact();
return ListTools.trim(list, true, true);
}
public ManualTaskIdentityMatrix replace(String source, String target) {
matrix.stream().forEach(row -> row.replaceAll(s -> StringUtils.equalsIgnoreCase(s, source) ? target : s));
compact();
return this;
}
public List<String> read() {
return isEmpty() ? new ArrayList<>() : new ArrayList<>(matrix.get(0));
}
public List<String> flat() {
List<String> list = new ArrayList<>();
this.matrix.stream().forEach(row -> row.stream().forEach(list::add));
return list;
}
public ManualTaskIdentityMatrix reduce(String identity) {
matrix.stream().forEach(row -> {
if (row.contains(identity)) {
row.clear();
row.add(identity);
}
});
compact();
return this;
}
private void compact() {
Iterator<Row> rowIterator = matrix.iterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<String> cellIterator = row.iterator();
while (cellIterator.hasNext()) {
if (StringUtils.isEmpty(cellIterator.next())) {
cellIterator.remove();
}
}
List<String> trim = ListTools.trim(row, true, true);
row.clear();
row.addAll(trim);
if (row.isEmpty()) {
rowIterator.remove();
}
}
}
public static class Matrix extends LinkedList<Row> {
private static final long serialVersionUID = -53740621980996248L;
}
public static class Row extends LinkedList<String> {
private static final long serialVersionUID = 4774108881630629L;
}
public static ManualTaskIdentityMatrix fromJson(String json) {
ManualTaskIdentityMatrix o = new ManualTaskIdentityMatrix();
o.matrix = (new Gson()).fromJson(json, Matrix.class);
return o;
}
public String toJson() {
return (new Gson()).toJson(this.matrix);
}
public static void main(String[] args) {
String json = "[['A','B','C','D'],['E','F'],['G'],['H'],['I','J'],['K','L','M']]";
ManualTaskIdentityMatrix matrix = ManualTaskIdentityMatrix.fromJson(json);
matrix.reduce("C");
matrix.replace("C", "E");
System.out.println(matrix.toJson());
}
}
\ No newline at end of file
package com.x.processplatform.assemble.surface.jaxrs.task;
import com.x.base.core.project.exception.LanguagePromptException;
class ExceptionExtend extends LanguagePromptException {
private static final long serialVersionUID = -5515077418025884395L;
ExceptionExtend(String id) {
super("扩充待办人失败, task:{}.", id);
}
}
package com.x.processplatform.assemble.surface.jaxrs.task;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.collections4.ListUtils;
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.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.jaxrs.WrapBoolean;
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.base.core.project.tools.StringTools;
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.Record;
import com.x.processplatform.core.entity.content.RecordProperties.NextManual;
import com.x.processplatform.core.entity.content.Task;
import com.x.processplatform.core.entity.content.TaskCompleted;
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.content.WorkLog;
import com.x.processplatform.core.express.ProcessingAttributes;
import com.x.processplatform.core.express.service.processing.jaxrs.task.V2ExtendWi;
import com.x.processplatform.core.express.service.processing.jaxrs.task.WrapProcessing;
import com.x.processplatform.core.express.service.processing.jaxrs.task.WrapUpdatePrevTaskIdentity;
import com.x.processplatform.core.express.service.processing.jaxrs.taskcompleted.WrapUpdateNextTaskIdentity;
public class V2Extend extends BaseAction {
private static final Logger LOGGER = LoggerFactory.getLogger(V2Extend.class);
// 当前提交的串号
private final String series = StringTools.uniqueToken();
// 新加入的身份列表
private List<String> identites = new ArrayList<>();
// 新创建的待办标识列表
private List<String> newTasks = new ArrayList<>();
// 当前待办转成已办得到的已办id
private String taskCompletedId;
// 已经存在的待办标识列表
private List<String> existTaskIds = new ArrayList<>();
// 输入
private Wi wi;
// 本操作创建的记录
private Record record;
// 当前执行用户
private EffectivePerson effectivePerson;
// 根据输入得到的待办
private Task task = null;
// 根据待办获取的工作
private Work work = null;
// 当前待办的workLog
private WorkLog workLog = null;
ActionResult<Wo> execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("execute:{}.", effectivePerson::getDistinguishedName);
}
this.init(effectivePerson, jsonElement);
this.extend(this.task, wi.getReplace(), identites);
if (BooleanUtils.isTrue(wi.getReplace())) {
taskCompletedId = this.processingTask(this.task);
}
this.processingWork(this.task);
this.record(task, workLog);
if (StringUtils.isNotEmpty(taskCompletedId)) {
this.updateTaskCompleted();
}
this.updateTask();
return result();
}
private void init(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
Business business = new Business(emc);
this.effectivePerson = effectivePerson;
this.wi = this.convertToWrapIn(jsonElement, Wi.class);
this.task = emc.find(wi.getTask(), Task.class);
if (null == task) {
throw new ExceptionEntityNotExist(wi.getTask(), Task.class);
}
this.work = emc.find(task.getWork(), Work.class);
if (null == work) {
throw new ExceptionEntityNotExist(task.getWork(), Work.class);
}
this.workLog = emc.firstEqualAndEqual(WorkLog.class, WorkLog.job_FIELDNAME, task.getJob(),
WorkLog.fromActivityToken_FIELDNAME, task.getActivityToken());
if (null == workLog) {
throw new ExceptionEntityNotExist(WorkLog.class);
}
WoControl control = business.getControl(effectivePerson, task, WoControl.class);
if (BooleanUtils.isNotTrue(control.getAllowReset())) {
throw new ExceptionAccessDenied(effectivePerson, task);
}
this.existTaskIds = emc.idsEqualAndEqual(Task.class, Task.job_FIELDNAME, task.getJob(),
Task.activity_FIELDNAME, task.getActivity());
this.identites = business.organization().identity().list(wi.getIdentityList());
// 在新扩充待办人员中去除已经有待办人员
this.identites = ListUtils.subtract(this.identites, ListTools.toList(task.getIdentity()));
if (ListTools.isEmpty(identites)) {
throw new ExceptionIdentityEmpty();
}
}
}
private void extend(Task task, Boolean replace, List<String> identites) throws Exception {
V2ExtendWi req = new V2ExtendWi();
req.setTask(task.getId());
req.setReplace(replace);
req.setIdentityList(identites);
WrapBoolean resp = ThisApplication.context().applications()
.postQuery(x_processplatform_service_processing.class, Applications.joinQueryUri("task", "extend"), req,
task.getJob())
.getData(WrapBoolean.class);
if (BooleanUtils.isNotTrue(resp.getValue())) {
throw new ExceptionExtend(task.getId());
}
}
private String processingTask(Task task) throws Exception {
WrapProcessing req = new WrapProcessing();
req.setProcessingType(TaskCompleted.PROCESSINGTYPE_EXTEND);
WoId resp = ThisApplication.context().applications()
.putQuery(x_processplatform_service_processing.class,
Applications.joinQueryUri("task", task.getId(), "processing"), req, task.getJob())
.getData(WoId.class);
if (StringUtils.isEmpty(resp.getId())) {
throw new ExceptionTaskProcessing(task.getId());
} else {
return resp.getId();
}
}
private void processingWork(Task task) throws Exception {
ProcessingAttributes req = new ProcessingAttributes();
req.setType(ProcessingAttributes.TYPE_TASKEXTEND);
req.setSeries(this.series);
WoId resp = ThisApplication.context().applications()
.putQuery(effectivePerson.getDebugger(), x_processplatform_service_processing.class,
Applications.joinQueryUri("work", task.getWork(), "processing"), req, task.getJob())
.getData(WoId.class);
if (StringUtils.isEmpty(resp.getId())) {
throw new ExceptionWorkProcessing(task.getWork());
}
}
private void record(Task task, WorkLog workLog) throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
final List<String> nextTaskIdentities = new ArrayList<>();
this.record = new Record(workLog, task);
// 校验workCompleted,如果存在,那么说明工作已经完成,标识状态为已经完成.
WorkCompleted workCompleted = emc.firstEqual(WorkCompleted.class, WorkCompleted.job_FIELDNAME,
task.getJob());
if (null != workCompleted) {
record.setCompleted(true);
record.setWorkCompleted(workCompleted.getId());
}
record.setPerson(effectivePerson.getDistinguishedName());
record.setType(Record.TYPE_RESET);
List<String> ids = emc.idsEqualAndEqual(Task.class, Task.job_FIELDNAME, task.getJob(),
Task.activity_FIELDNAME, task.getActivity());
ids = ListUtils.subtract(ids, existTaskIds);
List<Task> list = emc.fetch(ids, Task.class,
ListTools.toList(Task.identity_FIELDNAME, Task.job_FIELDNAME, Task.work_FIELDNAME,
Task.activity_FIELDNAME, Task.activityAlias_FIELDNAME, Task.activityName_FIELDNAME,
Task.activityToken_FIELDNAME, Task.activityType_FIELDNAME, Task.identity_FIELDNAME));
list.stream().collect(Collectors.groupingBy(Task::getActivity, Collectors.toList())).entrySet().stream()
.forEach(o -> {
Task next = o.getValue().get(0);
NextManual nextManual = new NextManual();
nextManual.setActivity(next.getActivity());
nextManual.setActivityAlias(next.getActivityAlias());
nextManual.setActivityName(next.getActivityName());
nextManual.setActivityToken(next.getActivityToken());
nextManual.setActivityType(next.getActivityType());
for (Task t : o.getValue()) {
nextManual.getTaskIdentityList().add(t.getIdentity());
nextTaskIdentities.add(t.getIdentity());
}
record.getProperties().getNextManualList().add(nextManual);
});
// 去重
record.getProperties().setNextManualTaskIdentityList(ListTools.trim(nextTaskIdentities, true, true));
}
WoId resp = ThisApplication.context().applications()
.postQuery(effectivePerson.getDebugger(), x_processplatform_service_processing.class,
Applications.joinQueryUri("record", "job", task.getJob()), record, task.getJob())
.getData(WoId.class);
if (StringUtils.isBlank(resp.getId())) {
throw new ExceptionExtend(task.getId());
}
}
private void updateTaskCompleted() throws Exception {
/* 记录下一处理人信息 */
WrapUpdateNextTaskIdentity req = new WrapUpdateNextTaskIdentity();
req.getTaskCompletedList().add(this.taskCompletedId);
req.setNextTaskIdentityList(record.getProperties().getNextManualTaskIdentityList());
ThisApplication.context().applications()
.putQuery(effectivePerson.getDebugger(), x_processplatform_service_processing.class,
Applications.joinQueryUri("taskcompleted", "next", "task", "identity"), req, task.getJob())
.getData(WrapBoolean.class);
}
private void updateTask() throws Exception {
/* 记录上一处理人信息 */
if (ListTools.isNotEmpty(newTasks)) {
WrapUpdatePrevTaskIdentity req = new WrapUpdatePrevTaskIdentity();
req.setTaskList(newTasks);
req.setPrevTaskIdentity(task.getIdentity());
req.getPrevTaskIdentityList().add(task.getIdentity());
ThisApplication.context().applications()
.putQuery(effectivePerson.getDebugger(), x_processplatform_service_processing.class,
Applications.joinQueryUri("task", "prev", "task", "identity"), req, task.getJob())
.getData(WrapBoolean.class);
}
}
private ActionResult<Wo> result() {
ActionResult<Wo> result = new ActionResult<>();
Wo wo = new Wo();
wo.setValue(true);
result.setData(wo);
return result;
}
public static class Wi extends V2ExtendWi {
private static final long serialVersionUID = -3241215869441470402L;
}
public static class WoControl extends WorkControl {
private static final long serialVersionUID = -8781558581462660831L;
}
public static class Wo extends WrapBoolean {
private static final long serialVersionUID = 4883624438858385234L;
}
}
\ No newline at end of file
......@@ -38,55 +38,58 @@ import com.x.processplatform.core.entity.element.ActivityType;
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Record extends SliceJpaObject {
private static final long serialVersionUID = 8673378766635237050L;
/* 正常流转 */
public final static String TYPE_CURRENTTASK = "currentTask";
public static final String TYPE_CURRENTTASK = "currentTask";
/* 正常流转 */
public final static String TYPE_TASK = "task";
public static final String TYPE_TASK = "task";
/* 转交流转 */
public final static String TYPE_APPENDTASK = "appendTask";
public static final String TYPE_APPENDTASK = "appendTask";
/* 回退流转 */
public final static String TYPE_BACK = "back";
public static final String TYPE_BACK = "back";
/* 调度 */
public final static String TYPE_REROUTE = "reroute";
public static final String TYPE_REROUTE = "reroute";
/* 撤回 */
public final static String TYPE_RETRACT = "retract";
public static final String TYPE_RETRACT = "retract";
/* 回滚 */
public final static String TYPE_ROLLBACK = "rollback";
public static final String TYPE_ROLLBACK = "rollback";
/* 重置 */
public final static String TYPE_RESET = "reset";
public static final String TYPE_RESET = "reset";
/* 增加分支 */
public final static String TYPE_ADDSPLIT = "addSplit";
public static final String TYPE_ADDSPLIT = "addSplit";
/* 催办 */
public final static String TYPE_URGE = "urge";
public static final String TYPE_URGE = "urge";
/* 超时 */
public final static String TYPE_EXPIRE = "expire";
public static final String TYPE_EXPIRE = "expire";
/* 待阅 */
public final static String TYPE_READ = "read";
public static final String TYPE_READ = "read";
/* 授权 */
public final static String TYPE_EMPOWER = "empower";
public static final String TYPE_EMPOWER = "empower";
/* 超时自动流转 */
public final static String TYPE_PASSEXPIRED = "passExpired";
public static final String TYPE_PASSEXPIRED = "passExpired";
/* 外部调用流转 */
public final static String TYPE_SERVICE = "service";
public static final String TYPE_SERVICE = "service";
/* 定制意见 */
public final static String TYPE_CUSTOM = "custom";
/* 待办扩充 */
public static final String TYPE_TASKEXTEND = "taskExtend";
private static final long serialVersionUID = 8673378766635237050L;
/* 定制意见 */
public static final String TYPE_CUSTOM = "custom";
private static final String TABLE = PersistenceProperties.Content.Record.table;
......
......@@ -80,6 +80,12 @@ public class TaskCompleted extends SliceJpaObject implements ProjectionInterface
public static final String PROCESSINGTYPE_BEAPPENDEDTASK = "beAppendedTask";
/* 授权,授权给他人处理 */
public static final String PROCESSINGTYPE_EMPOWER = "empower";
/* 扩充办理人 */
public static final String PROCESSINGTYPE_EXTEND = "extend";
/* 前添加处理人 */
public static final String PROCESSINGTYPE_ADDBEFORE = "addBefore";
/* 后添加处理人 */
public static final String PROCESSINGTYPE_ADDAFTER = "addAfter";
public String getId() {
return id;
......
......@@ -38,6 +38,7 @@ import com.x.base.core.entity.annotation.ContainerEntity;
import com.x.base.core.project.annotation.FieldDescribe;
import com.x.base.core.project.gson.XGsonBuilder;
import com.x.base.core.project.organization.OrganizationDefinition;
import com.x.base.core.project.processplatform.ManualTaskIdentityMatrix;
import com.x.base.core.project.tools.DateTools;
import com.x.base.core.project.tools.ListTools;
import com.x.base.core.project.tools.StringTools;
......@@ -51,6 +52,13 @@ import com.x.processplatform.core.entity.element.ActivityType;
+ JpaObject.DefaultUniqueConstraintSuffix, columnNames = { JpaObject.IDCOLUMN,
JpaObject.CREATETIMECOLUMN, JpaObject.UPDATETIMECOLUMN, JpaObject.SEQUENCECOLUMN }) })
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
/**
* 7.2.0版本 增加manualTaskIdentityMatrix
*
* @author ray
*
*/
public class Work extends SliceJpaObject implements ProjectionInterface {
private static final long serialVersionUID = 7668822947307502058L;
......@@ -84,10 +92,10 @@ public class Work extends SliceJpaObject implements ProjectionInterface {
this.title = StringTools.utf8SubString(this.getProperties().getTitle(), length_255B - 3) + "...";
}
// 填入处理人文本
if (ListTools.isEmpty(this.manualTaskIdentityList)) {
if (ListTools.isEmpty(this.getManualTaskIdentityMatrix().flat())) {
this.manualTaskIdentityText = "";
} else {
String text = StringUtils.join(OrganizationDefinition.name(manualTaskIdentityList), ",");
String text = StringUtils.join(OrganizationDefinition.name(this.getManualTaskIdentityMatrix().flat()), ",");
text = StringTools.utf8SubString(text, length_255B);
this.setManualTaskIdentityText(text);
}
......@@ -101,6 +109,7 @@ public class Work extends SliceJpaObject implements ProjectionInterface {
this.splitValueList = this.getProperties().getSplitValueList();
this.embedTargetJob = this.getProperties().getEmbedTargetJob();
this.embedCompleted = this.getProperties().getEmbedCompleted();
this.manualTaskIdentityMatrix = this.getProperties().getManualTaskIdentityMatrix();
}
/* 更新运行方法 */
......@@ -181,6 +190,18 @@ public class Work extends SliceJpaObject implements ProjectionInterface {
this.embedCompleted = embedCompleted;
}
public ManualTaskIdentityMatrix getManualTaskIdentityMatrix() {
if (null == this.manualTaskIdentityMatrix) {
this.setManualTaskIdentityMatrix(new ManualTaskIdentityMatrix());
}
return this.manualTaskIdentityMatrix;
}
public void setManualTaskIdentityMatrix(ManualTaskIdentityMatrix manualTaskIdentityMatrix) {
this.manualTaskIdentityMatrix = manualTaskIdentityMatrix;
this.getProperties().setManualTaskIdentityMatrix(manualTaskIdentityMatrix);
}
@Transient
@FieldDescribe("要拆分的值")
private List<String> splitValueList;
......@@ -193,6 +214,11 @@ public class Work extends SliceJpaObject implements ProjectionInterface {
@FieldDescribe("子流程返回标识.")
private String embedCompleted;
public static final String MANUALTASKIDENTITYMATRIX_FIELDNAME = "manualTaskIdentityMatrix";
@FieldDescribe("待办身份矩阵.")
@Transient
private ManualTaskIdentityMatrix manualTaskIdentityMatrix;
public static final String job_FIELDNAME = "job";
@FieldDescribe("工作")
@Column(length = JpaObject.length_id, name = ColumnNamePrefix + job_FIELDNAME)
......@@ -894,9 +920,7 @@ public class Work extends SliceJpaObject implements ProjectionInterface {
this.activityType = activityType;
}
public List<String> getManualTaskIdentityList() {
return manualTaskIdentityList;
}
public ActivityType getDestinationActivityType() {
return destinationActivityType;
......@@ -1006,14 +1030,6 @@ public class Work extends SliceJpaObject implements ProjectionInterface {
this.manualTaskIdentityText = manualTaskIdentityText;
}
// public String getTitleLob() {
// return titleLob;
// }
// public void setTitleLob(String titleLob) {
// this.titleLob = titleLob;
// }
public String getStringValue01() {
return stringValue01;
}
......@@ -1277,5 +1293,9 @@ public class Work extends SliceJpaObject implements ProjectionInterface {
public void setManualTaskIdentityList(List<String> manualTaskIdentityList) {
this.manualTaskIdentityList = manualTaskIdentityList;
}
public List<String> getManualTaskIdentityList() {
return manualTaskIdentityList;
}
}
\ No newline at end of file
......@@ -7,6 +7,7 @@ import java.util.Map;
import com.x.base.core.entity.JsonProperties;
import com.x.base.core.project.annotation.FieldDescribe;
import com.x.base.core.project.processplatform.ManualTaskIdentityMatrix;
public class WorkProperties extends JsonProperties {
......@@ -39,6 +40,17 @@ public class WorkProperties extends JsonProperties {
@FieldDescribe("拆分值列表")
private List<String> splitValueList = new ArrayList<>();
@FieldDescribe("待办身份矩阵")
private ManualTaskIdentityMatrix manualTaskIdentityMatrix = new ManualTaskIdentityMatrix();
public ManualTaskIdentityMatrix getManualTaskIdentityMatrix() {
return manualTaskIdentityMatrix;
}
public void setManualTaskIdentityMatrix(ManualTaskIdentityMatrix manualTaskIdentityMatrix) {
this.manualTaskIdentityMatrix = manualTaskIdentityMatrix;
}
public List<String> getManualForceTaskIdentityList() {
if (this.manualForceTaskIdentityList == null) {
this.manualForceTaskIdentityList = new ArrayList<>();
......
......@@ -79,6 +79,7 @@ public class Application extends SliceJpaObject {
public void postLoad() {
if (null != this.properties) {
this.defaultForm = this.getProperties().getDefaultForm();
this.maintenanceIdentity = this.getProperties().getMaintenanceIdentity();
}
}
......@@ -117,6 +118,20 @@ public class Application extends SliceJpaObject {
this.getProperties().setDefaultForm(defaultForm);
}
public static final String MAINTENANCEIDENTITY_FIELDNAME = "maintenanceIdentity";
@FieldDescribe("流程维护身份,如果无法找到处理身份默认的流程处理身份.")
@Transient
private String maintenanceIdentity;
public String getMaintenanceIdentity() {
return maintenanceIdentity;
}
public void setMaintenanceIdentity(String maintenanceIdentity) {
this.maintenanceIdentity = maintenanceIdentity;
this.getProperties().setMaintenanceIdentity(maintenanceIdentity);
}
public static final String name_FIELDNAME = "name";
@Flag
@FieldDescribe("名称.")
......@@ -169,7 +184,7 @@ public class Application extends SliceJpaObject {
@PersistentCollection(fetch = FetchType.EAGER)
@ContainerTable(name = TABLE + ContainerTableNameMiddle
+ availableGroupList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
+ availableGroupList_FIELDNAME + JoinIndexNameSuffix))
+ availableGroupList_FIELDNAME + JoinIndexNameSuffix))
@OrderColumn(name = ORDERCOLUMNCOLUMN)
@ElementColumn(length = length_255B, name = ColumnNamePrefix + availableGroupList_FIELDNAME)
@ElementIndex(name = TABLE + IndexNameMiddle + availableGroupList_FIELDNAME + ElementIndexNameSuffix)
......
......@@ -6,10 +6,21 @@ import com.x.base.core.project.annotation.FieldDescribe;
public class ApplicationProperties extends JsonProperties {
private static final long serialVersionUID = 8342746214747017734L;
@FieldDescribe("应用默认表单")
private String defaultForm;
@FieldDescribe("流程维护身份,如果无法找到处理身份默认的流程处理身份.")
private String maintenanceIdentity;
public String getMaintenanceIdentity() {
return maintenanceIdentity;
}
public void setMaintenanceIdentity(String maintenanceIdentity) {
this.maintenanceIdentity = maintenanceIdentity;
}
public String getDefaultForm() {
return defaultForm;
}
......
......@@ -34,6 +34,7 @@ import com.x.base.core.entity.annotation.ContainerEntity;
import com.x.base.core.entity.annotation.Flag;
import com.x.base.core.entity.annotation.IdReference;
import com.x.base.core.project.annotation.FieldDescribe;
import com.x.base.core.project.processplatform.ManualTaskIdentityMatrix;
import com.x.processplatform.core.entity.PersistenceProperties;
@Entity
......@@ -109,6 +110,18 @@ public class Manual extends Activity {
this.properties.setCustomData(customData);
}
public ManualTaskIdentityMatrix identitiesToManualTaskIdentityMatrix(List<String> identities) {
switch (this.getManualMode()) {
case parallel:
case queue:
return ManualTaskIdentityMatrix.concreteMultiRow(identities);
case single:
case grab:
default:
return ManualTaskIdentityMatrix.concreteSingleRow(identities);
}
}
@FieldDescribe("分组.")
@CheckPersist(allowEmpty = true)
@Column(length = JpaObject.length_255B, name = ColumnNamePrefix + group_FIELDNAME)
......
......@@ -3,7 +3,7 @@ package com.x.processplatform.core.entity.element;
import com.x.base.core.entity.JpaObject;
/**
* 节点方式,单人活动,并行, 顺序执行, 抢办
* 节点方式:单人活动,并行,顺序执行,抢办
*/
public enum ManualMode {
single, parallel, queue, grab;
......
package com.x.processplatform.core.entity.element;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.x.base.core.project.gson.GsonPropertyObject;
public class ManualTaskIdentityMatrix extends GsonPropertyObject {
private static final long serialVersionUID = 5107066526414421883L;
private List<List<String>> matrix = new ArrayList<>();
public static ManualTaskIdentityMatrix concteteAsColumn(List<String> list) {
ManualTaskIdentityMatrix manualTaskIdentityMatrix = new ManualTaskIdentityMatrix();
for (String str : list) {
if (StringUtils.isNotBlank(str)) {
List<String> row = new ArrayList<>();
row.add(str);
manualTaskIdentityMatrix.matrix.add(row);
}
}
return manualTaskIdentityMatrix;
}
public static ManualTaskIdentityMatrix concteteAsRow(List<String> list) {
ManualTaskIdentityMatrix manualTaskIdentityMatrix = new ManualTaskIdentityMatrix();
List<String> row = new ArrayList<>();
for (String str : list) {
if (StringUtils.isNotBlank(str)) {
row.add(str);
}
}
if (!row.isEmpty()) {
manualTaskIdentityMatrix.matrix.add(row);
}
return manualTaskIdentityMatrix;
}
public void clear() {
this.matrix.clear();
}
public boolean isEmpty() {
compact();
return matrix.isEmpty();
}
public boolean remove(String identity) {
boolean tag = false;
for (List<String> list : matrix) {
tag = list.remove(identity) || tag;
}
compact();
return tag;
}
public ManualTaskIdentityMatrix replace(String source, String target) {
for (List<String> list : this.matrix) {
list.replaceAll(s -> StringUtils.equalsIgnoreCase(s, source) ? target : s);
}
compact();
return this;
}
private void compact() {
for (List<String> row : matrix) {
Iterator<String> cell = row.iterator();
while (cell.hasNext()) {
String value = cell.next();
if (StringUtils.isEmpty(value)) {
cell.remove();
}
}
}
Iterator<List<String>> row = matrix.iterator();
while (row.hasNext()) {
List<String> value = row.next();
if (null == value || value.isEmpty()) {
row.remove();
}
}
}
}
\ No newline at end of file
......@@ -96,6 +96,20 @@ public class Process extends SliceJpaObject {
}
}
public static final String MAINTENANCEIDENTITY_FIELDNAME = "maintenanceIdentity";
@FieldDescribe("流程维护身份,如果无法找到处理身份默认的流程处理身份.")
@Transient
private String maintenanceIdentity;
public String getMaintenanceIdentity() {
return maintenanceIdentity;
}
public void setMaintenanceIdentity(String maintenanceIdentity) {
this.maintenanceIdentity = maintenanceIdentity;
this.getProperties().setMaintenanceIdentity(maintenanceIdentity);
}
public static final String UPDATETABLEENABLE_FIELDNAME = "updateTableEnable";
@FieldDescribe("启用同步到自建表.")
@Transient
......@@ -202,6 +216,7 @@ public class Process extends SliceJpaObject {
this.manualStayScriptText = this.getProperties().getManualStayScriptText();
this.updateTableEnable = this.getProperties().getUpdateTableEnable();
this.updateTableList = this.getProperties().getUpdateTableList();
this.maintenanceIdentity = this.getProperties().getMaintenanceIdentity();
}
}
......
......@@ -33,6 +33,17 @@ public class ProcessProperties extends JsonProperties {
@FieldDescribe("同步到自建表.")
private List<String> updateTableList;
@FieldDescribe("流程维护身份,如果无法找到处理身份默认的流程处理身份.")
private String maintenanceIdentity;
public String getMaintenanceIdentity() {
return maintenanceIdentity;
}
public void setMaintenanceIdentity(String maintenanceIdentity) {
this.maintenanceIdentity = maintenanceIdentity;
}
public Boolean getUpdateTableEnable() {
return updateTableEnable;
}
......
......@@ -23,6 +23,10 @@ public class ProcessingAttributes extends GsonPropertyObject {
public static final String TYPE_RETRACT = "retract";
public static final String TYPE_ROLLBACK = "rollback";
public static final String TYPE_SERVICE = "service";
public static final String TYPE_TASKEXTEND = "taskExtend";
public static final String TYPE_TASKADDBEFORE = "taskAddBefore";
public static final String TYPE_TASKADDAFTER = "taskAddAfter";
private Integer loop = 1;
@FieldDescribe("强制从arrive开始")
......
package com.x.processplatform.core.express.service.processing.jaxrs.task;
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 V2AddAfterWi extends GsonPropertyObject {
private static final long serialVersionUID = -3293122515327864483L;
@FieldDescribe("身份")
private List<String> identityList = new ArrayList<>();
@FieldDescribe("是否执行替换")
private Boolean replace;
@FieldDescribe("是否删除")
private String task;
public List<String> getIdentityList() {
return identityList;
}
public void setIdentityList(List<String> identityList) {
this.identityList = identityList;
}
public Boolean getReplace() {
return replace;
}
public void setReplace(Boolean replace) {
this.replace = replace;
}
public String getTask() {
return task;
}
public void setTask(String task) {
this.task = task;
}
}
\ No newline at end of file
package com.x.processplatform.core.express.service.processing.jaxrs.task;
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 V2AddBeforeWi extends GsonPropertyObject {
private static final long serialVersionUID = -3293122515327864483L;
@FieldDescribe("身份")
private List<String> identityList = new ArrayList<>();
@FieldDescribe("是否执行替换")
private Boolean replace;
@FieldDescribe("是否删除")
private String task;
public List<String> getIdentityList() {
return identityList;
}
public void setIdentityList(List<String> identityList) {
this.identityList = identityList;
}
public Boolean getReplace() {
return replace;
}
public void setReplace(Boolean replace) {
this.replace = replace;
}
public String getTask() {
return task;
}
public void setTask(String task) {
this.task = task;
}
}
\ No newline at end of file
package com.x.processplatform.core.express.service.processing.jaxrs.task;
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 V2ExtendWi extends GsonPropertyObject {
private static final long serialVersionUID = -3293122515327864483L;
@FieldDescribe("身份")
private List<String> identityList = new ArrayList<>();
@FieldDescribe("是否执行替换")
private Boolean replace;
@FieldDescribe("是否删除")
private String task;
public List<String> getIdentityList() {
return identityList;
}
public void setIdentityList(List<String> identityList) {
this.identityList = identityList;
}
public Boolean getReplace() {
return replace;
}
public void setReplace(Boolean replace) {
this.replace = replace;
}
public String getTask() {
return task;
}
public void setTask(String task) {
this.task = task;
}
}
\ No newline at end of file
......@@ -150,12 +150,20 @@ class ActionAppend extends BaseAction {
o.setProcessingType(TaskCompleted.PROCESSINGTYPE_BEAPPENDEDTASK);
}
}
Manual manual = (Manual) business.element().get(work.getActivity(), ActivityType.manual);
if (null == manual) {
throw new ExceptionEntityNotExist(work.getActivity(), Manual.class);
}
wo.getValueList().addAll(new ArrayList<>(identities));
identities = ListUtils.sum(
ListUtils.subtract(work.getManualTaskIdentityList(), ListTools.toList(task.getIdentity())), identities);
ListUtils.subtract(work.getManualTaskIdentityMatrix().flat(), ListTools.toList(task.getIdentity())),
identities);
identities = business.organization().identity().list(ListTools.trim(identities, true, true));
emc.beginTransaction(Work.class);
work.setManualTaskIdentityList(identities);
// work.setManualTaskIdentityList(identities);
work.setManualTaskIdentityMatrix(manual.identitiesToManualTaskIdentityMatrix(identities));
for (TaskIdentity taskIdentity : taskIdentities) {
if (BooleanUtils.isNotTrue(taskIdentity.getIgnoreEmpower())
&& StringUtils.isNotEmpty(taskIdentity.getFromIdentity())) {
......
......@@ -52,7 +52,8 @@ class ActionDelete extends BaseAction {
emc.beginTransaction(Task.class);
emc.beginTransaction(Work.class);
emc.remove(task, CheckRemoveType.all);
work.getManualTaskIdentityList().remove(task.getIdentity());
// work.getManualTaskIdentityList().remove(task.getIdentity());
work.getManualTaskIdentityMatrix().remove(task.getIdentity());
emc.commit();
MessageFactory.task_delete(task);
wo.setId(task.getId());
......
......@@ -71,7 +71,7 @@ class ActionGrab extends BaseAction {
MessageFactory.task_delete(o);
}
}
work.setManualTaskIdentityList(ListTools.toList(task.getIdentity()));
work.getManualTaskIdentityMatrix().reduce(task.getIdentity());
emc.commit();
wo.setId(task.getId());
result.setData(wo);
......
package com.x.processplatform.service.processing.jaxrs.task;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.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.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.executor.ProcessPlatformExecutorFactory;
import com.x.base.core.project.gson.GsonPropertyObject;
import com.x.base.core.project.exception.ExceptionDeprecatedAction;
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.base.core.project.tools.ListTools;
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.express.ProcessingAttributes;
import com.x.processplatform.service.processing.Business;
import com.x.processplatform.service.processing.MessageFactory;
import com.x.processplatform.service.processing.Processing;
@Deprecated
class ActionReset extends BaseAction {
private static final Logger LOGGER = LoggerFactory.getLogger(ActionReset.class);
......@@ -40,106 +17,108 @@ class ActionReset extends BaseAction {
LOGGER.debug("execute:{}, id:{}.", effectivePerson::getDistinguishedName, () -> id);
ActionResult<Wo> result = new ActionResult<>();
Wo wo = new Wo();
final Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
String executorSeed = null;
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
Task task = emc.fetch(id, Task.class, ListTools.toList(Task.job_FIELDNAME));
if (null == task) {
throw new ExceptionEntityNotExist(id, Task.class);
}
executorSeed = task.getJob();
}
Callable<String> callable = new Callable<String>() {
public String call() throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
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);
}
// 检查reset人员
List<String> identites = ListTools
.trim(business.organization().identity().list(wi.getIdentityList()), true, true);
// 在新增待办人员中删除当前的处理人
identites = ListUtils.subtract(identites, ListTools.toList(task.getIdentity()));
if (identites.isEmpty()) {
throw new ExceptionResetEmpty();
}
emc.beginTransaction(Work.class);
List<String> os = ListTools.trim(work.getManualTaskIdentityList(), true, true);
if (BooleanUtils.isNotTrue(wi.getKeep())) {
Date now = new Date();
Long duration = Config.workTime().betweenMinutes(task.getStartTime(), now);
TaskCompleted taskCompleted = new TaskCompleted(task, TaskCompleted.PROCESSINGTYPE_RESET, now,
duration);
emc.beginTransaction(TaskCompleted.class);
emc.beginTransaction(Task.class);
emc.persist(taskCompleted, CheckPersistType.all);
emc.remove(task, CheckRemoveType.all);
os.remove(task.getIdentity());
MessageFactory.taskCompleted_create(taskCompleted);
MessageFactory.task_delete(task);
}
os = ListUtils.union(os, identites);
work.setManualTaskIdentityList(ListTools.trim(os, true, true));
emc.check(work, CheckPersistType.all);
emc.commit();
ProcessingAttributes processingAttributes = new ProcessingAttributes();
processingAttributes.setDebugger(effectivePerson.getDebugger());
Processing processing = new Processing(processingAttributes);
processing.processing(work.getId());
wo.setId(task.getId());
result.setData(wo);
}
return "";
}
};
ProcessPlatformExecutorFactory.get(executorSeed).submit(callable).get(300, TimeUnit.SECONDS);
return result;
}
public static class CallWrap {
String job;
}
public static class Wi extends GsonPropertyObject {
private static final long serialVersionUID = -563586484778909479L;
@FieldDescribe("身份")
private List<String> identityList;
@FieldDescribe("保留自身待办.")
private Boolean keep;
public List<String> getIdentityList() {
return identityList;
}
public void setIdentityList(List<String> identityList) {
this.identityList = identityList;
}
public Boolean getKeep() {
return keep;
}
public void setKeep(Boolean keep) {
this.keep = keep;
}
throw new ExceptionDeprecatedAction(V2Reset.class.getName());
// ActionResult<Wo> result = new ActionResult<>();
// Wo wo = new Wo();
// final Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
// String executorSeed = null;
//
// try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
// Task task = emc.fetch(id, Task.class, ListTools.toList(Task.job_FIELDNAME));
// if (null == task) {
// throw new ExceptionEntityNotExist(id, Task.class);
// }
// executorSeed = task.getJob();
// }
//
// Callable<String> callable = new Callable<String>() {
// public String call() throws Exception {
// try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
// 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);
// }
//
// // 检查reset人员
// List<String> identites = ListTools
// .trim(business.organization().identity().list(wi.getIdentityList()), true, true);
//
// // 在新增待办人员中删除当前的处理人
// identites = ListUtils.subtract(identites, ListTools.toList(task.getIdentity()));
//
// if (identites.isEmpty()) {
// throw new ExceptionResetEmpty();
// }
// emc.beginTransaction(Work.class);
// List<String> os = ListTools.trim(work.getManualTaskIdentityList(), true, true);
// if (BooleanUtils.isNotTrue(wi.getKeep())) {
// Date now = new Date();
// Long duration = Config.workTime().betweenMinutes(task.getStartTime(), now);
// TaskCompleted taskCompleted = new TaskCompleted(task, TaskCompleted.PROCESSINGTYPE_RESET, now,
// duration);
// emc.beginTransaction(TaskCompleted.class);
// emc.beginTransaction(Task.class);
// emc.persist(taskCompleted, CheckPersistType.all);
// emc.remove(task, CheckRemoveType.all);
// os.remove(task.getIdentity());
// MessageFactory.taskCompleted_create(taskCompleted);
// MessageFactory.task_delete(task);
// }
// os = ListUtils.union(os, identites);
// work.setManualTaskIdentityList(ListTools.trim(os, true, true));
// emc.check(work, CheckPersistType.all);
// emc.commit();
// ProcessingAttributes processingAttributes = new ProcessingAttributes();
// processingAttributes.setDebugger(effectivePerson.getDebugger());
// Processing processing = new Processing(processingAttributes);
// processing.processing(work.getId());
// wo.setId(task.getId());
// result.setData(wo);
// }
// return "";
// }
// };
//
// ProcessPlatformExecutorFactory.get(executorSeed).submit(callable).get(300, TimeUnit.SECONDS);
//
// return result;
// }
//
// public static class CallWrap {
// String job;
// }
//
// public static class Wi extends GsonPropertyObject {
//
// private static final long serialVersionUID = -563586484778909479L;
//
// @FieldDescribe("身份")
// private List<String> identityList;
//
// @FieldDescribe("保留自身待办.")
// private Boolean keep;
//
// public List<String> getIdentityList() {
// return identityList;
// }
//
// public void setIdentityList(List<String> identityList) {
// this.identityList = identityList;
// }
//
// public Boolean getKeep() {
// return keep;
// }
//
// public void setKeep(Boolean keep) {
// this.keep = keep;
// }
}
public static class Wo extends WoId {
......
......@@ -4,6 +4,7 @@ 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;
import javax.ws.rs.PathParam;
......@@ -264,4 +265,76 @@ public class TaskAction extends StandardJaxrsAction {
}
asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
}
}
@JaxrsMethodDescribe(value = "V2_在指定待办位置扩充处理人.", action = V2Extend.class)
@POST
@Path("v2/extend")
@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
@Consumes(MediaType.APPLICATION_JSON)
public void v2Extend(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
JsonElement jsonElement) {
ActionResult<V2Extend.Wo> result = new ActionResult<>();
EffectivePerson effectivePerson = this.effectivePerson(request);
try {
result = new V2Extend().execute(effectivePerson, jsonElement);
} catch (Exception e) {
logger.error(e, effectivePerson, request, jsonElement);
result.error(e);
}
asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
}
@JaxrsMethodDescribe(value = "V2_在指定待办位置前新增处理人.", action = V2AddBefore.class)
@POST
@Path("v2/add/before")
@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
@Consumes(MediaType.APPLICATION_JSON)
public void v2AddBefore(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
JsonElement jsonElement) {
ActionResult<V2AddBefore.Wo> result = new ActionResult<>();
EffectivePerson effectivePerson = this.effectivePerson(request);
try {
result = new V2AddBefore().execute(effectivePerson, jsonElement);
} catch (Exception e) {
logger.error(e, effectivePerson, request, jsonElement);
result.error(e);
}
asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
}
@JaxrsMethodDescribe(value = "V2_在指定待办位置后新增处理人.", action = V2AddAfter.class)
@POST
@Path("v2/add/after")
@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
@Consumes(MediaType.APPLICATION_JSON)
public void v2AddAfter(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
JsonElement jsonElement) {
ActionResult<V2AddAfter.Wo> result = new ActionResult<>();
EffectivePerson effectivePerson = this.effectivePerson(request);
try {
result = new V2AddAfter().execute(effectivePerson, jsonElement);
} catch (Exception e) {
logger.error(e, effectivePerson, request, jsonElement);
result.error(e);
}
asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
}
@JaxrsMethodDescribe(value = "V2_删除指定待办处理人.", action = V2Remove.class)
@DELETE
@Path("v2/{id}/remove")
@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
@Consumes(MediaType.APPLICATION_JSON)
public void V2Remove(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
@JaxrsParameterDescribe("标识") @PathParam("id") String id) {
ActionResult<V2Remove.Wo> result = new ActionResult<>();
EffectivePerson effectivePerson = this.effectivePerson(request);
try {
result = new V2Remove().execute(effectivePerson, id);
} catch (Exception e) {
logger.error(e, effectivePerson, request, null);
result.error(e);
}
asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
}
}
\ No newline at end of file
package com.x.processplatform.service.processing.jaxrs.task;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
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.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.WrapBoolean;
import com.x.base.core.project.logger.Logger;
import com.x.base.core.project.logger.LoggerFactory;
import com.x.base.core.project.processplatform.ManualTaskIdentityMatrix;
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.express.service.processing.jaxrs.task.V2AddAfterWi;
class V2AddAfter extends BaseAction {
private static final Logger LOGGER = LoggerFactory.getLogger(V2AddAfter.class);
ActionResult<Wo> execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
final Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("execute:{}.", effectivePerson::getDistinguishedName);
}
Task task = getTask(wi.getTask());
if (null == task) {
throw new ExceptionEntityNotExist(wi.getTask(), Task.class);
}
if (null == this.getWork(task.getWork())) {
throw new ExceptionEntityNotExist(task.getWork(), Work.class);
}
return ProcessPlatformExecutorFactory.get(task.getJob())
.submit(new CallableImpl(task.getWork(), task.getIdentity(), wi.getReplace(), wi.getIdentityList()))
.get(300, TimeUnit.SECONDS);
}
private Task getTask(String id) throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
return emc.fetch(id, Task.class,
ListTools.toList(Task.job_FIELDNAME, Task.identity_FIELDNAME, Task.work_FIELDNAME));
}
}
private Work getWork(String id) throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
return emc.fetch(id, Work.class, ListTools.toList());
}
}
private class CallableImpl implements Callable<ActionResult<Wo>> {
private String id;
private String identity;
private Boolean replace;
private List<String> identities;
CallableImpl(String id, String identity, Boolean replace, List<String> identities) {
this.id = id;
this.identity = identity;
this.replace = replace;
this.identities = identities;
}
@Override
public ActionResult<Wo> call() throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
emc.beginTransaction(Work.class);
Work work = emc.find(this.id, Work.class);
ManualTaskIdentityMatrix matrix = work.getManualTaskIdentityMatrix();
matrix.addAfter(identity, replace, identities);
work.setManualTaskIdentityMatrix(matrix);
emc.check(work, CheckPersistType.all);
emc.commit();
} catch (Exception e) {
LOGGER.error(e);
}
ActionResult<Wo> result = new ActionResult<>();
Wo wo = new Wo();
wo.setValue(true);
result.setData(wo);
return result;
}
}
public static class Wi extends V2AddAfterWi {
private static final long serialVersionUID = -3542693358569393097L;
}
public static class Wo extends WrapBoolean {
private static final long serialVersionUID = 6457473592503074552L;
}
}
package com.x.processplatform.service.processing.jaxrs.task;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
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.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.WrapBoolean;
import com.x.base.core.project.logger.Logger;
import com.x.base.core.project.logger.LoggerFactory;
import com.x.base.core.project.processplatform.ManualTaskIdentityMatrix;
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.express.service.processing.jaxrs.task.V2AddBeforeWi;
class V2AddBefore extends BaseAction {
private static final Logger LOGGER = LoggerFactory.getLogger(V2AddBefore.class);
ActionResult<Wo> execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
final Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("execute:{}.", effectivePerson::getDistinguishedName);
}
Task task = getTask(wi.getTask());
if (null == task) {
throw new ExceptionEntityNotExist(wi.getTask(), Task.class);
}
if (null == this.getWork(task.getWork())) {
throw new ExceptionEntityNotExist(task.getWork(), Work.class);
}
return ProcessPlatformExecutorFactory.get(task.getJob())
.submit(new CallableImpl(task.getWork(), task.getIdentity(), wi.getReplace(), wi.getIdentityList()))
.get(300, TimeUnit.SECONDS);
}
private Task getTask(String id) throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
return emc.fetch(id, Task.class,
ListTools.toList(Task.job_FIELDNAME, Task.identity_FIELDNAME, Task.work_FIELDNAME));
}
}
private Work getWork(String id) throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
return emc.fetch(id, Work.class, ListTools.toList());
}
}
private class CallableImpl implements Callable<ActionResult<Wo>> {
private String id;
private String identity;
private Boolean replace;
private List<String> identities;
CallableImpl(String id, String identity, Boolean replace, List<String> identities) {
this.id = id;
this.identity = identity;
this.replace = replace;
this.identities = identities;
}
@Override
public ActionResult<Wo> call() throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
emc.beginTransaction(Work.class);
Work work = emc.find(this.id, Work.class);
ManualTaskIdentityMatrix matrix = work.getManualTaskIdentityMatrix();
matrix.addBefore(identity, replace, identities);
work.setManualTaskIdentityMatrix(matrix);
emc.check(work, CheckPersistType.all);
emc.commit();
} catch (Exception e) {
LOGGER.error(e);
}
ActionResult<Wo> result = new ActionResult<>();
Wo wo = new Wo();
wo.setValue(true);
result.setData(wo);
return result;
}
}
public static class Wi extends V2AddBeforeWi {
private static final long serialVersionUID = -3542693358569393097L;
}
public static class Wo extends WrapBoolean {
private static final long serialVersionUID = 6457473592503074552L;
}
}
package com.x.processplatform.service.processing.jaxrs.task;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
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.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.WrapBoolean;
import com.x.base.core.project.logger.Logger;
import com.x.base.core.project.logger.LoggerFactory;
import com.x.base.core.project.processplatform.ManualTaskIdentityMatrix;
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.express.service.processing.jaxrs.task.V2ExtendWi;
class V2Extend extends BaseAction {
private static final Logger LOGGER = LoggerFactory.getLogger(V2Extend.class);
ActionResult<Wo> execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
final Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("execute:{}.", effectivePerson::getDistinguishedName);
}
Task task = getTask(wi.getTask());
if (null == task) {
throw new ExceptionEntityNotExist(wi.getTask(), Task.class);
}
if (null == this.getWork(task.getWork())) {
throw new ExceptionEntityNotExist(task.getWork(), Work.class);
}
return ProcessPlatformExecutorFactory.get(task.getJob())
.submit(new CallableImpl(task.getWork(), task.getIdentity(), wi.getReplace(), wi.getIdentityList()))
.get(300, TimeUnit.SECONDS);
}
private Task getTask(String id) throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
return emc.fetch(id, Task.class,
ListTools.toList(Task.job_FIELDNAME, Task.identity_FIELDNAME, Task.work_FIELDNAME));
}
}
private Work getWork(String id) throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
return emc.fetch(id, Work.class, ListTools.toList());
}
}
private class CallableImpl implements Callable<ActionResult<Wo>> {
private String id;
private String identity;
private Boolean replace;
private List<String> identities;
CallableImpl(String id, String identity, Boolean replace, List<String> identities) {
this.id = id;
this.identity = identity;
this.replace = replace;
this.identities = identities;
}
@Override
public ActionResult<Wo> call() throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
emc.beginTransaction(Work.class);
Work work = emc.find(this.id, Work.class);
ManualTaskIdentityMatrix matrix = work.getManualTaskIdentityMatrix();
matrix.extend(identity, replace, identities);
// work.setManualTaskIdentityMatrix(matrix);
emc.check(work, CheckPersistType.all);
emc.commit();
} catch (Exception e) {
LOGGER.error(e);
}
ActionResult<Wo> result = new ActionResult<>();
Wo wo = new Wo();
wo.setValue(true);
result.setData(wo);
return result;
}
}
public static class Wi extends V2ExtendWi {
private static final long serialVersionUID = 8207729800479548859L;
}
public static class Wo extends WrapBoolean {
private static final long serialVersionUID = 6457473592503074552L;
}
}
package com.x.processplatform.service.processing.jaxrs.task;
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.WrapBoolean;
import com.x.base.core.project.logger.Logger;
import com.x.base.core.project.logger.LoggerFactory;
import com.x.base.core.project.processplatform.ManualTaskIdentityMatrix;
import com.x.base.core.project.tools.ListTools;
import com.x.processplatform.core.entity.content.Task;
import com.x.processplatform.core.entity.content.Work;
class V2Remove extends BaseAction {
private static final Logger LOGGER = LoggerFactory.getLogger(V2Remove.class);
ActionResult<Wo> execute(EffectivePerson effectivePerson, String id) throws Exception {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("execute:{}, id:{}.", effectivePerson::getDistinguishedName, () -> id);
}
Task task = getTask(id);
if (null == task) {
throw new ExceptionEntityNotExist(id, Task.class);
}
if (null == this.getWork(task.getWork())) {
throw new ExceptionEntityNotExist(task.getWork(), Work.class);
}
return ProcessPlatformExecutorFactory.get(task.getJob())
.submit(new CallableImpl(task.getWork(), task.getIdentity())).get(300, TimeUnit.SECONDS);
}
private Task getTask(String id) throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
return emc.fetch(id, Task.class,
ListTools.toList(Task.job_FIELDNAME, Task.identity_FIELDNAME, Task.work_FIELDNAME));
}
}
private Work getWork(String id) throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
return emc.fetch(id, Work.class, ListTools.toList());
}
}
private class CallableImpl implements Callable<ActionResult<Wo>> {
private String id;
private String identity;
CallableImpl(String id, String identity) {
this.id = id;
this.identity = identity;
}
@Override
public ActionResult<Wo> call() throws Exception {
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
emc.beginTransaction(Work.class);
Work work = emc.find(this.id, Work.class);
ManualTaskIdentityMatrix matrix = work.getManualTaskIdentityMatrix();
matrix.remove(identity);
work.setManualTaskIdentityMatrix(matrix);
emc.check(work, CheckPersistType.all);
emc.commit();
} catch (Exception e) {
LOGGER.error(e);
}
ActionResult<Wo> result = new ActionResult<>();
Wo wo = new Wo();
wo.setValue(true);
result.setData(wo);
return result;
}
}
public static class Wo extends WrapBoolean {
private static final long serialVersionUID = 6457473592503074552L;
}
}
......@@ -21,6 +21,8 @@ import com.x.base.core.project.logger.LoggerFactory;
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.express.service.processing.jaxrs.task.V2ResetWi;
import com.x.processplatform.service.processing.Business;
......@@ -55,6 +57,13 @@ class V2Reset extends BaseAction {
if (null == work) {
throw new ExceptionEntityNotExist(task.getWork(), Work.class);
}
Manual manual = (Manual) business.element().get(work.getActivity(), ActivityType.manual);
if (null == manual) {
throw new ExceptionEntityNotExist(work.getActivity(), Manual.class);
}
/* 检查reset人员 */
List<String> identites = ListTools.trim(business.organization().identity().list(wi.getIdentityList()),
true, true);
......@@ -64,7 +73,7 @@ class V2Reset extends BaseAction {
}
emc.beginTransaction(Work.class);
List<String> os = ListTools.trim(work.getManualTaskIdentityList(), true, true);
List<String> os = ListTools.trim(work.getManualTaskIdentityMatrix().flat(), true, true);
os = ListUtils.sum(os, identites);
/* 在新增待办人员中删除当前的处理人 */
......@@ -75,8 +84,9 @@ class V2Reset extends BaseAction {
if (ListTools.isEmpty(os)) {
throw new ExceptionResetEmpty();
}
work.setManualTaskIdentityList(ListTools.trim(os, true, true));
work.setManualTaskIdentityMatrix(
manual.identitiesToManualTaskIdentityMatrix(ListTools.trim(os, true, true)));
// work.setManualTaskIdentityList(ListTools.trim(os, true, true));
emc.check(work, CheckPersistType.all);
emc.commit();
......
......@@ -115,7 +115,8 @@ class ActionAddSplit extends BaseAction {
workCopy.setSplitToken(arrived.getSplitToken());
workCopy.setSplitting(from.getSplitting());
workCopy.setSplitValue(splitValue);
workCopy.getManualTaskIdentityList().clear();
// workCopy.getManualTaskIdentityList().clear();
workCopy.getManualTaskIdentityMatrix().clear();
workCopy.setBeforeExecuted(false);
workCopy.setDestinationActivity(null);
workCopy.setDestinationActivityType(null);
......
......@@ -26,6 +26,7 @@ import com.x.base.core.project.tools.ListTools;
import com.x.processplatform.core.entity.content.Review;
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.service.processing.Business;
class ActionManualAppendIdentity extends BaseAction {
......@@ -167,12 +168,20 @@ class ActionManualAppendIdentity extends BaseAction {
throw new ExceptionNotManual(work.getActivity());
}
Manual manual = (Manual) business.element().get(work.getActivity(), ActivityType.manual);
if (null == manual) {
throw new ExceptionEntityNotExist(work.getActivity(), Manual.class);
}
List<String> taskIdentities = business.organization().identity().list(wi.getTaskIdentityList());
taskIdentities = ListUtils.subtract(taskIdentities, work.getManualTaskIdentityList());
taskIdentities = ListUtils.subtract(taskIdentities, work.getManualTaskIdentityMatrix().flat());
work.setManualTaskIdentityMatrix(manual.identitiesToManualTaskIdentityMatrix(taskIdentities));
work.setManualTaskIdentityList(
ListUtils.sum(work.getManualTaskIdentityList(), wi.getTaskIdentityList()));
// work.setManualTaskIdentityList(
// ListUtils.sum(work.getManualTaskIdentityList(), wi.getTaskIdentityList()));
List<Review> addReviews = new ArrayList<>();
for (String identity : taskIdentities) {
......
......@@ -106,7 +106,8 @@ class V2AddSplit extends BaseAction {
workCopy.setSplitToken(arrived.getSplitToken());
workCopy.setSplitting(from.getSplitting());
workCopy.setSplitValue(splitValue);
workCopy.getManualTaskIdentityList().clear();
// workCopy.getManualTaskIdentityList().clear();
workCopy.getManualTaskIdentityMatrix().clear();
workCopy.setBeforeExecuted(false);
workCopy.setDestinationActivity(null);
workCopy.setDestinationActivityType(null);
......
......@@ -20,6 +20,7 @@ import com.x.base.core.project.http.EffectivePerson;
import com.x.base.core.project.jaxrs.WrapBoolean;
import com.x.base.core.project.logger.Logger;
import com.x.base.core.project.logger.LoggerFactory;
import com.x.base.core.project.processplatform.ManualTaskIdentityMatrix;
import com.x.base.core.project.tools.ListTools;
import com.x.processplatform.core.entity.content.Read;
import com.x.processplatform.core.entity.content.ReadCompleted;
......@@ -118,7 +119,8 @@ class V2Retract extends BaseAction {
taskCompleted.setProcessingType(TaskCompleted.PROCESSINGTYPE_RETRACT);
List<String> manualTaskIdentityList = new ArrayList<>();
manualTaskIdentityList.add(taskCompleted.getIdentity());
work.setManualTaskIdentityList(manualTaskIdentityList);
// work.setManualTaskIdentityList(manualTaskIdentityList);
work.setManualTaskIdentityMatrix(ManualTaskIdentityMatrix.concreteMultiRow(manualTaskIdentityList));
// 发送消息
sendRemoveMessages(removeTasks, removeTaskCompleteds, removeReads, removeReadCompleteds);
emc.commit();
......
......@@ -114,13 +114,13 @@ class V2Rollback extends BaseAction {
for (TaskCompleted o : taskCompleteds) {
if (BooleanUtils.isTrue(o.getJoinInquire())) {
// o.setProcessingType(TaskCompleted.PROCESSINGTYPE_ROLLBACK);
emc.remove(o, CheckRemoveType.all);
}
manualTaskIdentityList.add(o.getIdentity());
}
work.setManualTaskIdentityList(ListTools.trim(manualTaskIdentityList, true, true));
work.getProperties()
.setManualForceTaskIdentityList(ListTools.trim(manualTaskIdentityList, true, true));
// work.setManualTaskIdentityList(ListTools.trim(manualTaskIdentityList, true, true));
emc.commit();
}
......
......@@ -63,7 +63,7 @@ public abstract class AbstractProcessor extends AbstractBaseProcessor {
AeiObjects aeiObjects = new AeiObjects(this.business(), work, activity, processingConfigurator,
processingAttributes);
// 清空可能的Manual活动预期人员
this.arriveCleanManualTaskIdentityList(aeiObjects);
this.arriveCleanManualTaskIdentityMatrix(aeiObjects);
// 清空可能的Manual活动授权信息
this.arriveCleanManualEmpowerMap(aeiObjects);
// 计算是否经过人工节点
......@@ -108,8 +108,12 @@ public abstract class AbstractProcessor extends AbstractBaseProcessor {
}
}
private void arriveCleanManualTaskIdentityList(AeiObjects aeiObjects) {
aeiObjects.getWork().setManualTaskIdentityList(new ArrayList<>());
// private void arriveCleanManualTaskIdentityList(AeiObjects aeiObjects) {
// aeiObjects.getWork().setManualTaskIdentityList(new ArrayList<>());
// }
private void arriveCleanManualTaskIdentityMatrix(AeiObjects aeiObjects) {
aeiObjects.getWork().getManualTaskIdentityMatrix().clear();
}
private void arriveCleanManualEmpowerMap(AeiObjects aeiObjects) {
......
......@@ -320,6 +320,13 @@ public class AeiObjects extends GsonPropertyObject {
.collect(Collectors.toList());
}
public List<TaskCompleted> getJoinInquireTaskCompletedsWithActivityToken(String activityToken) throws Exception {
return this.getTaskCompleteds().stream()
.filter(o -> StringUtils.equalsIgnoreCase(activityToken, o.getActivityToken())
&& BooleanUtils.isNotFalse(o.getJoinInquire()))
.collect(Collectors.toList());
}
public List<Read> getReads() throws Exception {
if (null == this.reads) {
this.reads = this.business.entityManagerContainer().listEqual(Read.class, Read.job_FIELDNAME,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册