# FUW02501SFLogic

## Purpose

`FUW02501SFLogic` is the central business-logic controller for the **Home Page Access Analysis Service Application** workflow in a KCP (KDDI enterprise) web system. It orchestrates the full user journey: displaying the application screen with current contract and pricing information (initial display), processing the user's confirmation (check), and executing the actual service application (submit) — followed by customer refresh and a completion-notification email. In short, it is the single orchestrator that ties together service data retrieval, remote service invocation, pricing/billing decisions, and screen navigation for this subscription-signup flow.

## Design

This class follows the **Front Controller / Web Action Handler** pattern, extending `JCCWebBusinessLogic`. It is the business-layer counterpart to a web-view screen (screen ID `FUW02501`). Each public method (`init`, `cfm`, `mskm`, `back`) acts as an entry point invoked by the web framework in response to a specific user action on the page. The class acts as a **facade** over multiple underlying services:

- **Service invocation**: Calls remote SC/CC (Service Component / Cross-Component) handlers via `FUSV0069` (initial display) and `FUSV0070` (submission) mappers, invoking `invokeService()` from the parent class.
- **Data extraction**: Peels apart the shared `X31SDataBeanAccess` commoninfo bean tree (SSO info, current customer contract, service contract, option service contract) into a flat map for convenient consumption.
- **Billing logic**: Computes whether the application is paid or free, whether mansion-type contracts apply, and whether initial costs exist.
- **Screen routing**: Sets `NEXT_SCREEN_ID` and `NEXT_SCREEN_NAME` on the commoninfo bean to control the next page the user sees.

### Class Diagram

```
classDiagram
    class FUW02501SFLogic {
        -String EKK0411D010
        -String OP_SVC_KEI_NO
        -String USECASE_ID_FUSV0069
        -String USECASE_ID_FUSV0070
        -String SC_TITLE_FUSV006902
        -String CC_TITLE_FUSV006901
        -String EKK0601B001_LIST
        -String EKK0721A010_LIST
        -String UPD_DTM_BF
        -String SBOP_SVC_KEI_CNT
        -String PPLAN_KOTEI_AMNT
        -String MSKM_COMP_MAIL_ID
        +boolean init()
        +boolean cfm()
        +boolean mskm()
        +boolean back()
        +boolean chkPayKoteiTanka(Map)
        +boolean chkPayInitialCost(Map)
        -void checkSvcData(Map)
        -X31SDataBeanAccess getX31SDataBeanAccess(X31SDataBeanAccess, String)
        -boolean getMansionDiv(X31SDataBeanAccess, X31SDataBeanAccess, Map)
        -String getPrcGrpCd(X31SDataBeanAccess)
        -Map~String, Object~ getCommoninfoBeanInfo(X31SDataBeanAccess)
        -void execute(X31SDataBeanAccess, String)
        -void checkException(JCCWebServiceException)
        -boolean setPayFlg(X31SDataBeanAccess, Map, int)
    }
    FUW02501SFLogic --|> JCCWebBusinessLogic
```

## Key Methods

### `init()` — Initial Display

```java
public boolean init() throws Exception
```

This is the primary entry point, invoked when the user first loads the Home Page Access Analysis Service Application screen. It performs a large amount of setup in a single method:

1. **Extracts shared data** from `commoninfoBean` via `getCommoninfoBeanInfo()`, pulling out SSO info, current customer contract info, service contract info, and option service contract info.
2. **Validates** the option service contract data exists and has valid URL fields via `checkSvcData()`. If validation fails, a `JCCBusinessException` with error code `0102` (contract state error) is thrown.
3. **Invokes the initial-display service** (`FUSV0069`) through four mapper calls:
   - `FUSV006901SC` — Business parameter management (obtains the MY Home Page URL protocol).
   - `FUSV006902SC` — Fixed unit price list (application fee).
   - `FUSV006903SC` — Cost course / maximum subscription service contract count.
   - `FUSV006901CC` — Initial cost list.
