# FUW02001SFLogic

## Purpose

`FUW02001SFLogic` is the **business logic controller** for the Email Alias Setup Application screen (screen ID `FUW02001`) within the K-Opticom eo customer core system. It manages the full lifecycle of a user's email alias registration and modification request — from initial page load (fetching current service info, pricing, and availability constraints) through confirmation review and final submission — including sending completion notification emails.

## Design

This class follows the **screen-controller (frontend logic)** pattern common in Fujitsu's JCC web framework. It extends `JCCWebBusinessLogic` and orchestrates a sequence of steps:

1. **Data preparation** — retrieving shared customer, service contract, and SSO state from the common info bean tree.
2. **Service invocation** — calling backend CBS (Core Business System) services via mappers (`FUSV0055_*` for display, `FUSV0056_*` for submission) through the inherited `invokeService()` method.
3. **Post-processing** — configuring UI bean values (pricing, domain, mansion flag), navigating to the next screen, and sending emails on completion.
4. **Exception handling** — intercepting `JCCWebServiceException` and mapping low-level CBS error codes (stale update, contract state, usage limits) to user-facing business exceptions.

Each public method maps to a screen action: `init` (load), `cfm` (confirm), `mskm` (submit), `back` (return).

## Key Methods

### `init()` → `boolean`

**What it does:** Handles the initial page load for the email alias setup screen. Returns `true` to proceed to screen rendering.

**Steps performed:**

1. **Device check** — calls `JFUWebCommon.checkOrosi(this)` to detect the access device (PC, smartphone, etc.).
2. **Fetches shared info** — retrieves the common info bean and unpacks it via `getCommoninfoBeanInfo()` into five sub-beans:
   - `svcKeiInfoBean` — service contract info
   - `opSvcKeiInfoBean` — optional service contract info (null for new customers)
   - `sbopSvcKeiInfoBean` — sub-optional service contract info (null for new customers)
3. **Validates service data** — calls `checkSvcData()` to ensure an optional service contract exists (errors with `ERROR_CODE_0102` / "contract state error" if missing).
4. **Initializes display mappers** — creates an `FUSV0055_FUSV0055OPDBMapper` and populates a data map with four SC (Screen Configuration) methods:
   - `setFUSV005501SC` — business parameter management (contract change restriction days)
   - `setFUSV005502SC` — NG ward list
   - `setFUSV005503SC` — fixed unit price (application fee) list
   - `setFUSV005504SC` — cost course / sub-optional service agreement consent
5. **Initializes CC (Confirm) methods** — calls `setFUSV005501CC` for the initial cost list confirmation.
6. **Invokes the service** — calls `invokeService(paramMap, dataMap, outputMap)`. If a `JCCWebServiceException` is thrown, it wraps it as a system error (`ERROR_CODE_0002`).
7. **Restores results to bean** — maps output back into the service form bean for display.
8. **Email alias change restriction check** — if the user has existing sub-optional service info, checks whether the email alias was changed recently and the change restriction period hasn't expired. If so, throws usage restriction error (`ERROR_CODE_0101`).
9. **Configures form bean values** — sets:
   - Current email address (`NOW_MLAD`) and sub-domain (`SUB_DOMAIN`)
   - Add/change division (`ADD_CHG_DIV`): `"0"` for new registration, `"1"` for modification
   - Pay flag (`PAY_FLG`) via `setPayFlg()`
   - If free or modification mode, sets free pricing info
   - Price info area mapping via `setPrcInfoArea()`
   - Mansion division flag via `getMansionDiv()`
   - Current email alias (if modifying)
10. **Sets navigation target** — writes `NEXT_SCREEN_ID` and `NEXT_SCREEN_NAME` to the common info bean.

**Side effects:** Populates the service form bean with display data; modifies the common info bean's navigation fields.

### `cfm()` → `boolean`

**What it does:** Handles the **confirm button** press. Validates re-entry values and, if correct, prepares the data for service submission by calling the `FUSV0056` use case. Returns `true` to proceed to the confirmation screen.

**Key steps:**

