# FUW01403SFLogic

## Purpose

`FUW01403SFLogic` is the central screen logic controller for the **"2号サービスお申し込み" (Service 2 Application)** web form in the eo光電話 (eo Hikari Phone) business system. It orchestrates the complete application workflow — from initial display of customer contract and pricing information, through confirmation of entered data, to final submission of the service application. This appears to be a screen-level business logic class that mediates between the web presentation tier and backend services, handling customer data retrieval, pricing plan determination, contract state validation, and error handling for the eo Hikari Phone subscription process.

## Design

This class follows the **Screen Controller / Form Action** pattern common in Japanese enterprise web frameworks. It is part of a three-screen flow:

- **FUW01403** (initial display / input screen) — handled by `init()`
- **FUW01404** (confirmation screen) — navigated to after `cfm()`
- **FUW01405** (completion screen) — navigated to after `mskm()`

The class extends `JCCWebBusinessLogic`, which provides base infrastructure for screen navigation, DataBean management, and service invocation. The class acts as a **facade** that coordinates between multiple subsystems: customer information retrieval, contract state checking, pricing plan lookup, address manipulation, phone number validation, pricing table rendering, and downstream service execution.

All business logic is procedural and runs on the server side per request. The class does not extend any interface — it is a concrete implementation tied to the specific screen `FUW01403`.

### Key Architecture Points

- **Stateless per request**: Each public method (`init`, `cfm`, `mskm`) receives its own copies of `X31SDataBeanAccess` form beans via the framework's dependency injection. No state is retained between requests.
- **DataBean-driven**: All form data flows through `X31SDataBeanAccess` objects. The class reads from and writes to these beans using `sendMessageString()` and `sendMessageBoolean()` calls with operation codes (`CLEAR`, `SET`, `GET`, `ADD`).
- **Mapper-based service calls**: Screen-level data mapping is delegated to auto-generated mapper classes (`FUSV0041_FUSV0041OPDBMapper`, `FUSV0042_FUSV0042OPDBMapper`). The logic class sets up input parameters, invokes `invokeService()`, and then extracts output data.
- **Error categorization**: Errors are split into two categories — single-field check errors (displayed inline on the screen) and common business exceptions (cause screen transitions or system error pages).

## Key Methods

### `init()` → `boolean` [lines 337–410]

**Purpose**: Orchestrates the initial screen display. This is the entry point when a user first accesses the Service 2 Application screen.

**Flow**:
1. Retrieves screen transition info from the previous screen.
2. Checks if this is a returning existing customer by calling `checkRefreshGenCustKei()`.
3. Runs common relation checks via `checkService()`.
4. Retrieves current customer contract information from the shared form bean (`setCustKeiInfo()`).
5. Determines the pricing plan type (home / maison / mansion) via `setPlanJudgeFlg()`.
6. Executes the init service via `executeInitService()`, which calls a large number of backend screens.
7. Validates the service results via `checkInitError()`.
8. Formats display data for the UI via `editDispData()` and `editFrontKhrkInfoArea()`.
9. Sets the current operation date and navigation screen ID.

**Side effects**: Populates the `serviceFormBean` with customer info, address data, pricing information, commission tables, and display metadata. Sets the next screen ID to `FUW01403`.

### `cfm()` → `boolean` [lines 419–468]

**Purpose**: Handles the confirmation button press. Validates entered data, prepares registration data, and navigates to the confirmation screen (FUW01404) on success, or returns to the input screen (FUW01403) on error.

**Flow**:
1. Calls `editRegData()` to process and consolidate form input into the registration data structure.
2. Calls `executeCfmMskmService()` with `funcCode = "2"` (check-only mode) to validate the submitted data without actually committing it.
3. Checks for errors via `checkCfmMskmError()`.
4. If errors exist, sets the next screen back to FUW01403 (input screen).
5. If no errors, sets the next screen to FUW01404 (confirmation screen).

**Key detail**: The `executeCfmMskmService()` call with `funcCode = "2"` performs validation checks against backend services but does not commit the application. This is a "dry run" to catch issues before showing the confirmation screen.

### `mskm()` → `boolean` [lines 477–534]

**Purpose**: Handles the submission button press. Performs the actual service application registration.

