Files
cobol-tna-system/基本設計書/01_勤怠休暇管理システム_設計書(サブシステムA).md

37 KiB
Raw Permalink Blame History

勤怠休暇管理システム 設計書(サブシステムA)

概要

休暇申請データと打刻データを処理し、日別勤怠記録(DAILY_RECORDS)および月次統計(MONTHLY_ABSENCE)を生成する。

9本のCOBOLプログラムで構成される。

拠点間SORTやCSV変換などはCOBOLではなくJCL SORTで処理する方針とし、COBOLプログラムは純粋なビジネスロジックに専念する。

設計方針(カバレッジ拡大)

本設計は、サブシステムBで未カバーのプログラムタイプ・ステートメントを積極的にカバーするため、以下の方針でプログラム分割・構文選定を行う。

項目 Bの状況 Aで狙う追加カバレッジ
プログラムタイプ 6パターン◎ 未カバー5パターン + SYSIN(P28) を追加
ステートメント 主要構文は網羅済 SEARCH非ALL, DELETE, EVALUATE(4分岐), PERFORM THRU, WRITE FROM, WRITE AFTER ADVANCING, MULTIPLY, SUBTRACT, ACCEPT, DISPLAY, INSPECT
DB操作 INSERT/UPDATE/SELECT/COMMIT/ROLLBACK 上記に加え DELETE FROM を追加

システム定数

全てのプログラムで共通の前提値。COBOLのCNS-定数として保持する(DBは持たない)。

定数 説明
WORK-START 0900 所定労働開始時刻
WORK-END 1800 所定労働終了時刻
LUNCH-START 1200 ランチ開始時刻
LUNCH-END 1300 ランチ終了時刻
DAILY-HOURS 8.0 1日の所定労働時間(9h実働 − 1hランチ)

休暇種別

コード 名称 給与への影響 備考
01 年休(年假) 控除なし 有給年次休暇
02 事假(事假) 全額控除 私事欠勤
03 因公特批假(因公特批假) 控除なし 公務特認欠勤
04 病欠(病欠) 一部控除 控除率はSICK_LEAVE_RATEテーブル参照

休暇種別は上記4種で固定。勤怠ルールはこの4種を基準とする。


DBテーブル一覧

全テーブルはDB2で管理する。COBOLからは埋め込みSQL(EXEC SQL)で直接アクセスする。

1. EMP_MASTER(社員マスタ)

全社員の基本情報を保持する。サブシステムAでは参照のみ。

No カラム名 長さ NULL PK 備考
1 EMP_ID CHAR 8 NOT NULL 社員番号
2 DEPT_ID CHAR 4 NOT NULL 部署ID
3 EMP_NAME VARCHAR 50 NOT NULL 氏名
4 STATUS CHAR 1 NOT NULL '1'=在籍, '9'=退職

2. ABSENCE_SUMMARY(欠勤集計中間ファイル)

サブシステムA→Cの連携用。KIN08DBUが月次集計後に出力する。

No カラム名 長さ NULL PK 備考
1 EMP_ID CHAR 8 NOT NULL 社員番号
2 YEAR_MONTH CHAR 6 NOT NULL YYYYMM
3 ANNUAL_LEAVE_H DECIMAL 6,1 NOT NULL 年休使用合計
4 PERSONAL_LEAVE_H DECIMAL 6,1 NOT NULL 事假合計
5 OFFICIAL_LEAVE_H DECIMAL 6,1 NOT NULL 因公特批假合計
6 SICK_LEAVE_H DECIMAL 6,1 NOT NULL 病欠合計
7 UNAPPROVED_ABSENT_H DECIMAL 6,1 NOT NULL 未申請欠勤合計

3. HOLIDAY_CALENDAR(休日カレンダー)

祝日(曜日判定で休日にならない日)のみを列挙する。 土曜・日曜は曜日判定で休日とするため、このテーブルには含めない。

No カラム名 長さ NULL PK 備考
1 HOLIDAY_DATE CHAR 8 NOT NULL YYYYMMDD
2 DESCRIPTION VARCHAR 50 OK 任意(例:「建国記念の日」)

出勤日判定ロジック(全PGM共通):

1. HOLIDAY_CALENDARに日付が存在する → 休日
2. 曜日が土曜(6)または日曜(INTEGER-OF-DATE MOD 7 = 0) → 休日
3. 上記以外 → 出勤日(WORK-START=0900, WORK-END=1800

4. SICK_LEAVE_RATE(病欠控除率)

全社員共通の病欠控除率を保持する。

No カラム名 長さ NULL PK 備考
1 LEAVE_TYPE CHAR 2 NOT NULL '04'固定
2 DEDUCTION_RATE DECIMAL 3,2 NOT NULL 例:0.5050%控除)

5. LEAVE_RECORDS(休暇申請記録)

休暇申請の生データを保持する。取消はDELETE FROMで行い、レコードを物理削除する。 期間は開始日〜終了日で表現され、日別展開は行わない。

