# Business Logic — JKKHakkoSODCC.opHktgiOdrCtrl() [392 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `com.fujitsu.futurity.bp.custom.common.JKKHakkoSODCC` |
| Layer | CC/Common Component |
| Module | `common` (Package: `com.fujitsu.futurity.bp.custom.common`) |

## 1. Role

### JKKHakkoSODCC.opHktgiOdrCtrl()

This method implements **Option Inheritance Order Control Processing** -- the business operation responsible for orchestrating Service Order Data (SOD) generation when a telecom customer opts to inherit (port) their service contract from an existing line to a new line. It acts as a central dispatcher/router that evaluates the pre-change and post-change option service contract states, then issues the appropriate SODs for cancellation, registration, and restoration of the underlying telecom services.

The method handles multiple **service types**: Fixed Global IP Address (FTTH), Email (Mail/Chirp), WEB (Home Page), Mailing List, and Virus Protection -- each triggering a different set of SOD registrations. It also handles **sub-option** scenarios (e.g., sub-option virus protection under a primary option).

The method implements a **routing/dispatch design pattern** with a builder-like delegation model: it fetches contract agreement data from multiple service components (EKK0351A010SC, EKK0361A010SC, EKK0401A010SC, EKK0161B004SC), examines the resulting agreement records, and then dispatches to `addSOD()` with different order content codes (ODR_NAIYO_CD) to build the final SOD payload.

Its **role in the larger system** is as a shared utility called by the entry point `hakkoSOD()` method in the same class. It bridges the gap between raw service contract agreement data and the SOD creation layer -- transforming contract state into a sequence of operational orders.

Conditional branches cover: (1) pre-change option data exists but does not match the Fixed Global IP cancellation pattern -- no SOD; (2) post-change option data with sub-option present -- virus protection registration; (3) post-change option with no sub-option -- Email/WEB/Mailing-list issuance based on `OP_SVC_CD`; (4) Fixed Global IP cancellation (pre-change path) -- issues a cascade of three SODs.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["opHktgiOdrCtrl(params)"])

    START --> EXTRACT["Extract SOD/Service/Option maps from sodMap"]
    EXTRACT --> SHKKA["Sanitize maps via shkkaMap()"]
    SHKKA --> CHECKMULTI["Check dataList.size() > 1"]
    CHECKMULTI --> |"Size > 1"| SETMULTI["opHktgiHukusuFlg = true"]
    CHECKMULTI --> |"Size <= 1"| SKIPMULTI["opHktgiHukusuFlg = false"]
    SETMULTI --> EXTRACTPARAMS["Extract service contract and option parameters"]
    SKIPMULTI --> EXTRACTPARAMS
    EXTRACTPARAMS --> RETREIVEPRE["Retrieve pre-change option via callEKK0351A010SC"]
    RETREIVEPRE --> RETRIEVEPOST["Retrieve post-change option via callEKK0351A010SC"]
    RETRIEVEPOST --> RETRIEVESUB["Retrieve post-change sub-option via callEKK0401A010SC"]
    RETRIEVESUB --> CHECKPRECHANGE["chbfEKK0351A010SCHash != null?"]
    CHECKPRECHANGE --> |"Yes"| PRECHANGEPROC["Pre-change processing"]
    CHECKPRECHANGE --> |"No"| SKIPPRECHANGE["Skip pre-change processing"]
    PRECHANGEPROC --> PRECHANGECONDITION["opSvcKeiStat = SVC_KEI_STAT_910 AND opSvcCd = OP_SVC_CD_FIXIPAD"]
    PRECHANGECONDITION --> |"Match"| FIXEDIPPROC["Fixed Global IP cancellation"]
    PRECHANGECONDITION --> |"No match"| SKIPPRECHANGESOD["No SOD - skip"]
    FIXEDIPPROC --> FIXIP_SVCINFO["Get service contract details via callEKK0161B004SC"]
    FIXIP_SVCINFO --> FIXIP_SODS["Issue SODs: FIXIP cancel, FTTH cancel, FTTH register"]
    SKIPPRECHANGESOD --> CHECKPOSTCHANGE["chafEKK0351A010SCHash != null?"]
    SKIPPRECHANGE --> CHECKPOSTCHANGE
    CHECKPOSTCHANGE --> |"Yes"| POSTCHANGEPROC["Post-change processing"]
    CHECKPOSTCHANGE --> |"No"| SKIPPOSTCHANGE["Skip post-change"]
    POSTCHANGEPROC --> POSTSUBOPTION["chafEKK0401A010SCHash null?"]
    POSTSUBOPTION --> |"Null - no sub-option"| OPPOSTCONDITION["sakiOpSvcKeiStat >= SVC_KEI_STAT_020"]
    POSTSUBOPTION --> |"Not null - sub-option"| SUBOPTIONPROC["Sub-option processing"]
    OPPOSTCONDITION --> |"True - active"| OPPOSTSERVICES["Issue SODs by OP_SVC_CD"]
    OPPOSTCONDITION --> |"False - cancelled"| SKIPOPPOSTSOD["No SOD"]
    OPPOSTSERVICES --> |"Email"| EMAIL_SOD["addSOD: Email/Chirp register"]
    OPPOSTSERVICES --> |"WEB"| WEB_SOD["addSOD: WEB/Restore"]
    OPPOSTSERVICES --> |"Mailing"| MAILING_SOD["addSOD: Mailing-list/Restore"]
    SUBOPTIONPROC --> SUBOPTIONCHECK["sbopSvcKeiStat >= SVC_KEI_STAT_020"]
    SUBOPTIONCHECK --> |"True - active"| SUBOPTIONEMAIL["sbopSvcCd = SBOP_SVC_CD_VIRUS"]
    SUBOPTIONCHECK --> |"False - cancelled"| SKIPSUBOP["No SOD"]
    SUBOPTIONEMAIL --> SUBOP_SOD["addSOD: Email/Virus register"]
    SKIPOPPOSTSOD --> RESTOREWORKMAP["Restore workMap"]
    SKIPOPPOSTSOD --> RESTOREWORKMAP
    SKIPSUBOP --> RESTOREWORKMAP
    EMAIL_SOD --> RESTOREWORKMAP
    WEB_SOD --> RESTOREWORKMAP
    MAILING_SOD --> RESTOREWORKMAP
    SUBOP_SOD --> RESTOREWORKMAP
    FIXIP_SODS --> RESTOREWORKMAP
    RESTOREWORKMAP --> END(["Return param"])
    SKIPPOSTCHANGE --> END
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `handle` | `SessionHandle` | Session handle carrying session management context (e.g., security context, transaction info) -- used in all service component calls. |
| 2 | `param` | `IRequestParameterReadWrite` | Request parameter object containing the model group, control map, and business data payload. Used to read user data (`fixedText`-keyed data), write work maps, and receives the transformed result with SOD payload appended via `addSOD()` calls. |
| 3 | `fixedText` | `String` | User-optional identifier key used to retrieve user-specific data from `param`. Serves as the lookup key for `param.getData(fixedText)` to access the target data list. |
| 4 | `sodMap` | `HashMap<String, Object>` | SOD (Service Order Data) map containing three sub-maps: `SOD_KIHON_INFO` (basic SOD info), `SVC_KEI_INFO` (service contract info -- source line number, inherited-from number), and `OPSVKEI_INFO` (option service contract info -- pre-change/post-change option numbers and generation timestamps). |

