public TargetState Plan(DoOperationInfo info) { var tflow = repoTargetFlow.Query(o => o.TargetFlowId == info.TargetFlowId).FirstOrDefault(); var operation = repoFlowOp.Query(o => o.FlowId == tflow.FlowId && o.OperationId == info.OperationId).FirstOrDefault(); if (operation == null) throw new NullReferenceException(string.Format("Flow operation {0} not found.", info.OperationId)); if (operation.CanPlanned == false) throw new Exception(string.Format("The operation {0} cannot be planned.", operation.Name)); TargetState tstate = new TargetState() { TargetStateId = idGenerator.NewId(), TargetFlowId = tflow.TargetFlowId, StateId = operation.DefaultNextStateId, Title = info.Title, Message = info.Message, StateStatus = StateStatus.Planned, PlanTreatTime = info.OperationTime, PlannerId = info.UserId, PlannerName = info.UserName, }; NextTargetState nts = new NextTargetState() { TargetStateId = info.TargetStateId, NextTargetStateId = tstate.TargetStateId }; try { trans.BeginTransaction(); repoTargetState.Insert(tstate); repoNextTargetState.Insert(nts); trans.Commit(); } catch (Exception ex) { trans.Rollback(); throw ex; } TargetStateChangedMessage msg = new TargetStateChangedMessage() { OldTargetStates = null, NewTargetState = tstate, OperationId = null, DataOperation = DataOperation.Insert, OperateTime = info.OperationTime, OperatorId = info.UserId, OperatorName = info.UserName }; try { MessageManager.Publish<TargetStateChangedMessage>(msg); } catch (Exception ex) { //throw ex; } return tstate; }
public TargetState Do(DoOperationInfo info) { var tflow = repoTargetFlow.Query(o => o.TargetFlowId == info.TargetFlowId).FirstOrDefault(); if (tflow == null) throw new NullReferenceException(string.Format("Target flow {0} not found.", info.TargetFlowId)); var flow = repoBizFlow.Query(o => o.FlowId == tflow.FlowId).FirstOrDefault(); if (flow == null) throw new NullReferenceException(string.Format("Flow {0} not found.", tflow.FlowId)); var fop = repoFlowOp.Query(o => o.OperationId == info.OperationId).FirstOrDefault(); if (fop == null) throw new ArgumentNullException(string.Format("Flow operation {0} is not found.", info.OperationId)); FlowState nextState = null; if (!string.IsNullOrEmpty(info.NextStateIdOrCode)) nextState = repoFlowState.Query(o => o.FlowId == flow.FlowId && (o.StateId == info.NextStateIdOrCode || o.Code == info.NextStateIdOrCode)).FirstOrDefault(); if (nextState == null) nextState = repoFlowState.Query(o => o.StateId == fop.DefaultNextStateId).FirstOrDefault(); if (nextState == null) throw new NullReferenceException(string.Format("Operation {0} doesn't define next state.", fop.OperationId)); List<TargetState> needUpdatedTargetStates = new List<TargetState>(); if(!string.IsNullOrEmpty(info.TargetStateId)) { var tstate = repoTargetState.Query(o => o.TargetStateId == info.TargetStateId).FirstOrDefault(); needUpdatedTargetStates.Add(tstate); } // 当前状态为并行结束结点,需要判断当前并行点的所有操作是否都已经完成。 if (nextState.StateType == StateType.ParallelEnd) { bool allShouldDone = nextState.AllParallelStateShouldBeEnd.HasValue && nextState.AllParallelStateShouldBeEnd.Value; bool canExecute = true; var ts = repoTargetState.Query(o => o.TargetFlowId == tflow.TargetFlowId && o.State.StateType == StateType.ParallelStop && (int)o.StateStatus < (int)StateStatus.TreatedNormal).ToArray(); foreach (var t in ts) { var prevStateHasThisOperation = repoStateOp.Query(o => o.StateId == t.StateId && o.OperationId == fop.OperationId).Any(); if (allShouldDone) canExecute = canExecute && prevStateHasThisOperation; else canExecute = prevStateHasThisOperation; } // 必须所有并行的操作都达到下一状态(并行结束ParallelEnd结点),才可以进行后续的操作。 if (canExecute) { // 其他操作中,所有其他操作都已执行且执行后的状态都允许进行后续的操作。即本次操作是并行操作中的最后一个操作。 needUpdatedTargetStates.AddRange(ts); } else { throw new InvalidOperationException(string.Format("Target flow {0} is waiting for finishing parallel operations.", info.TargetFlowId)); } } List<NextTargetState> nextTargetStates = new List<NextTargetState>(); string nextTargetStateId = idGenerator.NewId(); foreach (var tstate in needUpdatedTargetStates) { var state = repoFlowState.Query(o => o.StateId == tstate.StateId).FirstOrDefault(); if (state == null) throw new NullReferenceException(string.Format("State {0} not found.", tstate.StateId)); StateStatus stateStatus = StateStatus.TreatedNormal; var sincomes = repoStateIncome.Query(o => o.StateId == tstate.StateId && o.IsRequired == true); if (sincomes.Any()) { var cincomes = repoTargetIncome.Query(o => o.TargetStateId == info.TargetStateId && sincomes.Any(d => d.IncomeId == o.IncomeId) && o.FileStatus != FileStatus.InValid); if (sincomes.Count() > cincomes.Count()) { if (flow.StopWhenIncomeRequired) { throw new ApplicationException("Some required incomes are not offered."); } else { stateStatus = StateStatus.TreatedError; } } else { if (cincomes.Any(o => o.FileStatus == FileStatus.Draft)) stateStatus = StateStatus.TreatedWarn; } } var soutcomes = repoStateOutcome.Query(o => o.StateId == tstate.StateId && o.IsRequired == true); if (soutcomes.Any()) { var coutcomes = repoTargetOutcome.Query(o => o.TargetStateId == tstate.TargetStateId && soutcomes.Any(d => d.OutcomeId == o.OutcomeId) && o.FileStatus != FileStatus.InValid); if (soutcomes.Count() > coutcomes.Count()) { if (flow.StopWhenIncomeRequired) { throw new ApplicationException("Some required outcomes are not offered."); } else { stateStatus = StateStatus.TreatedError; } } else { if (coutcomes.Any(o => o.FileStatus == FileStatus.Draft)) stateStatus = StateStatus.TreatedWarn; } } tstate.TreatTime = info.OperationTime; tstate.StateStatus = stateStatus; tstate.TreaterId = info.UserId; tstate.TreaterName = info.UserName; var nts = repoNextTargetState.Query(o => o.TargetStateId == tstate.TargetStateId && o.ToTargetState.StateId == nextState.StateId).FirstOrDefault(); if (nts == null) { nts = new NextTargetState() { TargetStateId = tstate.TargetStateId, NextTargetStateId = nextTargetStateId }; } else { nextTargetStateId = nts.NextTargetStateId; } if (state.StateType == StateType.ParallelBegin) { nts.ParallelTargetStateId = tstate.TargetStateId; } else if (state.StateType == StateType.ParallelStop || state.StateType == StateType.ParallelEnd) { var lastnts = repoNextTargetState.Query(o => o.NextTargetStateId == tstate.TargetStateId).FirstOrDefault(); nts.ParallelTargetStateId = lastnts.ParallelTargetStateId; } nextTargetStates.Add(nts); } var nextTargetState = repoTargetState.Query(o => nextTargetStateId == o.TargetStateId && o.StateId == nextState.StateId).FirstOrDefault(); if (nextTargetState == null) { nextTargetState = new TargetState() { TargetStateId = nextTargetStateId, TargetFlowId = tflow.TargetFlowId, StateId = nextState.StateId, }; } nextTargetState.Title = info.Title; nextTargetState.Message = info.Message; nextTargetState.OperateTime = info.OperationTime; nextTargetState.StateStatus = StateStatus.None; nextTargetState.OperationId = info.OperationId; nextTargetState.OperatorId = info.UserId; nextTargetState.OperatorName = info.UserName; if (nextState.IntervalType.HasValue) { if (nextState.ResponseIntervalValue.HasValue) nextTargetState.ResponseExpiryTime = info.OperationTime.Interval(nextState.IntervalType, nextState.ResponseIntervalValue); if (nextState.TreatIntervalValue.HasValue) nextTargetState.TreatExpiryTime = info.OperationTime.Interval(nextState.IntervalType, nextState.TreatIntervalValue); } try { trans.BeginTransaction(); if (nextState.StateType == StateType.End) { nextTargetState.StateStatus = StateStatus.TreatedNormal; tflow.HasCompleted = true; tflow.Result = nextState.Result; repoTargetFlow.Update(tflow); } needUpdatedTargetStates.ForEach(o => repoTargetState.Update(o)); repoTargetState.Insert(nextTargetState); nextTargetStates.ForEach(o => repoNextTargetState.Save(t => t.TargetStateId == o.TargetStateId && t.NextTargetStateId == o.NextTargetStateId,o)); trans.Commit(); } catch (Exception ex) { trans.Rollback(); throw ex; } TargetStateChangedMessage msg = new TargetStateChangedMessage() { OldTargetStates = needUpdatedTargetStates, NewTargetState = nextTargetState, OperationId = fop.OperationId, DataOperation = DataOperation.Update, OperateTime = info.OperationTime, OperatorId = info.UserId, OperatorName = info.UserName }; try { MessageManager.Publish<TargetStateChangedMessage>(msg); } catch (Exception ex) { //throw ex; } return nextTargetState; }