package foundation.state.approve;
|
|
import java.util.Date;
|
import java.util.List;
|
|
import foundation.action.ActionContext;
|
import foundation.dao.Filter;
|
import foundation.dao.OrderBy;
|
import foundation.data.entity.Entity;
|
import foundation.data.entity.EntitySet;
|
import foundation.data.object.DataObject;
|
import foundation.data.object.EntitySaver;
|
import foundation.json.IJSONProvider;
|
import foundation.json.IJSONWriter;
|
import foundation.persist.NamedSQL;
|
import foundation.state.DetailState;
|
import foundation.state.ReferObject;
|
import foundation.state.StateMachine;
|
import foundation.state.StatePoint;
|
import foundation.token.IOnlineUser;
|
import foundation.translator.ValueType;
|
import foundation.util.ContentBuilder;
|
import foundation.util.ID;
|
import foundation.util.Util;
|
|
public class WorkingInstance implements IJSONProvider {
|
|
private DataObject masterObject;
|
private StateMachine machine;
|
private String docId;
|
private Date now;
|
private String masterId;
|
private Entity master;
|
private WorkingStepList workingSteps;
|
private EntitySet histories;
|
private boolean builded;
|
private int pos;
|
|
|
public WorkingInstance(String docId) throws Exception {
|
this.docId = docId;
|
masterObject = DataObject.getInstance("sys_state_working_main");
|
builded = true;
|
}
|
|
public WorkingInstance(StateMachine machine, String docId) throws Exception {
|
this.machine = machine;
|
this.docId = docId;
|
|
masterObject = DataObject.getInstance("sys_state_working_main");
|
now = new Date();
|
builded = false;
|
}
|
|
|
public static DetailState start(String dataName, String docId, StatePoint statePoint, StatePoint hostPoint, StatePoint referPoint, ReferObject referObject, IOnlineUser user, ActionContext context) throws Exception {
|
StateMachine machine = statePoint.getMachine();
|
|
//1. 关闭指定单据先前流程的查询权限和审批权限(只能查询且审批新启动的审批流程)
|
closeTargetDocumentFlow(docId);
|
|
//2. 创建工作流实例
|
WorkingInstance flowInstance = new WorkingInstance(machine, docId);
|
|
//3. 插入审批流主记录
|
flowInstance.insertMaster(dataName, statePoint, hostPoint, referPoint, referObject);
|
|
//4. 插入审批流的执行步骤、执行人员
|
flowInstance.insertWorkingSteps(statePoint, user, context);
|
|
//5. 返回第一个步骤的明细状态
|
DetailState detailState = statePoint.getFirstDetailState();
|
return detailState;
|
}
|
|
public static WorkingInstance getInstance(StateMachine machine, String docId) throws Exception {
|
WorkingInstance result = new WorkingInstance(machine, docId);
|
result.loadWorkingMaster();
|
return result;
|
}
|
|
private void init() throws Exception {
|
if (builded) {
|
return;
|
}
|
|
//1. 为主记录加锁
|
lockMaster();
|
|
//2. 加载步骤
|
loadWorkingSteps();
|
|
//3.
|
builded = true;
|
}
|
|
public void close() throws Exception {
|
EntitySaver saver = masterObject.createEntitySaver(master);
|
saver.set("is_working", "F");
|
saver.update();
|
}
|
|
public void loadActive(boolean loadStep, boolean loadHistory) throws Exception {
|
//1. 加载审批主记录
|
loadActiveMaster();
|
|
//2. 加载审批步骤
|
if (loadStep) {
|
loadWorkingSteps();
|
}
|
|
//3. 加载审批历史
|
if (loadHistory) {
|
loadStepHistorys();
|
}
|
}
|
|
public void gotoActiveStep() throws Exception {
|
//1.
|
if (!builded) {
|
synchronized (this) {
|
if (!builded) {
|
init();
|
}
|
}
|
}
|
|
//2.
|
int max = workingSteps.size();
|
pos = -1;
|
|
for (int i = 0; i < max; i++) {
|
WorkingStep step = workingSteps.get(i);
|
|
if (step.isWorking()) {
|
pos = i;
|
}
|
}
|
}
|
|
public boolean validateCurrentUser(ApproveOperate operator, IOnlineUser onlineUser, String creatorId) throws Exception {
|
if (onlineUser == null) {
|
return false;
|
}
|
|
if ("admin".equalsIgnoreCase(onlineUser.getName())) {
|
return true;
|
}
|
|
WorkingStep step = getCurrentStep();
|
|
if (step == null) {
|
return false;
|
}
|
|
String userId = onlineUser.getId();
|
if (step.includeUser(userId)) {
|
return true;
|
}
|
return (ApproveOperate.PullBack == operator) && userId.equals(creatorId);
|
}
|
|
public ApprovalResult runStep(StatePoint statePoint, IOnlineUser onlineUser, ApproveOperate operator, String remark) throws Exception {
|
if (ApproveOperate.Approve == operator) {
|
return runApprove(statePoint, onlineUser, remark);
|
}
|
else if (ApproveOperate.GoEnd == operator) {
|
return runGoEnd(statePoint, onlineUser, remark);
|
}
|
else if (ApproveOperate.GoBack == operator) {
|
return runGoBack(statePoint, onlineUser, remark);
|
}
|
else if (ApproveOperate.GoHome == operator) {
|
return runGoHome(statePoint, onlineUser, remark);
|
}
|
else if (ApproveOperate.PullBack == operator) {
|
return runPullBack(statePoint, onlineUser, remark);
|
}
|
|
return null;
|
}
|
|
private ApprovalResult runApprove(StatePoint statePoint, IOnlineUser user, String remark) throws Exception {
|
ApprovalResult approvalResult = new ApprovalResult();
|
//1. 完成当前步骤
|
WorkingStep currentStep = getCurrentStep();
|
closeOneStep(currentStep, user, remark);
|
insertOneHistory(currentStep, user, ApproveOperate.Approve, remark);
|
|
//2. 开启下一个步骤(如果当前步骤是最后一个步骤,就不需要开启下一个步骤)
|
WorkingStep nextStep = goNextStep();
|
openOneStep(nextStep);
|
|
if (nextStep != null) {
|
approvalResult.setDetailState(nextStep.getId(), nextStep.getName());
|
}
|
|
//3. 返回运行后,最新的位置
|
if (isAtSuccess()) {
|
//3.1 审批流完成(成功)
|
approvalResult.setStepLoscation(StepLocation.AtSuccess);
|
}
|
else if (isAtLast()) {
|
//3.2 审批停留在最后一个步骤
|
approvalResult.setStepLoscation(StepLocation.AtLast);
|
}
|
else {
|
//3.3 审批停留在中间步骤
|
approvalResult.setStepLoscation(StepLocation.InMiddle);
|
}
|
|
return approvalResult;
|
}
|
|
private ApprovalResult runGoEnd(StatePoint statePoint, IOnlineUser user, String remark) throws Exception {
|
ApprovalResult approvalResult = new ApprovalResult();
|
//1. 完成当前步骤
|
WorkingStep currentStep = getCurrentStep();
|
closeOneStep(currentStep, user, remark);
|
insertOneHistory(currentStep, user, ApproveOperate.PullBack, remark);
|
|
//2. 跳出审批,进入提交完成状态(成功)
|
approvalResult.setStepLoscation(StepLocation.AtSuccess);
|
approvalResult.setDetailState("", "");
|
return approvalResult;
|
}
|
|
private ApprovalResult runGoBack(StatePoint statePoint, IOnlineUser user, String remark) throws Exception {
|
ApprovalResult approvalResult = new ApprovalResult();
|
//1. 完成当前步骤
|
WorkingStep currentStep = getCurrentStep();
|
closeOneStep(currentStep, user, remark);
|
insertOneHistory(currentStep, user, ApproveOperate.GoBack, remark);
|
|
//2. 开启下一个步骤(如果当前步骤是最后一个步骤,就不需要开启下一个步骤)
|
WorkingStep priorStep = goPriorStep();
|
openOneStep(priorStep);
|
|
if (priorStep != null) {
|
approvalResult.setDetailState(priorStep.getId(), priorStep.getName());
|
}
|
|
//3. 返回运行后,最新的位置
|
if (isAtHome()) {
|
//3.1 跳出审批,进入提交申请前的状态(Input)
|
approvalResult.setStepLoscation(StepLocation.AtHome);
|
}
|
else if (isAtFirst()) {
|
//3.2 审批停留在第一个步骤
|
approvalResult.setStepLoscation(StepLocation.AtFirst);
|
}
|
else {
|
//3.3 审批停留在中间步骤
|
approvalResult.setStepLoscation(StepLocation.InMiddle);
|
}
|
|
return approvalResult;
|
}
|
|
private ApprovalResult runGoHome(StatePoint statePoint, IOnlineUser user, String remark) throws Exception {
|
ApprovalResult approvalResult = new ApprovalResult();
|
//1. 完成当前步骤
|
WorkingStep currentStep = getCurrentStep();
|
closeOneStep(currentStep, user, remark);
|
insertOneHistory(currentStep, user, ApproveOperate.GoHome, remark);
|
|
//2. 跳出审批,进入提交申请前的状态(Input)
|
approvalResult.setStepLoscation(StepLocation.AtHome);
|
approvalResult.setDetailState("", "");
|
return approvalResult;
|
}
|
|
private ApprovalResult runPullBack(StatePoint statePoint, IOnlineUser user, String remark) throws Exception {
|
ApprovalResult approvalResult = new ApprovalResult();
|
//1. 完成当前步骤
|
WorkingStep step = new PullBackStep(statePoint);
|
insertOneHistory(step, user, ApproveOperate.PullBack, remark);
|
|
//2. 跳出审批,进入提交申请前的状态(Input)
|
approvalResult.setStepLoscation(StepLocation.AtHome);
|
approvalResult.setDetailState("", "");
|
return approvalResult;
|
}
|
|
public boolean isAtFirst() throws Exception {
|
//1.
|
if (!builded) {
|
synchronized (this) {
|
if (!builded) {
|
init();
|
}
|
}
|
}
|
|
//2.
|
return pos == 0;
|
}
|
|
public boolean isAtHome() throws Exception {
|
//1.
|
if (!builded) {
|
synchronized (this) {
|
if (!builded) {
|
init();
|
}
|
}
|
}
|
|
//2.
|
return pos < 0;
|
}
|
|
public boolean isAtLast() throws Exception {
|
//1.
|
if (!builded) {
|
synchronized (this) {
|
if (!builded) {
|
init();
|
}
|
}
|
}
|
|
//2.
|
return pos == workingSteps.size() - 1;
|
}
|
|
public boolean isAtSuccess() throws Exception {
|
//1.
|
if (!builded) {
|
synchronized (this) {
|
if (!builded) {
|
init();
|
}
|
}
|
}
|
|
//2.
|
return pos > workingSteps.size() - 1;
|
}
|
|
private static void closeTargetDocumentFlow(String docId) throws Exception {
|
NamedSQL namedSQL = NamedSQL.getInstance("closeApproveFlowAll");
|
namedSQL.setParam("doc_id", docId);
|
namedSQL.execute();
|
|
namedSQL = NamedSQL.getInstance("closeApproveFlowSteps");
|
namedSQL.setParam("doc_id", docId);
|
namedSQL.execute();
|
}
|
|
private void insertMaster(String dataName, StatePoint masterPoint, StatePoint hostPoint, StatePoint referPoint, ReferObject referObject) throws Exception {
|
masterId = ID.newValue();
|
|
String hostPointId = hostPoint == null ? null : hostPoint.getId();
|
String referPointId = referPoint == null ? null : referPoint.getId();
|
|
DataObject dataObject = DataObject.getInstance("sys_state_working_main");
|
master = dataObject.createTableEntity(true);
|
|
master.set("id", masterId);
|
master.set("machine_id", machine.getId());
|
master.set("dataname", dataName);
|
master.set("operator", masterPoint.getOperator());
|
master.set("title", masterPoint.getStateOperate().getName());
|
master.set("point_master_id", masterPoint.getId());
|
master.set("point_host_id", hostPointId);
|
master.set("point_refer_id", referPointId);
|
master.set("doc_id", docId);
|
master.set("is_working", "T");
|
master.set("is_alive", "T");
|
|
if (referObject != null) {
|
master.set("refer_name", referObject.getDataName());
|
master.set("refer_id", referObject.getId());
|
}
|
|
dataObject.insertEntity(master);
|
}
|
|
private void loadWorkingMaster() throws Exception {
|
Filter filter = new Filter("doc_id", docId).add("is_working", "T");
|
master = masterObject.getTableEntity(filter);
|
|
if (master == null || master.isEmpty()) {
|
masterId = null;
|
return;
|
}
|
|
masterId = master.getId();
|
}
|
|
private void loadActiveMaster() throws Exception {
|
Filter filter = new Filter("doc_id", docId).add("is_alive", "T");
|
master = masterObject.getTableEntity(filter);
|
|
if (master == null || master.isEmpty()) {
|
masterId = null;
|
return;
|
}
|
|
masterId = master.getId();
|
}
|
|
private void lockMaster() throws Exception {
|
DataObject dataObject = DataObject.getInstance("sys_state_working_main");
|
|
EntitySaver saver = dataObject.createEntitySaver(master.getId());
|
saver.set("lock_stamp", ID.newValue());
|
saver.update();
|
}
|
|
private void closeOneStep(WorkingStep step, IOnlineUser user, String remark) throws Exception {
|
if (step == null) {
|
return;
|
}
|
|
DataObject dataObject = DataObject.getInstance("sys_state_working_step");
|
|
EntitySaver saver = dataObject.createEntitySaver(step.getId());
|
saver.set("is_active", "F");
|
saver.set("end_time", now);
|
saver.set("writer_name", user.getEmployeeName());
|
saver.set("remark", remark);
|
saver.update();
|
}
|
|
private void openOneStep(WorkingStep step) throws Exception {
|
if (step == null) {
|
return;
|
}
|
|
DataObject dataObject = DataObject.getInstance("sys_state_working_step");
|
|
EntitySaver saver = dataObject.createEntitySaver(step.getId());
|
saver.set("is_active", "T");
|
saver.set("begin_time", now);
|
saver.set("end_time", ValueType.Null);
|
saver.set("remark", ValueType.Null);
|
saver.update();
|
}
|
|
private void loadWorkingSteps() throws Exception {
|
workingSteps = new WorkingStepList();
|
|
DataObject dataObject = DataObject.getInstance("sys_state_working_step");
|
EntitySet entitySet = dataObject.getTableEntitySet(new Filter("parent_id", masterId), new OrderBy("index_no asc"));
|
|
if (entitySet == null) {
|
return;
|
}
|
|
pos = -1; int idx = 0;
|
|
for (Entity entity: entitySet) {
|
WorkingStep workingStep = new WorkingStep();
|
workingStep.load(entity);
|
workingSteps.loadOne(workingStep);
|
|
if (workingStep.isWorking()) {
|
pos = idx;
|
}
|
|
idx++;
|
}
|
}
|
|
public void resetWorkingStep(String workingStepId) throws Exception {
|
DataObject dataObject = DataObject.getInstance("sys_state_working_user");
|
EntitySet entitySet = dataObject.getTableEntitySet(new Filter("working_step_id", workingStepId));
|
|
String wtiterName;
|
ContentBuilder result = new ContentBuilder(",");
|
for (Entity step : entitySet) {
|
wtiterName = step.getString("writer_name");
|
|
if (Util.isEmpty(wtiterName)) {
|
continue;
|
}
|
|
result.append(wtiterName);
|
}
|
|
String writerNames = result.toString();
|
|
dataObject = DataObject.getInstance("sys_state_working_step");
|
EntitySaver saver = dataObject.createEntitySaver(workingStepId);
|
saver.set("writer_name", writerNames);
|
|
saver.update();
|
}
|
|
private void loadStepHistorys() throws Exception {
|
DataObject dataObject = DataObject.getInstance("sys_state_working_history");
|
histories = dataObject.getTableEntitySet(new Filter("parent_id", masterId), new OrderBy("create_time desc"));
|
}
|
|
private void insertWorkingSteps(StatePoint statePoint, IOnlineUser user, ActionContext context) throws Exception {
|
String machineId = machine.getId();
|
ApproveRuntime steps = statePoint.getSteps(user, context);
|
|
DataObject stepObject = DataObject.getInstance("sys_state_working_step");
|
EntitySet stepSet = stepObject.createTableEntitySet();
|
|
DataObject userObject = DataObject.getInstance("sys_state_working_user");
|
EntitySet userSet = userObject.createTableEntitySet();
|
|
String first = "T";
|
|
for (Step step: steps) {
|
String id = ID.newValue();
|
|
Entity entity = stepSet.append();
|
entity.set("id", id);
|
entity.set("parent_id", masterId);
|
entity.set("machine_id", machine.getId());
|
entity.set("doc_id", docId);
|
entity.set("point_id", statePoint.getId());
|
entity.set("approve_id", step.getParentId());
|
entity.set("approve_step_id", step.getId());
|
entity.set("name", step.getName());
|
entity.set("index_no", step.getIndexNo());
|
entity.set("writer_name", step.getWriterNames());
|
entity.set("is_active", first);
|
entity.set("begin_time", "T".equals(first) ? new Date() : null);
|
|
List<StepUser> stepUsers = step.getUsers();
|
for (StepUser stepUser: stepUsers) {
|
Entity userEntity = userSet.append();
|
|
userEntity.set("id", ID.newValue());
|
userEntity.set("parent_id", masterId);
|
userEntity.set("machine_id", machineId);
|
userEntity.set("doc_id", docId);
|
userEntity.set("point_id", statePoint.getId());
|
userEntity.set("working_step_id", id);
|
userEntity.set("user_id", stepUser.getUserId());
|
userEntity.set("writer_name", stepUser.getWriterName());
|
}
|
|
first = "F";
|
}
|
|
stepObject.insertEntitySet(stepSet);
|
userObject.insertEntitySet(userSet);
|
}
|
|
private void insertOneHistory(WorkingStep step, IOnlineUser user, ApproveOperate operator, String remark) throws Exception {
|
String employeeName = user.getEmployeeName();
|
|
//4. 插入日志记录
|
DataObject dataObject = DataObject.getInstance("sys_state_working_history");
|
|
Entity entity = dataObject.createTableEntity(true);
|
entity.set("id", ID.newValue());
|
entity.set("parent_id", masterId);
|
entity.set("machine_id", machine.getId());
|
entity.set("doc_id", docId);
|
entity.set("point_id", step.getPointId());
|
entity.set("step_id", step.getId());
|
entity.set("step_name", step.getName());
|
entity.set("writer_name", employeeName);
|
entity.set("employee_id", user.getEmployeeId());
|
entity.set("employee_name", employeeName);
|
entity.set("remark", remark);
|
entity.set("user_id", user.getId());
|
entity.set("user_name", user.getName());
|
entity.set("result_code", operator.name());
|
entity.set("result_name", operator.getTitle());
|
entity.set("create_time", now);
|
|
dataObject.insertEntity(entity);
|
}
|
|
private WorkingStep getCurrentStep() throws Exception {
|
//1.
|
if (!builded) {
|
synchronized (this) {
|
if (!builded) {
|
init();
|
}
|
}
|
}
|
|
//2.
|
if (pos < 0 || pos >= workingSteps.size()) {
|
return null;
|
}
|
|
return workingSteps.get(pos);
|
}
|
|
private WorkingStep goNextStep() throws Exception {
|
//1.
|
if (!builded) {
|
synchronized (this) {
|
if (!builded) {
|
init();
|
}
|
}
|
}
|
|
//2.
|
pos = pos + 1;
|
|
if (pos < 0 || pos >= workingSteps.size()) {
|
return null;
|
}
|
|
return workingSteps.get(pos);
|
}
|
|
private WorkingStep goPriorStep() throws Exception {
|
//1.
|
if (!builded) {
|
synchronized (this) {
|
if (!builded) {
|
init();
|
}
|
}
|
}
|
|
//2.
|
pos = pos - 1;
|
|
if (pos < 0 || pos >= workingSteps.size()) {
|
return null;
|
}
|
|
return workingSteps.get(pos);
|
}
|
|
public String getOutStateCode() throws Exception {
|
WorkingStep step = getCurrentStep();
|
|
if (step == null) {
|
return null;
|
}
|
|
return step.getOutStateCode();
|
}
|
|
public EntitySet getHistories() {
|
return histories;
|
}
|
|
public boolean isEmpty() {
|
return master == null;
|
}
|
|
public List<WorkingStep> getWorkingSteps() {
|
return workingSteps.getList();
|
}
|
|
public Entity getMaster() {
|
return master;
|
}
|
|
public String getMasterPointId() {
|
String pointId = master.getString("point_master_id");
|
return pointId;
|
}
|
|
public String getHostPointId() {
|
String pointId = master.getString("point_host_id");
|
return pointId;
|
}
|
|
public String getReferPointId() {
|
String pointId = master.getString("point_refer_id");
|
return pointId;
|
}
|
|
@Override
|
public void writeJSON(IJSONWriter writer) {
|
writer.beginObject();
|
|
//1. steps
|
if (workingSteps == null) {
|
writer.writeNull("steps");
|
}
|
else {
|
writer.beginArray("steps");
|
workingSteps.writeJSONBody(writer);
|
writer.endArray();
|
}
|
|
//2. histories
|
if (histories == null) {
|
writer.writeNull("histories");
|
}
|
else {
|
writer.beginArray("histories");
|
histories.writeJSONBody(writer);
|
writer.endArray();
|
}
|
|
writer.endObject();
|
}
|
|
}
|