# Business Logic — JBSbatKKBndWdtOvrSendMl.updateFtthTsrckJsk() [108 LOC]

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

## 1. Role

### JBSbatKKBndWdtOvrSendMl.updateFtthTsrckJsk()

This method updates the **FTTH (Fiber To The Home) communication volume excess record** — specifically, it writes and consolidates usage-period data for the `KK_T_FTTH_TSRCK_JSK` (FTTH Communication Volume Excess Record) database table. It serves as the batch processing step that records whether a service contract has exceeded its FTTH bandwidth threshold in the current or target billing cycle, enabling downstream notification mail generation (implementation notice or warning notice) when excess usage is detected.

The method branches by **send type (sendKbn)** to set different values depending on whether this is an **implementation notice (jishi, sendKbn="2")** — where domain control is marked as implemented and ISP authentication IDs are populated — or a **warning notice (yokoku, sendKbn="1")** — where only the excess date is set to the current operation date. A **default branch** also retrieves the first-excess date via `getFtthJskInfo` for non-notice scenarios.

The method implements a **query-prepare-lock-write pattern**: it first queries the service contract table (`KK_T_SVC_KEI`) for pricing codes, prepares the update payload in a `JBSbatCommonDBInterface`, optionally retrieves FTTH usage details from the excess record table itself (to handle pricing code fallback logic), applies a row-level lock via `lockFtthTsrckJsk`, and finally executes a primary-key update via `executeKK_T_FTTH_TSRCK_JSK_PKUPDATE`. If the update affects zero or one rows, a `JBSbatBusinessError` is thrown.

Its role in the larger system is a **core batch data consolidation step** within the domain-control communication volume excess notification mail creation workflow. It is called by the class's own `execute()` method during batch processing cycles.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["updateFtthTsrckJsk svcKeiNo, sendKbn"])
    
    START --> Q1["Query KK_T_SVC_KEI: executeKK_T_SVC_KEI_KK_SELECT_180"]
    Q1 --> R1["Select pcrsCd, pplanCd from KK_T_SVC_KEI"]
    R1 --> INIT["Initialize nengetsu = getTargetNengetsu 0"]
    INIT --> SETMAP["Create setMap = new JBSbatCommonDBInterface"]
    SETMAP --> MAP1["ftthJskInfoFirst = new HashMap"]
    MAP1 --> MAP2["ftthJskInfoSecond = new HashMap"]
    MAP2 --> COND1{sendKbn == SEND_KBN_JISHI}
    
    COND1 -->|true| JISHI["Block 2: Implementation Notice"]
    COND1 -->|false| COND2{sendKbn == SEND_KBN_YOKOKU}
    COND2 -->|true| YOKOKU["Block 3: Warning Notice"]
    COND2 -->|false| DEFAULT["Block 4: Default"]
    
    JISHI --> J1["getFtthJskInfo svcKeiNo, ftthJskInfoFirst, getTargetNengetsu 1"]
    J1 --> J2["setMap.setValue FTTH_TSR_FST_CHOK_TCH_YMD"]
    J2 --> J3["setMap.setValue TIK_CTL_JSSI_ZM_FLG = 1"]
    J3 --> J4["setMap.setValue TIK_CTL_JSSI_YMD = super.opeDate"]
    J4 --> J5["ninshoId = getNinshoId svcKeiNo"]
    J5 --> J6["setMap.setValue ISP_NINSHO_ID"]
    J6 --> J7["mltNinshoId = getMltNinshoId svcKeiNo"]
    J7 --> J8["setMap.setValue MLTISE_NINSHO_ID"]
    J8 --> MERGE1["Proceed to post-branch processing"]
    
    YOKOKU --> Y1["setMap.setValue FTTH_TSR_FST_CHOK_TCH_YMD = super.opeDate"]
    Y1 --> MERGE1
    
    DEFAULT --> D1["getFtthJskInfo svcKeiNo, ftthJskInfoFirst, getTargetNengetsu 1"]
    D1 --> D2["setMap.setValue FTTH_TSR_FST_CHOK_TCH_YMD"]
    D2 --> MERGE1
    
    MERGE1 --> MAP3["ftthJskInfoSecond = new HashMap"]
    MAP3 --> G2["getFtthJskInfo svcKeiNo, ftthJskInfoSecond, getTargetNengetsu 0"]
    G2 --> COND3{pcrsCd from ftthJskInfoSecond null or blank?}
    COND3 -->|no| R2["pcrsCd = ftthJskInfoSecond.get PCRS_CD"]
    COND3 -->|no| R3["pplanCd = ftthJskInfoSecond.get PPLAN_CD"]
    COND3 -->|yes| R4["Keep original pcrsCd and pplanCd"]
    R2 --> WMAP["Create whereMap"]
    R3 --> WMAP
    R4 --> WMAP
    
    WMAP --> W1["whereMap.setValue SVC_KEI_NO"]
    W1 --> W2["whereMap.setValue PCRS_CD"]
    W2 --> W3["whereMap.setValue PPLAN_CD"]
    W3 --> W4["whereMap.setValue FTTH_TUSHIN_USE_YM"]
    W4 --> LOCK["lockFtthTsrckJsk svcKeiNo, pcrsCd, pplanCd"]
    LOCK --> UPDATE["executeKK_T_FTTH_TSRCK_JSK_PKUPDATE setMap, whereMap"]
    UPDATE --> CNT{cnt gt 1?}
    CNT -->|false| THROW["throw JBSbatBusinessError"]
    CNT -->|true| END(["Return void"])
    THROW --> END
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `svcKeiNo` | `String` | Service contract number — a unique identifier for the customer's service contract line. Used as the primary key to locate and update the FTTH excess record. |
| 2 | `sendKbn` | `String` | Send type classification — determines which notification branch to execute. Can be `"2"` (implementation notice / `SEND_KBN_JISHI`, `[-> SEND_KBN_JISHI="2" (JBSbatKKBndWdtOvrSendMl.java:118)`) to populate domain control flags and ISP authentication IDs, or `"1"` (warning notice / `SEND_KBN_YOKOKU`, `[-> SEND_KBN_YOKOKU="1" (JBSbatKKBndWdtOvrSendMl.java:114)`) to set only the first-excess date. Any other value falls into the default branch. |

