30 KiB
残業統計管理システム 設計書(サブシステムB)
システム概要
本サブシステムは、社員からの加班申請データを元に、振り分け・重複チェック・打刻照合・取消マッチング・キーブレイク集約を行い、月次の加班統計データをDBに保存する。
サブシステム情報
| 項目 | 内容 |
|---|---|
| サブシステムID | ZAN(残業→ZANgyo) |
| COBOLプログラム数 | 6 |
| JCL数 | 6 |
| DB | 1(OVERTIME-DB / DB2、2テーブル) |
システム定数
| 定数 | 値 | 説明 |
|---|---|---|
| WORK-START | 0900 | 所定労働開始時刻 |
| WORK-END | 1800 | 所定労働終了時刻 |
| DINNER-START | 1830 | 食事時間開始(1830以前は加班不可) |
| MIN-OVT-HOURS | 0.5 | 加班最小単位 |
入力CSV形式(OVT-APPLY)
各レコードはCSV形式。
| 項目 | 内容 |
|---|---|
| フォーマット | 申請番号,社員番号,日付(YYYYMMDD),開始時刻(HHMM),終了時刻(HHMM),ステータス |
| ステータス 0 | 申請(新規) |
| ステータス 1 | 承認済(後続処理で状態更新) |
| ステータス 9 | 取消 |
ファイル一覧
| # | ファイル名 | 編成 | RECM | サイズ | 用途 | 区分 |
|---|---|---|---|---|---|---|
| 1 | OVT-APPLY | SEQUENTIAL | FB | 80 | 加班申請CSV(入力) | 新規 |
| 2 | OVT-VALID | SEQUENTIAL | FB | 80 | 振り分け通過(有効申請) | 新規 |
| 3 | OVT-CANCEL | SEQUENTIAL | FB | 80 | 振り分け通過(取消) | 新規 |
| 4 | OVT-NODUP | SEQUENTIAL | FB | 80 | 重複チェック通過データ | 新規 |
| 5 | OVT-CHECKED | SEQUENTIAL | FB | 80 | 打刻照合通過(OVT-TYPE付加) | 新規 |
| 6 | OVT-MATCHED | SEQUENTIAL | FB | 80 | マッチング通過(処理番号付加) | 新規 |
| 7 | OVT-DBCLEAN | SEQUENTIAL | FB | 80 | 孤立取消(DB削除対象) | 新規 |
| 8 | OVT-SUMMARY | SEQUENTIAL | FB | 80 | 集約結果 | 新規 |
| 9 | ERROR-LOG | SEQUENTIAL | VB | 200 | エラーレコード退避 | Aと共用 |
| 10 | EDITED-PUNCH | SEQUENTIAL | FB | 80 | 打刻データ(Aシステム出力) | Aから連携 |
| 11 | HOLIDAY-FILE | SEQUENTIAL | FB | 80 | 休日マスタファイル(Aシステム提供) | Aから連携 |
DBテーブル管理方針
DB2インスタンスは全サブシステムで共有するが、テーブルはサブシステム別に機能分割する。 BサブシステムのテーブルはOVT-APPLICATIONS, OVT-MONTHLYの2つであり、これらの管理・更新はBのみが行う。 Aサブシステムのテーブル(DAILY_RECORDS, LEAVE_RECORDS等)は参照せず、A→Bの連携はEDITED-PUNCHファイル経由に限定する。 HOLIDAY_CALENDARテーブルについては、Aサブシステムによって提供されるHOLIDAY-FILEを使用することで参照を代替する。
DB二重対応
本サブシステムのDB操作はDB2の埋め込みSQL(EXEC SQL)で直接記述する。
ただし、休日マスタに関するDBアクセスはファイルベースで処理するため、
ZAN06UPD以外の全プログラムはDBアクセスを伴わない。
各プログラム内でEXEC SQL INSERT/UPDATE/SELECTを発行する。
共通関数利用方針
Aサブシステムの共通関数のうち、安定した汎用API(SUB01DAT, SUB02MSG, SUB03END, SUB04CHK, SUB05TIM)はBでも利用する。 SUB06DBUはサブシステムAで使用するDB更新用サブプログラムであり、Bでは使用しない(EXEC SQLを直接記述)。
DB構成
DB名称:残業統計データベース(OVERTIME-DB)
テーブル1:OVT-APPLICATIONS(個別加班申請テーブル)
| カラム | 型 | 内容 |
|---|---|---|
| APPL-ID | CHAR(8) | 申請番号(PK) |
| EMP-ID | CHAR(8) | 社員番号 |
| APPL-DATE | CHAR(8) | 申請日 YYYYMMDD |
| OVT-TYPE | CHAR(1) | W=平日 / H=休日 |
| START-TIME | CHAR(4) | 開始時刻 HHMM |
| END-TIME | CHAR(4) | 終了時刻 HHMM |
| OVT-HOURS | DECIMAL(4,1) | 加班時間 |
| STATUS | CHAR(1) | 0=有効 / 9=取消 |
| UPDATED-AT | TIMESTAMP | 更新日時 |
テーブル2:OVT-MONTHLY(月次集計テーブル)
| カラム | 型 | 内容 |
|---|---|---|
| EMP-ID | CHAR(8) | 社員番号(PK) |
| YEAR-MONTH | CHAR(6) | 対象年月 YYYYMM(PK) |
| OVT-TYPE | CHAR(1) | W=平日 / H=休日(PK) |
| OVT-HOURS | DECIMAL(6,1) | 加班時間合計 |
| OVT-COUNT | INTEGER | 加班回数 |
| UPDATED-AT | TIMESTAMP | 更新日時 |
処理フロー
OVT-APPLY(CSV、任意順)
レコード: 申請番号,社員番号,日付,開始時刻,終了時刻,ステータス(0/1/9)
│
╞══ ZANJ010 ═══════════════════════════════════╡
│ ZAN01CHK(残業申請振分処理)— 振り分け
│ UNSTRINGでCSV分解 / EVALUATEでステータス判定
│ SUB04CHKで日付/時刻/数値チェック / 0.5h未満チェック
├── ステータス=0,1 → OVT-VALID
├── ステータス=9 → OVT-CANCEL
└── 異常 → ERROR-LOG
│
╞══ ZANJ012 ═══════════════════════════════════╡
│ SORT(OVT-VALID → 社員番号+日付+開始時刻昇順)
│
│ ZAN02CHK(時間帯重複チェック処理)— 項目チェック
│ 同社員+同日の前レコード終了時刻 > 現レコード開始時刻
│ → 重複(境界接続は重複としない)
├── 通過 → OVT-NODUP
└── 重複 → ERROR-LOG
│
╞══ ZANJ013 ═══════════════════════════════════╡
│ SORT(EDITED-PUNCH → 社員番号+日付昇順)
│
│ ZAN03CHK(打刻時間照合処理)— マッチング(N:1)
│ OVT-NODUP + PUNCH-SORTED を社員番号+日付で突合
│ 申請時間帯が出勤〜退勤の範囲内か確認
│ HOLIDAY_CALENDAR検索+曜日関数で休日判定→OVT-TYPE(W/H)設定
├── 通過 → OVT-CHECKED
└── 異常 → ERROR-LOG
│
╞══ ZANJ015 ═══════════════════════════════════╡
│ SORT(OVT-CHECKED → 申請番号昇順)
│ SORT(OVT-CANCEL → 申請番号昇順)
│
│ ZAN04MAT(取消マッチング処理)— マッチング1:1
│ キー=申請番号で VALID vs CANCEL を突合
├── VALID有 + CANCEL無 → OVT-MATCHED
├── VALID有 + CANCEL有 → 消滅
└── VALID無 + CANCEL有 → OVT-DBCLEAN
│
╞══ ZANJ020 ═══════════════════════════════════╡
│ SORT(OVT-MATCHED → 申請番号+処理番号昇順)
│
│ ZAN05CAL(残業時間集計処理)— キーブレイク集計
│ 同一申請番号内の最終レコードを集計
│ DIVIDE 分→時間変換 / SUB05TIMで丸め
│ COMPUTE ROUNDED ON SIZE ERROR
│ → OVT-SUMMARY
│
╞══ ZANJ025 ═══════════════════════════════════╡
│ ZAN06UPD(残業統計DB更新処理)— DB更新
├── OVT-SUMMARY → OVT-APPLICATIONS INSERT/UPDATE
│ → OVT-MONTHLY UPSERT(平日/休日別)
└── OVT-DBCLEAN → OVT-APPLICATIONS STATUS='9' UPDATE
→ OVT-MONTHLY 減算UPDATE
→ 該当なし → ERROR-LOG
JCL
ZANJ010 — 残業申請振分
//ZANJ010 JOB (ACCT),'残業申請振分',CLASS=A
//*
//*--- パラメータ定義 ---
//SETPARM SET YEARMONTH=202605
//*
//*=====================================================================
//* STEP010: 振り分け(SORT不要)
//* 注:YEARMONTH PARMは他プログラムとの一貫性のため渡すが、ZAN01CHK内では未使用
//*=====================================================================
//STEP010 EXEC PGM=ZAN01CHK
//ZAN01R01 DD DSN=OVT-APPLY.DAT,DISP=SHR
//ZAN01W01 DD DSN=OVT-VALID.DAT,DISP=(NEW,PASS)
//ZAN01W02 DD DSN=OVT-CANCEL.DAT,DISP=(NEW,PASS)
//ZAN01W03 DD DSN=ERROR-LOG.DAT,DISP=(NEW,PASS)
ZANJ012 — 時間帯重複チェック
//ZANJ012 JOB (ACCT),'時間帯重複チェック',CLASS=A
//*
//*--- パラメータ定義 ---
//SETPARM SET YEARMONTH=202605
//*
//*=====================================================================
//* STEP012S: 有効申請 SORT
//*=====================================================================
//STEP012S EXEC PGM=SORT
//SORTIN DD DSN=OVT-VALID.DAT,DISP=(OLD,DELETE)
//SORTOUT DD DSN=OVT-VSORT.DAT,DISP=(NEW,PASS)
//SYSIN DD *
SORT FIELDS=(9,8,CH,A,17,8,CH,A,25,4,CH,A),EQUALS
/*
//*
//*=====================================================================
//* STEP012: 重複チェック
//*=====================================================================
//STEP012 EXEC PGM=ZAN02CHK,PARM='YEARMONTH=&YEARMONTH'
//ZAN02R01 DD DSN=OVT-VSORT.DAT,DISP=(OLD,DELETE)
//ZAN02W01 DD DSN=OVT-NODUP.DAT,DISP=(NEW,PASS)
//ZAN02W02 DD DSN=ERROR-LOG.DAT,DISP=(NEW,PASS)
ZANJ013 — 打刻時間照合
//ZANJ013 JOB (ACCT),'打刻時間照合',CLASS=A
//*
//*--- パラメータ定義 ---
//SETPARM SET YEARMONTH=202605
//*
//*=====================================================================
//* STEP013S: 打刻データ SORT
//*=====================================================================
//STEP013S EXEC PGM=SORT
//SORTIN DD DSN=EDITED-PUNCH.DAT,DISP=SHR
//SORTOUT DD DSN=PUNCH-SORTED.DAT,DISP=(NEW,PASS)
//SYSIN DD *
SORT FIELDS=(1,8,CH,A,9,8,CH,A),EQUALS
/*
//*
//*=====================================================================
//* STEP013: 打刻照合 + 曜日判定
//*=====================================================================
//STEP013 EXEC PGM=ZAN03CHK,PARM='YEARMONTH=&YEARMONTH'
//ZAN03R01 DD DSN=OVT-NODUP.DAT,DISP=(OLD,DELETE)
//ZAN03R02 DD DSN=PUNCH-SORTED.DAT,DISP=(OLD,DELETE)
//ZAN03R03 DD DSN=HOLIDAY-FILE.DAT,DISP=SHR
//ZAN03W01 DD DSN=OVT-CHECKED.DAT,DISP=(NEW,PASS)
//ZAN03W02 DD DSN=ERROR-LOG.DAT,DISP=(NEW,PASS)
ZANJ015 — 取消マッチング
//ZANJ015 JOB (ACCT),'取消マッチング',CLASS=A
//*
//*--- パラメータ定義 ---
//SETPARM SET YEARMONTH=202605
//*
//*=====================================================================
//* STEP015S1: チェック済データ SORT
//*=====================================================================
//STEP015SA EXEC PGM=SORT
//SORTIN DD DSN=OVT-CHECKED.DAT,DISP=(OLD,DELETE)
//SORTOUT DD DSN=OVT-SORTED.DAT,DISP=(NEW,PASS)
//SYSIN DD *
SORT FIELDS=(1,8,CH,A),EQUALS
/*
//*
//*=====================================================================
//* STEP015S2: 取消データ SORT
//*=====================================================================
//STEP015SB EXEC PGM=SORT
//SORTIN DD DSN=OVT-CANCEL.DAT,DISP=(OLD,DELETE)
//SORTOUT DD DSN=OVT-CSORT.DAT,DISP=(NEW,PASS)
//SYSIN DD *
SORT FIELDS=(1,8,CH,A),EQUALS
/*
//*
//*=====================================================================
//* STEP015: マッチング
//*=====================================================================
//STEP015 EXEC PGM=ZAN04MAT,PARM='YEARMONTH=&YEARMONTH'
//ZAN04R01 DD DSN=OVT-SORTED.DAT,DISP=(OLD,DELETE)
//ZAN04R02 DD DSN=OVT-CSORT.DAT,DISP=(OLD,DELETE)
//ZAN04W01 DD DSN=OVT-MATCHED.DAT,DISP=(NEW,PASS)
//ZAN04W02 DD DSN=OVT-DBCLEAN.DAT,DISP=(NEW,PASS)
//ZAN04W03 DD DSN=ERROR-LOG.DAT,DISP=(NEW,PASS)
ZANJ020 — 残業時間集計
//ZANJ020 JOB (ACCT),'残業時間集計',CLASS=A
//*
//*--- パラメータ定義 ---
//SETPARM SET YEARMONTH=202605
//*
//*=====================================================================
//* STEP020S: マッチング済データ SORT
//*=====================================================================
//STEP020S EXEC PGM=SORT
//SORTIN DD DSN=OVT-MATCHED.DAT,DISP=(OLD,DELETE)
//SORTOUT DD DSN=OVT-SORTED2.DAT,DISP=(NEW,PASS)
//SYSIN DD *
SORT FIELDS=(1,8,CH,A,35,2,CH,A),EQUALS
/*
//*
//*=====================================================================
//* STEP020: キーブレイク集計
//*=====================================================================
//STEP020 EXEC PGM=ZAN05CAL,PARM='YEARMONTH=&YEARMONTH'
//ZAN05R01 DD DSN=OVT-SORTED2.DAT,DISP=(OLD,DELETE)
//ZAN05W01 DD DSN=OVT-SUMMARY.DAT,DISP=(NEW,PASS)
ZANJ025 — 残業統計DB更新
//ZANJ025 JOB (ACCT),'残業統計DB更新',CLASS=A
//*
//*--- パラメータ定義 ---
//SETPARM SET YEARMONTH=202605
//*
//*=====================================================================
//* STEP025: DB更新(SORT不要)
//*=====================================================================
//STEP025 EXEC PGM=ZAN06UPD,PARM='YEARMONTH=&YEARMONTH'
//ZAN06R01 DD DSN=OVT-SUMMARY.DAT,DISP=(OLD,DELETE)
//ZAN06R02 DD DSN=OVT-DBCLEAN.DAT,DISP=(OLD,DELETE)
//ZAN06W01 DD DSN=ERROR-LOG.DAT,DISP=(NEW,PASS)
実行順序
BサブシステムのJOBは、AサブシステムのKINJ020(打刻チェック)出力を入力とする。 そのためJCL起動時は以下の順序を保証すること。
- Aサブシステム KINJ020(KIN03PCK)→ EDITED-PUNCH生成
- Bサブシステム ZANJ010〜ZANJ025(必要時順次実行)
KINJ030(日別計算)は各打刻確定後であればいつでも実行可能で、ZANJ系列との依存関係はない。
プログラム詳細
STEP010: ZAN01CHK(残業申請振分処理) — 振り分け
| 項目 | 内容 |
|---|---|
| プログラム名称 | 残業申請振分処理 |
| PGMパターン | 振り分け |
| SORT前処理 | 不要 |
| 入力ファイル | OVT-APPLY(80B / CSV形式) |
| 出力ファイル | OVT-VALID(80B)/ OVT-CANCEL(80B)/ ERROR-LOG(VB) |
| 件数変化 | N件 → 有効M件 + 取消K件 + 異常L件(M+K+L=N) |
| 使用共通関数 | SUB01DAT(運用日付), SUB02MSG(メッセージ), SUB03END(ABEND), SUB04CHK(項目チェック) |
入力CSVレコード例: A001,EMP001,20260610,1800,2000,0
機能:
- READ OVT-APPLY
- UNSTRING でCSVレコードを各項目に分解
- UNSTRING TALLYING でカンマ区切り数をカウント(項目数妥当性確認)
- EVALUATE でステータスを判定
- 0 or 1 → 有効申請として次へ
- 9 → OVT-CANCEL に書出し
- その他 → エラーとして処理
- SUB04CHK で日付(DATE8)・時刻(TIME4)・社員番号(NUMERIC)を検証
- 加班時間計算(時刻はHHMM形式のため分単位に変換してから減算)
開始分 = (開始時刻 / 100) * 60 + (開始時刻 - (開始時刻 / 100) * 100) 終了分 = (終了時刻 / 100) * 60 + (終了時刻 - (終了時刻 / 100) * 100) 加班時間(分) = 終了分 - 開始分- 開始時刻 < DINNER-START(1830) → エラー(18:30以前は食事時間のため加班不可)
- 加班時間 < 30分 → エラー(0.5h未満)
- 開始時刻 ≧ 終了時刻 → エラー
- 通過 → OVT-VALID に書出し
- エラー → 該当レコードをERROR-LOG用01レコードにMOVEしてWRITE出力
新規カバレッジ構文:
| 構文 | 用途 |
|---|---|
| UNSTRING | CSVレコードの項目分解(TALLYING句で区切り数カウント) |
| STRING | エラーレコード編集 |
STEP012: ZAN02CHK(時間帯重複チェック処理) — 項目チェック
| 項目 | 内容 |
|---|---|
| プログラム名称 | 時間帯重複チェック処理 |
| PGMパターン | 項目チェック |
| SORT前処理 | OVT-VALID → 社員番号+日付+開始時刻昇順 |
| 入力ファイル | OVT-VSORT(80B) |
| 出力ファイル | OVT-NODUP(80B)/ ERROR-LOG(VB) |
| 件数変化 | M件 → 通過K件 + 重複エラー(M-K)件 |
| 使用共通関数 | SUB01DAT(運用日付), SUB02MSG(メッセージ), SUB03END(ABEND) |
機能:
OVT-VSORT は既に社員番号+日付+開始時刻でソート済。順次READしながら直前レコードと比較する。
- READ OVT-VSORT → 現レコード取得成功
- 直前レコードと同一社員番号+日付 かつ 前終了時刻 > 現開始時刻 の場合 → 時間帯重複
- 境界接続(前終了時刻 = 現開始時刻)は重複としない
- 重複 → ERROR-LOG へ
- 重複なし → OVT-NODUP へ書出し
- 社員番号 or 日付が変わったら直前レコードをリセット
- SET で重複有無フラグを設定
新規カバレッジ構文:
| 構文 | 用途 |
|---|---|
| SET | 重複有無フラグ設定 |
| CONTINUE | リセット時の空処理 |
STEP013: ZAN03CHK(打刻時間照合処理) — マッチング(N:1)
| 項目 | 内容 |
|---|---|
| プログラム名称 | 打刻時間照合処理 |
| PGMパターン | マッチング(N:1) |
| SORT前処理 | EDITED-PUNCH → 社員番号+日付昇順 |
| 入力ファイル | OVT-NODUP(80B)/ PUNCH-SORTED(80B) |
| 出力ファイル | OVT-CHECKED(80B)/ ERROR-LOG(VB) |
| 件数変化 | K件 → 通過P件 + エラー(K-P)件 |
| 使用共通関数 | SUB02MSG(メッセージ) |
機能:
Step1:打刻時間内チェック
OVT-NODUP と PUNCH-SORTED を社員番号+日付で突合(共にソート済のため順次READで処理可)。
- READ OVT-NODUP → 現レコード
- 該当社員番号+日付の打刻レコードを PUNCH-SORTED から READ
- 打刻データあり かつ 以下を両方満たすことを確認:
- 申請開始時刻 ≧ 出勤時刻
- 申請終了時刻 ≦ 退勤時刻
- 範囲外 または 打刻データなし → ERROR-LOG
Step2:曜日判定
SEARCH ALL で休日マスタファイル(WORKING-STORAGE)を検索し、申請日の種別を判定。 Aサブシステムと同一の休日定義に従う(HOLIDAY-FILEファイル相当のデータを保持)。
休日ファイル初期化手順
初期処理(1000ITTSOR)でHOLIDAY-FILEを全件READし、WORKING-STORAGEのHOLIDAY-TABLEに格納する。
* 休日データ取得(ファイル読込み)
OPEN INPUT HOLIDAY-FILE
READ HOLIDAY-FILE
... 逐次処理
CLOSE HOLIDAY-FILE
01 HOLIDAY-TABLE.
05 HOLIDAY-CNT PIC 9(004).
05 HOLIDAY-DATA OCCURS 1 TO 366 TIMES
DEPENDING ON HOLIDAY-CNT
INDEXED BY HD-IDX.
10 HD-DATE PIC 9(008).
10 HD-TYPE PIC X(001).
88 HD-HOLIDAY VALUE 'H'.
SET HD-IDX TO 1
SEARCH ALL HOLIDAY-DATA
AT END
SET OVT-TYPE TO 'W'
WHEN HD-DATE(HD-IDX) = APPL-DATE
IF HD-HOLIDAY(HD-IDX)
SET OVT-TYPE TO 'H'
ELSE
SET OVT-TYPE TO 'W'
END-IF
END-SEARCH
- HOLIDAY-FILE該当 → OVT-TYPE='H'
- 該当なし → OVT-TYPE='W'
MOVE で OVT-TYPE を設定。
全通過レコードは OVT-TYPE を付加して OVT-CHECKED に書出し。
新規カバレッジ構文:
| 構文 | 用途 |
|---|---|
| SEARCH ALL | 休日マスタテーブル二分探索 |
| SET | テーブル添字操作 |
STEP015: ZAN04MAT(取消マッチング処理) — マッチング1:1
| 項目 | 内容 |
|---|---|
| プログラム名称 | 取消マッチング処理 |
| PGMパターン | マッチング(1:1) |
| SORT前処理 | OVT-CHECKED → 申請番号昇順 |
| OVT-CANCEL → 申請番号昇順 | |
| 入力ファイル | OVT-SORTED(80B)/ OVT-CSORT(80B) |
| 出力ファイル | OVT-MATCHED(80B)/ OVT-DBCLEAN(80B)/ ERROR-LOG(VB) |
| 件数変化 | 有効P件 + 取消R件 → 通過Q件 + 消滅S件 + DB削除T件(P=Q+S, R=S+T) |
| 使用共通関数 | SUB01DAT(運用日付), SUB02MSG(メッセージ), SUB03END(ABEND) |
機能:
キー=申請番号(APPL-ID) で OVT-SORTED(有効申請)と OVT-CSORT(取消)をマッチング1:1。
マッチング制御の分岐:
| 条件 | 結果 | 処理 |
|---|---|---|
| SORTED.APPL-ID < CSORT.APPL-ID | 申請のみ(取消なし) | OVT-MATCHEDへ |
| SORTED.APPL-ID = CSORT.APPL-ID | 両方あり(取消済) | 消滅(出力なし)。ただし監査のため取消情報をERROR-LOGに記録(エラー区分=03、取消申請番号+原本データ) |
| SORTED.APPL-ID > CSORT.APPL-ID | 取消のみ(既DB登録済) | OVT-DBCLEANへ |
同一申請番号グループ内の出力順に 処理番号(OA-PROC-SEQ) を1から付与する。
STRING で申請情報を編集して OVT-MATCHED に書出す。
新規カバレッジ構文:
| 構文 | 用途 |
|---|---|
| STRING | 申請情報編集出力 |
STEP020: ZAN05CAL(残業時間集計処理) — キーブレイク集計
| 項目 | 内容 |
|---|---|
| プログラム名称 | 残業時間集計処理 |
| PGMパターン | キーブレイク(集計) |
| SORT前処理 | OVT-MATCHED → 申請番号+処理番号昇順 |
| 入力ファイル | OVT-SORTED2(80B) |
| 出力ファイル | OVT-SUMMARY(80B) |
| 件数変化 | Q件 → 申請番号ユニーク数(L件、L≦Q) |
| 使用共通関数 | SUB01DAT(運用日付), SUB02MSG(メッセージ), SUB03END(ABEND), SUB05TIM(時刻丸め) |
機能:
Step1:キーブレイク制御
同一申請番号内に複数レコード(例:申請(0) + 承認済(1))がある場合、グループ内の最終レコードを集約結果として採用する。
入力(申請番号+処理番号昇順):
A001,EMP01,6/10,1800,2000,0 ← 申請(処理番号1)
A001,EMP01,6/10,1800,2000,1 ← 承認済(処理番号2 → 最新)
集約結果: 承認済(1) を採用、申請(0) は捨てる
- READ → 申請番号が変わるまで読み進める
- ブレイク(申請番号切替)時に、直前に保持していたレコードを出力
- グループ内の途中レコードは CONTINUE で読み飛ばす
- SET で集約結果の有無フラグを設定
Step2:加班時間計算
終了時刻 - 開始時刻 を分数で計算 → DIVIDE で時間に変換。
DIVIDE 分 BY 60 GIVING 時間 REMAINDER 剰余
SUB05TIM(mode 2:0.1h単位切捨) を呼び出して丸め処理。加班の丸めは0.1h単位切捨が正となる。
COMPUTE ROUNDED ON SIZE ERROR で内部計算のエラー処理。
COMPUTE WRK-OVT-HOURS ROUNDED = WRK-MINUTES / 60
ON SIZE ERROR
CONTINUE
MOVE ZERO TO WRK-OVT-HOURS
END-COMPUTE
新規カバレッジ構文:
| 構文 | 用途 |
|---|---|
| COMPUTE ROUNDED ON SIZE ERROR | 丸め計算+エラー処理 |
| DIVIDE | 分→時間変換 |
| CONTINUE | キーブレイク制御の空分岐 |
| SET | 集計結果フラグ設定 |
| ACCEPT FROM DATE | 処理日付取得 |
STEP025: ZAN06UPD(残業統計DB更新処理) — DB更新
| 項目 | 内容 |
|---|---|
| プログラム名称 | 残業統計DB更新処理 |
| PGMパターン | DB更新 |
| SORT前処理 | 不要 |
| 入力ファイル | OVT-SUMMARY(80B)/ OVT-DBCLEAN(80B) |
| 出力ファイル | OVERTIME-DB(DB2)/ ERROR-LOG(VB) |
| 使用共通関数 | SUB01DAT(運用日付), SUB02MSG(メッセージ), SUB03END(ABEND) |
機能:
全DB操作は埋め込みSQL(EXEC SQL)で直接記述する。
処理1:OVT-SUMMARY → DB登録
EXEC SQL でDB2にINSERT/UPDATEを発行する。
EXEC SQL
INSERT INTO OVT-APPLICATIONS
(APPL-ID, EMP-ID, APPL-DATE, OVT-TYPE,
START-TIME, END-TIME, OVT-HOURS, STATUS)
VALUES
(:WRK-APPL-ID, :WRK-EMP-ID, :WRK-APPL-DATE,
:WRK-OVT-TYPE, :WRK-START-TIME, :WRK-END-TIME,
:WRK-OVT-HOURS, :WRK-STATUS)
END-EXEC.
IF SQLCODE NOT = 0
* 同一APPL-ID存在 → UPDATEに変更
EXEC SQL
UPDATE OVT-APPLICATIONS SET
STATUS = :WRK-STATUS,
UPDATED-AT = CURRENT TIMESTAMP
WHERE APPL-ID = :WRK-APPL-ID
END-EXEC
END-IF.
OVT-MONTHLY のUPSERTも同様。
EXEC SQL
SELECT OVT-HOURS, OVT-COUNT
INTO :DB-OVT-HOURS, :DB-OVT-COUNT
FROM OVT-MONTHLY
WHERE EMP-ID = :WRK-EMP-ID
AND YEAR-MONTH = :WRK-YEAR-MONTH
AND OVT-TYPE = :WRK-OVT-TYPE
END-EXEC.
IF SQLCODE = 0
* UPDATE(加算)
EXEC SQL
UPDATE OVT-MONTHLY SET
OVT-HOURS = OVT-HOURS + :WRK-OVT-HOURS,
OVT-COUNT = OVT-COUNT + 1,
UPDATED-AT = CURRENT TIMESTAMP
WHERE EMP-ID = :WRK-EMP-ID
AND YEAR-MONTH = :WRK-YEAR-MONTH
AND OVT-TYPE = :WRK-OVT-TYPE
END-EXEC
ELSE
* INSERT(新規)
EXEC SQL
INSERT INTO OVT-MONTHLY
(EMP-ID, YEAR-MONTH, OVT-TYPE,
OVT-HOURS, OVT-COUNT, UPDATED-AT)
VALUES
(:WRK-EMP-ID, :WRK-YEAR-MONTH, :WRK-OVT-TYPE,
:WRK-OVT-HOURS, 1, CURRENT TIMESTAMP)
END-EXEC
END-IF.
処理2:OVT-DBCLEAN → DB取消
EXEC SQL
UPDATE OVT-APPLICATIONS SET
STATUS = '9',
UPDATED-AT = CURRENT TIMESTAMP
WHERE APPL-ID = :WRK-APPL-ID
END-EXEC.
IF SQLCODE NOT = 0
該当なし → ERROR-LOG に書出し
PERFORM 9999ABDSOR
END-IF.
OVT-MONTHLY の減算UPDATE:
EXEC SQL
UPDATE OVT-MONTHLY SET
OVT-HOURS = OVT-HOURS - :WRK-OVT-HOURS,
OVT-COUNT = OVT-COUNT - 1,
UPDATED-AT = CURRENT TIMESTAMP
WHERE EMP-ID = :WRK-EMP-ID
AND YEAR-MONTH = :WRK-YEAR-MONTH
AND OVT-TYPE = :WRK-OVT-TYPE
END-EXEC.
IF SQLCODE NOT = 0
* OVT-MONTHLYレコード不存在 → データ不整合の可能性
該当エラー → ERROR-LOG に書出し
PERFORM 9999ABDSOR
END-IF.
注意: OVT-MONTHLY減算UPDATEの失敗時は、OVT-MONTHLYに対応レコードが存在しないことを意味する。 ファイルとDBの不整合としてエラーログに記録した上でABENDさせる。
SQLCODE でDB操作の成否を確認し、異常時は ERROR-LOG に出力。
新規カバレッジ構文:
| 構文 | 用途 |
|---|---|
| EXEC SQL | DB2埋め込みSQLによるDB操作 |
| IF | SQLCODE判定による分岐 |
| PERFORM VARYING | 月バリデーションループ(1〜12月) |
| PERFORM TEST AFTER | OVT-MONTHLY減算リトライ制御 |
| MULTIPLY | 時間→分変換(MULTIPLY BY 60 GIVING) |
| SUBTRACT | 残容量検証(SUBTRACT FROM GIVING) |
レコード構成
OVT-VALID / OVT-CANCEL / OVT-NODUP / OVT-CHECKED(80B)
| # | 項目 | 名称 | 開始 | 長さ | 属性 | 備考 |
|---|---|---|---|---|---|---|
| 1 | 申請番号 | OA-APPL-ID | 1 | 8 | X(8) | |
| 2 | 社員番号 | OA-EMP-ID | 9 | 8 | 9(8) | |
| 3 | 申請日 | OA-APPL-DATE | 17 | 8 | 9(8) | YYYYMMDD |
| 4 | 開始時刻 | OA-START-TIME | 25 | 4 | 9(4) | HHMM |
| 5 | 終了時刻 | OA-END-TIME | 29 | 4 | 9(4) | HHMM |
| 6 | ステータス | OA-STATUS | 33 | 1 | X(1) | 0/1/9 |
| 7 | OVT-TYPE | OA-OVT-TYPE | 34 | 1 | X(1) | W/H(OVT-CHECKED以降のみ有効) |
| 8 | 予備 | OA-FILLER | 35 | 46 | X(46) |
OVT-MATCHED(80B)
| # | 項目 | 名称 | 開始 | 長さ | 属性 | 備考 |
|---|---|---|---|---|---|---|
| 1 | 申請番号 | OA-APPL-ID | 1 | 8 | X(8) | |
| 2 | 社員番号 | OA-EMP-ID | 9 | 8 | 9(8) | |
| 3 | 申請日 | OA-APPL-DATE | 17 | 8 | 9(8) | YYYYMMDD |
| 4 | 開始時刻 | OA-START-TIME | 25 | 4 | 9(4) | HHMM |
| 5 | 終了時刻 | OA-END-TIME | 29 | 4 | 9(4) | HHMM |
| 6 | ステータス | OA-STATUS | 33 | 1 | X(1) | 0/1 |
| 7 | OVT-TYPE | OA-OVT-TYPE | 34 | 1 | X(1) | W/H |
| 8 | 処理番号 | OA-PROC-SEQ | 35 | 2 | 9(2) | 同申請内連番 |
| 9 | 予備 | OA-FILLER | 37 | 44 | X(44) |
社員名・部署コードは DB2(OVT-APPLICATIONSテーブル)側で保持する。
OVT-SUMMARY(80B)
| # | 項目 | 名称 | 開始 | 長さ | 属性 | 備考 |
|---|---|---|---|---|---|---|
| 1 | 申請番号 | OS-APPL-ID | 1 | 8 | X(8) | |
| 2 | 社員番号 | OS-EMP-ID | 9 | 8 | 9(8) | |
| 3 | 申請日 | OS-APPL-DATE | 17 | 8 | 9(8) | YYYYMMDD |
| 4 | 開始時刻 | OS-START-TIME | 25 | 4 | 9(4) | HHMM |
| 5 | 終了時刻 | OS-END-TIME | 29 | 4 | 9(4) | HHMM |
| 6 | 加班時間 | OS-OVT-HOURS | 33 | 5 | 9(4)V9(1) | SUB05TIM丸め後 |
| 7 | OVT-TYPE | OS-OVT-TYPE | 38 | 1 | X(1) | W/H |
| 8 | 予備 | OS-FILLER | 39 | 42 | X(42) |
OVT-DBCLEAN(80B)
| # | 項目 | 名称 | 開始 | 長さ | 属性 |
|---|---|---|---|---|---|
| 1 | 申請番号 | OD-APPL-ID | 1 | 8 | X(8) |
| 2 | 予備 | OD-FILLER | 9 | 72 | X(72) |
新規COBOL構文カバレッジ一覧(14種)
| # | 構文 | ZAN01CHK | ZAN02CHK | ZAN03CHK | ZAN04MAT | ZAN05CAL | ZAN06UPD |
|---|---|---|---|---|---|---|---|
| 1 | UNSTRING | ● | |||||
| 2 | STRING | ● | ● | ||||
| 3 | SEARCH ALL | ● | |||||
| 4 | SET | ● | ● | ● | |||
| 5 | COMPUTE ROUNDED ON SIZE ERROR | ● | |||||
| 6 | DIVIDE | ● | ● | ||||
| 7 | CONTINUE | ● | ● | ||||
| 8 | ACCEPT FROM DATE | ● | |||||
| 9 | EXEC SQL(INSERT/UPDATE/SELECT/COMMIT/ROLLBACK) | ● | |||||
| 10 | IF(SQLCODE分岐) | ● | |||||
| 11 | PERFORM VARYING | ● | |||||
| 12 | PERFORM TEST AFTER | ● | |||||
| 13 | MULTIPLY | ● | |||||
| 14 | SUBTRACT | ● |
丸めルール
| 条件 | ルール |
|---|---|
| 加班開始時刻 < DINNER-START(1830) | エラー(申請不可、食事時間のため) |
| 加班時間 < 30分 | エラー(申請不可) |
| 加班時間 ≧ 30分 かつ < 0.5h換算 | 0.5hに切上 |
| 加班時間 ≧ 0.5h | 0.1h単位切捨(SUB05TIM mode 2) |
例:0.5h→0.5, 0.7h→0.7, 1.55h→1.5(切捨のため1.5、切上なら1.6)