---
title: "Business Logic — KKA14901SFLogic.actionBtnKaihkChk()"
created: "2026-06-29"
updated: "2026-06-29"
---

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

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.web.webview.KKA14901SF.KKA14901SFLogic` |
| Layer | Service Component / Web Logic (Controller-adjacent logic layer within the web module) |
| Module | `KKA14901SF` (Package: `eo.web.webview.KKA14901SF`) |

## 1. Role

### KKA14901SFLogic.actionBtnKaihkChk()

This method implements the **recovery button check** (回復ボタンチェック) — a gatekeeper validation that determines whether a user is permitted to press the "Recovery" button on the option service list screen. The Recovery operation allows customers to undo a previously registered option service contract. The method evaluates five distinct categories of restrictions before permitting recovery.

First, it performs a **blacklist check** against three arrays of operation service codes that are permanently excluded from recovery: `OPSVCCDS_DONTSENI` (services that cannot be transferred at all), `OPSVCCDS_DONTKAIHK` (services that are permanently non-recoverable — e.g., Credit registration B068, Credit card change B069, and various bundled services), and the caller-supplied `OPSVCCDS_SENIKKW2525` array (services excluded during the specific SENIKKW2525 phase).

Second, it validates the **recovery time window** by comparing the current operational date (`unyo_ymd`) against the service end date (`op_svc_end_ymd`) plus the allowed recovery period (`kaihk_psb_prd`). If the operational date has passed this calculated deadline, recovery is denied with message `EKB1530-JW`.

Third, when the service type is **Format Cell** (`B075`), it performs a **concurrent service count check**. It iterates through the list of option services to count how many Format Cell services are currently in active provision status (100), and enforces the maximum allowed number (`max_op_svc_cnt`). A special case handles Format Cell LTE (billing code `BC5`), which is capped at exactly one instance.

Fourth, it runs a **future service start date check** across option services and telecommunication package configurations. It detects whether any option service that composes part of a phone telecom package has a start date in the future relative to the operational date. This prevents users from recovering while future-dated package options are pending, as doing so would create a data inconsistency between active and scheduled services.

The method delegates error messaging to `JCCWebCommon.setMessageInfo()` and date retrieval to `JCCWebCommon.getOpeDate()`, and uses its own `setCalendar()` helper. It contains **no database or SC/CRUD operations** — it is a pure in-memory business rule evaluator.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["Start: actionBtnKaihkChk"])

    START --> DONT_SENI["Check each OPSVCCDS_DONTSENI code"]
    DONT_SENI --> DONT_SENI_Match{"op_svc_cd matches any code in
OPSVCCDS_DONTSENI
(B006,B007,B008,B009,B017,B019,B030,B031)?"}
    DONT_SENI_Match -->|Yes| DONT_SENI_SetMsg["Set error: EKB5420-JW
Arguments: Operation, Recovery"]
    DONT_SENI_SetMsg --> DONT_SENI_RET["ret = false"]
    DONT_SENI_Match -->|No| DONT_KAIHK["Check each OPSVCCDS_DONTKAIHK code"]
    DONT_SENI_RET --> DONT_KAIHK

    DONT_KAIHK --> DONT_KAIHK_Match{"op_svc_cd matches any code in
OPSVCCDS_DONTKAIHK
(B068,B069,B077,B130,B131,B132,B138)?"}
    DONT_KAIHK_Match -->|Yes| DONT_KAIHK_SetMsg["Set error: EKB5420-JW
Arguments: Operation, Recovery"]
    DONT_KAIHK_SetMsg --> DONT_KAIHK_RET["ret = false"]
    DONT_KAIHK_Match -->|No| SENIKKW_CHECK["Check SENIKKW2525 array (if not null)"]
    DONT_KAIHK_RET --> SENIKKW_CHECK

    SENIKKW_CHECK --> SENIKKW_Match{"op_svc_cd matches any code
in OPSVCCDS_SENIKKW2525?"}
    SENIKKW_Match -->|Yes| SENIKKW_SetMsg["Set error: EKB5420-JW
Arguments: Operation, Recovery"]
    SENIKKW_SetMsg --> SENIKKW_RET["ret = false"]
    SENIKKW_Match -->|No| GET_OPE_DATE["Get operational date
unyo_ymd = JCCWebCommon.getOpeDate()"]
    SENIKKW_RET --> GET_OPE_DATE

    GET_OPE_DATE --> SET_CAL["Set calendar
cal_op_svc_end_ymd = setCalendar(op_svc_end_ymd)"]
    SET_CAL --> KAIHK_PRD_NULL{"kaihk_psb_prd != null
and not empty?"}
    KAIHK_PRD_NULL -->|Yes| ADD_PRD["Add kaihk_psb_prd days
to cal_op_svc_end_ymd"]
    ADD_PRD --> KAIHK_END_FMT["Format end date
kaihkEndYmd = yyyyMMdd"]
    KAIHK_PRD_NULL -->|No| KAIHK_END_FMT
    KAIHK_END_FMT --> UNYO_AFTER_END{"unyo_ymd > kaihkEndYmd
(i.e., operational date is past end)?"}
    UNYO_AFTER_END -->|Yes| ERROR_1530["Set error: EKB1530-JW"]
    ERROR_1530 --> ERROR_1530_RET["ret = false"]
    UNYO_AFTER_END -->|No| FMTCEL_CHECK{"op_svc_cd ==
OP_SVC_CD_VALUE_FMTCEL
(B075 = Format Cell)?"}
    ERROR_1530_RET --> FMTCEL_CHECK

    FMTCEL_CHECK -->|Yes| FMTCEL_INIT["opSvcCdFmtcelCnt = 0
opSvcCdFmtcelLTECnt = 0"]
    FMTCEL_INIT --> FMTCEL_LOOP["Loop: for cnt = 0 to op_svc_kei_list.getCount()"]
    FMTCEL_LOOP --> FMTCEL_GET_BEAN["svcKeiInfo = op_svc_kei_list.getDataBean(cnt)"]
    FMTCEL_GET_BEAN --> FMTCEL_EXTRACT["Extract opSvcCd from field OP_SVC_CD_01
Extract opSvcKeiState from field OP_SVC_KEI_STAT_01
Extract pcrsCd from field PCRS_CD_01"]
    FMTCEL_EXTRACT --> FMTCEL_MATCH{"opSvcCd == FMTCEL (B075)
AND opSvcKeiState == 100
(Service provision active)?"}
    FMTCEL_MATCH -->|No| FMTCEL_NEXT["cnt++"]
    FMTCEL_MATCH -->|Yes| FMTCEL_PCRS{"pcrsCd == BC5
(Format Cell LTE)?"}
    FMTCEL_PCRS -->|Yes| LTE_CNT["opSvcCdFmtcelLTECnt++"]
    FMTCEL_PCRS -->|No| NORM_CNT["opSvcCdFmtcelCnt++"]
    LTE_CNT --> FMTCEL_NEXT
    NORM_CNT --> FMTCEL_NEXT
    FMTCEL_NEXT --> FMTCEL_LOOP_END{"cnt < count?"}
    FMTCEL_LOOP_END -->|Yes| FMTCEL_GET_BEAN
    FMTCEL_LOOP_END -->|No| FMTCEL_MAX_VALID{"max_op_svc_cnt != null
and not empty?"}
    FMTCEL_MAX_VALID -->|No| FUTURE_CHECK
    FMTCEL_MAX_VALID -->|Yes| FMTCEL_PCRS_CHECK{"op_pcrs_cd == BC5
(LTE)?"}
    FMTCEL_PCRS_CHECK -->|Yes| LTE_EXIST{"opSvcCdFmtcelLTECnt >= 1?"}
    LTE_EXIST -->|Yes| LTE_ERROR["Set error: EKB5420-JW
Arguments: Format Cell, Recovery"]
    LTE_ERROR --> LTE_ERROR_RET["ret = false"]
    LTE_EXIST -->|No| FUTURE_CHECK
    LTE_ERROR_RET --> FUTURE_CHECK
    FMTCEL_PCRS_CHECK -->|No| NORM_MAX_CMP{"opSvcCdFmtcelCnt + 1
> max_op_svc_cnt?"}
    NORM_MAX_CMP -->|Yes| NORM_ERROR["Set error: EKB5420-JW
Arguments: Format Cell, Recovery"]
    NORM_ERROR --> NORM_ERROR_RET["ret = false"]
    NORM_MAX_CMP -->|No| FUTURE_CHECK
    NORM_ERROR_RET --> FUTURE_CHECK

    FUTURE_CHECK["Check both lists
not null"] --> FUTURE_BOTH{"op_svc_kei_list != null
AND op_pack_kousei_list != null?"}
    FUTURE_BOTH -->|No| RETURN_FALSE
    FUTURE_BOTH -->|Yes| FUTURE_FLG_INIT["pack_mirai_msg_flg = false"]
    FUTURE_FLG_INIT --> FUTURE_PACK_STAT{"packStat != null, not empty,
AND != 910 (Cancelled),
AND != 920 (Terminated)?"}
    FUTURE_PACK_STAT -->|No| FUTURE_UNYO_CHECK
    FUTURE_PACK_STAT -->|Yes| FUTURE_USE_VALID{"packUseStaYmd != null
and not empty?"}
    FUTURE_USE_VALID -->|No| FUTURE_UNYO_CHECK
    FUTURE_USE_VALID -->|Yes| FUTURE_USE_CMP{"packUseStaYmd > unyo_ymd
(Package start date in future)?"}
    FUTURE_USE_CMP -->|Yes| FUTURE_FLG_SET1["pack_mirai_msg_flg = true"]
    FUTURE_USE_CMP -->|No| FUTURE_UNYO_CHECK
    FUTURE_FLG_SET1 --> FUTURE_UNYO_CHECK
    FUTURE_UNYO_CHECK["Loop: for i = 0
to op_pack_kousei_list.getCount()"]
    FUTURE_UNYO_CHECK --> FUTURE_OUTSIDE{"i < count?"}
    FUTURE_OUTSIDE -->|No| FUTURE_SECOND_LOOP
    FUTURE_OUTSIDE -->|Yes| FUTURE_GET_PACK_BEAN["opPackKouseiInfo = op_pack_kousei_list.getDataBean(i)"]
    FUTURE_GET_PACK_BEAN --> FUTURE_GET_PPLAN["kouseiOpPPlanCd = extract
field PPLAN_CD14"]
    FUTURE_GET_PPLAN --> FUTURE_PLAN_MATCH{"kouseiOpPPlanCd ==
op_pplan_cd?"}
    FUTURE_PLAN_MATCH -->|No| FUTURE_OUTSIDE_NEXT
    FUTURE_PLAN_MATCH -->|Yes| FUTURE_STA_CMP{"op_svc_sta_dtm > unyo_ymd
(Selected option start date in future)?"}
    FUTURE_STA_CMP -->|Yes| FUTURE_FLG_SET2["pack_mirai_msg_flg = true
break outside"]
    FUTURE_FLG_SET2 --> FUTURE_OUTSIDE_NEXT
    FUTURE_STA_CMP -->|No| FUTURE_OUTSIDE_NEXT
    FUTURE_OUTSIDE_NEXT --> FUTURE_OUTSIDE

    FUTURE_SECOND_LOOP["Loop: for cnt = 0
to op_svc_kei_list.getCount()"]
    FUTURE_SECOND_LOOP --> FUTURE_SECOND_I{"cnt < count?"}
    FUTURE_SECOND_I -->|No| FUTURE_FINAL_MSG{pack_mirai_msg_flg?
=== true?}
    FUTURE_SECOND_I -->|Yes| FUTURE_GET_SVC_BEAN["svcKeiInfo = op_svc_kei_list.getDataBean(cnt)"]
    FUTURE_GET_SVC_BEAN --> FUTURE_EXTRACT_SVC["Extract opPPlanCd from field PPLAN_CD_01
Extract opSvcKeiState from field OP_SVC_KEI_STAT_01
Extract list_op_svc_sta_dtm from field SVC_STA_DTM_01"]
    FUTURE_EXTRACT_SVC --> FUTURE_PACK_J_LOOP["Loop: for j = 0
to op_pack_kousei_list.getCount()"]
    FUTURE_PACK_J_LOOP --> FUTURE_PACK_J{"j < count?"}
    FUTURE_PACK_J -->|No| FUTURE_J_END
    FUTURE_PACK_J -->|Yes| FUTURE_GET_PACK_J["opPackKouseiInfo1 = op_pack_kousei_list.getDataBean(j)"]
    FUTURE_GET_PACK_J --> FUTURE_GET_KO_PPLAN["kouseiOpPPlanCd1 = extract
field PPLAN_CD14"]
    FUTURE_GET_KO_PPLAN --> FUTURE_PLAN_MATCH2{"kouseiOpPPlanCd1 == opPPlanCd?"}
    FUTURE_PLAN_MATCH2 -->|No| FUTURE_J_NEXT
    FUTURE_PLAN_MATCH2 -->|Yes| FUTURE_STATE_CHECK{"opSvcKeiState != 910
(Cancelled) AND != 920
(Terminated)?"}
    FUTURE_STATE_CHECK -->|No| FUTURE_J_NEXT
    FUTURE_STATE_CHECK -->|Yes| FUTURE_DTMCMP{"list_op_svc_sta_dtm > unyo_ymd
(Future start date)?"}
    FUTURE_DTMCMP -->|Yes| FUTURE_FLG_SET3["pack_mirai_msg_flg = true
break j loop"]
    FUTURE_DTMCMP -->|No| FUTURE_J_NEXT
    FUTURE_FLG_SET3 --> FUTURE_J_NEXT
    FUTURE_J_NEXT --> FUTURE_PACK_J

    FUTURE_J_END{"pack_mirai_msg_flg == true?"} -->|Yes| FUTURE_SECOND_DONE
    FUTURE_J_END -->|No| FUTURE_SECOND_I

    FUTURE_SECOND_DONE --> FUTURE_FINAL_MSG

    FUTURE_FINAL_MSG -->|Yes| MSG_EKBE130["Set error: EKBE130-KW
(Future start date exists)"]
    FUTURE_FINAL_MSG -->|No| RETURN_TRUE
    MSG_EKBE130 --> RETURN_TRUE

    RETURN_TRUE["Return ret = true"] --> END_NODE(["End: true"])
    RETURN_FALSE["Return ret = false"] --> END_FALSE(["End: false"])

    FUTURE_CHECK -->|No| RETURN_FALSE
```

