# Business Logic — JBSbatKKSmtvlMskmInfoTrkm.chkAddMskmsho() [357 LOC]

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

## 1. Role

### JBSbatKKSmtvlMskmInfoTrkm.chkAddMskmsho()

This method is the **address-change subscription registration check** for booking documents with detail numbers, acting as a gatekeeping validation step in KDDI's service contract management workflow. Its primary business purpose is to verify that a customer's service contracts (both fiber-optic/eo Hikari NET and telephone lines) are valid, properly linked, and eligible for a new subscription registration following an address change. The method resolves service contract data from booking document numbers or detail numbers, applies smart-billing eligibility rules to determine which contracts qualify, and enforces the critical business constraint that a NET contract must coexist with a telephone contract on the same alternate line (rensen route) — reflecting KDDI's bundled-service model where internet and voice services are cross-sold as a pair. The method implements a **routing/dispatch pattern**: it first attempts a booking-number lookup, falls back to a booking-detail-number lookup when configured (`isShogoMskmshoDtlNo`), and then branches its validation logic based on which service types (NET/telephone/both/none) are found. Upon passing all validations, it populates the `workMap` with resolved service contract numbers, third-party discount contract data, course names, and billing start dates for downstream processing stages.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["chkAddMskmsho start"])

    START --> L1["L2043: Init local vars and maps"]
    L1 --> L2["L2055: selectSvcKeiByMskmshoNo(mskmshoNo)"]
    L2 --> C1{svcKeiList empty?
or isShogoMskmshoDtlNo?}

    C1 -->|No: Normal query| L3["L2091: Loop svcKeiList - net contract check"]
    C1 -->|Yes: Fallback to detail| L4["L2066: selectSvcKeiByMskmshoDtlNo(mskmshoNo)"]

    L4 --> C2{isShogoMskmshoDtlNo?}
    C2 -->|Yes: Only detail lookup| C3{svcKeiList empty?}
    C2 -->|No: First query empty| C4{svcKeiList empty?}

    C3 -->|Yes| L5["L2074: Return false - not found"]
    C3 -->|No| L6["L2079-2081: Clear ERR_CD, KDDI_ERR_CD"]

    C4 -->|Yes| L7["L2091-2092: Debug log, ERR_CD_E03, KDDI_ERR_CD_206"]
    C4 -->|No| L3

    L3 --> RULE["L2100: executeRULE0086001(svcKeiMap)"]
    RULE --> C5{APLY_KH_OK?}
    C5 -->|No: Not applicable| C6{APLY_SVC_KEI_EOHNT?}
    C5 -->|Yes: Applicable| L8{APLY_SVC_KEI_EOHNT?}

    L8 -->|Yes and !isNetExist| L9["Set SYSID, SVC_KEI_NO_NET; store aplySvcKeiNetMap; break"]
    L8 -->|Yes: EOHTL phone| L10["Store aplySvcKeiTelMap if empty"]
    L8 -->|Neither| C7{isFirst iteration?}

    C6 -->|Yes: EOHNT but not applicable| L11["Set isNetExist=true, SVC_KEI_NO_NET"]
    C6 -->|No: Not EOHNT| L12["Next iteration or continue"]

    L11 --> C8{errCd == ERR_CD_E04?}
    C8 -->|No| L13["ERR_CD=errCd, KDDI_ERR_CD=kddiErrCd, Return false"]
    C8 -->|Yes| L12

    L9 --> NET_EXIST{aplySvcKeiNetMap not empty?}
    L10 --> NET_EXIST
    L12 --> NET_EXIST

    NET_EXIST -->|Yes: Both contract check| L14["Get svcKeiNoNet, sysIdNet"]
    NET_EXIST -->|No: No net contract| C9{aplySvcKeiTelMap empty?}

    L14 --> L15["L2153: selectSvcKeiBySysIdSvcKeiNo"]
    L15 --> L16["L2159: Loop svcKeiList - phone contract check"]
    L16 --> RULE2["L2161: executeRULE0086001"]
    RULE2 --> C10{APLY_KH_OK AND APLY_SVC_KEI_EOHTL?}

    C10 -->|Yes: Phone eligible| L17{isItens?}
    C10 -->|No: Not eligible| L12

    L17 -->|Yes| L18["Compare ITENS_SVKEI_KISUW_NO"]
    L17 -->|No| L19["Compare SVC_KEI_KAISEN_UCWK_NO"]

    L18 --> C11{Same line match?}
    L19 --> C12{Same line match?}

    C11 -->|Yes| L20["Store aplySvcKeiTelMap; break"]
    C11 -->|No| L21["Try alternate line: SVC_KEI_KAISEN_UCWK_NO"]
    C12 -->|Yes| L20
    C12 -->|No| L22["Set isExistBtKaisen=true"]

    L20 --> L23["aplySvcKeiTelMap empty?"]
    L22 --> L23

    L23 -->|No: Both found| C13{isExistBtKaisen?}
    L23 -->|Yes: No phone contract| C14{isExistBtKaisen?}

    C14 -->|Yes| L24["ERR_CD_EA1, KDDI_ERR_CD_207 - alternate line only"]
    C14 -->|No| L25["ERR_CD_E06, KDDI_ERR_CD_207 - net only"]

    C13 -->|No: Both found| L26["Continue to smart billing check"]
    C13 -->|Yes: Alternate only| L24

    C9 -->|Yes: Phone only| L27["ERR_CD_E05, KDDI_ERR_CD_207 - phone only"]
    C9 -->|No: Neither| L28["ERR_CD_E04, KDDI_ERR_CD_207 - both missing"]

    L24 --> L26
    L25 --> L26
    L27 --> L26
    L28 --> L26

    L26 --> L29["L2234: selectTajgsWribKeiByValCd"]
    L29 --> C15{tajgsWribKeiList not empty?}

    C15 -->|Yes| C16{isValidYmd?}
    C15 -->|No| L30["Loop svcKeiNoList - check each service contract"]

    C16 -->|Yes: Contract terminated| L24_2["ERR_CD_E10, KDDI_ERR_CD_209 - smart billing bound"]
    C16 -->|No: Active or provisional| L31["selectTajgswkeiTgkei"]

    L31 --> C17{List size < 2?}
    C17 -->|Yes| L24_3["ERR_CD_E10, KDDI_ERR_CD_209 - contract mismatch"]
    C17 -->|No| L32["Store aplyTajgsWribKeiMap"]

    L30 --> L33{"For each svcKeiNo"}
    L33 --> L34["selectTajgsWribKeiBySvcKeiNo"]
    L34 --> C18{List not empty?}

    C18 -->|Yes| C19{isValidYmd CNC_YMD?}
    C18 -->|No| L35["New registration - skip"]

    C19 -->|Yes| C20{isValidYmd DSL_YMD?}
    C19 -->|No: Provisional| L36["Store aplyTajgsWribKeiMap"]

    C20 -->|Yes: Terminated, not DSL| L24_4["ERR_CD_E10, KDDI_ERR_CD_209 - bound"]
    C20 -->|No: Terminated + DSL| L35

    L24_2 --> L37["L2330: Set output fields in workMap"]
    L24_3 --> L37
    L24_4 --> L37
    L32 --> L37
    L35 --> L37
    L36 --> L37
    L37 --> END_RETURN["L2391: Return true - check passed"]

    L5 --> END_RETURN
    L6 --> END_RETURN
    L7 --> END_RETURN
    L13 --> END_RETURN
    L25 --> END_RETURN
    L27 --> END_RETURN
    L28 --> END_RETURN
    L24 --> END_RETURN
    L24_2 --> END_RETURN
    L24_3 --> END_RETURN
    L24_4 --> END_RETURN
    L35 --> END_RETURN
    L36 --> END_RETURN
    L26 --> L37
    L32 --> L37
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `workMap` | `HashMap<String, Object>` | The shared work context map carrying all data between processing stages. It provides input fields such as the discount group code (`WRIBPRC_GRP_CD`) used to look up third-party discount contracts, and receives output fields including error codes (`ERR_CD`, `KDDI_ERR_CD`), service contract numbers for both NET (`SVC_KEI_NO_NET`) and telephone (`SVC_KEI_NO_TEL`), system ID (`SYSID`), third-party discount contract details, course name code, and billing start dates. |
| 2 | `isShogoMskmshoDtlNo` | `boolean` | Flag indicating whether the method should perform lookup using the **booking detail number** rather than the booking number. When `true`, the method only attempts the detail-number lookup path and, upon success, clears any prior error codes set by the booking-number fallback. This supports a secondary resolution mode used during address-change workflows. |
| 3 | `mskmshoNo` | `String` | The **booking document number** (or detail number if `isShogoMskmshoDtlNo` is `true`). This is the primary key used to retrieve service contract records from the database. It represents a specific customer booking associated with an address change event. |

