Comments
Description
Transcript
101NEO ワークフロー・チュートリアル
株式会社ワン・オー・ワン チュートリアル・ワークフロー Version 1.5 Note: コピー並びに配布厳禁 内容は予告なく変更される場合があります Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow 目次 はじめに ......................................................................................................................................................... 1 1. 設計........................................................................................................................................................... 2 1-1. 1-2. 1-3. 1-4. 概要............................................................................................................................................. 2 画面設計................................................................................................................................... 2 入出力項目の抽出................................................................................................................ 5 データベース設計.................................................................................................................. 5 2. アプリケーションの作成..................................................................................................................... 8 2-1. プロジェクトの作成 ................................................................................................................ 8 2-2. ログイン画面............................................................................................................................ 9 2-3. メイン画面...............................................................................................................................11 2-4. メニュー画面 ..........................................................................................................................11 2-5. 申請リストの一覧画面 .......................................................................................................12 2-6. 承認/否認対象リストの一覧画面...............................................................................14 2-7. 新しい申請書の作成画面 ................................................................................................16 2-8. 申請データの詳細画面 .....................................................................................................23 2-9. 承認/否認履歴画面.........................................................................................................29 2-10. 完了画面..............................................................................................................................30 2-11. エラー画面 ..........................................................................................................................31 2-12. 共通プログラム..................................................................................................................31 3. 動作確認 ...............................................................................................................................................36 3-1. 3-2. 3-3. 3-4. 3-5. 3-6. ログイン ...................................................................................................................................36 新しい申請書の作成 ..........................................................................................................36 承認処理.................................................................................................................................37 申請データの取消/再登録............................................................................................38 承認/否認履歴の確認....................................................................................................38 ログアウトの実行.................................................................................................................39 付録 A. SQL................................................................................................................................................40 ワークフロー関連の SQL 文 ........................................................................................................40 申請データ関連の SQL 文 ...........................................................................................................40 マスター関連の SQL 文.................................................................................................................41 付録 B. コマンドリスト.............................................................................................................................43 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow はじめに このチュートリアルでは、101NEOの組み込み機能であるワークフローエンジンを使用した申 請業務アプリケーションを作成します。 前提条件として、チュートリアル第1部および第2部を実施して101NEO Studioの基本的な使 い方、機能等について理解された方を対象としております。 本チュートリアルを実施する前に、マニュアルの第8章「ワークフローエンジン」をお読みいた だき、ワークフローエンジン機能の全体像を把握してください。また、巻末にコマンドリストを つけましたので、そちらも参照してください。 システム要件 このチュートリアルをすべて確認するためには、次のシステムおよび設定が必要です。 • JDBC対応データベース(説明ではOracleを使用) • 使用するデータベースにあわせた101NEO Studioのクラスパス設定 • メールサーバー • Java Mail(mail.jar)とJAF(activation.jar)およびクラスパス設定 • WebブラウザでCookieをブロックしない設定(セッション管理で使用) Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 1 1. 設計 1-1. 概要 このチュートリアルでは、簡単な申請業務アプリケーションとして経費精算システムを作成し ます。ユーザーによって申請された経費データに対して、承認者(経理と社長)が承認(もし くは否認)をします。 起票者 承認者 申請ボタンを押すと、 承認依頼が承認者 に送信される 承認者 承認ボタンを押すと、 承認依頼が次の承 認者に送信される 承 認 最後の承認者が 承認ボタンを押 せば、承認完了 承 認 データベース また、ユーザー認証のためのログイン処理、申請ステータスの確認画面、申請者や承認者 へのメール通知機能なども実装します。 1-2. 画面設計 1-2-1. 画面の数 次のような画面(合計10画面)を作成します。 ① ログイン画面 ② メイン画面(フレーム分割) ③ メニュー画面 ④ 申請リストの一覧画面 ⑤ 承認/否認対象リストの一覧画面 ⑥ 新しい申請書の作成画面 ⑦ 申請データの詳細画面 ⑧ 承認/否認履歴画面 ⑨ 完了画面 ⑩ エラー画面 ※メイン画面(②)の左フレームにメニュー(③)、右フレームにコンテンツ(④∼⑩)を表示し ます。 1-2-2. ラフな画面デザイン ※白抜き部分は入力フィールドです。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 2 ① ログイン画面 ユーザーID パスワード ログイン ② メイン画面(フレーム分割) メニュー(①) コンテンツ(④∼⑩) ③ メニュー画面 ○○さん、ようこそ。 ■新しい申請書の作成 ■申請リストの一覧 ■承認/否認対象リストの一覧 ログアウト ④ 申請リストの一覧画面 タイトル 登録日 申請開始日 申請期限 ステータス タイトル1 2004-01-01 12:00 2004-01-01 12:00 2004-01-01 12:00 申請中 タイトル2 2004-01-01 12:00 2004-01-01 12:00 2004-01-01 12:00 申請中 タイトル3 2004-01-01 12:00 2004-01-01 12:00 2004-01-01 12:00 申請中 ⑤ 承認/否認対象リストの一覧画面 タイトル 申請者 登録日 申請開始日 申請期限 タイトル1 申請者1 2004-01-01 12:00 2004-01-01 12:00 2004-01-01 12:00 タイトル2 申請者2 2004-01-01 12:00 2004-01-01 12:00 2004-01-01 12:00 タイトル3 申請者3 2004-01-01 12:00 2004-01-01 12:00 2004-01-01 12:00 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 3 ⑥ 新しい申請書の作成画面 タイトル タイトル1 起票日 記票者 社長 2004年01月01日 記票者1 社長 日付 明細 科目 経理 経理1 領収書No 金額 2004年01月01日 明細1 科目1 1 10,000 2004年01月01日 明細2 科目2 2 10,000 2004年01月01日 明細3 科目3 3 10,000 総合計 申請 30,000 仮払金控除 0 差引支払額 30,000 リセット ⑦ 申請データの詳細画面 タイトル タイトル1 起票日 記票者 社長 経理 2004年01月01日 記票者1 社長 経理1 日付 明細 科目 領収書No 金額 2004年01月01日 明細1 科目1 1 10,000 2004年01月01日 明細2 科目2 2 10,000 2004年01月01日 明細3 科目3 3 10,000 総合計 承認 30,000 仮払金控除 0 差引支払額 30,000 否認 ⑧ 承認/否認履歴画面 タイトル タイトル1 日時 承認者 承認/否認区分 2004-01-01 12:00 承認者1 承認 2004-01-01 12:00 承認者2 承認 閉じる ⑨ 完了画面 経費を精算しました。 申請リストの一覧 ⑩ エラー画面 エラーが発生しました! XXXXXXXXXXXXXXXXX Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 4 1-3. 入出力項目の抽出 1-3-1. 画面デザインから入出力項目を抽出 ① ログイン画面 ユーザーIDおよびパスワードを入力します。 ② 申請リストの一覧画面 タイトル、登録日、申請開始日、申請期限、ステータスをデータベースから取得し、一覧 表示します。 ③ 承認/否認リストの一覧画面 タイトル、申請者、登録日、申請開始日、申請期限をデータベースから取得し、一覧表 示します。 ④ 新しい申請書の作成画面 タイトル、経理、経費明細(日付、明細、科目、領収書No、金額)、仮払金控除を入力し ます。 起票日、記票者、社長は自動的に設定されるようにします。 総合計および差引支払額は、経費明細の金額および仮払金控除をもとに自動計算さ れるようにします(JavaScriptを使用)。 ⑤ 申請データの詳細画面 タイトル、起票日、記票者、社長、経理、経費明細(日付、明細、科目、領収書No、金 額)、総合計、仮払金控除、差引支払額をデータベースから取得し、表示します。 ⑥ 承認/否認履歴画面 タイトル、日時、承認者、承認/否認区分をデータベースから取得し、表示します。 1-4. データベース設計 1-4-1. データベース設計 ① ワークフローエンジンの実体である3つの表を作成します。 これらの表は101NEOのワークフロー機能を使用するために必須の表であり、表名や列 名を変更することはできません。また、これらの表に対するトランザクションは101NEO のワークフロー・コマンドを介して行われるので、開発者が独自のSQLで直接トランザク ションを発行する必要はありません。 WF_Worksheet(書類) PK sheetID(書類ID) userID(申請者ID) sheetTitle(タイトル) sheetKind(種別) timeout(申請期間[時間]) accepterNo(承認者順位) regDate(登録日時) startDate(申請開始日時) finishedDate(完了日時) statusCD(状態コード) 表名 WF_Worksheet Copyright © 2004 WF_Accepter(承認者リスト) FK sheetID(書類ID) accepterNo(承認者順位) accepterID(承認者ID) WF_AcceptHistory(承認履歴) FK sheetID(書類ID) accepterID(承認者ID) regDate(承認/否認日時) acceptKB(承認/否認区分) 説明 ワークフロー・プロセスに関する情報を格納します。申請を 新規に登録した時点でこの表にレコードが追加され、ワーク フロー・プロセスが開始されます。また、申請の承認や否 認、申請期間オーバーといった状態の変化に応じて、レコー 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 5 ドが更新されます。 WF_Accepter ワークフロー・プロセスにおいて指定された承認者を格納し ます。 WF_AcceptHistory 承認もしくは否認処理の履歴を格納します。 ② 申請データを格納する2つの表を作成します。101NEOのワークフローエンジンは申請 対象となるデータ自体は管理しませんので、開発者がアプリケーションに応じて適切な 表を定義する必要があります。 ここでは、申請データを管理するために2つの表を用意します。 Aapplication(申請データ) PK sheetID(書類ID) total(総合計) temporary(仮払金控除) payment(差引支払額) Application_Detail(申請明細データ) PK PK 表名 sheetID(書類ID) row_no(行番号) row_date(日付) detail(明細) item(科目) receipt(領収書No) amount(金額) 説明 Application 申請データに関する情報を格納します。 Application_Detail 申請データ中の明細項目に関する情報を格納します。 ③ 経費申請アプリケーションで必要となる2つのマスター表を作成します。 Item(科目) PK id(科目ID) item_cd(科目コード) item_name(科目名) 表名 User_M(ユーザー) PK userid(ユーザーID) password(パスワード) username(ユーザー名) mail(メールアドレス) smtp_userid(SMTPユーザーID) smtp_password(SMTPパスワード) position(役職) 説明 Item 申請データの入力時に参照する科目(交通費、接待費など) を格納します。 User_M 申請や承認を行うユーザーの情報を格納します。 1-4-2. スキーマ作成 各表を作成するためのSQL文を用意します。マスター表には適当なデータを挿入します。 ※Oracle用のSQL文を付録に記載しておりますので参照してください。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 6 1-4-3. JDBCツール ツールバーの一番右にあるボタン をクリックするか、メニューの「表示」→「JDBC」をク リックすると、「JDBCツール」が起動します。 JDBCツールでは、JDBCドライバー経由でアプリケーション仕様定義書の[database]セクシ ョンに定義されているデータベースにアクセスして、簡単にデータの確認、更新等を行うこと ができます。 1-4-4. User_M表の更新 User_M表には申請や承認を行うユーザーの情報を格納します。ログイン時やメール送信時 に使用するデータなどが格納されています。 更新したいフィールドをJDBCツール上でダブルクリックしします。更新後、画面右上の「情報 更新」ボタンをクリックします。 ユーザー名やパスワードなどは好みによって変えても構いません。メールに関するデータは 実行環境に合わせて適切な値に更新する必要があります。※User_M表には、positionが ‘president’(社長)であるユーザーを1人だけ必ず含めてください。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 7 2. アプリケーションの作成 2-1. プロジェクトの作成 2-1-1. プロジェクトファイルの指定 「プロジェクト」メニュー下の「新規」をクリックすると、次のようなダイアログが表示されます。 プロジェクト情報を管理するプロジェクトファイルを指定し、「適用」ボタンをクリックします。 2-1-2. プロジェクト情報の入力 次のようなダイアログが表示されるので、必要に応じて各項目を修正/入力して「適用」ボ タンをクリックします。 ここでは、「初期表示ページ」に「login.html」と指定します。 2-1-3. アプリケーション仕様定義書(app.spj) [database] # 接続するデータベース環境に応じて適宜修正してください。 db = oracle.jdbc.driver.OracleDriver,jdbc:oracle:thin:@localhost:1521: ora920,wf,wf Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 8 [reference] WEBAPP=/servlet/workflow [init_app] # トランザクションモードに2を指定してワークフローを開始します。 put(trans_mode, 2) call wf.Init($trans_mode) put(WEBAPP, "http://localhost:8888/servlet/workflow") Note: wf.Init はワークフローの使用を開始するためのコマンドです。このコマンドを [init_app]から呼び出すことで、ワークフローを使用することができるようになり ます。 引数のトランザクションモードに 1 を設定した場合、ワークフロー内部でトラン ザクションを発行してくれるので、ユーザーがトランザクション管理をする必要 はありません。これに対してトランザクションモードを 2 に設定した場合は、ア プリケーション側でトランザクションを発行する必要があります。ワークフロー エンジン内部ではトランザクションは一切発行しません。 このチュートリアルでは、ワークフローで管理している表以外にも、申請データ 自体を格納している表が存在します。これら両方の表に対する更新を1つのト ランザクションとして管理するために、トランザクションモードを 2 に設定してア プリケーション側でトランザクションを発行します。 2-2. ログイン画面 2-2-1. HTML(login.html) <html> <head> <meta http-equiv="content-type" content="text/html;charset=Shift_JIS"> <title>login</title> </head> <body> <center> <hr> <font size="4" color="Blue"><b>経費精算システム</b></font> <hr> <br> <form method="post" action="@WEBAPP" name="form"> <table border="0" cellspacing="0" cellpadding="1" align="center"> <tr> <td>ユーザーID</td> <td><input type="text" name="userid" value="@ユーザーID" size="15"></td> </tr> <tr> <td>パスワード</td> <td> <input type="password" name="password" value="@パスワード" size="15"> </td> </tr> </table> <br> <input type="submit" name="login" value="ログイン"> Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 9 </form> <!-- エラーメッセージの表示/非表示を制御するために、erase命令を使用 します。 --> <!-- %erase @消去フラグ --> <br> <font color="Red"><b>@エラーメッセージ</b></font> <!-- %end-erase --> </center> </body> </html> 2-2-2. 仕様定義書(login.spj) [reference] ユーザーID = ?userid パスワード = ?password # エラーメッセージの有無により、erase命令に指定するフラグをセットします。 消去フラグ = ($err_msg = "")? true : false エラーメッセージ = $err_msg [init_page] perform セッション変数チェック() [セッション変数チェック] call ExistSessionVariable(err_msg, err_msg, $err_msg, "") [action] login = ログイン [ログイン] # User_M表にアクセスして、入力されたユーザーIDとパスワードを持つユーザーが # 存在するか調べます。 local(sql, rs) call ReplaceMarker(sql, " select username from user_m where userid = '?userid' and password = '?password' ") call QuerySQL(rs, db, $sql) local(count) call SQLResultCount(count, rs) if ($count < 1) # ユーザーが存在しない場合、エラーメッセージを指定して再度ログイン画面を # 表示します。 put(err_msg, "ユーザーIDまたはパスワードが違います。") put(nextpage, login.html) else # ユーザーが存在する場合、メイン画面に遷移します。 put(err_msg, "") Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 10 put(s_userid, ?userid) call SQLResultElement(s_username, rs, 1, 1) put(nextpage, main.html) endif 2-3. メイン画面 2-3-1. HTML(main.html) <html> <head> <meta http-equiv="content-type" content="text/html;charset=Shift_JIS"> <title>main</title> <script language="javascript" src="/common.js"></script> </head> <!-- フレームの左にメニュー画面を、右にコンテンツ画面を指定します。 コンテンツの初期画面は申請リストの一覧とします。 --> <frameset cols="25%,75%" frameborder="1" <!-- ページが移動するかウィンドウが閉じられたタイミング(onUnload)で、 JavaScriptのquit関数を実行します。 --> onUnload='quit("@WEBAPP?cur_page=main.html&logout=")'> <frame src="@WEBAPP?nextpage=menu.html" name="menu" scrolling="yes"> <frame src="@WEBAPP?nextpage=list1.html" name="content" scrolling="yes"> </frameset> </html> 2-3-2. 仕様定義書(main.spj) [action] logout = ログアウト [ログアウト] # endコマンドを実行してセッションを終了します。これにより、すべての # セッション変数が消滅します。 end() # セッション終了後にログイン画面に戻る際に、エラーメッセージのための変数 # (err_msg)が必要になるので、ローカル変数として宣言します。 local(err_msg) 2-4. メニュー画面 2-4-1. HTML(menu.html) <html> <head> <meta http-equiv="content-type" content="text/html;charset=Shift_JIS"> <title>menu</title> </head> <body> <font size="2"> @ユーザー名さん、ようこそ。 <br><br> Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 11 <hr align="left"> <ul> <li type="square"><a href="@WEBAPP?nextpage=new.html" target="content"> 新しい申請書の作成</a> <li type="square"><a href="@WEBAPP?nextpage=list1.html" target="content"> 申請リストの一覧</a> <li type="square"><a href="@WEBAPP?nextpage=list2.html" target="content"> 承認/否認対象リストの一覧</a> </ul> <hr align="left"> <p align="right"> <!-- ログアウトのリンクをクリックすると、ログイン画面に遷移します。 --> <a href="@WEBAPP?nextpage=login.html" target="_parent">ログアウト</a> </p> </font> </body> </html> 2-4-2. 仕様定義書(menu.spj) [reference] ユーザー名 = $s_username 2-5. 申請リストの一覧画面 2-5-1. HTML(list1.html) <html> <head> <meta http-equiv="content-type" content="text/html;charset=Shift_JIS"> <title>list1</title> <style type="text/css">th,td{font-size:10pt}</style> <script language="javascript" src="/common.js"></script> </head> <body> <center> <hr> <font size="4" color="Blue"><b>申請リストの一覧</b></font> <hr> <br> <table width="700" border="1" cellspacing="0" cellpadding="1"> <tr bgcolor="Orange"> <th>タイトル</th> <th width="110">登録日</th> <th width="110">申請開始日</th> <th width="110">申請期限</th> <th width="110">ステータス</th> </tr> <!-- %repeat --> <tr> <td> <!-- シートタイトルをクリックすると、詳細画面(detail.html)に遷移 します。 --> Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 12 <a href="@WEBAPP?nextpage=detail.html&sheetid=@シートID &class=application">@シートタイトル</a> </td> <td>@登録日</td> <td>@申請開始日</td> <td>@申請期限</td> <td> <!-- ステータスをクリックすると、JavaScriptのopenWindow関数が実行 され、承認履歴が表示されます。 --> <a href='javascript:openWindow("@WEBAPP?nextpage=history.html &sheetid=@シートID")'>@ステータス</a> </td> </tr> <!-- %end --> </table> </center> </body> </html> 2-5-2. 仕様定義書(list1.spj) [reference] シートID = $sheeted シートタイトル = $sheettitle 登録日 = $regdate 申請開始日 = $startdate 申請期限 = $expiredate ステータス = $status %include check.spj [init_page] perform 申請期間チェック() perform 申請リスト取得() [申請リスト取得] # データベースにアクセスして、ログインユーザーの申請書をすべて取得します。 local(sql, rs) call ReplaceMarker(sql, " select sheetid, sheettitle, to_char(regdate, 'YYYY-MM-DD HH24:MI'), to_char(startdate, 'YYYY-MM-DD HH24:MI'), to_char(startdate + timeout / 24, 'YYYY-MM-DD HH24:MI'), case statuscd when 1 then '申請中' when 2 then '承認済' when 3 then '否認済' when 4 then '取消済' when 5 then '申請期間オーバー' else '?' end from Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 13 wf_worksheet where userid = '$s_userid' order by regdate ") call QuerySQL(rs, db, $sql) local(sheetid, sheettitle, regdate, startdate, expiredate, status) call SQLResultRowArray(rs, 1, 0, sheetid, sheettitle, regdate, startdate, expiredate, status) 2-6. 承認/否認対象リストの一覧画面 2-6-1. HTML(list2.html) <html> <head> <meta http-equiv="content-type" content="text/html;charset=Shift_JIS"> <title>list2</title> <style type="text/css">th,td{font-size:10pt}</style> </head> <body> <center> <hr> <font size="4" color="Blue"><b>承認/否認対象リストの一覧</b></font> <hr> <br> <table width="700" border="1" cellspacing="0" cellpadding="1"> <tr bgcolor="Orange"> <th>タイトル</th> <th width="110">申請者</th> <th width="110">登録日</th> <th width="110">申請開始日</th> <th width="110">申請期限</th> </tr> <!-- %repeat --> <tr> <td> <!-- シートタイトルをクリックすると、詳細画面(detail.html)に遷移 します。 --> <a href="@WEBAPP?nextpage=detail.html&sheetid=@シートID &class=approval">@シートタイトル</a> </td> <td>@申請者</td> <td>@登録日</td> <td>@申請開始日</td> <td>@申請期限</td> </tr> <!-- %end --> </table> </center> </body> </html> Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 14 2-6-2. 仕様定義書(list2.spj) [reference] シートID = $sheetid シートタイトル = $sheettitle 申請者 = $username 登録日 = $regdate 申請開始日 = $startdate 申請期限 = $expiredate %include check.spj [init_page] perform 申請期間チェック() perform 承認否認対象リスト取得() [承認否認対象リスト取得] # データベースにアクセスして、ログインユーザーが承認処理を行うべき申請書 # をすべて取得します。 local(sql, rs) call ReplaceMarker(sql, " select w.sheetid, w.sheettitle, u.username, to_char(w.regdate, 'YYYY-MM-DD HH24:MI'), to_char(w.startdate, 'YYYY-MM-DD HH24:MI'), to_char(w.startdate + w.timeout / 24, 'YYYY-MM-DD HH24:MI') from wf_worksheet w, wf_accepter a, user_m u where w.sheetid = a.sheeted and w.accepterno = a.accepterno and w.userid = u.userid and a.accepterid = '$s_userid' and w.statuscd = 1 order by w.regdate ") call QuerySQL(rs, db, $sql) local(sheetid, sheettitle, username, regdate, startdate, expiredate) call SQLResultRowArray(rs, 1, 0, sheetid, sheettitle, username, regdate, startdate, expiredate) Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 15 2-7. 新しい申請書の作成画面 2-7-1. HTML(new.html) <html> <head> <meta http-equiv="content-type" content="text/html;charset=Shift_JIS"> <title>new</title> <style type="text/css">th,td{font-size:10pt}</style> <script language="javascript" src="/common.js"></script> </head> <body> <center> <hr> <font size="4" color="Blue"><b>新しい申請書の作成</b></font> <hr> <br> <form method="post" action="@WEBAPP" name="form"> <table width="700" border="1" cellspacing="0" cellpadding="1"> <tr> <th width="60" bgcolor="Orange">タイトル</th> <td><input type="text" name="title" size="125" maxlength="50"></td> </tr> </table> <br> <table width="700" border="1" cellspacing="0" cellpadding="1"> <tr bgcolor="Orange"> <th>起票日</th> <th width="150">記票者</th> <th width="150">社長</th> <th width="150">経理</th> </tr> <tr align="center"> <td>@起票年年@起票月月@起票日日</td> <td>@記票者</td> <td>@社長</td> <td> <select name="accepter"> <!-- 承認者のリストをrepeat命令で作成します。 --> <!-- %repeat --> <option value="@承認者ID">@承認者名 <!-- %end --> </select> </td> </tr> </table> <br> <table width="700" border="1" cellspacing="0" cellpadding="1"> <tr bgcolor="Orange"> <th width="185">日付</th> <th>明細</th> <th width="95">科目</th> <th width="60">領収書No</th> <th width="75">金額</th> </tr> Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 16 <!-- groupオプションで指定した回数分繰り返します。 --> <!-- %repeat group=@グループ配列 --> <tr align="center"> <td> <select name="year">@年オプションリスト</select>年 <select name="month">@月オプションリスト</select>月 <select name="day">@日オプションリスト</select>日 </td> <td><input type="text" name="detail" size="50" maxlength="30"></td> <td><select name="item">@科目オプションリスト</select></td> <td> <input type="text" name="receipt" size="2" style="text-align:right"> </td> <td> <!-- 金額が変更されたタイミング(onChange)で、JavaScriptのrecast関数 を実行します。 --> <input type="text" name="amount" size="10" style="text-align:right" onChange="recast()"> </td> </tr> <!-- %end --> </table> <table width="700" border="1" cellspacing="0" cellpadding="1"> <tr> <td width="480"></td> <td width="120" bgcolor="Orange"><b>総合計</b></td> <td align="right"> <input type="text" name="total" size="15" readonly style="text-align:right"> </td> </tr> <tr> <td></td> <td bgcolor="Orange"><b>仮払金控除</b></td> <td align="right"> <!-- 仮払金控除が変更されたタイミング(onChange)で、JavaScriptの recast関数を実行します。 --> <input type="text" name="temporary" value="0" size="15" style="text-align:right" onChange="recast()"> </td> </tr> <tr> <td></td> <td bgcolor="Orange"><b>差引支払額</b></td> <td align="right"> <input type="text" name="payment" size="15" readonly style="text-align:right"> </td> </tr> </table> <br> <!-- 「申請」と「リセット」の2つのボタンを用意します。 --> <input type="submit" name="apply" value="申請"> <input type="reset" name="reset" value="リセット"> </form> Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 17 </center> </body> </html> 2-7-2. 仕様定義書(new.spj) [reference] 起票年 = $system_year 起票月 = $system_month 起票日 = $system_day 記票者 = $s_username 社長 = $president_name 承認者ID = $accepter_id 承認者名 = $accepter_name グループ配列 = $group_array 年オプションリスト = $year_optionlist 月オプションリスト = $month_optionlist 日オプションリスト = $day_optionlist 科目オプションリスト = $item_optionlist %include check.spj %include mail.spj [init_page] perform システム時間取得() perform 社長名取得() perform 承認者候補リスト作成() perform グループ配列作成() perform 年一覧オプションタグ作成() perform 月一覧オプションタグ作成() perform 日一覧オプションタグ作成() perform 科目一覧オプションタグ作成() [システム時間取得] # 現在時間を取得します。 local(date, ymd, system_year, system_month, system_day) date = date() call SeparateString(ymd, $date, ".") system_year = elementat($ymd, 0) system_month = elementat($ymd, 1) system_day = elementat($ymd, 2) [社長名取得] # データベースにアクセスして、社長のユーザーIDとパスワードを取得します。 local(sql, rs) call ReplaceMarker(sql, " select userid, username from user_m where position = 'president' ") Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 18 call QuerySQL(rs, db, $sql) call SQLResultRow(rs, 1, president_id, president_name) [承認者候補リスト作成] # データベースにアクセスして、承認者候補のリスト(ログインユーザーと社長以外) # を取得します。 local(sql, rs) call ReplaceMarker(sql, " select userid, username from user_m where userid != '$s_userid' and position != 'president' order by userid ") call QuerySQL(rs, db, $sql) local(accepter_id, accepter_name) call SQLResultRowArray(rs, 1, 0, accepter_id, accepter_name) [グループ配列作成] # repeat命令のgroupオプションに指定する配列を作成します。 local(group_array) group_array = mkseq(10, 0, 1) [年一覧オプションタグ作成] # 年一覧用のオプションタグを作成します。 # 去年/今年/来年の3年が対象になります。 local(brank, last_year, value, year_optionlist) call MakeArray(brank, "") compute(last_year, $system_year - 1) value = mkseq(3, $last_year, 1) call UnionArray(value, $brank, $value) call TagOption(year_optionlist, $value, $value, $brank) [月一覧オプションタグ作成] # 月一覧用のオプションタグを作成します。 # 01月∼12月が対象になります。 local(brank, value, month_optionlist) call MakeArray(brank, "") call MakeArray(value, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12) call UnionArray(value, $brank, $value) call TagOption(month_optionlist, $value, $value, $brank) [日一覧オプションタグ作成] # 日一覧のオプションタグを作成します。 # 01日∼31日が対象になります。 local(brank, value, day_optionlist) call MakeArray(brank, "") call MakeArray(value, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31) Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 19 call UnionArray(value, $brank, $value) call TagOption(day_optionlist, $value, $value, $brank) [科目一覧オプションタグ作成] # 科目一覧用のオプションタグを作成します。 # データベースにアクセスして、科目コードと科目名を取得します。 local(sql, rs) call ReplaceMarker(sql, " select item_cd, item_name from item order by id ") call QuerySQL(rs, db, $sql) local(value, label, data, item_optionlist) call SQLResultRowArray(rs, 1, 0, value, label) call MakeArray(data, "brank") call TagOption(item_optionlist, $value, $label, $data) [action] apply = 申請 [申請] catch(エラー処理) transaction(db) perform シートID取得() perform 申請データ追加() perform 申請明細データ追加() perform 申請書類登録() commit(db) catch() perform メール送信() put(nextpage, complete.html) [シートID取得] # データベースにアクセスして、シーケンスから新しい申請書のシートIDを取得 # します。 local(sql, rs) call ReplaceMarker(sql, " select sheetid.nextval from dual ") call QuerySQL(rs, db, $sql) local(sheetid) call SQLResultRow(rs, 1, sheetid) [申請データ追加] local(sql, rs, cnt) # タイトルの入力欄が空白だったら、エラーページを表示します。 if (?title = "") Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 20 rollback(db) put(err_msg, "タイトルを指定してください。") put(nextpage, error.html) break() endif # 仮払金控除に入力した値が数値でなかったら、エラーページを表示します。 if (isdecimal(?temporary) = false) rollback(db) put(err_msg, "仮払金控除に正しい数値を指定してください。") put(nextpage, error.html) break() endif # 総合計の入力欄が空白だったら(すなわち明細データが1つもなかったら)、 # エラーページを表示します。 if (?total = "") rollback(db) put(err_msg, "明細データがありません。") put(nextpage, error.html) break() endif # 上記エラーに該当しなければ、データベースにアクセスして申請データを挿入 # します。 call ReplaceMarker(sql, " insert into application values ( '$sheetid', ?total, ?temporary, ?payment ) ") call ExecuteSQL(cnt, db, $sql) [申請明細データ追加] # 入力された申請明細データを配列として格納し、その配列数分(すなわち明細 # データの行数分)繰り返し処理を行います。 local(year, month, day, detail, item, receipt, amount) call SelectMultipleList(year, year) call SelectMultipleList(month, month) call SelectMultipleList(day, day) call SelectMultipleList(detail, detail) call SelectMultipleList(item, item) call SelectMultipleList(receipt, receipt) call SelectMultipleList(amount, amount) local(len, i) len = count_array($year) put(i, 0) perform 申請明細行挿入($i < $len) [申請明細行挿入] local(my_year, my_month, my_day, my_detail, my_item, my_receipt, my_amount) my_year = elementat($year, $i) my_month = elementat($month, $i) my_day = elementat($day, $i) my_detail = elementat($detail, $i) my_item = elementat($item, $i) Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 21 my_receipt = elementat($receipt, $i) my_amount = elementat($amount, $i) # 明細データ行の入力欄がすべて空白の場合、以下の処理を行います。 if ($my_year = "" && $my_month = "" && $my_day = "" && $my_detail = "" && $my_item = "" && $my_receipt = "" && $my_amount = "") # 対象行が先頭行だった場合(すなわち明細データが1行もない場合)、エラー # ページを表示します。 if ($i = 0) rollback(db) put(err_msg, "明細データがありません。") put(nextpage, error.html) break() # それ以外の場合、ループを終了します。 else call ReplaceMarker(i, $len) return() endif endif perform 入力データチェック() local(my_date) call Append(my_date, $my_year, "-", $my_month, "-", $my_day) local(sql, rs, cnt) # データベースにアクセスして、申請明細データを挿入します。 call ReplaceMarker(sql, " insert into application_detail values ( '$sheetid', $i, to_date('$my_date', 'YYYY-MM-DD'), '$my_detail', '$my_item', nullif('$my_receipt', ''), $my_amount ) ") call ExecuteSQL(cnt, db, $sql) call Add(i, 1) [入力データチェック] # 日付の入力データをチェックします。 if ($my_year = "" ││ $my_month = "" ││ $my_day = "") rollback(db) put(err_msg, "日付を指定してください。") put(nextpage, error.html) break() endif # 詳細の入力データをチェックします。 if ($my_detail = "") rollback(db) put(err_msg, "明細を指定してください。") put(nextpage, error.html) break() endif # 科目の入力データをチェックします。 if ($my_item = "") rollback(db) Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 22 put(err_msg, "科目を指定してください。") put(nextpage, error.html) break() endif # 金額の入力データをチェックします。 if (isnumeric($my_amount) = false) rollback(db) put(err_msg, "金額に正しい数値を指定してください。") put(nextpage, error.html) break() endif [申請書類登録] # 申請書類の登録にはwf.CreateProcessコマンドを使用します。このコマンドが実行 # された時点でWF_Worksheet表およびWF_Accepter表にレコードが登録され、申請が 開始されます。 call ReplaceMarker(requester, $s_userid) call MakeArray(accepters, ?accepter, $president_id) put(kind, "経費") put(timeout, 24) call wf.CreateProcess(db, $sheetid, $requester, $accepters, ?title, $kind, $timeout) [エラー処理] # データベースエラーが発生した場合、そのエラーメッセージをエラーページに # 表示します。 catch() rollback(db) err_msg = sql.get_message() put(nextpage, error.html) Note: ここでは HTML 中の各<select>タグに指定するオプションリストを、TagOption コマンドを使用して作成しています。通常、オプションリストは HTML の repeat 命令を用いて作成しますが、このページのように repeat 命令で作成された各 行に対してオプションリストを作成したい場合は、オプションリスト全体を TagOption コマンドで作成します。 2-8. 申請データの詳細画面 2-8-1. HTML(detail.html) <html> <head> <meta http-equiv="content-type" content="text/html;charset=Shift_JIS"> <title>detail</title> <style type="text/css">th,td{font-size:10pt}</style> </head> <body> <center> <hr> <font size="4" color="Blue"><b>申請データの詳細</b></font> <hr> <br> Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 23 <form method="post" action="@WEBAPP" name="form"> <table width="700" border="1" cellspacing="0" cellpadding="1"> <tr> <th width="60" bgcolor="Orange">タイトル</th> <td>@タイトル</td> </tr> </table> <br> <table width="700" border="1" cellspacing="0" cellpadding="1"> <tr bgcolor="Orange"> <th>起票日</th> <th width="150">記票者</th> <th width="150">社長</th> <th width="150">経理</th> </tr> <tr align="center"> <td>@起票年年@起票月月@起票日日</td> <td>@記票者</td> <td>@承認者2</td> <td>@承認者1</td> </tr> </table> <br> <table width="700" border="1" cellspacing="0" cellpadding="1"> <tr bgcolor="Orange"> <th width="100">日付</th> <th>明細</th> <th width="95">科目</th> <th width="60">領収書No</th> <th width="75">金額</th> </tr> <!-- %repeat --> <tr> <td>@年年@月月@日日</td> <td>@明細</td> <td>@科目</td> <td align="right">@領収書No</td> <td align="right">@金額</td> </tr> <!-- %end --> </table> <table width="700" border="1" cellspacing="0" cellpadding="1"> <tr> <td width="480"></td> <td width="120" bgcolor="Orange"><b>総合計</b></td> <td align="right">@総合計</td> </tr> <tr> <td></td> <td bgcolor="Orange"><b>仮払金控除</b></td> <td align="right">@仮払金控除</td> </tr> <tr> <td></td> <td bgcolor="Orange"><b>差引支払額</b></td> Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 24 <td align="right">@差引支払額</td> </tr> </table> <br> <!-- 申請者用のボタン(取消、再登録)と承認者用のボタン(承認、否認)の 表示は、erase命令を使用して制御します。 --> <!-- %erase @消去フラグ1 --> <input type="submit" name="cancel" value="取消"> <!-- %end-erase --> <!-- %erase @消去フラグ2 --> <input type="submit" name="re-register" value="再登録"> <!-- %end-erase --> <!-- %erase @消去フラグ3 --> <input type="submit" name="accept" value="承認"> <input type="submit" name="reject" value="否認"> <!-- %end-erase --> </form> </center> </body> </html> 2-8-2. 仕様定義書(detail.spj) [reference] タイトル = $sheettitle 記票者 = $username 承認者1 = $accepter1 承認者2 = $accepter2 起票年 = $regdate_year 起票月 = $regdate_month 起票日 = $regdate_day 総合計 = $total 仮払金控除 = $temporary 差引支払額 = $payment 消去フラグ1 = $erase_flag1 消去フラグ2 = $erase_flag2 消去フラグ3 = $erase_flag3 年 = $year 月 = $month 日 = $day 明細 = $detail 科目 = $item 領収書No = ($receipt = "")? " " : $receipt 金額 = $amount %include check.spj %include mail.spj [init_page] perform リクエストデータ保存() perform 申請期間チェック() perform 承認者リスト取得() perform 申請データ取得() perform 申請詳細データ取得() Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 25 [リクエストデータ保存] # フォームのリクエストデータとして受け取ったシートIDを、セッション変数に # 保存します。 put(sheetid, ?sheetid) [承認者リスト取得] # データベースにアクセスして、承認者名を取得します。 local(sql, rs) call ReplaceMarker(sql, " select username from user_m, wf_accepter where userid = accepterid and sheetid = '?sheetid' order by accepterno ") call QuerySQL(rs, db, $sql) local(accepter, accepter1, accepter2) call SQLResultRowArray(rs, 1, 0, accepter) accepter1 = elementat($accepter, 0) accepter2 = elementat($accepter, 1) [申請データ取得] # データベースにアクセスして、申請データを取得します。 local(sql, rs) call ReplaceMarker(sql, " select sheettitle, to_char(regdate, 'YYYY'), to_char(regdate, 'MM'), to_char(regdate, 'DD'), username, total, temporary, payment, # 「取消」ボタン消去フラグを設定します。 case when '?class' = 'approval' then 'true' when statuscd = 1 then 'false' when statuscd = 2 then 'true' when statuscd = 3 then 'false' when statuscd = 4 then 'true' when statuscd = 5 then 'false' end, # 「再登録」ボタン消去フラグを設定します。 case when '?class' = 'approval' then 'true' when statuscd = 1 then 'true' when statuscd = 2 then 'true' Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 26 when statuscd = 3 then 'false' when statuscd = 4 then 'false' when statuscd = 5 then 'false' end, # 「承認、否認」ボタン消去フラグを設定します。 case '?class' when 'application' then 'true' when 'approval' then 'false' end from wf_worksheet w, application a, user_m u where w.sheetid = a.sheeted and w.userid = u.userid and w.sheetid = '?sheetid' ") call QuerySQL(rs, db, $sql) local(sheettitle, regdate_year, regdate_month, regdate_day, username, total, temporary, payment, erase_flag1, erase_flag2, erase_flag3) call SQLResultRow(rs, 1, sheettitle, regdate_year, regdate_month, regdate_day, username, total,temporary, payment,erase_flag1, erase_flag2, erase_flag3) [申請詳細データ取得] # データベースにアクセスして、申請詳細データを取得します。 local(sql, rs) call ReplaceMarker(sql, " select to_char(row_date, 'YYYY'), to_char(row_date, 'MM'), to_char(row_date, 'DD'), detail, item_name, receipt, amount from application_detail, item where item = item_cd and sheetid = '?sheetid' order by row_no ") call QuerySQL(rs, db, $sql) local(year, month, day, detail, item, receipt, amount) call SQLResultRowArray(rs, 1, 0, year, month, day, detail, item, receipt, amount) [action] cancel = 取消, list1.html Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 27 re-register = 再登録, list1.html accept = 承認, list2.html reject = 否認, list2.html [取消] # 取消ボタンがクリックされたら、申請を取り消します。 # wf.CancelProcessコマンドを実行することにより、WF_Worksheet表の状態コード # (statusCD)が‘4’(取消済)に更新されます。 transaction(db) call wf.CancelProcess(db, $sheetid) commit(db) [再登録] # 再登録ボタンがクリックされたら、申請を再登録します。 # wf.RestartProcessコマンドを実行することにより、WF_Worksheet表の状態コード # (statusCD)が‘1’(申請中)に、申請開始日時(startDate)が現在日時に # 更新されます。 transaction(db) call wf.RestartProcess(db, $sheetid) commit(db) # 最初の承認者にメールを送信します。 perform メール送信() [承認] # 承認ボタンがクリックされたら、申請を承認します。 # wf.AcceptSheetコマンドを実行することにより、WF_AcceptHistory表に承認履歴 # が登録されます。また、最終承認者が承認を行った場合には、WF_Worksheet表の # 状態コード(statusCD)が‘2’(承認済)に、完了日時(finishedDate)が現在 # 日時に更新されます。 transaction(db) call wf.AcceptSheet(db, $sheetid, $s_userid) commit(db) # 次の承認者にメールを送信します。 # 全員に承認された場合は、申請者にメールを送信します。 perform メール送信() [否認] # 否認ボタンがクリックされたら、申請を否認します。 # wf.RejectSheetコマンドを実行することにより、WF_AcceptHistory表に否認履歴 # が登録されます。また、WF_Worksheet表の状態コード(statusCD)が‘3’(否認 # 済)に、完了日時(finishedDate)が現在日時に更新されます。 transaction(db) call wf.RejectSheet(db, $sheetid, $s_userid) commit(db) # 申請者にメールを送信します。 perform メール送信() Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 28 2-9. 承認/否認履歴画面 2-9-1. HTML(history.html) <html> <head> <meta http-equiv="content-type" content="text/html;charset=Shift_JIS"> <title>history</title> <style type="text/css">th,td{font-size:10pt}</style> <script language="javascript" src="/common.js"></script> </head> <body> <center> <hr> <font size="4" color="Blue"><b>承認/否認履歴</b></font> <hr> <br> <table width="350" border="1" cellspacing="0" cellpadding="1"> <tr> <th width="60" bgcolor="Orange">タイトル</th> <td>@シートタイトル</th> </tr> </table> <br> <table width="350" border="1" cellspacing="0" cellpadding="1"> <tr bgcolor="Orange"> <th width="110">日時</th> <th width="110">承認者</th> <th>承認/否認区分</th> </tr> <!-- %repeat --> <tr> <td>@日時</td> <td>@承認者</td> <td>@承認否認区分</td> </tr> <!-- %end --> </table> <br> <input type="button" name="close" value="閉じる" onClick="window.close()"> </center> </body> </html> 2-9-2. 仕様定義書(history.spj) [reference] シートタイトル = $sheettitle 日時 = $regdate 承認者 = $username 承認否認区分 = $acceptkb Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 29 [init_page] perform シートタイトル取得() perform 承認否認履歴取得() [シートタイトル取得] # データベースにアクセスして、シートのタイトルを取得します。 local(sql, rs) call ReplaceMarker(sql, " select sheettitle from wf_worksheet where sheetid = '?sheetid' ") call QuerySQL(rs, db, $sql) local(sheettitle) call SQLResultRow(rs, 1, sheettitle) [承認否認履歴取得] # データベースにアクセスして、承認否認履歴を取得します。 local(sql, rs) call ReplaceMarker(sql, " select to_char(regdate, 'YYYY-MM-DD HH24:MI'), username, case acceptkb when 1 then '承認' when 2 then '否認' end from wf_accepthistory, user_m where accepterid = userid and sheetid = '?sheetid' order by regdate ") call QuerySQL(rs, db, $sql) local(regdate, username, acceptkb) call SQLResultRowArray(rs, 1, 0, regdate, username, acceptkb) 2-10. 完了画面 2-10-1. HTML(complete.html) <html> <head> <meta http-equiv="content-type" content="text/html;charset=Shift_JIS"> <title>complete</title> </head> <body> Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 30 経費を精算しました。 <br><br> <a href="@WEBAPP?nextpage=list1.html">申請リストの一覧</a> </body> </html> 2-11. エラー画面 2-11-1. HTML(error.html) <html> <head> <meta http-equiv="content-type" content="text/html;charset=Shift_JIS"> <title>error</title> </head> <body> <font size="4" color="Red"><b>エラーが発生しました!</b></font> <br><br> <hr align="left"> @エラーメッセージ <hr align="left"> </body> </html> 2-11-2. 仕様定義書(error.spj) [reference] エラーメッセージ = $err_msg 2-12. 共通プログラム 2-12-1. JavaScript(common.js) /* 申請データの「総合計」と「差引支払額」を再計算します。明細データの「金額」お よび「仮払金控除」が変更されたタイミングで実行されます。 */ function recast() { var amount = 0; var total = 0; var temporary = window.document.form.temporary.value; var payment = 0; for (i = 0; i < window.document.form.amount.length; i++) { amount = window.document.form.amount[i].value; if (amount == "") { amount = 0; } amount = parseInt(amount); total += amount; } payment = total - temporary; window.document.form.total.value = total; Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 31 window.document.form.payment.value = payment; } /* 引数に指定されたURLのページを別ウィンドウでオープンします。 */ function openWindow(url) { showModalDialog(url, "subwindow", "dialogWidth:400px;dialogHeight:300px"); } /* 引数として指定されたURLの次のページに指定し、終了メッセージを表示します。 */ function quit(url) { location.href = url; alert("ご利用ありがとうございました。"); } 2-12-2. 申請期間チェックの仕様定義書(check.spj) [申請期間チェック] # 申請期間をオーバーしているシートがないかチェックします。 local(temp_sheetid) call wf.GetSheet(temp_sheetid, db, , 1) Note: wf.GetSheet コマンドは本来、対象となるシートを取得するためのコマンドです が、このコマンドが実行されたタイミングですべての申請書の申請期間もチェ ックされます。申請期間をオーバーしている申請書が見つかった場合は、 WF_Worksheet 表の該当レコードの状態コード(statusCD)が‘5’(申請期間オ ーバー)に変更されます。 ここでは、シートを取得するためではなく、申請期間のチェックが目的でこのコ マンドを実行しています。 2-12-3. メール送信の仕様定義書(mail.spj) [メール送信] perform ステータス取得() # ステータスコードが1∼3(申請中/承認済/否認済)の場合のみ処理を続行します。 if ($status < 1 ││ 3 < $status) return() endif perform 送信先ユーザー設定() perform タイトル取得() perform 件名設定() perform メール本文作成() perform SMTPサーバー情報取得() perform SMTPサーバーオープン() perform メッセージ送信() perform SMTPサーバークローズ() [ステータス取得] # シートのステータスを取得します。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 32 # wf_GetSheetStatusコマンドを実行することにより、指定した書類ID(sheetID) # の状態コード(statusCD)をWF_Worksheet表から取得します。 local(status) call wf.GetSheetStatus(status, db, $sheetid) [送信先ユーザー設定] local(userid, username) # ステータスが「申請中」の場合、承認者が送信先となります。 if ($status = 1) perform 承認者取得() # ステータスが「承認済/否認済」の場合、申請者が送信先となります。 else if ($status <= 3) perform 申請者取得() endif [承認者取得] # データベースにアクセスして、承認者を取得します。 local(sql, rs) call ReplaceMarker(sql, " select a.accepterid, u.username from wf_worksheet w, wf_accepter a, user_m u where w.sheetid = a.sheeted and w.accepterno = a.accepterno and a.accepterid = u.userid and w.sheetid = '$sheetid' ") call QuerySQL(rs, db, $sql) call SQLResultRow(rs, 1, userid, username) [申請者取得] # データベースにアクセスして、申請者を取得します。 local(sql, rs) call ReplaceMarker(sql, " select w.userid, u.username from wf_worksheet w, user_m u where w.userid = u.userid and w.sheetid = '$sheetid' ") call QuerySQL(rs, db, $sql) call SQLResultRow(rs, 1, userid, username) Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 33 [タイトル取得] # データベースにアクセスして、シートのタイトルを取得します。 local(sql, rs) call ReplaceMarker(sql, " select sheettitle from wf_worksheet where sheetid = '$sheetid' ") call QuerySQL(rs, db, $sql) local(sheettitle) call SQLResultRow(rs, 1, sheettitle) [件名設定] # シートのステータスによって、メールのサブジェクトを設定します。 local(subject) if ($status = 1) put(subject, "【経費精算】承認処理のお願い") else if ($status = 2) put(subject, "【経費精算】申請が承認されました") else if ($status = 3) put(subject, "【経費精算】申請が否認されました") endif [メール本文作成] # シートのステータスによって、メールの本文を設定します。 local(body) if ($status = 1) put(body, "$usernameさん", "$line_separator", "$line_separator", "経費精算「$sheettitle」が申請されました。", "$line_separator", "下記URLからログインして承認/否認処理を行ってください。" "$line_separator", "$line_separator", "$WEBAPP" ) else if ($status = 2) put(body, "$usernameさん", "$line_separator", "$line_separator", "経費精算「$sheettitle」が承認されました。", "$line_separator" ) else if ($status = 3) put(body, "$usernameさん", "$line_separator", "$line_separator", Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 34 "経費精算「$sheettitle」が否認されました。", "$line_separator" ) endif call ReplaceMarker(body, $body) [SMTPサーバー情報取得] # データベースにアクセスして、SMTPサーバーのユーザー情報を取得します。 local(sql, rs) call ReplaceMarker(sql, " select mail, smtp_userid, smtp_password from user_m where userid = '$userid' ") call QuerySQL(rs, db, $sql) local(mail, smtp_userid, smtp_password) call SQLResultRow(rs, 1, mail, smtp_userid, smtp_password) [SMTPサーバーオープン] # STMPサーバーをオープンします。 local(smtp) smtp = mail.open_smtp($SMTPServer, $smtp_userid, $smtp_password) [メッセージ送信] # メッセージを送信します。 mail.send_message($smtp, $mail, , , "[email protected]", , $subject, $body) [SMTPサーバークローズ] # SMTPサーバーをクローズします。 mail.close_smtp($smtp) Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 35 3. 動作確認 編集したファイルをすべて保存し、実行ボタンをクリック、もしくは「実行」メニュー下の「実 行」をクリックすると101NEO Studioに内蔵された簡易HTTPサーバー、Servletコンテナを使 用して動作の確認ができます。 3-1. ログイン 次の画面でユーザーIDおよびパスワードを入力し、ログインします。 正常にログインすると次のような画面が表示されます。 3-2. 新しい申請書の作成 メニューの「新しい申請書の作成」をクリックすると次のような入力画面が表示されるので、 申請したい経費データを入力します。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 36 入力後「申請」ボタンを押すと、次のような完了画面が表示されます。 また、最初の承認者(経理)に次のようなメールが送られます。 3-3. 承認処理 「【経費精算】承認処理のお願い」というメールを受け取った承認者は、メールに記載されて いるURLからシステムにログインします。 メニューの「承認/否認対象リストの一覧」をクリックすると、次のような画面が表示されま す。 リスト内のタイトルのリンクをクリックすると、次のような申請データの詳細画面が表示され ます。 内容を確認して「承認」ボタンをクリックします。 次の承認者(社長)も同様に承認処理を行います。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 37 すべての承認が済むと、次のようなメールが申請者に送られます。 申請リストの一覧では、「ステータス」フィールドが「承認済」に変わります。 もし、いずれかの承認者が否認した場合は、次のようなメールが申請者に送られます。 3-4. 申請データの取消/再登録 「申請中」のシートの取消しや、「否認済」や「申請期間オーバー」のシートの再登録は、申 請者自身が申請データの詳細画面で行うことができます。 3-5. 承認/否認履歴の確認 申請リストの一覧画面にあるステータスのリンクをクリックすると、次のような履歴画面が表 示されます。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 38 3-6. ログアウトの実行 メニューの「ログアウト」をクリックするかメインウィンドウを閉じると、次のような終了メッセー ジが表示されます。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 39 付録A. SQL ワークフロー関連のSQL文 drop table WF_AcceptHistory / drop table WF_Accepter / drop table WF_Worksheet / create table WF_Worksheet ( sheetID varchar2(30) primary key, userID varchar2(30) not null, sheetTitle varchar2(120), sheetKind varchar2(10), timeout number(5), accepterNo number(2), regDate date not null, startDate date, finishedDate date, statusCD number(2) not null ) / create index userid_idx on WF_Worksheet(userID) / create table WF_Accepter ( sheetID varchar2(30) not null references WF_Worksheet(sheetID), accepterNo number(2) not null, accepterID varchar2(30) not null ) / create table WF_AcceptHistory ( sheetID varchar2(30) not null references WF_Worksheet(sheetID), accepterID varchar2(30) not null, regDate date not null, acceptKB number(2) not null ) / 申請データ関連のSQL文 drop table application / create table application ( sheetid varchar2(30) total number temporary number payment number ) / drop table application_detail Copyright © 2004 primary key, not null, not null, not null 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 40 / create table application_detail ( sheetid varchar2(30) row_no number row_date date detail varchar2(200) item varchar2(30) receipt number, amount number primary key (sheetid, row_no) ) / drop sequence sheetid / create sequence sheetid / not not not not not null, null, null, null, null, not null, マスター関連のSQL文 drop table item / create table item ( id item_cd item_name ) / insert into item values / insert into item values / insert into item values / insert into item values / insert into item values / insert into item values / insert into item values / insert into item values / insert into item values / insert into item values / drop table user_m / create table user_m ( userid password username mail Copyright © 2004 number varchar2(30), varchar2(30) primary key, (1, '', '') (2, 'travel', '旅費交通費') (3, 'entertainment', '接待費') (4, 'meeting', '会議費') (5, 'training', '研修費') (6, 'welfare', '福利厚生費') (7, 'stationery', '事務用品代') (8, 'book', '書籍代') (9, 'tax', '租税') (10, 'other', 'その他') varchar2(30) varchar2(30), varchar2(30), varchar2(30), primary key, 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 41 smtp_userid smtp_password position varchar2(30), varchar2(30), varchar2(30) ) / insert into user_m values ('user1', 'user1', 'ユーザー1', '[email protected]', 'user1', 'user1', 'president') / insert into user_m values ('user2', 'user2', 'ユーザー2', '[email protected]', 'user2', 'user2', 'auditor') / insert into user_m values ('user3', 'user3', 'ユーザー3', '[email protected]', 'user3', 'user3', 'director') / insert into user_m values ('user4', 'user4', 'ユーザー4', '[email protected]', 'user4', 'user4', 'sales') / commit / Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 42 付録B. コマンドリスト 初期化 wf.Init ワークフローエンジンの使用を開始 ワークフロープロセス(書類)の操作 wf.CreateProcess ワークフロープロセス(書類)を新規に登録して申請を開始 wf.CreateDynamicProcess 承認者を動的に決定できるワークフロープロセス(書類)を新 規に登録して申請を開始 wf.CancelProcess ワークフロープロセス(書類)を取り消し wf.RestartProcess ワークフロープロセス(書類)を再登録 wf.DeleteProcess ワークフロープロセス(書類)をデータベースから削除 承認操作 wf.AcceptSheet 申請中のワークフロープロセス(書類)を「承認」 wf.RejectSheet 申請中のワークフロープロセス(書類)を「否認」 拡張ステータスの設定 wf.SetStatusEx ワークフロープロセス(書類)の承認状態を拡張ステータスコ ードで設定 ワークフロープロセス(書類)取得操作 wf.GetSheet 特定ユーザーを対象とするワークフロープロセス(書類)を取 得 wf.GetSheetEx 特定ユーザーを対象とする拡張ステータスコードを使用したワ ークフロープロセス(書類)を取得 wf.GetSheetByStatus 特定の承認状態のワークフロープロセス(書類)を取得 ワークフロープロセス(書類)の承認状態取得操作 wf.GetSheetStatus ワークフロープロセス(書類)の承認状態を取得 初期化 wf.Init ワークフローエンジンの使用を開始 書式 call wf.Init($trans_mode) パラメータ trans_mode トランザクションモード 1: ワークフローエンジン内部でトランザクションを発行(省略時) 2: アプリケーション側でトランザクションを発行 説明 ワークフローエンジンの使用を開始します。 このコマンドをアプリケーション仕様定義書の[init_app]セクションから呼び出すことでワー クフローエンジンを使用することができるようになります。 トランザクションモードは、ワークフローコマンドの実行結果の確定をワークフローエンジ ン内で行うか、アプリケーション側で行うかを設定します。 トランザクションモードを 1 に設定した場合は、ワークフローコマンドが実行された時点で 実行結果が確定します。 トランザクションモードを 2 に設定した場合は、アプリケーション側でトランザクションの Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 43 発行(transaction)及び確定(commit)を行う必要があります。 ワークフローエンジン内部ではトランザクションは発行しません。 ワークフロープロセス(書類)の操作 wf.CreateProcess ワークフロープロセス(書類)を新規に登録して申請を開始 書式 call wf.CreateProcess(wfdb, $sheet, $requester, $accepter[, $title, $kind, $time]) パラメータ wfdb sheet requester accepter title kind time ワークフローDB のデータベース識別名 書類 ID 申請者 ID 承認者 ID もしくは承認者 ID の配列 書類タイトル(省略可) 書類種別(省略可) 申請期間(時間)(省略可) 説明 ワークフロープロセス(書類)を新規に登録して申請を開始します。 ワークフロープロセスの承認状態は「申請中」になり、最初の承認者の承認待ち状態にな ります。 書類 ID には、30 バイトまでのユニークな識別名を指定できます。 (ワークフロー用データベーススキーマを変更することで制限を変更することも可能です) 書類タイトル、書類種別、申請期間は省略することができます。 申請期間は時間単位で設定します。省略した場合は無期限になります。 関連コマンド/関数 拡張コマンド wf.CreateDynamicProcess 承認者を動的に決定できるワークフロー のプロセス(書類)を新規に登録して申請を開始 wf.CreateDynamicProcess 承認者を動的に決定できるワークフロープロセス(書類)を新規に登録して申請を開始 書式 call wf.CreateDynamicProcess(wfdb, $sheet, $requester, $obj[, $title, $kind, $time]) パラメータ wfdb sheet requester obj title kind time ワークフローDB のデータベース識別名 書類 ID 申請者 ID jp.co.val.workflow.IAccepter を実装したインスタンス 書類タイトル(省略可) 書類種別(省略可) 申請有効期間(時間)(省略可) 説明 承認者を動的に決定できるワークフロープロセス(書類)を新規に登録して申請を開始し ます。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 44 ワークフロープロセスの承認状態は「申請中」になり、最初の承認者を探すために jp.co.val.workflow.IAccepter を実装したインスタンスの nextAccepter メソッドが呼び出され ます。 承認が必要な度に承認者を得るために nextAccepter メソッドが呼び出されます。 このコマンドは、承認者をあらかじめ決定しておくことなく、申請の状況に応じて承認者を 変えることができるコマンドです。 書類 ID には、30 バイトまでのユニークな識別名を指定できます。 (ワークフロー用データベーススキーマを変更することで制限を変更することも可能です) 書類タイトル、書類種別、申請期間は省略することができます。 申請期間は時間単位で設定します。省略した場合は無期限になります。 関連コマンド/関数 拡張コマンド wf.CreateProcess 申請を開始 ワークフローのプロセス(書類)を新規に登録して wf.CancelProcess ワークフロープロセス(書類)を取り消し 書式 call wf.CancelProcess(wfdb, $sheet) パラメータ wfdb sheet ワークフローDB のデータベース識別名 書類 ID 説明 ワークフロープロセス(書類)を取り消します。 ワークフロープロセスの承認状態は「取消済」になります。 ただし、ワークフロープロセスのデータはデータベースから削除されません。 データベースから削除する場合は wf.DeleteProcess コマンドを呼び出します。 関連コマンド/関数 拡張コマンド wf.DeleteProcess 削除 ワークフローのプロセス(書類)をデータベースから wf.RestartProcess ワークフロープロセス(書類)を再登録 書式 call wf.RestartProcess(wfdb, $sheet) パラメータ wfdb sheet ワークフローDB のデータベース識別名 書類 ID 説明 ワークフロープロセスを再登録します。 ワークフロープロセスの承認状態は「申請中」になり、最初の承認者の承認待ちになりま す。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 45 wf.DeleteProcess ワークフロープロセス(書類)をデータベースから削除 書式 call wf.DeleteProcess(wfdb, $sheet) パラメータ wfdb sheet ワークフローDB のデータベース識別名 書類 ID 説明 ワークフロープロセス(書類)をデータベースから削除します。 関連コマンド/関数 拡張コマンド wf.CancelProcess ワークフローのプロセス(書類)を取り消し 承認操作 wf.AcceptSheet 申請中のワークフロープロセス(書類)を「承認」 書式 call wf.AcceptSheet(wfdb, $sheet, $accepter) パラメータ wfdb sheet accepter ワークフローDB のデータベース識別名 書類 ID 承認者 ID 説明 申請中のワークフロープロセス(書類)を「承認」します。 すべての承認者の承認が終了したときにワークフロープロセスの承認状態は「承認済」に なります。 関連コマンド/関数 拡張コマンド wf.RejectSheet 申請中の書類を「否認」 wf.RejectSheet 申請中の書類を「否認」 書式 call wf.RejectSheet(wfdb, $sheet, $accepter) パラメータ wfdb sheet accepter ワークフローDB のデータベース識別名 書類 ID 承認者 ID 説明 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 46 申請中のワークフロープロセス(書類)を「否認」します。 ワークフロープロセスの承認状態は「否認済」になります。 関連コマンド/関数 拡張コマンド wf.AcceptSheet 申請中の書類を「承認」 拡張ステータス設定 wf.SetStatusEx ワークフロープロセス(書類)の承認状態を拡張ステータスコードで設定 書式 call wf.SetStatusEx(wfdb, $sheet, $status) パラメータ wfdb sheet status ワークフローDB のデータベース識別名 書類 ID 拡張ステータスコード 説明 ワークフロープロセス(書類)(sheet)の承認状態を拡張ステータスコード(status)に更新し ます。 拡張ステータスコードは 10 以上の値です。 承認状態コード、拡張ステータスコードに関しては「8-2-5.承認状態コード」を参照してくだ さい。 ワークフロープロセス(書類)取得操作 wf.GetSheet 特定ユーザーを対象とするワークフロープロセス(書類)を取得 書式 call wf.GetSheet(sname, wfdb, $requester, $code [, $title]) パラメータ sname wfdb requester code 書類 ID 配列のセッション変数名 (出力パラメータ) ワークフローDB のデータベース識別名 申請者 ID/承認者 ID リクエストコード 1: 2: 3: 4: 5: title 申請中(申請者 ID) 承認済(申請者 ID) 否認済(申請者 ID) 申請期間オーバー(申請者 ID) 未承認(承認者 ID) 書類タイトル(省略可) 説明 特定ユーザー(requester)を対象とするワークフロープロセス(書類)の中からリクエストコ ードや書類タイトル(省略可)で検索し、該当するワークフロープロセスの書類 ID を配列と してセッション変数(sname)に設定します。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 47 関連コマンド/関数 拡張コマンド wf.GetSheetEx ワークフローから特定ユーザーを対象とする拡張 ステータスコードを使用した書類を取得 拡張コマンド wf.GetSheetByStatus ワークフローから特定の承認状態の書類を取得 Note: リクエストコードは、承認状態コードと似ていますが異なるもので す。 wf.GetSheetEx 特定ユーザーを対象とする拡張ステータスコードを使用したワークフロープロセス(書類) を取得 書式 call wf.GetSheetEx(sname, wfdb, $requester, $code [, $title]) パラメータ sname wfdb requester code title 書類 ID 配列のセッション変数名 (出力パラメータ) ワークフローDB のデータベース識別名 申請者 ID/承認者 ID 拡張ステータスコード 書類タイトル(省略可) 説明 特定ユーザー(requester)を対象とするワークフロープロセス(書類)の中から拡張ステータ スコードや書類タイトル(省略可)で検索し、該当する書類の書類 ID を配列としてセッショ ン変数に設定します。 拡張ステータスコードは 10 以上の値です。 拡張ステータスコードに関しては「8-2-5.承認状態コード」を参照してください 関連コマンド/関数 拡張コマンド wf.GetSheetEx ワークフローから特定ユーザーを対象とする拡張 ステータスコードを使用した書類を取得 拡張コマンド wf.GetSheetByStatus ワークフローから特定の承認状態の書類を取得 wf.GetSheetByStatus 特定の承認状態のワークフロープロセス(書類)を取得 書式 call wf.GetSheetByStatus(sname, wfdb, $status [, $title]) パラメータ sname wfdb code 書類 ID 配列のセッション変数名 (出力パラメータ) ワークフローDB のデータベース識別名 承認状態コード 1: 申請中 2: 承認済 3: 否認済 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 48 4: 取消済 5: 申請期間オーバー その他: 拡張ステータスコード title 書類タイトル(省略可) 説明 特定の承認状態(code)のワークフロープロセス(書類)の書類 ID を配列としてセッション変 数(sname)に設定します。 ワークフローエンジンがデフォルトで備えている承認状態以外の拡張ステータスも指定で きます。 関連コマンド/関数 拡張コマンド wf.GetSheet ワークフローから特定ユーザーを対象とする書類 を取得 拡張コマンド wf.GetSheetEx ワークフローから特定ユーザーを対象とする拡張 ステータスコードを使用した書類を取得 3-6-1. ワークフロープロセス(書類)の承認状態取得操作 wf.GetSheetStatus ワークフロープロセス(書類)の承認状態を取得 書式 call wf.GetSheetStatus(sname, wfdb, $sheet) パラメータ sname セッション変数名 (出力パラメータ) 承認状態 -1: 書類ID未登録 0: 準備中 1: 申請中 2: 承認済 3: 否認済 4: 取消済 5: 申請期間オーバー その他: 拡張ステータスコード wfdb sheet ワークフローDB のデータベース識別名 書類 ID 説明 ワークフロープロセス(書類)(sheet)の承認状態をセッション変数(sname)に設定します。 Copyright © 2004 101 Co., Ltd. All Rights Reserved. Tutorial Workflow - Page 49