# KKW03204SFLogic

## Purpose

`KKW03204SFLogic` is the central business-logic controller for the **050-number porting change (番号変更) workflow** in the JPC online service system. It coordinates the full lifecycle of a customer's request to change their telephone number: initial display, confirmation, execution (including three operation modes — cancellation, reactivation, and service termination), and final navigation. This class acts as a facade between web-view presentation classes and the underlying backend services (KKSV0135, KKSV0136, KKSV0162, KKSV0163), handling DataBean population, service invocation, error display, and screen navigation in a single place.

## Design

The class follows the **Front Controller / Web Logic Controller** pattern within the JCC (Japan Credit Card / similar platform) web framework. It extends `JCCWebBusinessLogic`, inheriting core infrastructure such as `invokeService()`, `getScreenInfo()`, `getServiceFormBean()`, and `dumpDatabean()`.

Each public method (`actionInit`, `actionUpd_cfm`, `actionFix`, etc.) corresponds to a distinct button action or screen event triggered by the user — similar to the page-controller pattern. The class uses a strategy approach internally: the `trans_div` field (populated during `actionInit` via `setDataInit`) determines which business sub-path to follow — `OP_TRAN_DIV_DSL` (解約 / cancellation), `OP_TRAN_DIV_KAIHK` (回復 / reactivation), or `OP_TRAN_DIV_RSV_CL` (予約取消 / reservation cancellation).

The private helper methods follow a consistent naming convention:
- `setData*` — populate the DataBean with input data required by a backend service
- `setMapped*` — set up the mapper for a specific service (translating DataBean fields to service parameters)
- `storeDataBean*srv` — extract the results from the service output and map them back to the DataBean
- `getMsgRep` — resolve message IDs to localized / templated display strings

## Key Methods

### actionInit() → boolean

**Entry point.** Handles the initial screen display for the 050-number porting change page.

1. Acquires screen information and the service form `DataBean` via `JCCWebCommon.getScreenInfo(this)` and `getServiceFormBean()`.
2. Sets the operation service code `B029` (050番番号変更オペレーションサービスコード) onto the DataBean.
3. Calls `setDataInit()` to extract customer contract items (session data, customer ID, service key number, operation service key numbers, transmission division, displacement reason codes, application number, etc.) and populate the form DataBean.
4. Dispatches to `setDataInit_Kaiyaku()` if the transmission division is "解約" — this sets the year/month/day fields for the end-use date and enables the 解約 button.
5. Sets a message banner based on `trans_div`: "050番番号変更の回復" (reactivation) or "050番番号変更の予約取消" (reservation cancellation).
6. Creates and configures a `KKSV0135_KKSV0135OPDBMapper` to map 6 sets of screen-to-service DataBean fields (`setKKSV013501SC` through `setKKSV013506SC`), covering the consent form and optional operation service consent.
7. Calls `doService("KKSV0135", "KKSV0135OP")` to fetch the initial consent/display service data.
8. If the service returns no error (`msgResult == null`), unmapping is done via `getKKSV013501SC`–`getKKSV013506SC` to pull results back into the DataBean.
9. Sets `DSP_STAYMD` (display start date) from `USE_STAYMD`. For non-cancellation paths, it additionally sets `DSP_ENDYMD` (display end date) from the last reservation's `rsv_aply_ymd` if available, otherwise falls back to `USE_ENDYMD`.
10. Dumps the DataBean to the log and returns `true`.

**Side effects:** Populates the session form DataBean with all initial display fields. Sets `outputMap` and `inputMap` via `doService`.

### actionUpd_cfm() → boolean

**Confirmation button handler.** Called when the user submits the change form for confirmation.