**Instance fields / external state read:**

| # | Field | Source | Business Description |
|---|-------|--------|---------------------|
| 1 | `super.opeDate` | Base class `JBSbatBusinessService` | Batch operation date — the processing date used for `TIK_CTL_JSSI_YMD` (domain control implementation date) and warning notice first-excess date. |
| 2 | `db_KK_T_SVC_KEI` | Instance field | Database access cursor for the `KK_T_SVC_KEI` (Service Contract) table, initialized during `initial()`. |
| 3 | `BndWdtOvrTchiCount` | Instance field | Domain control communication volume excess notification file output record count (not directly used in this method, but maintained at class level). |

## 4. CRUD Operations / Called Services

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

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `executeKK_T_SVC_KEI_KK_SELECT_180` | KK_SELECT_180 | KK_T_SVC_KEI | Selects pricing code (`pcrsCd`) and pricing plan code (`pplanCd`) for the given service contract number and operation date. |
| R | `JBSbatCommonDBInterface.getString` | JBSbatKK_T_SVC_KEI | KK_T_SVC_KEI | Extracts `pcrsCd` and `pplanCd` string values from the query result map. |
| R | `getTargetNengetsu` | N/A | N/A | Retrieves the FTTH communication usage month (billing period). Called twice: once with `0` (current) and once with `1` (previous). |
| R | `getFtthJskInfo` | KK_SELECT_006 | KK_T_FTTH_TSRCK_JSK | Queries the FTTH excess record table to find the first-excess date and pricing codes. Called twice: with month `1` (previous) for first-excess info, and with month `0` (current) for current pricing code fallback. |
| R | `getNinshoId` | N/A | KK_T_FTTH_TSRCK_JSK | Retrieves the ISP authentication ID for the service contract (used in implementation notice). |
| R | `getMltNinshoId` | N/A | KK_T_FTTH_TSRCK_JSK | Retrieves the multi-selection authentication ID for the service contract (used in implementation notice). |
| U | `executeKK_T_FTTH_TSRCK_JSK_PKUPDATE` | PKUPDATE | KK_T_FTTH_TSRCK_JSK | Performs an UPDATE on the FTTH communication volume excess record using `setMap` (payload) and `whereMap` (key conditions). |
| - | `lockFtthTsrckJsk` | N/A | KK_T_FTTH_TSRCK_JSK | Applies a row-level lock on the FTTH excess record before the update to prevent concurrent modifications. |
| - | `JDKStructuredMap.setValue` | N/A | N/A | Sets values into the `JBSbatCommonDBInterface` (used as setMap and whereMap) via `setValue(key, value)`. |
| - | `JKBKStringUtil.isNullBlank` | JKBKStringUtil | N/A | Checks whether the pricing code from the FTTH info map is null or blank (for fallback logic). |

