# Business Logic — JBSbatKKKojiKnrIfFileLoad.setKojiFinInf() [220 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.business.service.JBSbatKKKojiKnrIfFileLoad` |
| Layer | Service (Batch) |
| Module | `service` (Package: `eo.business.service`) |

## 1. Role

### JBSbatKKKojiKnrIfFileLoad.setKojiFinInf()

This method processes **construction completion information data** (工事完了情報データ) received from an external construction notification file. It is part of the eo Customer Core System's work-related information receiving file load batch (工事関連情報受信ファイル読込部), which ingests flat-file records containing job completion notices for telecom infrastructure projects.

The method implements a **validation-then-transform** pattern: first, it validates all 18 fields of the construction completion record against strict format rules (numeric-only checks, date validation, length checks, and character set restrictions). If any validation fails, an error counter is incremented. Only when all fields pass validation (`err_cunt == 0`) does the method proceed to the second phase — assembling the validated fields into a comma-delimited CSV string, appending a newline record separator, and storing the result into a `StringBuilder` accumulator that will later be written to an output file.

As a **routing/dispatch** entry point within the file-load batch (`execute()` method), this method is responsible for the record division type "40: Construction Completion Information" (レコード区分が「40：工事完了情報」). It is called sequentially by `JBSbatKKKojiKnrIfFileLoad.execute()` as each file record is parsed, making it a shared utility method invoked by many batch records rather than a screen-level entry point. When the special case of empty "new change division" and zero "sequence number" is detected, the method performs a **record skip** — returning early without appending anything to the output, effectively filtering out placeholder/dummy records.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["setKojiFinInf(data_list, koji_fin_inf)"])
    DEBUG1["printDebugLog: setKojiFinInf_START"]
    INIT["err_cunt = 0"]

    V1["isHannkakuESuuji field[1] svc_ct_no"]
    V2["isHannkakuESuuji field[2] svc_ct_line_no"]
    V3["isYearMonthDay field[3] renkou_ymd"]
    V4["isHannkakuSuuji1 field[4] tsuuban"]
    V5["isHannkakuESuuji field[5] shin_kai_kubun"]
    V6["isHannkakuESuuji field[6] koji_an_kei_sbt_cd"]
    V7["isHannkakuESuuji field[7] koji_an_ban"]
    V8["isHannkakuESuuji field[8] koji_an_rslt_cd"]
    V9["check 99999999 field[9] koji_an_ymd"]
    V9_REAL["isYearMonthDay field[9]"]
    V9_SKIP["set LAST_YEAR (20991231)"]
    V9_NYMD["isYearMonthDay field[9]"]
    V10["isHannkakuESuuji field[10] pon_sbt_cd"]
    V11["isHannkakuSuuji1 field[11] koji_kinhyo(std)"]
    V12["isHannkakuSuuji1 field[12] koji_kinhyo(out_std)"]
    V13["isHannkakuSuuji1 field[13] koji_kinhyo_std_phone"]
    V14["isHannkakuSuuji1 field[14] koji_kinhyo_out_phone"]
    V15["isHannkakuSuuji1 field[15] koji_kinhyo_std_lan"]
    V16["isHannkakuSuuji1 field[16] koji_kinhyo_out_lan"]
    V17["isHannkakuESuuji field[17] koji_range_cd"]

    ERR1["err_cunt++"]
    ERR2["err_cunt++"]

    CHK_ERR{err_cunt == 0?}
    SKIP_CHECK{empty newChgDiv AND seq=000000000000?}
    SKIP["return (record skip)"]

    BUILD["Build CSV: append fields 1-8 + comma + field[9] logic + fields 10-17 + field[0] + KAIGYOU_CODE"]
    DEBUG_END["printDebugLog: setKojiFinInf_END"]
    END(["Return / Next"])

    START --> DEBUG1 --> INIT
    INIT --> V1
    V1 -->|fail| ERR1
    V1 -->|ok| V2
    ERR1 --> V2
    V2 -->|fail| ERR2
    V2 -->|ok| V3
    ERR2 --> V3
    V3 -->|fail| V4
    V3 -->|ok| V4
    V4 -->|fail| V5
    V4 -->|ok| V5
    V5 -->|fail| V6
    V5 -->|ok| V6
    V6 -->|fail| V7
    V6 -->|ok| V7
    V7 -->|fail| V8
    V7 -->|ok| V8
    V8 -->|fail| V9
    V8 -->|ok| V9
    V9 -->|"99999999"| V9_SKIP
    V9 -->|other| V9_NYMD
    V9_SKIP --> V10
    V9_NYMD -->|fail| V10
    V9_NYMD -->|ok| V10
    V10 -->|fail| V11
    V10 -->|ok| V11
    V11 -->|fail| V12
    V11 -->|ok| V12
    V12 -->|fail| V13
    V12 -->|ok| V13
    V13 -->|fail| V14
    V13 -->|ok| V14
    V14 -->|fail| V15
    V14 -->|ok| V15
    V15 -->|fail| V16
    V15 -->|ok| V16
    V16 -->|fail| V17
    V16 -->|ok| V17
    V17 --> CHK_ERR
    CHK_ERR -->|no| DEBUG_END
    CHK_ERR -->|yes| SKIP_CHECK
    SKIP_CHECK -->|yes| SKIP
    SKIP_CHECK -->|no| BUILD
    BUILD --> DEBUG_END
    DEBUG_END --> END
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `data_list` | `ArrayList<String>` | A 18-element list of CSV field strings parsed from a single record of the construction completion information input file (工事完了情報ファイル). Each element at index 0–17 corresponds to a specific business field: record division number (0), service contract number (1), service contract line internal number (2), connection date (3), sequence number (4), new change division (5), construction project type code (6), construction project number (7), construction project result code (8), construction project completion date (9), PON type code (10), construction cost (standard) (11), construction cost (non-standard) (12), construction cost (standard) phone indoor work expense (13), construction cost (non-standard) phone indoor work expense (14), construction cost (standard) indoor LAN work expense (15), construction cost (non-standard) indoor LAN work expense (16), construction range code (17). |
| 2 | `koji_fin_inf` | `StringBuilder` | An accumulator StringBuilder that receives the formatted CSV output string. This is a shared mutable buffer — the method appends comma-separated validated fields and a newline character to this buffer, which is later written to an output file by the batch framework. |