4. **Computes billing flags**:
   - `setPayFlg()` determines if the application is paid (no free quota remaining and fixed unit price exists).
   - `getMansionDiv()` determines if the contract is a "mansion (all-unified) with payment" type.
5. **Configures the pricing area** on the form bean: if free, sets basic fee info; then populates the pricing display area via `JFUWebCommon.setPrcInfoArea()`.
6. **Sets context data**: current WEB ID, current Home Page URL (protocol + domain + account).
7. **Sets navigation**: `NEXT_SCREEN_ID` and `NEXT_SCREEN_NAME` to the current screen (`FUW02501`), indicating this is the first page in a multi-screen flow.

Returns `true` unconditionally. Throws `JCCBusinessException` with error code `0002` on service invocation failure.

### `cfm()` — Confirmation (Check Button)

```java
public boolean cfm() throws Exception
```

Invoked when the user clicks the **confirmation button** on the initial display screen. This prepares the data for the confirmation screen by calling:

1. `execute(commoninfoBean, JPCModelConstant.FUNC_CD_2)` — runs the submission service pipeline with `FUNC_CD_2` (check mode).
2. Sets `NEXT_SCREEN_ID` and `NEXT_SCREEN_NAME` to `FUW02502` (the confirmation screen).

Returns `true`. The `execute()` method is the shared workhorse for both check and submit modes.

### `mskm()` — Submit (Application Button)

```java
public boolean mskm() throws Exception
```

Invoked when the user clicks the **application/submit button**. This is the point of no return:

1. Runs frontend + backend common-relation checks via `JFUWebCommon.checkCommonRelation(this, USECASE_ID_FUSV0070)`.
2. Calls `execute(commoninfoBean, JPCModelConstant.FUNC_CD_1)` — runs the submission service pipeline with `FUNC_CD_1` (actual submit mode).
3. Refreshes the current customer info via `JFUWebCommon.refreshGenCustKei(this)`.
4. Sends a completion notification email via `JFUWebCommon.sendMskmFinMail(this, MSKM_COMP_MAIL_ID)` (mail template ID `FUW025_1`).
5. Sets navigation to `FUW02503` (the completion screen).

Returns `true`.

### `back()` — Back Button

```java
public boolean back() throws Exception
```

A simple method invoked when the user clicks **back** from the confirmation or submission flow. It resets the navigation to the initial screen (`FUW02501`) and returns `true`. No service calls or data processing occur.

### `checkSvcData(Map<String, Object> resultMap)` — Service Data Validation

```java
private void checkSvcData(Map<String, Object> resultMap)
```

Validates that the option service contract data is present and well-formed. Checks:
- The `opSvcKeiInfoBean` is not null (throws error code `0102` — contract state error if null).
- The URL domain and URL account fields are both non-null (throws error code `0102` if either is null).

This prevents null-pointer issues downstream and ensures the user has a valid contract before proceeding.

### `getCommoninfoBeanInfo(X31SDataBeanAccess commoninfoBean)` — Bean Extraction

```java
private Map<String, Object> getCommoninfoBeanInfo(X31SDataBeanAccess commoninfoBean)
```

This is the most complex private method (lines 391–520). It extracts and filters a rich tree of data beans from the shared context into a flat `Map<String, Object>`:

1. **SSO Info**: Extracts from `webChgInfoBean -> ssoInfoBean`. Validates that `WEB_ID_21` is set; throws error code `0002` (system error) if absent.
2. **Current Customer Contract Info**: Extracts from `webChgInfoBean -> genCustKeiInfoBean`.
3. **Service Contract Info**: Extracts from `genCustKeiInfoBean -> svcKeiInfoBean`.
4. **Service Contract Details**: Extracts nested `svcKeiUcwkInfoBean`.
5. **Billing Contract Info**: Extracts `seikyKeiInfoBean`.
6. **Option Service Contract (filtered)**: Iterates the `opSvcKeiInfoArray`, matching contracts where:
   - Status is `020` (approved), `030` (completed), or `100` (in service).
   - WEB ID matches the user's SSO WEB ID and service code is `B002` (MY Home Page).