1. Retrieves all shared info beans (same unpacking as `init()`).
2. **Re-entry validation** — compares the re-entered email alias against the original. If they differ, sets error `EKF0400_TW` (email alias mismatch) targeting `re_input_mailalias` and returns `true` (stays on screen).
3. **Initializes submission mappers** — creates `FUSV0056_FUSV0056OPDBMapper` and calls 10 SC methods:
   - `setFUSV005601SC` — application content approval registration
   - `setFUSV005602SC` — sub-optional service agreement <ISP> registration
   - `setFUSV005603SC` through `setFUSV005605SC` — consent, usage start, modification
   - `setFUSV005606SC` — engagement target usage completion
   - `setFUSV005607SC` — engagement target registration
   - `setFUSV005608SC` — advance registration
   - `setFUSV005609SC` — application detail lookup / subsequent task delegation
   - `setFUSV005610SC` — sub-optional service agreement <ISP> lookup
4. **CC (Confirm) methods** — 5 CC methods for agreement confirmation, engagement list, service IF result transfer, and order issuance.
5. **Sets optional service contract status** — calls `JFUWebCommon.setOpSvcKeiStatMail(this, dataMap)`.
6. **Invokes the service** — catches `JCCWebServiceException` and routes it to `checkException(se, CALL_METHOD_CFM)`.
7. **Sets next screen** — navigates to screen `FUW02002` (the confirmation/detail screen).

**Side effects:** Prepares service data for the CBS submission. If the service call succeeds, the CBS side has already committed the changes.

### `mskm()` → `boolean`

**What it does:** Handles the **submit button** press on the confirmation screen. This is the final step that permanently registers or modifies the email alias.

**Key steps:**

1. **Common relation check** — calls `JFUCommonRelationCheck.checkCommonRelation(this, USECASE_ID_FUSV0056)` to validate overall business conditions.
2. Fetches shared info beans and the service form bean (same structure as `cfm()`).
3. **Service invocation** — uses the same `FUSV0056` mappers and service call as `cfm()`, but with `FUNC_CD_1` instead of `FUNC_CD_2` (indicating a different execution mode — likely a committed vs. preview run). Catches `JCCWebServiceException` and routes to `checkException(se, CALL_METHOD_MSKM)`.
4. **Refreshes current customer state** — calls `JFUWebCommon.refreshGenCustKei(this)` to reload the customer's contract data after the CBS commit.
5. **Re-fetches updated service info** — gets the new `opSvcKeiInfoBean` and `sbopSvcKeiInfoBean` from the common info bean to set:
   - `NOW_MLAD` — current email address
   - `NOW_MAILALIAS` — confirmed email alias (if sub-optional service exists)
6. **Sends completion email** — based on `ADD_CHG_DIV`:
   - `"0"` (new registration): sends `MSKM_FIN_MAIL_FUW020_1`
   - `"1"` (modification): sends `MSKM_FIN_MAIL_FUW020_2`
7. **Navigation** — sets the next screen to `FUW02003` (completion screen).

**Side effects:** Commits the email alias change via CBS, refreshes customer data, sends a completion email.

### `back()` → `boolean`

**What it does:** Handles the back button. Sets the navigation target back to the current screen (`FUW02001`) and returns `true`. Minimal logic — it's a pass-through for browser back navigation.

### `checkSvcData(Map<String, Object> resultMap)` → `void`

**What it does:** Validates that the user has an existing optional service contract (`opSvcKeiInfoBean`). If it is `null`, throws `ERROR_CODE_0102` ("contract state error").

**Guards against:** Users accessing the email alias setup screen who are not eligible (no active optional service contract).

### `getCommoninfoBeanInfo(X31SDataBeanAccess commoninfoBean)` → `Map<String, Object>`

**What it does:** A central helper that traverses the shared bean tree and extracts five key pieces of information into a result map. This is called by every public method.

**Bean tree traversal:**

```
commoninfoBean
  └── webChgInfo[0]
        ├── ssoInfo[0]              → SSO SYSID, POPID
        ├── genCustKeiInfo[0]
        │     └── svcKeiInfo[0]
        │           ├── svcKeiUcwkInfo[0]
        │           │     └── opSvcKeiInfo[]  → iterated to find matching service
        │           │           └── sbopSvcKeiInfo[]  → iterated to find sub-service
        │           └── seikyKeiInfo[0]  → billing contract info
```

**Optional service matching logic:** Iterates through `opSvcKeiInfo` array, skipping entries whose status isn't `100` (service in progress), `020` (checked), or `030` (terminated). When it finds an entry where `popId` matches the SSO's `popId` AND the service code is `B001` (Email), it locks that as the confirmed optional service bean.

**Sub-optional service matching:** Only if an optional service bean was found, it then iterates through `sbopSvcKeiInfo`, skipping entries with status `910` (canceled) or `920` (cancelled). It matches entries where the optional service number equals the sub-optional's optional service number AND the service code is `D01` (Email Alias).