### Constant Resolution Summary

| Constant | Value | Business Meaning |
|----------|-------|-----------------|
| `OPSVCCDS_DONTSENI` | `["B006","B007","B008","B009","B017","B019","B030","B031"]` | Operation service codes that cannot be transferred to at all |
| `OPSVCCDS_DONTKAIHK` | `["B068","B069","B077","B130","B131","B132","B138"]` | Operation service codes that cannot be recovered (e.g., B068 = Credit registration, B069 = Credit card change, B077 = bundled services) |
| `OP_SVC_CD_VALUE_FMTCEL` | `"B075"` | Format Cell — a specific option service type |
| `SVC_KEI_STAT_100` | `"100"` | Service provision status code meaning "in active service" (サービス提供中) |
| `CD00134_BC5` | `"BC5"` | Billing course code for Format Cell LTE (スマートフォン) |
| `PACK_STAT_910` | `"910"` | Cancellation completed (キャンセル済み) |
| `PACK_STAT_920` | `"920"` | Termination completed (解約済み) |
| `EKB5420-JW` | Error code | Generic "not recoverable" error message |
| `EKB1530-JW` | Error code | "Recovery period has expired" error message |
| `EKBE130-KW` | Error code | "Future service start date" warning message |

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `op_svc_cd` | `String` | Option service code — the type of the current option service being evaluated for recovery eligibility. Triggers different validation branches (e.g., `B075` for Format Cell invokes the concurrent count check). |
| 2 | `OPSVCCDS_SENIKKW2525` | `String[]` | Phase-specific excluded service code array — service codes that are blocked from recovery during a particular operational phase (SENKKW2525 phase). Null-safe check is performed before iteration. |
| 3 | `op_svc_end_ymd` | `String` | Option service end date (YYYYMMDD) — the date on which the option service contract terminates. Used to calculate the recovery deadline window. |
| 4 | `kaihk_psb_prd` | `String` | Recovery-allowed period in days — the number of days after the service end date during which recovery is still permitted. If empty, the recovery deadline is the service end date itself. |
| 5 | `op_svc_kei_list` | `X31SDataBeanAccessArray` | Option service detail list — an array of data beans representing all option service contracts on the current screen. Used for Format Cell concurrent count validation and future start date detection. |
| 6 | `max_op_svc_cnt` | `String` | Maximum allowed option service count — the upper limit on the number of concurrent Format Cell services a customer may have active. Enforced when recovery is requested for a Format Cell service. |
| 7 | `op_svc_sta_dtm` | `String` | Option service start date (YYYYMMDD) — the date when the currently selected option service begins. Used in future service start date checks against the operational date. |
| 8 | `op_pack_kousei_list` | `X31SDataBeanAccessArray` | Option package composition list — an array of data beans representing which option services are bundled within each telecom package. Used to detect if recovering the current service would affect pending package options. |
| 9 | `op_pplan_cd` | `String` | Option plan code — the billing plan code of the currently selected option service. Compared against package composition list entries to identify related services within a package. |
| 10 | `op_pcrs_cd` | `String` | Option billing course code — the billing course classification for the option service. Determines whether the concurrent count check applies to Format Cell LTE (`BC5`) or standard Format Cell. |
| 11 | `packUseStaYmd` | `String` | Package usage start date (YYYYMMDD) — the date when the telecom package becomes active. If this is in the future, it triggers a future start date warning. |
| 12 | `packStat` | `String` | Package status — indicates the current state of the package. Values `910` (Cancelled) and `920` (Terminated) are excluded from future start date checks since those packages are no longer active. |