**Instance fields / external state read:**
- `super.logPrint` — Debug log logger inherited from `JBSbatBusinessService`, used for START/END debug logging and field value diagnostics.
- `CONMA` — Static constant `","` (comma), used as the field delimiter in the output CSV.
- `KAIGYOU_CODE` — Static constant `"
"` (newline), used as the record separator.
- `LAST_YEAR` — Static constant `"20991231"`, used as a fallback date when the input specifies `"99999999"` (indefinite future).

## 4. CRUD Operations / Called Services

### Pre-computed evidence from code analysis graph:

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| - | `JACBatCommon.printDebugLog` | JACBatCommon | - | Calls `printDebugLog` in `JACBatCommon` |
| - | `JACbatDebugLogUtil.printDebugLog` | JACbatDebugLog | - | Calls `printDebugLog` in `JACbatDebugLogUtil` |
| - | `JBSbatInterface.Rtrim` | JBSbatInterface | - | Calls `Rtrim` in `JBSbatInterface` |
| - | `JCKLcsRenkeiUtil.printDebugLog` | JCKLcsRenkei | - | Calls `printDebugLog` in `JCKLcsRenkeiUtil` |
| - | `JKKHttpCommunicator.printDebugLog` | JKKHttpCommunicator | - | Calls `printDebugLog` in `JKKHttpCommunicator` |
| - | `JBSbatKKCashPostAddMail.printDebugLog` | JBSbatKKCashPostAddMail | - | Calls `printDebugLog` in `JBSbatKKCashPostAddMail` |
| - | `JBSbatKKKojiKnrIfFileLoad.isHannkakuESuuji` | JBSbatKKKojiKnrIfFileLoad | - | Calls `isHannkakuESuuji` in `JBSbatKKKojiKnrIfFileLoad` — validates a field is a half-width alphanumeric string |
| - | `JBSbatKKKojiKnrIfFileLoad.isHannkakuSuuji1` | JBSbatKKKojiKnrIfFileLoad | - | Calls `isHannkakuSuuji1` in `JBSbatKKKojiKnrIfFileLoad` — validates a field is a half-width numeric-only string |
| - | `JBSbatKKKojiKnrIfFileLoad.isYearMonthDay` | JBSbatKKKojiKnrIfFileLoad | - | Calls `isYearMonthDay` in `JBSbatKKKojiKnrIfFileLoad` — validates a field is a valid YYYYMMDD date string |
| - | `JPCEditString.Rtrim` | JPCEditString | - | Calls `Rtrim` in `JPCEditString` |
| - | `JPCUtilCommon.Rtrim` | JPCUtilCommon | - | Calls `Rtrim` in `JPCUtilCommon` |