1. Reads the end-use date (year, month, day) from the DataBean and concatenates them into a single YYYYMMDD string for both `USE_ENDYMD` and `DSP_ENDYMD`.
2. Calls `setDataDsl()` to set the service charge end date and prepare the aging (billing) information list with the phone-type aging code.
3. Invokes `setMappedKKSV0136(FUNC_CD_2)` — sets up the mapper with check-only mode (not yet registered).
4. Calls `doService("KKSV0136", "KKSV0136OP")` to execute the cancellation confirmation service.
5. Checks for errors via `setErrorMessageInfo(outputMap, "KKSV013601SC")`. If an error is found, it displays `EKB020` (unexpected error) and returns `false`.
6. Stores results via `storeDataBeanDslsrv()`, which maps the service output back to the DataBean through `KKSV0136` mapper's `getOpsvckeiDslCC`.
7. If no DataBean-level error message is set (`ERR_MSG_ID` is empty):
   - Sets the next screen to KKW03205 (confirmation result screen).
   - Displays the success message "050番番号変更の解除".
8. If there is an error message:
   - Uses `getMsgRep()` to resolve the message ID to a displayable string array with placeholders.
   - Displays either a simple message (ID only) or a parameterized message via `JCCWebCommon.setMessageInfo()`.

**Side effects:** Updates `outputMap` with KKSV0136 service results. Sets `NEXT_SCREEN_ID` / `NEXT_SCREEN_NAME` for navigation to KKW03205.

### actionFix() → boolean

**Execution / confirmation button handler.** The most complex method — it dispatches to one of three sub-flows based on `trans_div`:

** cancellation flow (`OP_TRAN_DIV_DSL`):**
1. Calls `setDataDsl()` to populate the DataBean with the end-use date and aging info.
2. Calls `setMappedKKSV0136(FUNC_CD_1)` — mapper in register mode.
3. Calls `doService("KKSV0136", "KKSV0136OP")` to execute the cancellation service.
4. Stores results via `storeDataBeanDslsrv()`.
5. Message: "050番番号変更の解除".

** Reactivation flow (`OP_TRAN_DIV_KAIHK`):**
1. Calls `setDataKaihk()` to set the reactivation date (`KAIHK_YMD` = today) and aging info.
2. Calls `setMappedKKSV0162(FUNC_CD_1)` — mapper for the reactivation service.
3. Calls `doService("KKSV0162", "KKSV0162OP")`.
4. Checks for errors via `setErrorMessageInfo(outputMap, "KKSV016201SC")`.
5. Stores results via `storeDataBeanKaihksrv()` which uses `KKSV0162` mapper's `getOpsvckeiKaihkCC`.
6. Message: "050番番号変更の回復".

** Reservation cancellation flow (`OP_TRAN_DIV_RSV_CL`):**
1. Calls `setDataDslStp()` to set aging info.
2. Calls `setMappedKKSV0163(FUNC_CD_1)` — mapper for the cancellation service.
3. Calls `doService("KKSV0163", "KKSV0163OP")`.
4. Stores results via `storeDataBeanRsvclsrv()` (mapper `KKSV0163`, currently no-op for unmapping).
5. Message: "050番番号変更の予約取消".

After whichever sub-flow runs, if no DataBean error is present, the next screen is set to KKW03206 (completion screen) with the completion message. Otherwise, error messages are displayed via `getMsgRep()`.

### actionShusei() → boolean

**Correction / edit button handler.** Redirects back to the change input screen (KKW03204). No service call — simply sets `NEXT_SCREEN_ID` and `NEXT_SCREEN_NAME` to KKW03204 on the common info bean and returns `true`.

### actionBack() → boolean

**Back button handler.** Returns to the previous screen by reading the current screen ID via `JCCWebCommon.getScreenId(this)` and setting it as the next screen on the common info bean.

### actionFin() → boolean

**Finish button handler.** Similar to `actionBack()` — returns to the original calling screen by setting the current screen ID as the next screen.

### actionClear() → boolean

