# FUW02701SFLogic

## Purpose

`FUW02701SFLogic` is the web-layer business logic controller for the **Web Contract Capacity Addition Application** flow. It handles the three-screen journey that allows existing customers to request additional bandwidth (data capacity) on their Web service contract: initial display (FUW02701), confirmation (FUW02702), and completion (FUW02703). This class orchestrates data retrieval from shared form beans, invokes backend service mappers (FUSV0076 for display / FUSV0077 for submission), computes pricing and optional capacity options, and routes navigation between screens.

## Design

The class follows the **page controller** pattern within the web presentation tier. It extends `JCCWebBusinessLogic`, the framework's base class for web business logic components, and acts as the orchestrator for a single business use case spanning three sequential screens. The class itself holds no state beyond what's inherited; each public method is stateless and operates on data beans passed through the framework.

Architecturally, the class sits at the boundary between the web presentation layer and the backend service layer:

```mermaid
flowchart TD
    User["User"]
    Servlet01["WEBGAMEN_FUW027010PJP
FUW02701"]
    Servlet02["WEBGAMEN_FUW027020PJP
FUW02702"]
    Servlet03["WEBGAMEN_FUW027030PJP
FUW02703"]
    Logic["FUW02701SFLogic"]
    Mapper01["FUSV0076 Mapper
Display (read)"]
    Mapper02["FUSV0077 Mapper
Submission (write)"]
    Backend["Backend Service"]

    Servlet01 -->|init| Logic
    Servlet02 -->|cfm| Logic
    Servlet03 -->|mskm, back| Logic
    Logic -->|invokeService| Mapper01
    Logic -->|invokeService| Mapper02
    Mapper01 --> Backend
    Mapper02 --> Backend
    ServletBP["x31business_logic_FUW02701SF.xml"] -->|references| Logic
```

## Key Methods

### `init()` — Screen Initialization (lines 115–255)

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

This is the entry point invoked when the user first visits the capacity addition screen (FUW02701). It performs a comprehensive initialization sequence:

1. **Device check** — Calls `JFUWebCommon.checkOrosi(this)` to verify the accessing device (likely a Japanese mobile carrier compatibility check, given the `checkOrosi` naming convention).

2. **Customer data retrieval** — Extracts the shared form bean via `getCommonInfoBean()`, then calls `getCommoninfoBeanInfo()` to pull out six key data beans from the shared form hierarchy:
   - `SSO_INFO` — Single Sign-On information (sysid, webid, popid)
   - `GEN_CUST_KEI_INFO` — Current customer information
   - `SVC_KEI_INFO` — Service contract information
   - `SEIKY_KEI_INFO` — Billing contract information
   - `OP_SVC_KEI_INFO` — Option service contract information
   - `SBOP_SVC_KEI_INFO` — Sub-option service contract information (may be `null` for new registrations)

3. **Service data validation** — Calls `checkSvcData(resultMap)` to validate that the option service contract exists and has a valid home page URL/domain.

4. **Display data fetch** — Invokes the backend service via `FUSV0076_FUSV0076OPDBMapper` with usecase ID `FUSV0076`. This mapper populates four service components:
   - `FUSV007601SC` — Business parameter management (home page URL protocol)
   - `FUSV007602SC` — Pricing / Sub-option service agreement
   - `FUSV007603SC` — Fixed-price plan unit list (option application fees)
   - `FUSV007604SC` — Additional charges list

   It also sets up an initial fee display via `FUSV007601CC`.

5. **Capacity calculation** — Computes the currently available capacity:
   - Reads the current Web contract capacity (`NOW_WEB_KEI_CAPA`)
   - Reads the maximum allowed addition (`ADD_CAPA_ZOUBUN_UPPL_VALUE`)
   - Calculates `webKeiCapa = webMaxCapa - webCapa` (the additional capacity the user can add)
   - If `webKeiCapa <= 0`, throws `ERROR_CODE_0103` (Contract completion error)

6. **New vs. addition flag** — Sets `NEW_ADD_DIV` to `false` if a sub-option service contract (`sbopSvcKeiInfoBean`) already exists, indicating an upgrade rather than a first-time addition.

7. **Option data generation** — Calls `createOptioinData(bean, outputMap)` to build the capacity and pricing option list.

8. **Pricing display** — Calls `JFUWebCommon.setPrcInfoArea(bean, outputMap, ...)` to format and set the pricing area.