**Additional method calls specific to this method (from source code analysis):**

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| - | `JBSbatStringUtil.Rtrim` | JBSbatStringUtil | - | Calls `Rtrim` to strip trailing spaces from `data_list[5]` (new change division) and `data_list[4]` (sequence number) before comparison |
| - | `JBSbatBusinessService.logPrint.printDebugLog` | JBSbatBusinessService | - | Calls debug logging for START, END, field values, and record skip conditions |

**Classification notes:**
- This method performs **no database CRUD operations** (no C/R/U/D). It is purely an in-memory **validation and assembly** routine.
- All called utility methods (`isHannkakuESuuji`, `isHannkakuSuuji1`, `isYearMonthDay`, `Rtrim`) are format validation helpers and string utilities — they return boolean or string results without side effects.
- The output `koji_fin_inf` StringBuilder is a **write-only accumulator** — data is appended but never read or persisted within this method's scope.

## 5. Dependency Trace

### Pre-computed evidence from code analysis graph:

No screen/batch entry points found within 8 hops. Direct callers found: 1 methods.
Terminal operations from this method: `printDebugLog` [-], `printDebugLog` [-], `printDebugLog` [-], `printDebugLog` [-], `printDebugLog` [-], `printDebugLog` [-], `printDebugLog` [-], `printDebugLog` [-], `printDebugLog` [-], `printDebugLog` [-]  # NOSONAR

### Detailed call trace:

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Batch: JBSbatKKKojiKnrIfFileLoad | `JBSbatKKKojiKnrIfFileLoad.execute()` -> `setKojiFinInf(data_list, koji_fin_inf)` | `printDebugLog` [N/A] |

**Explanation:**
- This method is called exclusively from its **own class** `JBSbatKKKojiKnrIfFileLoad`, specifically from the `execute()` method (line 291) as part of a record-division-based dispatch chain in the file-parsing loop.
- The `execute()` method reads the construction completion information input file line by line, parses each line into a `data_list` ArrayList, identifies the record division code (レコード区分, e.g., `REC_DOV_40` = "40"), and routes to the appropriate per-type setter method.
- This method has **no further downstream service calls** — all called methods (`isHannkakuESuuji`, `isHannkakuSuuji1`, `isYearMonthDay`, `Rtrim`, `printDebugLog`) are self-contained utility operations.

## 6. Per-Branch Detail Blocks

**Block 1** — [IF] Field[1] Service Contract Number Validation `(L863)`