**Instance fields / external state read:**
- `setCalendar(String)` — private helper method of this class, converts YYYYMMDD string to a `java.util.Calendar` object.

## 4. CRUD Operations / Called Services

This method performs **zero database operations**. All processing is in-memory. It delegates to utility methods and reads data from parameter objects only.

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `JCCWebCommon.getOpeDate` | (utility) | - | Retrieves the current operational date from the application server's date context |
| - | `JCCWebCommon.setMessageInfo` | (utility) | - | Sets an error message in the web context to be displayed on the screen |
| R | `KKA14901SFLogic.setCalendar` | (internal) | - | Internal helper that converts a YYYYMMDD string to a `java.util.Calendar` instance |

**All called methods are utility/internal. No SC/CBS calls, no DB reads/writes, no entity operations.** The method is a pure business rule evaluator that operates exclusively on parameter data.

## 5. Dependency Trace

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Logic: `KKW02301SFLogic` (koptWebB) | `actionBtnCheck(op_svc_cd, ...)` -> `actionBtnKaihkChk(...)` (12 params) | None (pure in-memory check) |
| 2 | Logic: `KKA14901SFLogic` (koptWebA) | `actionBtnCheck(op_svc_cd, ...)` -> `actionBtnKaihkChk(...)` (10 params, commented) | None (commented out) |
| 3 | Logic: `KKA14701SFLogic` (koptWebA) | `actionBtnCheck(op_svc_cd, ...)` -> `actionBtnKaihkChk(...)` (10 params, commented) | None (commented out) |
| 4 | Logic: `KKA14201SFLogic` (koptWebA) | `actionBtnCheck(op_svc_cd, ...)` -> `actionBtnKaihkChk(...)` (10 params, commented) | None (commented out) |
| 5 | Logic: `KKA14401SFLogic` (koptWebA) | `actionBtnCheck(op_svc_cd, ...)` -> `actionBtnKaihkChk(...)` (10 params, commented) | None (commented out) |

