Add JavaSrc: cobol-tna-system COBOL->Java conversion (ZAN01-06/KIN01-09/KYU01-09 + 变换规则 doc)
This commit is contained in:
@@ -0,0 +1,561 @@
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import dto.Kyu03Rec;
|
||||
import dto.Kyu04Rec;
|
||||
import dto.Kyu99Rec;
|
||||
import dto.ZanendacPar;
|
||||
import dto.ZanmsgacPar;
|
||||
import util.ConvUtil;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 【COBOL→Java】KYU05DED 控除計算処理
|
||||
* ============================================================
|
||||
* PROGRAM-ID. KYU05DED → 类 Kyu05DedMain(PGMパターン:SELECT条件+DB参照)
|
||||
*
|
||||
* 使用ファイル(SELECT ASSIGN → パス定数):
|
||||
* R01INNFIL(KYU05R01 入力 FB240B) → R01INN_FILE(COPY KYU03REC → dto.Kyu03Rec)
|
||||
* W01OUTFIL(KYU05W01 出力 FB200B) → W01OUT_FILE(COPY KYU04REC → dto.Kyu04Rec)
|
||||
* W02OUTFIL(KYU05W02 出力 VB200B) → W02OUT_FILE(COPY KYU99REC → dto.Kyu99Rec 再利用)
|
||||
* 使用DB2(JDBC):
|
||||
* TAX-TABLE :SELECT ... WHERE :WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO
|
||||
* INSURANCE-TABLE:DECLARE CURSOR → FETCH全件 → WORKING-STORAGE(INSURANCE-WORK) → SEARCH
|
||||
* 使用SUB(CALL → 类#execute):
|
||||
* SUB02MSG→Sub02MsgSub / SUB03END→Sub03EndSub
|
||||
* 段落对应:
|
||||
* 0000MAJCOLSOR→run() 1000ITTSOR→initPara() 1100INSLOADSOR→insLoadPara()
|
||||
* 1200R01INNSOR→readR01Para() 2000MAJSOR→majPara() 2100WRITOUTSOR→writeW01Para()
|
||||
* 3000STPSOR→termPara() 4000MSGOUTSOR→msgOutPara() 9999ABDSOR→abendPara()
|
||||
*
|
||||
* 処理要点(詳細設計書_KYU05DED 準拠):
|
||||
* - 課税所得=総支給-基礎控除(50000)。所得税=課税所得×税率-控除額(ROUNDED、負は0)。
|
||||
* - 社会保険料=課税所得×(健康+厚生)比率(ROUNDED)。住民税=課税所得×0.10(ROUNDED)。
|
||||
* - 差引支給額=総支給-所得税-保険料-住民税。
|
||||
* - 金額計算は BigDecimal.setScale(0, HALF_UP) で COBOL ROUNDED を再現(转换基准 3.2)。
|
||||
* - 原COBOLの CONNECT TO 'data/SALARY.db' は SQLite 指定だが、設計書は DB2 を規定。
|
||||
* 转换基准「COBOLと式様書不一致は式様書優先」により DB2 URL を採用(報告書に注記)。
|
||||
*/
|
||||
public class Kyu05DedMain {
|
||||
|
||||
// ==================== コンスタント領域 CNSARA ====================
|
||||
|
||||
/** 03 CNS-PRGIDX PIC X(008) VALUE 'KYU05DED'. */
|
||||
private static final String CST_PRGIDX = "KYU05DED";
|
||||
/** 03 CNS-MSGSTR PIC 9(003) VALUE 001. 開始メッセージ */
|
||||
private static final int CST_MSGSTR = 1;
|
||||
/** 03 CNS-MSGFIN PIC 9(003) VALUE 002. 終了メッセージ */
|
||||
private static final int CST_MSGFIN = 2;
|
||||
/** 03 CNS-MSGSUBEEK PIC 9(003) VALUE 005.(設計上予約、本処理では未使用) */
|
||||
private static final int CST_MSGSUBEEK = 5;
|
||||
/** 03 CNS-MSGIINKES PIC 9(003) VALUE 006. 入力件数メッセージ */
|
||||
private static final int CST_MSGIINKES = 6;
|
||||
/** 03 CNS-MSGOUTKES PIC 9(003) VALUE 007. 出力件数メッセージ */
|
||||
private static final int CST_MSGOUTKES = 7;
|
||||
/** 03 CNS-MSGKEYINF PIC 9(003) VALUE 033. コンパイル日時メッセージ */
|
||||
private static final int CST_MSGKEYINF = 33;
|
||||
/** 03 CNS-KN0002 PIC 9(001) VALUE 2. */
|
||||
private static final int CST_KN0002 = 2;
|
||||
/** 03 CNS-ABD999 PIC 9(003) VALUE 999. */
|
||||
private static final int CST_ABD999 = 999;
|
||||
/** 03 CNS-TAX-BASIC-DEDUCTION PIC 9(006) VALUE 050000. 基礎控除 */
|
||||
private static final long CST_TAX_BASIC_DEDUCTION = 50000L;
|
||||
/** 03 CNS-RESIDENT-TAX-RATE PIC 9(001)V9(02) VALUE 0.10. 住民税率 */
|
||||
private static final BigDecimal CST_RESIDENT_TAX_RATE = new BigDecimal("0.10");
|
||||
|
||||
/** 各SQL文の定数 */
|
||||
private static final String INS_SELECT_SQL =
|
||||
"SELECT \"INS-INCOME-FROM\", \"INS-INCOME-TO\", \"INS-HEALTH-RATE\", \"INS-PENSION-RATE\" "
|
||||
+ "FROM \"INSURANCE-TABLE\" ORDER BY \"INS-INCOME-FROM\"";
|
||||
private static final String TAX_SELECT_SQL =
|
||||
"SELECT \"TAX-RATE\", \"DEDUCTION\" FROM \"TAX-TABLE\" WHERE ? BETWEEN \"TAX-FROM\" AND \"TAX-TO\"";
|
||||
|
||||
// ==================== ファイル定義(SELECT ASSIGN 相当) ====================
|
||||
|
||||
/** SELECT R01INNFIL ASSIGN TO KYU05R01.(FB 入力 240B) */
|
||||
private static final String R01INN_FILE = "data/KYU05R01.txt";
|
||||
/** SELECT W01OUTFIL ASSIGN TO KYU05W01.(FB 出力 200B) */
|
||||
private static final String W01OUT_FILE = "data/KYU05W01.txt";
|
||||
/** SELECT W02OUTFIL ASSIGN TO KYU05W02.(VB 出力 200B) */
|
||||
private static final String W02OUT_FILE = "data/KYU05W02.txt";
|
||||
|
||||
// ==================== DB 接続(EXEC SQL CONNECT 相当) ====================
|
||||
|
||||
/** DB2 接続先(設計書準拠;原COBOLの 'data/SALARY.db' は SQLite 指定のため非採用。テスト時は -Dkyu.db.url で上書き)。 */
|
||||
private static final String DB_URL = System.getProperty("kyu.db.url", "jdbc:db2://localhost:50000/TESTDB");
|
||||
private static final String DB_USER = "db2inst1";
|
||||
private static final String DB_PASS = "password";
|
||||
|
||||
// ==================== カウンタ領域 CUNARA(COMP-3 → long) ====================
|
||||
|
||||
/** 03 CUN-R01INN PIC S9(009) COMP-3 VALUE ZERO. */
|
||||
private long cunR01Inn;
|
||||
/** 03 CUN-W01OUT PIC S9(009) COMP-3 VALUE ZERO. */
|
||||
private long cunW01Out;
|
||||
/** 03 CUN-W02OUT PIC S9(009) COMP-3 VALUE ZERO. */
|
||||
private long cunW02Out;
|
||||
|
||||
// ==================== 作業領域 WRKARA ====================
|
||||
|
||||
/** 03 WRK-EOF PIC X(001). 読込フラグ(88 WRK-EOF-Y VALUE '1') */
|
||||
private String wrkEof = "0";
|
||||
/** 03 WRK-GROSS-PAYMENT PIC 9(009). */
|
||||
private long wrkGrossPayment;
|
||||
/** 03 WRK-TAXABLE-INCOME PIC 9(009). */
|
||||
private long wrkTaxableIncome;
|
||||
/** 03 WRK-INCOME-TAX PIC 9(009). */
|
||||
private long wrkIncomeTax;
|
||||
/** 03 WRK-INSURANCE PIC 9(009). */
|
||||
private long wrkInsurance;
|
||||
/** 03 WRK-RESIDENT-TAX PIC 9(009). */
|
||||
private long wrkResidentTax;
|
||||
/** 03 WRK-NET-PAYMENT PIC 9(009). */
|
||||
private long wrkNetPayment;
|
||||
|
||||
/** 88 WRK-EOF-Y VALUE '1'. */
|
||||
private boolean isEof() {
|
||||
return "1".equals(wrkEof);
|
||||
}
|
||||
|
||||
// ==================== DB2 ホスト変数 DBVARA ====================
|
||||
|
||||
/** 03 DBV-EMP-ID PIC X(008).(R01EMP-ID 設定、SQLでは未直接使用) */
|
||||
private String dbvEmpId = "";
|
||||
/** 03 DBV-TAX-RATE PIC 9(001)V9(04).(TAX-TABLE.TAX-RATE DECIMAL(5,4)) */
|
||||
private BigDecimal dbvTaxRate = BigDecimal.ZERO;
|
||||
/** 03 DBV-TAX-DEDUCTION PIC 9(009).(TAX-TABLE.DEDUCTION DECIMAL(9,0)) */
|
||||
private long dbvTaxDeduction;
|
||||
|
||||
// ==================== 保険料率 WORKING-STORAGE(SEARCH 相当) ====================
|
||||
|
||||
/** 03 IW-COUNT PIC 9(004).(OCCURS DEPENDING ON) */
|
||||
private int iwCount;
|
||||
/** 最大 200 件(OCCURS 1 TO 200)。 */
|
||||
private static final int IW_MAX = 200;
|
||||
/** 05 IW-INCOME-FROM PIC 9(009). */
|
||||
private final long[] iwIncomeFrom = new long[IW_MAX];
|
||||
/** 05 IW-INCOME-TO PIC 9(009). */
|
||||
private final long[] iwIncomeTo = new long[IW_MAX];
|
||||
/** 05 IW-HEALTH-RATE PIC V9(006).(0.xxxxxx、DECIMAL(7,6) 相当) */
|
||||
private final BigDecimal[] iwHealthRate = new BigDecimal[IW_MAX];
|
||||
/** 05 IW-PENSION-RATE PIC V9(006). */
|
||||
private final BigDecimal[] iwPensionRate = new BigDecimal[IW_MAX];
|
||||
|
||||
// ==================== サブプログラム連絡領域(LINKAGE COPY → DTO) ====================
|
||||
|
||||
/** COPY ZANMSGAC.(SUB02MSG用) */
|
||||
private final ZanmsgacPar m00MhoPar = new ZanmsgacPar();
|
||||
/** COPY ZANENDAC.(SUB03END用) */
|
||||
private final ZanendacPar e01AbdPar = new ZanendacPar();
|
||||
|
||||
// ==================== レコード(FILE SECTION → DTO) ====================
|
||||
|
||||
/** 01 R01INNREC.(FD R01INNFIL / COPY KYU03REC) */
|
||||
private final Kyu03Rec r01 = new Kyu03Rec();
|
||||
/** 01 W01OUTREC.(FD W01OUTFIL / COPY KYU04REC) */
|
||||
private final Kyu04Rec w01 = new Kyu04Rec();
|
||||
/** 01 W02OUTREC.(FD W02OUTFIL / COPY KYU99REC 再利用) */
|
||||
private final Kyu99Rec w02 = new Kyu99Rec();
|
||||
|
||||
// ==================== ファイルハンドル / DB接続(OPEN/CLOSE 相当) ====================
|
||||
|
||||
private BufferedReader r01InnFil;
|
||||
private PrintWriter w01OutFil;
|
||||
private PrintWriter w02OutFil;
|
||||
private Connection conn;
|
||||
|
||||
/** 入力ファイルパス。デフォルトは SELECT ASSIGN 対応の R01INN_FILE。 */
|
||||
private final String r01InnFile;
|
||||
|
||||
// ==================== PROCEDURE DIVISION ====================
|
||||
|
||||
public static void main(final String[] args) {
|
||||
final String inputFile = (args != null && args.length > 0) ? args[0] : R01INN_FILE;
|
||||
new Kyu05DedMain(inputFile).run();
|
||||
}
|
||||
|
||||
public Kyu05DedMain() {
|
||||
this(R01INN_FILE);
|
||||
}
|
||||
|
||||
public Kyu05DedMain(final String r01InnFile) {
|
||||
this.r01InnFile = r01InnFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 段落 0000MAJCOLSOR:制御処理。
|
||||
* PERFORM 1000ITTSOR → PERFORM 2000MAJSOR UNTIL EOF → PERFORM 3000STPSOR → GOBACK.
|
||||
*/
|
||||
private void run() {
|
||||
try {
|
||||
initPara();
|
||||
while (!isEof()) { // PERFORM 2000MAJSOR UNTIL WRK-EOF = '1'
|
||||
majPara();
|
||||
}
|
||||
termPara();
|
||||
// EXEC SQL COMMIT END-EXEC(正常終了時)
|
||||
if (conn != null) {
|
||||
conn.commit();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
// EXEC SQL WHENEVER SQLERROR 相当(DbSample パターン)
|
||||
System.out.println("[db] SQLERROR code=" + e.getErrorCode() + " msg=" + e.getMessage());
|
||||
rollbackQuiet(conn);
|
||||
abendPara(); // MOVE 999 TO E01ABDCOD / CALL SUB03END(System.exit)
|
||||
} finally {
|
||||
closeFiles();
|
||||
closeQuiet(conn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 段落 1000ITTSOR:初期処理。
|
||||
* 開始メッセージ→コンパイル日時→ワーク初期化→DB接続→INSURANCE-TABLE LOAD→OPEN→初回READ.
|
||||
*/
|
||||
private void initPara() throws SQLException {
|
||||
// *** 開始メッセージ出力
|
||||
msgOutPara(CST_MSGSTR, null, null);
|
||||
|
||||
// *** コンパイル日時出力 ※FUNCTION WHEN-COMPILED→起動時刻で代用
|
||||
final String compiled = java.time.LocalDateTime.now()
|
||||
.format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
|
||||
msgOutPara(CST_MSGKEYINF, compiled, "COMPILED");
|
||||
|
||||
// *** ワークエリア初期化 INITIALIZE WRKARA.
|
||||
cunR01Inn = 0;
|
||||
cunW01Out = 0;
|
||||
cunW02Out = 0;
|
||||
wrkEof = "0";
|
||||
wrkGrossPayment = 0;
|
||||
wrkTaxableIncome = 0;
|
||||
wrkIncomeTax = 0;
|
||||
wrkInsurance = 0;
|
||||
wrkResidentTax = 0;
|
||||
wrkNetPayment = 0;
|
||||
dbvEmpId = "";
|
||||
dbvTaxRate = BigDecimal.ZERO;
|
||||
dbvTaxDeduction = 0;
|
||||
iwCount = 0;
|
||||
|
||||
// *** DB接続 EXEC SQL CONNECT TO 'data/SALARY.db'(設計書準拠で DB2 URL を使用)
|
||||
conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
|
||||
conn.setAutoCommit(false); // 批処理標準(DbSample パターン)
|
||||
|
||||
// *** 使用ファイル OPEN INPUT R01INNFIL / OUTPUT W01OUTFIL W02OUTFIL.
|
||||
openFiles();
|
||||
|
||||
// *** INSURANCE-TABLE 全件 LOAD(1100INSLOADSOR)
|
||||
insLoadPara();
|
||||
|
||||
// *** 初回 READ(1200R01INNSOR)
|
||||
readR01Para();
|
||||
}
|
||||
|
||||
/**
|
||||
* 段落 1100INSLOADSOR:INSURANCE-TABLE 全件 LOAD 処理。
|
||||
* DECLARE/OPEN CURSOR → FETCH ループ → INSURANCE-WORK 配列へ格納 → CLOSE CURSOR.
|
||||
* OPEN/FETCH 異常(SQLCODE NOT = 0)時は W02 に詳細を書き ABEND.
|
||||
*/
|
||||
private void insLoadPara() {
|
||||
try {
|
||||
// EXEC SQL DECLARE INS-CURSOR CURSOR FOR ... / OPEN は executeQuery で暗黙実行
|
||||
try (PreparedStatement ps = conn.prepareStatement(INS_SELECT_SQL);
|
||||
ResultSet rs = ps.executeQuery()) { // OPEN INS-CURSOR
|
||||
// PERFORM UNTIL SQLCODE NOT = 0(rs.next() == false で終了)
|
||||
while (rs.next()) {
|
||||
iwCount++; // ADD 1 TO IW-COUNT
|
||||
final int idx = iwCount - 1; // 1-based → 0-based
|
||||
// MOVE DBV-INS-* TO IW-*(OW 配列へ格納)
|
||||
iwIncomeFrom[idx] = rs.getLong("INS-INCOME-FROM");
|
||||
iwIncomeTo[idx] = rs.getLong("INS-INCOME-TO");
|
||||
// DECIMAL(7,6) → scale 6(PIC V9(006) 相当)
|
||||
iwHealthRate[idx] = rs.getBigDecimal("INS-HEALTH-RATE");
|
||||
iwPensionRate[idx] = rs.getBigDecimal("INS-PENSION-RATE");
|
||||
}
|
||||
} // CLOSE INS-CURSOR(自動)
|
||||
} catch (SQLException e) {
|
||||
// IF SQLCODE NOT = 0 → MOVE 'INS-CURSOR OPEN ERR' TO W02ERR-DETAIL / PERFORM 9999ABDSOR
|
||||
w02.reset();
|
||||
w02.setErrDetail("INS-CURSOR OPEN ERR");
|
||||
writeW02();
|
||||
abendPara();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 段落 1200R01INNSOR:R01 読込処理。
|
||||
* READ AT END → SET WRK-EOF-Y / NOT AT END → ADD 1 TO CUN-R01INN.
|
||||
*/
|
||||
private void readR01Para() {
|
||||
try {
|
||||
final String line = r01InnFil.readLine();
|
||||
if (line == null) {
|
||||
// AT END: SET WRK-EOF-Y TO TRUE.
|
||||
wrkEof = "1";
|
||||
} else {
|
||||
// NOT AT END: MOVE R01INNREC … / ADD 1 TO CUN-R01INN.
|
||||
r01.setRecordLine(line);
|
||||
cunR01Inn++;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e); // READ異常 ≈ ABEND
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 段落 2000MAJSOR:主処理。
|
||||
* 課税所得→所得税(SELECT BETWEEN)→社会保険料(SEARCH)→住民税→差引支給額→W01出力→次READ.
|
||||
*/
|
||||
private void majPara() {
|
||||
// MOVE R01GROSS-PAYMENT TO WRK-GROSS-PAYMENT.
|
||||
wrkGrossPayment = r01.getGrossPayment();
|
||||
// MOVE R01EMP-ID TO DBV-EMP-ID.
|
||||
dbvEmpId = r01.getEmpId();
|
||||
|
||||
// *** 課税所得計算(IF WRK-GROSS-PAYMENT < CNS-TAX-BASIC-DEDUCTION …)
|
||||
if (wrkGrossPayment < CST_TAX_BASIC_DEDUCTION) {
|
||||
// MOVE ZERO TO WRK-TAXABLE-INCOME.
|
||||
wrkTaxableIncome = 0;
|
||||
} else {
|
||||
// COMPUTE WRK-TAXABLE-INCOME = WRK-GROSS-PAYMENT - CNS-TAX-BASIC-DEDUCTION.
|
||||
wrkTaxableIncome = wrkGrossPayment - CST_TAX_BASIC_DEDUCTION;
|
||||
}
|
||||
|
||||
// *** TAX-TABLE 参照(SELECT ... BETWEEN)→ 所得税計算
|
||||
taxSelectPara();
|
||||
|
||||
// *** 社会保険料計算(SEARCH IW-ENTRY)
|
||||
insSearchPara();
|
||||
|
||||
// *** 住民税計算 COMPUTE WRK-RESIDENT-TAX ROUNDED = 課税所得 × 0.10.
|
||||
BigDecimal resident = BigDecimal.valueOf(wrkTaxableIncome)
|
||||
.multiply(CST_RESIDENT_TAX_RATE)
|
||||
.setScale(0, RoundingMode.HALF_UP);
|
||||
wrkResidentTax = resident.longValue();
|
||||
|
||||
// *** 差引支給額 COMPUTE WRK-NET-PAYMENT = 総支給 - 所得税 - 保険料 - 住民税.
|
||||
wrkNetPayment = wrkGrossPayment - wrkIncomeTax - wrkInsurance - wrkResidentTax;
|
||||
|
||||
// *** W01 出力(2100WRITOUTSOR)
|
||||
writeW01Para();
|
||||
|
||||
// *** 次レコード読込(1200R01INNSOR)
|
||||
readR01Para();
|
||||
}
|
||||
|
||||
/**
|
||||
* 段落 2000MAJSOR 内:DB2 TAX-TABLE 税率取得(EXEC SQL SELECT ... BETWEEN)。
|
||||
* SQLCODE = 0 の場合のみ所得税を計算(負数は 0 に補正)、それ以外は 0.
|
||||
*/
|
||||
private void taxSelectPara() {
|
||||
wrkIncomeTax = 0; // 既定(SQLCODE NOT = 0 / エラー時は 0)
|
||||
try (PreparedStatement ps = conn.prepareStatement(TAX_SELECT_SQL)) {
|
||||
// WHERE :WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO
|
||||
ps.setLong(1, wrkTaxableIncome);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) { // IF SQLCODE = 0
|
||||
// INTO :DBV-TAX-RATE, :DBV-TAX-DEDUCTION
|
||||
dbvTaxRate = rs.getBigDecimal("TAX-RATE"); // DECIMAL(5,4)
|
||||
dbvTaxDeduction = rs.getLong("DEDUCTION"); // DECIMAL(9,0)
|
||||
// COMPUTE WRK-INCOME-TAX ROUNDED = 課税所得 × 税率 - 控除額.
|
||||
BigDecimal incomeTax = BigDecimal.valueOf(wrkTaxableIncome)
|
||||
.multiply(dbvTaxRate)
|
||||
.subtract(BigDecimal.valueOf(dbvTaxDeduction))
|
||||
.setScale(0, RoundingMode.HALF_UP);
|
||||
long it = incomeTax.longValue();
|
||||
if (it < 0) {
|
||||
it = 0; // IF WRK-INCOME-TAX < ZERO → MOVE ZERO.
|
||||
}
|
||||
wrkIncomeTax = it;
|
||||
}
|
||||
// ELSE(SQLCODE NOT = 0)→ WRK-INCOME-TAX は 0 のまま
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
// SQLCODE NOT = 0(実エラー含む)→ WRK-INCOME-TAX = 0(COBOL の ELSE 分岐と同義)
|
||||
wrkIncomeTax = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 段落 2000MAJSOR 内:社会保険料計算(SEARCH IW-ENTRY)。
|
||||
* 条件:IW-INCOME-FROM(idx) ≦ 課税所得 AND 課税所得 ≦ IW-INCOME-TO(idx)
|
||||
* AT END → WRK-INSURANCE = 0.
|
||||
*/
|
||||
private void insSearchPara() {
|
||||
boolean found = false;
|
||||
// SET IW-IDX TO 1 からの SEARCH(順次スキャン:COBOL SEARCH IW-ENTRY 相当)
|
||||
for (int i = 0; i < iwCount; i++) {
|
||||
if (iwIncomeFrom[i] <= wrkTaxableIncome && wrkTaxableIncome <= iwIncomeTo[i]) {
|
||||
// COMPUTE WRK-INSURANCE ROUNDED = 課税所得 × (健康比率 + 厚生比率).
|
||||
final BigDecimal sum = iwHealthRate[i].add(iwPensionRate[i]); // 双方 scale 6
|
||||
BigDecimal insurance = BigDecimal.valueOf(wrkTaxableIncome)
|
||||
.multiply(sum)
|
||||
.setScale(0, RoundingMode.HALF_UP);
|
||||
wrkInsurance = insurance.longValue();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
wrkInsurance = 0; // AT END: MOVE ZERO TO WRK-INSURANCE.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 段落 2100WRITOUTSOR:SALARY-NET 出力処理。
|
||||
* MOVE 各項目 → W01OUTREC/WRITE W01OUTREC/ADD 1 TO CUN-W01OUT.
|
||||
*/
|
||||
private void writeW01Para() {
|
||||
w01.reset();
|
||||
// MOVE R01EMP-ID TO W01EMP-ID.
|
||||
w01.setEmpId(r01.getEmpId());
|
||||
// MOVE 'S' TO W01REC-TYPE.
|
||||
w01.setRecType("S");
|
||||
// MOVE R01EMP-NAME TO W01EMP-NAME.
|
||||
w01.setEmpName(r01.getEmpName());
|
||||
// MOVE R01DEPT-CODE TO W01DEPT-CODE.
|
||||
w01.setDeptCode(r01.getDeptCode());
|
||||
// MOVE R01BASE-SALARY TO W01GROSS-PAYMENT.(設計書:設定元 R01BASE-SALARY)
|
||||
w01.setGrossPayment(r01.getBaseSalary());
|
||||
// MOVE WRK-INCOME-TAX TO W01INCOME-TAX.
|
||||
w01.setIncomeTax(wrkIncomeTax);
|
||||
// MOVE WRK-INSURANCE TO W01INSURANCE.
|
||||
w01.setInsurance(wrkInsurance);
|
||||
// MOVE WRK-RESIDENT-TAX TO W01RESIDENT-TAX.
|
||||
w01.setResidentTax(wrkResidentTax);
|
||||
// MOVE WRK-NET-PAYMENT TO W01NET-PAYMENT.
|
||||
w01.setNetPayment(wrkNetPayment);
|
||||
// MOVE WRK-TAXABLE-INCOME TO W01TAXABLE-INCOME.
|
||||
w01.setTaxableIncome(wrkTaxableIncome);
|
||||
// MOVE WRK-NET-PAYMENT TO W01PAY-AMOUNT.
|
||||
w01.setPayAmount(wrkNetPayment);
|
||||
writeW01();
|
||||
}
|
||||
|
||||
/**
|
||||
* 段落 3000STPSOR:終了処理。
|
||||
* CLOSE → 入出力件数メッセージ×3 → 終了メッセージ.
|
||||
*/
|
||||
private void termPara() {
|
||||
closeFiles();
|
||||
msgOutPara(CST_MSGIINKES, "KYU05R01", ConvUtil.padLeftZero(cunR01Inn, 9));
|
||||
msgOutPara(CST_MSGOUTKES, "KYU05W01", ConvUtil.padLeftZero(cunW01Out, 9));
|
||||
msgOutPara(CST_MSGOUTKES, "KYU05W02", ConvUtil.padLeftZero(cunW02Out, 9));
|
||||
msgOutPara(CST_MSGFIN, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 段落 4000MSGOUTSOR:メッセージ編集出力処理。
|
||||
* M00UMKDATS22-03(1:1)/-04(1:1) に '2'、-05 にプログラムIDを設定し SUB02MSG を呼ぶ。
|
||||
*/
|
||||
private void msgOutPara(final int msgCod, final String p1, final String p2) {
|
||||
m00MhoPar.reset();
|
||||
m00MhoPar.setM00MsgCod(msgCod);
|
||||
if (p1 != null) {
|
||||
m00MhoPar.setM00Umkdats2201(p1);
|
||||
}
|
||||
if (p2 != null) {
|
||||
m00MhoPar.setM00Umkdats2202(p2);
|
||||
}
|
||||
m00MhoPar.setM00Umkdats2203(ConvUtil.padRight(Integer.toString(CST_KN0002), 30));
|
||||
m00MhoPar.setM00Umkdats2204(ConvUtil.padRight(Integer.toString(CST_KN0002), 30));
|
||||
m00MhoPar.setM00Umkdats2205(CST_PRGIDX);
|
||||
Sub02MsgSub.execute(m00MhoPar);
|
||||
}
|
||||
|
||||
/**
|
||||
* 段落 9999ABDSOR:ABEND 処理。
|
||||
* MOVE 999 TO E01ABDCOD./CALL 'SUB03END' USING E01ABDPAR.
|
||||
*/
|
||||
private void abendPara() {
|
||||
e01AbdPar.reset();
|
||||
e01AbdPar.setE01AbdCod(CST_ABD999);
|
||||
Sub03EndSub.execute(e01AbdPar);
|
||||
}
|
||||
|
||||
// ==================== ファイル操作補助(OPEN/CLOSE/WRITE 相当) ====================
|
||||
|
||||
/** OPEN INPUT R01INNFIL / OUTPUT W01OUTFIL W02OUTFIL. */
|
||||
private void openFiles() {
|
||||
try {
|
||||
r01InnFil = new BufferedReader(
|
||||
new InputStreamReader(new FileInputStream(r01InnFile), StandardCharsets.UTF_8));
|
||||
w01OutFil = new PrintWriter(
|
||||
new OutputStreamWriter(new FileOutputStream(W01OUT_FILE), StandardCharsets.UTF_8));
|
||||
w02OutFil = new PrintWriter(
|
||||
new OutputStreamWriter(new FileOutputStream(W02OUT_FILE), StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e); // OPEN失敗 ≈ ABEND
|
||||
}
|
||||
}
|
||||
|
||||
/** WRITE W01OUTREC./ADD 1 TO CUN-W01OUT. */
|
||||
private void writeW01() {
|
||||
w01OutFil.println(w01.toRecordLine());
|
||||
cunW01Out++;
|
||||
}
|
||||
|
||||
/** WRITE W02OUTREC./ADD 1 TO CUN-W02OUT. */
|
||||
private void writeW02() {
|
||||
w02OutFil.println(w02.toRecordLine());
|
||||
cunW02Out++;
|
||||
}
|
||||
|
||||
/** CLOSE R01INNFIL W01OUTFIL W02OUTFIL. */
|
||||
private void closeFiles() {
|
||||
closeQuiet(r01InnFil);
|
||||
closeQuiet(w01OutFil);
|
||||
closeQuiet(w02OutFil);
|
||||
r01InnFil = null;
|
||||
w01OutFil = null;
|
||||
w02OutFil = null;
|
||||
}
|
||||
|
||||
private static void closeQuiet(final Object handle) {
|
||||
try {
|
||||
if (handle instanceof BufferedReader) {
|
||||
((BufferedReader) handle).close();
|
||||
} else if (handle instanceof PrintWriter) {
|
||||
((PrintWriter) handle).close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// CLOSE異常は無視(原程序も FILE STATUS 未管理)
|
||||
}
|
||||
}
|
||||
|
||||
/** EXEC SQL ROLLBACK END-EXEC(異常時) */
|
||||
private static void rollbackQuiet(final Connection c) {
|
||||
if (c != null) {
|
||||
try {
|
||||
c.rollback();
|
||||
System.out.println("[db] ROLLBACK DONE");
|
||||
} catch (SQLException e) {
|
||||
System.out.println("[db] ROLLBACK FAILED: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void closeQuiet(final Connection c) {
|
||||
if (c != null) {
|
||||
try {
|
||||
c.close();
|
||||
} catch (SQLException e) {
|
||||
System.out.println("[db] CLOSE FAILED: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user