No カラム名 長さ NULL PK 備考
1 APPLICATION_ID INTEGER NOT NULL 自動採番
2 EMP_ID CHAR 8 NOT NULL 社員番号
3 LEAVE_TYPE CHAR 2 NOT NULL '01'〜'04'
4 START_DATE CHAR 8 NOT NULL YYYYMMDD(出勤日)
5 START_TIME CHAR 4 NOT NULL HHMM(所定労働時間内)
6 END_DATE CHAR 8 NOT NULL YYYYMMDD(出勤日)
7 END_TIME CHAR 4 NOT NULL HHMM(所定労働時間内)
8 STATUS CHAR 1 NOT NULL '1'=有効, '9'=取消

6. DAILY_RECORDS(日別勤怠記録)

1社員1日の勤怠情報。出勤日のみレコードが存在する。 打刻がない日でも休暇または未申請欠勤の情報を持つ。

No カラム名 長さ NULL PK 備考
1 EMP_ID CHAR 8 NOT NULL
2 TARGET_DATE CHAR 8 NOT NULL YYYYMMDD
3 TIME_IN CHAR 4 NOT NULL 出勤時刻、'0000'=打刻なし
4 TIME_OUT CHAR 4 NOT NULL 退勤時刻、'0000'=打刻なし
5 ANNUAL_LEAVE_H DECIMAL 6,1 NOT NULL 年休使用時間
6 PERSONAL_LEAVE_H DECIMAL 6,1 NOT NULL 事假時間
7 OFFICIAL_LEAVE_H DECIMAL 6,1 NOT NULL 因公特批假時間
8 SICK_LEAVE_H DECIMAL 6,1 NOT NULL 病欠時間
9 UNAPPROVED_ABSENT_H DECIMAL 6,1 NOT NULL 未申請欠勤時間
10 UPDATED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP

7. MONTHLY_ABSENCE(月次統計)

DAILY_RECORDSを月次で集計したサマリ。

No カラム名 長さ NULL PK 備考
1 EMP_ID CHAR 8 NOT NULL
2 YEAR_MONTH CHAR 6 NOT NULL YYYYMM
3 ANNUAL_LEAVE_H DECIMAL 6,1 NOT NULL 年休使用合計
4 PERSONAL_LEAVE_H DECIMAL 6,1 NOT NULL 事假合計
5 OFFICIAL_LEAVE_H DECIMAL 6,1 NOT NULL 因公特批假合計
6 SICK_LEAVE_H DECIMAL 6,1 NOT NULL 病欠合計
7 UNAPPROVED_ABSENT_H DECIMAL 6,1 NOT NULL 未申請欠勤合計
8 UPDATED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP

ファイル一覧

# ファイル名 DD名 編成 RECM サイズ 生成元 消費先 備考
1 RAW-LEAVE KIN01R01 SEQUENTIAL FB 80 外部システム KIN01INP 休暇申請CSV
2 WORK-LEAVE KIN01W01 SEQUENTIAL FB 80 KIN01INP SORT→KIN02UPD 検証済休暇申請(中間)
3 RAW-PUNCH KIN04R01 SEQUENTIAL FB 80 打刻システム KIN04CHK 生打刻データ
4 EDITED-PUNCH KIN04W01 SEQUENTIAL FB 80 KIN04CHK KIN05MAT/B-サブシステム 項目チェック通過打刻
5 LEAVE-DAILY KIN02W01 SEQUENTIAL FB 80 KIN03EXP KIN05MAT / KIN07DAI 日別展開済休暇
6 KIN-LEAVE KIN05W01 SEQUENTIAL FB 160 KIN05MAT KIN07DAI 打刻+休暇照合結果
7 WORK-DAY-FILE KIN06W01 SEQUENTIAL FB 80 KIN06CLD KIN07DAI 出勤日カレンダー
8 DAILY-RECORD KIN07W01 SEQUENTIAL FB 200 KIN07DAI KIN08DBU 日別勤怠計算結果
9 ERROR-LOG KIN01E01 SEQUENTIAL VB 200 KIN01INP / KIN04CHK エラーレコード退避
10 ABSENCE-SUMMARY KIN08W01 SEQUENTIAL FB 80 KIN08DBU C-サブシステム 月次欠勤集計(Cへ連携)
11 CSV-OUTPUT KIN09W01 SEQUENTIAL FB 200 KIN09CSV 社員確認用CSV

処理フロー

休暇申請(RAW-LEAVE / CSV)
  │
  │ [KINJ010] KIN01INP — 休暇申請CSV取込・検証処理
  │   UNSTRINGでCSV分解 → IF/ELSE chain(新規/取消/変更)
  │   SEARCH(非ALL)で休暇種別テーブル検索
  │   SUB04CHKで日付/時刻/数値チェック
  ├──正常 → WORK-LEAVE-file
  └──異常 → ERROR-LOG
  │
  │ [KINJ011] SORT(WORK-LEAVE → APPLICATION_ID昇順)
  │
  │ [KINJ012] KIN02UPD — 休暇申請DB更新処理
  │   新規: EXEC SQL INSERT
  │   取消: EXEC SQL DELETE FROM     ← 新カバレッジ
  │   変更: EXEC SQL DELETE + INSERT
  │ → DB:LEAVE_RECORDS
  │
  │ [KINJ015] KIN03EXP — 休暇日別展開処理
  │   DB(SELECT/CURSOR) → PERFORM THRU(日付範囲)
  │   キーブレイク(社員番号切替) → HEADER処理
  │   休日除外 → CONTINUE
  │ → LEAVE-DAILY-file
  ▼
