# Business Logic — PartSequencer.transform() [80 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `com.fujitsu.futurity.bp.custom.common.PartSequencer` |
| Layer | CC/Common Component (Package: `com.fujitsu.futurity.bp.custom.common`) |
| Module | `common` (Package: `com.fujitsu.futurity.bp.custom.common`) |

## 1. Role

### PartSequencer.transform()

The `transform` method is a data transformation function responsible for extracting and mapping discount service contract (割引サービス契約) information from an incoming `CAANMsg` message into a `HashMap<String, String>` output structure. It serves as a unified entry point within the PartSequencer that consolidates data from a single, new service interface introduced in v5.00.20, replacing the previous approach that required reading from two separate CBS message lists (EKK0451B005CBSMsg1List and a previous dchskmst path). The method branches on the service discrimination code (`WRIB_DCHS_HAMBET_CD`) to handle two distinct business scenarios: **discount services** (keiKind="1", labeled as "WRIB" for *waribiki*) and **standard/non-discount services** (keiKind="2", labeled as "HNSOKU" for *hansoku* — non-discount). For discount services, it applies a special date calculation: if the start date (`staymd`) is the far-future sentinel value "20991231", it computes a meaningful start date by adding one day to the end date, as introduced in v5.00.24. For non-discount services, it additionally handles a special case for "net phone + TV triple plan" (DT0000002) where start and end dates are cleared because this service type does not have a defined billing period. The method implements the **Transformer design pattern**, receiving a `CAANMsg` input and producing a `HashMap<String, String>` output, and is called by numerous CBS controllers, screen controllers, batch processors, and external system integrators. It is part of the K-Opticom customer base system (eo customer base system) that manages discount/promotional service contracts in a Japanese telecommunications environment.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START["transform(CAANMsg in)"]
    START --> CREATE["Create HashMap out [DEFAULT_HASH_SIZE=50]"]
    CREATE --> GETKEIKIND["Get keiKind = in.getString(WRIB_DCHS_HAMBET_CD)"]
    GETKEIKIND --> COND1{"keiKind equals 1?"}

    COND1 -->|"true: Discount (WRIB)"| GETSTART["Get sYmd = in.getString(SVC_CHRG_DCHSKMST_STAYMD)"]
    GETSTART --> GETEND["Get eYmd = in.getString(SVC_CHRG_DCHSKMST_ENDYMD)"]
    GETEND --> COND2{"sYmd equals 20991231?"}
    COND2 -->|"false"| SETSTART["Set sYmd from input directly"]
    COND2 -->|"true"| COND3{"eYmd not null AND eYmd not 20991231?"}
    COND3 -->|"false"| SETSTART
    COND3 -->|"true"| COMPUTESTART["sYmd = JPCDateUtil.addDay(eYmd, 1)"]
    COMPUTESTART --> SETSTART
    SETSTART --> WRIBPUT1["out.put(no, input)")"]
    WRIBPUT1 --> WRIBPUT2["out.put(keiKind, KeiKind.WRIB)"]
    WRIBPUT2 --> WRIBPUT3["out.put(stat, input)")"]
    WRIBPUT3 --> WRIBPUT4["out.put(stat_nm, input)")"]
    WRIBPUT4 --> WRIBPUT5["out.put(type_cd, input)")"]
    WRIBPUT5 --> WRIBPUT6["out.put(type_cd_nm, input)")"]
    WRIBPUT6 --> WRIBPUT7["out.put(campaign_cd, input)")"]
    WRIBPUT7 --> WRIBPUT8["out.put(campaign_nm, input)")"]
    WRIBPUT8 --> WRIBPUT9["out.put(mskm_ymd, input)")"]
    WRIBPUT9 --> WRIBPUT10["out.put(staymd, sYmd computed)]"]
    WRIBPUT10 --> WRIBPUT11["out.put(endymd, input)")"]
    WRIBPUT11 --> WRIBPUT12["out.put(wrib_svc_cd, input)")"]
    WRIBPUT12 --> WRIBPUT13["out.put(aply_jun_nm, input)")"]
    WRIBPUT13 --> RETURN1["Return out HashMap"]

    COND1 -->|"false: Non-discount (HNSOKU)"| HNSOKU1["out.put(no, input)")"]
    HNSOKU1 --> HNSOKU2["out.put(keiKind, KeiKind.HNSOKU)"]
    HNSOKU2 --> HNSOKU3["out.put(stat, input)")"]
    HNSOKU3 --> HNSOKU4["out.put(stat_nm, input)")"]
    HNSOKU4 --> HNSOKU5["out.put(type_cd, input)")"]
    HNSOKU5 --> HNSOKU6["out.put(type_cd_nm, input)")"]
    HNSOKU6 --> HNSOKU7["out.put(campaign_cd, input)")"]
    HNSOKU7 --> HNSOKU8["out.put(campaign_nm, input)")"]
    HNSOKU8 --> HNSOKU9["out.put(mskm_ymd, input)")"]
    HNSOKU9 --> HNSOKU10["out.put(staymd, input directly)"]
    HNSOKU10 --> HNSOKU11["out.put(endymd, input directly)"]
    HNSOKU11 --> HNSOKU12["out.put(wrib_svc_cd, input)")"]
    HNSOKU12 --> HNSOKU13["out.put(aply_jun_nm, input)")"]
    HNSOKU13 --> CONDTHREE{"WRISVC_DCHSKM_CD equals DT0000002?"}
    CONDTHREE -->|"true: Net Phone+TV Triple"| CLEARDATES["Set staymd and endymd to empty"]
    CLEARDATES --> RETURN2["Return out HashMap"]
    HNSOKU13 -->|"false"| RETURN2
    WRIBPUT13 --> RETURN2

    style START fill:#f9f,stroke:#333
    style END fill:#f9f,stroke:#333
