외부 작업폼을 연계하기 위해서 기본적으로 제공해주는 방법으로 VPM상에서 "URL 연결설정" 을 이용하는 방법이 있다.
이는 단순히 Realflow 기본작업폼을 외부의 작업폼으로 대체해 주는 역할만 하기 때문에, 외부 작업폼과 리얼플로우간의 실질적인 데이터의 흐름은 직접 제어해 주어야 한다.
향후 외부 작업폼과 리얼플로우와의 연계가 더욱 많아지리라 예상되므로, 이에 표준적인 방안으로 제시를 하고자 한다.
1. 기본 전제.
외부 작업폼에서 처리되는 데이터는 대부분 웍플로우와는 관계가 없을것이다.
외부작업폼을 생성해주고 실제 작업을 수행하는 주체는 웹어플리케이션(asp, aspx, jsp…)로 웹기반에서 모든 작업이 이루어지고, 데이터의 연계도 웹을 통해 이루어진다고 하자.
작업폼을 구성하기 위해서 DB에서 데이터를 끌어와야 하는데 이때 기준이 되는 키값은 작업폼을 구성을 요청할 때 함께 넘겨줘야 할것이다.
각각의 작업폼 단위에서는 메인이 되는 키값을 가지고 모든작업을 수행할 것이며, 서로 독립적으로 작동할 것이다. 따라서 필요한 값들은 Realflow에서 넘겨줘야 한다.
작업폼위에서 입력된 내용들은 대부분 ERP-DB에 입력되고 실제 프로세스를 컨트롤하기 위한 데이터와 다음 작업폼 구성을 위한 키값등이 출력아이템에 담기면 된다.
2. 연계를 위한 시스템 구성도.
다음은 Realflow 시스템과 외부작업폼, 사용자간의 연계관계를 나타낸 것이다.
S
위의 그림은 하나의 휴먼태스크가 실행되어서 완료되는 하나의 싸이클을 나타낸다.
실제로 Realflow시스템에서는 사용자 입력을 처리하기 위해서 위의 과정을 거치게 되는데, Realflow내의 기본 작업폼을 처리하는 부분을 외부 작업폼처리로 대체한 것이다.
① 태스크 실행
A. 태스크가 실행되면서 담당자 셋팅과 함께 내부작업폼을 위한 데이터를 준비한다.
B. 작업시작을 알리는 메일을 보낸다.
② 작업시작 통보
A. 담당자는 메일을 통해 작업을 시작을 통보받는다.
③ 작업화면 요청
A. 나의 할일 목록에서 해당 작업을 선택한다. 이때 서버쪽에 작업화면을 요청하게 된다.
④ 작업화면 메뉴구성
A. 작업화면의 일반적인 형태는 좌측에 작업처리에 도움이 되는 메뉴가 있고, 오른쪽에 실제 작업폼이 배치된다.
B. 여기서는 좌측의 메뉴를 구성하고 실제 작업폼은 외부작업화면을 끼워넣는다. ⑤~⑧의 작업은 작업을 흐름자체를 외부작업폼에 넘겨버린 것이기 때문에, 외부작업폼 생성을 위해서 필요한 매개변수와 다음 흐름(⑨~)을 진행하기 위해 필요한 데이터(주로 ProjectID, ProcessID, TaskID, LoopID, DupID)을 함께 넘겨준다.
⑤ 외부작업화면
A. 여기서부터 제어권은 외부작업폼이 갖게 된다. 즉, ⑨태스크완료 을 요청하기 전에는 프로세스는 진행이 중단된다는 의미가 된다. 따라서 임시저장등의 기능도 외부작업폼에서 자체적으로 일어나게 된다.
B. Realflow로부터 넘겨받은 데이터를 가지고 작업폼을 구성한다. 보통 넘겨받은 데이터는 DB로부터 자료를 가지고 오기위한 키값이 될것이다.
C. 이렇게 만들어진 작업화면에 사용자가 입력하고 작업완료버튼을 누르면 ⑦이 호출되어 사용자 입력데이터를 처리할 것이다.
⑥ 사용자 입력
A. 사용자는 ③에서 요청한 화면을 보게 되며, 해당 작업을 위한 입력을 할것이다.
⑦ 단위작업처리
A. 사용자가 입력한 데이터를 실제 DB에 저장하거나 이런저런 비즈니스 로직에 따라 작업을 처리한다.
B. 만약 현재 작업을 완료하기 위한 요청이 들어왔다면 ⑧을 요청한다. 물론 ⑤에서 넘겨받은 데이터(각종 ID 들)와 함께, 다음 진행을 위한 데이터도 함께 넘겨준다. 예를 들자면 현재 태스크에서 피드백을 해야 된다면 프로세스와 사전에 약속된 값, 현재 작업에서 생성된 데이터를 다음 작업폼에서 사용해야 한다면 그 키에 해당하는 값등을 사전에 약속된 매개변수에 실어서 함께 넘겨준다.
⑧ 작업완료요청
A. 넘겨받은 값들을 현재 태스크의 출력아이템에 저장하고, 현재태스크의 완료를 요청한다.
⑨ 태스크 완료
A. 현재 태스크를 완료한다.
⑩ 다음 태스크 실행
A. 다음 태스크를 실행한다. ①의 단계로부터 다시 시작하게 된다.
그림에서 보듯이 실제로 해당태스크의 작업은 외부작업폼에 전적으로 위임하게 되며, Realflow에서는 단순히 프로세스의 흐름만 제어하는 방식이다.
따라서 Realflow에서 외부작업폼으로 제어를 넘기는 부분(A), 외부작업폼으로부터 제어를 받아오는 부분(B)에 대한 약속만 지켜주면 상호간에 이상없이 동작할 것이다.
3. 실제 구현 모델.
일단 http://x.x.x.x/realflow/custom 를 외부작업폼 연계를 위한 기본 폴더로 지정하자.
외부작업폼을 사용하지 않고 원래의 작업폼을 사용할경우
…/realflow/workboard/RfTaskRun.asp
가 작업화면구성을 처리해 주는데 (내부적으로는 xml + xsl = html 의 형식으로 실제 html을 만든다) 외부 작업폼에 대한 일괄적인 처리를 위해서 이 asp 을 대체하여 새로운 asp 을 만들어 사용한다.
새로운 asp 는 externalTaskRun.asp 라는 이름으로 만들었으며 …/realflow/custom/ 안에 들어가게 된다.
기능적으로는 rfTaskRun과 유사하나 외부작업폼을 연결해주는 부분이 추가된다.
일단 외부작업폼을 사용하는 태스크의 경우 커스텀URL 을 적용하여 externalTaskRun.asp을 호출하도록 한다.
VPM에서 태스크의 등록정보에서 제일아래쪽 URL연결 항목을 적어주면 된다.
이부분에 “../custom/externalTaskRun.asp” 이라 적어주면 실제 작업폼을 생성할 때 이쪽으로 redirect (Response.Redirect “../custom/externalTaskRun.asp”) 될것이다.
외부작업폼을 사용하는 태스크들에 대한 URL연결 작업이 끝났으면, 프로세스내의 데이터를 외부작업폼에 넘겨주기 위한 작업을 해보자.
그림을 보면 첫번째 태스크인 “접수 및 검수” 에서 Result, MainKey라는 출력아이템을 갖고 있는 것을 알수 있다.
태스크가 작업을 마치면 출력으로 내보내 줘야하는 값인데, 우리는 현재 외부작업폼을 사용하고 있고, 따라서 외부작업폼으로부터 해당 데이터를 얻어와야 할것이다.
이때 외부작업폼에 값을 넘겨주거나 받아올 아이템을 정해주기 위해서 Hidden 으로 올려놓으면 다른 작업이 편리하게 된다.
일단은 외부작업폼에 값을 넘겨주거나 받아올경우 Realflow내에서는 Hidden으로 작업폼을 만들어주면 된다고 알고 넘어가자.
이제 externalTaskRun.asp 을 살펴보자.
<!—externalTaskRun.asp -->
<%@ language="vbscript" %>
<% option explicit %>
<% Response.Buffer = true %>
<% Response.Expires = -1 %>
<!--#include file="../globals/RfConsts.asp"-->
<!--#include file="../globals/lib/RfAdoUtils.asp"-->
<!--#include file="../globals/lib/RfComFuncs.asp"-->
<!--#include file="../globals/lib/RfComObject.asp"-->
<!--#include file="../globals/lib/RfUserInfo.asp" -->
<!--#include file="../globals/lib/RfBase64Code.asp" -->
<!--#include file="../globals/lib/rfCustomTaskFormFunctions.asp" -->
<%
'Custom Page 를 위해서 Include 함
' XSL에 파라미트를 사용하기 위해
%>
<!--#include file="../globals/lib/rfXmlUtils.asp" -->
<!--#include file="../globals/lib/rfXslUtils.asp" -->
<!--#include file="../KM/rfKMConsts.asp" -->
<!--#include file="../KM/rfKMFuncs.asp" -->
<%
Dim nPID, nPCID, nTID, nLID, nDID, nTIDMD, sUID, sEncUID
sUID = CStr(Request("UID"))
nPID = CLng(Request("PID"))
nPCID = CLng(Request("PCID"))
nTID = CLng(Request("TID"))
nLID = CLng(Request("LID"))
nDID = CLng(Request("DID"))
%>
<!--#include file="../workboard/RfTaskTop.asp" -->
<%
'-----------------------------------------------------------
' 일단 WorkMan 으로 부터 DataXml 얻어온후 호출될 asp 의 매개변수를 만들어준다.
' 매개변수를 만들어주는 규칙은 입력아이템의 캡션과 값을 매치시키는 방식으로 한다.
' 예를 들어 입력아이템의 캡션이 "MainKey" 이고, 그 값이 "A0001" 이라면
' MainKey=A0001
' 과 같은 매개변수 문자열을 만들어준다.
'-----------------------------------------------------------
dim oRfWorkMan, oTaskDataDoc, oNodes, oNode, oCaption, oValue, sParams
Set oRfWorkMan = Server.CreateObject("RF_WORKMAN.RfWorkManager")
Set oTaskDataDoc = oRfWorkMan.GetTaskDataDoc(sUID, nPID, nPCID, nTID, nLID, nDID, false, false)
if Request("xml") <> "" then
Response.Clear
Response.ContentType = "text/xml"
oTaskDataDoc.Save Response
Response.End
end if
sParams = ""
set oNodes = oTaskDataDoc.documentElement.selectNodes("//components/component[@flag=1]")
set oNode = oNodes.nextNode
While not (oNode is Nothing)
set oCaption = oNode.selectSingleNode("@node_caption")
set oValue = oNode.selectSingleNode("values")
sParams = sParams & "&" & oCaption.nodeTypedValue & "=" & oValue.text
set oNode = oNodes.nextNode
Wend
set oNode = oTaskDataDoc.documentElement.selectSingleNode("//rftask/task/@name")
if not(oNode is Nothing) then
'------------------------------------------------------------------------------------
' 외부 작업화면을 만들어서 HTML 을 끼워넣는다.
' 여기서 만들어지는 HTML 은 FORM 태그로 쌓여있어야 한다.
'------------------------------------------------------------------------------------
dim sCustomUrl, sTaskName
sCustomUrl = "http://" & Request.ServerVariables("SERVER_NAME") & "/realflow/custom/"
sTaskName = oNode.nodeTypedValue
if sTaskName = "task1" then
sCustomUrl = sCustomUrl & "task1.asp"
elseif sTaskName = "task2" then
sCustomUrl = sCustomUrl & "task2.asp"
elseif sTaskName = "task3" then
sCustomUrl = sCustomUrl & "task3.asp"
else
sCustomUrl = ""
end if
' PID=551&PCID=757&TID=5254&LID=0&DID=0&UID=rfDebugger
if sCustomUrl = "" then
Response.Write sTaskName & " 은 알수없는 TaskName 입니다."
else
dim sURL
sURL = sCustomUrl & "?" & Request.Servervariables("QUERY_STRING") & sParams
'Response.Write RfXMLHttpGetXml(sURL)
Response.Redirect sURL
end if
else
Response.Write "MD_TASK_ID 을 찾을수 없습니다."
end if
%>
<script language="vbscript">
<!-- 대기화면 없애주기 -->
Document.All.ProcessingDiv.style.Display = "None"
</script>
<!--#include file="../workboard/RfTaskBtm.asp"-->
일단 이 asp에는 매개변수로서 PID, PCID, TID, LID, DID, UID 가 넘어오게 된다.
PID=ProjectID
PCID=ProcessID
TID=TaskID
LID=LoopID
DID=DupID
UID=UserID
라는 의미를 가지고 있다.
이 모듈에서는 해당태스크의 외부작업폼을 호출하는 일과 외부작업폼에 필요한 매개변수를 만들어 주는 일을 담당하고 있다.
일단, 매개변수로 들어온 값들을 정리해준다음
Set oTaskDataDoc = oRfWorkMan.GetTaskDataDoc(sUID, nPID, nPCID, nTID, nLID, nDID, false, false)
rfWordMan으로부터 작업폼을 위한 XML 을 넘겨받는다.
실제로는 MsXML DomDocument 객체를 넘겨받는다.
이 xml 에는 VPM에서 작성한 작업폼의 정보와 작업폼위에 있는 아이템들의 정보가 들어있다.
따라서 이 xml 에서 필요로 하는 데이터(아이템의 정보)을 꺼내서 외부작업폼을 위한 파라미터를 만들어 주게 된다.
여기서 약속을 하나 해야 하는데 매개변수의 이름은 아이템의 Caption을 따라가도록 하자는 것이다.
더욱 범용적인 처리가 가능해 지므로, 외부작업폼이 몇 개가 되던 하나의 모듈로 일관성있는 처리가 가능해진다.
이모듈에서는 외부작업폼을 구성하기 위한 데이터를 넘겨줘야 하므로
set oNodes = oTaskDataDoc.documentElement.selectNodes("//components/component[@flag=1]")
와 같이 flag=1 (입력용 아이템)만을 찾아서 매개변수를 구성해 준다.
외부작업폼을 위한 파라미터에 변경이 있다면 VPM에서 입/출력 아이템의 Caption을 파라미터의 이름과 같게 맞춰주고, 폼빌더에서 해당아이템을 Hidden으로 올려놓으면 될것이다.
이렇게 만들어진 파라미터는 외부 작업폼을 위한 매개변수로서 사용되지만, 빠진게 있다.
제어권이 외부작업폼으로 넘어가므로, 제어권이 되돌아올때 어떤 태스크를 완료시켜야 되는지를 알려줘야만 한다.
따라서 ProjectID, ProcessID, TaskID, LoopID, DupID 가 함께 넘어가야 할것이다.
이렇게 파라미터의 구성이 왼료되었다면, 실제로 외부작업폼을 만들어줄 url 을 알아야 한다.
현재 적당한 방법을 찾지 못해서 태스크의 Name 을 보고 이에 해당하는 asp 을 찾아서 맵핑하는 방식을 취하였다.
(향후 적당한 방법을 찾게 되면 문서를 수정해서 다시 올릴 예정임)
if sTaskName = "task1" then
sCustomUrl = sCustomUrl & "task1.asp"
elseif sTaskName = "task2" then
sCustomUrl = sCustomUrl & "task2.asp"
elseif sTaskName = "task3" then
sCustomUrl = sCustomUrl & "task3.asp"
else
sCustomUrl = ""
end if
와 같은 방식으로 각각의 태스크마다 해당하는 asp 을 연결시켜주는 방식이다.
이방식은 하나의 프로세스만을 대상으로 할경우 문제될게 없으나 여러 개의 프로세스일 경우 태스크의 이름만 가지고는 구분하기가 힘들다는 문제점을 안고 있다.
이렇게 정보를 가지고 실제로 호출하는 방식을 알아보자.
dim sURL
sURL = sCustomUrl & "?" & Request.Servervariables("QUERY_STRING") & sParams
'Response.Write RfXMLHttpGetXml(sURL) ‘ --- ①
Response.Redirect sURL ‘ --- ②
해당 URL을 호출해서 그결과로 반환된 html 을 그대로 써주는 방식이 ①이고,
아예 해당주소로 Redirect 시키는 방식으로 ②를 사용한다.
②의 경우 호출된 주소(외부작업폼을 만드는) 에서 모든 작업폼을 만들어서 처리하게 되므로 작업이 단순해 지는 장점이 있으나, Realflow에 해당하는 메뉴등의 구성을 직접 만들어줘야 하는 단점이 생긴다.
①의 경우 단순히 현재까지 짜여진 골격안에 외부작업폼으로 만든 html 을 body로서 포함시키는 방식이므로 Realflow에서 제공해주는 작업폼 형식과 유사한 모양으로 만들어지나, 해당 작업폼에서 submit 등의 작업을 처리할 때 좀더 신경을 써줘야 하는 부담이 생긴다.
각각의 상황에 따라 맞는 방식을 취하면 될것이다.
단 ②의 방식을 사용할때는 Realflow에서 골격을 만들어주는 작업이 무시되므로
<!--#include file="../workboard/RfTaskTop.asp" -->
…..
<!--#include file="../workboard/RfTaskBtm.asp"-->
위의 두 행을 삭제해 주어야 할것이다.
실제로 외부작업폼으로 만들어질 예제를 살펴보자.
<!—Task1.asp -->
<%@ language="vbscript" %>
<% option explicit %>
%>
<FORM name="RfTaskForm" action="task1Submit.asp" method="POST">
<!-- 필수 입력 내용 시작. -->
<input TYPE="HIDDEN" NAME="PID" VALUE="<%=Request("PID")%>" />
<input TYPE="HIDDEN" NAME="PCID" VALUE="<%= Request("PCID")%>" />
<input TYPE="HIDDEN" NAME="TID" VALUE="<%= Request("TID")%>" />
<input TYPE="HIDDEN" NAME="LID" VALUE="<%= Request("LID")%>" />
<input TYPE="HIDDEN" NAME="DID" VALUE="<%= Request("DID")%>" />
<input TYPE="HIDDEN" NAME="TMDID" VALUE="0" />
<input TYPE="HIDDEN" NAME="UID" VALUE="<%= Request("UID")%>" />
<!-- 필수 입력 내용 끝 -->
<div>외부 작업폼입니다.</div>
<div><%=Request.Servervariables("QUERY_STRING")%></div>
<input type="TEXT" NAME="EDIT1" VALUE="123"/>
<input TYPE="SUBMIT" VALUE="확인"/>
</FORM>
Realflow와의 연계를 위해서 PID(ProjectID)등을 hidden으로 숨겨두고 있다. 입력작업을 마치고 완료버튼을 누를 때 그 데이터가 함께 task1Submit.asp 로 넘어가게 될것이다.
이상의 작업으로 사용자는 웍리스트에서 원하는 작업을 클릭했을 때 그에 해당하는 작업화면을 보게 될것이다. 물론 VPM에서 폼빌더로 구성한 작업화면이 아닌 외부에서 만들어진 작업화면을 말이다.
여기서 주의할점은 실질적인 작업화면을 만들어 사용자로부터 데이터를 입력받고, 그 값을 처리하는 일련의 과정이 Realflow 외부에서 이루어 진다는 점이다.
다시 말해서 이런 일련의 과정이 완료되면 다시 제어를 Realflow로 넘겨줘야만 프로세스가 제대로 흘러갈수 있다는 얘기가 된다.
이제 외부작업폼의 Submit 처리예제를 살펴보자.
<%@ language="vbscript" %>
<% option explicit %>
<% Response.Buffer = true %>
<% Response.Expires = -1 %>
<!--#include file="../globals/lib/RfComFuncs.asp"-->
<%
‘ 받아온 데이터에 대해 처리를 한다.
Dim nPID, nPCID, nTID, nLID, nDID, sUID, sBody, sUrl, nResult, sMainKey
sUID = CStr(Request("UID"))
nPID = CLng(Request("PID"))
nPCID = CLng(Request("PCID"))
nTID = CLng(Request("TID"))
nLID = CLng(Request("LID"))
nDID = CLng(Request("DID"))
nResult = 1
sMainKey = "A0001"
‘ 현재 작업폼에서 Realflow로 넘겨줘야 하는 데이터로서 Result, MainKey 라는 항목이 있다.
‘ 이에 대한 값을 얻어온다음 Realflow로 넘겨준다.
sBody = "PID=" & nPID & "&PCID=" & nPCID & "&TID=" & nTID & "&LID=" & nLID & "&DID=" & nDID & _
"&UID=" & sUID & "&Result=" & nResult & "&MainKey=" & sMainKey & "&bSubmit=" & bSubmit
sUrl = "http://" & Request.ServerVariables("SERVER_NAME") & "/realflow/custom/externalSubmit.asp?"
‘ 제어를 Realflow로 넘겨주기 위해
Response.Redirect sUrl & sBody
%>
위의 예제에서는 작업폼에서 넘어온 데이터에 데한 처리가 빠져있다. 외부작업폼에서 사용자가 입력한 데이터에 대한 처리를 의미한다.
이 예제는 프로세스의 첫번째 태스크로서 출장신청서 작성등을 작성한다고 생각하면 된다.
출장신청서를 작성하면 ERP-DB에 출장신청서가 한건 insert 될것이고, 그 키값을 다음 태스크로 넘겨줘야 할것이다. 다음태스크에서는 이 키값을 가지고 해당하는 내용을 조회하고 수정하는 식으로 흘러갈것이기 때문에…
이 예제에서의 MainKey 라는 매개변수가 그 값을 의미한다. 여기서는 그 값으로 “A0001”로 고정을 했다. 물론 실전에서는 실제 데이터가 들어가게 될것이다.
이 예제에서는 Realflow로 넘겨야할 데이터로 Result, MainKey 가 있는데, 그 값을 얻은다음 .../realflow/custom/externalSubmit.asp 에 실어서 보낸다. 물론 기본 ID들도 함께…
이로서 제어는 Realflow로 돌아가게 된다.
다음은 이렇게 들어온 데이터를 가지고 태스크에 완료요청을 보내, 다음태스크를 진행하도록 하는 방식에 대해서 알아보도록 하자.
<% externalSubmit.asp %>
<%@ language="vbscript" %>
<% option explicit %>
<% Response.Buffer = true %>
<% Response.Expires = -1 %>
<%
'---------------------------------------------------------
' 제목 : 외부 작업화면 호출 SCRIPT
'
' 제작 : 여덕수 (fieldman@realweb21.com)
'---------------------------------------------------------
Dim nPID, nPCID, nTID, nLID, nDID, sUID, sEncUID, sFormData
sUID = CStr(Request("UID"))
nPID = CLng(Request("PID"))
nPCID = CLng(Request("PCID"))
nTID = CLng(Request("TID"))
nLID = CLng(Request("LID"))
nDID = CLng(Request("DID"))
' Response.write "externalSubmit.asp" & "?" & Request.Servervariables("QUERY_STRING")
' …/externalSubmti.asp?PID=123&PCID=234&TID=345&LID=0&DID=0&Result=1&MainKey=A0001
'=============================================================
' 넘겨받은 매개변수의 값을 태스크에 Submit 해준다.
' 넘겨받은 매개변수의 이름은 출력아이템의 캡션과 같다.
' 따라서 출력아이템의 캡션에 해당하는 매개변수가 있는지 확인하고
' 그 값을 가져온후 워크맨에 넘길 xml 을 만들어준다.
' xml 의 형식은 다음과 같다. 하나의 아이템이 여러개의 값을 가질경우 ORDER_NO 를 증가시키면서 구분을 한다.
'<ITEMS><ITEM ITEM_ID="RFITEM12321" ORDER_NO="1">ITEM 값</ITEM></ITEMS>
'=============================================================
dim oRfWorkMan, oTaskDataDoc, oNodes, oNode, sCaption, sValue, sName, nReturn
Set oRfWorkMan = Server.CreateObject("RF_WORKMAN.RfWorkManager")
Set oTaskDataDoc = oRfWorkMan.GetTaskDataDoc(sUID, nPID, nPCID, nTID, nLID, nDID, false, false)
' Root 태그를 시작한다.
sFormData = "<ITEMS>"
' 작업폼 데이터중 출력으로 연결된 아이템만 골라서 그 값을 현재 Request에 들어온 값과 연결시켜준다.
' 연결하는 키는 아이템의 캡션으로 작업폼의 출력아이템의 캡션이 Request에 들어온 매개변수에 존재하면 그 값을 가져다 사용한다.
set oNodes = oTaskDataDoc.documentElement.selectNodes("//components/component[@flag=2]")
set oNode = oNodes.nextNode
While not (oNode is Nothing)
sCaption = oNode.selectSingleNode("@node_caption").nodeTypedValue
sName = oNode.selectSingleNode("@name").nodeTypedValue
sValue = CStr(Request(sCaption))
sFormData = sFormData & "<ITEM ITEM_ID='" & sName & "'>" & sValue & "</ITEM>"
set oNode = oNodes.nextNode
Wend
' Root 태그를 닫아준다.
sFormData = sFormData & "</ITEMS>"
nReturn = oRfWorkMan.SubmitTask(nPID, nPCID, nTID, nLID, nDID, sFormData)
Set oRfWorkMan = Nothing
%>
이 모듈은 외부에서 태스크를 완료시키는 asp 로서 외부작업폼에서 호출하도록 작성되었으나 정해진 규격대로만 호출한다면 어디서나 사용가능할 것이다.
정해진 규칙이란 다음과 같다.
…/externalSubmti.asp?PID=123&PCID=234&TID=345&LID=0&DID=0&Result=1&MainKey=A0001
기본키로서 PID, PCID, TID, LID, DID 을 넘겨주며, 출력아이템에 넣을 값으로서 Result, MainKey 을 넘겨주는 것을 볼수 있다.
이런식으로 호출한다면 어디서나 태스크를 완료시키는 용도로 사용이 가능할것이다.
단 Result, MainKey 라는 매개변수의 처리를 위해서 해당태스크의 출력아이템으로 Result, MainKey 라는 캡션을 갖는 아이템이 있어야 하며, 그 아이템이 작업폼위에 Hidden 등으로 올라가 있어야 한다.
위의 모듈에서는 이 두개의 매개변수만이 아닌 어떤 매개변수라도 지정된 방식데로 처리될수 있으므로, 다른 용도로 사용되더라도 유용하게 사용될수 있을것이다.
이렇게 넘어온 매개변수중 기본키는 해당태스크를 찾아오는데 사용되고, 나머지 매개변수들은 해당태스크의 출력아이템에 값을 넣는데 사용된다.
소스를 보면 알수 있듯이, 해당태스크의 작업폼위에 올라간 아이템에 대해서만 처리를 하므로, 외부에서 값을 넣어줘야 하는 아이템은 반드시 작업폼위에 올려놔야 할것이다. 꼭 Hidden으로 놔야하는 것은 아니지만, 이전부터 이런종류의 작업을 위해 Hidden을 사용해 왔으므로 Hidden으로 놓는 것을 권장한다.
해당태스크의 작업폼에 올라간 출력아이템과 Request에 들어간 매개변수를 연결하는 키는 출력아이템의 Caption이 된다. 따라서 Request에 들어올 매개변수의 이름과 해당아이템의 Caption을 똑같이 써줘야 할것이다.
소스를 보면 작업폼 xml중에서 출력아이템만 골라서 순환문을 돌며, 그 캡션에 해당하는 Request의 매개변수값을 취하는 것을 볼수 있다.
이 값들은 정해진 포멧의 xml 로 만들어져서, 태스크의 완료를 요청하는 COM+ 메소드를 호출하게 된다.
이후의 작업은 Realflow 기본 작업폼에서 Submit했을때와 같은 절차로 실행되며, 현재 태스크는 Post-Condition 검사후 완료되며 다음태스크가 실행되게 된다.
4. 앞으로 처리해야 할일.
어떤 프로세스던 소화가 가능하도록 설계되었으면 좋으련만, 현재 그렇지 못하다.
이유는 이를 위한 준비가 약간 덜 되어 있기 때문으로, 향후 소화가 가능하리라 본다.
앞서 소개된 구현모델에서는 externalTaskRun 에서 태스크의 이름을 비교해서 실제 작업폼을 호출하는 방식인데, 이는 새로운 프로세스를 적용할때마다 asp 소스를 수정해서 사용해야 하는 불편함이 있다.
현재 구현된 방식은 태스크의 커스텀URL 기능을 이용할 때, 외부 작업폼의 경우 모두externalTaskRun.asp 로 설정해서 이 모듈 안에서 분기를 하도록 되어 있다.
따라서 이 모듈안에서는 각각의 태스크에 맞는 커스텀 페이지의 URL을 내부적으로 다시 설정해야 하는 방식이므로, 모듈소스의 수정이 불가피하게 된다.
이를 피하기 위해서는 WorkBoard의 기본 설정에서 태스크 폼을 보는 URL을 externalTaskRun으로 수정을 하고, 태스크의 커스텀URL을 실제 외부작업폼의 URL로 바꿔주면 된다.
이 경우 externalTaskRun 모듈에서는 커스텀URL설정이 되어 있을경우와 그렇지 않은 경우로 나누어 작업을 하면 될것이다.
만약 설정된 커스텀URL이 없다면 내부작업폼을 처리하듯이 처리하는 루틴을 타게 될것이고, 설정된 URL이 있다면 내부작업폼에서 매개변수를 뽑아내서 설정된 URL을 호출하는 방식으로 변경될 것이다.
물론 WorkBoard의 기본설정 (…/realflow/wordboard/rfWkBoardX.asp)을 수정해야 가능하게 된다.
이를 위해서는 rfWkBoardX.asp 의 수정본이 …/realflow/custom 폴더에 위치하게 되며, 해당 작업을 위한 URL을, 수정된 …/realflow/custom/rfWkBoardX.asp 로 연결되어야 할것이다.
물론 기본작업폼을 사용하는 경우라면 …/realflow/wordboard/rfWkBoardX.asp 을 직접 호출할것이다.
이렇게 수정된 rfWkBoardX.asp 을 사용하게 되면 externalTaskRun.asp 에서는 태스크의 커스텀 URL을 외부작업폼으로 설정할수 있기 때문에, 보다 범용적인 처리가 가능하며, 유연하게 외부 작업폼과의 연계가 이루어 질것이다.
5. 정리.
지금까지 설명한 방식을 정리하자면 다음과 같다.
a. 외부 작업폼의 연결을 위해서 중간에 externalTaskRun.asp 라는 모듈을 둔다.
b. 외부 작업폼에서 태스크의 완료를 요청하기 위해서 externalSubmit.asp 라는 모듈을 둔다.
c. 외부 작업폼과 Realflow간의 데이터의 연계는 내부작업폼에 올려놓은 Hidden아이템으로 처리하며, 아이템의 Caption을 외부작업폼 호출시 매개변수의 이름으로 삼는다.
d. 현재 완벽하게 정리된 방식이 아니므로 약간의 수정이 필요로 하며, externalTaskRun.asp 의 개념상의 위치 수정이 필요하다. (웍보드에서 작업폼을 위해서 바로 호출하는 방식으로, 현재는 rfTaskRun.asp 을 통해서 간접적으로 호출됨)