unit FLOWSTKOUTCTRLFORM;
interface
uses
Business.System, Business.Forms, Business.Model,
Business.Model.Org, Business.Model.Flow,
SysFuncCommonUnit, SystemCore,
BaseFlowBrowseFunc, BaseFlowStakeoutFunc;
type
TFLOWSTKOUTCTRLFORM = class(BaseFlowStakeoutFunc.TBaseFlowStakeoutMainForm)
actFlowBack: TAction;
actFlowOut: TAction;
actFlowTransmit: TAction;
actFlowAbort: TAction;
actTaskAbort: TAction;
actModifyController: TAction;
tbFlowBack: TToolButton;
tbFlowOut: TToolButton;
tbFlowTransmit: TToolButton;
tbTaskAbort: TToolButton;
tbFlowAbort: TToolButton;
tbModifyController: TToolButton;
mmiFlow: TMenuItem;
N1: TMenuItem;
pmiFlowAbort: TMenuItem;
N2: TMenuItem;
pmiFlowView: TMenuItem;
N3: TMenuItem;
pmiFlowBack: TMenuItem;
pmiFlowOut: TMenuItem;
pmiFlowTransmit: TMenuItem;
pmiTaskAbort: TMenuItem;
pmiModifyController: TMenuItem;
pmiShowBizData: TMenuItem;
mmiFlowBack: TMenuItem;
mmiFlowOut: TMenuItem;
mmiFlowTransmit: TMenuItem;
mmiTaskAbort: TMenuItem;
mmiFlowAbort: TMenuItem;
mmiModifyController: TMenuItem;
actAddExecutor: TAction;
actCancelExecutor: TAction;
pmiAddExecutor: TMenuItem;
pmiCancelExecutor: TMenuItem;
tbAddExecutor: TToolButton;
tbCancelExecutor: TToolButton;
procedure actFlowBackExecute(Sender: TObject);
procedure actFlowOutExecute(Sender: TObject);
procedure actFlowTransmitExecute(Sender: TObject);
procedure actFlowAbortExecute(Sender: TObject);
procedure actTaskAbortExecute(Sender: TObject);
procedure actModifyControllerExecute(Sender: TObject);
procedure actFlowAbortUpdate(Sender: TObject);
procedure actModifyControllerUpdate(Sender: TObject);
procedure BizFormShow(Sender: TObject);
procedure actFlowBackUpdate(Sender: TObject);
procedure actAddExecutorExecute(Sender: TObject);
procedure actAddExecutorUpdate(Sender: TObject);
procedure actCancelExecutorExecute(Sender: TObject);
procedure actCancelExecutorUpdate(Sender: TObject);
private
{private declarations}
function CreateFunc(const AContext: TContext; const ATask: TTask): TFunc;
function GetFuncURL(const ATask: TTask): string;
// function CreateOperatorURL: TOrgURL;
// procedure ChangeTaskMsg(const AOrgURL: TOrgURL; ATask: TTask);
protected
function CreateFlowRangeDlg: TFlowRangeDlg; override;
procedure DoFlowOperate(AFlowOperation: TFlowOperation);
function HasActiveTaskMsg(const ATask: TTask): Boolean;
function GetNewTaskMsgSequence(const ATask: TTask): Integer;
public
{public declarations}
end;
TFlowOperation = (foBack, foOut, foTransmit, foTaskAbort);
implementation
const
//可以终止的流程状态
csCanAbortFlowStates = [TFlowState.fsProcessing, TFlowState.fsPostPoned];
//此常量定义了可以改变控制者的任务消息状态
csCanModifyControllerStates = [TTaskMessageState.tmsSend, TTaskMessageState.tmsReceived,
TTaskMessageState.tmsWaiting];
{此常量定义了改变控制者时,新控制者的状态应于原来控制者一样的状态类型,
如果不在此状态集合内,则新控制者的状态统一为“未接收”}
csKeepOrginStates = [TTaskMessageState.tmsWaiting];
msg_FlowAbortConfirm = '确定要终止流程 "%s(%s)" 吗?';
msg_CancelExecutor = '确定要取消执行者"%s%s%s"吗?';
cFormat_BizDataCaption = '业务数据 [ %s ]';
procedure TFLOWSTKOUTCTRLFORM.actFlowBackExecute(Sender: TObject);
begin
DoFlowOperate(TFlowOperation.foBack);
end;
procedure TFLOWSTKOUTCTRLFORM.actFlowOutExecute(Sender: TObject);
begin
DoFlowOperate(TFlowOperation.foOut);
end;
procedure TFLOWSTKOUTCTRLFORM.actFlowTransmitExecute(Sender: TObject);
begin
DoFlowOperate(TFlowOperation.foTransmit);
end;
procedure TFLOWSTKOUTCTRLFORM.actFlowAbortExecute(Sender: TObject);
var
lFlowControl: TFlowControl;
lFlow: TFlow;
lFlowList: TList;
begin
Inherited;
lFlowControl := TFlowControl.Create(BizSys.GlobalContext);
try
lFlow := GetSelectedFlow;
lFlowControl.RegisterFlow(lFlow, nil);
if not lFlowControl.CanAbortFlow then
begin
JSDialogs.ShowMsg('此流程不能终止!', '');
Exit;
end;
if JSDialogs.ConfirmBox(SysUtils.Format(msg_FlowAbortConfirm,
[lFlow.DisplayName, lFlow.ID]), '', 2) then
begin
lFlowList := TList.Create;
try
lFlowList.Add(lFlow);
lFlowControl.FlowAbort(lFlowList);
ReloadProcFlow;
RefreshFlowGrid;
finally
lFlowList.Free;
end;
end;
finally
lFlowControl.UnRegisterFlow(lFlow, nil);
lFlowControl.Free;
end;
end;
procedure TFLOWSTKOUTCTRLFORM.actTaskAbortExecute(Sender: TObject);
begin
Inherited;
DoFlowOperate(TFlowOperation.foTaskAbort);
end;
procedure TFLOWSTKOUTCTRLFORM.actModifyControllerExecute(Sender: TObject);
var
lController: TControllerItem;
lDialog: TSelSubordinationDlg;
Save_Cursor: TCursor;
lBizNode: TBizNode;
lOrgURL: TOrgURL;
lTask: TTask;
lOrginTaskMsg, lNewTaskMsg: TTaskMessage;
lFlow: TFlow;
begin
Inherited;
lController := GetSelectedController;
if lController = nil then
Exit;
lDialog := TSelSubordinationDlg.Create(nil);
try
lDialog.Caption := '修改控制者';
lDialog.PromptText :=
'要修改当前控制者,请先从下面的组织模型树中选择要指定为控制者的组织单元,然后点击“确定”按钮即可。';
lDialog.BizTreeView.ShowOptions := [TBizObjectKind.boOrgServer, TBizObjectKind.boFolder,
TBizObjectKind.boOrgRoot, TBizObjectKind.boOrgan, TBizObjectKind.boDept,
TBizObjectKind.boPositionMember, TBizObjectKind.boPersonMember,
TBizObjectKind.boPositionRoot, TBizObjectKind.boPosition];
lDialog.BizTreeView.SmartOptions := [TBizObjectKind.boFolder];
lDialog.MustSelectedNode := [TBizObjectKind.boDept,
TBizObjectKind.boPositionMember, TBizObjectKind.boPersonMember,
TBizObjectKind.boPosition];
lDialog.MultiSelect := False;
lDialog.Init;
if lDialog.ShowModal = Business.Forms.Controls.mrOK then
begin
Save_Cursor := Forms.Screen.Cursor;
Forms.Screen.Cursor := Business.Forms.Controls.crHourGlass;
try
lBizNode := BizTree.BizTreeStructure.FindNodeByFullFileName(lDialog.Files[0]);
if lBizNode <> nil then
begin
lOrgURL := TOrgURL.Create(lBizNode.BizURL);
try
lFlow := GetSelectedFlow;
lTask := lFlow.Tasks.FindTaskByGUID(lController.Task.GUID);
lOrginTaskMsg := lTask.TaskMessages.GetTaskMessage(lController.TaskMessage.GUID);
if not (SysUtils.SameText(lOrginTaskMsg.ReceiverDeptID, lOrgURL.DeptID) and
SysUtils.SameText(lOrginTaskMsg.ReceiverPositionID, lOrgURL.PositionID) and
SysUtils.SameText(lOrginTaskMsg.ReceiverID, lOrgURL.PersonID)) then
begin
lNewTaskMsg := TTaskMessage.Create(lTask.TaskMessages);
lNewTaskMsg.ParentGUID := lOrginTaskMsg.ParentGUID;
if lOrginTaskMsg.State in csKeepOrginStates then
lNewTaskMsg.State := lOrginTaskMsg.State
else
lNewTaskMsg.State := TTaskMessageState.tmsSend;
lNewTaskMsg.ReceiverDeptID := lOrgURL.DeptID;
lNewTaskMsg.ReceiverPositionID := lOrgURL.PositionID;
lNewTaskMsg.ReceiverID := lOrgURL.PersonID;
lTask.TaskMessages.Add(lNewTaskMsg);
lOrginTaskMsg.State := TTaskMessageState.tmsCanceled;
Task.TaskManager.SaveTask(lTask);
ReLoadFlowController(lFlow.GUID);
RefreshControllerGrid;
end;
finally
lOrgURL.Free;
end;
end;
finally
Forms.Screen.Cursor := Save_Cursor;
end;
end;
finally
lDialog.Free;
end;
end;
procedure TFLOWSTKOUTCTRLFORM.actFlowAbortUpdate(Sender: TObject);
var
lFlow: TFlow;
begin
lFlow := GetSelectedFlow;
if Assigned(lFlow) then
actFlowAbort.Enabled := (lFlow.State in csCanAbortFlowStates)
else
actFlowAbort.Enabled := False;
end;
procedure TFLOWSTKOUTCTRLFORM.actModifyControllerUpdate(Sender: TObject);
var
lController: TControllerItem;
begin
Inherited;
lController := GetSelectedController;
if Assigned(lController) then
actModifyController.Enabled := lController.TaskMessage.State in csCanModifyControllerStates
else
actModifyController.Enabled := False;
end;
function TFLOWSTKOUTCTRLFORM.CreateFlowRangeDlg: TFlowRangeDlg;
begin
Result := TSysFlowRangeDlg.Create(Context);
end;
procedure TFLOWSTKOUTCTRLFORM.BizFormShow(Sender: TObject);
begin
Inherited;
{以下代码是为了解决ToolBar继承的按钮位置改动问题 }
{tbFlowRange.Left := 700;
tbRefresh.Left := 800;
tbColumnSelector.Left := 900;
tbFlowBack.Action := nil;
tbFlowBack.Action := actFlowBack;
tbFlowBack.Caption := '回退';
tbFlowOut.Action := nil;
tbFlowOut.Action := actFlowOut;
tbFlowOut.Caption := '流转';
tbFlowTransmit.Action := nil;
tbFlowTransmit.Action := actFlowTransmit;
tbFlowTransmit.Caption := '转发';
tbTaskAbort.Action := nil;
tbTaskAbort.Action := actTaskAbort;
tbTaskAbort.Caption := '终止任务';
tbFlowAbort.Action := nil;
tbFlowAbort.Action := actFlowAbort;
tbFlowAbort.Caption := '终止流程';
tbModifyController.Action := nil;
tbModifyController.Action := actModifyController;
tbModifyController.Caption := '修改控制者';
tbShowBizData.Action := nil;
tbShowBizData.Action := actShowBizData;
tbShowBizData.Caption := '业务数据';
tbFlowView.Action := nil;
tbFlowView.Action := actFlowView;
tbFlowView.Caption := '浏览';}
end;
procedure TFLOWSTKOUTCTRLFORM.actFlowBackUpdate(Sender: TObject);
begin
(Sender as TAction).Enabled := False;
//(Sender as TAction).Enabled := (CurrentSelTask <> nil);
end;
procedure TFLOWSTKOUTCTRLFORM.DoFlowOperate(AFlowOperation: TFlowOperation);
{var
lFlowControl: TFlowControl;
lOrgURL: TOrgURL;
lFunc: TFunc;
lResult: Boolean;
lDoTask: TTask;}
begin
{是否提供各种动作,还未定,暂且屏蔽
if CurrentSelTask = nil then
Exit;
lDoTask := TTask.Create;
try
lDoTask.Assign(CurrentSelTask);
lFlowControl := TFlowControl.Create(BizSys.GlobalContext);
lFunc := CreateFunc(lFlowControl.Context, lDoTask);
lOrgURL := CreateOperatorURL;
try
ChangeTaskMsg(lOrgURL, lDoTask);
lFlowControl.ExecuteTask(lDoTask, lOrgURL);
lFlowControl.Func := lFunc;
lFunc.Run('');
case AFlowOperation of
TFlowOperation.foBack:
lResult := lFlowControl.FlowBack(nil);
TFlowOperation.foOut:
lResult := lFlowControl.FlowOut(nil);
TFlowOperation.foTransmit:
lResult := lFlowControl.FlowTransmit(nil);
TFlowOperation.foTaskAbort:
lResult := lFlowControl.TaskAbort(nil);
end;
if lResult then
begin
ReloadProcFlow(GetSelectedProcNode);
RefreshFlowGrid;
end
else
begin}
{恢复。保存后任务消息不变,需要内部支持}
//Task.TaskManager.SaveTask(CurrentSelTask);
{ end;
finally
lFunc.Free;
lOrgURL.Free;
lFlowControl.Free;
end;
finally
lDoTask.Free;
end;}
end;
{function TFlowStkoutCtrlForm.CreateOperatorURL: TOrgURL;
var
lOrgURL: TOrgURL;
begin
lOrgURL := TOrgURL.Create;
try
lOrgURL.SetBizURL(TSysFuncCommonUnit.GetPersonMember(Context).BizURL);
Result := TOrgURL.Create(lOrgURL.DeptID, lOrgURL.PositionID,
lOrgURL.PersonID);
finally
lOrgURL.Free;
end;
end;}
function TFLOWSTKOUTCTRLFORM.GetFuncURL(const ATask: TTask): string;
var
lProcURL: TBizURL;
lProc: TProc;
begin
lProcURL := TBizURL.Create;
try
lProcURL.URL := ATask.ProcURL;
lProc := TProc(Business.Model.BizSys.BizSystem.GetBizObject(lProcURL));
Result := TProcActivity(lProc.GetUnit(ATask.ProcUnitID)).FuncURL.URL;
finally
lProcURL.Free;
end;
end;
function TFLOWSTKOUTCTRLFORM.CreateFunc(const AContext: TContext; const ATask: TTask): TFunc;
var
lFuncURL: string;
lBizObject: TBizObject;
lBizClassURL: TBizClassURL;
begin
lBizClassURL := TBizClassURL.Create;
Try
lFuncURL := GetFuncURL(ATask);
lBizClassURL.BizURL.URL := lFuncURL;
lBizObject := BizSys.BizService.CreateBizObject(lBizClassURL, Context);
try
Result := lBizObject as TFunc;
except
lBizObject.Free;
raise;
end;
finally
lBizClassURl.Free;
end;
end;
{procedure TFlowStkoutCtrlForm.ChangeTaskMsg(const AOrgURL: TOrgURL; ATask: TTask);
var
I: Integer;
lTaskMsg: TTaskMessage;
lNewMsg: TTaskMessage;
begin
{for I := 0 to ATask.TaskMessages.Count - 1 do
begin
lTaskMsg := ATask.TaskMessages.Items[I];
if lTaskMsg.State in Flow.SProcessingTaskMessageStates then
lTaskMsg.State := TTaskMessageState.tmsCanceled;
end;
ATask.TaskMessages.AddTaskMessage(nil, AOrgURL, TTaskMessageState.tmsSend);
Task.TaskManager.SaveTask(ATask);
end;}
procedure TFLOWSTKOUTCTRLFORM.actAddExecutorExecute(Sender: TObject);
var
lController: TControllerItem;
lDialog: TSelSubordinationDlg;
Save_Cursor: TCursor;
lBizNode: TBizNode;
lOrgURL: TOrgURL;
lTask: TTask;
lFlow: TFlow;
lExecuteMode: TTaskExecuteMode;
lSequence: Integer;
begin
lController := GetSelectedController;
if lController = nil then
Exit;
lDialog := TSelSubordinationDlg.Create(nil);
try
lDialog.Caption := '添加执行者';
lDialog.PromptText :=
'要添加执行者,请先从下面的组织模型树中选择要添加的组织单元,然后点击“确定”按钮即可。';
lDialog.BizTreeView.ShowOptions := [TBizObjectKind.boOrgServer, TBizObjectKind.boFolder,
TBizObjectKind.boOrgRoot, TBizObjectKind.boOrgan, TBizObjectKind.boDept,
TBizObjectKind.boPositionMember, TBizObjectKind.boPersonMember,
TBizObjectKind.boPositionRoot, TBizObjectKind.boPosition];
lDialog.BizTreeView.SmartOptions := [TBizObjectKind.boFolder];
lDialog.MustSelectedNode := [TBizObjectKind.boDept,
TBizObjectKind.boPositionMember, TBizObjectKind.boPersonMember,
TBizObjectKind.boPosition];
lDialog.MultiSelect := False;
lDialog.Init;
if lDialog.ShowModal = Business.Forms.Controls.mrOK then
begin
Save_Cursor := Forms.Screen.Cursor;
Forms.Screen.Cursor := Business.Forms.Controls.crHourGlass;
try
lBizNode := BizTree.BizTreeStructure.FindNodeByFullFileName(lDialog.Files[0]);
if lBizNode <> nil then
begin
lOrgURL := TOrgURL.Create(lBizNode.BizURL);
lFlow := GetSelectedFlow;
lTask := lFlow.Tasks.FindTaskByGUID(lController.Task.GUID);
lSequence := 0;
lExecuteMode := lTask.ExecuteMode;
case lExecuteMode of
TTaskExecuteMode.emSequential:
begin
lSequence := GetNewTaskMsgSequence(lTask);
lTask.TaskMessages.AddTaskMessage(nil, lOrgURL, TTaskMessageState.tmsWaiting,
lSequence, False);
end;
else
lTask.TaskMessages.AddTaskMessage(nil, lOrgURL, TTaskMessageState.tmsSend,
lSequence, False);
end;
Task.TaskManager.SaveTask(lTask);
ReLoadFlowController(lFlow.GUID);
RefreshControllerGrid;
end;
finally
Forms.Screen.Cursor := Save_Cursor;
end;
end;
finally
lDialog.Free;
end;
end;
procedure TFLOWSTKOUTCTRLFORM.actAddExecutorUpdate(Sender: TObject);
var
lTask: TTask;
begin
lTask := GetCurrentSelTask;
actAddExecutor.Enabled := (lTask <> nil) and
(lTask.State in Task.SProcessingTaskStates);
end;
procedure TFLOWSTKOUTCTRLFORM.actCancelExecutorExecute(Sender: TObject);
var
lController: TControllerItem;
lTask: TTask;
lTaskMsg: TTaskMessage;
lFlow: TFlow;
lDeptName, lPositionName, lPersonName: string;
begin
lController := GetSelectedController;
if lController = nil then
Exit;
lFlow := GetSelectedFlow;
lTask := lFlow.Tasks.FindTaskByGUID(lController.Task.GUID);
lTaskMsg := lTask.TaskMessages.GetTaskMessage(lController.TaskMessage.GUID);
lDeptName := '';
lPositionName := '';
lPersonName := '';
GetReceiverName(lTaskMsg, lDeptName, lPositionName, lPersonName);
if JSDialogs.ConfirmBox(SysUtils.Format(msg_CancelExecutor,
[lDeptName, lPositionName, lPersonName]), '', 2) then
begin
lTaskMsg.State := TTaskMessageState.tmsCanceled;
Task.TaskManager.SaveTask(lTask);
ReLoadFlowController(lFlow.GUID);
RefreshControllerGrid;
end;
end;
procedure TFLOWSTKOUTCTRLFORM.actCancelExecutorUpdate(Sender: TObject);
var
lTask: TTask;
lTaskMsg: TTaskMessage;
begin
lTask := GetCurrentSelTask;
lTaskmsg := GetCurrentSelTaskMessage;
actCancelExecutor.Enabled := ((lTaskMsg <> nil) and
(lTaskMsg.State in csCanModifyControllerStates)) and
((lTask <> nil) and HasActiveTaskMsg(lTask));
end;
function TFLOWSTKOUTCTRLFORM.HasActiveTaskMsg(const ATask: TTask): Boolean;
var
I: Integer;
lTaskMsg: TTaskMessage;
lActiveCount: Integer;
begin
Result := False;
lActiveCount := 0;
for I := 0 to ATask.TaskMessages.Count - 1 do
begin
lTaskMsg := ATask.TaskMessages.Items[I];
if (lTaskMsg.Parent = nil) and (lTaskMsg.State in Task.SActiveTaskMessageStates) then
begin
lActiveCount := lActiveCount + 1;
if lActiveCount >= 2 then
begin
Result := True;
Exit;
end;
end;
end;
end;
function TFLOWSTKOUTCTRLFORM.GetNewTaskMsgSequence(const ATask: TTask): Integer;
var
I: Integer;
lSequence: Integer;
lTaskMsg: TTaskMessage;
begin
lSequence := 0;
for I := 0 to ATask.TaskMessages.Count - 1 do
begin
lTaskMsg := ATask.TaskMessages.Items[I];
if (lTaskMsg.Parent = nil) and (lTaskMsg.Sequence > lSequence) then
lSequence := lTaskMsg.Sequence;
end;
Result := lSequence + 1;
end;
end. |