**Returns:** A map containing `SYSID`, `POPID`, `SSO_INFO`, `GEN_CUST_KEI_INFO`, `SVC_KEI_INFO`, `SVC_KEI_UCWK_INFO`, `SEIKY_KEI_INFO`, `OP_SVC_KEI_INFO`, and `SBOP_SVC_KEI_INFO`.

### `getMansionDiv(...)` → `Boolean`

**What it does:** Determines whether this customer is in a "mansion (all-unified)" pricing tier. Returns `true` only when ALL three conditions hold:
- Price group code (`PRC_GRP_CD`) is `"04"` (net mansion)
- Subscription contract payment method code (`KANYU_KEI_PAY_HOSHIKI_CD`) is `"003"` (all-unified)
- The service is paid (`payFlag` is `true`)

This flag controls whether mansion-specific UI elements are shown.

### `checkException(JCCWebServiceException se, String callMethod)` → `void`

**What it does:** The most complex error-handling method. Extracts error metadata from a `JCCWebServiceException` and maps specific CBS error scenarios to appropriate business exceptions.

**Error metadata extracted from the exception's `MessageMoreInfo[0]`:**
- `templateid` — the CBS template that generated the error
- `itemid` — the field/parameter involved
- `status` — error category (`RELATION_ERR` = related check error)
- `itemCheckErr` — specific check type (e.g., `EH`, `EI`, `EF`, `EG`, `EA`)

**Error mapping table:**

| Template | Check Code | Item | Call Method | Exception | Meaning |
|---|---|---|---|---|---|
| `EKK0411D010` | `EH` | `op_svc_kei_no` | `cfm` | `se` (re-throw) | New registration — NG ward check failed (business error) |
| `EKK0411D010` | `EI` | `op_svc_kei_no` | `cfm` | `se` (re-throw) | New registration — engagement check failed |
| `EKK0411C010` | `EF` | `sbop_svc_kei_no` | `cfm` | `se` (re-throw) | Modification — NG ward check failed |
| `EKK0411C010` | `EG` | `sbop_svc_kei_no` | `cfm` | `se` (re-throw) | Modification — engagement check failed |
| `EKK0411D010` | `EH`/`EI` | `op_svc_kei_no` | `mskm` | `ERROR_CODE_0102` | New registration — contract state error (system) |
| `EKK0411C010` | `EF`/`EG` | `sbop_svc_kei_no` | `mskm` | `ERROR_CODE_0102` | Modification — contract state error (system) |
| `EKK0411D010` | `EA` | `upd_dtm_bf` | `mskm` | `ERROR_CODE_0204` | Stale update error (optimistic lock) |
| `EKK0411C010` | `EH` | `sbop_svc_kei_no` | `mskm` | `ERROR_CODE_0101` | Usage limit error (optional contract cap) |
| `EKK0411C010` | `EA` | `upd_dtm_bf` | `mskm` | `ERROR_CODE_0204` | Stale update error (optimistic lock) |

**Notable design decision:** During `cfm()` (confirm), the original exception is re-thrown for certain template/check combos, allowing the calling code to handle it at a higher level. During `mskm()` (submit), these same errors are translated to specific business exceptions so the user sees a meaningful message.

Any error not matching the above patterns falls through to `ERROR_CODE_0002` (system error).

### `setPayFlg(...)` → `boolean`

**What it does:** Determines the "pay flag" — whether this email alias setup is a paid or free service. Returns `true` (paid) only if both conditions hold:
- `chkPayKoteiTanka()` returns `true` (a fixed unit price with amount > 0 exists)
- The free count (`SVCTK_BUT_MRYO_VALUE`) is 0

Otherwise returns `false` (free).

### `chkPayKoteiTanka(HashMap outputMap)` → `boolean`

**What it does:** Checks whether there's a non-zero fixed unit price in the pricing data (`FUSV005503SC` → `EKK0601B001CBSMsg1List`). Iterates through the price items and returns `true` if any item has `PPLAN_KOTEI_AMNT > 0`.

### `chkPayInitialCost(HashMap outputMap)` → `boolean`

**What it does:** Checks whether initial costs exist (`FUSV005501CC` → `EKK0721A010CBSMsg1List`). Returns `true` if the list is non-empty. This appears to be available for use but isn't currently called by `setPayFlg` (which only checks fixed unit price).