**Clear button handler.** Resets the form by calling `setDataInit_Kaiyaku()`, which re-initializes the end-use date fields (today's date split into year/month/day) and re-enables the 解約 button. Used to reset the form state during the cancellation flow.

### doService(String usecase_id, String operation_id) → X31CMessageResult

**Core service invocation.** A private method that wraps the base class `invokeService()`:

1. Creates a parameter map with `TELEGRAM_INFO_USECASE_ID` and `TELEGRAM_INFO_OPERATION_ID`.
2. Clears any existing message result list via `clearMessageResultList()`.
3. Creates a new `outputMap`.
4. Calls `invokeService(paramMap, inputMap, outputMap)` — this is inherited from `JCCWebBusinessLogic` and dispatches to the appropriate backend business logic service.
5. If the service executes successfully, returns `null` (normal termination). If an error occurs, returns an `X31CMessageResult` object containing error information.
6. The `outputMap` is populated with the service results for later consumption by store methods.

**Return value semantics:** `null` = success. Non-null `X31CMessageResult` = error / exception.

### setDataInit() → void

**Initial data population.** Extracts customer contract information from the session's `custKeiHktgiList` and populates the service form DataBean with:
- `trans_div` — the operation division (解約/回復/予約取消)
- `ido_div` — displacement division code
- `sys_id` — system ID
- `svc_kei_no` — service key number
- `op_svc_kei_no` — operation service key numbers (array)
- `ido_rsn_list` — displacement reason codes and memos (iterates over all reasons)
- `mskm_no` and `mskm_dtl_no` — application number and detail number
- `UNYO_YMD` and `UNYO_DTM` — operational date and timestamp
- `OP_SVC_CD` — operation service code `B029`
- `TEL_1_TAB_OP_IF_CTL_CD` / `TEL_2_TAB_OP_IF_CTL_CD` — phone number ordering tab control code

### setDataInit_Kaiyaku() → void

**Initial data for cancellation flow.** Sets the today date into `USE_ENDYMD_YEAR`, `USE_ENDYMD_MON`, `USE_ENDYMD_DAY` and enables the 解約 view flag (`DSL_VIEW_ENABLE_FLG`). Called from `actionInit` when `trans_div == DSL` and from `actionClear`.

### setDataDsl() → void

**Data setup for cancellation.** Sets `SVC_CHRG_ENDYMD` to the end-use date and populates the aging info list with a single entry: aging type `001` (phone) and aging target value from `HRADSI_050_NO`.

### setDataKaihk() → void

**Data setup for reactivation.** Sets `KAIHK_YMD` (reactivation date) to today and populates the aging info list identically to `setDataDsl()`.

### setDataDslStp() → void

**Data setup for reservation cancellation.** Only populates the aging info list (same aging type and target as the other two). Does not set a date field.

### storeDataBeanDslsrv(X31SDataBeanAccess[] paramBean, HashMap<String, Object> outputMap) → void

Maps KKSV0136 (cancellation) service output back to the DataBean via `KKSV0136_KKSV0136OPDBMapper.getOpsvckeiDslCC()`.

### storeDataBeanKaihksrv(X31SDataBeanAccess[] paramBean, HashMap<String, Object> outputMap) → void

Maps KKSV0162 (reactivation) service output back to the DataBean via `KKSV0162_KKSV0162OPDBMapper.getOpsvckeiKaihkCC()`.

### storeDataBeanRsvclsrv(X31SDataBeanAccess[] paramBean, HashMap<String, Object> outputMap) → void

Maps KKSV0163 (reservation cancellation) service output back to the DataBean. Currently the mapper call is commented out, indicating either the unmapping is handled elsewhere or this is a placeholder for future functionality.

### setMappedKKSV0136(String func_cd) → void

Configures the `KKSV0136` mapper for the cancellation service. Maps fields: `KKSV0136WORK`, `OpsvckeiDslCC`, `JKKHakkoSODCC`, and `KKSV013601SC` (error check flag).

### setMappedKKSV0162(String func_cd) → void

Configures the `KKSV0162` mapper for the reactivation service. Maps fields: `OpsvckeiKaihkCC`, `JKKHakkoSODCC`, `KKSV0162WORK`, and `KKSV016201SC` (error check flag).

### setMappedKKSV0163(String func_cd) → void

Configures the `KKSV0163` mapper for the reservation cancellation service. Maps fields: `OpSvcKeiCnslCC`, `KKSV0163WORK`, `JKKHakkoSODCC`, and `KKSV016302CC` (input support work update).

### getMsgRep(String trandiv, String rtn_msg_id) → String[]

**Message resolution.** Converts backend message IDs to user-displayable string arrays with placeholders filled in. Handles different message codes depending on the operation division:

| Message ID | Division | Display String Array |
|---|---|---|
| `EKB5440-JW` | 解約 | ["休止中", "未来日指定の解約は"] |
| `EKB0270-NW` | 解約 | ["利用終了日", "運用日+60日", "日付"] |
| `EKB0690-NW` | 解約 | ["利用終了日", "過去"] |
| `EKB5440-JW` | 回復 | ["回復可能期間外", "回復は"] |

Returns `null` if no substitution text is needed (the caller will display the message ID directly).

### setErrorMessageInfo(HashMap<String, Object> outputMap, String key) → boolean

**Error detection helper.** Checks the service output for an error indicator. Looks up the specified key (e.g. `"KKSV013601SC"`) in the output map, then checks if `chk_kbn == "1"`. If so, displays a generic error message `EKB020` and returns `true` (error found). Otherwise returns `false`.

## Relationships

```mermaid
flowchart TD
    Sub1["WEBGAMEN_KKW032040PJP"]
    Sub2["WEBGAMEN_KKW032050PJP"]
    Sub3["WEBGAMEN_KKW032060PJP"]
    Sub4["x31business_logic_KKW03204SF"]
    KKW["KKW03204SFLogic"]
    Parent["JCCWebBusinessLogic"]

    Sub1 --> KKW
    Sub2 --> KKW
    Sub3 --> KKW
    Sub4 --> KKW

    KKW --> Parent
```

**Inbound (4 dependents):**
- **WEBGAMEN_KKW032040PJP.xml** — The initial input/change screen. This presentation class invokes `actionInit()`, `actionUpd_cfm()`, and `actionBack()`.
- **WEBGAMEN_KKW032050PJP.xml** — The confirmation result screen. Invokes `actionFix()` and `actionShusei()`.
- **WEBGAMEN_KKW032060PJP.xml** — The completion screen. Invokes `actionFin()` and `actionBack()`.
- **x31business_logic_KKW03204SF.xml** — The business logic configuration that wires the logic class into the framework's service invocation pipeline.

**Outbound (1 dependency):**
- **JCCWebBusinessLogic** — Base class providing `invokeService()`, `getServiceFormBean()`, `getCommonInfoBean()`, `getScreenInfo()`, `clearMessageResultList()`, `dumpDatabean()`, and core framework infrastructure.

## Flow of Execution

```mermaid
flowchart TD
    User["User / Browser"]
    Init["actionInit"]
    UpdCfm["actionUpd_cfm"]
    Fix["actionFix"]
    Shusei["actionShusei"]
    Back["actionBack"]
    Fin["actionFin"]
    Clear["actionClear"]

    User --> Init
    User --> UpdCfm
    User --> Fix
    User --> Shusei
    User --> Back
    User --> Fin
    User --> Clear

    Init --> SetInit["setDataInit"]
    Init --> Svc0135["KKSV0135 service"]

    UpdCfm --> Map0136["setMappedKKSV0136"]
    UpdCfm --> DoSvc136["doService"]
    UpdCfm --> Svc136["KKSV0136"]
    UpdCfm --> StoreDsl["storeDataBeanDslsrv"]
    UpdCfm --> ErrInfo["setErrorMessageInfo"]

    Fix --> Dsl["setDataDsl"]
    Fix --> Kaihk["setDataKaihk"]
    Fix --> DslStp["setDataDslStp"]

    Fix --> Map0136
    Fix --> Map0162["setMappedKKSV0162"]
    Fix --> Map0163["setMappedKKSV0163"]

    Fix --> DoSvc136
    DoSvc136 --> Svc136
    DoSvc136 --> Svc162["KKSV0162"]
    DoSvc136 --> Svc163["KKSV0163"]

    Fix --> StoreDsl
    Fix --> StoreKaihk["storeDataBeanKaihksrv"]
    Fix --> StoreRsvcl["storeDataBeanRsvclsrv"]
    Fix --> ErrInfo

    Shusei --> Back
    Fin --> Back
    Clear --> SetInitKai["setDataInit_Kaiyaku"]
```

## Usage Example

A typical user journey through the 050-number porting change workflow:

1. **Initial display:** The presentation class `WEBGAMEN_KKW032040PJP` calls `actionInit()`. The logic class reads the customer's contract data from the session, determines the operation division (`trans_div`), calls the KKSV0135 service to fetch consent information, and returns the populated DataBean to the view for rendering.

2. **Confirmation:** The user edits fields (e.g., end-use date) and presses the "confirm" button. `WEBGAMEN_KKW032040PJP` calls `actionUpd_cfm()`. The logic class validates the data, calls KKSV0136 in check mode, and either returns to the same screen with an error or navigates to `KKW03205` (the confirmation display screen).

3. **Execution:** On the confirmation screen, the user presses "confirm" (確定). `WEBGAMEN_KKW032050PJP` calls `actionFix()`. Based on `trans_div`, the logic class dispatches to one of three paths:
   - **Cancellation:** KKSV0136 in register mode → navigate to `KKW03206` with success message
   - **Reactivation:** KKSV0162 in register mode → navigate to `KKW03206` with success message
   - **Reservation cancellation:** KKSV0163 in register mode → navigate to `KKW03206` with success message

4. **Completion:** On the completion screen `KKW03206`, the user can either go back or finish. `WEBGAMEN_KKW032060PJP` calls `actionBack()` (return to previous screen) or `actionFin()` (return to origin screen).

## Notes for Developers

- **Thread safety:** This class is **not thread-safe**. It maintains mutable instance state (`inputMap`, `outputMap`, `trans_div`) that is set and read within a single request. Each HTTP request creates a new instance (or reuses a short-lived scope), so concurrent access to the same instance should not occur under normal framework operation.

- **trans_div as routing key:** The `trans_div` field is set once during `actionInit` / `setDataInit` from the customer contract data and is subsequently used to dispatch all three action paths (`actionFix` sub-flows). Never modify `trans_div` after initial population — it drives all branching logic.

- **Service return convention:** `doService()` returns `null` on success and a non-null `X31CMessageResult` on error. However, business-level errors are also communicated via `ERR_MSG_ID` in the DataBean (checked in `actionUpd_cfm` and `actionFix` via `getMsgRep`). This dual error path means callers must check both the return value and the DataBean error fields.

- **Error check via `chk_kbn`:** The `setErrorMessageInfo` method (added in OM-2015-0000564) provides an additional error detection layer by inspecting the `chk_kbn` field in the service output map. If `chk_kbn == "1"`, a generic `EKB020` message is displayed and the action short-circuits. This is only used for KKSV0136 and KKSV0162 currently, not KKSV0163.

- **Aging info list duplication:** Each of `setDataDsl`, `setDataKaihk`, and `setDataDslStp` independently creates the aging info list entry (aging type `001` for phone, target value from `HRADSI_050_NO`). If the same DataBean instance is reused across steps, this could cause duplicate aging entries. The null-check on `aging_info_list.getCount() == 0` protects against this.

- **storeDataBeanRsvclsrv is a stub:** The KKSV0163 store method currently has the unmapping call commented out. This means reservation cancellation results are not fully populated back into the DataBean — likely intentional if the completion screen does not need to display service-specific data, but worth confirming before modifying.

- **Hardcoded constants:** The class defines several constants with Japanese comments (application type code, service reason code, aging type, process state code, etc.). These are framework-specific values and should not be changed without consulting the business specification. The operation service code `B029` is the 050-number porting service identifier.

- **Message ID routing:** The `getMsgRep` method uses a chain of `if` statements to match message IDs against known patterns. New error conditions require adding new branches and must be added for the correct `trans_div` (解約 or 回復) to ensure the substitution text is only applied in the relevant context.

- **DataBean logging:** Every public action method logs the full DataBean state via `JSYwebLog.println(JSYwebLog.DataBean_Dump, getClass(), dumpDatabean(), ...)`. This is useful for debugging but can generate significant log output — ensure the log level is appropriate in production.

- **Framework dependencies:** The class relies on the JCC framework's message infrastructure (`JCCWebCommon.setMessageInfo`, `JPCOnlineMessageConstant`), DataBean access patterns, and mapper classes (`KKSV0135_*`, `KKSV0136_*`, `KKSV0162_*`, `KKSV0163_*`). All mappers are instantiated locally within each method call, not cached as instance fields.