**Instance fields read/modified by the method:**

| Field | Type | Business Description |
|-------|------|---------------------|
| `this.same_trn_no` | `String` (cached) | Same processing number -- used to ensure multiple option inheritance calls share a single transaction number when `opHktgiHukusuFlg` is true. |
| `this.svc_kei_ucwk_no[]` | `String[]` (size 1) | Service contract detail work number -- retrieved from `callEKK0161B004SC` result, used for tracking. |
| `this.svc_kei_ucwk_gadtm[]` | `String[]` (size 1) | Service contract detail work generation timestamp. |
| `this.op_svc_kei_no_fixipad` | `String` | Pre-change option service contract number specifically for Fixed Global IP Address handling. |
| `this.op_gadtm_fixipad` | `String` | Pre-change option generation timestamp for Fixed Global IP Address. |
| `this.op_svc_kei_no_ml` | `String` | Option service contract number for Mail/Chirp service. |
| `this.op_gadtm_ml` | `String` | Mail/Chirp generation timestamp. |
| `this.mlad` | `String` | Mail/Chirp address (MLAD) from agreement hash. |
| `this.op_svc_kei_no_hp` | `String` | Option service contract number for WEB/Home Page service. |
| `this.op_gadtm_hp` | `String` | WEB/Home Page generation timestamp. |
| `this.op_svc_kei_no_mlist` | `String` | Option service contract number for Mailing List service. |
| `this.op_gadtm_mlist` | `String` | Mailing List generation timestamp. |
| `this.old_vrsb_jdg_svc_dtl_cd` | `String` | Old VR (voice recognition?) identification judgment service detail code -- used for legacy system compatibility. |
| `this.pplan_cd` | `String` | Plan code -- referenced in `getOldVrsbIdgSvcDtlCd()` call. |

## 4. CRUD Operations / Called Services

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `callEKK0351A010SC` | EKK0351A010SC | KK_T_OP_SVC_KEI (Option service contract) | Retrieves pre-change and post-change option service contract agreement data. Called for both `chbf` (pre-change) and `chaf` (post-change) option info with `FUNC_CODE_1`. |
| R | `callEKK0401A010SC` | EKK0401A010SC | KK_T_SBOP_SVC_KEI (Sub-option service contract) | Retrieves post-change sub-option service contract agreement data (e.g., virus protection sub-option). Uses `FUNC_CODE_1` if generation timestamp exists, `FUNC_CODE_2` for date-based retrieval. |
| R | `callEKK0161B004SC` | EKK0161B004SC | KK_T_SVC_KEI (Service contract), KK_T_SVC_KEI_UCWK (Service contract detail work) | Retrieves service contract details list. Called to get current service contract work number (`SVC_KEI_UCWK_NO`) and generation timestamp for Fixed Global IP Address handling. |
| R | `callEKK0361A010SC` | EKK0361A010SC | KK_T_OP_SVC_KEI_ISP (Option service contract ISP) | Retrieves option service contract <ISP> agreement data. Called when post-change Email service is active to fetch the Mail/Chirp address (`MLAD`). |
| R | `getOldVrsbIdgSvcDtlCd` | (internal) | - | Determines old VR identification judgment service detail code for legacy system compatibility. Called with the moto (inherited-from) service contract number and plan code. |
| R | `getSame_trn_no` | (internal) | - | Retrieves the same processing number to ensure consistent transaction numbering for multiple option inheritance operations. |
| R | `getSvcKeiInfo` | (internal) | - | Retrieves service contract information including plan code (`pplan_cd`). Called in the Fixed Global IP path to fetch the plan code for legacy judgment. |
| R | `takeCurrentSvcKeiUcwk` | (internal) | - | Extracts current service contract detail work data from the `EKK0161B004SC` result hash. Returns a map containing `SVC_KEI_UCWK_NO` and `GENE_ADD_DTM`. |
| - | `isBlank` | (internal) | - | Null/blank check utility for string fields. Used throughout for defensive null checking. |
| - | `shkkaMap` | (internal) | - | Map sanitization utility -- cleans/normalizes HashMap data before use. |
| C | `addSOD` | (internal) | SOD (Service Order Data) entity | Creates and appends SOD records to the param. Called with different `ODR_NAIYO_CD` values: `154` (Fixed Global IP Address cancellation), `104` (FTTH cancellation), `101` (FTTH registration), `120` (Email/Chirp registration), `128` (WEB restoration), `133` (Mailing-list restoration), `114` (Email/Virus registration), `152` (Fixed Global IP Address registration). |

