# Business Logic — KKA14201SFLogic.actionBtnKaihkChk() [296 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.web.webview.KKA14201SF.KKA14201SFLogic` |
| Layer | Service Component / WebLogic (Web MVC Screen Logic) |
| Module | `KKA14201SF` (Package: `eo.web.webview.KKA14201SF`) |

## 1. Role

### KKA14201SFLogic.actionBtnKaihkChk()

This method implements the **Recovery Button Validation** (回復ボタンチェック — "kaishaku botton check") for the OptService (Operation Service) screen. It serves as a centralized gatekeeper that determines whether a user's request to "recover" (再登録 / re-register) an OptService should be permitted or rejected. The method implements a **multi-layer filtering design**: it first applies exclusion-list checks to immediately block recovery for service types that are permanently non-recoverable, then enforces date-based recovery windows, and finally applies business-rule validation for specific service categories and package dependencies.

The method handles several distinct validation paths: (1) **Exclusion List Filtering** — rejects recovery for services listed in `OPSVCCDS_DONTSENI` (non-transferable services), `OPSVCCDS_DONTKAIHK` (non-recoverable services), and `OPSVCCDS_SENIKKW2525` (seniority-limited services); (2) **Recovery Period Enforcement** — validates that the current operation date does not exceed the operational service end date plus the recovery-permitted period (`kaihk_psb_prd`); (3) **Max Service Count Constraint** — for Fiber-To-Home (FTTH/B075) services, ensures the number of concurrently active services does not exceed the system-configured maximum (`max_op_svc_cnt`), with special handling for LTE pricing plans (BC5); (4) **Future Start Date Package Conflict Check** — verifies that no OptService participating in the same phone satellite package has a future start date, which would create a scheduling conflict. The method returns `true` if all validations pass, or `false` if any rejection condition is triggered (with an appropriate error message set via `JCCWebCommon.setMessageInfo`).

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["actionBtnKaihkChk params"])
    START --> INIT["ret = true"]
    INIT --> LOOP1["Loop OPSVCCDS_DONTSENI"]
    LOOP1 --> CHECK1["Check op_svc_cd in DONTSENI"]
    CHECK1 --> MSG_BLOCK1["setMessageInfo EKB5420-JW, ret = false"]
    CHECK1 --> LOOP2["Loop OPSVCCDS_DONTKAIHK"]
    MSG_BLOCK1 --> LOOP2
    LOOP2 --> CHECK2["Check op_svc_cd in DONTKAIHK"]
    CHECK2 --> MSG_BLOCK2["setMessageInfo EKB5420-JW, ret = false"]
    CHECK2 --> CHECK3["Check OPSVCCDS_SENIKKW2525 != null"]
    MSG_BLOCK2 --> CHECK3
    CHECK3 --> LOOP3["Loop OPSVCCDS_SENIKKW2525"]
    LOOP3 --> CHECK3A["Check op_svc_cd in SENIKKW2525"]
    CHECK3A --> MSG_BLOCK3["setMessageInfo EKB5420-JW, ret = false"]
    CHECK3A --> LOOP3
    MSG_BLOCK3 --> GET_DATE["getOpeDate unyo_ymd"]
    CHECK3 --> GET_DATE
    GET_DATE --> SET_CAL["setCalendar op_svc_end_ymd"]
    SET_CAL --> CHECK_PRD["kaihk_psb_prd valid?"]
    CHECK_PRD --> ADD_DATE["cal_op_svc_end_ymd.add kaihk_psb_prd"]
    ADD_DATE --> COMPARE_DATES
    CHECK_PRD --> COMPARE_DATES
    COMPARE_DATES["unyo_ymd > kaihkEndYmd?"] --> COMPARE_YES["setMessageInfo EKB1530-JW, ret = false"]
    COMPARE_YES --> CHECK_FMTCEL
    COMPARE_DATES --> CHECK_FMTCEL
    CHECK_FMTCEL["op_svc_cd == B075?"] --> CHECK_LIST["op_svc_kei_list != null?"]
    CHECK_FMTCEL --> CHECK_PACK
    CHECK_LIST --> COUNT_LOOP["Count FMTCEL ops in service list"]
    COUNT_LOOP --> COUNT_SUB["pcrsCd == BC5?"]
    COUNT_SUB --> LTE_INC["opSvcCdFmtcelLTECnt++"]
    COUNT_SUB --> REG_INC["opSvcCdFmtcelCnt++"]
    LTE_INC --> COUNT_LOOP
    REG_INC --> CHECK_MAX
    CHECK_LIST --> CHECK_PACK
    CHECK_MAX["max_op_svc_cnt set?"] --> LTE_CHECK["op_pcrs_cd == BC5?"]
    LTE_CHECK --> LTE_BLOCK["opSvcCdFmtcelLTECnt >= 1?"]
    LTE_BLOCK --> MSG_LTE["setMessageInfo FMTCEL LTE EKB5420-JW"]
    LTE_BLOCK --> FMTCEL_CHECK["opSvcCdFmtcelCnt+1 > max?"]
    FMTCEL_CHECK --> MSG_F["setMessageInfo FMTCEL EKB5420-JW"]
    MSG_LTE --> CHECK_PACK
    MSG_F --> CHECK_PACK
    LTE_CHECK --> FMTCEL_CHECK
    CHECK_PACK["both lists not null?"] --> INIT_FLG["pack_mirai_msg_flg = false"]
    CHECK_PACK --> RETURN_RET["return ret"]
    INIT_FLG --> CHECK_PACK_STAT["packStat valid?"]
    CHECK_PACK_STAT --> CHECK_USE_DT["packUseStaYmd > unyo_ymd?"]
    CHECK_USE_DT --> SET_FLG1["pack_mirai_msg_flg = true"]
    CHECK_USE_DT --> OUTSIDE_LOOP["Loop op_pack_kousei_list"]
    SET_FLG1 --> OUTSIDE_LOOP
    OUTSIDE_LOOP --> CHECK_PLAN["op_pplan_cd match?"]
    CHECK_PLAN --> CHECK_STA["op_svc_sta_dtm > unyo_ymd?"]
    CHECK_STA --> SET_FLG2["pack_mirai_msg_flg = true, break"]
    CHECK_STA --> OUTSIDE_LOOP
    CHECK_PLAN --> OUTSIDE_LOOP
    OUTSIDE_LOOP --> INNER_LOOP["Loop op_svc_kei_list x op_pack_kousei_list"]
    INNER_LOOP --> CHECK_INNER["opSvcKeiState != 910 920 and startDt > unyo_ymd?"]
    CHECK_INNER --> SET_FLG3["pack_mirai_msg_flg = true, break"]
    CHECK_INNER --> INNER_LOOP
    SET_FLG3 --> CHECK_MSG_FLG["pack_mirai_msg_flg == true?"]
    SET_FLG2 --> CHECK_MSG_FLG
    SET_FLG1 --> CHECK_MSG_FLG
    CHECK_MSG_FLG --> BREAK["break outer"]
    CHECK_MSG_FLG --> CHECK_FINAL["pack_mirai_msg_flg?"]
    BREAK --> CHECK_FINAL
    CHECK_FINAL --> MSG_FINAL["setMessageInfo EKBE130-KW"]
    CHECK_FINAL --> RETURN_RET
    MSG_FINAL --> END_NODE(["END"])