7. **Subscription Service Contract (filtered)**: If the option service contract was found, iterates `sbopSvcKeiInfoArray`, counting contracts where:
   - Service code is `D05` (Home Page Access Analysis).
   - Status is NOT `910` (terminated) or `920` (cancelled).
   - Option service contract number matches the parent option service contract number.

Returns a map containing: `SYSID_21`, `WEB_ID_21`, `SSO_INFO`, `GEN_CUST_KEI_INFO`, `SVC_KEI_INFO`, `SVC_KEI_UCWK_INFO`, `SEIKY_KEI_INFO`, `OP_SVC_KEI_INFO`, `SBOP_SVC_KEI_INFO`, `SBOP_SVC_KEI_CNT` (the count from step 7).

### `execute(X31SDataBeanAccess commoninfoBean, String funcCd)` — Shared Submission Pipeline

```java
private void execute(X31SDataBeanAccess commoninfoBean, String funcCd) throws Exception
```

The core workhorse called by both `cfm()` and `mskm()`. It runs the full application submission service pipeline:

1. Extracts the same shared data beans as `init()` (SSO, current customer, service contract, option service contract, billing contract).
2. Sets up the use case ID `FUSV0070` (submission service).
3. Builds a `FUSV0070_FUSV0070OPDBMapper` and configures seven service components:
   - `FUSV007001SC` — Application content acceptance registration (`EKK0011D020`).
   - `FUSV007002SC` — Subscription service contract `<ISP>` registration (`EKK0411D010`).
   - `FUSV007003SC` — Subscription service contract `<ISP>` approval completion (`EKK0411C040`).
   - `FUSV007004SC` — Subscription service contract `<ISP>` start of use (`EKK0411C050`).
   - `FUSV007005SC` — Progress registration (`EKK1091D010`).
   - `FUSV007006SC` — Application detail approval / follow-up task request (`EKK0021C060`).
   - `FUSV007007SC` — Subscription service contract `<ISP>` approval (`EKK0411C020`).
4. Also configures two CC (cross-component) calls:
   - `FUSV007001CC` — Service IF result data transfer (`JFUTransferCC`).
   - `FUSV007002CC` — Service order issuance (`JKKHakkoSODCC`).
5. Sets the option service contract status for MY Home Page via `JFUWebCommon.setOpSvcKeiStatMyHp()`.
6. Invokes `invokeService(paramMap, dataMap, outputMap)`. On `JCCWebServiceException`, delegates to `checkException()`.

### `checkException(JCCWebServiceException se)` — Error Translation

```java
private void checkException(JCCWebServiceException se)
```

Interprets service-layer exceptions and maps them to user-friendly business errors:

- If the error status is `RELATION_ERR` (related check failure) and the template ID is `EKK0411D010` (option service contract registration):
  - If error flag is `EG` (already contracted) and item is `op_svc_kei_no`: throws error code `0103` (already contracted).
  - If error flag is `EA` (update impossible) and item is `upd_dtm_bf`: throws error code `0204` (cannot update — likely a row-locking/version mismatch).
- Any other exception is re-thrown as error code `0002` (system error).

### `setPayFlg(...)` — Billing Flag Calculation

```java
private boolean setPayFlg(X31SDataBeanAccess bean, HashMap<String, Object> outputMap, int keiCnt)
```

Determines whether the application will be a **paid** transaction. The logic:

1. Gets `hpAcsMryoCnt` (free usage count for Home Page Access Analysis) from the service form bean.
2. Computes remaining free count: `mryoCnt = hpAcsMryoCnt - keiCnt` (where `keiCnt` is the number of existing subscription service contracts for this option).
3. If `chkPayKoteiTanka()` returns `true` (a fixed unit price exists) AND `mryoCnt <= 0` (no free quota remaining): returns `true` (paid).
4. Otherwise: returns `false` (free/no payment).