9. **Mansion type detection** — Calls `getMansionDiv()` to determine if the customer is on an "eo光ネットマンションタイプ" (eo Light Net Mansion type) plan.

10. **Payment flag** — Calls `getPayFlg(bean)` to determine if the addition will be chargeable.

11. **Next screen routing** — Sets `NEXT_SCREEN_ID` and `NEXT_SCREEN_NAME` to the initial screen (FUW02701).

12. **Operation date** — Fetches and sets the operation date via `setFuOpedate()`.

**Returns:** Always `true`.

**Side effects:** Populates the service form bean with display data, capacity options, pricing, and routing information.

---

### `cfm()` — Confirmation Button (lines 263–420)

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

Handles the **Confirm** button press on the initial screen (FUW02701). This method prepares a review summary for the user and routes them to the confirmation screen (FUW02702).

Key steps:

1. **Data extraction** — Retrieves the same shared form bean hierarchy as `init()`, but additionally extracts the WEB change information bean chain to get the service contract data, including price group code (`PRC_GRP_CD_23`) and contract payment method code (`KANYU_KEI_PAY_HOSHIKI_CD_23`).

2. **Capacity selection** — Reads the selected capacity option from `ADD_CAPA_LIST` and calculates:
   - `selectValue` — The selected additional capacity
   - `freeValue` — The free (gratuitous) capacity allowance
   - `gokei_capa` — The total capacity after addition (current + selected)

3. **Mansion-type pricing display** — For customers on the "eo Light Net Mansion type" (`prcGrpCd = "04"`) with all-house payment method (`kanyuKeiPayHoshikiCd = "003"`), recalculates the mansion flag based on whether the total capacity after addition exceeds the free capacity.

4. **Formatted capacity display** — Sets `MSKM_WEB_CAPA` with a formatted string like "100MB (combined Web contract capacity 200MB)".

5. **Payment flag re-evaluation** — If the payment flag was previously set, re-evaluates it against the selected capacity.

6. **Service invocation** — Invokes the backend service using `FUSV0077_FUSV0077OPDBMapper` with usecase ID `FUSV0077`. This mapper runs multiple service components in sequence:
   - `FUSV007701SC` — Application content acceptance registration
   - `FUSV007702SC` — Option service contract <ISP> information change
   - `FUSV007703SC` — Sub-option service contract <ISP> registration
   - `FUSV007709SC` — Sub-option service contract <ISP> inquiry
   - `FUSV007704SC` — Sub-option service contract <ISP> inquiry conclusion
   - `FUSV007705SC` — Sub-option service contract <ISP> usage start
   - `FUSV007706SC` — Sub-option service contract <ISP> change
   - `FUSV007707SC` — Progress registration
   - `FUSV007708SC` — Application detail inquiry / follow-up business request

   CC (consistency check) components are also invoked.

7. **Exception handling** — If `JCCWebServiceException` is thrown, delegates to `checkException(se)` for intelligent error classification.

8. **Routing** — Sets `NEXT_SCREEN_ID` and `NEXT_SCREEN_NAME` to `FUW02702` (confirmation screen).

**Note:** Unlike `mskm()`, this method's service call does **not** perform common relation checks or send a completion email. It's a read-the-results-and-show-summary step.

---

### `mskm()` — Submission Button (lines 428–526)

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

Handles the **Submit** button press on the confirmation screen (FUW02702). This is the **critical method** that actually commits the capacity addition to the backend system.

The workflow mirrors `cfm()` but with key differences:

1. **Service invocation with common relation check** — Calls `JFUCommonRelationCheck.checkCommonRelation(this, USECASE_ID_FUSV0077)` before the service call, performing pre-submission data validation. This ensures the customer's data hasn't changed since the initial display.

2. **Full service invocation** — Uses the same `FUSV0077_FUSV0077OPDBMapper` with the same set of service components, but passes `FUNC_CD_1` instead of `FUNC_CD_2`.

3. **Post-processing** — After the service call completes:
   - Calls `JFUWebCommon.refreshGenCustKei(this)` to refresh the current customer information (so subsequent pages show updated data)
   - Calls `JFUWebCommon.sendMskmFinMail(this, MSKM_FIN_MAIL_FUW027_1)` to send the completion notification email to the customer

