public static string UserName(this TargetState tstate) { switch (tstate.StateStatus) { case StateStatus.Responsed: return(tstate.ResponsorName); case StateStatus.Planned: return(tstate.PlannerName); default: return(tstate.OperatorName); } }
public static DateTime OperationTime(this TargetState tstate) { switch (tstate.StateStatus) { case StateStatus.Responsed: return(tstate.ResponseTime.Value); case StateStatus.Planned: return(tstate.PlanTreatTime.Value); default: return(tstate.OperateTime.Value); } }
/* public BizFlow GetFlow(string flowId, bool loadAllInfo = true) { BizFlow flow = repoBizFlow.Query(o => o.FlowId == flowId).FirstOrDefault(); if (flow == null) throw new NullReferenceException(string.Format("Flow {0} not found!", flowId)); if (loadAllInfo) { LoadBizFlowAllInfo(flow); } return flow; } private void LoadBizFlowAllInfo(BizFlow flow) { flow.States = repoFlowState.Query(o => o.FlowId == flow.FlowId).OrderBy(o => o.Code).ToArray(); flow.Operations = repoFlowOp.Query(o => o.FlowId == flow.FlowId).OrderBy(o => o.Code).ToArray(); flow.Incomes = repoFlowIncome.Query(o => o.FlowId == flow.FlowId).OrderBy(o => o.Code).ToArray(); flow.Outcomes = repoFlowOutcome.Query(o => o.FlowId == flow.FlowId).OrderBy(o => o.Code).ToArray(); flow.NextBizFlows = repoNextFlow.Query(o => o.FlowId == flow.FlowId).ToArray(); flow.States.ForEach(it => { it.Operations = repoStateOp.Query(op => op.StateId == it.StateId).ToArray(); it.Incomes = repoStateIncome.Query(op => op.StateId == it.StateId).ToArray(); it.Outcomes = repoStateOutcome.Query(op => op.StateId == it.StateId).ToArray(); it.Operations.ForEach(o => { o.Operation = flow.Operations.FirstOrDefault(op => op.OperationId == o.OperationId); }); it.Incomes.ForEach(o => { o.Income = flow.Incomes.FirstOrDefault(d => d.IncomeId == o.IncomeId); }); it.Outcomes.ForEach(o => { o.Outcome = flow.Outcomes.FirstOrDefault(d => d.OutcomeId == o.OutcomeId); }); }); flow.NextBizFlows.ForEach(it => { it.FromBizFlow = flow; it.ToBizFlow = repoBizFlow.Query(o => o.FlowId == it.NextFlowId).FirstOrDefault(); }); } public IEnumerable<TargetFlow> LoadFlows(string clientId, string flowCodeOrTargetType, DateTime? beginTime, DateTime? endTime, bool? started, bool? completed, FlowResult? result, bool loadAllInfo = true) { var query = repoTargetFlow.Query(o => o.Flow.ClientId == clientId && (o.Flow.Code == flowCodeOrTargetType || o.Flow.TargetType == flowCodeOrTargetType)); if (beginTime.HasValue) { query = query.Where(o => o.CreateTime >= beginTime.Value); } if (endTime.HasValue) { query = query.Where(o => o.CreateTime <= endTime.Value); } if (started.HasValue) { query = query.Where(o => o.HasStarted == started.Value); } if (completed.HasValue) { query = query.Where(o => o.HasCompleted == completed.Value); } if (result.HasValue) { query = query.Where(o => o.Result.Value == result.Value); } var tflows = query.ToArray(); if (loadAllInfo) { tflows.ForEach(o => LoadTargetFlowAllInfo(o)); } return tflows; } public TargetFlow LoadFlow(string clientId, string flowCodeOrTargetType, string targetId, bool loadAllInfo = true) { var tflowId = repoTargetFlow.Query(o => o.Flow.ClientId == clientId && (o.Flow.Code == flowCodeOrTargetType || o.Flow.TargetType == flowCodeOrTargetType) && o.TargetId == targetId).Select(o => o.TargetFlowId).FirstOrDefault(); if (string.IsNullOrEmpty(tflowId)) return null; return LoadFlow(tflowId, loadAllInfo); } public TargetFlow LoadFlow(string targetFlowId, bool loadAllInfo = true) { var tflow = repoTargetFlow.Query(o => o.TargetFlowId == targetFlowId).FirstOrDefault(); if (tflow == null) return null; if (tflow != null && loadAllInfo) { LoadTargetFlowAllInfo(tflow); } return tflow; } private void LoadTargetFlowAllInfo(TargetFlow tflow) { tflow.Flow = GetFlow(tflow.FlowId, true); tflow.TreatedStates = repoTargetState.Query(o => o.TargetFlowId == tflow.TargetFlowId).ToArray(); tflow.TreatedStates.ForEach(o => { o.TargetIncomes = repoTargetIncome.Query(d => d.TargetStateId == o.TargetStateId).ToArray(); o.TargetOutcomes = repoTargetOutcome.Query(d => d.TargetStateId == o.TargetStateId).ToArray(); o.State = tflow.Flow.States.FirstOrDefault(s => s.StateId == o.StateId); o.Operation = tflow.Flow.Operations.FirstOrDefault(p => p.OperationId == o.OperationId); o.TargetIncomes.ForEach(obj => { obj.Income = tflow.Flow.Incomes.FirstOrDefault(d => d.IncomeId == obj.IncomeId); }); o.TargetOutcomes.ForEach(obj => { obj.Outcome = tflow.Flow.Outcomes.FirstOrDefault(d => d.OutcomeId == obj.OutcomeId); }); }); if (!string.IsNullOrEmpty(tflow.LastTargetFlowId)) { tflow.LastTargetFlow = repoTargetFlow.Query(o => o.TargetFlowId == tflow.LastTargetFlowId).FirstOrDefault(); } } public TargetState LoadState(string targetStateId, bool loadAllInfo = true) { var tstate = repoTargetState.Query(o => o.TargetStateId == targetStateId).OrderByDescending(o => o.OperateTime).FirstOrDefault(); if (tstate == null) throw new NullReferenceException(string.Format("Target Flow state {0} not found!", targetStateId)); if (loadAllInfo) { LoadTargetStateAllInfo(tstate); } return tstate; } private void LoadTargetStateAllInfo(TargetState tstate) { tstate.TargetFlow = repoTargetFlow.Query(o => o.TargetFlowId == tstate.TargetFlowId).FirstOrDefault(); tstate.State = repoFlowState.Query(o => o.StateId == tstate.StateId).FirstOrDefault(); if (tstate.State != null) { tstate.State.Operations = repoStateOp.Query(o => o.StateId == tstate.StateId).ToArray(); tstate.State.Operations.ForEach(op => { op.State = tstate.State; op.Operation = repoFlowOp.Query(o => o.OperationId == op.OperationId).FirstOrDefault(); }); tstate.State.Incomes = repoStateIncome.Query(o => o.StateId == tstate.StateId).ToArray(); tstate.State.Incomes.ForEach(obj => { obj.State = tstate.State; obj.Income = repoFlowIncome.Query(o => o.IncomeId == obj.IncomeId).FirstOrDefault(); }); tstate.State.Outcomes = repoStateOutcome.Query(o => o.StateId == tstate.StateId).ToArray(); tstate.State.Outcomes.ForEach(obj => { obj.State = tstate.State; obj.Outcome = repoFlowOutcome.Query(o => o.OutcomeId == obj.OutcomeId).FirstOrDefault(); }); } tstate.FromTargetStates = repoNextTargetState.Query(o => o.NextTargetStateId == tstate.TargetStateId).ToList(); tstate.FromTargetStates.ForEach(obj => { obj.ToTargetState = tstate; obj.FromTargetState = repoTargetState.Query(o => o.TargetStateId == obj.TargetStateId).FirstOrDefault(); }); tstate.ToTargetStates = repoNextTargetState.Query(o => o.TargetStateId == tstate.TargetStateId).ToList(); tstate.ToTargetStates.ForEach(obj => { obj.FromTargetState = tstate; obj.ToTargetState = repoTargetState.Query(o => o.TargetStateId == obj.NextTargetStateId).FirstOrDefault(); }); tstate.TargetIncomes = repoTargetIncome.Query(o => o.TargetStateId == tstate.TargetStateId).ToList(); tstate.TargetOutcomes = repoTargetOutcome.Query(o => o.TargetStateId == tstate.TargetStateId).ToList(); if (!string.IsNullOrEmpty(tstate.OperationId)) tstate.Operation = repoFlowOp.Query(o => o.OperationId == tstate.OperationId).FirstOrDefault(); } */ /* public IEnumerable<TargetState> GetCurrentStates(string targetFlowId, bool loadAllInfo = true) { var tflow = LoadFlow(targetFlowId, loadAllInfo); if (tflow == null) throw new NullReferenceException(string.Format("Target Flow {0} not found!", targetFlowId)); var tstates = repoTargetState.Query(o => o.TargetFlowId == tflow.TargetFlowId && o.StateStatus == StateStatus.None).OrderByDescending(o => o.OperateTime).ToArray(); if (tstates == null || tstates.Count() <= 0) tstates = repoTargetState.Query(o => o.TargetFlowId == tflow.TargetFlowId && o.State.StateType == StateType.End).ToArray(); if (tstates == null || tstates.Count() <= 0) tstates = repoTargetState.Query(o => o.TargetFlowId == tflow.TargetFlowId && o.State.StateType == StateType.Begin).ToArray(); if (loadAllInfo) { tstates.ForEach(o => LoadTargetStateAllInfo(o)); } return tstates; } public IEnumerable<FlowOperation> GetNextOperations(string targetFlowId) { var tStates = GetCurrentStates(targetFlowId, false); List<FlowOperation> operations = new List<FlowOperation>(); TargetState paralleTargetState = null; foreach(var tstate in tStates) { switch(tstate.StateStatus) { case StateStatus.Started: var ops = GetStateOperations(tstate.StateId); operations.AddRange(ops); break; case StateStatus.Finished: break; case StateStatus.None: var state = repoFlowState.Query(o => o.StateId == tstate.StateId).FirstOrDefault(); if(state.StateType == StateType.ParallelStop) { paralleTargetState = tstate; if (!state.AllParallelStateShouldBeEnd.HasValue || !state.AllParallelStateShouldBeEnd.Value) { var currOps = GetStateOperations(tstate.StateId); operations.AddRange(currOps); } } break; } } // 添加未开始执行的并行操作 if (paralleTargetState != null) { var nts = repoNextTargetState.Query(o => o.NextTargetStateId == paralleTargetState.TargetStateId).FirstOrDefault(); var beginParallelTState = repoTargetState.Query(o => o.TargetStateId == nts.ParallelTargetStateId).FirstOrDefault(); var beginParallelOpids = repoStateOp.Query(o => o.StateId == beginParallelTState.StateId).Select(o => o.OperationId); var startedOpids = repoTargetState.Query(o => o.TargetFlowId == paralleTargetState.TargetFlowId && beginParallelOpids.Contains(o.OperationId)).Select(o => o.OperationId); var notStartedOpids = beginParallelOpids.Except(startedOpids); var notStartedOps = repoFlowOp.Query(o => notStartedOpids.Contains(o.OperationId)).ToArray(); operations.AddRange(notStartedOps); } return operations; } private IEnumerable<FlowOperation> GetStateOperations(string stateId) { var opids = repoStateOp.Query(o => o.StateId == stateId).Select(o => o.OperationId); var ops = repoFlowOp.Query(o => opids.Contains(o.OperationId)).ToArray(); return ops; } */ public TargetState StartFlow(StartFlowInfo info) { BizFlow flow = repoBizFlow.Query(o => o.ClientId == info.ClientId && (o.Code == info.FlowCodeOrTargetType || o.TargetType == info.FlowCodeOrTargetType)).FirstOrDefault(); if (flow == null) throw new NullReferenceException(string.Format("Flow {0} not found!", info.FlowCodeOrTargetType)); TargetFlow tflow = repoTargetFlow.Query(o => o.FlowId == flow.FlowId && o.TargetId == info.TargetId).FirstOrDefault(); if (tflow == null) { tflow = new TargetFlow() { TargetFlowId = idGenerator.NewId(), FlowId = flow.FlowId, TargetId = info.TargetId, FlowCode = info.TargetFlowCode, Title = info.FlowTitle, Message = info.FlowMessage, HasStarted = false, HasCompleted = false, CreatorId = info.UserId, CreatorName = info.UserName, CreateTime = info.OperationTime }; if (!string.IsNullOrEmpty(info.LastTargetFlowId)) { tflow.LastTargetFlowId = info.LastTargetFlowId; NextTargetFlowCreatedMessage msg = new NextTargetFlowCreatedMessage() { FinishedTargetFlow = repoTargetFlow.Query(o => o.TargetFlowId == info.LastTargetFlowId).FirstOrDefault(), CreatedTargetFlow = tflow, OperateTime = info.OperationTime, OperatorId = info.UserId, OperatorName = info.UserName }; try { MessageManager.Publish<NextTargetFlowCreatedMessage>(msg); } catch (Exception ex) { //throw ex; } } repoTargetFlow.Insert(tflow); } var startState = repoFlowState.Query(o => o.FlowId == tflow.FlowId && o.StateType == StateType.Begin).FirstOrDefault(); if (startState == null) throw new NullReferenceException(string.Format("Flow {0} has no start state defined.", tflow.FlowId)); TargetState tstate = new TargetState() { TargetStateId = idGenerator.NewId(), TargetFlowId = tflow.TargetFlowId, StateId = startState.StateId, Title = info.StartTitle, Message = info.StartMessage, StateStatus = StateStatus.Started, OperateTime = info.OperationTime, OperatorId = info.UserId, OperatorName = info.UserName }; if (startState.IntervalType.HasValue) { if (startState.ResponseIntervalValue.HasValue) tstate.ResponseExpiryTime = info.OperationTime.Interval(startState.IntervalType, startState.ResponseIntervalValue); if (startState.TreatIntervalValue.HasValue) tstate.TreatExpiryTime = info.OperationTime.Interval(startState.IntervalType, startState.ResponseIntervalValue); } tflow.HasStarted = true; try { trans.BeginTransaction(); repoTargetFlow.Update(tflow); repoTargetState.Insert(tstate); trans.Commit(); } catch (Exception ex) { trans.Rollback(); throw ex; } TargetStateChangedMessage tscMsg = new TargetStateChangedMessage() { OldTargetStates = null, NewTargetState = tstate, OperationId = null, DataOperation = DataOperation.Insert, OperateTime = info.OperationTime, OperatorId = info.UserId, OperatorName = info.UserName }; try { MessageManager.Publish<TargetStateChangedMessage>(tscMsg); } catch (Exception ex) { //throw ex; } //tstate.State = startState; //tstate.TargetFlow = tflow; //tstate.TargetFlow.Flow = flow; return tstate; }
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; }
public TargetStateWrapper(TargetFlowWrapper tflow, TargetState tstate) : this(tflow, new TargetState[] { tstate }) { }