## 5. Dependency Trace

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | `JKKHakkoSODCC.hakkoSOD()` | `hakkoSOD()` -> `opHktgiOdrCtrl()` | `addSOD [C] SOD entity`, `callEKK0351A010SC [R] KK_T_OP_SVC_KEI`, `callEKK0401A010SC [R] KK_T_SBOP_SVC_KEI`, `callEKK0161B004SC [R] KK_T_SVC_KEI`, `callEKK0361A010SC [R] KK_T_OP_SVC_KEI_ISP` |

## 6. Per-Branch Detail Blocks

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

> Initializes status code and multi-item flag, extracts and sanitizes the three sub-maps from the sodMap.

| # | Type | Code |
|---|------|------|
| 1 | SET | `statusCode = 0` // Service interval execution status |
| 2 | SET | `opHktgiHukusuFlg = false` // Option inheritance multi-data flag |
| 3 | SET | `sod_kihon_info_Map = (HashMap)sodMap.get(SOD_KIHON_INFO)` // SOD basic info [-> `SOD_KIHON_INFO`] |
| 4 | SET | `svc_kei_info_Map = (HashMap)sodMap.get(SVC_KEI_INFO)` // Service contract info [-> `SVC_KEI_INFO`] |
| 5 | SET | `opsvkei_info_Map = (HashMap)sodMap.get(OPSVKEI_INFO)` // Option service contract info [-> `OPSVKEI_INFO`] |
| 6 | EXEC | `sod_kihon_info_Map = shkkaMap(sod_kihon_info_Map)` // Sanitize basic info map |
| 7 | EXEC | `svc_kei_info_Map = shkkaMap(svc_kei_info_Map)` // Sanitize service info map |
| 8 | EXEC | `opsvkei_info_Map = shkkaMap(opsvkei_info_Map)` // Sanitize option info map |
| 9 | SET | `chbfEKK0351A010SCHash = null` // Pre-change option service contract agreement hash [-> `chbf` = 変更前 = "before change"] |
| 10 | SET | `chafEKK0351A010SCHash = null` // Post-change option service contract agreement hash [-> `chaf` = 変更後 = "after change"] |
| 11 | SET | `chafEKK0401A010SCHash = null` // Post-change sub-option service contract agreement hash (OM-2014-0001956) |

**Block 2** — [SET] Extract user data and check for multiple items (L17096)

> Retrieves user data keyed by `fixedText` and checks if the target data list contains multiple items.

| # | Type | Code |
|---|------|------|
| 1 | SET | `inMap = (HashMap)param.getData(fixedText)` // User data info |
| 2 | SET | `dataList = (ArrayList)inMap.get(TRGT_DATA_LIST)` // Target data list [-> `TRGT_DATA_LIST`] |
| 3 | IF | `dataList.size() > 1` → `opHktgiHukusuFlg = true` // Multiple items flag set |

**Block 3** — [SET] Extract option inheritance mandatory parameters (L17103)

> Retrieves service contract numbers, pre-change/post-change option numbers, and generation timestamps from the sanitized maps.

| # | Type | Code |
|---|------|------|
| 1 | SET | `svc_kei_no = svc_kei_info_Map.get(INFO_SVC_KEI_NO)` // Prior service contract number [-> `INFO_SVC_KEI_NO`] |
| 2 | SET | `moto_svc_kei_no = svc_kei_info_Map.get(INFO_MOTO_SVC_KEI_NO)` // Inherited-from service contract number [-> `INFO_MOTO_SVC_KEI_NO`] (LT-2013-0000487) |
| 3 | SET | `moto_svckei_gene_add_dtm = svc_kei_info_Map.get(INFO_MOTO_SVKEI_GENE_ADD_DTM)` // Inherited-from generation timestamp [-> `INFO_MOTO_SVKEI_GENE_ADD_DTM`] |
| 4 | SET | `chbf_opsvkei_no = opsvkei_info_Map.get(INFO_CHBF_OPSVKEI_NO)` // Pre-change option service contract number [-> `INFO_CHBF_OPSVKEI_NO`] |
| 5 | SET | `chbf_opsvkei_gene_add_dtm = opsvkei_info_Map.get(INFO_CHBF_OPSVKEI_GENE_ADD_DTM)` // Pre-change option generation timestamp [-> `INFO_CHBF_OPSVKEI_GENE_ADD_DTM`] |
| 6 | SET | `chaf_opsvkei_no = opsvkei_info_Map.get(INFO_CHAF_OPSVKEI_NO)` // Post-change option service contract number [-> `INFO_CHAF_OPSVKEI_NO`] |
| 7 | SET | `chaf_opsvkei_gene_add_dtm = opsvkei_info_Map.get(INFO_CHAF_OPSVKEI_GENE_ADD_DTM)` // Post-change option generation timestamp [-> `INFO_CHAF_OPSVKEI_GENE_ADD_DTM`] |
| 8 | SET | `chaf_sbopsvkei_no = opsvkei_info_Map.get(INFO_CHAF_SBOPSVKEI_NO)` // Post-change sub-option number [-> `INFO_CHAF_SBOPSVKEI_NO`] (OM-2014-0001956) |
| 9 | SET | `chaf_sbopsvkei_gene_add_dtm = opsvkei_info_Map.get(INFO_CHAF_SBOPSVKEI_GENE_ADD_DTM)` // Post-change sub-option generation timestamp [-> `INFO_CHAF_SBOPSVKEI_GENE_ADD_DTM`] |
| 10 | SET | `tmpWorkMap = param.getData(HAKKOSODCCWORKMAP)` // Work map [-> `HAKKOSODCCWORKMAP`] (ANK-4468-00-01) |
| 11 | SET | `sakiSvkeiGaDtm = tmpWorkMap.get("svkei_gadtm")` // Destination service contract generation date/time [-> `svkei_gadtm`] |