```

**Business meaning of the discrimination constant (keiKind):**

| Condition | Value | Business Meaning |
|-----------|-------|-----------------|
| `keiKind == "1"` | `"1"` | **Discount (WRIB)** — Service is a discounted/promotional contract. Uses computed start date logic. |
| `keiKind != "1"` | `"2"` (typical) | **Non-discount (HNSOKU)** — Standard service contract. Direct date passthrough. |

**Special service code (TgHansoku):**

| Constant | Value | Business Meaning |
|----------|-------|-----------------|
| `TgHansoku` | `"DT0000002"` | **Net Phone + TV Triple Plan** — A bundled telecommunications package where no fixed billing period applies, so start/end dates are cleared. |

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `in` | `CAANMsg` | Input message containing discount/non-discount service contract data. This message is structured according to the `EKK0451B011CBSMsg1List` message definition and carries all fields needed to represent a service contract line item including discrimination code, status, type, campaign details, billing period (start/end dates), and service CD. The `WRIB_DCHS_HAMBET_CD` field determines which of two processing branches (discount vs. non-discount) the data follows. |

**No instance fields or external state** are read by this method. It is a pure transformation — all input data comes from the `in` parameter and all output data is written to the local `out` HashMap.

## 4. CRUD Operations / Called Services

This method performs **pure data transformation only**. It does not invoke any CRUD operations, SC codes, or database/entity access. All operations are local data access via `CAANMsg.getString()` (read from message) and `HashMap.put()` (write to local output map).

### Pre-computed evidence from code analysis graph

The pre-computed evidence lists method calls that are **not invoked** by this specific method. The actual method calls within `transform()` are listed below:

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `CAANMsg.getString` | - | - | Read string field from input message (no database access — reads from in-memory message object) |
| C | `HashMap.put` | - | - | Write string key-value pair to output HashMap (local memory operation only) |
| C | `JKKWribSvcKeiOperateCC.KeiKind.getKeiKind()` | - | - | Retrieve the constant string value for the KeiKind discriminator (WRIB or HNSOKU) |
| C | `JPCDateUtil.addDay` | - | - | Compute a date by adding 1 day to the end date (v5.00.24 — used only when start date sentinel detected) |
| R | `JKKStringUtil.isNullBlank` | - | - | Utility check to determine if the end date field is null or blank (used in date computation guard) |

## 5. Dependency Trace

### Direct callers (from code analysis graph)

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | `JKKBatKKCashPostBase` (Batch) | `JKKBatKKCashPostBase.execute()` → `PartSequencer.transform()` | `getString[R] -`, `keySet[-] -`, `put[C] -` |
| 2 | `Items` (Utility) | `Items.map()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 3 | `JECNA0040001TPMA` (CBS) | `JECNA0040001TPMA.invoke()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 4 | `JECNA0040002TPMA` (CBS) | `JECNA0040002TPMA.invoke()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 5 | `JECNA0150001TPMA` (CBS) | `JECNA0150001TPMA.callPost()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 6 | `JECNA0160001TPMA` (CBS) | `JECNA0160001TPMA.callPost()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 7 | `JKKejbKKA0010002SecProc` (CBS) | `JKKejbKKA0010002SecProc.searchCredit()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 8 | `JKKejbKKA001SecProc` (CBS) | `JKKejbKKA001SecProc.shokaiOsrIrai()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 9 | `JKKejbKKA0110001SecProc` (CBS) | `JKKejbKKA0110001SecProc.execute()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 10 | `JCKCtrlCisInfoImpl` (CBS) | `JCKCtrlCisInfoImpl.call_CIS()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 11 | `JCKCtrlCisInfoStubImpl` (CBS) | `JCKCtrlCisInfoStubImpl.call_CIS()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 12 | `JCRCtrlTnInfoImpl` (CBS) | `JCRCtrlTnInfoImpl.ctrlTnInfo_CRA0001()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 13 | `JKKCtrlMvnoSvcKeiInfoImpl` (CBS) | `JKKCtrlMvnoSvcKeiInfoImpl.ctrlMvnoInfo_KKA0003()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 14 | `JZMCtrlCisInfoImpl` (CBS) | `JZMCtrlCisInfoImpl.ctrlCisInfo_ZMA0001()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |
| 15 | `JZMCtrlTrankInfoImpl` (CBS) | `JZMCtrlTrankInfoImpl.call_TRANK()` → `PartSequencer.transform()` | `getString[R] -`, `put[C] -` |

