# FUW05401SFLogic

## Purpose

`FUW05401SFLogic` is the central business logic facade for the **eo Optical Fiber Telephone Option Service Subscription/Cancellation** module. It orchestrates the entire lifecycle of telecom option service management — from initial screen display (gathering pricing, contract status, and available services) through confirmation, submission, cancellation, and modification flows. It appears in 34 inbound connections, making it the critical aggregation point for option service screen controllers.

This class sits between the web screen controllers (XML-defined page handlers) and the backend service layer (FUSV0031, FUSV0032, FUSV0033, FUSV0207), handling all business rules, validation, navigation, and state preparation for a set of eleven related screen features.

## Design

`FUW05401SFLogic` follows the **facade pattern** within the framework's business logic tier. It extends `JCCWebBusinessLogic` (the framework's base business logic class) and provides a single entry point for all option service screens in the FUW054/FUW055 functional families. The class manages three transaction divisions (`TRAN_DIV`):

| Code | Value | Meaning |
|------|-------|---------|
| `TRAN_DIV_MSKM` | `"1"` | Subscription (申込) |
| `TRAN_DIV_DSL` | `"2"` | Cancellation (解約) |
| `TRAN_DIV_CHG` | `"3"` | Modification (変更) |

These three divisions flow through a shared pipeline: initial display (`init`) → confirmation (`cfm`) → submit/cancel (`mskmDsl`) or back (`back`). The screen ID suffixes follow a consistent convention: `01` = subscription screen, `02` = confirmation screen, `03` = completion screen.

The class is **not thread-safe** — it operates on per-request `X31SDataBeanAccess` instances and relies on the framework's request-scoped bean management.

## Key Methods

### Public Methods

#### `init() → boolean` [lines 526–674]

The primary entry point, called on the initial display of the option service subscription/cancellation screen (screen ID `FUW05401`). This method orchestrates the entire initialization pipeline:

1. **Retains screen info** — pulls the source screen ID and processing division from the navigation context via `JFUWebCommon.getScreenInfo(this)`.
2. **Gets beans** — retrieves the `commonInfoBean` (shared form) and `bean` (service form bean) from the framework.
3. **Determines the functional screen ID** — calls `getRonriScreenId()` to extract a 6-character functional ID (e.g., `FUW054`, `FUW055`) from the navigation context.
4. **Common relation check** — calls `JFUWebCommon.checkCommonRelation(this, SVC_ID_INIT)` for pre-check validation against service `FUSV0031`.
5. **Refreshes customer contract** — if the source screen ID is set, calls `JFUWebCommon.refreshGenCustKei(this)` to update customer contract data.
6. **Sets service interface parameters** — calls `paramForFUSV0031()` which in turn calls `setCommonInfoBeanToSvcFormBean()` and `setOpSvcInfo()`, populating the bean with SSO information, service codes, pricing codes, and processing flags for the current functional screen.
7. **Retrieves service contract info** — calls `setSvcKeiInfo()` to copy service contract data from the shared bean to the service form bean.
8. **Calls initial display service** — invokes `callSvcFUSV0031()` to fetch option service list, pricing plans, opt-in eligibility checks, and related data from the backend service `FUSV0031`.
9. **Extracts target records** — calls `getTranTrgtRecOp()` to filter the option service contract records matching the current service code.
10. **Checks for init errors** — calls `checkInitError()` to validate contract existence, status, and pending reservations.
11. **Parses parent contract info** — calls `setOyaKeiInfo()` to copy parent service contract internal numbers and flags.
12. **Runs various tran calculations** — calls `runVariTranForTrgtKeiRec()` to determine contract counts, reservation counts, and auto-set `tran_div` if not specified. Returns a `kensuMap` (count map) with:
    - `RSV_TTDKI_CNT` — pending reservation count
    - `KEIYAKU_CHU_CNT` — active contract count
    - `DOUGETU_DSL_CNT` — same-month cancellation count