**Instance fields / external state read:**
- `commonItem` — Provides access to logging/debug utilities (`getLogPrint().printDebugLog`) used throughout all error paths.

## 4. CRUD Operations / Called Services

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

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `JBSbatKKSmtvlMskmInfoTrkm.selectSvcKeiByMskmshoNo` | EKK (Service Contract) | KK_T_SVC_KEI | Retrieves service contract records by booking document number |
| R | `JBSbatKKSmtvlMskmInfoTrkm.selectSvcKeiByMskmshoDtlNo` | EKK (Service Contract) | KK_T_SVC_KEI | Retrieves service contract records by booking detail number (fallback) |
| - | `JBSbatKKSmtvlMskmInfoTrkm.executeRULE0086001` | RULE0086001 | - | Smart-billing eligibility rule engine — evaluates whether a service contract qualifies under current business rules |
| R | `JBSbatKKSmtvlMskmInfoTrkm.selectSvcKeiBySysIdSvcKeiNo` | EKK (Service Contract) | KK_T_SVC_KEI | Retrieves all service contracts for the same SYSID + NET service contract number (to find co-located phone contracts) |
| R | `JBSbatKKSmtvlMskmInfoTrkm.selectTajgsWribKeiByValCd` | EKK (Third-party Discount) | KK_T_TAJGS_WRIB_KEI | Retrieves third-party discount contracts by value code (discount group code from workMap) |
| R | `JBSbatKKSmtvlMskmInfoTrkm.selectTajgswkeiTgkei` | EKK (Third-party Discount Link) | KK_T_TAJGS_WRIB_KEI, KK_T_SVC_KEI | Retrieves linked third-party discount contract-to-service-contract relationship records |
| R | `JBSbatKKSmtvlMskmInfoTrkm.selectTajgsWribKeiBySvcKeiNo` | EKK (Third-party Discount) | KK_T_TAJGS_WRIB_KEI | Retrieves third-party discount contracts by individual service contract number (when no group discount exists) |
| R | `JBSbatKKSmtvlMskmInfoTrkm.getCourseNmCd` | EKK (Course) | KK_T_COURSE / KK_T_SVC_KEI | Resolves course name code from NET service contract number, process group code, product code, and plan code |
| - | `JBSbatKKSmtvlMskmInfoTrkm.isNullSpace` | - | - | Utility: checks if a string is null or blank |
| - | `JBSbatKKSmtvlMskmInfoTrkm.isValidYmd` | - | - | Utility: validates whether a year-month-day string is a real date (not the initial value "20991231") |
| - | `JACBatCommon.printDebugLog` | Debug | - | Debug logging utility (via commonItem.getLogPrint()) |