**Active caller:** `KKW02301SFLogic.actionBtnCheck()` in `source/koptWebB/src/eo/web/webview/KKW02301SF/KKW02301SFLogic.java` (line ~1751) is the sole currently-uncommented caller, passing all 12 parameters including `op_pcrs_cd`, `packUseStaYmd`, and `packStat`. This is the One-Stop screen's operation button handler, which dispatches to this recovery check when the user presses the Recovery button.

The five callers in koptWebA classes (KKA14901SF, KKA14701SF, KKA14201SF, KKA14401SF) have older versions of this method call (10 parameters, without `op_pcrs_cd`, `packUseStaYmd`, `packStat`) and are currently commented out, likely awaiting migration to the new parameter set.

## 6. Per-Branch Detail Blocks

**Block 1** — [FOR-LOOP] `OPSVCCDS_DONTSENI blacklist` (L3198)

> Iterates through the array of operation service codes that cannot be transferred at all, and blocks recovery if the current `op_svc_cd` matches any of them.

| # | Type | Code |
|---|------|------|
| 1 | SET | `i = 0` [loop initializer] |
| 2 | COMPARE | `i < OPSVCCDS_DONTSENI.length` |
| 3 | CALL | `OPSVCCDS_DONTSENI[i].equals(op_svc_cd)` [check blacklist match] |
| 4 | IF | match found |
| 5 | SET | `str = ["オプション", "回復"]` (Operation, Recovery) |
| 6 | CALL | `JCCWebCommon.setMessageInfo(this, "EKB5420-JW", str)` |
| 7 | SET | `ret = false` |
| 8 | EXEC | `i++` |