**Note:** No screen entry points (KKSV*) were found within 8 hops. The method is primarily called by CBS (Contract Business System) controllers and batch processors that handle customer service contract operations, credit searches, and CIS (Customer Information System) integrations. The `JFUXPathManager.getDomSize()` caller appears to be an unrelated match on the word "transform" in a different context.

## 6. Per-Branch Detail Blocks

**Block 1** — `if/else` `(keiKind discrimination)` (L17047)

> Retrieve the service discrimination code and branch on whether this is a discount service or a standard (non-discount) service. The discrimination code is read from `WRIB_DCHS_HAMBET_CD` in the input message.

| # | Type | Code |
|---|------|------|
| 1 | SET | `keiKind = in.getString(EKK0451B011CBSMsg1List.WRIB_DCHS_HAMBET_CD)` // Read service discrimination code from input |
| 2 | IF | `if ("1".equals(keiKind))` // Branch: discount service (WRIB = *waribiki* / discount) [-> "1"] |

---

**Block 1.1** — `IF` `(keiKind == "1" : Discount Service)` (L17051)

> Discount service branch. Handles special date computation logic introduced in v5.00.24. When the start date (`staymd`) is the sentinel value `20991231`, it computes a meaningful start date from the end date. This addresses a billing period calculation issue where discount services lacked a proper start date.

| # | Type | Code |
|---|------|------|
| 1 | SET | `sYmd = in.getString(EKK0451B011CBSMsg1List.SVC_CHRG_DCHSKMST_STAYMD)` // Get start date from input [v5.00.24] |
| 2 | SET | `eYmd = in.getString(EKK0451B011CBSMsg1List.SVC_CHRG_DCHSKMST_ENDYMD)` // Get end date from input [v5.00.24] |
| 3 | IF | `if ("20991231".equals(sYmd))` // Sentinel: start date not set [-> far-future sentinel] |

---

**Block 1.1.1** — `nested IF` `(end date guard)` (L17053)

> Nested guard: only compute start date from end date if the end date itself is meaningful (not null/blank and not the sentinel).

| # | Type | Code |
|---|------|------|
| 1 | IF | `if (!JKKStringUtil.isNullBlank(eYmd) && !"20991231".equals(eYmd))` // Guard: end date must be valid |
| 2 | SET | `sYmd = JPCDateUtil.addDay(eYmd, 1)` // Compute: start date = end date + 1 day [v5.00.24] |

---

**Block 1.2** — `block body` `(populate output HashMap for discount service)` (L17056–L17071)

> Populate the output HashMap with all 13 fields for a discount service contract. Most fields are direct passthroughs from the input message. The `keiKind` field is set to the constant value from `KeiKind.WRIB`. The `staymd` field uses the computed `sYmd` variable instead of reading directly from input.