> Validate that the service contract number is a half-width alphanumeric string, max 10 characters, with optional leading blanks. This is a required field (must not be null/empty).

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(1)` // Service contract number |
| 2 | CALL | `isHannkakuESuuji(data, 10, true, "工事完了：サービス契約番号")` // Validates half-width alphanumeric, max 10 chars, blankable |
| 3 | IF | `if (!isHannkakuESuuji(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 2** — [IF] Field[2] Service Contract Line Internal Number Validation `(L870)`

> Validate that the service contract line internal number is a half-width alphanumeric string, max 12 characters, required (blankable).

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(2)` // Service contract line internal number |
| 2 | CALL | `isHannkakuESuuji(data, 12, true, "工事完了：サービス契約回線内訳番号")` // Validates half-width alphanumeric, max 12 chars |
| 3 | IF | `if (!isHannkakuESuuji(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 3** — [IF] Field[3] Connection Date Validation `(L877)`

> Validate that the connection date is a valid YYYYMMDD date string. This is a required field.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(3)` // Connection date (連携年月日) |
| 2 | CALL | `isYearMonthDay(data, true, "工事完了：連携年月日")` // Validates YYYYMMDD format, required |
| 3 | IF | `if (!isYearMonthDay(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 4** — [IF] Field[4] Sequence Number Validation `(L884)`

> Validate that the sequence number is a half-width numeric-only string, max 12 characters, required.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(4)` // Sequence number (通番) |
| 2 | CALL | `isHannkakuSuuji1(data, 12, true, "工事完了：通番")` // Validates half-width numeric, max 12 chars |
| 3 | IF | `if (!isHannkakuSuuji1(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 5** — [IF] Field[5] New Change Division Validation `(L891)`

> Validate that the new change division is a half-width alphanumeric string, max 1 character, optional (not required).

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(5)` // New change division (新規変更区分) |
| 2 | CALL | `isHannkakuESuuji(data, 1, false, "工事完了：新規変更区分")` // Validates half-width alphanumeric, max 1 char, not required |
| 3 | IF | `if (!isHannkakuESuuji(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 6** — [IF] Field[6] Construction Project Type Code Validation `(L898)`

> Validate that the construction project type code is a half-width alphanumeric string, max 3 characters, optional.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(6)` // Construction project type code (工事案件種別コード) |
| 2 | CALL | `isHannkakuESuuji(data, 3, false, "工事完了：工事案件種別コード")` // Validates half-width alphanumeric, max 3 chars |
| 3 | IF | `if (!isHannkakuESuuji(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 7** — [IF] Field[7] Construction Project Number Validation `(L905)`

> Validate that the construction project number is a half-width alphanumeric string, max 10 characters, optional.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(7)` // Construction project number (工事案件番号) |
| 2 | CALL | `isHannkakuESuuji(data, 10, false, "工事完了：工事案件番号")` // Validates half-width alphanumeric, max 10 chars |
| 3 | IF | `if (!isHannkakuESuuji(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 8** — [IF] Field[8] Construction Project Result Code Validation `(L912)`

> Validate that the construction project result code is a half-width alphanumeric string, max 1 character, optional.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(8)` // Construction project result code (工事案件結果コード) |
| 2 | CALL | `isHannkakuESuuji(data, 1, false, "工事完了：工事案件結果コード")` // Validates half-width alphanumeric, max 1 char |
| 3 | IF | `if (!isHannkakuESuuji(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 9** — [IF / ELSE] Field[9] Construction Project Completion Date Validation `(L919)`

> V3.01.00 Fix: Special handling for the construction project completion date. If the value is the sentinel `"99999999"` (meaning indefinite/unset), skip date validation and accept it. Otherwise, validate as a proper YYYYMMDD date string.

| # | Type | Code |
|---|------|------|
| 1 | IF | `if (!"99999999".equals(data_list.get(9)))` // Value is NOT the sentinel |
| 2 | CALL | `isYearMonthDay(data_list.get(9), false, "工事完了：工事案件完了年月日")` // Validate as YYYYMMDD, not required |
| 3 | IF | `if (!isYearMonthDay(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |
| 5 | ELSE | — |
| 6 | CALL | `isHannkakuSuuji1(data_list.get(9), 8, false, "工事完了：工事案件完了年月日")` // Validate as 8-digit numeric |
| 7 | IF | `if (!isHannkakuSuuji1(...))` // Validation fails |
| 8 | SET | `err_cunt++` // Increment error counter |

**Block 10** — [IF] Field[10] PON Type Code Validation `(L934)`

> Validate that the PON (Passive Optical Network) type code is a half-width alphanumeric string, max 1 character, optional.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(10)` // PON type code (PON種別コード) |
| 2 | CALL | `isHannkakuESuuji(data, 1, false, "工事完了：PON種別コード")` // Validates half-width alphanumeric, max 1 char |
| 3 | IF | `if (!isHannkakuESuuji(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 11** — [IF] Field[11] Construction Cost (Standard) Validation `(L941)`

> Validate that the standard construction cost is a half-width numeric-only string, max 12 characters, optional.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(11)` // Construction cost (standard) (工事金額(標準)) |
| 2 | CALL | `isHannkakuSuuji1(data, 12, false, "工事完了：工事金額(標準)")` // Validates half-width numeric, max 12 chars |
| 3 | IF | `if (!isHannkakuSuuji1(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 12** — [IF] Field[12] Construction Cost (Non-Standard) Validation `(L948)`

> Validate that the non-standard construction cost is a half-width numeric-only string, max 12 characters, optional.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(12)` // Construction cost (non-standard) (工事金額(標準外)) |
| 2 | CALL | `isHannkakuSuuji1(data, 12, false, "工事完了：工事金額(標準外)")` // Validates half-width numeric, max 12 chars |
| 3 | IF | `if (!isHannkakuSuuji1(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 13** — [IF] Field[13] Construction Cost (Standard) Phone Indoor Work Expense Validation `(L955)`

> Validate that the standard phone indoor work expense is a half-width numeric-only string, max 12 characters, optional.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(13)` // Construction cost (standard) phone indoor work expense (工事金額(標準)電話宅内工事費用) |
| 2 | CALL | `isHannkakuSuuji1(data, 12, false, "工事完了：工事金額(標準)電話宅内工事費用")` // Validates half-width numeric, max 12 chars |
| 3 | IF | `if (!isHannkakuSuuji1(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 14** — [IF] Field[14] Construction Cost (Non-Standard) Phone Indoor Work Expense Validation `(L962)`

> Validate that the non-standard phone indoor work expense is a half-width numeric-only string, max 12 characters, optional.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(14)` // Construction cost (non-standard) phone indoor work expense (工事金額(標準外)電話宅内工事費用) |
| 2 | CALL | `isHannkakuSuuji1(data, 12, false, "工事完了：工事金額(標準外)電話宅内工事費用")` // Validates half-width numeric, max 12 chars |
| 3 | IF | `if (!isHannkakuSuuji1(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 15** — [IF] Field[15] Construction Cost (Standard) Indoor LAN Work Expense Validation `(L969)`

> Validate that the standard indoor LAN work expense is a half-width numeric-only string, max 12 characters, optional.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(15)` // Construction cost (standard) indoor LAN work expense (工事金額(標準)宅内工事(LAN)費用) |
| 2 | CALL | `isHannkakuSuuji1(data, 12, false, "工事完了：工事金額(標準)宅内工事(LAN)費用")` // Validates half-width numeric, max 12 chars |
| 3 | IF | `if (!isHannkakuSuuji1(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 16** — [IF] Field[16] Construction Cost (Non-Standard) Indoor LAN Work Expense Validation `(L976)`

> Validate that the non-standard indoor LAN work expense is a half-width numeric-only string, max 12 characters, optional.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(16)` // Construction cost (non-standard) indoor LAN work expense (工事金額(標準外)宅内工事(LAN)費用) |
| 2 | CALL | `isHannkakuSuuji1(data, 12, false, "工事完了：工事金額(標準外)宅内工事(LAN)費用")` // Validates half-width numeric, max 12 chars |
| 3 | IF | `if (!isHannkakuSuuji1(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 17** — [IF] Field[17] Construction Range Code Validation `(L983)`

> Validate that the construction range code is a half-width alphanumeric string, max 3 characters, optional.

| # | Type | Code |
|---|------|------|
| 1 | SET | `data = data_list.get(17)` // Construction range code (工事範囲コード) |
| 2 | CALL | `isHannkakuESuuji(data, 3, false, "工事完了：工事範囲コード")` // Validates half-width alphanumeric, max 3 chars |
| 3 | IF | `if (!isHannkakuESuuji(...))` // Validation fails |
| 4 | SET | `err_cunt++` // Increment error counter |

**Block 18** — [IF] Overall Error Count Check `(L990)`

> After all 18 fields are validated, check if any errors were accumulated. If `err_cunt > 0`, skip the output assembly entirely and proceed directly to end logging.

| # | Type | Code |
|---|------|------|
| 1 | IF | `if (0 == err_cunt)` // All fields passed validation |
| 2 | [ENTIRE Block 19 is nested here] | // Output assembly |

**Block 18.1** — [IF] Record Skip Condition `(L994)`

> If the "new change division" (field[5]) is empty AND the sequence number (field[4]) is `"000000000000"`, skip writing this record — it represents a dummy/placeholder entry that should not appear in the output file.

| # | Type | Code |
|---|------|------|
| 1 | SET | `newChgDiv = JBSbatStringUtil.Rtrim(data_list.get(5))` // Trim trailing spaces from new change division |
| 2 | SET | `seq = JBSbatStringUtil.Rtrim(data_list.get(4))` // Trim trailing spaces from sequence number |
| 3 | EXEC | `printDebugLog("新規変更区分：" + newChgDiv)` // Log the new change division value |
| 4 | EXEC | `printDebugLog("通番        ：" + seq)` // Log the sequence number value |
| 5 | IF | `if ("".equals(newChgDiv) && "000000000000".equals(seq))` // Both are empty/zero |
| 6 | EXEC | `printDebugLog("「新規変更区分」がNULL、通番が000000000000の場合、レコードスキップ")` // Record skip log |
| 7 | RETURN | `return` // Early return — no data appended to koji_fin_inf |

**Block 19** — [SERIES OF APPENDS] CSV Output Assembly `(L1007–L1070)`

> Build the complete CSV output string by appending all 18 fields in the required output order, separated by commas (CONMA). Field[9] (construction project completion date) receives special handling: if the input value is `"99999999"`, substitute `"20991231"` (LAST_YEAR). Finally, append the record division number (field[0]) and the newline code (KAIGYOU_CODE).

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `koji_fin_inf.append(data_list.get(1))` // Service contract number |
| 2 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter [-> CONSTANT=","] |
| 3 | EXEC | `koji_fin_inf.append(data_list.get(2))` // Service contract line internal number |
| 4 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 5 | EXEC | `koji_fin_inf.append(data_list.get(3))` // Connection date |
| 6 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 7 | EXEC | `koji_fin_inf.append(data_list.get(4))` // Sequence number |
| 8 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 9 | EXEC | `koji_fin_inf.append(data_list.get(5))` // New change division |
| 10 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 11 | EXEC | `koji_fin_inf.append(data_list.get(6))` // Construction project type code |
| 12 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 13 | EXEC | `koji_fin_inf.append(data_list.get(7))` // Construction project number |
| 14 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 15 | EXEC | `koji_fin_inf.append(data_list.get(8))` // Construction project result code |
| 16 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 17 | IF | `if ("99999999".equals(data_list.get(9)))` // Sentinel date detected |
| 18 | EXEC | `koji_fin_inf.append(LAST_YEAR)` // Substitute "20991231" [-> CONSTANT="20991231"] |
| 19 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 20 | ELSE | — |
| 21 | EXEC | `koji_fin_inf.append(data_list.get(9))` // Use actual completion date |
| 22 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 23 | EXEC | `koji_fin_inf.append(data_list.get(10))` // PON type code |
| 24 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 25 | EXEC | `koji_fin_inf.append(data_list.get(11))` // Construction cost (standard) |
| 26 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 27 | EXEC | `koji_fin_inf.append(data_list.get(12))` // Construction cost (non-standard) |
| 28 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 29 | EXEC | `koji_fin_inf.append(data_list.get(13))` // Construction cost (standard) phone indoor expense |
| 30 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 31 | EXEC | `koji_fin_inf.append(data_list.get(14))` // Construction cost (non-standard) phone indoor expense |
| 32 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 33 | EXEC | `koji_fin_inf.append(data_list.get(15))` // Construction cost (standard) indoor LAN expense |
| 34 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 35 | EXEC | `koji_fin_inf.append(data_list.get(16))` // Construction cost (non-standard) indoor LAN expense |
| 36 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 37 | EXEC | `koji_fin_inf.append(data_list.get(17))` // Construction range code |
| 38 | EXEC | `koji_fin_inf.append(CONMA)` // Comma delimiter |
| 39 | EXEC | `koji_fin_inf.append(data_list.get(0))` // Record division number (レコード区分) |
| 40 | EXEC | `koji_fin_inf.append(KAIGYOU_CODE)` // Newline record separator [-> CONSTANT="
"] |

**Block 20** — [END] Final Debug Logging `(L1073)`

> Log completion and return control to the caller.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `printDebugLog("setKojiFinInf_END")` // End debug marker |
| 2 | RETURN | `return` // End method execution |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| 工事完了 | Field | Construction Completion — refers to the completion status of telecom infrastructure construction work |
| 工事完了情報 | Field | Construction Completion Information — a record type in the batch file containing full details of a completed construction job |
| サービス契約番号 | Field | Service Contract Number — the primary identifier for a service contract (index 1 in the input CSV) |
| サービス契約回線内訳番号 | Field | Service Contract Line Internal Number — a sub-line identifier within a service contract (index 2) |
| 連携年月日 | Field | Connection/Coordination Date — the date the construction completion was registered/coordinated, in YYYYMMDD format (index 3) |
| 通番 | Field | Sequence Number — a sequential numbering for records within a batch (index 4) |
| 新規変更区分 | Field | New Change Division — indicates whether this record represents a new installation or a change to an existing service (index 5). Empty string indicates no change classification |
| 工事案件種別コード | Field | Construction Project Type Code — a code classifying the type of construction project (e.g., FTTH installation, cable laying) (index 6) |
| 工事案件番号 | Field | Construction Project Number — the unique identifier for a construction project/case (index 7) |
| 工事案件結果コード | Field | Construction Project Result Code — indicates the outcome of the construction project (e.g., completion, failure) (index 8) |
| 工事案件完了年月日 | Field | Construction Project Completion Date — the actual date the construction work was completed, in YYYYMMDD format (index 9). `"99999999"` is a sentinel meaning "not yet determined" |
| PON種別コード | Field | PON Type Code — classifies the type of Passive Optical Network technology used (e.g., GPON, EPON) (index 10) |
| 工事金額(標準) | Field | Construction Cost (Standard) — the standard/base construction cost (index 11) |
| 工事金額(標準外) | Field | Construction Cost (Non-Standard) — additional or non-standard construction charges (index 12) |
| 工事金額(標準)電話宅内工事費用 | Field | Construction Cost (Standard) Phone Indoor Work Expense — standard cost for indoor cabling/work for phone services (index 13) |
| 工事金額(標準外)電話宅内工事費用 | Field | Construction Cost (Non-Standard) Phone Indoor Work Expense — non-standard/extra cost for indoor phone cabling (index 14) |
| 工事金額(標準)宅内工事(LAN)費用 | Field | Construction Cost (Standard) Indoor LAN Work Expense — standard cost for indoor LAN cabling work (index 15) |
| 工事金額(標準外)宅内工事(LAN)費用 | Field | Construction Cost (Non-Standard) Indoor LAN Work Expense — non-standard/extra cost for indoor LAN cabling (index 16) |
| 工事範囲コード | Field | Construction Range Code — indicates the scope/scope of construction work (e.g., entire building, partial floor) (index 17) |
| レコード区分 | Field | Record Division Code — identifies the type of record in the batch file (index 0). Value `"40"` means "Construction Completion Information" |
| REC_DOV_40 | Constant | Record Division "40" — the constant used in `execute()` to route records to `setKojiFinInf()`. Represents "工事完了情報" (Construction Completion Information) |
| CONMA | Constant | Comma — the field delimiter used in the output CSV string |
| KAIGYOU_CODE | Constant | Newline — `"
"`, the record separator appended at the end of each output record |
| LAST_YEAR | Constant | `"20991231"` — a far-future sentinel date used as a substitute when the input specifies `"99999999"` (indefinite/unset completion date) |
| isHannkakuESuuji | Method | Half-width Alphanumeric String Validator — validates that a field contains only half-width alphanumeric characters (A-Z, a-z, 0-9), with configurable max length and blank allowance |
| isHannkakuSuuji1 | Method | Half-width Numeric-Only Validator — validates that a field contains only half-width numeric digits (0-9), with configurable max length and blank allowance |
| isYearMonthDay | Method | Date Format Validator — validates that a field is a valid YYYYMMDD date string |
| Rtrim | Method | Right-trim utility — removes trailing whitespace/blank characters from a string |
| FTTH | Business term | Fiber To The Home — fiber-optic broadband internet service, the primary service type in this telecom system |
| PON | Acronym | Passive Optical Network — a fiber-optic network architecture used for broadband delivery (e.g., GPON, EPON) |
| LAN | Acronym | Local Area Network — refers to indoor wiring/cabling work for LAN services (e.g., ethernet) |
| eo Customer Core System | System | The overarching telecom customer management system in which this batch resides |
| Batch: JBSbatKKKojiKnrIfFileLoad | Component | The batch class that reads construction-related information input files and routes records to per-type setter methods based on record division codes |