**Block 2** — [FOR-LOOP] `OPSVCCDS_DONTKAIHK blacklist` (L3219)

> Iterates through the array of operation service codes that are permanently non-recoverable. If matched, recovery is denied.

| # | Type | Code |
|---|------|------|
| 1 | SET | `i = 0` [loop initializer] |
| 2 | COMPARE | `i < OPSVCCDS_DONTKAIHK.length` |
| 3 | CALL | `OPSVCCDS_DONTKAIHK[i].equals(op_svc_cd)` |
| 4 | IF | match found |
| 5 | SET | `str = ["オプション", "回復"]` (Operation, Recovery) |
| 6 | CALL | `JCCWebCommon.setMessageInfo(this, "EKB5420-JW", str)` |
| 7 | SET | `ret = false` |
| 8 | EXEC | `i++` |

**Block 3** — [IF + FOR-LOOP] `OPSVCCDS_SENIKKW2525 phase-specific check` (L3231)

> Null-safe check on the caller-supplied SENIKKW2525 array. If the current service code matches any entry, recovery is denied.

| # | Type | Code |
|---|------|------|
| 1 | IF | `OPSVCCDS_SENIKKW2525 != null` |
| 2 | FOR | `i = 0; i < OPSVCCDS_SENIKKW2525.length` |
| 3 | CALL | `OPSVCCDS_SENIKKW2525[i].equals(op_svc_cd)` |
| 4 | IF | match found |
| 5 | SET | `str = ["オプション", "回復"]` (Operation, Recovery) |
| 6 | CALL | `JCCWebCommon.setMessageInfo(this, "EKB5420-JW", str)` |
| 7 | SET | `ret = false` |
| 8 | EXEC | `i++` |