LEAVE-DAILY-file(日別休暇)
  │

打刻生データ(RAW-PUNCH / CSV)
  │
  │ [KINJ020] KIN04CHK — 打刻項目チェック処理
  │   UNSTRING + SUB04CHK(日付/時刻/数値)
  │   IF多重ネスト(必須→日付→時刻→数値の4段階)
  ├──正常 → EDITED-PUNCH
  └──異常 → ERROR-LOG
  │
  │ [KINJ022] SORT(EDITED-PUNCH → 社員番号+日付昇順)
  │
  │ [KINJ025] KIN05MAT — 打刻休暇照合処理
  │   マッチング(1:N) EDITED-PUNCH × LEAVE-DAILY
  │   休暇種別優先順位(01/02連動, 03/04独立)
  │ → KIN-LEAVE
  ▼
KIN-LEAVE(照合結果)
  │
  │ [KINJ030] KIN06CLD — 出勤日カレンダー生成処理
  │   DB SELECT(CURSOR) + PERFORM VARYING
  │   SEARCH ALL(休日判定) / WRITE FROM  ← 新カバレッジ
  │ → WORK-DAY-FILE
  ▼
WORK-DAY-FILE(出勤日カレンダー)
  │
  │ [KINJ033] KIN07DAI — 日別勤怠計算処理
  │   マッチング(1:N) + EVALUATE分岐  ← MULTIPLY/SUBTRACT新カバレッジ
  │   WORK-DAY(主駆動) × KIN-LEAVE(N側)
  │   4パターン(A/B/C/D)をEVALUATE + PERFORMで分岐
  │   休暇時間計算(ランチ除外) + SUB05TIM丸め(0.1h切上)
  │ → DAILY-RECORD
  ▼
DAILY-RECORD(日別計算結果)
  │
  │ [KINJ036] KIN08DBU — 勤怠DB更新処理
  │   DAILY-RECORD → DAILY_RECORDS INSERT
  │   社員別月次集計 → MONTHLY_ABSENCE UPSERT
  │   ABSENCE_SUMMARYファイル出力(Cへ連携)
  ▼
DB: DAILY_RECORDS + DB: MONTHLY_ABSENCE
  │ ABSENCE-SUMMARY-file
  ▼
C:給与計算システム(KYU01CAL
  │
  │ [KINJ040] KIN09CSV — 勤怠CSV出力処理
  │   DB SELECT → STRING → WRITE AFTER ADVANCING  ← 新カバレッジ
  ▼
CSV(社員確認用)

プログラム詳細

STEP010: KIN01INP — 休暇申請CSV取込・検証処理

項目 内容
PGMパターン 振り分け
JCL前処理 なし
入力 RAW-LEAVE80B / CSV形式)
出力 WORK-LEAVE80B/ ERROR-LOGVB

機能:

  1. READ RAW-LEAVE → CSVレコード1行を取得
  2. UNSTRING でCSV分解(申請番号,社員番号,日付,開始時刻,終了時刻,休暇種別,ステータス)+ TALLYING でフィールド数カウント(項目数チェック)
  3. SEARCH(非ALL) でWORKING-STORAGE上の休暇種別テーブルを線形探索 → 該当種別の存在確認 ← 新カバレッジ
  4. IF/ELSE chain でステータス判定(新規/取消/変更) ← 新カバレッジ(振り分けIF文)
  5. SUB04CHKで日付・時刻・数値の各項目検証
    • IF多重ネスト:必須チェック → 日付形式 → 時刻範囲 → 数値
  6. 通過 → WORK-LEAVEに出力(検証済みレコード)
  7. エラー → ERROR-LOGに出力

新規カバレッジ構文:

構文 用途
UNSTRING CSVレコードの項目分解
INSPECT TALLYING カンマ区切り数カウント
SEARCH(非ALL) 休暇種別テーブル線形探索 ← 新規
IF/ELSE chain ステータス別の振り分け処理(EVALUATE不使用)

STEP020: KIN02UPD — 休暇申請DB更新処理

項目 内容
PGMパターン DB更新
JCL前処理 WORK-LEAVE → APPLICATION_ID昇順SORT
入力 WORK-LEAVE80B
出力 LEAVE_RECORDSDB2