### `chkPayKoteiTanka(HashMap<String, Object> outputMap)` — Fixed Unit Price Check

```java
public boolean chkPayKoteiTanka(HashMap<String, Object> outputMap)
```

Checks whether a **fixed unit price** (application fee) exists that is greater than 0. Scans the `SC_TITLE_FUSV006902` parent map, retrieves the `EKK0601B001_LIST` child list, and if any entry has `PPLAN_KOTEI_AMNT > 0`, returns `true`.

Note: due to the loop structure, if multiple child entries exist, the result is determined by the **last** entry processed.

### `chkPayInitialCost(HashMap<String, Object> outputMap)` — Initial Cost Check

```java
public boolean chkPayInitialCost(HashMap<String, Object> outputMap)
```

Checks whether **initial costs** exist. Scans the `CC_TITLE_FUSV006901` parent map; if the `EKK0721A010_LIST` child list is non-empty, returns `true`. This is used in `getMansionDiv()` to determine mansion-type display.

### `getMansionDiv(...)` — Mansion (All-Unified) Type Check

```java
private boolean getMansionDiv(X31SDataBeanAccess bean, X31SDataBeanAccess commoninfoBean, HashMap<String, Object> outputMap)
```

Determines if the user's contract is a **mansion (all-unified) type with payment**. Returns `true` if all three conditions hold:
1. Price group code is `"04"` (mansion type).
2. Contracted payment method code is `"003"` (all-unified).
3. Payment flag is set OR initial costs exist.

This value is displayed on the screen to provide context-specific UI control.

### `getPrcGrpCd(X31SDataBeanAccess commoninfoBean)` — Price Group Code Extraction

```java
private String getPrcGrpCd(X31SDataBeanAccess commoninfoBean)
```

Iterates the nested bean hierarchy: `webChgInfo -> genCustKeiInfo[i] -> svcKeiInfo[j]`, extracting the `PRC_GRP_CD_23` (price group code) from each service contract entry. Returns the code from the last entry processed.

### `getX31SDataBeanAccess(X31SDataBeanAccess bean, String componentID)` — Safe Bean Retrieval

```java
private X31SDataBeanAccess getX31SDataBeanAccess(X31SDataBeanAccess bean, String componentID)
```

Helper that safely retrieves (or creates) a data bean at a given component ID path. If the bean at index 0 does not exist, it creates one. This is used in `getPrcGrpCd()` to ensure the `WEB_CHG_INFO` path is populated.

## Relationships

### Who Uses This Class (4 dependents)

The class is referenced by 4 XML configuration files, indicating it is wired into multiple screens:

```mermaid
flowchart TD
    subgraph Consumers["Web Pages (Consumers)"]
        FUW02501["FUW02501 - Initial Display"]
        FUW02502["FUW02502 - Confirmation"]
        FUW02503["FUW02503 - Completion"]
        BizLogic["x31business_logic_FUW02501SF"]
    end

    subgraph Logic["Business Logic"]
        FUW02501SFLogic["FUW02501SFLogic"]
    end

    subgraph Framework["Framework / Dependencies"]
        JCCWebBL["JCCWebBusinessLogic"]
        FUSV0069["FUSV0069 - Initial Display SC/CC"]
        FUSV0070["FUSV0070 - Submission SC/CC"]
    end

    FUW02501 -->|"invoke init()"| FUW02501SFLogic
    FUW02502 -->|"invoke cfm()"| FUW02501SFLogic
    FUW02503 -->|"invoke mskm()"| FUW02501SFLogic
    BizLogic -->|"reference"| FUW02501SFLogic

    FUW02501SFLogic -->|"extends"| JCCWebBL
    FUW02501SFLogic -->|"calls FUSV0069 SC/CC"| FUSV0069
    FUW02501SFLogic -->|"calls FUSV0070 SC/CC"| FUSV0070
```