4. **Routing** — Sets `NEXT_SCREEN_ID` and `NEXT_SCREEN_NAME` to `FUW02703` (completion screen).

5. **Exception handling** — Delegates to `checkException(se)` which performs intelligent classification of backend errors into specific business exceptions.

---

### `back()` — Back Button (lines 534–550)

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

Handles the **Back** button on the confirmation screen (FUW02702), routing the user back to the initial display screen (FUW02701).

This is a lightweight method that:
1. Sets the next screen to `FUW02701` (initial display)
2. Re-evaluates and sets the payment flag by calling `getPayFlg(bean)`

No service invocation is performed — the back action simply re-displays the initial screen with updated payment status.

---

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

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

Validates that the customer has a valid, active option service contract before proceeding. Checks:

1. **Contract existence** — If `opSvcKeiInfoBean` is `null`, throws `ERROR_CODE_0102` (Contract status error).
2. **Home page accessibility** — If the option service contract's domain (`URL_DOMAIN_28`) or account (`URL_ACCOUNT_28`) is null, throws `ERROR_CODE_0102`.

This acts as a guard against users who lack a valid My Home page setup attempting to access the capacity addition feature.

---

### `createOptioinData(X31SDataBeanAccess bean, HashMap<String, Object> outputMap)` — Capacity Option Generation (lines 591–697)

```java
private void createOptioinData(X31SDataBeanAccess bean, HashMap<String, Object> outputMap) throws Exception
```

Generates the list of capacity options (addition amounts and corresponding prices) displayed to the user on the initial screen. This is a key method for the pricing table shown during selection.

Algorithm:
1. Reads the base parameters: current capacity (`NOW_WEB_KEI_CAPA`), free capacity (`MRYO_CAPA`), increment value (`ADD_CAPA_ZOUBUN_VALUE`), max increment (`ADD_CAPA_ZOUBUN_UPPL_VALUE`), unit price (`PPLAN_KOTEI_AMNT`), and unit type (`PPLAN_KOTEI_TANI_CD_NM`).

2. Sets the `PAY_FLG` based on whether there's a valid pricing scenario (non-zero increment limit, non-zero free capacity, free capacity less than max, non-zero unit price).

3. Iterates through a **while loop**, creating entries from `addValue * 0` up to `addValue * n >= endValue`. For each iteration:
   - Calculates total capacity: `baseValue + addCapa`
   - Determines if the entry is free: `totalCapacity <= freeValue` or `payFlg` is false
   - If charged, computes: `addMoney = tanka * (goukeiCapa - freeValue) / addValue`
   - Formats the add capacity text as "XMB"
   - Creates a child map with `PPLAN_KOTEI_AMNT` and `PPLAN_KOTEI_TANI_CD_NM` for use by `JFUWebCommon.setPrcInfoArea()`

4. Stores the option list in `outputMap` under the key `EKK0601B001CBSMsg1List` (associated with title `FUSV007604SC`).

---

### `getCommoninfoBeanInfo(X31SDataBeanAccess commoninfoBean)` — Customer Data Extraction (lines 705–831)

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

This is a **central helper method** called by `init()`, `cfm()`, and `mskm()`. It traverses the shared form bean hierarchy to extract and validate customer and contract data, returning a map with keys for each piece of information.

The method performs a deep traversal:
1. Extracts SSO info (sysid, webid, popid) and validates that `webid` is set. If not, throws `ERROR_CODE_0002` (system error) with a debug message "SSO情報 WebID未設定エラー".
2. Walks down: `WEB_CHG_INFO -> GEN_CUST_KEI_INFO -> SVC_KEI_INFO`
3. Gets nested beans: `SVC_KEI_UCWK_INFO`, `SEIKY_KEI_INFO`
4. **Iterates through option service contracts** to find the matching one for the current user:
   - Filters by webid match and option service code `"B002"` (My Home page)
   - Filters by status: `"020"` (inquiry completed), `"030"` (concluded), or `"100"` (service provision)
5. If an option contract is found, **iterates through sub-option contracts** to find the matching capacity addition contract:
   - Filters by matching `op_svc_kei_no` and sub-option service code `"D04"` (home page capacity addition)
   - Excludes contracts with status `"910"` (cancelled) or `"920"` (resigned)

Returns a map populated with: `SYSID_21`, `WEB_ID_21`, `POP_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`.