**Flow**:
1. Runs frontend common item validation via `JFUWebCommon.checkCommonRelation()`.
2. Executes the submission service via `executeCfmMskmService()` with `funcCode = "1"` (submission mode).
3. Checks for errors via `checkCfmMskmError()`.
4. Sets navigation to either the input screen or a completion screen based on error state.

### `executeInitService(commonInfoBean, serviceFormBean)` → `HashMap<String, HashMap<String, Object>>` [lines 604–710]

**Purpose**: Executes the backend service for the initial display. This is the most complex service call, coordinating data retrieval from approximately 15+ backend screens.

**What it does**:
- Creates an `FUSV0041_FUSV0041OPDBMapper` to handle data mapping.
- Sets up input parameters from the service form bean.
- Calls `set*` methods on the mapper for each backend screen:
  - `FUSV004101SC` — eo Hikari Phone contract information list
  - `FUSV004102SC` — Equipment provider service contract list
  - `FUSV004104SC` — Pricing plan fixed unit price (base fee)
  - `FUSV004105SC` — Pricing plan fixed unit price (eo adaptor fee)
  - `FUSV004106SC` — Equipment option service contract list (front)
  - `FUSV004107SC` — Equipment option service contract list (compound search)
  - `FUSV004108SC` — Work case list
  - `FUSV004103CC` — Equipment option service contract registration component (router retention)
  - `JFUInitialCostShokaiCC` — Initial cost list
  - `JFUInitialCostShokaiCCWari` — Initial cost list (number porting fee)
  - `FUSV004104CC` — ONU exchange work determination
  - `FUSV004105CC` — Work skip determination
  - `JFUInitialCostShokaiCCKoji` — Initial cost list (ONU exchange fee)
- Invokes the backend service via `invokeService()`.
- On exception, delegates to `handleInitException()`.
- Extracts results via corresponding `get*` methods.
- Sets multi-phone-call and warikomi (bundled phone) display flags.

**Returns**: A nested `HashMap` mapping screen IDs to their result data, used by `checkInitError()` and display editing methods.

### `executeCfmMskmService(commonInfoBean, serviceFormBean, funcCode)` → `HashMap<String, HashMap<String, Object>>` [lines 725–851]

**Purpose**: Executes the backend service for confirmation and submission. The `funcCode` parameter controls the mode: `"1"` for submission, `"2"` for check-only.

**What it does**:
- Creates an `FUSV0042_FUSV0042OPDBMapper`.
- Conditionally sets up ~25 backend screen calls depending on the form state:
  - `FUSV0042WORK01` — Application work items
  - `JFUSplitAddressInfoCC` — Address info splitting
  - `FUSV004202SC` — Application registration
  - `FUSV004212SC` — Prefix one-agreement (if phone number provided)
  - `FUSV004203CC` — Number port registration possibility check
  - `FUSV004207CC` — Same-number call forwarding possibility check
  - `FUSV004211CC` — Phone number master change
  - `FUSV004213SC` — Telecommunications carrier list
  - `FUSV004203SC` — Phone number registration
  - `FUSV004215SC` — Service contract details <eo Hikari> agreement
  - `FUSV004214SC` / `FUSV004206SC` — Service contract details registration
  - `FUSV004207SC` — Option service contract <phone> registration
  - `FUSV004209SC` — Advance registration
  - `FUSV004210SC` — Business parameter management
  - `FUSV004204CC` / `FUSV004206CC` / `FUSV004205CC` — Data transfer components
  - Submission-specific screens (16–25) only when `noTchSvcUm` flag is set
- Calls the backend service via `invokeService()`.
- On exception, delegates to `handleMskmException()`.

### `checkRefreshGenCustKei(serviceFormBean)` → `void` [lines 860–873]

**Purpose**: Determines whether the current customer's contract needs to be refreshed. If coming from a previous screen (i.e., `fromScreenId` is set), it calls `JFUWebCommon.refreshGenCustKei()` to refresh the existing customer contract data.

### `checkService(serviceFormBean)` → `void` [lines 882–895]

**Purpose**: Runs common relation checks when coming from a previous screen. Calls `JFUWebCommon.checkCommonRelation()` for use case `FUSV0042` (Service 2 Application - Submission).

### `setCustKeiInfo(commonInfoBean, serviceFormBean)` → `void` [lines 906–1031]