13. **Gets discount service code** — calls `getPackScreenWribSvcCd()` to determine if a discount package applies and would redirect to a package screen.
14. **Runs judgment checks** — calls `runVariJudge()` to validate business rules (see below).
15. **Sets transaction target key info** — calls `setTranTrgtKeyInfo()` to transfer key fields from target records to the bean.
16. **Sets call charge limit** — calls `setTwryoStiam()` to handle the call charge limit notification amount setting (for screen `FUW102`).
17. **Sets price information** — calls `setPrcInfoAreaEoTelOp()` to populate pricing display area based on free/paid flag.
18. **Sets transfer page info** — if a discount package is applicable, sets up screen info for the package screen (`FUW11001`) with a `createDataMapForPack()` call. Otherwise, sets the next screen name to the subscription confirmation screen name.
19. **Sets current day pricing** — calls `JFUWebCommon.setPrcDspNowDay(this)`.

Returns `true` (hardcoded) — the return value is not used for navigation control.

#### `cfm() → boolean` [lines 1775–1809]

The **confirmation button** handler. Called when the user presses the confirmation (確定) button on the initial display screen.

1. Retrieves beans and the functional screen ID.
2. Calls `chkPreAndExecMskm(bean, commonInfoBean, funcCd="2", ronriScreenId)` — this runs the common relation check with the subscription service ID (`FUSV0032`) and invokes the subscription service, then checks for business errors. Note that `funcCd="2"` means the common relation check is performed with subscription-side checking.
3. Sets the next screen ID and name to the confirmation screen (`<ronriScreenId>02`, e.g., `FUW05402`) via `getCfmScreenId()` / `getCfmScreenName()`.

The `cfm()` method prepares the screen for the confirmation display by running pre-checks and executing the subscription service call.

#### `back() → boolean` [lines 1821–1847]

The **back button** handler. Called when the user presses the back (戻る) button on the confirmation screen. Simply sets the next screen to the subscription screen (`<ronriScreenId>01`) — no validation or service calls are performed. This is a pass-through navigation.

#### `mskmDsl() → boolean` [lines 1855–1897]

The **submit/cancel button** handler (submit: 申込 / cancel: 解約). Called when the user confirms and submits (or cancels) on the confirmation screen.

1. Retrieves beans and the functional screen ID.
2. Calls `chkPreAndExecMskm(bean, commonInfoBean, funcCd="1", ronriScreenId)` — this runs the common relation check (without prompting check for subscription) and executes the appropriate backend service based on `tran_div`:
    - `"1"` (subscription) → calls `FUSV0032` (option service subscription/cancellation — subscription)
    - `"2"` (cancellation) → calls `FUSV0033` (option service subscription/cancellation — cancellation)
    - `"3"` (modification) → calls `FUSV0207` (option service subscription/cancellation — modification)
3. Sets up completed email info via `setMskmMailInfo()` — dispatches the appropriate completion email template based on the functional screen ID and transaction division.
4. Refreshes current customer contracts via `JFUWebCommon.refreshGenCustKei(this)`.
5. Sets the next screen ID and name to the completion screen (`<ronriScreenId>03`, e.g., `FUW05403`) via `getFinScreenId()` / `getFinScreenName()`.

### Core Private Methods

#### `runVariTranForTrgtKeiRec(commonInfoBean, bean, tranTrgtRecOpArray) → HashMap<String, Integer>` [lines 1205–1377]

This is the **contract state analysis** engine. It iterates through all target option/sub-option contract records and counts them by state, then performs auto-set of the transaction division.

Counts tracked:
- **rsvTtdkiCnt** — pending reservation count (status `"010"`: 受注済). Checks both option and sub-option service contract statuses.
- **keiyakuChuCnt** — active contract count (status `"020"`: 照会済, `"030"`: 締結済, `"100"`: サービス提供中).
- **dougetuDslCnt** — same-month cancellation count. Records with status `"910"` (解約済: cancelled) where the reservation apply date falls within the current month.

Additionally, it scans the service contract info list for **pending reservation details** — if a pack-eligible option has status `"010"` or reservation detail code set, it sets a `reserveFlag` on the bean.

If `rsvTtdkiCnt > 0` or `reserveFlag` is set, throws `ERROR_CODE_0203` (contract change procedure in progress error).

Calls `judgeTranDiv(bean, kensuMap)` which:
- For `"1"` (subscription): throws `ERROR_CODE_0201` if `keiyakuChuCnt > 0` (customer already has active contracts).
- For `"2"` or `"3"` (cancel/mod): throws `ERROR_CODE_0201` if `keiyakuChuCnt == 0` (no active contracts to cancel/modify).
- If `tran_div` is null (external system navigation): auto-detects — `"1"` if no active contracts, `"2"` (cancel) if active contracts exist and it's not the call charge limit notification service, `"3"` (modify) if it IS the call charge limit notification service.