---

### `getMansionDiv(...)` — Mansion Type Detection (lines 842–906)

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

Determines whether the customer is on an **eo Light Net Mansion type** plan (premium/glass-fiber types: premium, global, light distribution line).

Returns `true` if:
- Price group code is `"04"` (Mansion type) AND
- Payment method code is `"003"` (all-house unified) AND
- Either the max increment > free capacity AND unit price > 0, OR there are initial fee entries in `EKK0721A010CBSMsg1List`

This flag affects display behavior and is stored in the bean as `MANSION_DIV`.

---

### `getPayFlg(X31SDataBeanAccess bean)` — Payment Flag (lines 914–940)

```java
private boolean getPayFlg(X31SDataBeanAccess bean)
```

Determines whether the capacity addition will incur a charge.

Returns `true` if:
- The max increment value is non-zero AND
- The free capacity is non-zero AND
- The max increment > free capacity AND
- The unit price (`tanka`) is greater than zero

Returns `false` otherwise. This is used across multiple methods to determine whether to show the user a paid option.

---

### `checkException(JCCWebServiceException se)` — Error Classification (lines 947–998)

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

This method **classifies backend service errors** into specific business exceptions. It inspects the error's template ID, item ID, status, and check error flag to determine the error type and maps them to user-friendly error codes.

Classification logic:

| Error Condition | Business Exception | Meaning |
|---|---|---|
| `EKK0361C050`, `ED`, `capa` | `ERROR_CODE_0103` | Contract completion error (system error) |
| `EKK0361C050`, `EA`, `upd_dtm_bf` | `ERROR_CODE_0204` | Update impossibility error (stale data / timestamp mismatch) |
| `EKK0411D010`, `EB`, `add_capa` | `ERROR_CODE_0102` | Contract status error |
| `EKK0411C010`, `EL`, `sbop_svc_kei_no` | `ERROR_CODE_0102` | Contract status error |
| Any other error | `ERROR_CODE_0002` | System error (catch-all) |

The method reads from the first element of `messageMoreInfoList`, as the comment notes that relation check errors always have exactly one entry.

---

### `setFuOpedate(X31SDataBeanAccess commonInfoBean, String opeDate)` — Operation Date Setting (lines 1008–1017)

```java
private void setFuOpedate(X31SDataBeanAccess commonInfoBean, String opeDate)
```

Sets the operation date (OPEDATE) on the front shared information bean. The date is fetched via `JFUWebCommon.getOpeDate(this, null)` and stored in `FU_OPEDATE_05`. This is used for audit logging and transaction processing.

## Relationships

### Who uses this class (4 inbound connections)

```mermaid
flowchart LR
    Servlet1["WEBGAMEN_FUW027010PJP.xml
FUW02701 screen"]
    Servlet2["WEBGAMEN_FUW027020PJP.xml
FUW02702 screen"]
    Servlet3["WEBGAMEN_FUW027030PJP.xml
FUW02703 screen"]
    BizProxy["x31business_logic_FUW02701SF.xml
Business logic proxy"]

    Servlet1 -->|init, back| Logic["FUW02701SFLogic"]
    Servlet2 -->|cfm| Logic
    Servlet3 -->|mskm, back| Logic
    BizProxy -->|references| Logic
```

- **WEBGAMEN_FUW027010PJP.xml** — The page servlet (JP) for the initial display screen (FUW02701). Calls `init()` and `back()`.
- **WEBGAMEN_FUW027020PJP.xml** — The page servlet for the confirmation screen (FUW02702). Calls `cfm()`.
- **WEBGAMEN_FUW027030PJP.xml** — The page servlet for the completion screen (FUW02703). Calls `mskm()` and `back()`.
- **x31business_logic_FUW02701SF.xml** — A business logic proxy XML configuration that references this class, likely wiring it into the service layer.

### Dependencies (outbound)

- **JCCWebBusinessLogic** — The parent class this extends. Provides framework methods like `getCommonInfoBean()`, `getServiceFormBean()`, and `invokeService()`.
- **FUSV0076_FUSV0076OPDBMapper** — Used in `init()` to fetch display data (pricing, parameters, capacity options).
- **FUSV0077_FUSV0077OPDBMapper** — Used in `cfm()` and `mskm()` to submit the capacity addition request.
- **X31SDataBeanAccess / X31SDataBeanAccessArray** — The framework's data bean types used for passing data through the shared form hierarchy.
- **JFUWebCommon, JFUCommonRelationCheck** — Shared utility classes for common operations (error handling, logging, email, etc.).

