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

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

## 1. Role

### CAANMsgValuesPicker.transform()

This method is the transformation logic for **discount service contracts** (割引サービス契約, "waribiki services keiyaku") within the K-Opticom customer backbone system (eo customer main system). It implements the `Transformer<CAANMsg, HashMap<String, String>>` interface inside the inner class `WribSvcKeiMover`, acting as a data-mapping adapter that extracts fields from a service-input message (`CAANMsg`) and populates a normalized output `HashMap` for downstream processing.

The method branches on the **line type discrimination code** (`WRIB_DCHS_HAMBET_CD`, i.e., "discount service selection discrimination") from the input message. When the code equals `"1"`, the method treats the contract as a **WRIB (discount service) type** and applies a date-adjustment rule: if the start date is set to the sentinel year `20991231`, it computes the actual start date as the day after the end date. When the code is anything other than `"1"`, the method handles it as a **HNSOKU (reduction/discount) type**, extracting the same fields but using a different `kei_kind` enum value. An additional conditional branch clears both `staymd` and `endymd` when the service code matches `"DT0000002"`, which represents an **NTT Phone/TV 3-line bundled application** where fixed start/end dates are intentionally omitted per requirement LT-2013-0000101.

This method follows the **Builder + Routing/Dispatch pattern**: it constructs a HashMap by extracting values through a consistent set of field lookups, with routing driven by the `keiKind` discriminator. It serves as a shared data-transform utility called from multiple CBS (common business service) entry points including `JKKBatKKCashPostBase`, screen processes (`JKSV0004`), batch processors, and various controller implementations that all need a unified representation of discount service contract data.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["transform(CAANMsg in)"])

    START --> INIT["Initialize out HashMap DEFAULT_HASH_SIZE=50"]

    INIT --> GET_KEI["Get keiKind from in.getString(WRIB_DCHS_HAMBET_CD)"]

    GET_KEI --> COND1{keiKind equals 1?}

    COND1 -->|Yes WRIB Branch| WRIB_START["Get sYmd from SVC_CHRG_DCHSKMST_STAYMD"]
    WRIB_START --> GET_ENDYM["Get eYmd from SVC_CHRG_DCHSKMST_ENDYMD"]
    GET_ENDYM --> COND_INIFINITY{sYmd equals 20991231?}
    COND_INIFINITY -->|Yes| COND_ENOTINFINITY{eYmd not null blank and not 20991231?}
    COND_INIFINITY -->|No| POPULATE_WRIB["Populate out HashMap: no, kei_kind=WRIB, stat, stat_nm, type_cd, type_cd_nm, campaign_cd, campaign_nm, mskm_ymd, staymd=sYmd, endymd, wrib_svc_cd, aply_jun_nm"]
    COND_ENOTINFINITY -->|Yes| CALC_STAY["sYmd = JPCDateUtil.addDay(eYmd, 1)"]
    CALC_STAY --> POPULATE_WRIB
    COND_ENOTINFINITY -->|No| POPULATE_WRIB

    COND1 -->|No HNSOKU Branch| HNSOKU_START["Populate out HashMap: no, kei_kind=HNSOKU, stat, stat_nm, type_cd, type_cd_nm, campaign_cd, campaign_nm, mskm_ymd, staymd, endymd, wrib_svc_cd, aply_jun_nm"]
    HNSOKU_START --> GET_CD["Get WRISVC_DCHSKM_CD from in.getString(WRISVC_DCHSKM_CD)"]
    GET_CD --> COND_NTTV{CD equals DT0000002 NTT Phone TV 3-line?}
    COND_NTTV -->|Yes| CLEAR_DATES["out.put staymd empty out.put endymd empty"]
    COND_NTTV -->|No| RETURN_OUT
    CLEAR_DATES --> RETURN_OUT["Return out"]

    POPULATE_WRIB --> RETURN_OUT
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `in` | `CAANMsg` | Input message carrier containing discount service contract data. This message is populated by upstream CBS processes and carries fields such as the service line discrimination code (`WRIB_DCHS_HAMBET_CD`), status, type codes, campaign information, service codes, and start/end dates for the discount service period. The method reads all data from this message and produces a normalized `HashMap<String, String>` output. |

**Instance fields / external state read by the method:**

| No | Field / Constant | Type | Business Description |
|----|-----------------|------|---------------------|
| 1 | `DEFAULT_HASH_SIZE` | `int = 50` | Initial capacity for the output HashMap, chosen to accommodate the 12+ fields populated per call. |
| 2 | `JKKWribSvcKeiOperateCC.KeiKind.WRIB.getKeiKind()` | `String` | Enum value representing the discount service (割引サービス) line type — used when `keiKind = "1"`. |
| 3 | `JKKWribSvcKeiOperateCC.KeiKind.HNSOKU.getKeiKind()` | `String` | Enum value representing the reduction/discount service (減算サービス) line type — used when `keiKind != "1"`. |