機能:

  1. READ WORK-LEAVE → 検証済みレコード1件
  2. レコード種別に応じたDB操作:
    • 新規申請(ステータス='1'EXEC SQL INSERT
    • 取消申請(ステータス='9'EXEC SQL DELETE FROM WHERE APPLICATION_ID = :id ← 新カバレッジ
    • 変更申請(ステータス='1', APPLICATION_ID指定済) → DELETE + INSERT
  3. IF SQLCODE NOT = 0 → エラーハンドリング

新規カバレッジ構文:

構文 用途
EXEC SQL INSERT DB登録
EXEC SQL DELETE FROM DB削除(物理削除による取消)← 新規
IF SQLCODE判定

STEP030: KIN03EXP — 休暇日別展開処理

項目 内容
PGMパターン キーブレイク
JCL前処理 なし
入力 LEAVE_RECORDSDB2 SELECT / CURSOR
出力 LEAVE-DAILY-file80B

機能:

  1. LEAVE_RECORDSからSTATUS='1'(有効)の全レコードをCURSOR SELECTする(ORDER BY EMP_ID, START_DATE)。
  2. PERFORM THRU で処理範囲を指定 ← 新カバレッジ
    • 2100-PROCESS-EMP THRU 2100-PROCESS-EMP-EXIT1社員分の処理
    • 2200-EXPAND-DATE THRU 2200-EXPAND-DATE-EXIT:日付展開処理
  3. キーブレイク(社員番号切替)時に社員別小計を出力 ← キーブレイク(その他)
  4. 各申請の開始日〜終了日をループ(PERFORM VARYING):
    • 休日判定:HOLIDAY_CALENDARに存在 or 土日 → CONTINUE でスキップ
    • 出勤日 → LEAVE-DAILY-fileに出力

新規カバレッジ構文:

構文 用途
PERFORM THRU 段落範囲指定による構造化処理 ← 新規
PERFORM UNTIL 日付ループ(開始日〜終了日)
CONTINUE 休日スキップ時の空処理
EXEC SQL SELECT(CURSOR) DB読込(FETCH
SET キーブレイクフラグ操作

STEP040: KIN04CHK — 打刻項目チェック処理

項目 内容
PGMパターン 項目チェック(重複なし)
JCL前処理 なし
入力 RAW-PUNCH80B / CSV形式)
出力 EDITED-PUNCH80B/ ERROR-LOGVB

機能:

  1. READ RAW-PUNCH → CSVレコード
  2. UNSTRING で分解
  3. IF多重ネスト で4段階チェック:
    IF 社員番号 NOT = SPACE  THEN
        IF 日付が有効形式 THEN
            IF 時刻が有効範囲 THEN
                IF 出勤 < 退勤 THEN
                    正常出力
                ELSE → エラー
            ELSE → エラー
        ELSE → エラー
    ELSE → エラー
    END-IF
    
  4. 各チェックは SUB04CHK を呼出
  5. 正常 → EDITED-PUNCHに出力(WRITE FROM 使用)
  6. 異常 → ERROR-LOGに出力(STRING で編集)

新規カバレッジ構文:

構文 用途
UNSTRING CSV分解
IF多重ネスト(THEN句) 必須→日付→時刻→数値の4段階チェック ← 新規(深度)
WRITE FROM 出力レコードの一括書出
STRING エラーメッセージ編集

STEP050: KIN05MAT — 打刻休暇照合処理

項目 内容
PGMパターン マッチング(1:N)
JCL前処理 EDITED-PUNCH → 社員番号+日付昇順SORTKINJ022
入力R01 EDITED-PUNCH80B、打刻側)
入力R02 LEAVE-DAILY-file80B、休暇側、N件あり得る)
出力 KIN-LEAVE160B

機能:

EDITED-PUNCH(打刻)とLEAVE-DAILY-file(日別休暇)を社員番号+日付で照合する。

  1. マッチング制御EVALUATE TRUE):

    • R01キー < R02キー → 打刻のみ(休暇なし)→ 休暇='99'+0hで出力
    • R01キー = R02キー → マッチ → 休暇情報マージ
      • 同一キーにN件のR02がある場合は全件読み、休暇種別優先順位で1件選定
    • R01キー > R02キー → R02次へ(R01側に該当なしの休暇 → この後のR01読込で拾う)
  2. 休暇種別優先順位:

    • 01(年休)と02(事假)は連動:年休残あり→01, なし→02
    • 03(因公特批假)と04(病欠)は独立
    • 複数種別混在時はAPPLICATION_ID基準で時刻範囲判定
  3. 出力:打刻情報(80B)+休暇情報(80B)=160BのKIN-LEAVE

新規カバレッジ構文:

構文 用途
EVALUATE TRUE マッチング3分岐制御
STRING 出力レコード編集
CONTINUE 空分岐処理

STEP060: KIN06CLD — 出勤日カレンダー生成処理

項目 内容
PGMパターン GETPUT
JCL前処理 なし
入力 EMP_MASTERDB2 SELECT / CURSOR)、HOLIDAY_CALENDARDB2 SELECT
出力 WORK-DAY-FILE80B FB

PARM解析:

  • YEARMONTH=202605 — 必須。対象年月。

機能:

  1. PARMから対象年月を取得
  2. EMP_MASTERテーブルからSTATUS='1'(在籍)の社員一覧をSELECTCURSOR, ORDER BY EMP_ID
  3. HOLIDAY_CALENDARテーブルから該当月の祝日一覧をSELECTWORKING-STORAGEのテーブルに格納)
  4. 各社員について、当月1日〜月末日まで PERFORM VARYING でループ:
    • SEARCH ALL でHOLIDAY-CALENDARテーブルを二分探索
    • 土曜(6) or 日曜(7) → 休日
    • その他 → 出勤日として WRITE FROM で出力 ← 新カバレッジ
  5. 出力レコードは社員番号+日付の昇順に保証(ORDER BY + ループ順)

新規カバレッジ構文:

