# Business Logic — JBSbatKKKjhKapZnskIktSikyAdchg.addKojihiKapKei() [121 LOC]

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

## 1. Role

### JBSbatKKKjhKapZnskIktSikyAdchg.addKojihiKapKei()

This method registers (inserts) a **Construction Fee Installment Contract** (工事費割賦契約) record into the `KK_T_KOJIHI_KAP_KEI` database table. In the K-Opticom customer infrastructure system, "construction fee installment contracts" represent payment agreements where customers pay installation/construction costs in installment installments rather than a single lump sum. The method receives pre-validated, exclusivity-locked data via `excSearchList` (the result of a prior optimistic-lock check), extracts 32 field values, applies business-rule-based adjustments to two key date fields, and delegates the actual database insert to `executeKK_T_KOJIHI_KAP_KEI_PKINSERT()`.

The method implements a **builder pattern** — it constructs an `Object[32]` parameter array by sequentially reading fields from the input interface and populating business, audit, and metadata columns. It implements a **delegation pattern** for the terminal write operation, routing to a dedicated PK-insert method. The method handles two conditional business branches: (1) a **date adjustment branch** that corrects the charge-start date if it falls after the judgment reference date (falling back to the service-start date), and (2) a **plan-type branch** that clears the lump-sum request-switch year-month when the installment plan is a lump-sum type (either `KP0041` or `KP0141`), since lump-sum plans do not require monthly switching.