**Classification rationale:**
- **Read (R)**: All five database query methods follow the `select*By*` naming convention and are used exclusively to retrieve data for validation checks.
- **RULE0086001**: An internal business rule evaluation method that returns a map containing eligibility flags (`APLY_KH`, `APLY_SVC_KEI`) and error codes — it does not directly access the database.
- **getCourseNmCd**: A read operation that resolves a human-readable course name from service contract metadata.
- **isNullSpace / isValidYmd**: In-memory validation utilities.

## 5. Dependency Trace

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | `JBSbatKKSmtvlMskmInfoTrkm.chkAdd` | `chkAdd` -> `chkAddMskmsho(workMap, isShogoMskmshoDtlNo, mskmshoNo)` | `selectSvcKeiByMskmshoNo [R] KK_T_SVC_KEI`, `selectSvcKeiByMskmshoDtlNo [R] KK_T_SVC_KEI`, `selectSvcKeiBySysIdSvcKeiNo [R] KK_T_SVC_KEI`, `selectTajgsWribKeiByValCd [R] KK_T_TAJGS_WRIB_KEI`, `selectTajgswkeiTgkei [R] KK_T_TAJGS_WRIB_KEI/KK_T_SVC_KEI`, `selectTajgsWribKeiBySvcKeiNo [R] KK_T_TAJGS_WRIB_KEI`, `getCourseNmCd [R] KK_T_COURSE/KK_T_SVC_KEI`, `printDebugLog [-]`, `executeRULE0086001 [-]`, `isValidYmd [-]`, `isNullSpace [-]` |

**Instructions:**
- The sole direct caller is `chkAdd()` within the same class, which serves as the address-change subscription entry-point validation method.
- `chkAdd()` is itself called during the broader address-change registration batch flow, feeding through work maps that contain the discount group code and booking number.
- Terminal operations resolve to two primary database tables: `KK_T_SVC_KEI` (service contract data) and `KK_T_TAJGS_WRIB_KEI` (third-party discount contract data), plus course metadata tables.

## 6. Per-Branch Detail Blocks

**Block 1** — [SET] Local variable initialization (L2043)

> Initializes the local working state: rule result map, smart-billing eligibility tracking maps for NET and telephone contracts, and a map for third-party discount contract data.

| # | Type | Code |
|---|------|------|
| 1 | SET | `ruleResult = new HashMap<String, Object>()` // Rule evaluation result storage |
| 2 | SET | `aplyKh = ""` // Smart-billing applicability flag [-> APLY_KH_OK="0" (JBSbatKKSmtvlMskmInfoTrkm.java:323)] |
| 3 | SET | `aplySvcKei = ""` // Applicable service contract type [-> APLY_SVC_KEI_EOHNT="01" (JBSbatKKSmtvlMskmInfoTrkm.java:331)] |
| 4 | SET | `errCd = ""` // Rule evaluation error code |
| 5 | SET | `kddiErrCd = ""` // KDDI-specific error code |
| 6 | SET | `aplySvcKeiNetMap = new HashMap<String, Object>()` // NET contract data cache |
| 7 | SET | `aplySvcKeiTelMap = new HashMap<String, Object>()` // Telephone contract data cache |
| 8 | SET | `aplyTajgsWribKeiMap = new HashMap<String, Object>()` // Third-party discount contract data cache |

**Block 2** — [SET] Service contract list initialization (L2055)

> Retrieves service contracts by booking document number.

| # | Type | Code |
|---|------|------|
| 1 | SET | `svcKeiList = new ArrayList<HashMap<String, Object>>()` // Empty list |
| 2 | CALL | `svcKeiList = selectSvcKeiByMskmshoNo(mskmshoNo)` // R: KK_T_SVC_KEI — get contracts by booking number |

**Block 3** — [IF] `svcKeiList == null || svcKeiList.size() == 0 || isShogoMskmshoDtlNo` (L2059)

> If the primary booking-number lookup returned nothing, or if detail-number lookup is explicitly requested, fall back to the detail-number query path.

**Block 3.1** — [IF] `isShogoMskmshoDtlNo` is true (L2066)

> Explicit detail-number lookup mode. The booking number query was skipped or the caller requires detail-number resolution.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `svcKeiList = selectSvcKeiByMskmshoDtlNo(mskmshoNo)` // R: KK_T_SVC_KEI — get contracts by detail number |
| 2 | IF | Check if result is empty |
| 3 | SET | `workMap.put(ERR_CD, "")` // Clear error code [-> ERR_CD="err_cd" (JBSbatKKSmtvlMskmInfoTrkm.java:425)] |
| 4 | SET | `workMap.put(KDDI_ERR_CD, "")` // Clear KDDI error code [-> KDDI_ERR_CD="kddi_err_cd" (JBSbatKKSmtvlMskmInfoTrkm.java:428)] |
| 5 | RETURN | `return false` // If no records found via detail number either |

