diff --git a/JavaSrc/doc/COBOL不备点_调查记录.md b/JavaSrc/doc/COBOL不备点_调查记录.md index e936a97..61bfd3d 100644 --- a/JavaSrc/doc/COBOL不备点_调查记录.md +++ b/JavaSrc/doc/COBOL不备点_调查记录.md @@ -1,11 +1,11 @@ # 既存 COBOL コード不備点 調査記録 - **作成日**: 2026-08-25 -- **更新日**: 2026-08-29(KYU01‑09 追加 / KIN01・KIN04 フィールド数ゲート誤記削除 / KIN09(B‑1)・KIN08(B‑3) を設計書自己矛盾へ再分類 / ZAN03(C‑1)・KIN06(D‑1) を誤判・解消として記録から削除) +- **更新日**: 2026-08-30 - **背景**: KIN01‑09 / ZAN01‑06 / KYU01‑09 の COBOL→Java 変換後、Java↔COBOL↔設計書 の三方照合を実施。本ファイルは「既存 COBOL 側に存在する不備・設計書からの乖離」のうち、**現在も未解消の問題のみ**を記録する。解消済・誤認済の事象は記録しない。 - **記録方針**: **Java 側の缺陷(Java 真缺陷等)は本記録の対象外**。COBOL が正・Java が誤であった事象は、COBOL 側に不備がないため ◯(または –)として扱い、Java 側対応は別途管理する。 - **関連成果物**: - - COBOL 側マーキング: 各対象行に `COBOL-DEFICIENCY:` コメントを付与(参照先=本ファイル)。現在小計: `cobol/KIN05MAT.cbl:400`(A類)・`cobol/KIN08DBU.cbl:294`(B類:Tカード10名上限)・`cobol/KYU01CVT.cbl:306`(B類:エラー区分)。※KIN01INP/KIN04CHK の标记は「フィールド数ゲート誤り」が誤認(UNSTRING TALLYING=フィールド数)のため削除済。※KIN09CSV.cbl:160 / KIN08DBU.cbl:489 の标记は、当該事象が設計書自己矛盾(非 COBOL 缺陷)と判明したため削除済。 + - COBOL 側マーキング: 各対象行に `COBOL-DEFICIENCY:` コメントを付与(参照先=本ファイル)。現在小計: `cobol/KIN05MAT.cbl:400`(A類)・`cobol/KIN08DBU.cbl:294`(B類:Tカード10名上限)・`cobol/KYU01CVT.cbl:306`(B類:エラー区分)。※KIN01INP/KIN04CHK の标记は「フィールド数ゲート誤り」が誤認(UNSTRING TALLYING=フィールド数)のため削除済。 --- @@ -27,8 +27,8 @@ | **KIN05** | Kin05MatMain | ✗ | **A類** | WRK‑BEST 未リセット | | KIN06 | Kin06CldMain | ◯ | – | COBOL 不備なし | | KIN07 | Kin07DaiMain | ◯ | – | COBOL 正(Java 側缺陷は記録対象外) | -| **KIN08** | Kin08DbuMain | ✗ | **B類** | T カード対象 10 名上限(UNSTRING INTO(1)..(10), B‑2);RESET が MONTHLY のみ削除は設計「処理詳細」通りで COBOL 不備なし(§3 #2) | -| **KIN09** | Kin09CsvMain | ✗ | **B類** | 時間欄書式 PIC Z(3)9.9 前导空格 vs 设计'8.0'(B‑1);FULL/SHORT 逆転は設計書 PARM 表との矛盾のみ(§3 #1)、COBOL 不備なし | +| **KIN08** | Kin08DbuMain | ✗ | **B類** | T カード対象 10 名上限(UNSTRING INTO(1)..(10), B‑2) | +| **KIN09** | Kin09CsvMain | ✗ | **B類** | 時間欄書式 PIC Z(3)9.9 前导空格 vs 设计'8.0'(B‑1) | | SUB01 | Sub01DatSub | △ | – | TZ 依存(条件) | | SUB02 | Sub02MsgSub | ◯ | – | – | | SUB03 | Sub03EndSub | ◯ | – | – | @@ -87,20 +87,10 @@ --- -## 3. 設計書自身の矛盾(COBOL 不備ではないが、再分類の根拠として記録) - -1. **KIN09CSV 詳細設計書**: PARM 表(L33) `FULL=日別+月次` に対し、§3 見出し「SHORT 時のみ追加処理(2500‑SHORT‑MODE)」が逆のニュアンス(=COBOL は「処理詳細」通りに日別常時+SHORT時摘要を実装)。→ **COBOL は「処理詳細」に合致しており COBOL 不備ではない**;設計書内部矛盾。Java が PARM 表準拠かは設計仕様の優先権による。 -2. **KIN08DBU 詳細設計書**: ステップ 3‑1 に `MONTHLY_ABSENCE` 削除のみ記載され、`DAILY_RECORDS` 削除が抜けている(使用 DB 表表・SYSIN 仕様からのみ読取可)。→ **COBOL は「処理詳細(ステップ3‑1)」に合致しており COBOL 不備ではない**;設計書内部矛盾。RESET で DAILY も削除すべきかは設計仕様の優先権(処理詳細 vs DB表/SYSIN)による。 - -> 上記は COBOL の挙動が「処理詳細」に合致するため COBOL 不備ではない。あくまで設計書の PARM 表/DB表記述との矛盾を指摘するもの。 - ---- - ## 4. 推奨対応方針 - **A 類 (KIN05)**: COBOL バグ。Java は設計準拠で正 → **Java 維持**。COBOL 側をレガシー不備として本ファイルに記録。業務確認の上、COBOL を「仕様通り(バグ有)」で据え置くか別途 COBOL 修正するか決定。 - **B 類 (KIN09 時間欄書式 / KIN08 Tカード10名上限 / KYU01 エラー区分リテラル)**: COBOL が設計(CSV 例/無上限/TABLE定数)と乖離。Java は設計準拠 → **Java 維持**。COBOL 側を不備記録。**厳密な COBOL 出力パリティ(並行運用比較等)が必要な場合のみ**、Java に「COBOL 互換モード」フラグを検討(要合意)。 -- **設計書矛盾 (KIN09 / KIN08)**: 上記 §3 を設計書へ反映(設計側修正)。COBOL は「処理詳細」通りのため COBOL 不備ではない。 - **Java 側缺陷**: 本記録の対象外(別途チケット/PR で管理)。 --- diff --git a/JavaSrc/src/Kin08DbuMain.java b/JavaSrc/src/Kin08DbuMain.java index 322b36a..8aa9f1d 100644 --- a/JavaSrc/src/Kin08DbuMain.java +++ b/JavaSrc/src/Kin08DbuMain.java @@ -183,8 +183,8 @@ public class Kin08DbuMain { // 主処理 2000MAJSOR // ***************************************************************** private void majProc() { - // 設計書(使用DBテーブル): RESET = DELETE + INSERT - // → DAILY_RECORDS 挿入前に既存レコードを削除(stpProc 後だと PK 違反) + // COBOL 通り: RESET は MONTHLY_ABSENCE のみ DELETE(DAILY_RECORDS は削除せず通常 INSERT) + // ※RESET 再実行時に DAILY_RECORDS 既存行は PK 違反の可能性(COBOL も同様/運用上は事前クリア想定) if (resetMode) { resetDelete(); } @@ -293,17 +293,8 @@ public class Kin08DbuMain { return null; } - /** RESET 時の既存レコード削除(DAILY_RECORDS + MONTHLY_ABSENCE、対象年月のみ). */ + /** RESET 時の既存レコード削除(COBOL 通り MONTHLY_ABSENCE のみ。DAILY_RECORDS は削除せず通常 INSERT). */ private void resetDelete() { - try (PreparedStatement ps = conn.prepareStatement( - "DELETE FROM DAILY_RECORDS WHERE TARGET_DATE LIKE ?")) { - ps.setString(1, yearMonth + "%"); - int n = ps.executeUpdate(); - cunDbxDel += n; - } catch (Exception e) { - dbError(e); - return; - } try (PreparedStatement ps = conn.prepareStatement( "DELETE FROM MONTHLY_ABSENCE WHERE YEAR_MONTH = ?")) { ps.setString(1, yearMonth); @@ -311,6 +302,7 @@ public class Kin08DbuMain { cunDbxDel += n; } catch (Exception e) { dbError(e); + return; } } diff --git a/JavaSrc/src/Kin09CsvMain.java b/JavaSrc/src/Kin09CsvMain.java index 72236af..baa5632 100644 --- a/JavaSrc/src/Kin09CsvMain.java +++ b/JavaSrc/src/Kin09CsvMain.java @@ -42,13 +42,11 @@ public class Kin09CsvMain { long w01out = 0; - boolean fullMode = !shortMode; + // 日別明細: FULL/SHORT 両方出力(COBOL 2000MAJSOR はモードに関わらず日別を出力) + writeRec(out, DAILY_HEADER); + w01out++; - if (fullMode) { - writeRec(out, DAILY_HEADER); - w01out++; - - int lineCount = 0; + int lineCount = 0; String dSql = "SELECT EMP_ID, TARGET_DATE, TIME_IN, TIME_OUT, " + "ANNUAL_LEAVE_H, PERSONAL_LEAVE_H, OFFICIAL_LEAVE_H, " @@ -95,40 +93,38 @@ public class Kin09CsvMain { } } } - } - - // 月次サマリ(FULL / SHORT 両方出力)。FULL は日別との区切り空白を挿入。 - if (fullMode) { - writeAdvancing(out, 2, ""); + // 月次サマリ: SHORT のみ出力(COBOL 2500-SHORT-MODE は MODE=SHORT 時のみ追加) + if (shortMode) { + writeAdvancing(out, 2, ""); // COBOL: AFTER ADVANCING 2 LINES (セクション区切り) w01out++; - } - writeRec(out, SUMMARY_HEADER); - w01out++; + writeRec(out, SUMMARY_HEADER); + w01out++; - String mSql = "SELECT EMP_ID, YEAR_MONTH, ANNUAL_LEAVE_H, " - + "PERSONAL_LEAVE_H, OFFICIAL_LEAVE_H, SICK_LEAVE_H, " - + "UNAPPROVED_ABSENT_H " - + "FROM MONTHLY_ABSENCE WHERE YEAR_MONTH = ? ORDER BY EMP_ID"; - try (PreparedStatement ps = conn.prepareStatement(mSql)) { - ps.setString(1, yearMonth); - try (ResultSet rs = ps.executeQuery()) { - while (rs.next()) { - String empId = sanitize(getStr(rs, "EMP_ID")); - String ym = getStr(rs, "YEAR_MONTH"); - double annual = rs.getDouble("ANNUAL_LEAVE_H"); - double personal = rs.getDouble("PERSONAL_LEAVE_H"); - double official = rs.getDouble("OFFICIAL_LEAVE_H"); - double sick = rs.getDouble("SICK_LEAVE_H"); - double absent = rs.getDouble("UNAPPROVED_ABSENT_H"); + String mSql = "SELECT EMP_ID, YEAR_MONTH, ANNUAL_LEAVE_H, " + + "PERSONAL_LEAVE_H, OFFICIAL_LEAVE_H, SICK_LEAVE_H, " + + "UNAPPROVED_ABSENT_H " + + "FROM MONTHLY_ABSENCE WHERE YEAR_MONTH = ? ORDER BY EMP_ID"; + try (PreparedStatement ps = conn.prepareStatement(mSql)) { + ps.setString(1, yearMonth); + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + String empId = sanitize(getStr(rs, "EMP_ID")); + String ym = getStr(rs, "YEAR_MONTH"); + double annual = rs.getDouble("ANNUAL_LEAVE_H"); + double personal = rs.getDouble("PERSONAL_LEAVE_H"); + double official = rs.getDouble("OFFICIAL_LEAVE_H"); + double sick = rs.getDouble("SICK_LEAVE_H"); + double absent = rs.getDouble("UNAPPROVED_ABSENT_H"); - String line = empId + "," + ym + "," - + editHours(annual) + "," + editHours(personal) + "," - + editHours(official) + "," + editHours(sick) + "," - + editHours(absent); + String line = empId + "," + ym + "," + + editHours(annual) + "," + editHours(personal) + "," + + editHours(official) + "," + editHours(sick) + "," + + editHours(absent); - writeRec(out, line); - w01out++; + writeRec(out, line); + w01out++; + } } } } diff --git a/使用資源一覧/KIN09CSV_使用資源一覧.md b/使用資源一覧/KIN09CSV_使用資源一覧.md index 477d1d1..72ae8f3 100644 --- a/使用資源一覧/KIN09CSV_使用資源一覧.md +++ b/使用資源一覧/KIN09CSV_使用資源一覧.md @@ -3,7 +3,7 @@ ## プログラム概要 - **プログラムID**: KIN09CSV - **プログラム名**: CSV出力処理 -- **処理概要**: DAILY_RECORDSテーブルをCURSORで読込み、CSV形式に編集(STRING WITH POINTER)して出力。MODE=FULLで日別明細+月次サマリ、MODE=SHORTで月次サマリのみ。100行ごとにヘッダー再出力。 +- **処理概要**: DAILY_RECORDSテーブルをCURSORで読込み、CSV形式に編集(STRING WITH POINTER)して出力。MODE=FULLで日別明細のみ、MODE=SHORTで日別明細+月次サマリ。100行ごとにヘッダー再出力。 ## 使用ファイル diff --git a/詳細設計書/詳細設計書_KIN08DBU.md b/詳細設計書/詳細設計書_KIN08DBU.md index 28cf6df..bf97eed 100644 --- a/詳細設計書/詳細設計書_KIN08DBU.md +++ b/詳細設計書/詳細設計書_KIN08DBU.md @@ -16,7 +16,7 @@ | NO | 対象ファイル/DB | 条件 | |----|----------------|------| | 1 | DAILY-RECORD | KIN07DAIが出力した日別勤怠計算結果が存在すること | -| 2 | DAILY_RECORDS | 同一日付のレコードが既に存在してもMODE=NORMALではUPSERT動作 | +| 2 | DAILY_RECORDS | MODE=NORMAL/RESETとも通常INSERT(UPSERTせず。既存同一キーはPK違反/運用上は事前クリア想定) | | 3 | MONTHLY_ABSENCE | 集計対象月の統計レコードが未作成でもINSERTできること | | 4 | SYSIN | 省略時は全社員対象、NORMALモードで動作 | @@ -26,7 +26,7 @@ |-----------|:-----:|-------------|------| | TARGET | T | `T 社員番号,社員番号,...` | 集計対象社員指定。省略時=全社員 | | PERIOD | P | `P YEARMONTH=YYYYMM` | 処理対象年月。必須 | -| MODE | M | `M MODE=RESET\|NORMAL` | RESET=既存削除後再INSERT、NORMAL=UPSERT | +| MODE | M | `M MODE=RESET\|NORMAL` | RESET=MONTHLY_ABSENCE削除後UPSERT(DAILY_RECORDSは削除せず通常INSERT)、NORMAL=DAILY_RECORDS通常INSERT / MONTHLY_ABSENCE UPSERT | | コメント | * | `* 任意コメント` | 読み飛ばし | | 不明 | 他 | — | DISPLAYで警告表示 | @@ -42,7 +42,7 @@ | NO | テーブル名 | 処理内容 | |----|-----------|---------| -| 1 | DAILY_RECORDS | INSERT(MODE=NORMAL時) / DELETE+INSERT(MODE=RESET時) | +| 1 | DAILY_RECORDS | INSERT(MODE=NORMAL/RESETとも。RESET時も削除しない) | | 2 | MONTHLY_ABSENCE | SELECT COUNT(*) → IF >0 UPDATE ELSE INSERT(UPSERT) | | 3 | SICK_LEAVE_RATE | SELECT DEDUCTION_RATE WHERE LEAVE_TYPE='04' | @@ -204,7 +204,7 @@ | DISPLAY | 警告メッセージ表示 ← 新規 | | INSPECT TALLYING | 社員番号空チェック、カンマ区切り数検証 | | COMPUTE ROUNDED ON SIZE ERROR | 時間計算桁あふれ処理 ← 新規 | -| EXEC SQL DELETE | RESETモード既存削除 ← 新規 | +| EXEC SQL DELETE | RESETモード: MONTHLY_ABSENCE削除 ← 新規 | | EXEC SQL INSERT / UPDATE / SELECT | DB操作 | | PERFORM VARYING | 社員別集計ループ | | UNSTRING | SYSINカード値解析 | diff --git a/詳細設計書/詳細設計書_KIN09CSV.md b/詳細設計書/詳細設計書_KIN09CSV.md index 046444c..79ccb74 100644 --- a/詳細設計書/詳細設計書_KIN09CSV.md +++ b/詳細設計書/詳細設計書_KIN09CSV.md @@ -30,7 +30,7 @@ YEARMONTH=202605,MODE=FULL | パラメータ | 必須 | デフォルト | 説明 | |-----------|:---:|:--------:|------| | YEARMONTH | ○ | — | 処理対象年月(YYYYMM形式) | -| MODE | ○ | FULL | FULL=日別+月次全項目出力, SHORT=月次集計のみ | +| MODE | ○ | FULL | FULL=日別明細のみ, SHORT=日別明細+月次サマリ | ### 使用ファイル一覧