# FUW02401SFLogic

## Purpose

`FUW02401SFLogic` is the central web-view business logic class for **myHP (personal home page) URL reservation and service registration** in the K-Opticom system. It handles the complete lifecycle of a user reserving and confirming a custom URL (like `xxx.k-opticom.co.jp`) — from the initial page load (displaying available reservation slots and pre-set values), through confirmation, to final submission which triggers a completion email.

## Design

This class follows the **web business logic tier** pattern common in the Fujitsu Futurity JCC web framework. It extends `JCCWebBusinessLogic` (the framework's base class for view-side business logic) and sits above the data access/mapper layer. The class acts as an **orchestrator**: it gathers user session data, delegates to domain-specific mappers for database query preparation, invokes the underlying service layer via `invokeService()`, and then post-processes results for display.

The class operates across a three-step screen flow:

| Step | Screen | Entry Method | Outcome |
|------|--------|-------------|---------|
| 1 | FUW02401 | `init()` | Display the URL reservation page with pre-populated data |
| 2 | FUW02402 | `cfm()` | Confirm and submit the reservation details |
| 3 | FUW02403 | `mskm()` | Finalize the reservation and send a completion email |

The class also supports a `back()` method allowing the user to return to the initial page from either the confirmation or final step.

## Relationships

```mermaid
flowchart TD
    XML1["WEBGAMEN_FUW024010PJP"] --> Logic["FUW02401SFLogic"]
    XML2["WEBGAMEN_FUW024020PJP"] --> Logic
    XML3["WEBGAMEN_FUW024030PJP"] --> Logic
    XML4["x31business_logic_FUW02401SF"] --> Logic
    Logic --> Parent["JCCWebBusinessLogic"]
```

### Inbound (4 dependencies)

- **WEBGAMEN_FUW024010PJP.xml** — Route configuration for the initial URL reservation page (FUW02401). Invokes `init()`.
- **WEBGAMEN_FUW024020PJP.xml** — Route configuration for the confirmation page (FUW02402). Invokes `cfm()`.
- **WEBGAMEN_FUW024030PJP.xml** — Route configuration for the mail-completion page (FUW02403). Invokes `mskm()`.
- **x31business_logic_FUW02401SF.xml** — Business logic routing/configuration that wires this class into the broader x31 business framework.

### Outbound (1 dependency)

- **JCCWebBusinessLogic** — The framework base class providing shared methods like `getCommonInfoBean()`, `getServiceFormBean()`, and `invokeService()`.

### Internal Dependencies

The class also uses several mapper classes and framework utilities:
- `FUSV0024_FUSV0024OPDBMapper` — For the init step's database query preparation (FUSV0024 use case).
- `FUSV0025_FUSV0025OPDBMapper` — For the cfm/mskm steps' database query preparation (FUSV0025 use case).
- `JFUWebCommon` — Shared web utility methods (null checks, free price info, screen IDs, email sending).
- `JFUCommonRelationCheck` — Common relation validation utility.

## Key Methods

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

**Lines 121-310**

This is the entry point for the URL reservation page. It initializes all display data for the user.

1. **Validates session data** — Retrieves the common info bean and drills into the SSO info to get the user's `webid`. Throws `ERROR_CODE_0002` if the SSO WebID is missing.
2. **Traverses the data bean hierarchy** — Navigates from `commoninfoBean` -> `webChgInfoBean` -> `ssoInfoBean` -> `genCustKeiInfoBean` -> `svcKeiInfoBean` -> `svcKeiUcwkInfoBean` to reach operational service info.
3. **Filters operational service accounts** — Iterates through the `OP_SVC_KEI_INFO` array, skipping accounts that:
   - Don't have operational service code `CD00136_B002` (i.e., non-myHP accounts).
   - Have status `910` (canceled) or `920` (termination).
   - Don't match the user's SSO WebID.
4. **Validates the WebID was found** — If no matching operational service account is found, throws `ERROR_CODE_0102`.
5. **Creates and configures the form bean** — Sets the current WebID into the service form bean via `FUW02401SFConst.NOW_WEB_ID`.
6. **Invokes the mapper chain** — Creates `FUSV0024_FUSV0024OPDBMapper` and calls its `set` methods to prepare SQL parameters:
   - `setFUSV002401SC` — Service charge table data preparation.
   - `setFUSV002402SC` — Mail address data preparation.
   - `setFUSV002403SC` — URL account reservation data preparation.
   - `setFUSV002404SC` — Free price reservation table preparation.
   - `setFUSV002401CC` — Confirmation charge data preparation.
7. **Invokes the service layer** — Calls `invokeService(paramMap, dataMap, outputMap)` to execute the actual database operations.
8. **Validates business constraints** — Checks that the maximum operational service count is non-zero, present, and that the user hasn't exceeded their URL account limit. Throws `ERROR_CODE_0002` (system error) or `ERROR_CODE_0103` (max URL limit exceeded).
9. **Sets initial display settings** — Calls `setShokiSettei()` to compute mansion flag, payment flag, and free pricing information.
10. **Configures the next screen** — Sets `NEXT_SCREEN_NAME` and `NEXT_SCREEN_ID` to point to screen `FUW02402` (the confirmation page).

**Returns:** `true` on success.

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

**Lines 319-335**

Handles the **confirmation step** — the user has reviewed their reservation details and clicked "confirm."

1. Retrieves the common info bean.
2. Delegates to `cfmMskmSyori(CHEK_CFM, commoninfoBean)` — the shared processing method (see below) that validates the data against the **FUSV0025** use case.
3. Sets the next screen to `FUW02402` (stays on the confirmation screen).

**Returns:** `true` on success.

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

**Lines 344-366**

Handles the **finalization step** — the reservation is being submitted and a completion email should be sent.

1. **Validates common relations** — Calls `JFUCommonRelationCheck.checkCommonRelation(this, USECASE_ID_FUSV0025)` to check referential integrity.
2. Retrieves the common info bean.
3. Delegates to `cfmMskmSyori(CHEK_MSKM, commoninfoBean)` — processes with the MSKM (mail) check flag, meaning it will validate data and handle specific error codes for the final submission path.
4. **Sends the completion email** — Calls `JFUWebCommon.sendMskmFinMail(this, MSKM_FIN_MAIL_FUW024_1)` to dispatch a "reservation complete" email using template `FUW024_1`.
5. Sets the next screen to `FUW02403` (the completion/confirmation receipt page).

**Returns:** `true` on success.

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

**Lines 375-389**

Allows the user to navigate back to the initial page (FUW02401) from either the confirmation or final step.

Simply retrieves the common info bean and sets the next screen to point back to screen `FUW02401`. No additional processing or data validation is performed.

**Returns:** `true` on success.

### `private void checkException(JCCWebServiceException se, String isTarget)`

**Lines 397-475**

A **fine-grained error classifier** that translates low-level `JCCWebServiceException` exceptions into specific application error codes based on:
- Which check path is active (`isTarget` = `"cfm"` or `"mskm"`).
- The exception's `templateid`, `itemid`, `errFlg`, and `status` metadata.

The method extracts detailed error information from the exception's `MessageMoreInfo` list (expecting at least one entry). It then applies conditional logic:

| Path | Template | Item | Error Flag | Action |
|------|----------|------|------------|--------|
| CFM | EKK0361C050 | URL_DOMAIN | EB | Re-throw original exception |
| CFM | EKK0361C050 | URL_ACCOUNT | EA | Re-throw original exception |
| CFM | EZM0111D010 | AGING_TG_VALUE | EA | Re-throw original exception |
| CFM | EKK0361C050 | UPD_DTM_BF | EA | Throw `ERROR_CODE_0204` (outdated data) |
| MSKM | EKK0361C050 | URL_DOMAIN | EB | Throw `ERROR_CODE_0101` (URL reservation error) |
| MSKM | EKK0361C050 | URL_ACCOUNT | EA | Throw `ERROR_CODE_0204` (outdated data) |
| MSKM | EZM0111D010 | AGING_TG_VALUE | EA | Throw `ERROR_CODE_0204` (outdated data) |
| MSKM | EKK0361C050 | UPD_DTM_BF | EA | Throw `ERROR_CODE_0204` (outdated data) |

If none of the specific cases match, a generic `ERROR_CODE_0002` (system error) is thrown.

**Note:** This method assumes `moreInfo[0]` exists — if the array is empty, it will throw an `ArrayIndexOutOfBoundsException` wrapped in the catch block.

### `private void cfmMskmSyori(String isTarget, X31SDataBeanAccess commoninfoBean) throws Exception`

**Lines 485-658**

This is the **shared processing workhorse** called by both `cfm()` and `mskm()`. It performs a full round-trip to validate and persist the user's URL reservation. The method closely mirrors `init()` but uses a different mapper and use case ID.

1. **Retrieves session data** — Same bean traversal as `init()` to get SSO WebID and operational service info.
2. **Filters operational service accounts** — Identical filtering logic: only `CD00136_B002` accounts, excluding statuses 910/920, matching the SSO WebID.
3. **Validates WebID** — Throws `ERROR_CODE_0102` if no matching account found.
4. **Creates the FUSV0025 mapper** — This is a different mapper from `init()`'s `FUSV0024_*`, handling the **FUSV0025** use case (URL reservation submission).
5. **Configures function code** — `FUNC_CD_2` for CFM path, `FUNC_CD_1` for MSKM path.
6. **Invokes the mapper chain** (7 `setSC` calls + 3 `setCC` calls):
   - `setFUSV002501SC` — Processing start
   - `setFUSV002502SC` — ISP update
   - `setFUSV002503SC` — Aging value validation
   - `setFUSV002504SC` — Finalization
   - `setFUSV002505SC` — Service charge table data
   - `setFUSV002506SC` — ISP update (second pass)
   - `setFUSV002507SC` — ISP update (third pass)
   - `setFUSV002501CC` — Confirmation charge
   - `setFUSV002502CC` — Service charge table confirmation
   - `setFUSV002503CC` — Aging value validation confirmation
7. **Sets service status** — Calls `JFUWebCommon.setSvcKeiStat()` and `JFUWebCommon.setOpSvcKeiStatMyHpRsv1()` to set operational service statuses.
8. **Invokes the service layer** — Executes the database operations.
9. **Validates constraints** — Same max URL count and domain checks as `init()`.
10. **Catches and classifies exceptions** — If a `JCCWebServiceException` is thrown, delegates to `checkException()` for precise error code mapping.

### `private void setShokiSettei(X31SDataBeanAccess bean, X31SDataBeanAccess svcKeiInfoBean, HashMap<String, Object> outputMap, int mryoZanNum) throws Exception`

**Lines 669-763**

Sets the **initial display settings** on the form bean, computing three boolean flags and potentially overriding pricing info.

1. **Retrieves processing group and payment method codes** from the service info bean.
2. **Walks nested output maps** — Iterates over two map keys (`FUSV002404SC` and `FUSV002401CC`), drills into child lists containing message maps, and extracts:
   - `kihonPrc` (base amount) from `PPLAN_KOTEI_AMNT`.
   - `shokiPrc` (initial amount) from `TMP_PAY_PRC_AMNT`.
3. **Computes `MANSION_DIV` flag** — Set to `true` if:
   - Processing group is `CD00133_04` (mansion), **and** payment method is `CD01216_003`, **and** (remaining count is zero and base amount > 0, **or** initial price is set).
   - Otherwise `false`.
4. **Computes `PAY_FLG`** — Set to `true` if remaining count is zero and base amount is positive. Otherwise `false`.
5. **Sets free price info** — If base amount is zero, calls `JFUWebCommon.setFreePrcInfoMap()` to override pricing display.
6. **Sets `KEIYAKU_YAKKAN_DOI`** — Always set to `false` (contract reservation not in progress).

## Usage Example

The typical calling pattern follows a screen-based request flow:

```
User request --> XML router --> FUW02401SFLogic.init()
                         |
                         +--> User reviews, submits --> cfm()
                                            |
                                            +--> User confirms --> mskm()
```

```java
// Framework instantiates the class per-request.
// Typical flow (pseudo-code):

FUW02401SFLogic logic = new FUW02401SFLogic();

// Step 1: Display the reservation page
logic.init();
// Returns true; next screen set to FUW02402

// Step 2 (user clicks "confirm"):
logic = new FUW02401SFLogic();
logic.cfm();
// Throws JCCBusinessException if validation fails
// Returns true; stays on FUW02402

// Step 3 (user clicks "submit"):
logic = new FUW02401SFLogic();
logic.mskm();
// Sends completion email, returns true; next screen set to FUW02403

// User clicks "back" at any point:
logic = new FUW02401SFLogic();
logic.back();
// Returns true; next screen set to FUW02401
```

## Notes for Developers

- **Thread safety:** This class is **not thread-safe**. Each request creates a new instance (as indicated by the per-request instantiation pattern and framework usage). The `@SuppressWarnings("serial")` annotation suggests the class may implement `Serializable` by virtue of extending `JCCWebBusinessLogic`, but it does not declare any synchronization.
- **Error handling is exception-throwing, not returning:** All public methods throw `Exception` (specifically `JCCBusinessException` or `JCCWebServiceException`). There are no `if-else` error return codes — errors always propagate up to the framework's exception handler.
- **The `checkException` method is fragile:** It assumes `moreInfo[0]` exists without a bounds check. If a service exception is thrown with an empty message list, this will throw `ArrayIndexOutOfBoundsException` which will then be caught by the outer catch block and re-thrown as a generic `ERROR_CODE_0002`. This masks the actual error.
- **Shared processing:** `cfm()` and `mskm()` share substantial logic through `cfmMskmSyori()`. The differentiation is controlled by:
  - The `isTarget` parameter (`"cfm"` vs `"mskm"`) which affects error code mapping in `checkException()`.
  - The `functionCode` (`FUNC_CD_2` vs `FUNC_CD_1`) which affects mapper SQL generation.
  - The additional `JFUCommonRelationCheck` call and email-sending step unique to `mskm()`.
- **Data bean hierarchy is deep:** Both `init()` and `cfmMskmSyori()` drill 5-6 levels deep through `getDataBeanArray(...).getDataBean(...)` chains. This is brittle — if any level returns null or has a different structure, a `NullPointerException` will be thrown.
- **URL account limits are enforced twice:** Once in `init()` (for display) and again in `cfmMskmSyori()` (for submission). If the `maxOpSvcCnt` is 0, missing, or the domain is null, `ERROR_CODE_0002` is thrown. If the user's existing accounts (`urlAccountCnt`) meet or exceed the limit, `ERROR_CODE_0103` is thrown.
- **The class uses magic strings** extensively for constant-like values (e.g., `"mskm"`, `"cfm"`, `"EKK0361C050"`). These are partially centralized in other classes (`JFUStrConst`, `FUW02401SFConst`), but several remain as raw string literals within this class.
- **`JPCModelConstant.RELATION_ERR`** is checked by comparing against `String.valueOf()` — this is likely a numeric constant being compared as a string, which works due to `status` also being a string but adds unnecessary string conversion overhead.