構文 用途
WRITE FROM MOVE + WRITEを1文で記述 ← 新規
PERFORM VARYING 日付ループ
SEARCH ALL 休日テーブル二分探索
EXEC SQL SELECT(CURSOR) DB読込

STEP070: KIN07DAI — 日別勤怠計算処理

項目 内容
PGMパターン マッチング(1:N)
JCL前処理 なし(WORK-DAY-FILE / KIN-LEAVE / LEAVE-DAILYともソート済み前提)
入力R01 WORK-DAY-FILE80B、主駆動、1社員1日=1件)
入力R02 KIN-LEAVE160B、N側、1日0〜N件)
副参照 LEAVE-DAILY-file80B、ファイル併走読込)
出力 DAILY-RECORD200B FB

機能:

WORK-DAY-FILE(出勤日カレンダー)を主駆動とし、社員番号+日付をキーにKIN-LEAVE(打刻+休暇)とLEAVE-DAILY-file(日別休暇)を照合する。

EVALUATEによる4パターン分岐:

マッチング結果に応じてPATTERN-NUM(1〜4)を設定し、EVALUATE で処理分岐(実装時にGO TO DEPENDING ONのフォールスルー問題を確認したため、EVALUATE + PERFORMに変更):

01  PATTERN-NUM    PIC 9(1).
    88  PATTERN-A  VALUE 1.
    88  PATTERN-B  VALUE 2.
    88  PATTERN-C  VALUE 3.
    88  PATTERN-D  VALUE 4.

    EVALUATE PATTERN-NUM
        WHEN 1  PERFORM 6100-PATTERN-A
        WHEN 2  PERFORM 6200-PATTERN-B
        WHEN 3  PERFORM 6300-PATTERN-C
        WHEN 4  PERFORM 6400-PATTERN-D
    END-EVALUATE.
パターン R01(WORK-DAY) R02(KIN-LEAVE) LEAVE-DAILY 処理
A=1 あり あり あり 打刻情報設定+休暇時間計算(ランチ除外、0.1h切上丸め)
B=2 あり あり なし 打刻情報設定のみ、休暇=0
C=3 あり なし あり 打刻=0000、休暇時間計算(所定労働時間8h上限、ランチ除外)
D=4 あり なし なし 打刻=0000、休暇=0、未申請欠勤=8.0h

休暇時間計算(ランチ考慮):

例:終日休暇申請 0900〜1800
   0900-1200 = 3h(午前)
   1200-1300 = ランチ(除外)
   1300-1800 = 5h(午後)
   合計休暇時間 = 8h

例:午後休暇申請 1300〜1800
   1300-1800 = 5h(午後、ランチ除外済み)
   合計休暇時間 = 5h

丸め:SUB05TIM(0.1h単位切上)を呼出。

バリエーション構文(MULTIPLY / SUBTRACT):

COMPUTEのみに依存せず、MULTIPLYとSUBTRACTも併用して時間計算のバリエーションを確保する。

* 例:時間(hhmm)を分(minutes)に変換 → ランチ除外
MULTIPLY WRK-HOURS BY 60 GIVING WRK-MINUTES    ← MULTIPLY
SUBTRACT LUNCH-MINUTES FROM WRK-MINUTES          ← SUBTRACT

新規カバレッジ構文:

構文 用途
GO TO ... DEPENDING ON 4パターンの処理分岐 ← 新規
PERFORM THRU 各パターン内の段落範囲処理
COMPUTE ROUNDED ON SIZE ERROR 時間計算のエラー処理
MULTIPLY 時間→分単位変換 ← 新規
SUBTRACT ランチ時間除外 ← 新規
STRING エラーメッセージ編集
CALL 'SUB05TIM' 時刻丸め計算

STEP080: KIN08DBU — 勤怠DB更新処理

項目 内容
PGMパターン DB更新 + SYSIN読込(P28)
JCL前処理 なし
入力 DAILY-RECORD200B)、SYSIN(制御カード)
出力 DAILY_RECORDS / MONTHLY_ABSENCEDB2)、ABSENCE_SUMMARY80B

SYSIN制御カード(3種):