## 5. Dependency Trace

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Batch:JBSbatKKBndWdtOvrSendMl | `JBSbatKKBndWdtOvrSendMl.execute()` -> `JBSbatKKBndWdtOvrSendMl.updateFtthTsrckJsk(svcKeiNo, sendKbn)` | `executeKK_T_FTTH_TSRCK_JSK_PKUPDATE [U] KK_T_FTTH_TSRCK_JSK`, `lockFtthTsrckJsk [-] KK_T_FTTH_TSRCK_JSK`, `getFtthJskInfo [R] KK_T_FTTH_TSRCK_JSK`, `getNinshoId [R] KK_T_FTTH_TSRCK_JSK`, `getMltNinshoId [R] KK_T_FTTH_TSRCK_JSK`, `getTargetNengetsu [R] N/A` |

## 6. Per-Branch Detail Blocks

**Block 1** — [SET / EXEC] Initialize service contract query and prepare data structures (L897)

> Queries the `KK_T_SVC_KEI` table for pricing codes, initializes the billing month variable, and creates HashMaps for FTTH info retrieval.

| # | Type | Code |
|---|------|------|
| 1 | SET | `svcKeiParam = {svcKeiNo, super.opeDate}` | // Build query parameter array with service contract number and operation date |
| 2 | CALL | `executeKK_T_SVC_KEI_KK_SELECT_180(svcKeiParam)` | Query service contract table `KK_T_SVC_KEI` [-> KK_T_SVC_KEI_KK_SELECT_180="KK_SELECT_180" (JBSbatKKBndWdtOvrSendMl.java:61)] |
| 3 | CALL | `resultMap = db_KK_T_SVC_KEI.selectNext()` | Retrieve next result row from the query cursor |
| 4 | SET | `pcrsCd = null` | Initialize pricing code variable |
| 5 | SET | `pplanCd = null` | Initialize pricing plan code variable |
| 6 | IF | `null != resultMap` | (L903) — Conditional extraction of pricing codes from query result |

**Block 1.1** — [IF] Extract pricing codes from result (L903-907)

> When the query returns a result row, extract the pricing code and pricing plan code into local variables for later use in the update WHERE clause.

| # | Type | Code |
|---|------|------|
| 1 | SET | `pcrsCd = resultMap.getString(JBSbatKK_T_SVC_KEI.PCRS_CD)` | Get pricing code from result map |
| 2 | SET | `pplanCd = resultMap.getString(JBSbatKK_T_SVC_KEI.PPLAN_CD)` | Get pricing plan code from result map |

**Block 2** — [IF] Implementation Notice (L922) `[SEND_KBN_JISHI="2"]` (L922)

> When sendKbn is the implementation notice type (`"2"`), populate the FTTH excess record with the first-excess date, mark domain control as implemented (`TIK_CTL_JSSI_ZM_FLG = "1"`), set the implementation date to the operation date, and retrieve ISP authentication IDs. This branch performs the most comprehensive field updates — it is used when the system has already confirmed the excess and needs to record the implementation details.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `getFtthJskInfo(svcKeiNo, ftthJskInfoFirst, getTargetNengetsu(1))` | Retrieve FTTH info for previous month (v10.00.00 modification — replaced getLastMonthFtthFstYmd) [-> SEND_KBN_JISHI="2" (JBSbatKKBndWdtOvrSendMl.java:118)] |
| 2 | SET | `setMap.setValue(JBSbatKK_T_FTTH_TSRCK_JSK.FTTH_TSR_FST_CHOK_TCH_YMD, ftthJskInfoFirst.get(...))` | Set first-excess notification date from retrieved info |
| 3 | SET | `setMap.setValue(JBSbatKK_T_FTTH_TSRCK_JSK.TIK_CTL_JSSI_ZM_FLG, "1")` | Mark domain control implementation flag as completed |
| 4 | SET | `setMap.setValue(JBSbatKK_T_FTTH_TSRCK_JSK.TIK_CTL_JSSI_YMD, super.opeDate)` | Set domain control implementation date to current operation date |
| 5 | CALL | `ninshoId = getNinshoId(svcKeiNo)` | Retrieve ISP authentication ID |
| 6 | SET | `setMap.setValue(JBSbatKK_T_FTTH_TSRCK_JSK.ISP_NINSHO_ID, ninshoId)` | Store ISP authentication ID in the update set |
| 7 | CALL | `mltNinshoId = getMltNinshoId(svcKeiNo)` | Retrieve multi-selection authentication ID |
| 8 | SET | `setMap.setValue(JBSbatKK_T_FTTH_TSRCK_JSK.MLTISE_NINSHO_ID, mltNinshoId)` | Store multi-selection authentication ID in the update set |