**Block 4** — [IF] Retrieve pre-change option info (L17123)

> If the pre-change option number and generation timestamp are both non-blank, calls `EKK0351A010SC` to retrieve pre-change option service contract agreement data.
> [CONST: `isBlank()` checks for null or empty string]

| # | Type | Code |
|---|------|------|
| 1 | IF | `!isBlank(chbf_opsvkei_no) && !isBlank(chbf_opsvkei_gene_add_dtm)` // Pre-change option exists? |
| 2 | SET | `chbfInHash = new HashMap<>()` // Input hash |
| 3 | SET | `chbfResultHash = new HashMap<>()` // Result hash |
| 4 | SET | `chbfInHash.put(OP_SVC_KEI_NO, chbf_opsvkei_no)` // Set pre-change option number [-> `OP_SVC_KEI_NO`] |
| 5 | SET | `chbfInHash.put(GENE_ADD_DTM, chbf_opsvkei_gene_add_dtm)` // Set generation timestamp [-> `GENE_ADD_DTM`] |
| 6 | CALL | `statusCode = callEKK0351A010SC(param, handle, chbfInHash, chbfResultHash, FUNC_CODE_1)` // Option service contract agreement [-> `FUNC_CODE_1`] |
| 7 | IF | `0 != statusCode` → throw `CCException("...", new SCCallException("...", statusCode))` |
| 8 | SET | `chbfEKK0351A010SCHash = chbfResultHash.get(TEMPLATE_ID_EKK0351A010)` // Extract result [-> `TEMPLATE_ID_EKK0351A010`] |

**Block 5** — [IF] Retrieve post-change option info (L17145)

> If the post-change option number and generation timestamp are both non-blank, calls `EKK0351A010SC` to retrieve post-change option service contract agreement data. Same pattern as Block 4.
> [CONST: `isBlank()` checks for null or empty string]

| # | Type | Code |
|---|------|------|
| 1 | IF | `!isBlank(chaf_opsvkei_no) && !isBlank(chaf_opsvkei_gene_add_dtm)` // Post-change option exists? |
| 2 | SET | `chafInHash = new HashMap<>()` |
| 3 | SET | `chafResultHash = new HashMap<>()` |
| 4 | SET | `chafInHash.put(OP_SVC_KEI_NO, chaf_opsvkei_no)` |
| 5 | SET | `chafInHash.put(GENE_ADD_DTM, chaf_opsvkei_gene_add_dtm)` |
| 6 | CALL | `statusCode = callEKK0351A010SC(param, handle, chafInHash, chafResultHash, FUNC_CODE_1)` |
| 7 | IF | `0 != statusCode` → throw `CCException("...", new SCCallException("...", statusCode))` |
| 8 | SET | `chafEKK0351A010SCHash = chafResultHash.get(TEMPLATE_ID_EKK0351A010)` |

**Block 6** — [IF] Retrieve post-change sub-option info (L17166)

> If the post-change sub-option number is non-blank, calls `EKK0401A010SC` to retrieve post-change sub-option service contract agreement data. Handles two functional codes based on whether generation timestamp is present.
> [CONST: `FUNC_CODE_1` vs `FUNC_CODE_2` -- FUNC_CODE_1 if `chaf_sbopsvkei_gene_add_dtm` is present, FUNC_CODE_2 with `getOpeDate(null)` for date-based retrieval]

| # | Type | Code |
|---|------|------|
| 1 | IF | `!isBlank(chaf_sbopsvkei_no)` // Post-change sub-option exists? |
| 2 | SET | `chafInHash = new HashMap<>()` |
| 3 | SET | `chafResultHash = new HashMap<>()` |
| 4 | SET | `chafInHash.put(OP_SVC_KEI_NO, chaf_opsvkei_no)` // Post-change option number |
| 5 | SET | `chafInHash.put(SBOP_SVC_KEI_NO, chaf_sbopsvkei_no)` // Post-change sub-option number [-> `SBOP_SVC_KEI_NO`] |
| 6 | IF | `!isBlank(chaf_sbopsvkei_gene_add_dtm)` → `funcCode = FUNC_CODE_1`, `chafInHash.put(GENE_ADD_DTM, chaf_sbopsvkei_gene_add_dtm)` [-> `FUNC_CODE_1`] |
| 7 | ELSE | `funcCode = FUNC_CODE_2`, `chafInHash.put(OPE_DATE, JCCBPCommon.getOpeDate(null))` [-> `FUNC_CODE_2`] |
| 8 | CALL | `statusCode = callEKK0401A010SC(param, handle, chafInHash, chafResultHash, funcCode)` // Sub-option agreement |
| 9 | IF | `0 != statusCode` → throw `CCException("...", new SCCallException("...", statusCode))` |
| 10 | SET | `chafEKK0401A010SCHash = chafResultHash.get(TEMPLATE_ID_EKK0401A010)` [-> `TEMPLATE_ID_EKK0401A010`] |

**Block 7** — [IF] Pre-change data confirmation -- Fixed Global IP Address cancellation (L17190)

> If the pre-change option record exists, checks whether it matches the Fixed Global IP Address cancellation pattern: `opSvcKeiStat = SVC_KEI_STAT_910` AND `opSvcCd = OP_SVC_CD_FIXIPAD`. If matched, issues a cascade of SODs for Fixed Global IP cancellation, FTTH cancellation, and FTTH registration.
> [CONST: `SVC_KEI_STAT_910 = "910"`, `OP_SVC_CD_FIXIPAD = "01"` -- fixed as per LT-2013-0000487 bug fix]