## Relationships

```mermaid
flowchart TD
    A["WEBGAMEN_FUW020010PJP"] -->|"uses"| B["FUW02001SFLogic"]
    C["WEBGAMEN_FUW020020PJP"] -->|"uses"| B
    D["WEBGAMEN_FUW020030PJP"] -->|"uses"| B
    E["x31business_logic_FUW02001SF"] -->|"uses"| B
    B -->|"extends"| F["JCCWebBusinessLogic"]
```

**Inbound (4 classes depend on `FUW02001SFLogic`):**

- **`WEBGAMEN_FUW020010PJP`** — The initial setup screen. Calls `init()` to load the page.
- **`WEBGAMEN_FUW020020PJP`** — The confirmation screen. Calls `cfm()` when the user presses confirm.
- **`WEBGAMEN_FUW020030PJP`** — The completion screen. Calls `mskm()` when the user presses submit, then shows completion.
- **`x31business_logic_FUW02001SF`** — The business logic routing configuration. References this class as the handler for the email alias setup application use case.

**Outbound dependencies:**

- **`JCCWebBusinessLogic`** — The parent class that provides `invokeService()`, `getCommonInfoBean()`, `getServiceFormBean()`, and the service invocation framework.

## Usage Example

The typical flow for a user modifying their email alias looks like this:

```
1. User navigates to FUW02001
   → WEBGAMEN_FUW020010PJP calls init()
   → Page loads with current email, pricing info, and "modify" mode

2. User edits the alias and clicks Confirm
   → WEBGAMEN_FUW020020PJP calls cfm()
   → Re-entry validation runs
   → FUSV0056 service is invoked (CBS prepares data)
   → Confirmation screen (FUW02002) displays

3. User clicks Submit on confirmation
   → WEBGAMEN_FUW020030PJP calls mskm()
   → FUSV0056 service is invoked again with commit mode
   → Customer data is refreshed
   → Completion email is sent
   → Completion screen (FUW02003) displays
```

For a **new registration** (user has no existing optional service contract), the flow would be blocked at `init()` by `checkSvcData()`, which throws `ERROR_CODE_0102` if `opSvcKeiInfoBean` is null.

## Notes for Developers

**Thread safety:** Each HTTP request creates a new instance of `FUW02001SFLogic`. The class is **stateless** — all state flows through method parameters and the shared bean tree (`X31SDataBeanAccess`). No instance fields hold request-specific data. The only fields are `private static final` constants.

**Service invocation:** The class delegates all CBS interaction to `invokeService()`, which is inherited from `JCCWebBusinessLogic`. The mappers (`FUSV0055_*` and `FUSV0056_*`) prepare input data and extract output data. The distinction between SC (screen config) and CC (confirm) methods is:
- **SC** methods populate the data map with service parameters for the CBS call.
- **CC** methods populate the data map with confirm/agreement data.

**`FUNC_CD_1` vs `FUNC_CD_2`:** The `init()` and `mskm()` methods use `FUNC_CD_1`, while `cfm()` uses `FUNC_CD_2`. This appears to signal different execution modes to the CBS — `FUNC_CD_2` likely indicates a "preview" or "non-committal" call, while `FUNC_CD_1` is the "committed" call.

**Email alias change restriction:** The 14-day (or configured period) lock on email alias changes after a previous modification is enforced in `init()` by comparing `aliasChgYmd + keiChgStpPrd` against the current system date. If the lock period hasn't expired, the user gets `ERROR_CODE_0101` (usage restriction).

**Error handling strategy:** The `checkException()` method has a large `if-else` chain matching specific CBS template IDs against error check codes. Adding a new CBS error code requires adding a new branch to this method. Errors not matched fall through to the generic system error.

**Pricing logic nuance:** `setPayFlg()` determines paid vs. free based on fixed unit price + free count. `chkPayInitialCost()` is defined but not currently used in the paid flag logic — it may be intended for future pricing logic changes or other screens.

**Mansion division:** The `getMansionDiv()` result controls whether mansion-specific UI is shown. This requires three specific codes to match: price group `"04"`, payment method `"003"`, and a paid service. All three must hold simultaneously.

**Next screen configuration:** Each public method sets `NEXT_SCREEN_ID` and `NEXT_SCREEN_NAME` in the common info bean before returning. This is the framework's way of routing the user to the next screen. The values are screen-specific constants (`FUW02001`, `FUW02002`, `FUW02003`).