**Block 4** — [PROCESSING] Get operational date and set calendar (L3246)

> Retrieves the current operational date and converts the service end date to a Calendar object.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `unyo_ymd = JCCWebCommon.getOpeDate(this, null)` [operational date in YYYYMMDD] |
| 2 | CALL | `cal_op_svc_end_ymd = setCalendar(op_svc_end_ymd)` [converts end date to Calendar] |

**Block 5** — [IF] `kaihk_psb_prd` recovery period extension (L3253)

> If a recovery-allowed period is specified, extends the service end date by that many days to calculate the recovery deadline.

| # | Type | Code |
|---|------|------|
| 1 | IF | `kaihk_psb_prd != null && !"".equals(kaihk_psb_prd)` |
| 2 | SET | `cal_op_svc_end_ymd.add(Calendar.DATE, Integer.parseInt(kaihk_psb_prd))` [extends end date] |

**Block 6** — [IF] Recovery period expiration check (L3262)

> Compares the operational date against the calculated recovery deadline. If the current operational date exceeds the deadline, recovery is denied with error `EKB1530-JW`.

| # | Type | Code |
|---|------|------|
| 1 | SET | `kaihkEndYmd = (new SimpleDateFormat("yyyyMMdd")).format(cal_op_svc_end_ymd.getTime())` |
| 2 | IF | `unyo_ymd.compareTo(kaihkEndYmd) > 0` [operational date is past the recovery deadline] |
| 3 | CALL | `JCCWebCommon.setMessageInfo(this, "EKB1530-JW")` [Recovery period expired] |
| 4 | SET | `ret = false` |

**Block 7** — [IF] Format Cell concurrent service count check (L3269)

> When `op_svc_cd == "B075"` (Format Cell), counts how many Format Cell services are currently active and enforces the maximum count limit.

| # | Type | Code |
|---|------|------|
| 1 | IF | `JKKCommonConst.OP_SVC_CD_VALUE_FMTCEL.equals(op_svc_cd)` [B075] |
| 2 | IF | `op_svc_kei_list != null` |
| 3 | SET | `opSvcCdFmtcelCnt = 0` [Format Cell non-LTE count] |
| 4 | SET | `opSvcCdFmtcelLTECnt = 0` [Format Cell LTE count (BC5)] |
| 5 | FOR | `cnt = 0; cnt < op_svc_kei_list.getCount()` |
| 6 | SET | `svcKeiInfo = op_svc_kei_list.getDataBean(cnt)` |
| 7 | SET | `opSvcCd = svcKeiInfo.sendMessageString(OP_SVC_CD_01, DATABEAN_GET_VALUE)` |
| 8 | SET | `opSvcKeiState = svcKeiInfo.sendMessageString(OP_SVC_KEI_STAT_01, DATABEAN_GET_VALUE)` |
| 9 | SET | `pcrsCd = svcKeiInfo.sendMessageString(PCRS_CD_01, DATABEAN_GET_VALUE)` |
| 10 | IF | `JKKCommonConst.OP_SVC_CD_VALUE_FMTCEL.equals(opSvcCd) && JKKCommonConst.SVC_KEI_STAT_100.equals(opSvcKeiState)` |
| 11 | IF | `JKKStrConst.CD00134_BC5.equals(pcrsCd)` [is Format Cell LTE?] |
| 12 | SET | `opSvcCdFmtcelLTECnt++` [LTE branch] |
| 13 | ELSE | `opSvcCdFmtcelCnt++` [non-LTE branch] |

**Block 7.1** — [IF] `max_op_svc_cnt` enforcement for Format Cell (L3320)

> After counting active Format Cell services, enforces the maximum concurrent limit.