For subscription or modification, calls `checkTokusokuStat()` to verify the customer is not in a collection/dunning status ≥ 15 (強制解約予告済).

Returns the `kensuMap` with the three counts.

#### `runVariJudge(bean, tranTrgtRecOpArray, kensuMap) → void` [lines 966–1129]

A **multi-rule validation** method covering:

1. **Telecom suspension error block** — for FUW055 (ported telephone) subscription, always throws `ERROR_CODE_0002` (system error). This is a hard business rule (AN-linked restriction).
2. **WEB option add-not-allowed check** — if `tran_div = "1"` and `WEB_OP_ADD_FAIL_FLG = "1"`, throws `ERROR_CODE_0101` (usage restriction error).
3. **050 option re-submission restriction** — if `tran_div = "1"`, 050 option processing is required, and `dougetuDslCnt > 0`, throws `ERROR_CODE_0101`. This prevents re-submitting 050 number within the same month after cancellation.
4. **Max option service count check** — retrieves `max_op_svc_cnt` from pricing. For cost code `"A32"` (No. 2 cost), the max is halved. Throws `ERROR_CODE_0101` if `keiyakuChuCnt >= max`.
5. **Free/paid determination** — counts free option services and applies the same A32 halving. If `keiyakuChuCnt + rsvTtdkiCnt < mryo_op_svc_cnt`, sets `mryo_flg = "1"` (free). Otherwise checks the fixed plan price — if zero, marks free; otherwise marks paid (`mryo_flg = "0"`).
6. **Sub-option submission eligibility** — if `tran_div = "1"` and sub-option processing is required, throws `ERROR_CODE_0102` (contract status error) if there are zero target records or the option contract status is `"910"` (already cancelled).
7. **Sub-option cancellation necessity** — calls `sbopDslYhJudge()` (see below).

#### `sbopDslYhJudge(bean, tranTrgtRecOpArray) → void` [lines 1142–1188]

Determines whether a sub-option cancellation is required when processing an option cancellation (`tran_div = "2"` and `op_tran_flg = "1"`). Sets `sbop_tran_flg` to:
- `"1"` (required) if sub-option status is `"020"`, `"030"`, or `"100"`.
- `"0"` (not required) if sub-option status is null, empty, `"910"`, or `"920"`.
- Throws `ERROR_CODE_0102` for any other unexpected sub-option status.

#### `checkInitError(bean, commonInfoBean, tranTrgtRecOpArray) → void` [lines 1622–1731]

Pre-flight validation on initial display:
- **(a) Service contract existence** — throws `ERROR_CODE_0102` if service contract list or machine provision contract list has zero records.
- **(b) Service contract status** — throws `ERROR_CODE_0102` if the internal contract status is not `"020"`, `"030"`, or `"100"`.
- **(b) Sub-option contract status** — if sub-option processing is required, validates the first target record's option contract status.
- **(c) Pending reservation existence** — if option or sub-option processing is required, checks for pending reservation detail codes on target records. Throws `ERROR_CODE_0203` if found.
- **(d) Master data integrity** — throws `ERROR_CODE_0002` if the pricing code option service list has zero records.

#### `callSvcFUSV0031(bean, commonInfoBean) → HashMap<String, Object>` [lines 1480–1564]

Invokes the **initial display service** (`FUSV0031 — eo Optical Fiber Telephone Option Service Subscription/Cancellation`). Uses `FUSV0031_FUSV0031OPDBMapper` to map inputs and outputs for:
- Service contract list (EKK0081B508)
- Machine provision contract list (EKK0341B002)
- Pricing code option service agreement (EKK0811A010)
- Pricing plan fixed unit price — option subscription fee (EKK0601B001, two calls)
- Business parameter management (EKK0601B501)
- Machine option service contract list — front (EKK2811B053)
- Machine option service contract list — compound search (EKK2811B504)
- Phone Select Option Pack Operate CC
- JFUTelOpMskmCheckCC (tel op eligibility check)

Catches `JCCWebServiceException` and delegates to `handleInitException()`. After the service call, checks `TEL_OP_MSKM_CHECK_KEY` — if `mskmKhFlg = "1"`, throws `ERROR_CODE_0102` (submission not allowed). Returns the full output map for downstream price info processing.