| # | Type | Code |
|---|------|------|
| 1 | SET | `out.put("no", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_NO))` // Service contract number |
| 2 | SET | `out.put("kei_kind", JKKWribSvcKeiOperateCC.KeiKind.WRIB.getKeiKind())` // Fixed: discount type [-> KeiKind.WRIB] |
| 3 | SET | `out.put("stat", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_STAT))` // Service status |
| 4 | SET | `out.put("stat_nm", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_STAT_NM))` // Status name |
| 5 | SET | `out.put("type_cd", in.getString(EKK0451B011CBSMsg1List.WRIB_DCHS_TYPE_CD))` // Discrimination type code |
| 6 | SET | `out.put("type_cd_nm", in.getString(EKK0451B011CBSMsg1List.WRIB_DCHS_TYPE_CD_NM))` // Type name |
| 7 | SET | `out.put("campaign_cd", in.getString(EKK0451B011CBSMsg1List.DSP_CAMPAIGN_DCHSKM_CD))` // Campaign/promotion code |
| 8 | SET | `out.put("campaign_nm", in.getString(EKK0451B011CBSMsg1List.WRISVC_DCHSKM_NM))` // Campaign/promotion name |
| 9 | SET | `out.put("mskm_ymd", in.getString(EKK0451B011CBSMsg1List.MSKM_YMD))` // Month start date (application) |
| 10 | SET | `out.put("staymd", sYmd)` // Start date — computed from end date if sentinel detected [v5.00.24] |
| 11 | SET | `out.put("endymd", in.getString(EKK0451B011CBSMsg1List.SVC_CHRG_DCHSKMST_ENDYMD))` // End date |
| 12 | SET | `out.put("wrib_svc_cd", in.getString(EKK0451B011CBSMsg1List.WRISVC_DCHSKM_CD))` // Discount service code |
| 13 | SET | `out.put("aply_jun_nm", in.getString(EKK0451B011CBSMsg1List.APLY_JUN_NM))` // Application sequence name |

---

**Block 2** — `else` `(keiKind != "1" : Non-discount Service)` (L17072)

> Non-discount (standard) service branch. All fields are direct passthroughs from the input message. The `kei_kind` is set to `KeiKind.HNSOKU`. Additionally, handles a special case for the "net phone + TV triple plan" (DT0000002) where billing period dates are cleared.

| # | Type | Code |
|---|------|------|
| 1 | SET | `out.put("no", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_NO))` // Service contract number |
| 2 | SET | `out.put("kei_kind", JKKWribSvcKeiOperateCC.KeiKind.HNSOKU.getKeiKind())` // Fixed: non-discount type [-> KeiKind.HNSOKU] |
| 3 | SET | `out.put("stat", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_STAT))` // Service status |
| 4 | SET | `out.put("stat_nm", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_STAT_NM))` // Status name |
| 5 | SET | `out.put("type_cd", in.getString(EKK0451B011CBSMsg1List.WRIB_DCHS_TYPE_CD))` // Discrimination type code |
| 6 | SET | `out.put("type_cd_nm", in.getString(EKK0451B011CBSMsg1List.WRIB_DCHS_TYPE_CD_NM))` // Type name |
| 7 | SET | `out.put("campaign_cd", in.getString(EKK0451B011CBSMsg1List.DSP_CAMPAIGN_DCHSKM_CD))` // Campaign/promotion code |
| 8 | SET | `out.put("campaign_nm", in.getString(EKK0451B011CBSMsg1List.WRISVC_DCHSKM_NM))` // Campaign/promotion name |
| 9 | SET | `out.put("mskm_ymd", in.getString(EKK0451B011CBSMsg1List.MSKM_YMD))` // Month start date (application) |
| 10 | SET | `out.put("staymd", in.getString(EKK0451B011CBSMsg1List.SVC_CHRG_DCHSKMST_STAYMD))` // Start date — direct passthrough |
| 11 | SET | `out.put("endymd", in.getString(EKK0451B011CBSMsg1List.SVC_CHRG_DCHSKMST_ENDYMD))` // End date — direct passthrough |
| 12 | SET | `out.put("wrib_svc_cd", in.getString(EKK0451B011CBSMsg1List.WRISVC_DCHSKM_CD))` // Discount service code |
| 13 | SET | `out.put("aply_jun_nm", in.getString(EKK0451B011CBSMsg1List.APLY_JUN_NM))` // Application sequence name |

---

**Block 2.1** — `if` `(net phone + TV triple plan special case)` (L17093–L17095)

> Special handling for the bundled telecommunications package "DT0000002". When the service code matches this value, the start and end dates are explicitly cleared because this triple-plan service type does not use a fixed billing period. This was introduced as part of LT-2013-0000101 date handling support.

| # | Type | Code |
|---|------|------|
| 1 | SET | `final String TgHansoku = "DT0000002"` // Net phone + TV triple plan service code [local constant] |
| 2 | IF | `if (TgHansoku.equals(in.getString(EKK0451B011CBSMsg1List.WRISVC_DCHSKM_CD)))` // Check if service is triple plan |
| 3 | SET | `out.put("staymd", "")` // Clear start date for triple plan |
| 4 | SET | `out.put("endymd", "")` // Clear end date for triple plan |

---