| # | Type | Code |
|---|------|------|
| 1 | IF | `chbfEKK0351A010SCHash != null` // Pre-change option record exists? |
| 2 | SET | `opSvcKeiStat = chbfEKK0351A010SCHash.get(OP_SVC_KEI_STAT)` [-> `OP_SVC_KEI_STAT`] |
| 3 | SET | `opSvcCd = chbfEKK0351A010SCHash.get(OP_SVC_CD)` [-> `OP_SVC_CD`] |
| 4 | IF | `SVC_KEI_STAT_910.equals(opSvcKeiStat) && OP_SVC_CD_FIXIPAD.equals(opSvcCd)` [-> `SVC_KEI_STAT_910 = "910"`, `OP_SVC_CD_FIXIPAD = "01"` (Fixed Global IP Address)] |
| 5 | **Block 7.1** — [IF] Multiple option -- get same processing number (L17205) |
| | IF | `opHktgiHukusuFlg && isBlank(this.same_trn_no)` |
| | SET | `sameTrnNo = new String[1]` |
| | CALL | `getSame_trn_no(param, handle, null, sameTrnNo)` |
| | SET | `this.same_trn_no = sameTrnNo[0]` |
| | **END Block 7.1** |
| 6 | SET | `workMap = (HashMap)param.getData(HAKKOSODCCWORKMAP)` |
| 7 | SET | `workMap.put("svc_kei_no", moto_svc_kei_no)` // Set inherited-from service contract number [-> `HAKKOSODCCWORKMAP`] |
| 8 | SET | `workMap.put("svkei_gadtm", moto_svckei_gene_add_dtm)` // Set inherited-from generation timestamp (LT-2013-0000487 fix) |
| 9 | EXEC | `param.setData(HAKKOSODCCWORKMAP, workMap)` |
| 10 | SET | `svckeiMap = getSvcKeiInfo(handle, param)` // Get service contract info (IT1-2016-0000107) |
| 11 | SET | `motoPplanCd = svckeiMap.get("pplan_cd")` // Plan code |
| 12 | SET | `inHashUcwk = new HashMap<>()` // Input hash for EKK0161B004 |
| 13 | SET | `resultHashUcwk = new HashMap<>()` |
| 14 | SET | `inHashUcwk.put(SVC_KEI_NO, moto_svc_kei_no)` [-> `SVC_KEI_NO`] |
| 15 | CALL | `statusCode = callEKK0161B004SC(param, handle, inHashUcwk, resultHashUcwk, FUNC_CODE_1)` // Service contract details |
| 16 | IF | `0 != statusCode` → throw `CCException` |
| 17 | SET | `retHash = takeCurrentSvcKeiUcwk(resultHashUcwk)` // Extract current work data |
| 18 | SET | `this.svc_kei_ucwk_no = new String[1]` |
| 19 | SET | `this.svc_kei_ucwk_no[0] = retHash.get(SVC_KEI_UCWK_NO)` [-> `SVC_KEI_UCWK_NO`] |
| 20 | SET | `this.svc_kei_ucwk_gadtm = new String[1]` |
| 21 | SET | `this.svc_kei_ucwk_gadtm[0] = retHash.get(GENE_ADD_DTM)` |
| 22 | SET | `this.op_svc_kei_no_fixipad = chbf_opsvkei_no` |
| 23 | SET | `this.op_gadtm_fixipad = chbf_opsvkei_gene_add_dtm` |
| 24 | SET | `this.old_vrsb_jdg_svc_dtl_cd = getOldVrsbIdgSvcDtlCd(handle, param, moto_svc_kei_no, this.svc_kei_ucwk_no[0], motoPplanCd)` |
| 25 | CALL | `param = addSOD(handle, param, ODR_NAIYO_CD_154)` // Fixed Global IP Address cancellation [-> `ODR_NAIYO_CD_154 = "154"`] |
| 26 | CALL | `param = addSOD(handle, param, ODR_NAIYO_CD_104)` // FTTH cancellation [-> `ODR_NAIYO_CD_104 = "104"`] |
| 27 | CALL | `param = addSOD(handle, param, ODR_NAIYO_CD_101)` // FTTH registration [-> `ODR_NAIYO_CD_101 = "101"`] |
| 8 | ELSE | No SOD issued -- pre-change option exists but does not match Fixed Global IP pattern -- "SOD issuance not applicable" |
| **END Block 7** |

**Block 8** — [IF] Post-change data confirmation -- main processing (L17290)

> If the post-change option record exists, updates the work map, checks for sub-option presence, and dispatches SOD issuance based on option service code.
> [CONST: `SVC_KEI_STAT_020 = "020"`, `OP_SVC_CD_EMAIL = "01"` (Email/Chirp), `OP_SVC_CD_HP = "02"` (WEB/Home Page), `OP_SVC_CD_MLIST = "03"` (Mailing List)]