#### `callSvcMskm(bean, commonInfoBean, funcCd) → void` [lines 2018–2042]

**Service call dispatcher** for the submit/cancel flow. Routes to the appropriate service based on `tran_div`:
- `"1"` → `callSvcFUSV0032()` (subscription)
- `"2"` → `callSvcFUSV0033()` (cancellation)
- `"3"` → `callSvcFUSV0207()` (modification)

#### `callSvcFUSV0032(bean, commonInfoBean, funcCd) → void` [lines 2052–2128]

Invokes the **subscription service** (`FUSV0032`). Maps a comprehensive set of input/output operations including:
- Work item mapping
- Telecom operator list (ETU0051B010)
- Phone number list (EZM0121B010)
- Engineering target registration (EZM0111D010)
- Content registration/confirmation (EKK0011D020, EKK0371C010, etc.)
- Option/sub-option contract registration and confirmation
- Start-of-use registrations
- Submission registration
- Billing registration (EKK1091D010)
- Submission detail check / follow-up request (EKK0021C060)
- SOD issuance (`setFUSV003202CC()`)

Clears the phone number list array before calling. Sets service contract internal status and option contract status via `JFUWebCommon` helpers. Catches `JCCWebServiceException` and delegates to `handleMskmException()`.

#### `callSvcFUSV0033(bean, commonInfoBean, funcCd) → void` [lines 2249–2327]

Invokes the **cancellation service** (`FUSV0033`). Maps:
- Content registration (EKK0011D020)
- Sub-option contract cancellation and confirmation (EKK0401C170, EKK0401C180, EKK0401C150)
- Option contract cancellation and confirmation (EKK0351C240, EKK0351C250, EKK0351C220)
- Engineering use termination (EZM0111C010)
- Billing registration (EKK1091D010)
- Non-billing determination (JFUHiChrgJdgCC)
- SOD issuance with `tran_flg = true` (indicates cancellation/restore flow)
- Option/sub-option status setup and registration

#### `callSvcFUSV0207(bean, commonInfoBean, funcCd) → void` [lines 2337–2374]

Invokes the **modification service** (`FUSV0207`). Maps:
- Content registration (EKK0011D020)
- Option contract information change (EKK0371C050)
- Billing registration (EKK1091D010)
- Submission detail check / follow-up request (EKK0021C060)
- eo Optical Fiber telephone connection over-limit notification code change (EAC0401C020)

#### `setFUSV003202CC(bean[], outputMap, func_code, tran_flg) → HashMap<String, Object>` [lines 2140–2239]

Builds the **SOD (Service Order Document) issuance request** map. For each machine provision service contract record, constructs a nested map containing:
- SYSID, IDO_DIV (異動区分)
- Service contract number, service contract internal info (with change-after registration datetime)
- Option contract info (change-before number and datetimes, conditionally set for cancellation/restore/sub-option submission flows)
- Machine provision internal info (change-after number and datetimes)

Sets `req_data_list` and returns the parent map under `HAKKO_SOD_MAP`.

#### `chkPreAndExecMskm(bean, commonInfoBean, funcCd, ronriScreenId) → void` [lines 1908–1956]

**Pre-check and execute** wrapper for submit/cancel. If `funcCd = "1"`, performs a common relation check using the appropriate service ID based on `tran_div` (subscription: FUSV0032, cancellation: FUSV0033, modification: FUSV0032). Then calls `callSvcMskm()` and, for submission only, runs `checkMskmError()`.

#### `checkMskmError(bean) → void` [lines 1964–2006]

Post-submission validation. Specifically checks the **050 phone number dial-out**. If 050 processing is required and the phone number list is empty or the number is null, throws `ERROR_CODE_0002`. Otherwise, copies the first phone number from the list to the bean for the completion screen display.

#### `handleInitException(se) → void` [lines 1741–1767]

Handles exceptions from `callSvcFUSV0031()`. If the status is `"1000"` (single item check error), throws `ERROR_CODE_0102` (contract status error) — these cannot be corrected on-screen. Otherwise throws `ERROR_CODE_0002` (system error).

#### `handleMskmException(se) → void` [lines 2382–2424]