**Block 3** — [ELSE-IF] Warning Notice (L937) `[SEND_KBN_YOKOKU="1"]` (L937)

> When sendKbn is the warning notice type (`"1"`), only set the first-excess notification date to the current operation date. This is a minimal update — used when issuing a warning before full implementation. [-> SEND_KBN_YOKOKU="1" (JBSbatKKBndWdtOvrSendMl.java:114)]

| # | Type | Code |
|---|------|------|
| 1 | SET | `setMap.setValue(JBSbatKK_T_FTTH_TSRCK_JSK.FTTH_TSR_FST_CHOK_TCH_YMD, super.opeDate)` | Set first-excess date to current operation date |

**Block 4** — [ELSE] Default (L942)

> For any sendKbn value that is neither implementation notice nor warning notice, perform the same first-excess date retrieval as the implementation notice branch — this ensures the first-excess date is always populated even for non-notice scenarios.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `getFtthJskInfo(svcKeiNo, ftthJskInfoFirst, getTargetNengetsu(1))` | Retrieve FTTH info for previous month [v10.00.00 Mod Start] |
| 2 | SET | `setMap.setValue(JBSbatKK_T_FTTH_TSRCK_JSK.FTTH_TSR_FST_CHOK_TCH_YMD, ftthJskInfoFirst.get(...))` | Set first-excess date from retrieved info |

**Block 5** — [SET / EXEC] Post-branch: retrieve current-month FTTH info and resolve pricing codes (L948-960)

> After the sendKbn branch resolves, retrieve the current-month FTTH info into a second HashMap. Then apply a fallback: if the pricing code from the FTTH info map is NOT null or blank, override the pricing codes (`pcrsCd`, `pplanCd`) that were originally fetched from `KK_T_SVC_KEI`. This handles the case where the service contract table returns null pricing codes but the FTTH excess record table has valid data. (v10.00.01 modification) [-> JKBKStringUtil.isNullBlank check (JBSbatKKBndWdtOvrSendMl.java:958)]

| # | Type | Code |
|---|------|------|
| 1 | SET | `ftthJskInfoSecond = new HashMap<String,String>()` | Create new HashMap for current-month FTTH info [v10.00.00 Add] |
| 2 | CALL | `getFtthJskInfo(svcKeiNo, ftthJskInfoSecond, getTargetNengetsu(0))` | Retrieve FTTH info for current month |
| 3 | IF | `!JKKStringUtil.isNullBlank(ftthJskInfoSecond.get(JBSbatKK_T_FTTH_TSRCK_JSK.PCRS_CD))` | (L958) — v10.00.01: If pricing code from FTTH info is available, use it to override |

**Block 5.1** — [IF] Override pricing codes from FTTH info (L959-960)

> When the FTTH excess record contains a non-null pricing code, use it to override the pricing code and pricing plan code obtained from the service contract query. This ensures the update uses the most recently available pricing data.

| # | Type | Code |
|---|------|------|
| 1 | SET | `pcrsCd = ftthJskInfoSecond.get(JBSbatKK_T_FTTH_TSRCK_JSK.PCRS_CD)` | Override pricing code from FTTH info |
| 2 | SET | `pplanCd = ftthJskInfoSecond.get(JBSbatKK_T_FTTH_TSRCK_JSK.PPLAN_CD)` | Override pricing plan code from FTTH info |

**Block 6** — [SET / EXEC] Build WHERE clause and execute update (L963-984)

> Constructs the WHERE clause map using the service contract number, pricing code, pricing plan code, and billing month. Then applies a row-level lock and executes the primary-key update on the FTTH excess record table. Finally validates the update count — if less than or equal to 1 row was updated, a business error is thrown.