**Block 3.2** — [ELSE-IF] `isShogoMskmshoDtlNo` is false, result is empty (L2091)

> The booking number lookup returned no results and this was not a detail-number-only lookup. This indicates the booking number is not registered — an error.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `commonItem.getLogPrint().printDebugLog(...)` // Debug: "照合チェックエラー（登録）「割引料金引継番号でサービス契約情報が取得できませんでした」" (Verification check error (registration) "Service contract could not be retrieved with the discount carryover number") |
| 2 | SET | `workMap.put(ERR_CD, ERR_CD_E03)` // "E03" — Customer not registered [-> ERR_CD_E03="E03" (JBSbatKKSmtvlMskmInfoTrkm.java:226)] |
| 3 | SET | `workMap.put(KDDI_ERR_CD, KDDI_ERR_CD_206)` // "206" — Business contract management number not found [-> KDDI_ERR_CD_206="206" (JBSbatKKSmtvlMskmInfoTrkm.java:299)] |
| 4 | RETURN | `return false` |

**Block 4** — [FOR] Iterate `svcKeiList` — NET contract eligibility check (L2091)

> Loop through all service contracts found, evaluating each against the smart-billing eligibility rule.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `ruleResult = executeRULE0086001(svcKeiMap)` // Rule engine evaluation |
| 2 | SET | `aplyKh = (String)ruleResult.get("APLY_KH")` // [-> APLY_KH_OK="0"] |
| 3 | SET | `aplySvcKei = (String)ruleResult.get("APLY_SVC_KEI")` // [-> APLY_SVC_KEI_EOHNT="01", APLY_SVC_KEI_EOHTL="02"] |
| 4 | SET | `errCd = (String)ruleResult.get("ERR_CD")` |
| 5 | SET | `kddiErrCd = (String)ruleResult.get("KDDI_ERR_CD")` |

**Block 4.1** — [IF] `APLY_KH_OK.equals(aplyKh)` (L2109)

> The service contract meets smart-billing eligibility criteria.

**Block 4.1.1** — [IF] `APLY_SVC_KEI_EOHNT.equals(aplySvcKei) && !isNetExist` (L2110)

> The applicable contract is an eo Hikari NET contract (not yet captured).

| # | Type | Code |
|---|------|------|
| 1 | SET | `workMap.put(SYSID, (String)svcKeiMap.get(JBSbatKK_T_SVC_KEI.SYSID))` // [-> SYSID="sysid" (JBSbatKKSmtvlMskmInfoTrkm.java:467)] |
| 2 | SET | `workMap.put(SVC_KEI_NO_NET, (String)svcKeiMap.get(JBSbatKK_T_SVC_KEI.SVC_KEI_NO))` // [-> SVC_KEI_NO_NET="svc_kei_no_net" (JBSbatKKSmtvlMskmInfoTrkm.java:470)] |
| 3 | SET | `aplySvcKeiNetMap.putAll(svcKeiMap)` // Cache the NET contract data |
| 4 | EXEC | `break` // First NET contract found — exit loop |

**Block 4.1.2** — [ELSE-IF] `APLY_SVC_KEI_EOHTL.equals(aplySvcKei)` (L2130)

> The applicable contract is an eo Hikari telephone contract.

| # | Type | Code |
|---|------|------|
| 1 | IF | `aplySvcKeiTelMap.isEmpty()` |
| 2 | SET | `aplySvcKeiTelMap.putAll(svcKeiMap)` // Cache first telephone contract |

**Block 4.2** — [ELSE] `!APLY_KH_OK` — Not eligible per rule (L2138)

> The contract does not meet smart-billing criteria. However, if it is a NET contract, record the error and potentially fail.

| # | Type | Code |
|---|------|------|
| 1 | IF | `APLY_SVC_KEI_EOHNT.equals(aplySvcKei)` (L2140) |
| 2 | SET | `isNetExist = true` // NET exists but with error |
| 3 | SET | `workMap.put(SVC_KEI_NO_NET, (String)svcKeiMap.get(JBSbatKK_T_SVC_KEI.SVC_KEI_NO))` // Still record the NET contract number |
| 4 | IF | `!ERR_CD_E04.equals(errCd)` (L2146) — [-> ERR_CD_E04="E04" (JBSbatKKSmtvlMskmInfoTrkm.java:229)] |
| 5 | EXEC | `commonItem.getLogPrint().printDebugLog(...)` // Debug: "照合チェックエラー（登録）「関連ルールによるネットの照合チェックエラー」" |
| 6 | SET | `workMap.put(ERR_CD, errCd)` // Propagate the rule error |
| 7 | SET | `workMap.put(KDDI_ERR_CD, kddiErrCd)` |
| 8 | RETURN | `return false` |

**Block 5** — [IF] `!aplySvcKeiNetMap.isEmpty()` — NET contract found, check telephone contract (L2163)

> A valid NET contract was identified. Now verify that a co-located telephone contract exists on the same alternate line.