Handles exceptions from `callSvcMskm()` (FUSV0032/0033/0207). Checks:
- Status `"1100"` (internal schema check error) → `ERROR_CODE_0204` (update impossible error).
- Status `"1300"` (external schema correlation error) with itemID `"ido_div"` → `ERROR_CODE_0102` (contract status error).
- Otherwise → `ERROR_CODE_0002` (system error).

#### `setTranTrgtKeyInfo(bean, tranTrgtRecOpArray) → void` [lines 683–740]

Copies key fields from the target option contract record (index 0) to the service form bean:
- Subscription registration detail — sets form code `"06"` and submission form code `"01"` (WEB).
- Dispute reason detail — sets reason code `"56"` (etc.).
- Option service contract number, sub-option service contract number, engineering number, engineering last update datetime, 050 option phone number.

Also creates the single required records for subscription detail and dispute reason lists, since the subscription service IF requires at least one record per single-item related constraint.

#### `setTwryoStiam(bean, tranTrgtRecOpArray) → void` [lines 749–792]

Sets the **call charge limit notification designated amount** (`TWRYO_STIAM_TTU_TCHI_STIAM`). Only for screen `FUW102` (call charge limit notification). If the contract status is `"020"`, `"030"`, or `"100"`, copies from the service record; otherwise uses the work parameter value. Uses `cutTwryo()` to truncate the last 3 characters (millisecond precision).

#### `cutTwryo(String par) → String` [lines 800–811]

Utility that truncates a numeric string by removing the last 3 characters (converting from yen-with-milliseconds to yen).

#### `setOpSvcInfo(bean, ronriScreenId) → void` [lines 845–875]

Sets all service codes and processing flags on the bean by looking up the current functional screen ID in the various mapping maps:
- Option service code (`OP_SVC_CD`)
- Sub-option service code (`SBOP_SVC_CD`)
- Pricing codes (KK0351, KK0401, KK0601 for both `pcrs_cd` and `pplan_cd`)
- Processing flags (050 option, option, sub-option, service order data)

#### `setCommonInfoBeanToSvcFormBean(bean, commonInfoBean) → void` [lines 884–917]

Copies SSO and contract context from the shared bean to the service form bean: SYSID, service contract number, phone number, pricing codes (KK0081), and invoice contract number.

#### `setOyaKeiInfo(bean) → void` [lines 925–945]

Copies parent service contract internal info from the first service contract record: internal contract number, internal contract division number, and WEB option add-not-allowed flag.

#### `setSvcKeiInfo(commonInfoBean, serviceFormBean) → void` [lines 3272–3290]

Copies the current subscription service contract number and internal number from the shared form to the service form bean (used for the discount package service mapping).

#### `getTranTrgtRecOp(bean) → X31SDataBeanAccess[]` [lines 1386–1404]

Extracts option service contract records matching the current option service code from the service contract info list.

#### `judgeTranDiv(bean, kensuMap) → void` [lines 1413–1470]

Validates and potentially auto-sets the transaction division. For subscription, requires zero active contracts. For cancel/modify, requires at least one active contract. If `tran_div` is null (external navigation), auto-detects based on contract state and the specific service type.

#### `setPrcInfoAreaEoTelOp(bean, outputMap, ronriScreenId) → void` [lines 1577–1612]

Sets the price information display area. If free (`mryo_flg = "1"`), uses the free pricing map. Otherwise calls `JFUWebCommon.setPrcInfoArea()` with the appropriate screen ID (`FUW06201` for 050 number plan, `FUW05401` for others).

#### `getRonriScreenId(commonInfoBean) → String` [lines 2797–2807]

Extracts the 6-character functional screen ID by taking the first 6 characters of `NEXT_SCREEN_ID` from the common info bean.

### Screen-to-Service Code Mappings

The class defines 11 functional screen IDs, each mapped to option service codes, pricing codes, and screen IDs:

| Functional ID | Japanese Name | Option SVC Code |
|---|---|---|
| `FUW054` | Split Telephone (割込電話) | `CD00136_B023` |
| `FUW055` | Ported Telephone (転送電話) | `CD00136_B024` |
| `FUW056` | Ported Telephone Selection (転送電話選択) | `CD00136_B024` (sub) |
| `FUW057` | Caller ID Display (発信者番号表示) | `CD00136_B025` |
| `FUW058` | Non-notice Rejection (非通知着信拒否) | `CD00136_B025` (sub) |
| `FUW059` | Confused Call Rejection (迷惑電話拒否) | `CD00136_B026` |
| `FUW060` | Designated Number Selection (指定番号着信選択) | `CD00136_B027` |
| `FUW061` | Call Detail Delivery (通話明細送付) | `CD00136_B028` |
| `FUW062` | 050 Number Plan (050ナンバープラン) | `CD00136_B029` |
| `FUW102` | Call Charge Upper Limit Notification (通話料指定額到達お知らせ) | `CD00136_B072` |
| `FUW103` | International Call Usage Suspension (国際電話利用停止) | `CD00136_B071` |

### Other Notable Methods

#### `setMskmMailInfo(bean, ronriScreenId) → void` [lines 2816–2973]

Dispatches completion emails after a successful submission. Uses `JFUWebCommon.sendMskmFinMail()` with screen-specific email template IDs. For `FUW054` (split telephone), different templates are used for single vs. multiple calls (`FUW054_1`/`FUW054_3` for subscription, `FUW054_2`/`FUW054_4` for cancellation), determined by the `MULTI_PHONE_CALL_FLG` bean field.

#### `getOptPackPrcList(serviceFormBean) → ArrayList<HashMap<String, String>>` [lines 2983–3171]

Builds the list of pricing information for option services. Iterates through service contract records, filtering for pack-eligible services, skipping cancelled/cancelled-records, and looking up pricing codes from the `OP_PRC_LIST` constant. Returns a list of maps with `pcrs_cd` and `pplan_cd` entries used by `JFUWebCommon.getTelOptPack()` for discount package eligibility determination.

#### `chkOpInPack(ronriScreenId) → boolean` [lines 3180–3206]

Determines if the current functional screen's option service is eligible for pack application by checking if its service code appears in `TEL_PACK_OPT_LIST`.

#### `createDataMapForPack(tranDiv, wribSvcCd, opSvcCd) → HashMap<String, Object>` [lines 3217–3262]

Builds the data map for inter-screen navigation to the option pack screen (`FUW11001`). Contains: source screen ID, transaction division, discount service code, pricing code, pricing plan code, option service code, and multi-call flag.

#### `getPackScreenWribSvcCd(bean) → String` [lines 3300–3351]

Determines which discount package service code to pass to the pack screen. Calls `chkOpInPack()`, retrieves the option pricing list, runs the discount judgment via `JFUWebCommon.getTelOptPack()`, and compares the result against the current service contract's discount code to determine the package type (`KK0841_WRIB_SVC_CD_TEL_OP_PACK3` or `KK0841_WRIB_SVC_CD_TEL_OP_PACK7`).

#### `checkTokusokuStat(commonInfoBean) → void` [lines 3359–3395]

Checks the customer's collection/dunning status. Navigates the bean hierarchy (web change info → current customer → service contract → invoice contract) and reads the `tokusoku_stat` field. If the status is >= `"15"` (強制解約予告済: forced cancellation notice given), throws `ERROR_CODE_0104` (collection status error).

#### `getX31SDataBeanAccess(bean, componentID) → X31SDataBeanAccess` [lines 3406–3416]

Utility to safely retrieve (or create) the first child DataBean from a list by component ID.

## Relationships

### Who Uses This Class

Five screen controller XML definitions reference `FUW05401SFLogic`:

```mermaid
flowchart TD
    subgraph Consumers ["Screen Controller XMLs"]
        XML1["WEBGAMEN_FUW054010PJP.xml"]
        XML2["WEBGAMEN_FUW054020PJP.xml"]
        XML3["WEBGAMEN_FUW054030PJP.xml"]
        XML4["WEBGAMEN_FUW055010PJP.xml"]
        XML5["WEBGAMEN_FUW055020PJP.xml"]
    end

    Logic["FUW05401SFLogic<br/>Business Logic Facade"]

    subgraph Services ["External Services"]
        FUSV0031["FUSV0031<br/>Initial Display"]
        FUSV0032["FUSV0032<br/>Subscription"]
        FUSV0033["FUSV0033<br/>Cancellation"]
        FUSV0207["FUSV0207<br/>Modification"]
    end

    Logic --> FUSV0031
    Logic --> FUSV0032
    Logic --> FUSV0033
    Logic --> FUSV0207

    XML1 --> Logic
    XML2 --> Logic
    XML3 --> Logic
    XML4 --> Logic
    XML5 --> Logic
```