```

**Key Constants Resolved:**

| Constant | Value | Business Meaning |
|----------|-------|-----------------|
| `OPSVCCDS_DONTSENI` | `["B006","B007","B008","B009","B017","B019","B030","B031"]` | Non-transferable OptService codes — these services cannot be moved or re-registered at all |
| `OPSVCCDS_DONTKAIHK` | `["B068","B069","B077","B130","B131","B132","B138"]` | Non-recoverable OptService codes — these services cannot be re-registered after cancellation |
| `OP_SVC_CD_VALUE_FMTCEL` | `"B075"` | Fiber To The Home (FTTH) / "Fumuchaseru" service code |
| `SVC_KEI_STAT_100` | `"100"` | Active service status — service is currently being provided |
| `CD00134_BC5` | `"BC5"` | BC5 pricing code — indicates "Fumuchaseru (LTE)" pricing plan |

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `op_svc_cd` | `String` | OptService code — the service type identifier for the OptService the user is attempting to recover. Used for exclusion list lookups and conditional routing (e.g., B075 triggers FTTH max-count validation). |
| 2 | `OPSVCCDS_SENIKKW2525` | `String[]` | Seniority-restricted OptService codes array — service codes that are restricted based on user seniority/tenure. Recovery is blocked if `op_svc_cd` matches any element. May be null. |
| 3 | `op_svc_end_ymd` | `String` | OptService end date (yyyyMMdd format) — the date when the OptService contract officially terminates. Used as the base for calculating the recovery-permitted deadline. |
| 4 | `kaihk_psb_prd` | `String` | Recovery permitted period (days) — number of days after service end date during which recovery is still possible. Added to `op_svc_end_ymd` to compute the recovery deadline. |
| 5 | `op_svc_kei_list` | `X31SDataBeanAccessArray` | OptService detail list — array of all OptService detail line items for the customer. Used to count currently active FTTH services and validate against the maximum concurrent service limit. |
| 6 | `max_op_svc_cnt` | `String` | Maximum OptService count — the maximum number of concurrent active FTTH services a customer is allowed to have. If exceeded, recovery is blocked. |
| 7 | `op_svc_sta_dtm` | `String` | OptService start date/time — the date when the selected OptService begins operation. Used in future date validation for package conflict checks. Added in IT1-2014-0000122. |
| 8 | `op_pack_kousei_list` | `X31SDataBeanAccessArray` | Package composition list — array of OptServices that make up a phone satellite package. Used to check if any package member has a future start date that would conflict with recovery. Added in IT1-2014-0000122. |
| 9 | `op_pplan_cd` | `String` | OptService pricing plan code — the pricing plan associated with the selected OptService. Used to match against package composition to identify related services. Added in IT1-2014-0000122. |
| 10 | `op_pcrs_cd` | `String` | Pricing course code — identifies the pricing plan type (e.g., "BC5" = FTTH/LTE). Used to determine which max-count validation path to follow. Added in ANK-2184-00-00. |
| 11 | `packUseStaYmd` | `String` | Package usage start date (yyyyMMdd) — the date when the satellite package starts being used. Used to check if the package start date is in the future. Added in IT1-2014-0000155. |
| 12 | `packStat` | `String` | Package status — the current status of the satellite package. Values "910" (cancelled) and "920" (rescinded) mean no package validation is needed. Added in IT1-2014-0000155. |

**Instance/External State Read:**
- `OPSVCCDS_DONTSENI` — static field, non-transferable service codes array (8 codes)
- `OPSVCCDS_DONTKAIHK` — static field, non-recoverable service codes array (7 codes)
- `this` — the `KKA14201SFLogic` instance, passed to `JCCWebCommon.setMessageInfo` and `JCCWebCommon.getOpeDate`

## 4. CRUD Operations / Called Services

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `JCCWebCommon.getOpeDate(this, null)` | JCCWebCommon | - | Retrieves the current operational date (unyo_ymd) from the system. Shared utility for date acquisition. |
| - | `JCCWebCommon.setMessageInfo(this, "EKB5420-JW", str)` | JCCWebCommon | - | Sets a web error message for the "OptService / Recovery" rejection scenario. Non-CRUD UI feedback. |
| - | `JCCWebCommon.setMessageInfo(this, "EKB1530-JW")` | JCCWebCommon | - | Sets a web error message indicating the recovery deadline has passed. Non-CRUD UI feedback. |
| - | `JCCWebCommon.setMessageInfo(this, JPCOnlineMessageConstant.EKBE130_KW)` | JCCWebCommon | - | Sets a web error message (EKBE130-KW) indicating a future start date conflict with package services. Non-CRUD UI feedback. |
| R | `KKA14201SFLogic.setCalendar(unyo_ymd)` | KKA14201SFLogic | - | Converts a yyyyMMdd string into a Calendar object for date comparison. Internal utility. |
| R | `KKA14201SFLogic.setCalendar(op_svc_end_ymd)` | KKA14201SFLogic | - | Converts the OptService end date string into a Calendar object for recovery deadline calculation. |
| R | `op_svc_kei_list.getCount()` | OneStopDataBeanAccessArray | - | Returns the count of OptService detail items in the list. |
| R | `op_svc_kei_list.getDataBean(cnt)` | OneStopDataBeanAccessArray | - | Retrieves a specific OptService detail data bean by index from the service list. |
| R | `op_pack_kousei_list.getCount()` | OneStopDataBeanAccessArray | - | Returns the count of package composition items. |
| R | `op_pack_kousei_list.getDataBean(i)` | OneStopDataBeanAccessArray | - | Retrieves a specific package composition data bean by index. |
| - | `dataBean.sendMessageString(KEY, X31CWebConst.DATABEAN_GET_VALUE)` | X31SDataBeanAccess | - | Extracts a string value from a data bean by key. Used to retrieve opSvcCd, opSvcKeiState, pcrsCd, kouseiOpPPlanCd, opPPlanCd, list_op_svc_sta_dtm. |

**Classification Notes:**
- No direct Create/Update/Delete (C/U/D) operations against database tables are performed in this method.
- This method is a **pure Read/Validation method** (R-only) — it reads service list data beans and performs business rule validation against in-memory data and system state.
- All `sendMessageString` calls on data beans are data extraction operations (Read).
- `JCCWebCommon.getOpeDate` is a utility Read for the current operational date.
- `setCalendar` is an internal utility method within `KKA14201SFLogic`.

## 5. Dependency Trace

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | CBS:KKW02301SFLogic | `setSessionData(actionBtn)` -> `if ACTION_BTN_KAIHK` -> `actionBtnKaihkChk(op_svc_cd, OPSVCCDS_SENIKKW2525, op_svc_end_ymd, kaihk_psb_prd, op_svc_kei_list, max_op_svc_cnt, op_svc_sta_dtm, op_pack_kousei_list, op_pplan_cd, op_pcrs_cd, packUseStaYmd, packStat)` | `no CRUD` — pure validation, returns boolean |
| 2 | Screen:KKA14201SF | `actionBtn` handling -> commented out legacy call (21 params, pre-IT1-2014-0000122) | N/A — code is commented out |
| 3 | Screen:KKA14201SF | `actionBtn` handling -> commented out call (11 params, pre-ANK-2184) | N/A — code is commented out |
| 4 | Screen:KKA14201SF | `actionBtn` handling -> commented out call (12 params, pre-full signature) | N/A — code is commented out |
| 5 | Screen:KKA14401SF | `actionBtn` handling -> commented out legacy call | N/A — code is commented out |
| 6 | Screen:KKA14701SF | `actionBtn` handling -> commented out legacy call | N/A — code is commented out |
| 7 | Screen:KKA14901SF | `actionBtn` handling -> commented out legacy call | N/A — code is commented out |

**Notes:** The only **active caller** is `KKW02301SFLogic.setSessionData()` which invokes this method when the user presses the Recovery (再登録) button. All calls in KKA14201SF, KKA14401SF, KKA14701SF, and KKA14901SF are commented out (progressively commented through IT1-2014-0000122 and IT1-2014-0000155 migrations). The method signature evolved from 9 params to 12 params across these releases.

## 6. Per-Branch Detail Blocks

**Block 1** — [WHILE LOOP] `for(int i = 0; i < OPSVCCDS_DONTSENI.length; i++)` (L3355)

> Iterates through the non-transferable service codes list. If the current `op_svc_cd` matches any entry, recovery is blocked immediately.
> Constant: `OPSVCCDS_DONTSENI = ["B006","B007","B008","B009","B017","B019","B030","B031"]`

| # | Type | Code |
|---|------|------|
| 1 | SET | `ret = true;` // initial default: recovery permitted [L3354] |
| 2 | EXEC | `for(int i = 0; i < OPSVCCDS_DONTSENI.length; i++)` // iterate exclusion list [L3355] |
| 3 | IF | `if(OPSVCCDS_DONTSENI[i].equals(op_svc_cd))` // match found [L3358] |
| 3.1 | SET | `String[] str = {"OptService", "Recovery"};` // message parameters [L3360] |
| 3.2 | EXEC | `JCCWebCommon.setMessageInfo(this, "EKB5420-JW", str);` // set rejection error message [L3361] |
| 3.3 | SET | `ret = false;` // reject recovery [L3362] |
| 3.4 | [implicit] | Loop continues to next element (no break — checks all, though first match suffices) [L3357] |

**Block 2** — [WHILE LOOP] `for(int i = 0; i < OPSVCCDS_DONTKAIHK.length; i++)` (L3370)

> Iterates through the non-recoverable service codes list. Same pattern as Block 1.
> Constant: `OPSVCCDS_DONTKAIHK = ["B068","B069","B077","B130","B131","B132","B138"]`

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `for(int i = 0; i < OPSVCCDS_DONTKAIHK.length; i++)` // iterate non-recoverable list [L3370] |
| 2 | IF | `if(OPSVCCDS_DONTKAIHK[i].equals(op_svc_cd))` // match found [L3373] |
| 2.1 | SET | `String[] str = {"OptService", "Recovery"};` [L3375] |
| 2.2 | EXEC | `JCCWebCommon.setMessageInfo(this, "EKB5420-JW", str);` [L3376] |
| 2.3 | SET | `ret = false;` [L3377] |

**Block 3** — [IF + WHILE LOOP] `OPSVCCDS_SENIKKW2525` null check + loop (L3382)

> Seniority-based restriction list. Only processed if `OPSVCCDS_SENIKKW2525` is non-null.
> This array is a parameter, not a class constant, and is populated by the caller.

| # | Type | Code |
|---|------|------|
| 1 | IF | `if(OPSVCCDS_SENIKKW2525 != null)` [L3382] |
| 1.1 | EXEC | `for(int i = 0; i < OPSVCCDS_SENIKKW2525.length; i++)` [L3383] |
| 1.1.1 | IF | `if(OPSVCCDS_SENIKKW2525[i].equals(op_svc_cd))` [L3386] |
| 1.1.1.1 | SET | `String[] str = {"OptService", "Recovery"};` [L3388] |
| 1.1.1.2 | EXEC | `JCCWebCommon.setMessageInfo(this, "EKB5420-JW", str);` [L3389] |
| 1.1.1.3 | SET | `ret = false;` [L3390] |

**Block 4** — [DATE ACQUISITION] Operational date and end date parsing (L3398)

> Retrieves the current operational date and parses the OptService end date into Calendar objects for comparison.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `String unyo_ymd = JCCWebCommon.getOpeDate(this, null);` // current operational date [L3398] |
| 2 | CALL | `Calendar cal_op_svc_end_ymd = setCalendar(op_svc_end_ymd);` // parse end date [L3404] |

**Block 5** — [IF] Recovery period calculation (L3407)

> If a recovery period (`kaihk_psb_prd`) is specified, adds it to the end date to compute the recovery deadline.
> Note: OM-2014-0001744 changed from `kaihk_psb_prd - 1` to `kaihk_psb_prd` (inclusive of the period day).

| # | Type | Code |
|---|------|------|
| 1 | IF | `if(kaihk_psb_prd != null && !"".equals(kaihk_psb_prd))` [L3407] |
| 1.1 | EXEC | `cal_op_svc_end_ymd.add(Calendar.DATE, Integer.parseInt(kaihk_psb_prd));` // add period days [L3412] |
| 1.1.1 | [commented] | `cal_op_svc_end_ymd.add(Calendar.DATE, Integer.parseInt(kaihk_psb_prd) - 1);` // old logic (OM-2014-0001744) [L3410] |

**Block 6** — [IF] Recovery deadline date comparison (L3417)

> Compares the operational date against the computed recovery deadline. If today is past the deadline, recovery is blocked.
> Modified by OM-2014-0001744: changed from Calendar.compareTo to string-based yyyyMMdd comparison for year/month/day only.

| # | Type | Code |
|---|------|------|
| 1 | SET | `String kaihkEndYmd = (new SimpleDateFormat("yyyyMMdd")).format(cal_op_svc_end_ymd.getTime());` [L3418] |
| 2 | IF | `if(unyo_ymd.compareTo(kaihkEndYmd) > 0)` [L3419] // operational date exceeds deadline [L3419] |
| 2.1 | EXEC | `JCCWebCommon.setMessageInfo(this, "EKB1530-JW");` // "Recovery period has expired" message [L3420] |
| 2.2 | SET | `ret = false;` [L3421] |
| 2.2.1 | [commented] | `if(cal_unyo_ymd.compareTo(cal_op_svc_end_ymd) > 0)` // old Calendar comparison [L3417] |

**Block 7** — [IF] FTTH service max-count validation (L3427)

> If the service code is `B075` (FTTH), validates the number of concurrently active FTTH services against the maximum allowed count.

| # | Type | Code |
|---|------|------|
| 1 | IF | `if(JKKCommonConst.OP_SVC_CD_VALUE_FMTCEL.equals(op_svc_cd))` // op_svc_cd == "B075" [L3427] |
| 1.1 | IF | `if(op_svc_kei_list != null)` [L3428] |
| 1.1.1 | SET | `int opSvcCdFmtcelCnt = 0;` // FTTH active count [L3431] |
| 1.1.2 | SET | `int opSvcCdFmtcelLTECnt = 0;` // FTTH/LTE active count [L3433] |
| 1.1.3 | EXEC | `for(int cnt = 0; cnt < op_svc_kei_list.getCount(); cnt++)` // iterate service list [L3435] |
| 1.1.3.1 | SET | `X31SDataBeanAccess svcKeiInfo = op_svc_kei_list.getDataBean(cnt);` [L3436] |
| 1.1.3.2 | SET | `String opSvcCd = svcKeiInfo.sendMessageString(KKW02301SFConst.OP_SVC_CD_01, X31CWebConst.DATABEAN_GET_VALUE);` [L3438] |
| 1.1.3.3 | SET | `String opSvcKeiState = svcKeiInfo.sendMessageString(KKW02301SFConst.OP_SVC_KEI_STAT_01, X31CWebConst.DATABEAN_GET_VALUE);` [L3440] |
| 1.1.3.4 | SET | `String pcrsCd = svcKeiInfo.sendMessageString(KKW02301SFConst.PCRS_CD_01, X31CWebConst.DATABEAN_GET_VALUE);` [L3442] |
| 1.1.3.5 | IF | `if(JKKCommonConst.OP_SVC_CD_VALUE_FMTCEL.equals(opSvcCd) && JKKCommonConst.SVC_KEI_STAT_100.equals(opSvcKeiState))` // opSvcCd=="B075" AND opSvcKeiState=="100" (active) [L3445] |
| 1.1.3.5.1 | IF | `if(JKKStrConst.CD00134_BC5.equals(pcrsCd))` // pcrsCd == "BC5" (LTE pricing) [L3450] |
| 1.1.3.5.1.1 | SET | `opSvcCdFmtcelLTECnt++;` // increment LTE counter [L3451] |
| 1.1.3.5.2 | ELSE | (default branch) |
| 1.1.3.5.2.1 | SET | `opSvcCdFmtcelCnt++;` // increment regular FTTH counter [L3454] |

**Block 8** — [IF] Max service count enforcement (L3460)

> After counting active FTTH services, checks if the count exceeds the system maximum. Has two sub-branches: LTE (BC5) and non-LTE.

| # | Type | Code |
|---|------|------|
| 1 | IF | `if(! (max_op_svc_cnt == null || "".equals(max_op_svc_cnt)))` // max count is configured [L3460] |
| 1.1 | IF (LTE branch) | `if(JKKStrConst.CD00134_BC5.equals(op_pcrs_cd))` // op_pcrs_cd == "BC5" (LTE) [L3464] |
| 1.1.1 | IF | `if(opSvcCdFmtcelLTECnt >= 1)` // already has 1+ LTE FTTH [L3466] |
| 1.1.1.1 | SET | `String[] str = {"Fumuchaseru", "Recovery"};` [L3467] |
| 1.1.1.2 | EXEC | `JCCWebCommon.setMessageInfo(this, "EKB5420-JW", str);` [L3468] |
| 1.1.1.3 | SET | `ret = false;` [L3469] |
| 1.2 | IF (non-LTE branch) | `if(opSvcCdFmtcelCnt + 1 > Integer.parseInt(max_op_svc_cnt))` // current count + 1 exceeds max [L3473] |
| 1.2.1 | SET | `String[] str = {"Fumuchaseru", "Recovery"};` [L3474] |
| 1.2.2 | EXEC | `JCCWebCommon.setMessageInfo(this, "EKB5420-JW", str);` [L3475] |
| 1.2.3 | SET | `ret = false;` [L3476] |

**Block 9** — [IF] Future package date check — satellite package loop (L3487)

> Validates that no OptService in the same phone satellite package has a future start date. This checks the selected service's own start date first.

| # | Type | Code |
|---|------|------|
| 1 | IF | `if(op_svc_kei_list != null && op_pack_kousei_list != null)` // both lists present [L3487] |
| 1.1 | SET | `boolean pack_mirai_msg_flg = false;` // message display flag [L3490] |
| 1.2 | IF | `if(packStat != null && !"".equals(packStat) && !packStat.equals("910") && !packStat.equals("920"))` // package is not cancelled/rescinded [L3494] |
| 1.2.1 | IF | `if(packUseStaYmd != null && !"".equals(packUseStaYmd))` [L3496] |
| 1.2.1.1 | IF | `if(packUseStaYmd.compareTo(unyo_ymd) > 0)` // package start date is in the future [L3498] |
| 1.2.1.1.1 | SET | `pack_mirai_msg_flg = true;` [L3500] |
| 1.3 | EXEC | `outside: for(int i = 0; i < op_pack_kousei_list.getCount(); i++)` // satellite package loop with label [L3506] |
| 1.3.1 | SET | `X31SDataBeanAccess opPackKouseiInfo = op_pack_kousei_list.getDataBean(i);` [L3507] |
| 1.3.2 | SET | `String kouseiOpPPlanCd = opPackKouseiInfo.sendMessageString(KKW02301SFConst.PPLAN_CD14, X31CWebConst.DATABEAN_GET_VALUE);` [L3509] |
| 1.3.3 | IF | `if(kouseiOpPPlanCd.equals(op_pplan_cd))` // package service shares the same pricing plan [L3513] |
| 1.3.3.1 | IF | `if(op_svc_sta_dtm.compareTo(unyo_ymd) > 0)` // service start date is in the future [L3515] |
| 1.3.3.1.1 | SET | `pack_mirai_msg_flg = true;` [L3517] |
| 1.3.3.1.2 | EXEC | `break outside;` // exit package loop early [L3518] |

**Block 10** — [FOR] Inner loop — other OptServices in package check (L3547)

> Checks all OptService detail entries against the package composition to detect if any other service in the same package has a future start date (while actively being provided).

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `for(int cnt = 0; cnt < op_svc_kei_list.getCount(); cnt++)` // outer: iterate service list [L3547] |
| 1.1 | SET | `X31SDataBeanAccess svcKeiInfo = op_svc_kei_list.getDataBean(cnt);` [L3548] |
| 1.2 | SET | `String opPPlanCd = svcKeiInfo.sendMessageString(KKW02301SFConst.PPLAN_CD_01, X31CWebConst.DATABEAN_GET_VALUE);` [L3550] |
| 1.3 | SET | `String opSvcKeiState = svcKeiInfo.sendMessageString(KKW02301SFConst.OP_SVC_KEI_STAT_01, X31CWebConst.DATABEAN_GET_VALUE);` [L3552] |
| 1.4 | SET | `String list_op_svc_sta_dtm = svcKeiInfo.sendMessageString(KKW02301SFConst.SVC_STA_DTM_01, X31CWebConst.DATABEAN_GET_VALUE);` [L3554] |
| 1.5 | EXEC | `for(int j = 0; j < op_pack_kousei_list.getCount(); j++)` // inner: iterate package composition [L3555] |
| 1.5.1 | SET | `X31SDataBeanAccess opPackKouseiInfo1 = op_pack_kousei_list.getDataBean(j);` [L3556] |
| 1.5.2 | SET | `String kouseiOpPPlanCd1 = opPackKouseiInfo1.sendMessageString(KKW02301SFConst.PPLAN_CD14, X31CWebConst.DATABEAN_GET_VALUE);` [L3558] |
| 1.5.3 | IF | `if(kouseiOpPPlanCd1.equals(opPPlanCd))` // matches a package composition entry [L3560] |
| 1.5.3.1 | IF | `if(!opSvcKeiState.equals("910") && !opSvcKeiState.equals("920") && list_op_svc_sta_dtm.compareTo(unyo_ymd) > 0)` // not cancelled/rescinded AND start date in future [L3563] |
| 1.5.3.1.1 | SET | `pack_mirai_msg_flg = true;` [L3566] |
| 1.5.3.1.2 | EXEC | `break;` // break inner loop [L3567] |
| 1.6 | IF | `if(pack_mirai_msg_flg == true)` // early exit flag [L3571] |
| 1.6.1 | EXEC | `break;` // break outer loop [L3572] |

**Block 11** — [IF] Future date conflict message display (L3575)

> If any future-start-date conflict was detected, display the appropriate error message.

| # | Type | Code |
|---|------|------|
| 1 | IF | `if(pack_mirai_msg_flg)` [L3575] |
| 1.1 | EXEC | `JCCWebCommon.setMessageInfo(this, JPCOnlineMessageConstant.EKBE130_KW);` // EKBE130-KW: "This OptService has a future start date and cannot be recovered" [L3576] |

**Block 12** — [RETURN] Return validation result (L3580)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return ret;` // true = recovery permitted, false = recovery rejected |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `op_svc_cd` | Field | OptService code — the unique service type identifier for an OptService (e.g., B075 = FTTH, B068 = Mail) |
| `OPSVCCDS_DONTSENI` | Constant | Non-transferable service codes — services that cannot be moved to another customer or account |
| `OPSVCCDS_DONTKAIHK` | Constant | Non-recoverable service codes — services that cannot be re-registered after cancellation. Includes: B068, B069, B077, B130, B131, B132, B138 |
| `OPSVCCDS_SENIKKW2525` | Field | Seniority-restricted OptService codes array — services restricted by customer tenure/eligibility |
| `op_svc_end_ymd` | Field | OptService end date (yyyyMMdd) — the date when the service contract ends |
| `kaihk_psb_prd` | Field | Recovery permitted period (days) — number of days after service end during which re-registration is allowed |
| `unyo_ymd` | Field | Operational date (yyyyMMdd) — the current system date used as reference for all date comparisons |
| `kaihkEndYmd` | Field | Recovery end date (yyyyMMdd) — computed as end date + recovery permitted period |
| `op_svc_kei_list` | Field | OptService detail list — all service line items associated with the customer for the current session |
| `opSvcCd` | Field | Extracted OptService code from a service detail data bean |
| `opSvcKeiState` | Field | Service contract status — "100" = active service provided, "910" = cancelled, "920" = rescinded |
| `max_op_svc_cnt` | Field | Maximum OptService count — system-configured limit for concurrent active FTTH services per customer |
| `opSvcCdFmtcelCnt` | Variable | Count of active FTTH services (non-LTE pricing) in the current service list |
| `opSvcCdFmtcelLTECnt` | Variable | Count of active FTTH services with LTE pricing (BC5) in the current service list |
| `op_pack_kousei_list` | Field | Package composition list — OptServices that comprise a phone satellite package |
| `op_pplan_cd` | Field | OptService pricing plan code — pricing plan associated with the selected service |
| `op_pcrs_cd` | Field | Pricing course code — identifies the pricing tier (BC5 = FTTH/LTE pricing) |
| `kouseiOpPPlanCd` | Field | Pricing plan code of a package composition member |
| `packUseStaYmd` | Field | Package usage start date (yyyyMMdd) — when the satellite package begins service |
| `packStat` | Field | Package status — "910" = cancelled, "920" = rescinded, other = active |
| `pack_mirai_msg_flg` | Variable | Future date message flag — indicates a future-start-date conflict was detected |
| `B075` | Code | FTTH (Fiber To The Home) / "Fumuchaseru" service code |
| `BC5` | Code | LTE pricing code — indicates the service uses LTE-based FTTH pricing |
| `EKB5420-JW` | Message Key | "Recovery is not possible for this service" error message (Japanese) |
| `EKB1530-JW` | Message Key | "Recovery period has expired" error message (Japanese) |
| `EKBE130-KW` | Message Key | "Future start date conflict with package services" error message (Japanese) |
| `SVC_KEI_STAT_100` | Constant | Active service status code — service is currently being provided |
| `setCalendar` | Method | Internal utility that converts yyyyMMdd string to Java Calendar object |
| `getOpeDate` | Method | JCCWebCommon utility that returns the current operational date |
| `setMessageInfo` | Method | JCCWebCommon utility that sets a web screen error/success message |
| FTTH | Business term | Fiber To The Home — fiber-optic broadband internet service (service code B075) |
| 回復 (Kaishaku) | Japanese term | Recovery / Re-registration — the process of re-registering a previously cancelled OptService |
| オプション (Opushon) | Japanese term | OptService — optional telecom value-added service attached to a base contract |
| 解約 (Kaiya) | Japanese term | Cancellation — service contract termination (status "910") |
| 解除 (Kaijo) | Japanese term | Rescission — contract rescinded (status "920") |
| サテライトパッケット (Satelite Pakket) | Japanese term | Satellite package — a bundled group of services (typically phone-related services grouped together) |