| # | Type | Code |
|---|------|------|
| 1 | IF | `chafEKK0351A010SCHash != null` // Post-change option record exists? |
| 2 | SET | `workMap = (HashMap)param.getData(HAKKOSODCCWORKMAP)` |
| 3 | SET | `workMap.put("svc_kei_no", svc_kei_no)` // Restore prior service contract number (LT-2013-0000487 fix) |
| 4 | SET | `svkeiGaDtm = workMap.get("svkei_gadtm")` |
| 5 | SET | `workMap.put("svkei_gadtm", "")` // Clear for SOD processing |
| 6 | EXEC | `param.setData(HAKKOSODCCWORKMAP, workMap)` |
| 7 | IF | `opHktgiHukusuFlg && isBlank(this.same_trn_no)` → same logic as Block 7.1 -- get same processing number |
| 8 | SET | `opSvcCd = chafEKK0351A010SCHash.get(OP_SVC_CD)` |
| 9 | **Block 8.1** — [IF] No sub-option -- branch by OP_SVC_CD (L17324) |
| | IF | `chafEKK0401A010SCHash == null` // No sub-option present |
| | SET | `sakiOpSvcKeiStat = chafEKK0351A010SCHash.get(OP_SVC_KEI_STAT)` |
| | IF | `SVC_KEI_STAT_020.compareTo(sakiOpSvcKeiStat) <= 0` [-> `SVC_KEI_STAT_020 = "020"` -- post-change option is active/resolved] |
| | **Block 8.1.1** — [IF] `OP_SVC_CD_EMAIL` (L17338) -- Email/Chirp service |
| | | IF | `OP_SVC_CD_EMAIL.equals(opSvcCd)` [-> `OP_SVC_CD_EMAIL = "01"`] |
| | | SET | `chafEKK0361A010SCHash = new HashMap<>()` // ISP agreement hash |
| | | SET | `chafInHashNet = new HashMap<>()` |
| | | SET | `chafResultHashNet = new HashMap<>()` |
| | | SET | `chafInHashNet.put(OP_SVC_KEI_NO, chaf_opsvkei_no)` |
| | | SET | `chafInHashNet.put(GENE_ADD_DTM, chaf_opsvkei_gene_add_dtm)` |
| | | CALL | `statusCode = callEKK0361A010SC(param, handle, chafInHashNet, chafResultHashNet, FUNC_CODE_1)` // ISP agreement |
| | | IF | `0 != statusCode` → throw `CCException` |
| | | SET | `chafEKK0361A010SCHash = chafResultHashNet.get(TEMPLATE_ID_EKK0361A010)` [-> `TEMPLATE_ID_EKK0361A010`] |
| | | SET | `this.op_svc_kei_no_ml = chaf_opsvkei_no` |
| | | SET | `this.op_gadtm_ml = chaf_opsvkei_gene_add_dtm` |
| | | SET | `this.mlad = chafEKK0361A010SCHash.get(MLAD)` [-> `MLAD`] |
| | | CALL | `param = addSOD(handle, param, ODR_NAIYO_CD_120)` // Email/Chirp registration [-> `ODR_NAIYO_CD_120 = "120"`] |
| | | **END Block 8.1.1** |
| | **Block 8.1.2** — [IF] `OP_SVC_CD_HP` (L17356) -- WEB/Home Page service |
| | | IF | `OP_SVC_CD_HP.equals(opSvcCd)` [-> `OP_SVC_CD_HP = "02"`] |
| | | SET | `this.op_svc_kei_no_hp = chaf_opsvkei_no` |
| | | SET | `this.op_gadtm_hp = chaf_opsvkei_gene_add_dtm` |
| | | CALL | `param = addSOD(handle, param, ODR_NAIYO_CD_128)` // WEB restoration [-> `ODR_NAIYO_CD_128 = "128"`] |
| | | **END Block 8.1.2** |
| | **Block 8.1.3** — [IF] `OP_SVC_CD_MLIST` (L17366) -- Mailing List service |
| | | IF | `OP_SVC_CD_MLIST.equals(opSvcCd)` [-> `OP_SVC_CD_MLIST = "03"`] |
| | | SET | `this.op_svc_kei_no_mlist = chaf_opsvkei_no` |
| | | SET | `this.op_gadtm_mlist = chaf_opsvkei_gene_add_dtm` |
| | | CALL | `param = addSOD(handle, param, ODR_NAIYO_CD_133)` // Mailing-list restoration [-> `ODR_NAIYO_CD_133 = "133"`] |
| | | **END Block 8.1.3** |
| | **Block 8.1.4** — [IF] `OP_SVC_CD_FIXIPAD` (L17375) -- Fixed Global IP Address post-change registration |
| | | IF | `OP_SVC_CD_FIXIPAD.equals(opSvcCd)` [-> `OP_SVC_CD_FIXIPAD = "01"`] |
| | | SET | `inHashUcwk = new HashMap<>()` |
| | | SET | `resultHashUcwk = new HashMap<>()` |
| | | SET | `inHashUcwk.put(SVC_KEI_NO, svc_kei_no)` // Set prior service contract number |
| | | SET | `workMap.put("svkei_gadtm", sakiSvkeiGaDtm)` // ANK-4468-00-01 |
| | | CALL | `statusCode = callEKK0161B004SC(param, handle, inHashUcwk, resultHashUcwk, FUNC_CODE_1)` |
| | | IF | `0 != statusCode` → throw `CCException` |
| | | SET | `retHash = takeCurrentSvcKeiUcwk(resultHashUcwk)` |
| | | SET | `this.svc_kei_ucwk_no = new String[1]` |
| | | SET | `this.svc_kei_ucwk_no[0] = retHash.get(SVC_KEI_UCWK_NO)` |
| | | SET | `this.svc_kei_ucwk_gadtm = new String[1]` |
| | | SET | `this.svc_kei_ucwk_gadtm[0] = retHash.get(GENE_ADD_DTM)` |
| | | SET | `this.op_svc_kei_no_fixipad = chaf_opsvkei_no` |
| | | SET | `this.op_gadtm_fixipad = chaf_opsvkei_gene_add_dtm` |
| | | SET | `this.old_vrsb_jdg_svc_dtl_cd = getOldVrsbIdgSvcDtlCd(handle, param, svc_kei_no, this.svc_kei_ucwk_no[0], this.pplan_cd)` |
| | | CALL | `param = addSOD(handle, param, ODR_NAIYO_CD_152)` // Fixed Global IP Address registration [-> `ODR_NAIYO_CD_152 = "152"`] |
| | | **END Block 8.1.4** |
| | **END Block 8.1** -- sub-option absent |
| **Block 8.2** — [ELSE] Sub-option processing (L17420) |
| | Sub-option present -- handles virus protection sub-option scenario. |
| | SET | `workMap = (HashMap)param.getData(HAKKOSODCCWORKMAP)` |
| | SET | `workMap.put("svc_kei_no", svc_kei_no)` |
| | SET | `workMap.put("svkei_gadtm", svkeiGaDtm)` |
| | EXEC | `param.setData(HAKKOSODCCWORKMAP, workMap)` |
| | SET | `sbopSvcCd = chafEKK0401A010SCHash.get(SBOP_SVC_CD)` [-> `SBOP_SVC_CD`] |
| | SET | `sbopSvcKeiStat = chafEKK0401A010SCHash.get(SBOP_SVC_KEI_STAT)` [-> `SBOP_SVC_KEI_STAT`] |
| | **Block 8.2.1** — [IF] Active sub-option (L17430) |
| | IF | `SVC_KEI_STAT_020.compareTo(sbopSvcKeiStat) <= 0` [-> `SVC_KEI_STAT_020 = "020"`] |
| | **Block 8.2.2** — [IF] Virus protection sub-option (L17432) |
| | IF | `SBOP_SVC_CD_VIRUS.equals(sbopSvcCd)` [-> `SBOP_SVC_CD_VIRUS = "D03"`] |
| | SET | `chafInHashNet = new HashMap<>()` |
| | SET | `chafResultHashNet = new HashMap<>()` |
| | SET | `chafInHashNet.put(OP_SVC_KEI_NO, chaf_opsvkei_no)` |
| | SET | `chafInHashNet.put(GENE_ADD_DTM, chaf_opsvkei_gene_add_dtm)` |
| | CALL | `statusCode = callEKK0361A010SC(param, handle, chafInHashNet, chafResultHashNet, FUNC_CODE_1)` |
| | IF | `0 != statusCode` → throw `CCException` |
| | SET | `chafEKK0361A010SCHash = chafResultHashNet.get(TEMPLATE_ID_EKK0361A010)` |
| | SET | `this.op_svc_kei_no_ml = chaf_opsvkei_no` |
| | SET | `this.op_gadtm_ml = chaf_opsvkei_gene_add_dtm` |
| | SET | `this.mlad = chafEKK0361A010SCHash.get(MLAD)` |
| | CALL | `param = addSOD(handle, param, ODR_NAIYO_CD_114)` // Email/Virus registration [-> `ODR_NAIYO_CD_114 = "114"`] |
| | **END Block 8.2.2** |
| | **END Block 8.2.1** |
| | **END Block 8.2** |
| 10 | SET | `workMap = (HashMap)param.getData(HAKKOSODCCWORKMAP)` // Restore workMap |
| 11 | SET | `workMap.put("svc_kei_no", svc_kei_no)` // Restore prior service contract number |
| 12 | SET | `workMap.put("svkei_gadtm", svkeiGaDtm)` // Restore generation timestamp |
| 13 | EXEC | `param.setData(HAKKOSODCCWORKMAP, workMap)` |
| **END Block 8** |