**Purpose**: Retrieves and copies customer contract information from the shared `commonInfoBean` into the `serviceFormBean`. This is a large data-mapping method that extracts approximately 20+ fields from the SSO info, existing customer contract info, and service contract info trees, then sets them on the service form bean.

**Key data copied**:
- SYSID, service contract number
- Full postal code (split into first 3 digits and remaining digits)
- Full address components (prefecture, city, district, town, lot number, building info, room number)
- Customer name and kana name (for number portability sales)
- Contract address (combined into single formatted string via `JZMCommonUtil.getPtn01()`)
- Contract type code
- Pricing plan info (delegated to `setPlanCdInfo()`)
- Service contract internal details number

### `setPlanJudgeFlg(commonInfoBean, serviceFormBean)` → `void` [lines 1041–1070]

**Purpose**: Determines the property type of the customer's current plan and sets a `pplanJudgeFlg` on the service form bean. The flag values are:
- `"1"` — Home (individual/residential)
- `"2"` — Maison (medium-sized business)
- `"3"` — Mansion (multi-unit dwelling)

This flag is used throughout the class to determine pricing rules and whether certain fee items apply.

### `editDispData(serviceFormBean, outputMap)` → `void` [lines 1120–1207]

**Purpose**: Formats data for screen display. Specifically:
- Splits the line location postal code into display format (`"XXX-XXXX"`).
- Combines address components into a single formatted string.
- Builds a telecom carrier combo box from property-based display items, sorted alphabetically by carrier code.

### `editFrontKhrkInfoArea(serviceFormBean, outputMap)` → `void` [lines 1222–1453]

**Purpose**: Builds the pricing table display data. This is a significant rendering method that:
- Reads pricing table property definitions from the display property file.
- Extracts monthly fees (base fee + eo adaptor fee) and initial fees (change handling fee, number porting fee, ONU exchange fee) from the service results.
- Formats amounts using `JPCUtilCommon.formatNumber()`.
- Constructs table rows with labels from the property file and formatted amounts.
- Applies CSS style classes for layout.

### `editRegData(commonInfoBean, serviceFormBean)` → `void` [lines 1464–1876]

**Purpose**: Processes and consolidates form input data for submission. This is the most data-processing-intensive method in the class.

**Key operations**:
- Retrieves the selected telecom carrier from the combo box.
- Copies registration-relevant fields from both beans.
- Assembles the full phone number from area code, local code, and subscriber number.
- Extracts the 7-digit prefix for the `judgeKyokuNo` (exchange office determination).
- Handles the number portability selection (`bmpUm`):
  - If `"0"` (not continuing): clears all NTT contract info fields.
  - If `"1"` (continuing): populates NTT contract info based on the installation location choice (`stcPlaceAdChoice`):
    - Use current service location
    - Use contract address
    - Custom address
- Handles the contract name choice (`kshnmChoice`):
  - Same as applicant: copies from existing customer info
  - Different: combines given/family name from form input, handling individual vs. corporate types.
- Sets the number porting notification service registration flag.
- Determines if a pricing code change is needed.
- Creates a single registration detail record (the backend requires exactly one record).

### `checkInitError(outputMap)` → `void` [lines 1887–2151]

**Purpose**: Validates the results from `executeInitService()`. Throws `JCCBusinessException` if any validation fails.

**Validation checks performed**:
1. **Contract existence**: The eo Hikari Phone contract information screen must return exactly one record.
2. **Equipment provider contract**: Must return exactly one record (or 2+ if multi-router retention is available).
3. **Work case equipment availability**: No active work cases with equipment in use.
4. **Contract state**: Must be `"100"` (service in progress), `"030"`, or `"020"`.
5. **Pricing code**: Must be `"A31"` (1st service co-schedule).
6. **Pricing plan code**: Must be one of PA3101–PA3104 (1st service fixed-price plans).
7. **Duplicate application check**: No duplicate service contract internal details numbers.
8. **Pending change check**: No pending modification agreements (異動予約).

### `checkCfmMskmError(outputMap, funcCode)` → `void` [lines 2168–2241]

**Purpose**: Validates the results from `executeCfmMskmService()`. Handles two types of validation:
- **Number port possibility check** (`FUSV004203CC`): If an error occurs and `funcCode` is `"2"` (check), displays an inline error. If `"1"` (submit), throws an exception.
- **Same-number call forwarding possibility check** (`FUSV004207CC`): Same treatment.

