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 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 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(); } }