| # | Type | Code |
|---|------|------|
| 1 | SET | `aplySvcKeiTelMap = new HashMap<String, Object>()` // Reset phone map |
| 2 | SET | `svcKeiNoNet = (String)aplySvcKeiNetMap.get(JBSbatKK_T_SVC_KEI.SVC_KEI_NO)` |
| 3 | SET | `sysIdNet = (String)aplySvcKeiNetMap.get(JBSbatKK_T_SVC_KEI.SYSID)` |
| 4 | SET | `isExistBtKaisen = false` // Alternate-line phone contract flag |
| 5 | SET | `isItens = !isNullSpace(aplySvcKeiNetMap.get(JBSbatKK_T_ADCHG.ITENS_SVKEI_KISUW_NO))` // [-> JBSbatKK_T_ADCHG = entity class] |
| 6 | CALL | `svcKeiList = selectSvcKeiBySysIdSvcKeiNo(svcKeiNoNet, sysIdNet)` // R: KK_T_SVC_KEI — find all contracts with same SYSID |

**Block 5.1** — [FOR] Iterate service contracts with same SYSID — find telephone contract (L2159)

| # | Type | Code |
|---|------|------|
| 1 | CALL | `ruleResult = executeRULE0086001(svcKeiMap)` |
| 2 | SET | `aplyKh`, `aplySvcKei` from rule result |

**Block 5.1.1** — [IF] `APLY_KH_OK.equals(aplyKh) && APLY_SVC_KEI_EOHTL.equals(aplySvcKei)` (L2178)

> A telephone contract found that meets smart-billing eligibility.

**Block 5.1.1.1** — [IF] `isItens` — Address-change scenario (L2183)

> When the NET contract has an address-change carryover number, verify the telephone contract is on the same alternate line.

| # | Type | Code |
|---|------|------|
| 1 | SET | `svcKeiKaisenUcwkNoNet = aplySvcKeiNetMap.get(JBSbatKK_T_ADCHG.ITENS_SVKEI_KISUW_NO)` // NET's carryover number |
| 2 | SET | `svcKeiKaisenUcwkNoTel = svcKeiMap.get(JBSbatKK_T_ADCHG.ITENS_SVKEI_KISUW_NO)` // Phone's carryover number |
| 3 | IF | `!svcKeiKaisenUcwkNoNet.equals(svcKeiKaisenUcwkNoTel)` — [-> JBSbatKK_T_KAISEN_TG_SVKEI = entity] |
| 4 | SET | `svcKeiKaisenUcwkNoNet = aplySvcKeiNetMap.get(JBSbatKK_T_KAISEN_TG_SVKEI.SVC_KEI_KAISEN_UCWK_NO)` // Fallback: use alternate-line carryover number |
| 5 | SET | `svcKeiKaisenUcwkNoTel = svcKeiMap.get(JBSbatKK_T_KAISEN_TG_SVKEI.SVC_KEI_KAISEN_UCWK_NO)` |

**Block 5.1.1.2** — [ELSE] `!isItens` — No address-change carryover (L2193)

> Fall back to the alternate-line carryover number (`SVC_KEI_KAISEN_UCWK_NO`) for cross-referencing.

| # | Type | Code |
|---|------|------|
| 1 | SET | `svcKeiKaisenUcwkNoNet = aplySvcKeiNetMap.get(JBSbatKK_T_KAISEN_TG_SVKEI.SVC_KEI_KAISEN_UCWK_NO)` |
| 2 | SET | `svcKeiKaisenUcwkNoTel = svcKeiMap.get(JBSbatKK_T_KAISEN_TG_SVKEI.SVC_KEI_KAISEN_UCWK_NO)` |

**Block 5.1.1.3** — [IF] `svcKeiKaisenUcwkNoNet != null && equals(svcKeiKaisenUcwkNoTel)` (L2201)

> Phone contract on the same alternate line found — valid pairing.

| # | Type | Code |
|---|------|------|
| 1 | SET | `aplySvcKeiTelMap.putAll(svcKeiMap)` // Cache the matching phone contract |
| 2 | EXEC | `break` |

**Block 5.1.1.4** — [ELSE] Line numbers do not match (L2210)

> A phone contract exists but on a different alternate line — flag it as an alternate-line candidate.

| # | Type | Code |
|---|------|------|
| 1 | SET | `isExistBtKaisen = true` |

**Block 5.2** — [IF] `aplySvcKeiTelMap.isEmpty()` — No valid telephone contract found (L2221)

| # | Type | Code |
|---|------|------|
| 1 | IF | `isExistBtKaisen` — Alternate-line phone contract was found (L2226) |
| 2 | EXEC | `commonItem.getLogPrint().printDebugLog(...)` // "別回線内線番号" (Different line internal number) |
| 3 | SET | `workMap.put(ERR_CD, ERR_CD_EA1)` // "EA1" — Alternate line internal number [-> ERR_CD_EA1="EA1" (JBSbatKKSmtvlMskmInfoTrkm.java:266)] |
| 4 | SET | `workMap.put(KDDI_ERR_CD, KDDI_ERR_CD_207)` // "207" — FTTH contract line service error [-> KDDI_ERR_CD_207="207" (JBSbatKKSmtvlMskmInfoTrkm.java:296)] |
| 5 | RETURN | `return false` |
| 6 | [ELSE] — No telephone contract at all (L2230) |
| 7 | EXEC | `commonItem.getLogPrint().printDebugLog(...)` // ".NETのみ契約" (NET-only contract) |
| 8 | SET | `workMap.put(ERR_CD, ERR_CD_E06)` // "E06" — NET-only contract [-> ERR_CD_E06="E06" (JBSbatKKSmtvlMskmInfoTrkm.java:236)] |
| 9 | SET | `workMap.put(KDDI_ERR_CD, KDDI_ERR_CD_207)` |
| 10 | RETURN | `return false` |

