# KKW00147SFLogic

## Purpose

`KKW00147SFLogic` is the core business-logic controller for the **Telephone Number Registration screen** (電話番号情報登録画面) in the EO Hikari Denwa (NTT East's fiber optic telephone service) web application. It orchestrates the entire customer-facing workflow: displaying the initial registration form, validating user input, submitting data to backend services, and navigating between the three-page confirmation flow (initial edit → confirmation → completion). This class is the central hub for phone number operations including **number addition**, **number change**, **line cancellation (contract termination)**, **portability (MNP) handling**, and **port information management**.

## Design

`KKW00147SFLogic` follows the **front-controller / page-controller hybrid pattern** typical of the JCC web framework. It extends `JCCWebBusinessLogic` (from the base framework) and acts as both:

- **Page controller** — Each `action*()` method handles a specific button press or screen transition (e.g., `actionCfm()`, `actionFix()`, `actionBack()`, `actionBmp()`).
- **Facade** — It coordinates dozens of service-level calls (via `invokeService()`) and maps data between the presentation layer (`X31SDataBeanAccess` beans) and backend service mappers (e.g., `KKSV0065_KKSV0065OPDBMapper`, `KKSV0211_KKSV0211OPDBMapper`).

The class manages a multi-step wizard flow:

```
Screen KKW00147 (Edit)  →  Screen KKW00151 (Confirm)  →  Screen KKW00152 (Complete)
```

It also forwards to sub-screens for specialized tasks: KKW00148 (portability input), KKW04213 (diversion/transfer lookup), KKW00404 (work information entry), KKW00834 (TDIS inquiry).

The entire workflow is driven by the `ido_div` field, a discriminator that determines which operation mode is active:
- **Number addition** (`IDO_DIV_BANGO_TSUIKA` — code `00041`)
- **Number change** (`IDO_DIV_BANGO_HENKO` — code `00049`)
- **Contract termination** (`IDO_DIV_BANGO_KAIYAKU` — code `00044`)
- **Phone number info change** (`IDO_DIV_DENWA_HENKO` — code `00050`)
- **Port information change** (`IDO_DIV_BANPO_HENKO` — code `00052`)

## Key Methods

### Screen Entry & Initialization

#### `actionInit() → boolean`

Entry point for the screen. Reads the target screen ID from the shared `CommonInfoBean` and dispatches to the correct initialization handler:
- `KKW00147` → calls `actionInitKKW00147()` (main edit screen)
- `KKW00151` → confirmation screen (minimal init)
- `KKW00152` → completion screen (minimal init)

Sets `NEXT_SCREEN_ID` and `NEXT_SCREEN_NAME` in the common info bean. Returns `true` on success.

#### `actionInitKKW00147() → boolean`

The heavy initialization routine for the main edit screen. It:
1. Creates and initializes the `svcFormBean` via `initServiceFormBean()`.
2. Retrieves inherited screen data via `getMotoData()`, including the critical `ido_div` discriminator.
3. Calls `KKSV0064_KKSV0064OPDBMapper` to fetch all pre-populated data from the backend service **KKSV0064** (phone number registration initial display). This involves ~30 mapper methods (`setKKSV0064XXSC`) covering customer info, service contracts, portability data, VA (virtual appliance / home gateway) choices, and address data.
4. Invokes the service via `invokeService(paramMap, inputMap, outputMap)`.
5. Retrieves results back into beans via corresponding `getKKSV0064XXSC()` methods.
6. Calls `editServiceFormBean()` to transform service results into display-ready form fields.

#### `initServiceFormBean(X31SDataBeanAccess svcFormBean) → void`

Sets up foundational bean fields: operation date (`UNYO_YMD`), caller screen ID (`BACK_SCREEN_ID`), aging/sub-service code (`AGING_SBT_CD` = `"001"` for telephone number), and operation service service code.

#### `getMotoData(X31SDataBeanAccess svcFormBean) → void`

Copies inherited screen state from the `CUST_KEI_HKTGI_LIST` bean into the service form bean. Extracts `SYSID`, `SVC_KEI_NO`, `SVC_KEI_UCWK_NO`, and `IDO_DIV`. Also checks for a return flag (`RETURN_FLG`) indicating the user came back from a sub-screen.

#### `editNrn(X31SDataBeanAccess svcFormBean, String bmpUm) → void`

Extracts and normalizes the **NRN** (Number Portability/Non-Portability Identifier — a 16-digit unique number for subscriber identification). It first checks the telephone number agreement result (`EZM0121A010DATA`); if NRN is blank, it falls back to individual or corporate NRN from the local exchange agreement result (`EZM0211A010DATA`).

#### `editServiceFormBean(X31SDataBeanAccess svcFormBean, HashMap<String, Object> outputMap) → void`

This is one of the **largest methods** in the class (spanning lines 454–1362). It performs comprehensive transformation of backend service results into display-ready form bean fields. The method is split into branches based on `ido_div`:

- **Number addition** (`IDO_DIV_BANGO_TSUIKA`): Sets service commission pulldowns, address, phone number fields, VA choice pulldown, port number pulldown, forwarding (diversion) status, contract details, and resets cancellation/charge dates.
- **Number change** / **Contract termination**: Sets pre-existing phone number, NRN, user name, address, forwarding status, commission pulldowns.
- **Other modes**: Clears appropriate fields.

Also configures display pulldowns for portability (BMP), caller ID notification (HASINSHA_NO_TCH), number guide, phone book listing, and service status fields.

#### `configureVAChoicePulldown(X31SDataBeanAccess svcFormBean, HashMap<String, Object> outputMap) → void`

Populates the **VA (Virtual Appliance / Home Gateway) model selection pulldown**. VA models are devices like "eo光多機能ルーター" (eo multifunction router) and "eoホームゲートウェイ" (eo home gateway). This method:
1. Builds a map of VA models from multiple sources (`EKK0341B002DATA` — equipment provision service contracts, `EZM0221A010DATA` — VA model list, etc.).
2. Adds a default "none" option at index 0.
3. If the user already has a VA model registered, it auto-selects that model.
4. Populates dependent pulldowns: `VA_CHOICE` (model selection), `KIKIPULLDOWN_LIST` (model + change number combinations), and `PORT_NO` (port number).

### Data Validation

#### `checkSVData() → boolean`

Server-side validation executed before form submission. Checks:
- **Portability (BMP) withdrawal**: If the user previously had portability enabled and selects "no", blocks with error `EKB4210-KW`.
- **VA selection**: For number addition or phone number info change, if the user selects a non-default VA model, a VA model must be explicitly chosen. Error `EKB1320-NW` if blank.
- **User name length**: Kana user name must be ≤ 36 characters after full-to-half-width conversion. Error `EKB0040-TW`.
- **Port number selection**: For number addition, a port number must be selected. Error `EKB1320-NW`.
- **ONU exchange work conflict**: If ONU exchange work is enabled but there's already an ongoing construction project (new installation, plane change, or removal), registration is blocked. Error `EKB1040-JW`.

Returns `true` if validation passes, `false` otherwise.

### Form Submission & Business Logic

#### `actionCfm() → boolean` (Confirmation button)

Sets `KARI_TOUROKU_FLG` to `FLG_OFF` (not a temporary registration) and delegates to `cfmTran()`. This triggers the primary confirmation flow.

#### `actionKrAdd() → boolean` (Temporary registration button)

Sets `KARI_TOUROKU_FLG` to `FLG_ON` and delegates to `cfmTran()`. Creates a temporary record that can be updated later.

#### `cfmTran() → boolean`

The **central submission routine** that both `actionCfm()` and `actionKrAdd()` call. The flow:
1. Resets the data bean to handle JavaScript-cleared fields.
2. Calls `checkSVData()` — if validation fails, calls `actionKikiChange()` and returns to re-display the form.
3. Calls `confirmServiceFormBean()` to prepare the bean for the confirmation screen.
4. Calls `doAddTelephoneNumberInfo(FUNC_CD_2)` — this performs a **dry-run** (check-only) service call.
5. In a `finally` block, calls `reeditServiceFormBean()` to restore the form for re-display if needed.
6. Performs additional checks:
   - For number addition: validates emergency address (`checkEmegencyAddress()`).
   - For contract termination: validates the service end date is within the allowed term (`svcEndTerm`).
   - Checks if the caller ID notification option was changed and shows a warning if so.
   - For phone number info change: shows a warning if the VA model changed.
7. Sets `NEXT_SCREEN_ID` to `KKW00151` (confirmation screen).
8. Displays appropriate confirmation message.

#### `doAddTelephoneNumberInfo(String funcCode) → boolean`

The **primary service invocation method**. This massive method (lines 3775–4176) branches by `ido_div` and invokes the appropriate backend service:

- **Number addition** (`IDO_DIV_BANGO_TSUIKA`): Invokes service **KKSV0065** with `setKKSV006501CC()`. This registers the phone number with forwarding, portability, and VA information. Sets `PRG_STAT` to `IDO_STAT_B301` (number addition complete).

- **Phone number info change** (`IDO_DIV_DENWA_HENKO`): Invokes service **KKSV0211** with ~25 mapper calls covering customer agreement, service contract details, application content approval, service contract information change, option service registration/cancellation/opening, application details approval/follow-up, progress registration, service agreement agreement, and service contract agreement. This is the most complex path.

- **Number change** (`IDO_DIV_BANGO_HENKO`): Also invokes **KKSV0211** but with a different parameter set.

- **Contract termination** (`IDO_DIV_BANGO_KAIYAKU`): Invokes **KKSV0211** with service cancellation mappers, setting `PRG_STAT` to `IDO_STAT_B101` (contract termination).

- **Port information change** (`IDO_DIV_BANPO_HENKO`): Invokes **KKSV0211** focused on port information updates.

Returns `true` if an error occurred, `false` on success.

#### `actionFix() → boolean` (Determine / Finalize button)

Called from the confirmation screen (KKW00151). Sets up the final submit by:
1. Calling `confirmServiceFormBean()`.
2. Invoking `doAddTelephoneNumberInfo(FUNC_CD_1)` — this time with `FUNC_CD_1` (actual execution, not dry-run).
3. In `finally`, calls `reeditServiceFormBean()` to restore the form.
4. Checks if the user has 2 phone lines and uses a VA port — if so, shows a message `EKBA420--I`.
5. Sets `NEXT_SCREEN_ID` to `KKW00152` (completion screen).
6. Displays completion message `EKB4390--I`.

#### `confirmServiceFormBean() → void`

Prepares the service form bean for submission by:
- Setting commission (jimu) rate calculations based on the selected service commission type.
- Extracting Bampo (port) information via `editBampoInfo()` if applicable.
- Resolving the selected VA model to its actual model code, serial number, and change number from the `KIKIPULLDOWN_LIST`.
- Setting port number, device provision service code, and home gateway type.
- Building submission content approval registration detail lists.
- For contract termination: composing service end date from year/month/day fields and setting penalty fee generation flags.
- Setting operation date, timestamp, billing contract number, parent contract code, and delivery/submission parameters.

### Screen Transitions & Sub-screens

#### `forward2BangoPortabilityGamen(String motoScreenId) → boolean`

Forwards to the **portability input screen** (KKW00148). Collects portability information from the `BMP_INPUT` bean, constructs an inheritance map with customer/service contract data, and sets the screen info for the destination. If the moto screen is KKW00151 (confirmation), uses `makeKkninHktgiDataMap()` for confirmed data.

#### `forward2DoubanItenGamen(String motoScreenId) → boolean`

Forwards to the **diversion/transfer input screen** (KKW04213). Collects diversion information from the `DOBANITEN_INPUT` bean and forwards it.

#### `actionDobaniten() → boolean` / `actionDobanitenRet() → boolean`

Button handlers for the diversion lookup screen. `actionDobaniten()` navigates to KKW04213; `actionDobanitenRet()` returns from it, copying results back into the calling bean.

#### `actionItnToki() → boolean`

Handles the forwarding activation button. Sets up screen info and navigates to screen KKW05601 (forwarding activation settings).

#### `actionOpenTDIS() → boolean` / `actionOpenTDISRef() → boolean`

Opens the TDIS (Tel ID Display) inquiry screen. `actionOpenTDIS()` constructs params via `configureParams4SubScreen()` and navigates to KKW00834. `actionOpenTDISRef()` is an alias.

#### `configureParams4SubScreen() → HashMap<String, Object>`

Builds the inheritance data map for sub-screens (TDIS inquiry). Extracts phone number, service contract numbers, diversion reason codes, and customer contract inheritance list from the current form bean.

#### `actionForceUseExit() → boolean`

Handles the forced service termination button. Validates the user's service type — if it's an MT/MZ removal service (SCM type B), blocks with error `EKB0930-NW`. Otherwise, calls the KKSV0065 service to process the termination.

### Pulldown Configuration

#### `configPulldown(X31SDataBeanAccess svcFormBean, String srcKeyCd, String tgtKeyCd, String initVal) → void`

Copies options from a source pulldown (e.g., `CD00002DATA` — yes/no codes) to a target pulldown, selecting `initVal` as the pre-selected option. Sets `CD_DIV_LIST_01`, `CD_DIV_NM_LIST_01`, and `INDEX_01` fields.

#### `configClearPulldown(X31SDataBeanAccess svcFormBean, String tgtKeyCd) → void`

Clears a pulldown and sets it to an empty single option (index 0).

#### `configureVAPortPulldown(X31SDataBeanAccess svcFormBean, X31SDataBeanAccess svcKeiUcwkTelBean) → void`

Configures the port number pulldown from the service contract info. Extracts the VA port number and populates the target pulldown.

#### `addTaknkikiModel(...)` / `containsCheck(...)`

Helper methods for building the VA model selection map. `addTaknkikiModel` merges equipment provision contract VA models into a map keyed by service contract internal number. `containsCheck` verifies if a model code already exists in the map.

### Utility Methods

#### `isNull(Object arg0) → boolean`

Static utility: returns `true` if the argument is `null` or an empty string.

#### `getDisplayNameFromPulldown(...) → String` / `getPulldownNm(...)` / `getPulldownCd(...)` / `getPulldownSelectedName(...)`

Helper methods to extract display names or codes from pulldown selections.

#### `selectedPulldownIndex(X31SDataBeanAccess bean, String pulldownInfName, String targetCd) → void`

Selects a pulldown option by code value.

#### `editAddress(...) → String`

Composes a full address string from state, city, oaza (district), and azcho (block) name fields. Also sets individual address components in the form bean.

#### `createYMDStr(String year, String month, String day) → String`

Concatenates year, month, and day into an YYYYMMDD string.

#### `getMotoData(...)` / `makeHktgiDataMap(...)` / `makeKkninHktgiDataMap(...)` / `getHktgiDataMap(...)`

Construct inheritance data maps for screen navigation. `makeKkninHktgiDataMap()` is used when data has already been confirmed (from KKW00151), preserving the confirmed state.

#### `reeditServiceFormBean() → void`

Rebuilds the service form bean after a submission. Used in `finally` blocks to ensure the confirmation screen can always be displayed, even if the submission failed. Restores pulldown selections for portability, BMP, caller ID notification, etc.

#### `actionBack() → boolean`

Navigates back to the previous screen using stored `BACK_SCREEN_ID`.

#### `actionKikiChange() → boolean`

Handles device type change operations. Reconfigures the VA model pulldown based on the current service state.

#### `isTknrt(X31SDataBeanAccess svcFormBean, String kikiModelCd) → boolean`

Checks if the given model code corresponds to an eo Hikari multifunction router by looking up the `EKK0341B002DATA` list and matching against service code `C024` (or `C025` for HGW).

#### `isTowPortVA(X31SDataBeanAccess svcFormBean) → boolean`

Determines if the customer's phone service uses a VA port (second line via virtual appliance).

#### `checkEmegencyAddress(...) → boolean`

Validates that an emergency notification address is properly configured for the customer's service.

#### `getTelNoTchUm() → String`

Determines whether caller ID notification is enabled by checking `EKK0351B010DATA` records — if any record has a status less than `SVC_KEI_STAT_910` (canceled/terminated), caller ID notification is considered "present".

#### `getTelKeiCount(X31SDataBeanAccess svcFormBean) → int`

Returns the count of phone line records for the customer.

#### `setErrorMessageInfo(...)` / `setEgErrorMessageInfo(...)`

Check error conditions from service output maps and display appropriate error messages for order issuance and E→G conversion work scenarios.

#### `actionKojiifinput() → boolean` / `actionKojiifinputrefresh() → boolean`

Navigate to/from the work information entry screen (KKW00404). Passes work-related fields (construction method, notes, preferred dates, contact info) to the sub-screen and retrieves them on return.

#### `getDispAuthority() → boolean`

Checks if the current user has authorization code `AUKKW00147300` to access this screen.

## Relationships

```mermaid
flowchart TD
    subgraph ScreenFlow["Screen Flow"]
        Init["KKW00147SF<br/>Initial Display"] --> Edit["KKW00147SF<br/>Edit Form"]
        Edit --> Confirm["KKW00151SF<br/>Confirmation"]
        Confirm --> Complete["KKW00152SF<br/>Completion"]
        Confirm --> Portability["KKW00148SF<br/>Portability Input"]
        Confirm --> Transfer["KKW04213SF<br/>Diversion Lookup"]
        Edit --> SubScreen["KKW00404SF<br/>Work Info Entry"]
        Edit --> TDIS["KKW00834SF<br/>TDIS Inquiry"]
    end

    subgraph Logic["KKW00147SFLogic"]
        actionInit["actionInit"]
        actionInitKKW00147["actionInitKKW00147"]
        actionCfm["actionCfm"]
        actionKrAdd["actionKrAdd"]
        actionFix["actionFix"]
        doAddTelInfo["doAddTelephoneNumberInfo"]
        cfmTran["cfmTran"]
        confirmSvc["confirmServiceFormBean"]
        checkSV["checkSVData"]
        editSvc["editServiceFormBean"]
        configVA["configureVAChoicePulldown"]
        fwdPort["forward2BangoPortabilityGamen"]
        fwdDiv["forward2DoubanItenGamen"]
        fwdTDIS["configureParams4SubScreen"]
        forceExit["actionForceUseExit"]
    end

    actionInit --> actionInitKKW00147
    actionInitKKW00147 --> editSvc
    editSvc --> configVA
    actionCfm --> cfmTran
    actionKrAdd --> cfmTran
    actionFix --> doAddTelInfo
    cfmTran --> checkSV
    cfmTran --> confirmSvc
    cfmTran --> doAddTelInfo
    cfmTran --> reedit["reeditServiceFormBean"]
    confirmSvc --> doAddTelInfo
    actionFix --> doAddTelInfo
    actionBmp["actionBmp"] --> fwdPort
    actionDobaniten2["actionDobaniten2"] --> fwdDiv
    actionOpenTDIS["actionOpenTDIS"] --> fwdTDIS
    forceExit --> fwdTDIS
```

### Inbound Dependencies (5 classes reference this)

| Class | Relationship |
|---|---|
| `WEBGAMEN_KKW001470PJP.xml` | JSP page for screen KKW00147 (edit form) |
| `WEBGAMEN_KKW001510PJP.xml` | JSP page for screen KKW00151 (confirmation) |
| `WEBGAMEN_KKW001520PJP.xml` | JSP page for screen KKW00152 (completion) |
| `x31business_logic_KKW00147SF.xml` | XML configuration wiring the logic to the screen |
| `x31business_logic_KKW00151SF.xml` | XML configuration for the confirmation screen logic |

### Outbound Dependencies

| Class | Relationship |
|---|---|
| `JCCWebBusinessLogic` | Parent class — provides `invokeService()`, `getServiceFormBean()`, `getCommonInfoBean()` |

### Related Data Beans (35+ beans in the same package)

The logic works with a large set of `KKW00147SF*DBean` data beans (e.g., `KKW00147SFBean`, `KKW00147SF01DBean` through `KKW00147SF33DBean`), plus supporting files:
- `KKW00147SFConst.java` — constant definitions
- `KKW00147SFChecker.java` — client-side/form-level validation

## Usage Example

The typical flow when a customer registers or modifies a telephone number:

```
1. User navigates to the phone number registration screen (KKW00147)
   → JSP invokes actionInit(), which reads screen ID and dispatches
   → actionInitKKW00147() calls KKSV0064 service to fetch existing data
   → editServiceFormBean() transforms results for display
   → configureVAChoicePulldown() populates the VA model selector

2. User fills in the form and clicks "Confirm" (確定)
   → actionCfm() sets KARI_TOUROKU_FLG = OFF
   → cfmTran() runs checkSVData() for validation
   → confirmServiceFormBean() prepares the bean for confirmation
   → doAddTelephoneNumberInfo(FUNC_CD_2) performs a dry-run submission
   → reeditServiceFormBean() restores the form for re-display
   → Screen transitions to KKW00151 (confirmation)

3. User reviews and clicks "Determine" (決定) on confirmation screen
   → actionFix() calls doAddTelephoneNumberInfo(FUNC_CD_1) for actual execution
   → Screen transitions to KKW00152 (completion)
```

For a **temporary registration** (仮登録), the user clicks the temporary registration button instead:
```
→ actionKrAdd() sets KARI_TOUROKU_FLG = ON
→ cfmTran() runs similarly but leaves data as temporary
→ User can later return to finalize with actionFix()
```

For **portability information**, the user clicks the port info button:
```
→ actionBmp() → forward2BangoPortabilityGamen()
→ Screen transitions to KKW00148 for port number input
```

## Notes for Developers

1. **Thread safety**: This class is **not thread-safe**. It maintains mutable instance state via the `ido_div` field, which is set once during `actionInitKKW00147()` and read throughout the lifecycle. Each HTTP request creates a new instance, so this is not a practical concern in the web context, but be aware if the class is ever reused.

2. **Huge method**: `editServiceFormBean()` spans ~900 lines and `cfmTran()` spans ~250 lines. These are candidates for extraction into smaller, testable methods. The method uses a `switch`-like pattern with `if/else` on `ido_div`, making it relatively easy to navigate.

3. **Extensive commenting with issue IDs**: The source code is heavily annotated with issue/tracking IDs (e.g., `IT2-2012-0000266`, `ANK-4315-00-00`, `OM-2014-0002880`). These are Japanese internal tracking codes. They are valuable context for understanding *why* certain logic exists but make the code harder to read. The presence of large commented-out blocks suggests a history of iterative changes.

4. **Japanese business logic**: The class implements business rules specific to Japanese telecommunications, including:
   - NRN (Number Portability/Non-Portability Identifier) extraction for individual vs. corporate subscribers
   - Address parsing following Japanese postal address conventions (都道府県 → 市区町村 → 大字通称 → 字町名)
   - Portability (MNP — Mobile Number Portability) handling
   - Service commission (事務手数料) calculations with different rate types (free, 50%, specified amount)
   - Forwarding (転送) status tracking
   - Emergency notification address validation for telephone contracts

5. **Service contract state awareness**: The class tracks many service contract states through codes like `SVC_KEI_STAT_21` (010=accepted, 020=contracted, 030=completed), `SVC_KEI_UCWK_STAT_05` (agreement status), and `OP_SVC_KEI_STAT_15` (option service status). These codes are referenced throughout and are defined in `JKKCommonConst`.

6. **Screen flow is rigid**: The confirmation screen (KKW00151) and completion screen (KKW00152) are navigated through strictly. Navigation between KKW00147 → KKW00151 → KKW00152 uses `JCCWebCommon.setScreenId()` which records the previous screen ID for back-navigation support.

7. **Error handling**: Errors are communicated via `JCCWebCommon.setMessageInfo()` which sets message codes (e.g., `EKB4210-KW`) that are resolved into user-facing messages by the framework's message resolution layer. Check the message ID constants in the codebase for the actual error text.

8. **Constants file is large**: `KKW00147SFConst.java` (78KB) contains over 800 constant definitions for field names, codes, and display strings. Refer to it when working with unfamiliar bean field names.

9. **The `doAddTelephoneNumberInfo` method is the critical path**: This single method handles ALL backend service invocations for every operation mode. If you need to add a new operation or modify an existing one, this is the method to start with. Be cautious when changing it — it affects all screen flows.

10. **Pulldown configuration is data-driven**: The `configPulldown` and `configClearPulldown` methods are generic utilities that copy options from source beans to target beans. The actual pulldown data comes from `X31SDataBean` lists (e.g., `CD00002DATA` for yes/no, `CD00346DATA` for service commission types). The data is likely populated from database lookup tables at runtime.