As a batch-side service method in the `koptBatch` module, it serves as the registration endpoint for construction fee installment contracts created during batch operations (invoked from the class's own `execute()` method). It is not called from any UI screen directly.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["addKojihiKapKei(excSearchList)"])
    CHECK_NULL{"excSearchList<br/>!= null?"}
    GET_KAP_CHRG{Get KAP_KEI_CHRG_STAYMD}
    SUBSTRING_6{Substring<br/>first 6 chars}
    GET_JUDGE_YM{Get judgeYm from<br/>judgeYmd}
    COMPARE_YM{"kapKeiChrgStaym<br/>compareTo judgeYm"}
    FALLBACK_GET{Fallback: get<br/>KAP_KEI_SVC_STAYMD}
    USE_KAP_CHRG{Use kapKeiChrgStaymd}
    CREATE_SET_PARAM{Create Object[32]<br/>setParam}
    POPULATE_0{"Populate setParam[0] - KOJIHI_KAP_KEI_NO"}
    POPULATE_1{"Populate setParam[1] - GENE_ADD_DTM"}
    POPULATE_2{"Populate setParam[2] - KAP_KEI_STAT"}
    POPULATE_3{"Populate setParam[3] - KAP_PLAN_CD"}
    POPULATE_4{"Populate setParam[4] - SVC_KEI_KAISEN_UCWK_NO"}
    POPULATE_5{"Populate setParam[5] - FIRST_SEIKY_SVC_KEI_NO"}
    POPULATE_6{"Populate setParam[6] - MSKM_DTL_NO"}
    POPULATE_7{"Populate setParam[7] - IDO_DIV"}
    POPULATE_8{"Populate setParam[8] - KAP_IKT_SIKY_SWCH_YM"}
    IKKATSU_CHECK{"Is KAP_PLAN_CD<br/>IKKATSU or IKKATSU_10_PERCENT?"}
    SET_EMPTY{setParam[8] = ""}
    SET_JUDGE_YM{setParam[8] = judgeYm}
    POPULATE_9{"Populate setParam[9] - KAP_KEI_CNC_YMD"}
    POPULATE_10{"Populate setParam[10] - KAP_KEI_ENDYMD"}
    POPULATE_11{"Populate setParam[11] - KAP_KEI_CANCEL_YMD"}
    POPULATE_12{"Populate setParam[12] - KAP_KEI_SVC_STAYMD"}
    POPULATE_13{"Populate setParam[13] - KAP_KEI_CHRG_STAYMD"}
    POPULATE_14{"Populate setParam[14] - KAP_SEIKY_STA_YM"}
    POPULATE_15{"Populate setParam[15] - KAP_PAY_ZAN_CNT"}
    POPULATE_16{"Populate setParam[16] - KAP_SEIKY_ZUMI_CNT"}
    POPULATE_17{"Populate setParam[17] - KAP_SEIKY_ZUMI_AMNT"}
    POPULATE_18{"Populate setParam[18] - ADD_DTM"}
    POPULATE_19{"Populate setParam[19] - ADD_OPEACNT"}
    POPULATE_20{"Populate setParam[20] - UPD_DTM"}
    POPULATE_21{"Populate setParam[21] - UPD_OPEACNT"}
    POPULATE_22{"Populate setParam[22] - DEL_DTM"}
    POPULATE_23{"Populate setParam[23] - DEL_OPEACNT"}
    POPULATE_24{"Populate setParam[24] - MK_FLG"}
    POPULATE_25{"Populate setParam[25] - ADD_UNYO_YMD"}
    POPULATE_26{"Populate setParam[26] - ADD_TRN_ID"}
    POPULATE_27{"Populate setParam[27] - UPD_UNYO_YMD"}
    POPULATE_28{"Populate setParam[28] - UPD_TRN_ID"}
    POPULATE_29{"Populate setParam[29] - DEL_UNYO_YMD"}
    POPULATE_30{"Populate setParam[30] - DEL_TRN_ID"}
    POPULATE_31{"Populate setParam[31] - BUNKATSU_PAY_KAIK_SUMUP_YM"}
    EXEC_INSERT{executeKK_T_KOJIHI_KAP_KEI_PKINSERT}
    END_NODE(["Return / Next"])

    START --> CHECK_NULL
    CHECK_NULL -->|true| GET_KAP_CHRG
    CHECK_NULL -->|false| END_NODE
    GET_KAP_CHRG --> SUBSTRING_6
    SUBSTRING_6 --> GET_JUDGE_YM
    GET_JUDGE_YM --> COMPARE_YM
    COMPARE_YM -->|> 0 (True)| FALLBACK_GET
    COMPARE_YM -->|<= 0 (False)| USE_KAP_CHRG
    FALLBACK_GET --> USE_KAP_CHRG
    USE_KAP_CHRG --> CREATE_SET_PARAM
    CREATE_SET_PARAM --> POPULATE_0
    POPULATE_0 --> POPULATE_1
    POPULATE_1 --> POPULATE_2
    POPULATE_2 --> POPULATE_3
    POPULATE_3 --> POPULATE_4
    POPULATE_4 --> POPULATE_5
    POPULATE_5 --> POPULATE_6
    POPULATE_6 --> POPULATE_7
    POPULATE_7 --> POPULATE_8
    POPULATE_8 --> IKKATSU_CHECK
    IKKATSU_CHECK -->|true| SET_EMPTY
    IKKATSU_CHECK -->|false| SET_JUDGE_YM
    SET_EMPTY --> POPULATE_9
    SET_JUDGE_YM --> POPULATE_9
    POPULATE_9 --> POPULATE_10
    POPULATE_10 --> POPULATE_11
    POPULATE_11 --> POPULATE_12
    POPULATE_12 --> POPULATE_13
    POPULATE_13 --> POPULATE_14
    POPULATE_14 --> POPULATE_15
    POPULATE_15 --> POPULATE_16
    POPULATE_16 --> POPULATE_17
    POPULATE_17 --> POPULATE_18
    POPULATE_18 --> POPULATE_19
    POPULATE_19 --> POPULATE_20
    POPULATE_20 --> POPULATE_21
    POPULATE_21 --> POPULATE_22
    POPULATE_22 --> POPULATE_23
    POPULATE_23 --> POPULATE_24
    POPULATE_24 --> POPULATE_25
    POPULATE_25 --> POPULATE_26
    POPULATE_26 --> POPULATE_27
    POPULATE_27 --> POPULATE_28
    POPULATE_28 --> POPULATE_29
    POPULATE_29 --> POPULATE_30
    POPULATE_30 --> POPULATE_31
    POPULATE_31 --> EXEC_INSERT
    EXEC_INSERT --> END_NODE
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `excSearchList` | `JBSbatCommonDBInterface` | The result of an exclusive lock (optimistic locking) search — contains all fields of a pre-validated Construction Fee Installment Contract record. The exclusivity check guarantees no concurrent modification occurred between read and register. |
| — | `judgeYmd` | `String` (instance field) | Judgment reference date (年月日). Set by the enclosing `execute()` method based on service type: DSL service start date, operation date, etc. Used to compare against the installment charge start date for correction logic. |
| — | `batchUserId` | `String` (inherited) | The batch operator account identifier. Used for `ADD_OPEACNT` (registration operator) and `UPD_OPEACNT` (update operator) audit fields. |

## 4. CRUD Operations / Called Services

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

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `JBSbatCommonDBInterface.getString(String)` | - | - | Reads field values from the exclusivity-locked search result data |
| R | `JCCBatCommon.getSysDateTimeStamp()` | JCCBatCommon | - | Retrieves system date-time for `GENE_ADD_DTM` (generation registration timestamp) |
| R | `JBSbatDateUtil.getSystemDateTimeStamp()` | JBSbatDateUtil | - | Retrieves system date-time for audit fields (`ADD_DTM`, `UPD_DTM`) |
| C | `executeKK_T_KOJIHI_KAP_KEI_PKINSERT(Object[])` | JBSbatKKKjhKapZnskIktSikyAdchg | `KK_T_KOJIHI_KAP_KEI` | Inserts a new row into the Construction Fee Installment Contract table with 32-parameter set |

### Additional calls (utility/substring):

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `String.substring(int, int)` | - | - | Extracts year-month (first 6 characters) from date strings |

## 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: `executeKK_T_KOJIHI_KAP_KEI_PKINSERT` [C], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getSystemDateTimeStamp` [R], `getSystemDateTimeStamp` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R]  # NOSONAR

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Batch: JBSbatKKKjhKapZnskIktSikyAdchg.execute() | `JBSbatKKKjhKapZnskIktSikyAdchg.execute()` -> `JBSbatKKKjhKapZnskIktSikyAdchg.addKojihiKapKei(excSearchList)` | `executeKK_T_KOJIHI_KAP_KEI_PKINSERT` [C] `KK_T_KOJIHI_KAP_KEI` |

## 6. Per-Branch Detail Blocks

### Block 1 — IF (null check on excSearchList) (L1564)

> If the exclusivity-locked search result exists, register the data. (レコードが存在するとき、データを登録する。)

| # | Type | Code |
|---|------|------|
| 1 | CALL | `kapKeiChrgStaymd = excSearchList.getString(JBSbatKK_T_KOJIHI_KAP_KEI.KAP_KEI_CHRG_STAYMD)` // Get installment contract charge start YMD (割賦契約課金開始年月日) |
| 2 | SET | `kapKeiChrgStaym = kapKeiChrgStaymd.substring(0, 6)` // Extract year-month from charge start date (割賦契約課金開始年月) |
| 3 | SET | `judgeYm = judgeYmd.substring(0, 6)` // Extract year-month from judgment reference date (判定基準日の年月を取得) |
| 4 | COMPARE | `kapKeiChrgStaym.compareTo(judgeYm) > 0` // Compare installment charge start month vs judgment reference month (割賦契約課金開始年月と判定基準日の年月を比較する) [Block 1.1 IF below] |

#### Block 1.1 — IF (kapKeiChrgStaym > judgeYm) (L1586)

> If the judgment reference month is earlier than the charge start month, fall back to the service-start date. (判定基準日の年月が割賦契約課金開始年月より過去の場合、割賦契約サービス開始年月日を設定する。)

| # | Type | Code |
|---|------|------|
| 1 | SET | `kapKeiChrgStaymd = excSearchList.getString(JBSbatKK_T_KOJIHI_KAP_KEI.KAP_KEI_SVC_STAYMD)` // Fallback: use service start date (割賦契約サービス開始年月日を設定する) |

### Block 2 — SET (Create parameter array) (L1595)

> Create a mapping map for the registration SQL's set values. (登録用SQLの設定値のマップを作成します)

| # | Type | Code |
|---|------|------|
| 1 | SET | `setParam = new Object[32]` // Array of 32 columns = KK_T_KOJIHI_KAP_KEI_CNT |

### Block 3 — SET (Populate setParam[0-7]) (L1598–L1609)

| # | Type | Code | Field |
|---|------|------|-------|
| 1 | SET | `setParam[0] = excSearchList.getString(KOJIHI_KAP_KEI_NO)` | Construction Fee Installment Contract No. (工事費割賦契約番号) |
| 2 | SET | `setParam[1] = JCCBatCommon.getSysDateTimeStamp()` | Generation Registration DateTimeStamp (世代登録年月日时分秒) |
| 3 | SET | `setParam[2] = excSearchList.getString(KAP_KEI_STAT)` | Installment Contract Status (割賦契約ステータス) |
| 4 | SET | `setParam[3] = excSearchList.getString(KAP_PLAN_CD)` | Installment Plan Code (割賦プランコード) |
| 5 | SET | `setParam[4] = excSearchList.getString(SVC_KEI_KAISEN_UCWK_NO)` | Service Contract Circuit Detail No. (サービス契約回線内訳番号) |
| 6 | SET | `setParam[5] = excSearchList.getString(FIRST_SEIKY_SVC_KEI_NO)` | First Invoice Service Contract No. (初回請求サービス契約番号) |
| 7 | SET | `setParam[6] = excSearchList.getString(MSKM_DTL_NO)` | Application Detail No. (申請明細番号) |
| 8 | SET | `setParam[7] = excSearchList.getString(IDO_DIV)` | Movement Division (異動区分) |

### Block 4 — IF-ELSE (Populate setParam[8] — Lump-sum request switch) (L1612–L1628)

> Conditional logic for the installment lump-sum request switch year-month. (割賦一括請求切替年月)
> **Condition:** `[KAP_PLAN_CD_IKKATSU="KP0041" (Lump-sum)] || [KAP_PLAN_CD_IKKATSU_10_PERCENT="KP0141" (Lump-sum 10%)]` (割賦プランが「一括」の場合)

| # | Type | Code |
|---|------|------|
| 1 | CALL | `excSearchList.getString(KAP_PLAN_CD)` // Read plan code twice for comparison |
| 2 | IF | `JKKStrConst.KAP_PLAN_CD_IKKATSU.equals(planCd) || JKKStrConst.KAP_PLAN_CD_IKKATSU_10_PERCENT.equals(planCd)` |

#### Block 4.1 — IF (true: plan is lump-sum type)

| # | Type | Code |
|---|------|------|
| 1 | SET | `setParam[8] = ""` // Clear lump-sum switch year-month since lump-sum plans don't need monthly switching |

#### Block 4.2 — ELSE (false: plan is non-lump-sum type)

| # | Type | Code |
|---|------|------|
| 1 | SET | `setParam[8] = judgeYm` // Set to judgment reference year-month |

### Block 5 — SET (Populate setParam[9-17]) (L1630–L1647)

| # | Type | Code | Field |
|---|------|------|-------|
| 1 | SET | `setParam[9] = excSearchList.getString(KAP_KEI_CNC_YMD)` | Installment Contract Conclusion YMD (割賦契約締結年月日) |
| 2 | SET | `setParam[10] = excSearchList.getString(KAP_KEI_ENDYMD)` | Installment Contract End YMD (割賦契約終了年月日) |
| 3 | SET | `setParam[11] = excSearchList.getString(KAP_KEI_CANCEL_YMD)` | Installment Contract Cancel YMD (割賦契約キャンセル年月日) |
| 4 | SET | `setParam[12] = excSearchList.getString(KAP_KEI_SVC_STAYMD)` | Installment Contract Service Start YMD (割賦契約サービス開始年月日) |
| 5 | SET | `setParam[13] = kapKeiChrgStaymd` | Installment Contract Charge Start YMD (割賦契約課金開始年月日) — **possibly adjusted by Block 1.1** |
| 6 | SET | `setParam[14] = excSearchList.getString(KAP_SEIKY_STA_YM)` | Installment Billing Start Month (割賦請求開始年月) |
| 7 | SET | `setParam[15] = excSearchList.getString(KAP_PAY_ZAN_CNT)` | Installment Payment Remaining Count (割賦支払い残回数) |
| 8 | SET | `setParam[16] = excSearchList.getString(KAP_SEIKY_ZUMI_CNT)` | Installment Billing Completed Count (割賦請求済回数) |
| 9 | SET | `setParam[17] = excSearchList.getString(KAP_SEIKY_ZUMI_AMNT)` | Installment Billing Completed Amount (割賦請求済金額) |

### Block 6 — SET (Populate setParam[18-31]: Audit & Metadata) (L1649–L1681)

| # | Type | Code | Field |
|---|------|------|-------|
| 1 | SET | `setParam[18] = JBSbatDateUtil.getSystemDateTimeStamp()` | Registration DateTimeStamp (登録年月日时分秒 = ADD_DTM) |
| 2 | SET | `setParam[19] = super.batchUserId` | Registration Operator Account (登録オペレータアカウント = ADD_OPEACNT) |
| 3 | SET | `setParam[20] = JBSbatDateUtil.getSystemDateTimeStamp()` | Update DateTimeStamp (更新年月日时分秒 = UPD_DTM) |
| 4 | SET | `setParam[21] = super.batchUserId` | Update Operator Account (更新オペレータアカウント = UPD_OPEACNT) |
| 5 | SET | `setParam[22] = ""` | Delete DateTimeStamp (削除年月日时分秒 = DEL_DTM) — empty for new record |
| 6 | SET | `setParam[23] = ""` | Delete Operator Account (削除オペレータアカウント = DEL_OPEACNT) — empty for new record |
| 7 | SET | `setParam[24] = JBSbatKKConst.MK_FLG_YK` | Invalid Flag (有効 = 0, Valid) [-> `"0"`] |
| 8 | SET | `setParam[25] = ""` | Registration Operation YMD (登録運用年月日 = ADD_UNYO_YMD) |
| 9 | SET | `setParam[26] = ""` | Registration Process ID (登録処理ID = ADD_TRN_ID) |
| 10 | SET | `setParam[27] = ""` | Update Operation YMD (更新運用年月日 = UPD_UNYO_YMD) |
| 11 | SET | `setParam[28] = ""` | Update Process ID (更新処理ID = UPD_TRN_ID) |
| 12 | SET | `setParam[29] = ""` | Delete Operation YMD (削除運用年月日 = DEL_UNYO_YMD) |
| 13 | SET | `setParam[30] = ""` | Delete Process ID (削除処理ID = DEL_TRN_ID) |
| 14 | SET | `setParam[31] = excSearchList.getString(BUNKATSU_PAY_KAIK_SUMUP_YM)` | Split Payment Account Accumulation YMD (分割支払会計計上年月) |

### Block 7 — CALL (Execute Insert) (L1683)

> Execute DB access. (DBアクセスを実行します)

| # | Type | Code |
|---|------|------|
| 1 | CALL | `executeKK_T_KOJIHI_KAP_KEI_PKINSERT(setParam)` |

### Block 8 — RETURN (implicit)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `void` — No return value, registration is side-effect only |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `KOJIHI_KAP_KEI_NO` | Field | Construction Fee Installment Contract No. — primary key / contract identifier |
| `KAP_KEI_STAT` | Field | Installment Contract Status — current lifecycle state of the installment agreement |
| `KAP_PLAN_CD` | Field | Installment Plan Code — classifies the payment plan type (e.g., `KP0040` = Installment, `KP0041` = Lump-sum, `KP0140` = Installment 10%, `KP0141` = Lump-sum 10%) |
| `SVC_KEI_KAISEN_UCWK_NO` | Field | Service Contract Circuit Detail Work No. — internal tracking ID linking to the service contract line item |
| `FIRST_SEIKY_SVC_KEI_NO` | Field | First Invoice Service Contract No. — the contract number of the first billing cycle's service line |
| `MSKM_DTL_NO` | Field | Application Detail No. — detail record identifier from the original application |
| `IDO_DIV` | Field | Movement Division — classification of contract movement/transfer type |
| `KAP_IKT_SIKY_SWCH_YM` | Field | Installment Lump-sum Request Switch Year-Month — month when lump-sum billing switch occurs (empty for lump-sum plan types) |
| `KAP_KEI_CNC_YMD` | Field | Installment Contract Conclusion YMD — date the installment contract was formally concluded |
| `KAP_KEI_ENDYMD` | Field | Installment Contract End YMD — scheduled end date of the installment agreement |
| `KAP_KEI_CANCEL_YMD` | Field | Installment Contract Cancel YMD — date the contract was cancelled (empty if active) |
| `KAP_KEI_SVC_STAYMD` | Field | Installment Contract Service Start YMD — date the service actually started |
| `KAP_KEI_CHRG_STAYMD` | Field | Installment Contract Charge Start YMD — date billing for the installment charges begins |
| `KAP_SEIKY_STA_YM` | Field | Installment Billing Start Month — month when installment billing begins |
| `KAP_PAY_ZAN_CNT` | Field | Installment Payment Remaining Count — number of remaining installment payments |
| `KAP_SEIKY_ZUMI_CNT` | Field | Installment Billing Completed Count — number of installment payments already billed |
| `KAP_SEIKY_ZUMI_AMNT` | Field | Installment Billing Completed Amount — total amount of installments already billed |
| `BUNKATSU_PAY_KAIK_SUMUP_YM` | Field | Split Payment Account Accumulation YMD — year-month for split payment accounting aggregation |
| `GENE_ADD_DTM` | Field | Generation Registration DateTimeStamp — timestamp when the record was generated |
| `ADD_DTM` / `UPD_DTM` / `DEL_DTM` | Field | Registration / Update / Delete DateTimeStamp — audit timestamps for each operation type |
| `ADD_OPEACNT` / `UPD_OPEACNT` / `DEL_OPEACNT` | Field | Registration / Update / Delete Operator Account — audit identity of the operator |
| `MK_FLG` | Field | Valid/Invalid Flag — `"0"` = Valid (有効), `"1"` = Invalid (無効) |
| `judgeYmd` | Field | Judgment Reference Date — the date used as a baseline for validating date consistency in installment registration |
| `excSearchList` | Parameter | Exclusivity-locked search result — data result after optimistic concurrency lock check |
| `KK_T_KOJIHI_KAP_KEI` | Table | Construction Fee Installment Contract table — the persistent entity for installment agreements |
| `KP0041` | Constant | Installment Plan Code: Lump-sum (一括) |
| `KP0141` | Constant | Installment Plan Code: Lump-sum 10% (一括 10%) |
| `KP0040` | Constant | Installment Plan Code: Installment (分割) |
| `KP0140` | Constant | Installment Plan Code: Installment 10% (分割 10%) |
| IT2-2018-0000042 | Change ticket | IT change ticket that modified the charge-start date logic to use judgment reference date comparison |
| ANK-3951-10-00 | Change ticket | ANK change ticket that modified setParam[8] to use judgment reference date and added lump-sum plan type check |
| OM-2019-0000601 | Change ticket | OM change ticket that replaced batch operation date with judgment reference date for comparison |