**Block 6** — [ELSE] `aplySvcKeiNetMap.isEmpty()` — No NET contract found (L2235)

> The initial scan did not find any valid NET contract. Check if only a telephone contract exists.

**Block 6.1** — [IF] `!aplySvcKeiTelMap.isEmpty()` — Telephone-only contract (L2239)

> A telephone contract exists without a NET contract — this is an invalid configuration for this workflow.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `commonItem.getLogPrint().printDebugLog(...)` // "電話のみ" (Telephone only) |
| 2 | SET | `workMap.put(SVC_KEI_NO_NET, (String)aplySvcKeiTelMap.get(JBSbatKK_T_SVC_KEI.SVC_KEI_NO))` // Store phone number in NET field (for KDDI error notification) |
| 3 | SET | `workMap.put(ERR_CD, ERR_CD_E05)` // "E05" — Telephone-only contract [-> ERR_CD_E05="E05" (JBSbatKKSmtvlMskmInfoTrkm.java:233)] |
| 4 | SET | `workMap.put(KDDI_ERR_CD, KDDI_ERR_CD_207)` |
| 5 | RETURN | `return false` |

**Block 6.2** — [ELSE] Neither NET nor telephone contract found (L2248)

> No applicable service contract at all.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `commonItem.getLogPrint().printDebugLog(...)` // "対象外サービス" (Non-target service) |
| 2 | SET | `workMap.put(ERR_CD, ERR_CD_E04)` // "E04" — Non-target service [-> ERR_CD_E04="E04" (JBSbatKKSmtvlMskmInfoTrkm.java:229)] |
| 3 | SET | `workMap.put(KDDI_ERR_CD, KDDI_ERR_CD_207)` |
| 4 | RETURN | `return false` |

**Block 7** — [SET] Smart billing binding check — Third-party discount validation (L2261)

> When both NET and telephone contracts are valid, verify that the customer has not already bound a smart billing arrangement with a third-party discount contract.

| # | Type | Code |
|---|------|------|
| 1 | SET | `tajgsWribKeiList = new ArrayList<HashMap<String, Object>>()` |
| 2 | CALL | `tajgsWribKeiList = selectTajgsWribKeiByValCd((String)workMap.get(WRIBPRC_GRP_CD))` // R: KK_T_TAJGS_WRIB_KEI — get third-party discount by discount group code [-> WRIBPRC_GRP_CD="wribprc_grp_cd" (JBSbatKKSmtvlMskmInfoTrkm.java:404)] |

**Block 7.1** — [IF] `tajgsWribKeiList != null && size > 0` (L2265)

> A third-party discount contract exists.

**Block 7.1.1** — [IF] `isValidYmd(TAJGS_WRIB_KEI_CNC_YMD)` — Contract already terminated (L2267)

> The discount contract's termination date is set (not the initial "20991231"), meaning it has already been terminated.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `commonItem.getLogPrint().printDebugLog(...)` // "スマートバリ締結チェック" (Smart billing binding check) |
| 2 | SET | `workMap.put(ERR_CD, ERR_CD_E10)` // "E10" — Discount info already registered [-> ERR_CD_E10="E10" (JBSbatKKSmtvlMskmInfoTrkm.java:248)] |
| 3 | SET | `workMap.put(KDDI_ERR_CD, KDDI_ERR_CD_209)` // "209" — Duplicate registration error [-> KDDI_ERR_CD_209="209" (JBSbatKKSmtvlMskmInfoTrkm.java:293)] |
| 4 | RETURN | `return false` |

**Block 7.1.2** — [IF] `tajgswkeiTgkeiList.size() < 2` — Contract mismatch (L2285)

> The linked third-party discount contract-to-service-contract relationship records are missing or insufficient. The linked discount group code and booking number service contracts must match exactly.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `tajgswkeiTgkeiList = selectTajgswkeiTgkei(tajgsWribKeiNo, aplySvcKeiNetMap svcKeiNo, aplySvcKeiTelMap svcKeiNo)` // R: KK_T_TAJGS_WRIB_KEI, KK_T_SVC_KEI |
| 2 | EXEC | `commonItem.getLogPrint().printDebugLog(...)` // "バリコードと申込書の関連チェック" (Discount code and booking document relationship check) |
| 3 | SET | `workMap.put(ERR_CD, ERR_CD_E10)` |
| 4 | SET | `workMap.put(KDDI_ERR_CD, KDDI_ERR_CD_209)` |
| 5 | RETURN | `return false` |
| 6 | SET | `aplyTajgsWribKeiMap.putAll(tajgsWribKeiMap)` |

**Block 7.2** — [ELSE] No third-party discount contract by group code (L2295)

> No group-level discount contract exists. Check each service contract individually for third-party discount contracts (OM-2014-0003197: 2014/10/02 modification).

| # | Type | Code |
|---|------|------|
| 1 | SET | `svcKeiNoList[] = {aplySvcKeiNetMap.SVC_KEI_NO, aplySvcKeiTelMap.SVC_KEI_NO}` // Array of both service contract numbers |

**Block 7.2.1** — [FOR] Each `svcKeiNo` in `svcKeiNoList` (L2295–L2329)