- **`WEBGAMEN_FUW054010PJP.xml`** — Initial display screen controller for FUW054 (split telephone option service). Calls `init()`.
- **`WEBGAMEN_FUW054020PJP.xml`** — Confirmation screen controller for FUW054. Calls `cfm()`, `back()`.
- **`WEBGAMEN_FUW054030PJP.xml`** — Completion screen controller for FUW054.
- **`WEBGAMEN_FUW055010PJP.xml`** — Initial display for FUW055 (ported telephone). Calls `init()`, `mskmDsl()`.
- **`WEBGAMEN_FUW055020PJP.xml`** — Confirmation for FUW055. Calls `cfm()`, `back()`.

### Outbound Dependencies

- **`JCCWebBusinessLogic`** — The parent class providing base service invocation, bean management, and logging infrastructure.
- **`JFUWebCommon`** — Framework utility class for screen navigation, data bean access, date operations, pricing display, common relation checks, SOD issuance, customer refresh, and service status setup.
- **`JFUCommonUtil`** — Utility for null checks.
- **`JPCUtilCommon`** — Utility for date comparison (past date checking).
- **`JFUStrConst` / `JFUScreenConst`** — Constants for codes, screen IDs, screen names, error codes.
- **`FUW05401SFConst`** — Local constants specific to this logic class.
- **`X31SDataBeanAccess` / `X31SDataBeanAccessArray`** — Framework data bean types for structured data transfer.
- **`JCCWebServiceException` / `JCCBusinessException`** — Framework exception types.
- **`FUSV0031_FUSV0031OPDBMapper`**, **`FUSV0032_FUSV0032OPDBMapper`**, etc. — Auto-generated DataBean-BP mappers for each service call.

### Data Flow

```mermaid
flowchart LR
    subgraph XML ["Screen Controllers"]
        ctrl["XML Page Handler"]
    end

    subgraph Logic ["FUW05401SFLogic"]
        init["init()"]
        cfm["cfm()"]
        mskmDsl["mskmDsl()"]
        judge["runVariJudge()"]
        svc["callSvcFUSV003x()"]
        mail["setMskmMailInfo()"]
    end

    subgraph Svc ["Backend Services"]
        s1["FUSV0031<br/>Initial Display"]
        s2["FUSV0032<br/>Subscription"]
        s3["FUSV0033<br/>Cancellation"]
        s4["FUSV0207<br/>Modification"]
    end

    subgraph Beans ["Data Beans"]
        cib["commonInfoBean<br/>(Shared Context)"]
        sfb["serviceFormBean<br/>(Service Form)"]
    end

    ctrl --> init
    init --> svc
    svc --> s1
    s1 --> cib
    s1 --> sfb
    init --> judge
    init --> cfm
    cfm --> svc
    svc --> s2
    cfm --> mskmDsl
    mskmDsl --> svc
    svc --> s3
    svc --> s4
    mskmDsl --> mail
```

## Usage Example

The typical calling pattern follows a three-screen flow:

### 1. Initial Display (FUW05401)

The screen controller XML invokes `logic.init()`:

```java
FUW05401SFLogic logic = new FUW05401SFLogic();
logic.init();
// Returns true. Side effects:
// - Bean populated with option service info, pricing, flags
// - Next screen name set to confirmation screen (e.g., "FUW05402")
```

Inside `init()`, the full pipeline runs:
1. Extract functional screen ID (e.g., `"FUW054"` for split telephone).
2. Look up service codes, pricing codes, and flags from mapping maps.
3. Call `FUSV0031` to fetch service contract info, pricing plans, and opt-in eligibility.
4. Filter target option contract records by service code.
5. Validate business rules (contract existence, status, pending reservations, master data integrity).
6. Count contracts by state (pending, active, same-month cancelled).
7. Validate: max option count, free/paid determination, sub-option eligibility.
8. Set transfer page info if a discount package is applicable (redirect to `FUW11001`).

### 2. Confirmation (FUW05402)

User presses confirmation button → controller calls `logic.cfm()`:

```java
logic.cfm();
// Side effects:
// - Common relation check with subscription service (FUSV0032)
// - Subscription service called
// - Next screen set to completion screen (e.g., "FUW05403")
```

### 3. Completion (after submission)

User presses submit → controller calls `logic.mskmDsl()`:

```java
logic.mskmDsl();
// Side effects:
// - Subscription service called (FUSV0032) with funcCd="1"
// - Completion email dispatched based on screen ID and tran_div
// - Customer contract refreshed
// - Next screen set to completion screen (e.g., "FUW05403")
```

For cancellation, the same `mskmDsl()` path is taken, but with `tran_div = "2"`, routing to `FUSV0033` instead.

## Notes for Developers

### Screen ID Extraction

The functional screen ID (6 characters, e.g., `"FUW054"`) is extracted by taking the first 6 characters of `NEXT_SCREEN_ID` from the common info bean. This determines which of the 11 supported screens is being served and drives all code lookups.

### Mapping Maps Are Static

All service code, pricing code, screen ID, and screen name mappings are defined as `static final` maps initialized with double-brace initialization. These are immutable at runtime and serve as a configuration table that determines which service codes and pricing information are used for each functional screen.

### Transaction Division (tran_div) Auto-Detection

If `tran_div` is null when entering `judgeTranDiv()`, the system auto-detects:
- `"1"` (subscription) — no active contracts.
- `"2"` (cancellation) — active contracts exist AND the service is NOT the call charge limit notification service (`CD00136_B072`).
- `"3"` (modification) — active contracts exist AND the service IS the call charge limit notification service.

This auto-detection path exists to handle external system navigation where the processing division is not specified.

### Hardcoded Error Codes

The class uses `JFUStrConst.ERROR_CODE_*` constants extensively. The key business error codes thrown are:
- `0002` — System error
- `0101` — Usage restriction error (WEB option add-not-allowed, 050 re-submission restriction, max option count exceeded)
- `0102` — Contract status error (no service contract, invalid status, pending reservation, sub-option eligibility)
- `0104` — Collection status error (dunning status >= 15)
- `0201` — Customer info change error (active contract count mismatch for operation type)
- `0203` — Contract change procedure in progress error (pending reservations)
- `0204` — Update impossible error (internal schema check error)

### Call Charge Limit Notification Service (FUW102)

The call charge limit notification service (`CD00136_B072`) has special handling:
- It is the only service that triggers `TRAN_DIV_CHG` (modification) in auto-detection.
- `setTwryoStiam()` only applies to this service.
- It supports the modification flow (tran_div `"3"`) in `mskmDsl()`, dispatching to `FUSV0207`.

### SOD (Service Order Document) Issuance

The `setFUSV003202CC()` method builds a complex nested structure for SOD issuance. It is called from both `callSvcFUSV0032()` (subscription, `tran_flg=false`) and `callSvcFUSV0033()` (cancellation, `tran_flg=true`). The `tran_flg` parameter changes whether change-before data is included in the request.

### Thread Safety

The class has **no thread safety** guarantees. It operates on per-request bean instances and maintains no instance state beyond the inherited framework state. It should only be used in a single-threaded request processing context.

### Maintenance Considerations

- The class contains 11 functional screen IDs, each with its own set of mapping constants. Adding a new option service requires updating **all** mapping maps (`OP_SVC_CD_MAPPING_MAP`, `SBOP_SVC_CD_MAPPING_MAP`, `PCRS_CD_KK0351_MAPPING_MAP`, `PPLAN_CD_KK0351_MAPPING_MAP`, `PCRS_CD_KK0401_MAPPING_MAP`, `PPLAN_CD_KK0401_MAPPING_MAP`, `PCRS_CD_KK0601_MAPPING_MAP`, `PPLAN_CD_KK0601_MAPPING_MAP`, `MSKM_SCREEN_NAME_MAPPING_MAP`, `CFM_SCREEN_NAME_MAPPING_MAP`, `FIN_SCREEN_NAME_MAPPING_MAP`), plus adding entries to `OP_SVC_RONRI_LIST`, `TEL_PACK_OPT_LIST`, and `OP_PRC_LIST`.
- The `setMskmMailInfo()` method has a long if-else chain for email template dispatch — adding a new screen requires adding a case for both subscription (`_1` suffix) and cancellation (`_2` suffix) templates.
- The class uses `JFUWebCommon.setSvcKeiUcwkStat()` and similar v4.00 correction additions (marked with `/* ++++++++++ v4.00 修正開始 ++++++++++ */` comments) — these are framework-dependent and may require framework updates.