### `handleInitException(se)` → `void` [lines 2252–2274]

**Purpose**: Error handler for `executeInitService()`. If the error is a single-field check error (`status = "1000"`), throws a contract state error. Otherwise, throws a system error.

### `handleMskmException(se, funcCode)` → `void` [lines 2289–2389]

**Purpose**: Error handler for `executeCfmMskmService()`. This is the most sophisticated error handler, handling many specific error scenarios:
- **Number port check error** (`EZM0121D010` / `key_telno`): Inline error for check mode.
- **Phone number master change error** (`FUW004203SC`): Duplicate phone number detected → inline error for check mode.
- **Prefix one-agreement error** (`ETU0071A010`): Inline error for check mode.
- **Timestamp conflict** (`upd_dtm_bf`): Update impossible error.
- **Displacement reservation** (`ido_div`): Contract state error.
- Other errors are treated as system errors.

### `hasMultiPhoneCall(outputMap, svcKeiNo)` → `String` [lines 2560–2632]

**Purpose**: Checks if the customer's service contract has multi-function features (multi-phone call capability). Returns `"1"` if multi-function is available, `"0"` otherwise. Performs a deep traversal of the customer hierarchy to find equipment option service contracts with code `G02` (phone adaptor) in active states.

### `hasWarikomiPhone(outputMap, svcKeiNo)` → `String` [lines 2642–2689]

**Purpose**: Checks if the customer's service contract has bundled phone services (割込電話). Returns `"1"` if bundled services exist, `"0"` otherwise. Delegates to `hasWrikomoi()` for the actual check.

### `hasWrikomoi(svc_kei_ucwk_infoArray)` → `boolean` [lines 2691–2712]

**Purpose**: Inner helper used by `hasWarikomiPhone()`. Traverses nested data bean arrays to find option service contracts with code `B023` that are not in terminated (`910`) or canceled (`920`) state.

### `createAdSearchDataMap()` → `HashMap<String, Object>` [lines 2420–2448]

**Purpose**: Generates screen transition data for the address search popup. Copies the postal code (front and back parts) from the service form bean into a map that will be passed to the address search popup screen.

### `setPlanCdInfo(commonInfoBean, serviceFormBean)` → `void` [lines 2460–2508]

**Purpose**: Determines the 2nd pricing plan code and mansion judgment flag based on the 1st pricing plan code. Uses the `PPLAN_CD_CTRL_LIST` constant array which defines the mapping between 1st plan codes and their corresponding 2nd plan codes, split by property type (home/maison vs. mansion).

## Relationships

```mermaid
flowchart TD
    A["WEBGAMEN_FUW014030PJP"] --> B["FUW01403SFLogic"]
    C["WEBGAMEN_FUW014040PJP"] --> B
    D["WEBGAMEN_FUW014050PJP"] --> B
    E["x31business_logic_FUW01403SF"] --> B
    B --> F["JCCWebBusinessLogic"]

    subgraph ScreenFlow ["Screen Flow"]
        G["init - Initial Display"] --> H["cfm - Confirmation"]
        H --> I["mskm - Submission"]
    end

    B --> G
```

**Inbound connections (4 classes depend on this)**:
- `WEBGAMEN_FUW014030PJP.xml` — The initial display screen's presentation layer (screen FUW01403).
- `WEBGAMEN_FUW014040PJP.xml` — The confirmation screen's presentation layer (screen FUW01404).
- `WEBGAMEN_FUW014050PJP.xml` — The completion screen's presentation layer (screen FUW01405).
- `x31business_logic_FUW01403SF.xml` — The business logic XML configuration that wires the screen to this logic class.

**Outbound dependencies**:
- `JCCWebBusinessLogic` — The parent class providing base infrastructure for web screen logic, including DataBean management, screen navigation, and service invocation.

**Key collaborators (used internally)**:
- `JFUWebCommon` — Shared web utilities for screen info, property access, data bean creation, and service result processing.
- `JPCUtilCommon` — General utilities for date comparison and number formatting.
- `JZMCommonUtil` — Address formatting utilities.
- `FUSV0041_FUSV0041OPDBMapper` / `FUSV0042_FUSV0042OPDBMapper` — Auto-generated DataBean-BP mapping classes.
- `X31SDataBeanAccess` — The framework's form data container.