**Block 7.2.1.1** — [CALL] `selectTajgsWribKeiBySvcKeiNo(svcKeiNo)` (L2304)

> Query for third-party discount contracts attached to this individual service contract.

**Block 7.2.1.2** — [IF] `tajgsWribKeiBySvcKeiNoList != null && size > 0` (L2305)

> A third-party discount contract exists for this service contract.

**Block 7.2.1.2.1** — [IF] `isValidYmd(TAJGS_WRIB_KEI_CNC_YMD)` — Contract terminated (L2310)

| # | Type | Code |
|---|------|------|
| 1 | IF | `!isValidYmd(TAJGS_WRIB_KEI_DSL_YMD)` — Contract bound but not released (L2313) |
| 2 | EXEC | `commonItem.getLogPrint().printDebugLog(...)` // "スマートバリ締結チェック2" (Smart billing binding check 2) |
| 3 | SET | `workMap.put(ERR_CD, ERR_CD_E10)` |
| 4 | SET | `workMap.put(KDDI_ERR_CD, KDDI_ERR_CD_209)` |
| 5 | RETURN | `return false` |
| 6 | [ELSE] — Contract terminated AND released (L2320) |
| 7 | SET | Re-registration for new subscription (no error — the contract was fully released) |

**Block 7.2.1.2.2** — [ELSE] Provisional registration (L2324)

> The contract is in provisional (not yet terminated) state.

| # | Type | Code |
|---|------|------|
| 1 | SET | `aplyTajgsWribKeiMap.putAll(tajgsWribKeiBySvcKeiNoMap)` // Use this provisional contract for update processing |

**Block 8** — [SET] Populate output fields in workMap — Check OK (L2330)

> All validations passed. Set the resolved data fields into `workMap` for downstream stages.

| # | Type | Code |
|---|------|------|
| 1 | SET | `workMap.put(SVC_KEI_NO_TEL, aplySvcKeiTelMap.SVC_KEI_NO)` // Telephone service contract number [-> SVC_KEI_NO_TEL="svc_kei_no_tel" (JBSbatKKSmtvlMskmInfoTrkm.java:473)] |
| 2 | SET | `workMap.put(TAJGS_WRIB_KEI_NO, aplyTajgsWribKeiMap.TAJGS_WRIB_KEI_NO)` // [-> TAJGS_WRIB_KEI_NO="tajgs_wrib_kei_no" (JBSbatKKSmtvlMskmInfoTrkm.java:476)] |
| 3 | SET | `workMap.put(TAJGS_WRIB_KEI_UPD_DTM, aplyTajgsWribKeiMap.UPD_DTM)` // [-> TAJGS_WRIB_KEI_UPD_DTM="tajgs_wrib_kei_upd_dtm" (JBSbatKKSmtvlMskmInfoTrkm.java:479)] |
| 4 | SET | `workMap.put(KDDI_JGS_KEI_KANRI_NO, aplyTajgsWribKeiMap.KDDI_JGS_KEI_KANRI_NO)` // [-> KDDI_JGS_KEI_KANRI_NO="kddi_jgs_kei_kanri_no" (JBSbatKKSmtvlMskmInfoTrkm.java:482)] |
| 5 | SET | `workMap.put(TAJGS_WRIB_KEI_GENE_ADD_DTM, aplyTajgsWribKeiMap.GENE_ADD_DTM)` // [-> TAJGS_WRIB_KEI_GENE_ADD_DTM="tajgs_wrib_kei_gene_add_dtm" (JBSbatKKSmtvlMskmInfoTrkm.java:485)] |
| 6 | SET | `workMap.put(COURSE_NM_CD, getCourseNmCd(netSvcKeiNo, netPRC_GRP_CD, netPCRS_CD, netPPLAN_CD))` // [-> COURSE_NM_CD="course_nm_cd" (JBSbatKKSmtvlMskmInfoTrkm.java:431)] — Resolve course name from NET contract metadata |
| 7 | SET | `workMap.put(NET_SVC_MSKM_YMD, aplySvcKeiNetMap.SHOSA_YMD)` // [-> NET_SVC_MSKM_YMD="net_svc_mskm_ymd" (JBSbatKKSmtvlMskmInfoTrkm.java:434)] — NET service subscription date |
| 8 | SET | `workMap.put(NET_SVC_CHRG_STAYMD, aplySvcKeiNetMap.SVC_CHRG_STAYMD)` // [-> NET_SVC_CHRG_STAYMD="net_svc_chrg_staymd" (JBSbatKKSmtvlMskmInfoTrkm.java:437)] — NET service billing start date |
| 9 | SET | `workMap.put(TEL1_SVC_MSKM_YMD, aplySvcKeiTelMap.SHOSA_YMD)` // [-> TEL1_SVC_MSKM_YMD="tel1_svc_mskm_ymd" (JBSbatKKSmtvlMskmInfoTrkm.java:440)] — Telephone service subscription date |
| 10 | SET | `workMap.put(TEL1_SVC_CHRG_STAYMD, aplySvcKeiTelMap.SVC_CHRG_STAYMD)` // [-> TEL1_SVC_CHRG_STAYMD="tel1_svc_chrg_staymd" (JBSbatKKSmtvlMskmInfoTrkm.java:443)] — Telephone service billing start date |