| # | Type | Code |
|---|------|------|
| 1 | IF | `max_op_svc_cnt != null && !"".equals(max_op_svc_cnt)` |
| 2 | IF | `JKKStrConst.CD00134_BC5.equals(op_pcrs_cd)` [is the target service LTE?] |
| 3 | IF | `opSvcCdFmtcelLTECnt >= 1` [already has at least one Format Cell LTE] |
| 4 | SET | `str = ["スマートフォン", "回復"]` (Smartphone, Recovery) |
| 5 | CALL | `JCCWebCommon.setMessageInfo(this, "EKB5420-JW", str)` |
| 6 | SET | `ret = false` |
| 7 | ELSE | `opSvcCdFmtcelCnt + 1 > Integer.parseInt(max_op_svc_cnt)` [non-LTE, exceeds max] |
| 8 | SET | `str = ["スマートフォン", "回復"]` (Smartphone, Recovery) |
| 9 | CALL | `JCCWebCommon.setMessageInfo(this, "EKB5420-JW", str)` |
| 10 | SET | `ret = false` |

**Block 8** — [IF] Future service start date check — outer list guard (L3340)

> Both the option service list and the package composition list must be non-null before running the future date checks.

| # | Type | Code |
|---|------|------|
| 1 | IF | `op_svc_kei_list != null && op_pack_kousei_list != null` |
| 2 | SET | `pack_mirai_msg_flg = false` [message display flag] |

**Block 8.1** — [IF] Package start date in future (L3345)

> If the package is active (not cancelled `910` or terminated `920`) and the package usage start date is in the future, set the future message flag.

| # | Type | Code |
|---|------|------|
| 1 | IF | `packStat != null && !"".equals(packStat) && !"910".equals(packStat) && !"920".equals(packStat)` |
| 2 | IF | `packUseStaYmd != null && !"".equals(packUseStaYmd)` |
| 3 | IF | `packUseStaYmd.compareTo(unyo_ymd) > 0` [package start date is in the future] |
| 4 | SET | `pack_mirai_msg_flg = true` |

**Block 8.2** — [FOR-LOOP with labeled break] Telecom package composition check — selected option (L3360)

> Iterates through the package composition list to find if the currently selected option is part of a telecom package with a future start date.