**Block 3** — `return` (L17098)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return out` // Return the populated HashMap with all 13 fields |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `WRIB_DCHS_HAMBET_CD` | Field | Service discrimination code — determines whether the service is a discount/promotional contract ("1") or standard/non-discount ("2"). Key discriminator for branching logic. |
| `WRIB` | Field | *Waribiki* (割引) — Discount/Promotional Service. A contracted service line item that receives a price reduction or promotional pricing. |
| `HNSOKU` | Field | *Hansoku* (半額/非割引) — Non-discount/Standard Service. A contracted service line item at regular pricing. |
| `KeiKind` | Field | *Kei* (*Kei* — type/kind) discriminator — indicates the contract type (WRIB = discount, HNSOKU = non-discount). Stored as a string in the output HashMap. |
| `SVC_CHRG_DCHSKMST_STAYMD` | Field | Service Charge Discount Start Month/Day — the date when the discounted billing period begins. If set to "20991231" (sentinel), the start date is computed from the end date. |
| `SVC_CHRG_DCHSKMST_ENDYMD` | Field | Service Charge Discount End Month/Day — the date when the discounted billing period ends. |
| `staymd` | Field | Start Month/Day — the billing start date of the service contract period. Cleared to empty for triple-plan services. |
| `endymd` | Field | End Month/Day — the billing end date of the service contract period. Cleared to empty for triple-plan services. |
| `mskm_ymd` | Field | Application Month/Day — the date the application was submitted or the month the service is active. |
| `WRIBSVK_DCHSKMST_NO` | Field | WRIB Service Key Discount Master Number — the primary key/serial number identifying the discount service master record. |
| `WRIBSVK_DCHSKMST_STAT` | Field | WRIB Service Key Discount Master Status — the current operational status of the discount service (e.g., active, terminated). |
| `WRIBSVK_DCHSKMST_STAT_NM` | Field | WRIB Service Key Discount Master Status Name — human-readable status label. |
| `WRIB_DCHS_TYPE_CD` | Field | WRIB Discrimination Type Code — classifies the type of discount discrimination (e.g., network, mobile, TV). |
| `WRIB_DCHS_TYPE_CD_NM` | Field | WRIB Discrimination Type Code Name — human-readable type label. |
| `DSP_CAMPAIGN_DCHSKM_CD` | Field | Display Campaign Discount Master Campaign Code — the promotional campaign associated with this service. |
| `WRISVC_DCHSKM_NM` | Field | WRIB Service Discount Master Name — the display name of the discount service/promotion. |
| `WRISVC_DCHSKM_CD` | Field | WRIB Service Discount Master Code — the unique code identifying the discount service type. |
| `APLY_JUN_NM` | Field | Application Sequence/Stage Name — the sequence or stage at which this service application was made. |
| `DT0000002` | Constant | **Net Phone + TV Triple Plan** — a bundled telecommunications service package (internet + VoIP + TV) that does not use a fixed billing period, hence start/end dates are cleared. |
| `20991231` | Constant | **Far-future sentinel date** — used as a placeholder/default value when the start date has not yet been set. Indicates the actual start date needs to be computed from the end date. |
| `CAANMsg` | Type | Fujitsu's messaging object — a message container carrying named string fields, used throughout the eo customer base system for inter-component data exchange. |
| `EKK0451B011CBSMsg1List` | Type | Message field constant class — defines the field keys for the EKK0451B011 CBS message list (the unified service interface introduced in v5.00.20). |
| `JKKWribSvcKeiOperateCC` | Class | WRIB Service Key Operation CC — the controller class containing the `WribSvcKeiMover` inner class with the `transform` method. Part of the common utility package. |
| `KeiKind` | Enum/Class | Service key kind discriminator — an enum-like class with values WRIB (discount) and HNSOKU (non-discount), each returning a fixed string via `getKeiKind()`. |
| `JPCDateUtil.addDay` | Method | Date utility — adds a specified number of days to a date string (format YYYYMMDD) and returns the resulting date string. |
| `JKKStringUtil.isNullBlank` | Method | String utility — checks if a string is null, empty, or whitespace-only. Returns true if the value is blank. |
| `DEFAULT_HASH_SIZE` | Constant | 50 — the initial capacity of the output HashMap, chosen to hold all 13 transformed fields with room for expansion. |
| eo | Business term | K-Opticom's broadband telecommunications service brand in Japan (formerly NTT East's hikari one service). |
| CBS | Acronym | Contract Business System — the core telecom billing and contract management subsystem. |
| SOD | Acronym | Service Order Data — the entity/table representing service order requests in the system. |