**Block 9** — [RETURN] Success (L2391)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return true` // All checks passed — proceed to subscription registration |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `mskmshoNo` | Field | Booking document number — the primary identifier for a customer's service subscription application/registration |
| `mskm_dtl_no` | Field | Booking detail number — a sub-identifier for individual line items within a booking document |
| `svc_kei_no` | Field | Service contract number — unique identifier for a specific service contract line (NET or telephone) |
| `svc_kei_no_net` | Field | NET service contract number — the service contract number specifically for the eo Hikari internet line |
| `svc_kei_no_tel` | Field | Telephone service contract number — the service contract number for the eo Hikari voice line |
| `sysid` | Field | System ID — a grouping identifier that links service contracts belonging to the same customer account |
| `aply_kh` | Field | Applicability flag — indicates whether a service contract meets smart-billing eligibility criteria ("0" = applicable, "1" = not applicable) |
| `aply_svc_kei` | Field | Applicable service type — classifies the type of qualifying service ("01" = eo Hikari NET, "02" = eo Hikari telephone) |
| `ERR_CD` | Field | Error code — internal application error code (e.g., "E03" = customer not found, "E04" = non-target service, "E05" = telephone-only, "E06" = NET-only, "E10" = discount info registered) |
| `KDDI_ERR_CD` | Field | KDDI error code — external KDDI-side error code for partner notification ("206" = contract management number not found, "207" = FTTH line service status error, "209" = duplicate registration error) |
| `WRIBPRC_GRP_CD` | Field | Discount group code — the KDDI value code that groups third-party discount contracts; used to look up discount relationships |
| `tajgs_wrib_kei_no` | Field | Third-party discount contract number — identifier for a discount arrangement with an external carrier |
| `TAJGS_WRIB_KEI_CNC_YMD` | Field | Third-party discount contract termination date — date when the discount contract was terminated; "20991231" (initial value) means still active |
| `TAJGS_WRIB_KEI_DSL_YMD` | Field | Third-party discount contract release date — date when the discount contract was fully released |
| `ITENS_SVKEI_KISUW_NO` | Field | Alternate line internal number — the carryover service contract number used in address-change workflows to link old and new contracts on the same physical line |
| `SVC_KEI_KAISEN_UCWK_NO` | Field | Service contract alternate-line carryover work number — used as a fallback for linking contracts when the primary carryover number does not match |
| APLY_KH_OK | Constant | Applicability = OK ("0") — service contract meets smart-billing criteria |
| APLY_KH_NG | Constant | Applicability = NG ("1") — service contract does not meet smart-billing criteria |
| APLY_SVC_KEI_EOHNT | Constant | Applicable service = eo Hikari NET ("01") |
| APLY_SVC_KEI_EOHTL | Constant | Applicable service = eo Hikari telephone ("02") |
| ERR_CD_E03 | Constant | Customer not registered error code ("E03") — booking number not found in system |
| ERR_CD_E04 | Constant | Non-target service error code ("E04") — service type is not supported for this workflow |
| ERR_CD_E05 | Constant | Telephone-only contract error code ("E05") — telephone exists but NET does not |
| ERR_CD_E06 | Constant | NET-only contract error code ("E06") — NET exists but telephone does not |
| ERR_CD_E10 | Constant | Discount info already registered error code ("E10") — customer already has a bound smart billing arrangement |
| ERR_CD_EA1 | Constant | Alternate line internal number mismatch error code ("EA1") — phone and NET contracts are on different physical lines |
| KDDI_ERR_CD_206 | Constant | Business contract management number not found ("206") |
| KDDI_ERR_CD_207 | Constant | FTTH contract line service error ("207") — line status or service mismatch |
| KDDI_ERR_CD_209 | Constant | Duplicate registration error ("209") — customer already has a valid smart binding |
| KK_T_SVC_KEI | Entity | Service contract master table — stores all service contract records (NET and telephone lines) |
| KK_T_TAJGS_WRIB_KEI | Entity | Third-party discount contract table — stores discount arrangements with external carriers |
| KK_T_ADCHG | Entity | Address change table — stores address-change carryover numbers linking contracts across moves |
| KK_T_KAISEN_TG_SVKEI | Entity | Alternate-line target service contract table — stores alternate-line carryover work numbers |
| eo Hikari NET | Business term | KDDI's fiber-optic broadband internet service (brand: eo光ネット) |
| eo Hikari telephone | Business term | KDDI's VoIP telephone service bundled with eo Hikari (brand: eo光電話) |
| Smart billing (スマートバリ) | Business term | KDDI's smart billing service that bundles third-party carrier discounts into KDDI billing |
| Third-party discount (他事業者割引) | Business term | Discount arrangements with external mobile/carrier providers that are linked to KDDI service contracts |
| Alternate line (別回線) | Business term | A different physical phone line; contracts on different alternate lines cannot be bundled for smart billing |
| isShogoMskmshoDtlNo | Parameter | Flag — when true, performs lookup exclusively by booking detail number rather than booking number |
| executeRULE0086001 | Method | Internal smart-billing eligibility rule engine that evaluates whether a service contract qualifies under current business rules |
| isItens | Local variable | Flag — indicates whether the address-change carryover number (`ITENS_SVKEI_KISUW_NO`) is set, enabling alternate-line verification |
| isExistBtKaisen | Local variable | Flag — indicates whether a phone contract exists on an alternate (different) line |
| chkAddMskmsho | Method | This method — address-change subscription registration check for booking documents with detail numbers |
| chkAdd | Method | Caller — address-change subscription entry-point validation that invokes chkAddMskmsho |