## Usage Example

The typical call flow for a capacity addition request spans three HTTP requests:

**Request 1 — Initial Display:**
```
GET /FUW027010PJP
  -> WEBGAMEN_FUW027010PJP.xml dispatches to FUW02701SFLogic
  -> Logic.init()
    - Retrieves customer data from shared form bean
    - Invokes FUSV0076 mapper to fetch pricing/parameters
    - Calculates available addition capacity
    - Generates option list (capacity increments with prices)
    - Sets payment flag, mansion type flag
  -> Returns true, forwards to FUW02701 (JSP view)
```

**Request 2 — Confirmation (user selects capacity, clicks Confirm):**
```
POST /FUW027020PJP
  -> WEBGAMEN_FUW027020PJP.xml dispatches to FUW02701SFLogic
  -> Logic.cfm()
    - Reads selected capacity from form bean
    - Calculates total capacity after addition
    - Invokes FUSV0077 mapper (pre-read phase)
    - Sets summary data for display
  -> Returns true, forwards to FUW02702 (confirmation JSP)
```

**Request 3 — Submit (user confirms, clicks Submit):**
```
POST /FUW027030PJP
  -> WEBGAMEN_FUW027030PJP.xml dispatches to FUW02701SFLogic
  -> Logic.mskm()
    - Runs common relation check (data hasn't changed)
    - Invokes FUSV0077 mapper (write phase: registers contract)
    - Refreshes customer data
    - Sends completion email
  -> Returns true, forwards to FUW02703 (completion JSP)
```

## Notes for Developers

- **Screen flow is strict** — The three screens (FUW02701 -> FUW02702 -> FUW02703) follow a fixed sequence. The `back()` method only returns to FUW02701, never to a prior confirmation.

- **Error classification is template-driven** — `checkException()` relies on specific template IDs (`EKK0361C050`, `EKK0411D010`, `EKK0411C010`) and item IDs to distinguish between contract completion errors, timestamp mismatch errors, and contract status errors. Changes to backend error codes here will silently fall through to the generic system error (`0002`).

- **Stale data protection** — The `upd_dtm_bf` (update timestamp before) item ID check in `checkException()` handles optimistic concurrency control. If the customer's data changed between initial display and submission, the system returns `ERROR_CODE_0204` (update impossibility error).

- **SSO validation is a hard gate** — `getCommoninfoBeanInfo()` throws a system error (`0002`) if the user's SSO web ID is not set, preventing access for users without valid SSO credentials.

- **`mskm()` vs `cfm()` service invocation** — The `mskm()` method includes a `JFUCommonRelationCheck.checkCommonRelation()` call that `cfm()` omits. Additionally, `mskm()` uses `FUNC_CD_1` while `cfm()` uses `FUNC_CD_2` — these likely differentiate read-only vs. write-mode service behavior.

- **Option service contract matching** — `getCommoninfoBeanInfo()` iterates through the option service contract array looking for a contract matching the current SSO web ID with code `"B002"` and status in `["020", "030", "100"]`. If no match is found, `opSvcKeiInfoBean` remains `null`, and `checkSvcData()` subsequently throws error `0102`.

- **Sub-option contract matching** — When a sub-option contract exists (`sbopSvcKeiInfoBean` != `null`), the `NEW_ADD_DIV` flag is set to `false`, indicating this is an upgrade of an existing contract rather than a first-time addition.

- **Thread safety** — The class holds no instance fields beyond static constants. Each method call is independent and does not share mutable state. However, the data beans (e.g., `X31SDataBeanAccess`) may be shared across the web session, so thread safety depends on the underlying bean implementation.

- **Typo in method name** — The method is named `createOptioinData()` with a deliberate typo ("Optioin" instead of "Option"). This appears to be a copy/paste artifact from the original code and should not be changed without coordination, as it may be referenced in other parts of the system.

- **Capacity calculation uses integer arithmetic** — The pricing in `createOptioinData()` uses integer division (`tanka * (goukeiCapa - freeValue) / addValue`), which may introduce rounding differences compared to floating-point arithmetic. This is likely intentional to match backend billing behavior.