| # | Type | Code |
|---|------|------|
| 1 | SET | `whereMap = new JBSbatCommonDBInterface()` | Create WHERE clause map |
| 2 | SET | `whereMap.setValue(JBSbatKK_T_FTTH_TSRCK_JSK.SVC_KEI_NO, svcKeiNo)` | Set service contract number as WHERE key |
| 3 | SET | `whereMap.setValue(JBSbatKK_T_FTTH_TSRCK_JSK.PCRS_CD, pcrsCd)` | Set pricing code as WHERE key |
| 4 | SET | `whereMap.setValue(JBSbatKK_T_FTTH_TSRCK_JSK.PPLAN_CD, pplanCd)` | Set pricing plan code as WHERE key |
| 5 | SET | `whereMap.setValue(JBSbatKK_T_FTTH_TSRCK_JSK.FTTH_TUSHIN_USE_YM, nengetsu)` | Set FTTH usage month as WHERE key |
| 6 | CALL | `lockFtthTsrckJsk(svcKeiNo, pcrsCd, pplanCd)` | Acquire row-level lock on the target record |
| 7 | CALL | `cnt = executeKK_T_FTTH_TSRCK_JSK_PKUPDATE(setMap, whereMap)` | Execute UPDATE on KK_T_FTTH_TSRCK_JSK table |
| 8 | IF | `1 > cnt` | (L986) — Validate update count |

**Block 6.1** — [IF] Update validation failure (L987)

> If the update did not affect more than 1 row (meaning the target record was not found or the update failed), throw a business error to abort the batch processing.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `throw new JBSbatBusinessError()` | Throw business exception — no rows were updated |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `svcKeiNo` | Field | Service contract number — unique identifier for the customer's service contract line item. |
| `sendKbn` | Field | Send type classification — determines whether to issue an implementation notice ("2") or a warning notice ("1"). |
| `pcrsCd` | Field | Pricing code — the code identifying the billing/pricing tier for the service contract. |
| `pplanCd` | Field | Pricing plan code — the code identifying the specific pricing plan associated with the service contract. |
| `nengetsu` | Field | FTTH communication usage month — the billing period (YYYYMM format) for which excess usage is being recorded. |
| `ninshoId` | Field | ISP authentication ID — the customer's authentication identifier for the Internet Service Provider. |
| `mltNinshoId` | Field | Multi-selection authentication ID — additional authentication IDs for services with multiple selections. |
| `opeDate` | Field | Batch operation date — the processing date of the batch job (inherited from base class). |
| `TIK_CTL_JSSI_ZM_FLG` | Field | Domain control implementation flag — when set to "1", indicates that domain control has been implemented for this excess record. |
| `TIK_CTL_JSSI_YMD` | Field | Domain control implementation date — the date when domain control was implemented. |
| `FTTH_TSR_FST_CHOK_TCH_YMD` | Field | FTTH communication volume first-excess notification date — the date when the customer first exceeded the communication volume threshold. |
| `ISP_NINSHO_ID` | Field | ISP authentication ID — stored in the FTTH excess record for implementation notice purposes. |
| `MLTISE_NINSHO_ID` | Field | Multi-selection ISP authentication ID — stored in the FTTH excess record for multi-service customers. |
| `FTTH_TUSHIN_USE_YM` | Field | FTTH communication usage month — the target billing month used in the WHERE clause to identify the exact excess record. |
| FTTH | Business term | Fiber To The Home — fiber-optic broadband internet service. |
| JISHI | Japanese term | 実施 — "Implementation"; sendKbn value "2" indicating a confirmed/excess-confirmed notification. |
| YOKOKU | Japanese term | 警告 — "Warning"; sendKbn value "1" indicating a pre-emptive warning notification. |
| KK_T_SVC_KEI | DB Table | Service Contract table — stores service contract header information including pricing codes. |
| KK_T_FTTH_TSRCK_JSK | DB Table | FTTH Communication Volume Excess Record table — stores records of customers who have exceeded their FTTH bandwidth limits. |
| SETMAP | Internal | JBSbatCommonDBInterface instance holding the SET values for the UPDATE statement. |
| WHEREMAP | Internal | JBSbatCommonDBInterface instance holding the WHERE clause keys for the UPDATE statement. |