* コメント行(先頭*)
T 社員番号,社員番号,...    ← TARGET: 集計対象社員指定(省略時=全社員)
P YEARMONTH=YYYYMM         ← PERIOD: 処理対象年月(必須)
M MODE=RESET|NORMAL        ← MODE: RESET=再実行(既存削除後に再INSERT, NORMAL=通常(UPSERT

カード種別('T','P','M')を第1桁で識別。GO TO DEPENDING ON で処理分岐する。

機能:

  1. SYSIN読込(パターン28:制御カードをSYSINから順次読み込み、カード種別でGO TO DEPENDING ON分岐
    • Tカード → 対象社員一覧をWORKING-STORAGEの内部テーブルに保持
    • Pカード → YEARMONTHを解析(UNSTRING + INSPECT TALLYINGでカンマ区切り数検証)
    • Mカード → MODEを判定。未指定ならNORMAL
    • *カード → コメント行としてスキップ(CONTINUE
    • 不明カード → DISPLAYで警告表示
  2. DAILY-RECORDを1レコードずつ読込み、DAILY_RECORDSにEXEC SQL INSERT
    • 各INSERT前にINSPECT TALLYINGで社員番号の有効性チェック → 空または無効値はDISPLAYで警告表示
  3. 社員別・月別の集計値をPERFORM VARYINGで積算(全社員ループ)
    • COMPUTE ROUNDED ON SIZE ERROR で時間計算(桁あふれ時に警告表示)
  4. MODE=RESETの場合:EXEC SQL DELETEで該当月の既存レコードを削除
  5. MONTHLY_ABSENCEに対してEXEC SQL SELECT COUNT(*) → IF >0 → UPDATE ELSE INSERTUPSERT
  6. 病欠時間はSICK_LEAVE_RATEテーブルを参照し、控除前時間として保持
  7. 集計後データをABSENCE_SUMMARYファイルに出力

GO TO DEPENDING ON ロジック:

   READ SYSINFILE INTO WS-SYSIN-REC
       AT END SET SYSIN-EOF TO TRUE
   END-READ.
   IF NOT SYSIN-EOF
       MOVE WS-SYSIN-REC(1:1) TO WS-CARD-TYPE
       IF WS-CARD-TYPE = 'T' OR 'P' OR 'M'
           IF WS-CARD-TYPE = 'T' MOVE 1 TO WS-DISP-IDX
           IF WS-CARD-TYPE = 'P' MOVE 2 TO WS-DISP-IDX
           IF WS-CARD-TYPE = 'M' MOVE 3 TO WS-DISP-IDX
           GO TO DEPENDING ON WS-DISP-IDX
               2100-TARGETSOR 2200-PERIODSOR 2300-MODESOR
           .
       ELSE
           IF WS-CARD-TYPE = '*'
               DISPLAY 'COMMENT: ' WS-SYSIN-REC
           ELSE
               DISPLAY 'WARNING: Unknown SYSIN card type ['
                       WS-CARD-TYPE ']'
           END-IF
       END-IF
   END-IF.

新規カバレッジ構文:

構文 用途
READ SYSIN(パターン28 制御カード読込 ← 新規パターン
GO TO DEPENDING ON カード種別による3分岐 ← 新規
DISPLAY 警告メッセージ表示 ← 新規
INSPECT TALLYING 社員番号の空チェック、カンマ区切り数検証
COMPUTE ON SIZE ERROR 時間計算の桁あふれ処理 ← 新規
EXEC SQL DELETE RESETモード時既存レコード削除 ← 新規(メインPGM)
PERFORM VARYING 社員別月次集計ループ
EXEC SQL SELECT / INSERT / UPDATE DB操作(UPSERTパターン)

STEP090: KIN09CSV — 勤怠CSV出力処理

項目 内容
PGMパターン GETPUT(編集出力)
JCL前処理 なし
入力 DAILY_RECORDS / MONTHLY_ABSENCEDB2)、COMMAND-LINE PARM
出力 CSVファイル(社員確認用)

PARM解析:

  • YEARMONTH=202605 — 必須。対象年月。
  • MODE=FULL — オプション。FULL=全項目出力(日別+月次), SHORT=月次集計のみ。

機能:

  1. ACCEPT FROM COMMAND-LINE でPARM解析(INSPECT TALLYINGでカンマ区切り数チェック)
  2. DAILY_RECORDSから当月の全レコードをCURSOR SELECTORDER BY EMP_ID, TARGET_DATE
  3. INSPECT REPLACING でCSV危険文字をサニタイズ(カンマ→セミコロン、改行→スペース)
  4. STRING WITH POINTER でCSV行を位置指定編集 ← 新カバレッジ
  5. WRITE AFTER ADVANCING 3種 でページ制御 ← 新カバレッジ
    • 先頭ページ:WRITE header-rec AFTER ADVANCING PAGE
    • セクション区切り:WRITE section-rec AFTER ADVANCING 2 LINES
    • データ行:WRITE data-rec AFTER ADVANCING 1 LINE
  6. MODE=FULL時:100行ごとにヘッダー行を再出力
  7. CSVフォーマット:
社員番号,日付,出勤時刻,退勤時刻,休暇種別,年休時間,事假時間,因公特批假時間,病欠時間,未申請欠勤時間
00000101,20260501,0900,1800,99,0.0,0.0,0.0,0.0,0.0
00000101,20260502,0900,1300,02,0.0,4.0,0.0,0.0,4.0
00000101,20260503,0000,0000,01,8.0,0.0,0.0,0.0,0.0
00000101,20260504,0000,0000,99,0.0,0.0,0.0,0.0,8.0
  1. 休暇種別は該当日に休暇がある場合は最初に該当した休暇種別コード、ない場合は'99'

INSPECT REPLACING によるCSVサニタイズ:

MOVE WS-FIELD TO WS-SAFE-FIELD.
INSPECT WS-SAFE-FIELD REPLACING ALL ',' BY ';'
                               ALL X"0D" BY SPACE
                               ALL X"0A" BY SPACE.

STRING WITH POINTER によるCSV行編集:

MOVE 1 TO WS-PTR.
STRING WS-EMP-ID           DELIMITED BY SIZE
       ','                 DELIMITED BY SIZE
       WS-DATE             DELIMITED BY SIZE
       ','                 DELIMITED BY SIZE
       WS-TIME-IN          DELIMITED BY SIZE
       ','                 DELIMITED BY SIZE
       WS-TIME-OUT         DELIMITED BY SIZE
       ','                 DELIMITED BY SIZE
       WS-LEAVE-TYPE       DELIMITED BY SIZE
       ','                 DELIMITED BY SIZE
       WS-ANNUAL-H         DELIMITED BY SIZE
       ','                 DELIMITED BY SIZE
       WS-PERSONAL-H       DELIMITED BY SIZE
       ','                 DELIMITED BY SIZE
       WS-OFFICIAL-H       DELIMITED BY SIZE
       ','                 DELIMITED BY SIZE
       WS-SICK-H           DELIMITED BY SIZE
       ','                 DELIMITED BY SIZE
       WS-ABSENT-H         DELIMITED BY SIZE
  INTO WS-CSV-LINE WITH POINTER WS-PTR
END-STRING.

新規カバレッジ構文:

構文 用途
ACCEPT FROM COMMAND-LINE PARM解析(対象年月・出力モード)
INSPECT REPLACING CSV危険文字置換 ← 新規
STRING WITH POINTER 位置指定CSV行編集 ← 新規
WRITE AFTER ADVANCING PAGE ページヘッダー制御 ← 新規
WRITE AFTER ADVANCING 2 LINES セクション区切り ← 新規
WRITE AFTER ADVANCING 1 LINE データ行出力 ← 新規
STRING CSV行編集(DELIMITED BY SIZE
EXEC SQL SELECT(CURSOR) DB読込

共通関数(サブプログラム)

サブシステムAの全プログラムで使用する共通関数。SUB06DBUは使用せず、全DB操作はEXEC SQLで直接記述する。

サブプログラム I/Fコピー句 用途 使用プログラム
SUB01DAT D01010AC 運用日付取得 KIN01INP, KIN04CHK, KIN08DBU, KIN09CSV
SUB02MSG MSG000AC メッセージ編集出力 全プログラム
SUB03END MSG000AC ABEND終了 KIN02UPD, KIN04CHK, KIN07DAI
SUB04CHK SUB04CHK 項目チェック(日付/時刻/数値) KIN01INP, KIN04CHK
SUB05TIM TIME010AC 時刻丸め計算(分→時間) KIN07DAI

JCL構成概要

9本のJOB。拠点間ソートはJCL SORTで処理し、COBOLプログラムはビジネスロジックに専念する。

JOB名 実行PGM 処理概要 SORT
KINJ010 KIN01INP 休暇申請CSV取込・検証 不要
KINJ011 SORT WORK-LEAVE → APPLICATION_ID昇順 必須
KINJ012 KIN02UPD 休暇申請DB更新(INSERT/DELETE 不要
KINJ015 KIN03EXP 休暇日別展開(キーブレイク) 不要
KINJ020 KIN04CHK 打刻項目チェック 不要
KINJ022 SORT EDITED-PUNCH → 社員番号+日付昇順 必須
KINJ025 KIN05MAT 打刻休暇照合(1:N 不要
KINJ030 KIN06CLD 出勤日カレンダー生成(GETPUT 不要
KINJ033 KIN07DAI 日別計算(EVALUATE / MULTIPLY / SUBTRACT 不要
KINJ036 KIN08DBU 勤怠DB更新(集計) 不要
KINJ040 KIN09CSV 勤怠CSV出力 不要

丸めルール一覧

項目 最小単位 超過後丸め 適用プログラム
休暇時間(全種別) 1.0h 0.1h単位切上 KIN07DAISUB05TIM
未申請欠勤時間 8.0h/日 切捨 KIN07DAI

サブシステムB(残業計算)の丸めルールとは独立して管理する。


期待される新規カバレッジ

プログラムタイプ(未カバー → Aで追加)

No パターン 状態 A該当プログラム A状態
2 マッチング処理(1:N × KIN05MAT
11 キーブレイク処理(その他) × KIN03EXP
12 レイアウト編集のみ(GETPUT × KIN06CLD
15 振り分け(IF文) × KIN01INP
17 内部テーブル検索 KIN01INP(SEARCH非ALL)
19 CSV→FB変換(改行なし) KIN01INP
28 SYSIN読込・チェック × KIN08DBU 新規◎

ステートメント(未カバー → Aで追加)

ステートメント 状態 A該当プログラム
SEARCH(非ALL) × KIN01INP
DELETE FROM(DB2) × KIN02UPD
GO TO DEPENDING ON × KIN08DBU(← 新規)
PERFORM THRU × KIN03EXP
WRITE FROM × KIN04CHK, KIN06CLD
WRITE AFTER ADVANCINGPAGE/1/2 × KIN09CSV(← 新規)
INSPECT REPLACING × KIN09CSV(← 新規)
STRING WITH POINTER × KIN09CSV(← 新規)
COMPUTE ON SIZE ERROR ○(ZAN系のみ) KIN08DBU(← 新規)
MULTIPLY ○(ZAN06UPDのみ) KIN07DAI
SUBTRACT ○(ZAN06UPDのみ) KIN07DAI
ACCEPT FROM COMMAND-LINE ◎(ZAN05CAL,KIN06CLD) KIN09CSV
DISPLAY △(SUB02MSG,SUB03ENDのみ) KIN08DBU
INSPECT TALLYING KIN08DBU

全体カバレッジ目標

カテゴリ 現状 追加後(目標)
プログラムタイプ(35種) 14使用(40.0% 15使用(42.9%
ステートメント(45ユニーク) 33使用(73.3% 36使用(80.0%
カテゴリ(9種) 8/9カバー(88.9% 9/9カバー(100%

レコード構成

EDITED-PUNCHはBサブシステムのZAN03CHKが入力として使用するため、互換性を維持する。

EDITED-PUNCH80B

Bサブシステムとの連携インターフェース。

# 項目 名称 属性 開始 備考
1 社員番号 SI-EMP-ID 9(8) 1
2 日付 SI-DATE 9(8) 9 YYYYMMDD
3 出勤時刻 SI-TIME-IN 9(4) 17 HHMM
4 退勤時刻 SI-TIME-OUT 9(4) 21 HHMM
5 部署ID SI-DEPT-ID 9(4) 25
6 端末ID SI-TERMINAL X(6) 29
7 予備 FILLER X(46) 35

WORK-LEAVE80B — 新規(KIN01INP→KIN02UPD中間)

# 項目 名称 属性 開始 備考
1 申請ID WL-APPLICATION-ID 9(9) 1 新規=0, 取消/変更=APPLICATION_ID
2 社員番号 WL-EMP-ID X(8) 10
3 休暇種別 WL-LEAVE-TYPE X(2) 18 '01'〜'04'
4 開始日 WL-START-DATE 9(8) 20 YYYYMMDD
5 開始時刻 WL-START-TIME 9(4) 28 HHMM
6 終了日 WL-END-DATE 9(8) 32 YYYYMMDD
7 終了時刻 WL-END-TIME 9(4) 40 HHMM
8 ステータス WL-STATUS X(1) 44 '1'=新規/変更, '9'=取消
9 予備 FILLER X(36) 45

LEAVE-DAILY80B

# 項目 名称 属性 開始 備考
1 社員番号 SL-EMP-ID X(8) 1
2 日付 SL-DATE 9(8) 9 YYYYMMDD
3 休暇種別 SL-LEAVE-TYPE X(2) 17 '01'〜'04'
4 開始時刻 SL-START-TIME 9(4) 19 HHMM(元申請の開始時刻)
5 終了時刻 SL-END-TIME 9(4) 23 HHMM(元申請の終了時刻)
6 申請ID SL-APPLICATION-ID 9(9) 27 LEAVE_RECORDSのAPPLICATION_ID
7 予備 FILLER X(45) 36

KIN-LEAVE160B — EDITED-PUNCH(80B)+休暇情報(80B)

# 項目 名称 属性 開始 備考
1-7 打刻情報 1 EDITED-PUNCHと同一
8 休暇種別 SR-LEAVE-TYPE X(2) 81 '01'〜'04' or '99'
9 開始時刻 SR-LEAVE-START-TIME 9(4) 83 該当休暇の申請開始時刻
10 終了時刻 SR-LEAVE-END-TIME 9(4) 87 該当休暇の申請終了時刻
11 休暇時間 SR-LEAVE-HOURS 9(4)V9(1) 91 KIN07DAIが再計算(ランチ除外・丸め適用)
12 申請ID SR-APPLICATION-ID 9(9) 96 LEAVE_RECORDSのAPPLICATION_ID
13 予備 FILLER X(56) 105

WORK-DAY-FILE80B

# 項目 名称 属性 開始 備考
1 社員番号 SW-EMP-ID 9(8) 1
2 日付 SW-DATE 9(8) 9 YYYYMMDD
3 曜日 SW-DAY-OF-WEEK 9(1) 17 1=月…7=日
4 予備 FILLER X(63) 18

DAILY-RECORD200B

# 項目 名称 属性 開始 備考
1 社員番号 SD-EMP-ID 9(8) 1
2 日付 SD-DATE 9(8) 9 YYYYMMDD
3 出勤時刻 SD-TIME-IN 9(4) 17 '0000'=打刻なし
4 退勤時刻 SD-TIME-OUT 9(4) 21 '0000'=打刻なし
5 年休時間 SD-ANNUAL-H 9(4)V9(1) 25
6 事假時間 SD-PERSONAL-H 9(4)V9(1) 30
7 因公特批假時間 SD-OFFICIAL-H 9(4)V9(1) 35
8 病欠時間 SD-SICK-H 9(4)V9(1) 40
9 未申請欠勤時間 SD-ABSENT-H 9(4)V9(1) 45
10 予備 FILLER X(151) 50

CSV-OUTPUT200B

# 項目 名称 属性 開始 備考
1 CSV行データ SC-CSV-LINE X(200) 1 STRING編集済みCSV1行

ERROR-LOGVB 200B

# 項目 名称 属性 開始 備考
1 エラー区分 ER-CATEGORY 9(2) 1 01=休暇エラー, 02=打刻エラー
2 発生日時 ER-DATETIME X(16) 3
3 プログラムID ER-PGM-ID X(8) 19
4 エラー内容 ER-MESSAGE X(100) 27
5 原データ ER-RAW-DATA X(80) 127 エラー原因となった入力レコード