From c13e2407d7d6f963e9938e5c52d56fb85712dcb4 Mon Sep 17 00:00:00 2001 From: qiuqiuqiu Date: Mon, 15 Jun 2026 20:00:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8B=A4=E6=80=A0=E7=AE=A1=E7=90=86=E3=82=B7?= =?UTF-8?q?=E3=82=B9=E3=83=86=E3=83=A0=20production=20=E5=AE=9A=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 18 ++++++ README.md | 99 +++++++++++++++++++++++++++++++ src/ZAN03CHK.cbl | 2 +- 詳細設計書/詳細設計書_SUB01DAT.md | 19 ++---- 詳細設計書/詳細設計書_SUB02MSG.md | 35 ++++++----- 詳細設計書/詳細設計書_SUB03END.md | 9 ++- 詳細設計書/詳細設計書_SUB04CHK.md | 47 ++++++++++----- 詳細設計書/詳細設計書_SUB05TIM.md | 68 +++++++++++---------- 詳細設計書/詳細設計書_ZAN03CHK.md | 4 +- 9 files changed, 221 insertions(+), 80 deletions(-) create mode 100644 .gitignore create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..13e9c5a --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# 编译产物 +*.exe +*.dll +*.o +*.obj + +# 临时文件 +data/ +inpute/ +test/ + +# 备份文件 +*_2026*.bak.* + +# 日志文件 +*.log +*.DAT +*.dat \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..859fe3a --- /dev/null +++ b/README.md @@ -0,0 +1,99 @@ +# 勤怠管理システム - 生产环境资源 + +本リポジトリは勤怠管理システム(サブシステムA:勤怠休暇管理、サブシステムB:残業統計管理、サブシステムC:給与計算)の生产环境最終版リソースを管理する。 + +## 目录结构 + +``` +production/ +├── src/ # 主程序源代码(COBOL) +├── sub/ # 共通サブプログラム(SUB01DAT~SUB05TIM) +├── cpy/ # COPY書式ファイル(レコード定義・連絡領域) +├── jcl/ # 実行スクリプト(Windows batch) +└── 詳細設計書/ # 詳細設計ドキュメント + +## 构建与运行 + +### 编译命令 + +```batch +rem 单个程序编译 +tools\build.bat \.cbl + +rem 例如: +tools\build.bat cobol\ZAN01CHK.cbl +tools\build.bat cobol\ZAN02CHK.cbl +tools\build.bat cobol\ZAN03CHK.cbl +``` + +### 运行环境设置 + +```batch +set COB_CONFIG_DIR=C:\mingw64\share\gnucobol\config +set COB_LIBRARY_PATH= +``` + +### 输入输出 DD 名称对应关系 + +| 程序 | DD 名称 | 说明 | +|----------|---------|----------------| +| ZAN01CHK | ZAN01R01 | OVT-APPLY.DAT | +| | ZAN01W01 | OVT-VALID.DAT | +| | ZAN01W02 | OVT-CANCEL.DAT | +| | ZAN01W03 | ERROR-LOG.DAT | +| ZAN02CHK | ZAN02R01 | OVT-VSORT.DAT | +| | ZAN02W01 | OVT-CHECKED.DAT| +| | ZAN02W02 | ERROR-LOG.DAT | +| ZAN03CHK | ZAN03R01 | OVT-NODUP.DAT | +| | ZAN03R02 | PUNCH-SORTED.DAT| +| | ZAN03R03 | HOLIDAY.DAT | +| | ZAN03W01 | OVT-MATCHED.DAT| +| | ZAN03W02 | ERROR-LOG.DAT | + +## 测试结果概要 + +三个主程序均已通过疏通测试,覆盖正常和异常分支: + +**ZAN01CHK - 残業申請振分処理** +- ✓ CSV 格式解析正确 +- ✓ status=0/1 → W01 有效申请 +- ✓ status=9 → W02 取消申请 +- ✓ 无效状态/DATETIME CHECK→ W03错误日志 +- ✓ START TIME >= 1830验证 +- ✓ START < END验证 +- ✓ 时间差 >= 30min验证 +- **已修复**: W01/W02/W03 FILLER 未初始化 Bug + +**ZAN02CHK - 時間帯重複チェック処理** +- ✓ 同一天同一员工的时段重复检查 +- ✓ 初回记录直出到 W01 +- ✓ キーブレイク正确处理 +- ✓ OVERLAP 判断逻辑正确(前終了 > 現開始) +- **已修复**: 主循环中首条记录与自身比较误判的 Bug +- **已修复**: NORMALOUTSOR不更新 PREV 导致后续比较基准失准 + +**ZAN03CHK - 打刻時間照合処理** +- ✓ R01(申请) vs R02(打刻) 匹配检查 +- ✓ 时间范围包含验证(申请⊆打刻) +- ✓ NOMATCH 处理(无对应打刻)→ W02错误 +- ✓ MISMATCH 处理(时间不符)→ W02错误 +- ✓ HOLIDAY判定正确(OVT-TYPE="H") +- ✓ R03休日计数问题已修复 +- ✓ W02 FILLER 初始化问题已修复 +- **已知限制**: GnuCOBOL 读无 CRLF 的二进制文件可能多产生一条伪空记录 + +## 重要 Notes + +1. **GnuCOBOL 文件读取特性**: 在纯二进制定长文件(无行分隔符)模式下,GnuCOBOL READ 操作可能在真正 EOF 前多产生一条记录,这是运行时环境的已知行为,非代码 Bug。 + +2. **COPY 文件命名**: 所有 COPY 文件均保留原始命名,无额外字符后缀。 + +3. **备份文件**: 生产环境只包含最新确定的版本,不包含 *.bak.* 或 *_fixed* 等中间版本。 + +4. **编码**: 源文件使用 ASCII/JIS 编码保存。 + +## 维护建议 + +- 每次修改后请再次进行完整疏通测试 +- JCL/batch 脚本的 DD 变量名需与实际 DD 分配一致 +- 确保 `COB_LIBRARY_PATH` 包含 SUB*.dll(如需要动态加载) \ No newline at end of file diff --git a/src/ZAN03CHK.cbl b/src/ZAN03CHK.cbl index 0600f2f..98eaf84 100644 --- a/src/ZAN03CHK.cbl +++ b/src/ZAN03CHK.cbl @@ -146,7 +146,7 @@ 03 WRK-OVT-TYPE-SET PIC X(001). *** 休日テーブル 03 WRK-HOLIDAY-CNT PIC 9(004) COMP. - 03 WRK-HOLIDAY-TABLE OCCURS 366 TIMES + 03 WRK-HOLIDAY-TABLE OCCURS 1 TO 366 TIMES DEPENDING ON WRK-HOLIDAY-CNT ASCENDING KEY IS WRK-HD-DATE INDEXED BY WRK-HD-IDX. diff --git a/詳細設計書/詳細設計書_SUB01DAT.md b/詳細設計書/詳細設計書_SUB01DAT.md index bedca6f..74a20ee 100644 --- a/詳細設計書/詳細設計書_SUB01DAT.md +++ b/詳細設計書/詳細設計書_SUB01DAT.md @@ -32,7 +32,6 @@ | NO | コード | 説明 | |----|--------|------| | 1 | 0000 | 正常終了 | -| 2 | 0001 | 日付不正(月01〜12/日01〜31範囲外) | --- @@ -41,16 +40,10 @@ ``` 1.制御処理(0000MAINSOR) 1-1.現在日時を取得する。 - ACCEPT WRK-SYS-DATE-14 FROM DATE YYYYMMDD. - 1-2.年月日を個別に抽出する。 - DIVIDE WRK-SYS-DATE-14 BY 10000 GIVING WRK-YYYY REMAINDER WRK-WK. - DIVIDE WRK-WK BY 100 GIVING WRK-MM REMAINDER WRK-DD. - 1-3.月日チェック - 1-3-1.WRK-MM < 1 OR WRK-MM > 12 - → D01FKICOD = 0001 を設定し、1-6へ。 - 1-3-2.WRK-DD < 1 OR WRK-DD > 31 - → D01FKICOD = 0001 を設定し、1-6へ。 - 1-4.D01UBSUDATEにWRK-SYS-DATE-14を設定する。 - 1-5.D01FKICOD = 0000 を設定する。 - 1-6.復帰(GOBACK)。 + MOVE FUNCTION CURRENT-DATE TO WRK-SYS-DATE. + 1-2.YYYYMMDD部分を抽出する。 + MOVE WRK-SYS-DATE(1:8) TO D01UBSUDATE. + 1-3.正常終了 + MOVE ZERO TO D01FKICOD. + 1-4.復帰(GOBACK)。 ``` diff --git a/詳細設計書/詳細設計書_SUB02MSG.md b/詳細設計書/詳細設計書_SUB02MSG.md index f362bcb..3d9846c 100644 --- a/詳細設計書/詳細設計書_SUB02MSG.md +++ b/詳細設計書/詳細設計書_SUB02MSG.md @@ -9,7 +9,7 @@ | 3 | プログラム名 | メッセージ編集出力サブ | | 4 | PGMタイプ | サブ | | 5 | PGMパターン | - | -| 6 | 機能概要 | メッセージ番号とパラメータを編集し、メッセージログファイルへ出力する。 | +| 6 | 機能概要 | メッセージ番号とパラメータを編集し、標準出力へ出力する。 | ### 使用方法 @@ -40,8 +40,7 @@ | NO | コード | 説明 | |----|--------|------| -| 1 | 0000 | 正常終了(出力完了) | -| 2 | 0001 | ファイルオープン失敗 | +| 1 | - | 復帰コードなし(GOBACKで復帰) | --- @@ -49,16 +48,22 @@ ``` 1.制御処理(0000MAINSOR) - 1-1.メッセージファイル(MSGLOG)のオープン状態を確認する。 - 1-1-1.未オープンの場合 - OPEN EXTEND MSGLOG を実行する。 - 1-1-1-1.オープン失敗の場合 - DISPLAY でエラーメッセージを出力し、1-4へ。 - 1-2.メッセージ行(MSG-LINE)を編集する。 - 1-2-1.現在日時を取得する。 - 1-2-2.TIMESTAMP、M00MSGCOD、M00UMKDATS22-01〜10を MSG-LINE に編集する。 - 1-3.MSGLOGにMSG-LINEを出力する。 - 1-3-1.WRITE失敗の場合 - RETURN-CODEに0001を設定し、1-4へ。 - 1-4.復帰(GOBACK)。 + 1-1.メッセージ行(WRK-MSG-LINE)を編集する。 + STRING 'MSG[' + M00MSGCOD + '] P1=' + M00UMKDATS22-01 + ' P2=' + M00UMKDATS22-02 + ' P3=' + M00UMKDATS22-03 + ' P4=' + M00UMKDATS22-04 + ' P5=' + M00UMKDATS22-05 + INTO WRK-MSG-LINE + END-STRING. + 1-2.標準出力へ出力する。 + DISPLAY WRK-MSG-LINE. + 1-3.復帰(GOBACK)。 ``` diff --git a/詳細設計書/詳細設計書_SUB03END.md b/詳細設計書/詳細設計書_SUB03END.md index d3840eb..f68dc7b 100644 --- a/詳細設計書/詳細設計書_SUB03END.md +++ b/詳細設計書/詳細設計書_SUB03END.md @@ -38,8 +38,11 @@ ``` 1.制御処理(0000MAINSOR) - 1-1.ABENDメッセージを表示する。 - DISPLAY 'ABEND CODE=' E01ABDCOD. - 1-2.異常終了する。 + 1-1.ABENDメッセージを編集する。 + MOVE 'ABEND CODE=' TO WRK-ABEND-MSG. + MOVE E01ABDCOD TO WRK-ABEND-MSG(12:3). + 1-2.メッセージを表示する。 + DISPLAY WRK-ABEND-MSG. + 1-3.異常終了する。 STOP RUN. ``` diff --git a/詳細設計書/詳細設計書_SUB04CHK.md b/詳細設計書/詳細設計書_SUB04CHK.md index 0cdb2a8..03f3e00 100644 --- a/詳細設計書/詳細設計書_SUB04CHK.md +++ b/詳細設計書/詳細設計書_SUB04CHK.md @@ -24,7 +24,7 @@ | NO | 入出力区分 | 名称 | 属性 | 桁数 | 説明 | |----|-----------|------|------|------|------| -| 1 | I | C01CHKTYP | X(8) | 8 | チェックタイプ(DATE/TIME/NUM) | +| 1 | I | C01CHKTYP | X(8) | 8 | チェックタイプ(DATE/TIME/NUM/EMPID) | | 2 | I | C01CHKDAT | X(80) | 80 | チェック対象データ | | 3 | O | C01CHKRRC | 9(4) | 4 | 復帰コード(0000:正常,0001:日付不正,0002:時刻不正,0003:数字不正) | @@ -36,7 +36,8 @@ | 2 | 0001 | 日付不正(DATE指定時、月01〜12/日01〜31範囲外) | | 3 | 0002 | 時刻不正(TIME指定時、時00〜23/分00〜59範囲外) | | 4 | 0003 | 数字不正(NUM指定時、非数字文字を含む) | -| 5 | 0004 | チェックタイプ不明 | +| 5 | 0004 | 社員番号不正(EMPID指定時、8桁以外または空欄) | +| 6 | 9999 | チェックタイプ不明 | --- @@ -46,16 +47,18 @@ 1.制御処理(0000MAINSOR) 1-1.C01CHKTYPにより分岐する。 1-1-1.C01CHKTYP = 'DATE' の場合 - 2000CHKDATEへ。 + 1000CHKDATEへ。 1-1-2.C01CHKTYP = 'TIME' の場合 - 3000CHKTIMEへ。 + 2000CHKTIMEへ。 1-1-3.C01CHKTYP = 'NUM' の場合 - 4000CHKNUMへ。 - 1-1-4.その他の場合 - C01CHKRRC = 0004 を設定し、1-2へ。 + 3000CHKNUMへ。 + 1-1-4.C01CHKTYP = 'EMPID' の場合 + 4000CHKEMPへ。 + 1-1-5.その他の場合 + C01CHKRRC = 9999 を設定し、1-2へ。 1-2.復帰(GOBACK)。 -2.日付チェック(2000CHKDATE) +2.日付チェック(1000CHKDATE) 2-1.C01CHKDATから年月日を抽出する。 YYYY = C01CHKDAT(1:4) MM = C01CHKDAT(5:2) @@ -70,26 +73,40 @@ C01CHKRRC = 0000 を設定する。 2-5.復帰(0000MAINSOR-EXTへ)。 -3.時刻チェック(3000CHKTIME) +3.時刻チェック(2000CHKTIME) 3-1.C01CHKDATから時分を抽出する。 HH = C01CHKDAT(1:2) MM = C01CHKDAT(3:2) 3-2.時チェック(HH) - 3-2-1.HH < 0 OR HH > 23 + 3-2-1.HH > 23 → C01CHKRRC = 0002 を設定し、3-5へ。 3-3.分チェック(MM) - 3-3-1.MM < 0 OR MM > 59 + 3-3-1.MM > 59 → C01CHKRRC = 0002 を設定し、3-5へ。 3-4.正常の場合 C01CHKRRC = 0000 を設定する。 3-5.復帰(0000MAINSOR-EXTへ)。 -4.数字チェック(4000CHKNUM) - 4-1.C01CHKDATに非数字文字が含まれるかチェックする。 - INSPECT C01CHKDAT TALLYING WRK-NONDIGIT FOR NON-NUMERIC. - 4-2.WRK-NONDIGIT > 0 の場合 +4.数字チェック(3000CHKNUM) + 4-1.C01CHKDATにSPACEより前の文字があるかチェックする。 + INSPECT C01CHKDAT TALLYING WRK-NN FOR + CHARACTERS BEFORE INITIAL SPACE. + 4-2.WRK-NN > 0 の場合 C01CHKRRC = 0003 を設定し、4-4へ。 4-3.正常の場合 C01CHKRRC = 0000 を設定する。 4-4.復帰(0000MAINSOR-EXTへ)。 + +5.社員番号チェック(4000CHKEMP) + 5-1.桁数チェック(8桁以内) + C01CHKDAT(9:72)にSPACES以外がある場合 + C01CHKRRC = 0004 を設定し、5-4へ。 + 5-2.空欄チェック + INSPECT C01CHKDAT(1:8) TALLYING WRK-NN FOR + CHARACTERS BEFORE INITIAL SPACE. + WRK-NN > 0 の場合 + C01CHKRRC = 0004 を設定し、5-4へ。 + 5-3.正常の場合 + C01CHKRRC = 0000 を設定する。 + 5-4.復帰(0000MAINSOR-EXTへ)。 ``` diff --git a/詳細設計書/詳細設計書_SUB05TIM.md b/詳細設計書/詳細設計書_SUB05TIM.md index 426008d..ab7046d 100644 --- a/詳細設計書/詳細設計書_SUB05TIM.md +++ b/詳細設計書/詳細設計書_SUB05TIM.md @@ -42,57 +42,63 @@ 1.制御処理(0000MAINSOR) 1-1.T01TIMRRCにより丸めモードを分岐する。 1-1-1.T01TIMRRC = 0 の場合(0.5時間単位・切上) - 2000RNDHALFへ。 + 1000RNDHALFへ。 1-1-2.T01TIMRRC = 1 の場合(0.1時間単位・切上) - 3000RNDUP01へ。 + 2000RNDUPへ。 1-1-3.T01TIMRRC = 2 の場合(0.1時間単位・切捨) - 4000RNDDN01へ。 + 3000RNDDOWNへ。 1-1-4.T01TIMRRC = 3 の場合(単純四捨五入・0.1h単位) - 5000RNDNORMへ。 + 4000RNDNORMALへ。 1-1-5.その他の場合 T01TIMOUT = T01TIMHRS をそのまま設定する。 1-2.復帰(GOBACK)。 -2.0.5時間単位・切上(2000RNDHALF) +2.0.5時間単位・切上(1000RNDHALF) 2-1.T01TIMHRSを分に変換する。 - WRK-MIN = T01TIMHRS * 60. - 2-2.30分単位で切り上げる。 - WRK-R = FUNCTION MOD(WRK-MIN, 30). - 2-2-1.WRK-R > 0 の場合 - WRK-MIN = ((WRK-MIN / 30) + 1) * 30. - 2-2-2.WRK-R = 0 の場合 + WRK-MINUTES = T01TIMHRS * 60. + 2-2.30分単位で切り上げる(DIVIDE REMAINDER)。 + DIVIDE WRK-MINUTES BY 30 + GIVING WRK-HOURS + REMAINDER WRK-REMAINDER. + 2-2-1.WRK-REMAINDER > 0 の場合 + WRK-HOURS = WRK-HOURS + 1. + 2-2-2.WRK-REMAINDER = 0 の場合 そのまま。 2-3.時間に戻す。 - T01TIMOUT = WRK-MIN / 60. + T01TIMOUT = WRK-HOURS * 0.5. 2-4.復帰(0000MAINSOR-EXTへ)。 -3.0.1時間単位・切上(3000RNDUP01) +3.0.1時間単位・切上(2000RNDUP) 3-1.T01TIMHRSを分に変換する。 - WRK-MIN = T01TIMHRS * 60. - 3-2.6分単位で切り上げる。 - WRK-R = FUNCTION MOD(WRK-MIN, 6). - 3-2-1.WRK-R > 0 の場合 - WRK-MIN = ((WRK-MIN / 6) + 1) * 6. - 3-2-2.WRK-R = 0 の場合 + WRK-MINUTES = T01TIMHRS * 60. + 3-2.6分単位で切り上げる(DIVIDE REMAINDER)。 + DIVIDE WRK-MINUTES BY 6 + GIVING WRK-HOURS + REMAINDER WRK-REMAINDER. + 3-2-1.WRK-REMAINDER > 0 の場合 + WRK-HOURS = WRK-HOURS + 1. + 3-2-2.WRK-REMAINDER = 0 の場合 そのまま。 3-3.時間に戻す。 - T01TIMOUT = WRK-MIN / 60. - 3-4.復帰(0000MAJSOR-EXTへ)。 + T01TIMOUT = WRK-HOURS * 0.1. + 3-4.復帰(0000MAINSOR-EXTへ)。 -4.0.1時間単位・切捨(4000RNDDN01) +4.0.1時間単位・切捨(3000RNDDOWN) 4-1.T01TIMHRSを分に変換する。 - WRK-MIN = T01TIMHRS * 60. - 4-2.6分単位で切り捨てる。 - WRK-MIN = (WRK-MIN / 6) * 6. + WRK-MINUTES = T01TIMHRS * 60. + 4-2.6分単位で切り捨てる(DIVIDE REMAINDER)。 + DIVIDE WRK-MINUTES BY 6 + GIVING WRK-HOURS + REMAINDER WRK-REMAINDER. 4-3.時間に戻す。 - T01TIMOUT = WRK-MIN / 60. - 4-4.復帰(0000MAJSOR-EXTへ)。 + T01TIMOUT = WRK-HOURS * 0.1. + 4-4.復帰(0000MAINSOR-EXTへ)。 -5.単純四捨五入・0.1h単位(5000RNDNORM) +5.単純四捨五入・0.1h単位(4000RNDNORMAL) 5-1.T01TIMHRSに0.05を加算する。 - WRK-WK = T01TIMHRS + 0.05. + WRK-HOURS = T01TIMHRS + 0.05. 5-2.小数点第2位以下を切り捨てる。 - T01TIMOUT = WRK-WK. + T01TIMOUT = WRK-HOURS. *> 9(4)V9(1)へのMOVEにより自動で切捨 - 5-3.復帰(0000MAJSOR-EXTへ)。 + 5-3.復帰(0000MAINSOR-EXTへ)。 ``` diff --git a/詳細設計書/詳細設計書_ZAN03CHK.md b/詳細設計書/詳細設計書_ZAN03CHK.md index f87e5f4..b23a577 100644 --- a/詳細設計書/詳細設計書_ZAN03CHK.md +++ b/詳細設計書/詳細設計書_ZAN03CHK.md @@ -74,8 +74,8 @@ 2-1.R01キーとR02キーを比較 2-1-1.R01キー < R02キー(打刻データなし) ERROR-LOGにエラー出力する(エラーカテゴリ03)。(2010NOMATCHSOR) - 2-1-2.R01キー = R02キー(マッチ) - 時間範囲チェックを実施する。(2020MATCHSOR→2100CHKTIMSOR) + 2-1-2.R01キー = R02キー(マッチ) + 時間範囲チェックを実施する。(2020MATCHSOR) 2-1-2-1.開始時刻>=出勤時刻 かつ 終了時刻<=退勤時刻 → 通過 OVT-TYPEを設定しW01に出力する。(2200SETOVTSOR) 2-1-2-2.範囲外 → ERROR-LOGに出力(エラーカテゴリ03)