## Usage Example

The typical calling pattern for this class is managed by the web framework:

```
1. User navigates to screen FUW01403
   → Framework instantiates FUW01403SFLogic
   → Framework calls init()
   → init() populates form beans with customer data, pricing, address info
   → Framework renders the input HTML page

2. User fills in phone number, carrier, and optional fields
   → User clicks "確認" (confirm) button
   → Framework calls cfm()
   → cfm() validates data and calls executeCfmMskmService(funcCode="2")
   → If validation passes, next screen is set to FUW01404
   → Framework renders the confirmation HTML page

3. User reviews and clicks "申し込む" (submit) button
   → Framework calls mskm()
   → mskm() calls executeCfmMskmService(funcCode="1") to submit
   → On success, navigates to completion screen FUW01405
```

Example of accessing a customer data field from within the logic:

```java
X31SDataBeanAccess commonInfoBean = getCommonInfoBean();
X31SDataBeanAccess genCustKeiInfo =
    JFUWebCommon.getDataBeanTypeByPath(commonInfoBean, JFUWebCommon.GEN_CUST_KEI_INFO);
String customerName = genCustKeiInfo.sendMessageString(CommonInfoCFConst.CUST_NM_22, GET);
```

Example of checking a pricing plan:

```java
String pplanCd = svcKeiInfo.sendMessageString(CommonInfoCFConst.PPLAN_CD_23, GET);
if (pplanCd.equals(CD00565_PA3101)) {
    // Home type - applies home-specific pricing rules
}
```

## Notes for Developers

1. **Single-threaded**: This class is instantiated per request by the web framework. There is no shared mutable state — all fields are `static final` constants. Each request gets a fresh instance with its own `commonInfoBean` and `serviceFormBean`.

2. **Large method sizes**: Several methods are very long (e.g., `editRegData` at ~412 lines, `checkInitError` at ~264 lines, `handleMskmException` at ~100 lines). These could benefit from extraction into smaller private helper methods, but they follow a consistent pattern of "read → validate → set" that makes them traceable.

3. **Japanese domain terminology**: The codebase uses Japanese romanization throughout (e.g., `keisha` = 契約者 = contract holder, `mskm` = 申請 = application, `cfm` = 確認 = confirmation, `kaisen` = 回線 = line). The class name `FUW01403SFLogic` encodes a screen ID within the web application.

4. **Error code conventions**: Error codes follow a consistent pattern:
   - `0002` — System error (unrecoverable)
   - `0102` — Contract state error (invalid contract for this operation)
   - `0203` — Contract change in progress (pending modifications block this operation)
   - `0204` — Update impossible (conflict with concurrent updates)

5. **Pricing plan code mapping**: The `PPLAN_CD_CTRL_LIST` constant is critical for correct pricing. It maps 1st plan codes to 2nd plan codes and a mansion flag. Adding a new plan requires updating this array. The plan codes `PA3101`–`PA3104` correspond to:
   - `PA3101`: 1st service fixed-price plan (home/maison)
   - `PA3102`: 1st service fixed-price plan (mansion)
   - `PA3103`: 1st service fixed-price plan (home/maison variant)
   - `PA3104`: 1st service fixed-price plan (mansion variant)

6. **Phone number formatting**: Phone numbers are assembled from three parts (`telArea` + `telLocal` + `telSubscriber`) and padded with 7 spaces to safely extract the 7-digit prefix using `(telno + "       ").substring(0, 7).trim()`.

7. **Address formatting**: The `JZMCommonUtil.getPtn01()` utility combines the seven address components (prefecture, city, district, town, lot number, building, room) into a single display string using a standard Japanese address format pattern.

8. **Number portability branch**: The `editRegData()` method's number portability handling has three sub-branches (current location, contract address, custom address) each with different data mapping rules. Changes to one branch may need to be reflected in the others.

9. **Screen transition safety**: All public methods always set `NEXT_SCREEN_ID` and `NEXT_SCREEN_NAME` on the `commonInfoBean` before returning. This is essential — if a method throws an unhandled exception before setting the next screen, the framework may not know where to navigate.

10. **Work case check**: The `checkInitError()` method validates that no active work cases exist with equipment in use (work states 130–190). This prevents applications that would conflict with ongoing field work.