| # | Type | Code |
|---|------|------|
| 1 | FOR | `outside: for (i = 0; i < op_pack_kousei_list.getCount())` |
| 2 | SET | `opPackKouseiInfo = op_pack_kousei_list.getDataBean(i)` |
| 3 | SET | `kouseiOpPPlanCd = opPackKouseiInfo.sendMessageString(PPLAN_CD14, DATABEAN_GET_VALUE)` |
| 4 | IF | `kouseiOpPPlanCd.equals(op_pplan_cd)` [matches the selected option's plan] |
| 5 | IF | `op_svc_sta_dtm.compareTo(unyo_ymd) > 0` [option start date is in the future] |
| 6 | SET | `pack_mirai_msg_flg = true` |
| 7 | EXEC | `break outside;` |

**Block 8.3** — [FOR-LOOP x FOR-LOOP] Non-selected option future start date check (L3394)

> Iterates through all option services and all package compositions to find if any option that composes part of a telecom package has a future start date and is not cancelled/terminated.

| # | Type | Code |
|---|------|------|
| 1 | FOR | `cnt = 0; cnt < op_svc_kei_list.getCount()` |
| 2 | SET | `svcKeiInfo = op_svc_kei_list.getDataBean(cnt)` |
| 3 | SET | `opPPlanCd = svcKeiInfo.sendMessageString(PPLAN_CD_01, DATABEAN_GET_VALUE)` |
| 4 | SET | `opSvcKeiState = svcKeiInfo.sendMessageString(OP_SVC_KEI_STAT_01, DATABEAN_GET_VALUE)` |
| 5 | SET | `list_op_svc_sta_dtm = svcKeiInfo.sendMessageString(SVC_STA_DTM_01, DATABEAN_GET_VALUE)` |
| 6 | FOR | `j = 0; j < op_pack_kousei_list.getCount()` |
| 7 | SET | `opPackKouseiInfo1 = op_pack_kousei_list.getDataBean(j)` |
| 8 | SET | `kouseiOpPPlanCd1 = opPackKouseiInfo1.sendMessageString(PPLAN_CD14, DATABEAN_GET_VALUE)` |
| 9 | IF | `kouseiOpPPlanCd1.equals(opPPlanCd)` [package composition matches this option] |
| 10 | IF | `!"910".equals(opSvcKeiState) && !"920".equals(opSvcKeiState)` |
| 11 | IF | `list_op_svc_sta_dtm.compareTo(unyo_ymd) > 0` [future start date] |
| 12 | SET | `pack_mirai_msg_flg = true` |
| 13 | EXEC | `break` [breaks inner j loop] |
| 14 | IF | `pack_mirai_msg_flg == true` |
| 15 | EXEC | `break` [breaks outer cnt loop] |

**Block 9** — [IF] Future message flag display (L3477)

> If any future start date was detected during the package composition checks, display the warning message and the method returns true (allowing the caller to handle the display).

| # | Type | Code |
|---|------|------|
| 1 | IF | `pack_mirai_msg_flg == true` |
| 2 | CALL | `JCCWebCommon.setMessageInfo(this, JPCOnlineMessageConstant.EKBE130_KW)` |

**Block 10** — [RETURN] Final return (L3483)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return ret` |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `op_svc_cd` | Field | Option service code — classifies the type of option service (e.g., B075 = Format Cell, B006 = credit) |
| `op_svc_kei_list` | Field | Option service detail list — list of all option service contracts on the current screen, each with status, billing code, and plan code |
| `op_svc_end_ymd` | Field | Option service end date — the date the service contract expires (YYYYMMDD format) |
| `kaihk_psb_prd` | Field | Recovery-allowed period in days — how many days after service end date recovery is still permitted |
| `op_svc_sta_dtm` | Field | Option service start date — when the option service begins (YYYYMMDD format) |
| `op_pack_kousei_list` | Field | Option package composition list — which option services are bundled within each telecom package |
| `op_pplan_cd` | Field | Option plan code — billing plan code for the selected option |
| `op_pcrs_cd` | Field | Option billing course code — billing course classification (e.g., BC5 = Format Cell LTE) |
| `packUseStaYmd` | Field | Package usage start date — when the telecom package becomes active (YYYYMMDD format) |
| `packStat` | Field | Package status — current state of the package (910 = Cancelled, 920 = Terminated) |
| `max_op_svc_cnt` | Field | Maximum allowed option service count — upper limit on concurrent active Format Cell services |
| `OPSVCCDS_DONTSENI` | Constant | Array of service codes that cannot be transferred at all (B006, B007, B008, B009, B017, B019, B030, B031) |
| `OPSVCCDS_DONTKAIHK` | Constant | Array of service codes that cannot be recovered (B068 = Credit registration, B069 = Credit card change, B077 = bundled services, B130-B132, B138) |
| `OPSVCCDS_SENIKKW2525` | Field | Phase-specific excluded service codes — caller-supplied array of non-recoverable services for a particular operation phase |
| `OP_SVC_CD_VALUE_FMTCEL` | Constant | `"B075"` — Format Cell option service code |
| `SVC_KEI_STAT_100` | Constant | `"100"` — Service provision active status (サービス提供中) |
| `CD00134_BC5` | Constant | `"BC5"` — Billing course code for Format Cell LTE (スマートフォン / smartphone) |
| `EKB5420-JW` | Error code | "This option service cannot be recovered" — generic recovery prohibition |
| `EKB1530-JW` | Error code | "Recovery period has expired" — the operational date is past the deadline |
| `EKBE130-KW` | Error code | "Future service start date exists" — a package option has a start date in the future |
| `910` | Status code | Cancellation completed (キャンセル済み) |
| `920` | Status code | Termination completed (解約済み) |
| `setCalendar` | Method | Internal helper converting YYYYMMDD string to `java.util.Calendar` |
| `JCCWebCommon.getOpeDate` | Method | Retrieves the application server's current operational date |
| `JCCWebCommon.setMessageInfo` | Method | Sets a message in the web context for screen display |
| `OP_SVC_CD_01` | Field key | Data bean field name for option service code |
| `OP_SVC_KEI_STAT_01` | Field key | Data bean field name for option service contract status |
| `PCRS_CD_01` | Field key | Data bean field name for billing course code |
| `PPLAN_CD_01` | Field key | Data bean field name for billing plan code |
| `PPLAN_CD14` | Field key | Data bean field name for billing plan code (package composition) |
| `SVC_STA_DTM_01` | Field key | Data bean field name for service start date-time |
| Format Cell | Business term | A smartphone data plan option service (スマートフォンデータ定額) |
| SENIKKW2525 | Business term | A specific operational phase/code — services excluded from recovery during this phase |
| Recovery (回復) | Business term | Undo/rollback an option service registration — the operation this method guards |
| One-Stop | Business term | Unified service screen (One-Stop screen) where option services, packages, and subscriptions are managed together |