**Block 9** — [RETURN] Return param (L17462)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return param` // Return parameter with accumulated SOD payload |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `opHktgiOdrCtrl` | Field | Option Inheritance Order Control -- Japanese: オプション引継オーダ制御. The method name describing option porting order control processing. |
| SOD | Acronym | Service Order Data -- the core order entity in the telecom billing system, representing a service order record that triggers downstream provisioning operations. |
| `SOD_KIHON_INFO` | Field | SOD basic information map key -- contains fundamental SOD metadata. |
| `SVC_KEI_INFO` | Field | Service contract information map key -- contains the service contract line item data (number, inherited-from number, generation timestamps). `KEI` = 契約 = contract. |
| `OPSVKEI_INFO` | Field | Option service contract information map key -- contains option-level service contract data (pre-change/post-change numbers and timestamps). `OP` = オプション = option. |
| `INFO_SVC_KEI_NO` | Field | Service contract number -- the current/destination line's service contract identifier. |
| `INFO_MOTO_SVC_KEI_NO` | Field | Inherited-from (source) service contract number. `MOTO` = 元 = source/origin. The existing line number from which the customer is porting. |
| `INFO_MOTO_SVKEI_GENE_ADD_DTM` | Field | Inherited-from service contract generation date/time. Used to establish the timeline for the source contract. |
| `INFO_CHBF_OPSVKEI_NO` | Field | Pre-change option service contract number. `CHBF` = 変更前 = before change. |
| `INFO_CHAF_OPSVKEI_NO` | Field | Post-change option service contract number. `CHAF` = 変更後 = after change. |
| `INFO_CHAF_SBOPSVKEI_NO` | Field | Post-change sub-option service contract number. `SBOP` = サブオプション = sub-option (OM-2014-0001956). |
| `OP_SVC_KEI_NO` | Field | Option service contract number -- generic key for option service contract number in input/result maps. |
| `OP_SVC_KEI_STAT` | Field | Option service contract status -- indicates the state of the option (e.g., `020` = resolved, `910` = cancellation pending). |
| `OP_SVC_CD` | Field | Option service code -- classifies the type of option service (Email, WEB, Mailing, Fixed Global IP, etc.). |
| `GENE_ADD_DTM` | Field | Generation date/time -- the timestamp when the contract record was created/registered. |
| `SVC_KEI_NO` | Field | Service contract number -- used as key for service contract queries (EKK0161B004SC). |
| `SVC_KEI_UCWK_NO` | Field | Service contract detail work number -- internal work tracking number for service contract details. |
| `OP_SVC_CD_FIXIPAD` | Field | Fixed Global IP Address option code [-> `"01"`]. Identifies the Fixed Global IP Address service type. |
| `OP_SVC_CD_EMAIL` | Field | Email/Chirp option code [-> `"01"`]. Identifies the Mail (Chirp/メール) service type. |
| `OP_SVC_CD_HP` | Field | WEB/Home Page option code [-> `"02"`]. Identifies the WEB (HP/ホームページ) service type. |
| `OP_SVC_CD_MLIST` | Field | Mailing List option code [-> `"03"`]. Identifies the Mailing List (メルリグ/メーリングリスト) service type. |
| `SBOP_SVC_CD` | Field | Sub-option service code -- identifies the type of sub-option service. |
| `SBOP_SVC_CD_VIRUS` | Field | Virus protection sub-option code [-> `"D03"`]. Identifies the virus protection sub-option service. |
| `SVC_KEI_STAT_020` | Constant | Service contract status `020` = resolved/completed -- meaning the option has been activated. `SVC_KEI_STAT_020.compareTo(val) <= 0` checks if the option is at least in resolved state. |
| `SVC_KEI_STAT_910` | Constant | Service contract status `910` = cancellation processing pending -- used for Fixed Global IP Address cancellation scenarios (LT-2013-0000487). |
| `TRGT_DATA_LIST` | Field | Target data list key -- the list of items being processed in this operation. `TRGT` = 対象 = target. |
| `HAKKOSODCCWORKMAP` | Field | Issuance SOD work map key -- temporary work storage for SOD issuance parameters within the `param` object. |
| `same_trn_no` | Field | Same processing number -- ensures multiple option inheritance operations within a single transaction share a consistent transaction number. |
| `old_vrsb_jdg_svc_dtl_cd` | Field | Old VR identification judgment service detail code -- used for legacy voice recognition system compatibility (ANK-2765-00-00). |
| `pplan_cd` | Field | Plan code -- the pricing/product plan identifier for a service contract. |
| `MLAD` | Field | Mail address -- the actual email address from the ISP agreement record. |
| `OPE_DATE` | Field | Operation date -- the business date used for date-based service component queries. |
| `FUNC_CODE_1` | Constant | Function code `1` -- standard processing mode for service component calls. |
| `FUNC_CODE_2` | Constant | Function code `2` -- date-based processing mode used when generation timestamp is unavailable. |
| `ODR_NAIYO_CD_154` | Constant | Order content code `154` -- Fixed Global IP Address cancellation SOD (固定グローバルIPアドレス解約オーダ). |
| `ODR_NAIYO_CD_104` | Constant | Order content code `104` -- FTTH cancellation SOD (FTTH解約). |
| `ODR_NAIYO_CD_101` | Constant | Order content code `101` -- FTTH registration SOD (FTTH登録). |
| `ODR_NAIYO_CD_152` | Constant | Order content code `152` -- Fixed Global IP Address registration SOD (固定グローバルIPアドレス登録). |
| `ODR_NAIYO_CD_120` | Constant | Order content code `120` -- Email/Chirp (Mail) registration SOD (メール・チープ登録). |
| `ODR_NAIYO_CD_128` | Constant | Order content code `128` -- WEB restoration SOD (WEB・復旧). |
| `ODR_NAIYO_CD_133` | Constant | Order content code `133` -- Mailing-list restoration SOD (メルリグ・復旧). |
| `ODR_NAIYO_CD_114` | Constant | Order content code `114` -- Email/Virus registration SOD (メール・ウイルス登録). |
| FTTH | Business term | Fiber To The Home -- fiber-optic broadband internet service. |
| ISP | Business term | Internet Service Provider -- the internet access service bundled with telecom plans. |
| Chirp (メール) | Business term | Mail/Chirp -- NTT Docomo's email service, referred to as "Chirp" or メール in the system. |
| Virus Protection (ウイルス) | Business term | Virus protection sub-option service -- an antivirus software subscription bundled as an option. |
| EKK0351A010SC | Technical | Option service contract agreement service component -- retrieves option-level service contract agreement data. |
| EKK0361A010SC | Technical | Option service contract <ISP> agreement service component -- retrieves ISP-level option agreement data including mail address. |
| EKK0401A010SC | Technical | Sub-option service contract agreement service component -- retrieves sub-option service contract agreement data (OM-2014-0001956). |
| EKK0161B004SC | Technical | Service contract details list consultation service component -- retrieves detailed service contract information including work tracking numbers. |
| shkkaMap | Method | Map sanitization utility -- cleans/normalizes HashMap data before processing. |
| `chbf` | Abbreviation | 変更前 = "before change" -- prefix for pre-change option data. |
| `chaf` | Abbreviation | 変更後 = "after change" -- prefix for post-change option data. |
| `moto` | Abbreviation | 元 = "source/origin" -- refers to the inherited-from (source) line. |
| `saki` | Abbreviation | 先 = "destination" -- refers to the target line receiving the inherited service. |
| MLAD | Field | Mail address -- the email address field from the ISP agreement record. |
| OM-2014-0001956 | Change ID | Fix for wildcard registration not occurring at inheritance destination when family pack exists. Added sub-option handling. |
| LT-2013-0000487 | Change ID | Fix for incorrect SOD generation during Fixed Global IP inheritance. Corrected `SVC_KEI_STAT` from `100` to `910`, changed `saki_svc_kei_no` to `moto_svc_kei_no`, added generation timestamp handling. |
| ANK-2765-00-00 | Change ID | Added old VR identification judgment service detail code for legacy system compatibility. |
| IT1-2016-0000107 | Change ID | Updated old VR identification to use moto (inherited-from) service contract number and plan code instead of prior service contract number. |
| ANK-4468-00-01 | Change ID | Added `sakiSvkeiGaDtm` work map field for Fixed Global IP post-change registration path. |