- **WEBGAMEN_FUW025010PJP.xml**: The initial display screen handler that invokes `init()`.
- **WEBGAMEN_FUW025020PJP.xml**: The confirmation screen handler that invokes `cfm()`.
- **WEBGAMEN_FUW025030PJP.xml**: The completion screen handler that invokes `mskm()`.
- **x31business_logic_FUW02501SF.xml**: Business logic configuration wiring.

### Outbound Dependencies

- **`JCCWebBusinessLogic`** (extends): The parent class provides `getCommonInfoBean()`, `getServiceFormBean()`, `invokeService()`, and the overall web action framework.

## Usage Example

The typical calling pattern for this class is:

1. A user navigates to the Home Page Access Analysis Service Application page. The web framework instantiates `FUW02501SFLogic` and calls **`init()`**.
2. `init()` extracts the user's contract data, invokes the initial-display service (`FUSV0069`), computes billing flags, and configures the form bean with pricing and contract information.
3. The user reviews the screen and clicks **confirmation**. The framework calls **`cfm()`**, which invokes the submission service pipeline in check mode (`FUNC_CD_2`) and navigates to the confirmation screen (`FUW02502`).
4. The user reviews and clicks **submit**. The framework calls **`mskm()`**, which runs the full submission pipeline in submit mode (`FUNC_CD_1`), refreshes customer data, sends a completion email, and navigates to the completion screen (`FUW02503`).
5. If the user clicks **back** at any point, the framework calls **`back()`** to return to the initial screen.

## Notes for Developers

- **Screen flow**: This class drives a 3-screen flow: `FUW02501` (initial) -> `FUW02502` (confirmation) -> `FUW02503` (completion). The `back()` method always returns to `FUW02501`. The initial screen sets `NEXT_SCREEN_ID` to itself as a standard convention for the first screen in a flow.
- **Thread safety**: The class has no instance state beyond what is inherited from `JCCWebBusinessLogic`. Each request appears to get a fresh instance, so the class is effectively stateless and thread-safe for typical web request handling.
- **Error handling**: Service-layer exceptions (`JCCWebServiceException`) are caught in `execute()` and translated by `checkException()` into business errors. The `init()` method catches them and re-throws as a generic `JCCBusinessException` with code `0002` (system error) without the detailed error translation. This is a notable asymmetry: submit-mode errors get nuanced translation (`0103`, `0204`), but initial-display errors do not.
- **Contract state filtering**: `getCommoninfoBeanInfo()` does significant filtering of option service contracts by status (`020`, `030`, `100`) and matches by WEB ID. Only the matching contract is used downstream. Be cautious when modifying this logic, as it implicitly governs which user contracts are visible.
- **Loop-late-return in `chkPayKoteiTanka`**: The method iterates a list of price entries and overwrites the result each time. The final value depends on the last entry in the list, which may or may not be intentional. If multiple fixed-price entries can exist, this may mask edge cases.
- **`mskm()` emails**: The completion email is sent with template ID `FUW025_1`. If email delivery is critical to the business process, verify error handling around `sendMskmFinMail()` — the method does not appear to have a try/catch in `mskm()`, so a mail-send failure could cause the entire submission to fail.
- **`FUNC_CD_1` vs `FUNC_CD_2`**: In `execute()`, `FUNC_CD_1` is used for actual submission (`mskm()`) and `FUNC_CD_2` for confirmation/check (`cfm()`). The mapper methods use this code to differentiate behavior in the underlying SC/CC handlers.
- **Constants are all `private static final String`**: There is no configuration mechanism; all behavior is hardcoded via string constants. Changes to contract status codes, service codes, or template IDs require code changes.
- **`getPrcGrpCd()` returns the last entry's code**: The nested loop overwrites `prcGrpCd` on each iteration and returns the final value. If multiple service contracts exist, only the last one's price group code is used — verify this is the intended semantics.