## 4. CRUD Operations / Called Services

### Pre-computed evidence from code analysis graph:

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `JKKWribSvcKeiOperateCC.WribSvcKeiMover.transform` | EKK0451B011CBS | `KK_T_WRIB_SVC_KEI_DCHSKMST` | Reads discount service contract header data (line number, status, type code, campaign info, dates) from the input `CAANMsg` message populated by CBS EKK0451B011. This is a Read operation on CBS-level message data. |

**Notes:**
- This method is a pure data-transformation method that reads from the input `CAANMsg` message and writes to an output `HashMap`. It does not directly call any database layer or external SC (Service Component) methods.
- The `CAANMsg` input is pre-populated by upstream CBS processing (typically `EKK0451B011CBS`), which is responsible for reading the discount service contract table (`KK_T_WRIB_SVC_KEI_DCHSKMST`) and populating the message fields.
- The only external method call is `JPCDateUtil.addDay()` for date arithmetic, which is a utility function (not a CRUD operation).

## 5. Dependency Trace

### Pre-computed evidence from code analysis graph:

No screen/batch entry points found within 8 hops. Direct callers found: 16 methods.
Terminal operations from this method: `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `addDay` [C], `addDay` [C], `addDay` [C], `addDay` [C], `getKeiKind` [-]

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

## 6. Per-Branch Detail Blocks

**Block 1** — [IF] `(keiKind equals "1") [WRIB_DCHS_HAMBET_CD="1"]` (L17062)

> **Business description:** This branch handles the WRIB (discount service / 割引サービス) line type. It extracts the start and end dates from the input message, applies a date-adjustment rule (v5.00.24), and populates the output HashMap with all discount service contract fields. The `kei_kind` is set to `WRIB`.

| # | Type | Code |
|---|------|------|
| 1 | SET | `sYmd = in.getString(EKK0451B011CBSMsg1List.SVC_CHRG_DCHSKMST_STAYMD)` // Get start date from CBS message |
| 2 | SET | `eYmd = in.getString(EKK0451B011CBSMsg1List.SVC_CHRG_DCHSKMST_ENDYMD)` // Get end date from CBS message |
| 3 | CALL | `out.put("no", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_NO))` // Set discount service contract line number |
| 4 | SET | `out.put("kei_kind", JKKWribSvcKeiOperateCC.KeiKind.WRIB.getKeiKind())` // [-> KeiKind.WRIB="1"] Set line type to WRIB (discount service) |
| 5 | CALL | `out.put("stat", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_STAT))` // Set contract status code |
| 6 | CALL | `out.put("stat_nm", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_STAT_NM))` // Set status name |
| 7 | CALL | `out.put("type_cd", in.getString(EKK0451B011CBSMsg1List.WRIB_DCHS_TYPE_CD))` // Set discount service type code |
| 8 | CALL | `out.put("type_cd_nm", in.getString(EKK0451B011CBSMsg1List.WRIB_DCHS_TYPE_CD_NM))` // Set type name |
| 9 | CALL | `out.put("campaign_cd", in.getString(EKK0451B011CBSMsg1List.DSP_CAMPAIGN_DCHSKM_CD))` // Set campaign code |
| 10 | CALL | `out.put("campaign_nm", in.getString(EKK0451B011CBSMsg1List.WRISVC_DCHSKM_NM))` // Set campaign name |
| 11 | CALL | `out.put("mskm_ymd", in.getString(EKK0451B011CBSMsg1List.MSKM_YMD))` // Set service start date |
| 12 | SET | `out.put("staymd", sYmd)` // [v5.00.24 mod] Use potentially-adjusted sYmd, not raw input [-> adjusted by v5.00.24 rule if start=20991231] |
| 13 | CALL | `out.put("endymd", in.getString(EKK0451B011CBSMsg1List.SVC_CHRG_DCHSKMST_ENDYMD))` // Set contract end date |
| 14 | CALL | `out.put("wrib_svc_cd", in.getString(EKK0451B011CBSMsg1List.WRISVC_DCHSKM_CD))` // Set discount service code |
| 15 | CALL | `out.put("aply_jun_nm", in.getString(EKK0451B011CBSMsg1List.APLY_JUN_NM))` // Set application priority name |

**Block 1.1** — [IF-IF NESTED] `(sYmd equals "20991231")` (L17067)

> **Business description:** This is a nested date-adjustment rule added in v5.00.24. If the start date is set to the sentinel value `20991231` (meaning "indefinite/future"), and the end date is valid and not also the sentinel, compute the actual start date as the day after the end date. This resolves the "long-term discount auto-continuation" scenario.

| # | Type | Code |
|---|------|------|
| 1 | IF | `"20991231".equals(sYmd)` // [Sentinel infinity date check — 2099-12-31 means "not yet started"] |
| 2 | IF-IF | `!JKKStringUtil.isNullBlank(eYmd) && !"20991231".equals(eYmd)` // eYmd must be present and not also the sentinel |
| 3 | SET | `sYmd = JPCDateUtil.addDay(eYmd, 1)` // Compute start date as end date + 1 day [-> v5.00.24: long-term discount auto-continuation rule] |

**Block 2** — [ELSE] `(keiKind does not equal "1") [WRIB_DCHS_HAMBET_CD != "1"]` (L17093)

> **Business description:** This branch handles the HNSOKU (reduction/discount / 減算サービス) line type. It populates the same 12 fields as Block 1, but with `kei_kind` set to `HNSOKU`, and uses the raw `sYmd` value directly (no date-adjustment rule). An additional conditional branch clears `staymd` and `endymd` for NTT Phone/TV 3-line bundled applications.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `out.put("no", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_NO))` // Set discount service contract line number |
| 2 | SET | `out.put("kei_kind", JKKWribSvcKeiOperateCC.KeiKind.HNSOKU.getKeiKind())` // [-> KeiKind.HNSOKU="2"] Set line type to HNSOKU (reduction service) |
| 3 | CALL | `out.put("stat", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_STAT))` // Set contract status code |
| 4 | CALL | `out.put("stat_nm", in.getString(EKK0451B011CBSMsg1List.WRIBSVK_DCHSKMST_STAT_NM))` // Set status name |
| 5 | CALL | `out.put("type_cd", in.getString(EKK0451B011CBSMsg1List.WRIB_DCHS_TYPE_CD))` // Set discount service type code |
| 6 | CALL | `out.put("type_cd_nm", in.getString(EKK0451B011CBSMsg1List.WRIB_DCHS_TYPE_CD_NM))` // Set type name |
| 7 | CALL | `out.put("campaign_cd", in.getString(EKK0451B011CBSMsg1List.DSP_CAMPAIGN_DCHSKM_CD))` // Set campaign code |
| 8 | CALL | `out.put("campaign_nm", in.getString(EKK0451B011CBSMsg1List.WRISVC_DCHSKM_NM))` // Set campaign name |
| 9 | CALL | `out.put("mskm_ymd", in.getString(EKK0451B011CBSMsg1List.MSKM_YMD))` // Set service start date |
| 10 | CALL | `out.put("staymd", in.getString(EKK0451B011CBSMsg1List.SVC_CHRG_DCHSKMST_STAYMD))` // [Raw input, no adjustment] Set start date |
| 11 | CALL | `out.put("endymd", in.getString(EKK0451B011CBSMsg1List.SVC_CHRG_DCHSKMST_ENDYMD))` // Set contract end date |
| 12 | CALL | `out.put("wrib_svc_cd", in.getString(EKK0451B011CBSMsg1List.WRISVC_DCHSKM_CD))` // Set discount service code |
| 13 | CALL | `out.put("aply_jun_nm", in.getString(EKK0451B011CBSMsg1List.APLY_JUN_NM))` // Set application priority name |

**Block 2.1** — [IF] `(WRISVC_DCHSKM_CD equals "DT0000002")` (L17111)

> **Business description:** For NTT Phone/TV 3-line bundled applications (ネット電話TV三点申込, per comment at L17109), both the start date and end date are explicitly cleared (set to empty strings). This is required per requirement ticket LT-2013-0000101.

| # | Type | Code |
|---|------|------|
| 1 | SET | `TgHansoku = "DT0000002"` // [Constant] Target handling code for NTT Phone TV 3-line bundled application |
| 2 | IF | `TgHansoku.equals(in.getString(EKK0451B011CBSMsg1List.WRISVC_DCHSKM_CD))` // Check if service code matches the 3-line bundled code |
| 3 | SET | `out.put("staymd", "")` // [LT-2013-0000101] Clear start date for 3-line bundled application |
| 4 | SET | `out.put("endymd", "")` // [LT-2013-0000101] Clear end date for 3-line bundled application |

**Block 3** — [RETURN] (L17114)

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return out` // Return the populated HashMap containing 12 discount service contract fields |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `wr` | Abbreviation | Short for "waribiki" (割引) — discount service in K-Opticom's telecom billing system |
| `wrib` | Abbreviation | Short for "waribiki service" — discount/reduction service contract type |
| `svc_kei` | Field | Service line (サービス系) — refers to a specific telecom service product line |
| `kei_kind` | Field | Line type discrimination code — distinguishes between WRIB (discount, "1") and HNSOKU (reduction, "2") service types |
| `HNSOKU` | Field | Reduction service (減算サービス) — a discount type where the service charge is reduced by a fixed amount or percentage |
| `WRIB` | Field | Discount service (割引サービス) — a promotional discount contract type |
| `DCHS_HAMBET_CD` | Field | Discount service selection discrimination code — the discriminator that determines whether the contract is WRIB type ("1") or HNSOKU type (anything else) |
| `DCHSKM` | Abbreviation | Discount service charge definition (割引サービス料金定義) |
| `staymd` | Field | Start date (開始日) — the date the discount service contract period begins |
| `endymd` | Field | End date (終了日) — the date the discount service contract period ends |
| `mskm_ymd` | Field | Service start date (サービス開始年月日) — the date the actual service begins, which may differ from the contract start date |
| `wrib_svc_cd` | Field | Discount service code (割引サービスコード) — unique identifier for a specific discount service offering |
| `campaign_cd` | Field | Campaign code (キャンペーンコード) — promotional campaign identifier associated with the discount |
| `campaign_nm` | Field | Campaign name (キャンペーン名称) — human-readable name of the promotional campaign |
| `type_cd` | Field | Service type code (サービス種別コード) — code classifying the type of discount service |
| `stat` | Field | Contract status code (契約状態コード) — current status of the discount service contract |
| `stat_nm` | Field | Status name (状態名称) — human-readable contract status |
| `aply_jun_nm` | Field | Application priority name (申請順序名称) — priority ordering for the application |
| `DT0000002` | Constant | NTT Phone/TV 3-line bundled application code (ネット電話TV三点申込) — special service code for bundled NTT Phone + TV + broadband packages where start/end dates are not applicable |
| `20991231` | Constant | Sentinel infinity date — represents "no fixed end date" or "indefinite period" in the system's date convention |
| `WRIBSVK_DCHSKMST_NO` | Field | Discount service contract line number (割引サービス契約行番号) — unique line identifier within the discount service contract |
| `WRIBSVK_DCHSKMST_STAT` | Field | Discount service contract status code (割引サービス契約状態コード) |
| `WRIB_DCHS_TYPE_CD` | Field | Discount service type code (割引サービス種別コード) |
| `DSP_CAMPAIGN_DCHSKM_CD` | Field | Display campaign discount service code (表示キャンペーン割引サービスコード) |
| `SVC_CHRG_DCHSKMST_STAYMD` | Field | Service charge discount definition start date (サービス料金割引定義開始日) |
| `SVC_CHRG_DCHSKMST_ENDYMD` | Field | Service charge discount definition end date (サービス料金割引定義終了日) |
| `WRISVC_DCHSKM_NM` | Field | Discount service name (割引サービス名称) |
| `WRISVC_DCHSKM_CD` | Field | Discount service code (割引サービスコード) |
| `CAANMsg` | Class | Contract Account Announcement Message — a message carrier used to pass structured business data between CBS components and transformation layers |
| `CAANSchemaInfo` | Class | Schema metadata class defining the structure of a CAANMsg |
| `EKK0451B011CBS` | SC Code | Common Business Service for discount service contract data retrieval (割引サービス契約照会 CBS) |
| `EKK0451B005CBS` | SC Code | Legacy Common Business Service for discount service data (deprecated in v5.00.20) |
| `Transformer<T, R>` | Interface | Functional interface defining the `transform` method pattern used for data mapping between input and output types |
| `JPCDateUtil.addDay` | Method | Utility function that adds a specified number of days to a date string (format: yyyyMMdd) |
| `JKKWribSvcKeiOperateCC` | Class | Outer class — discount service contract operation control component (割引サービス契約操作管理コンポーネント) |
| `WribSvcKeiMover` | Class | Inner class — data mover that transforms `CAANMsg` to `HashMap<String, String>` for discount service contracts |
| v5.00.20 | Version | Version that consolidated discount/promotion information into a single service IF, replacing the old dual-CBS approach (EKK0451B005CBS -> EKK0451B011CBS) |
| v5.00.24 | Version | Version that added the infinity-date adjustment rule for long-term discount auto-continuation (長期継続利用割引) |
| LT-2013-0000101 | Ticket | Requirement ticket for clearing start/end dates on NTT Phone/TV 3-line bundled applications |
