# Business Logic — DKW01302SFLogic.buildHeaderRecord() [123 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.web.webview.DKW01302SF.DKW01302SFLogic` |
| Layer | Controller / Web View Logic (Package: `eo.web.webview.DKW01302SF`) |
| Module | `DKW01302SF` (Package: `eo.web.webview.DKW01302SF`) |

## 1. Role

### DKW01302SFLogic.buildHeaderRecord()

This method generates a CSV header record for a single shelf-move (stock transfer) row as part of the DKW01302SF screen, which handles shelf-move result information output. It reads row-level data from an in-memory data bean array (the CSV result list), resolves hierarchical codes for move source/destination locations and device model numbers using fallback precedence, and selects between two specification modes — serial number assignment (`shiteiCd = "2"`) or quantity-based counting — to populate the appropriate fields. The method then increments a shared `record_count` to track the cumulative output record count across all rows and builds a comma-delimited CSV line of 12 fields using `dqot()` (double-quote wrapper) and `join()` for proper CSV formatting.

The business operation is part of a larger CSV file export flow where the DKW01302SF screen produces a structured output file summarizing shelf-move results (inventory transfers) for each lot and data row. The method implements the **Builder** design pattern — assembling a single output record from multiple resolved inputs — and the **Delegation** pattern, reading from shared form beans and helper methods. It is an internal utility method (private) called by `buildFile()`, which orchestrates the full CSV body generation by iterating over rows and inserting header records at group boundaries determined by move lot or spare-device delivery number.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["buildHeaderRecord_lotNo_rowNo"])
    START --> LOAD["Load datas from CSV_LIST at rowNo"]

    LOAD --> GET_SRC["Get sokoMtCd kojiMtCd ofcMtCd"]
    GET_SRC --> COND_SRC["Move Source Code"]

    COND_SRC --> SRC_SOKO["mtCd = sokoMtCd"]
    COND_SRC --> SRC_KOJI["mtCd = kojiMtCd"]
    COND_SRC --> SRC_OFICE["mtCd = ofcMtCd"]
    SRC_SOKO --> GET_MDL["Get nmlMdlNo setMdlNo fzkMdlNo"]
    SRC_KOJI --> GET_MDL
    SRC_OFICE --> GET_MDL

    GET_MDL --> COND_MDL["Model Number"]
    COND_MDL --> MDL_NML["mdlNo = nmlMdlNo"]
    COND_MDL --> MDL_SET["mdlNo = setMdlNo"]
    COND_MDL --> MDL_FZK["mdlNo = fzkMdlNo"]
    MDL_NML --> GET_SHITEI["Get shiteiCd"]
    MDL_SET --> GET_SHITEI
    MDL_FZK --> GET_SHITEI

    GET_SHITEI --> COND_SHITEI{"shiteiCd == 2"}
    COND_SHITEI -->|Yes| BR_SERIAL["Serial Number Mode"]
    COND_SHITEI -->|No| BR_QUANTITY["Quantity Mode"]

    BR_SERIAL --> SRC_NML["nmlSeizoNo not null"]
    SRC_NML -->|Yes| SERIAL_NML["seizoNo = nmlSeizoNo"]
    SRC_NML -->|No| SRC_SET["setSeizoNo not null"]
    SRC_SET -->|Yes| SERIAL_SET["seizoNo = setSeizoNo"]
    SRC_SET -->|No| SERIAL_EMPTY["seizoNo = empty"]
    SERIAL_NML --> SET_CONST["sjiNo=1 idoNo=1"]
    SERIAL_SET --> SET_CONST
    SERIAL_EMPTY --> SET_CONST

    BR_QUANTITY --> COUNT_LOOP["Count identical MOVE_NO in all rows"]
    COUNT_LOOP --> SET_IDO["idoNo = count as String"]
    SET_IDO --> INC_COUNT["record_count++"]
    SET_CONST --> INC_COUNT

    INC_COUNT --> GET_DST["Get sokoSkCd kojiSkCd ofcSkCd"]
    GET_DST --> COND_DST["Move Destination Code"]
    COND_DST --> DST_SOKO["skCd = sokoSkCd"]
    COND_DST --> DST_KOJI["skCd = kojiSkCd"]
    COND_DST --> DST_OFICE["skCd = ofcSkCd"]
    DST_SOKO --> BUILD_CSV["Build CSV record"]
    DST_KOJI --> BUILD_CSV
    DST_OFICE --> BUILD_CSV

    BUILD_CSV --> END_NODE(["Return CSV record"])
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `lotNo` | `String` | Shelf-move lot number (`disp_sheve_move_lot_no`). A business-level grouping identifier that tracks a batch of inventory transfers processed together. Passed through as-is into the CSV output field for traceability. |
| 2 | `rowNo` | `int` | Data row index within the CSV result list (`CSV_LIST`). Selects which row's data is used to populate the header record. The index is used to retrieve the corresponding `X31SDataBeanAccess` from the form-bean-stored data array. |

**Read instance fields:**

| Field | Type | Business Description |
|-------|------|---------------------|
| `record_count` | `int` | Shared cumulative record counter, incremented each time this method is invoked to track how many CSV output records have been generated across the full file. |

## 4. CRUD Operations / Called Services

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on move source warehouse code |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on move source construction company code |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on move source pre-booking office code |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on normal device model code |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on set product model code |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on accessory model code |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on specification method code |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on normal manufacturing serial number |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on set product serial number |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on quantity specification count |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on destination warehouse code |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on destination construction company code |
| - | `JDKCommonUtil.isNull` | JDKCommonUtil | - | Utility null-check on destination pre-booking office code |
| R | `X31SDataBeanAccessArray.getDataBeanArray` | X31SDataBeanAccessArray | In-memory bean store | Retrieves the CSV result list data array by key `CSV_LIST` from the form bean |
| R | `X31SDataBeanAccessArray.getDataBean` | X31SDataBeanAccessArray | In-memory bean store | Retrieves a specific row's data bean by index |
| R | `X31SDataBeanAccessArray.getCount` | X31SDataBeanAccessArray | In-memory bean store | Returns total row count for MOVE_NO iteration loop |
| R | `getData` (static JDKWebCommon) | JDKWebCommon | In-memory bean store | Extracts a field value from a data bean by key |
| - | `JDKStrConst.COMMA` | JDKStrConst | - | Constant: `","` — CSV delimiter |
| - | `join` (static JDKCommonUtil) | JDKCommonUtil | - | Joins multiple strings with comma separator |
| - | `dqot` (instance DKW01302SFLogic) | DKW01302SFLogic | - | Wraps a string value in double quotes for CSV output formatting |
| - | `RECORD_KIHON` (field DKW01302SFLogic) | DKW01302SFLogic | - | Constant: `"7G"` — CSV record type code for basic/standard record |

## 5. Dependency Trace

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Caller: DKW01302SFLogic.buildFile() | `buildFile()` -> `buildHeaderRecord(lotNo, i)` | `getDataBeanArray [R] InMemory CSV_LIST`, `getData [R] InMemory Field Values`, `getCount [R] InMemory Row Count` |

**Caller details:**

`DKW01302SFLogic.buildFile()` iterates over all data rows in `CSV_LIST`. For each row, it checks the specification method (`shiteicd`). If `shiteicd == "2"` (serial number assignment), it calls `buildHeaderRecord()` for every row unconditionally. For quantity-mode rows, it calls `buildHeaderRecord()` only at group boundaries — when the row is the first, when the `MOVE_NO` changes from the previous row, or at the final row with a differing `MOVE_NO`. This ensures each unique spare-device delivery number group gets one header record.

## 6. Per-Branch Detail Blocks

**Block 1** — [Data Load] (L1018)

> Retrieves the CSV result list data array and the specific row's data bean.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `datas = getServiceFormBean().getDataBeanArray(CSV_LIST)` — Gets the CSV result list from form bean `[-> CSV_LIST="shelf-move result info list for CSV"]` |
| 2 | CALL | `resultData = datas.getDataBean(rowNo)` — Gets the data bean at the specified row index |

**Block 2** — [Move Source Code Resolution] (L1021–1037)

> Determines the move source location code with fallback precedence: warehouse -> construction company -> pre-booking office. Only one of these codes will be populated per row.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `sokoMtCd = getData(resultData, MV_MT_SOKO_CD_04)` — Get move source warehouse code `[-> MV_MT_SOKO_CD_04="move source warehouse code"]` |
| 2 | CALL | `kojiMtCd = getData(resultData, MV_MT_KOJI_CD_04)` — Get move source construction company code `[-> MV_MT_KOJI_CD_04="move source construction company code"]` |
| 3 | CALL | `ofcMtCd = getData(resultData, MV_MT_OFFICE_CD_04)` — Get move source pre-booking office code `[-> MV_MT_OFFICE_CD_04="move source pre-booking office code"]` |
| 4 | SET | `mtCd = ""` — Initialize move source code variable |
| 5 | IF | `!JDKCommonUtil.isNull(sokoMtCd)` — Warehouse code branch |

**Block 2.1** — [IF: sokoMtCd not null] (L1024)

> Move source is a warehouse.

| # | Type | Code |
|---|------|------|
| 1 | SET | `mtCd = sokoMtCd` |

**Block 2.2** — [ELSE-IF: kojiMtCd not null] (L1029)

> Move source is a construction company (when warehouse code is empty).

| # | Type | Code |
|---|------|------|
| 1 | SET | `mtCd = kojiMtCd` |

**Block 2.3** — [ELSE-IF: ofcMtCd not null] (L1034)

> Move source is a pre-booking office (when both warehouse and construction company codes are empty).

| # | Type | Code |
|---|------|------|
| 1 | SET | `mtCd = ofcMtCd` |

**Block 3** — [Model Number Resolution] (L1039–1056)

> Determines the device model number with fallback precedence: normal device -> set product -> accessory. Only one model code will be populated per row.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `nmlMdlNo = getData(resultData, TKKIKI_MDL_CD_04)` — Get normal device model code `[-> TKKIKI_MDL_CD_04="indoor device model code"]` |
| 2 | CALL | `setMdlNo = getData(resultData, TKKIKI_SETHIN_MDL_CD_04)` — Get set product model code `[-> TKKIKI_SETHIN_MDL_CD_04="indoor device set product model code"]` |
| 3 | CALL | `fzkMdlNo = getData(resultData, HUZOKUHIN_MDL_CD_04)` — Get accessory model code `[-> HUZOKUHIN_MDL_CD_04="accessory model code"]` |
| 4 | SET | `mdlNo = ""` — Initialize model number variable |
| 5 | IF | `!JDKCommonUtil.isNull(nmlMdlNo)` — Normal device branch |

**Block 3.1** — [IF: nmlMdlNo not null] (L1042)

> Device has a normal model code (standard indoor device).

| # | Type | Code |
|---|------|------|
| 1 | SET | `mdlNo = nmlMdlNo` |

**Block 3.2** — [ELSE-IF: setMdlNo not null] (L1047)

> Device has a set product model code (bundled/set product).

| # | Type | Code |
|---|------|------|
| 1 | SET | `mdlNo = setMdlNo` |

**Block 3.3** — [ELSE-IF: fzkMdlNo not null] (L1052)

> Device only has an accessory model code (accessory-only transfer).

| # | Type | Code |
|---|------|------|
| 1 | SET | `mdlNo = fzkMdlNo` |

**Block 4** — [Specification Mode Branching] (L1059–1076)

> Determines whether the row uses serial number assignment mode (`shiteiCd == "2"`) or quantity-based mode. This controls how manufacturing serial number, instruction count, and move count are populated.

| # | Type | Code |
|---|------|------|
| 1 | SET | `seizoNo = ""` — Initialize serial number |
| 2 | SET | `sjiNo = ""` — Initialize instruction count |
| 3 | SET | `idoNo = ""` — Initialize move count |
| 4 | CALL | `shiteiCd = getData(resultData, SHITEI_WAY_04)` — Get specification method code `[-> SHITEI_WAY_04="specification method"]` |
| 5 | IF | `!JDKCommonUtil.isNull(shiteiCd) && "2".equals(shiteiCd)` — Serial Number Assignment Mode |

**Block 4.1** — [IF: shiteiCd == "2"] — Serial Number Assignment Mode (L1062)

> The shelf-move uses serial number assignment. The method resolves the manufacturing serial number (normal -> set fallback), then hardcodes instruction count and move count to "1" since each serial-numbered item is a single physical unit.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `nmlSeizoNo = getData(resultData, KIKI_SEIZO_NO_04)` — Get normal device serial number `[-> KIKI_SEIZO_NO_04="device manufacturing serial number"]` |
| 2 | CALL | `setSeizoNo = getData(resultData, TKKIKI_SETHIN_SEIZO_NO_04)` — Get set product serial number `[-> TKKIKI_SETHIN_SEIZO_NO_04="indoor device set product serial number"]` |
| 3 | IF | `!JDKCommonUtil.isNull(nmlSeizoNo)` — Normal serial number present |

**Block 4.1.1** — [IF: nmlSeizoNo not null] (L1065)

> Normal device has a serial number; use it directly.

| # | Type | Code |
|---|------|------|
| 1 | SET | `seizoNo = nmlSeizoNo` |

**Block 4.1.2** — [ELSE-IF: setSeizoNo not null] (L1068)

> Normal device serial is empty but set product has one.

| # | Type | Code |
|---|------|------|
| 1 | SET | `seizoNo = setSeizoNo` |

**Block 4.1.3** — [ELSE: neither present] (L1071)

> Both serial numbers are empty — serialNo remains "".

| # | Type | Code |
|---|------|------|
| 1 | SET | `seizoNo = ""` (already initialized, no-op) |

**Block 4.1.4** — [Set constants after serial resolution] (L1073–1074)

> In serial number mode, both instruction count and move count are hardcoded to "1".

| # | Type | Code |
|---|------|------|
| 1 | SET | `sjiNo = "1"` — Instruction count = 1 |
| 2 | SET | `idoNo = "1"` — Move count = 1 |

**Block 4.2** — [ELSE] — Quantity Mode (L1076)

> The shelf-move uses quantity specification (not individual serial numbers). The instruction count comes from the data, and the move count must be computed by counting how many rows share the same spare-device delivery number (`MOVE_NO`).

| # | Type | Code |
|---|------|------|
| 1 | SET | `seizoNo = ""` — Serial number is empty in quantity mode |
| 2 | CALL | `sjiNo = getData(resultData, SJI_CNT_04)` — Get instruction count from data `[-> SJI_CNT_04="instruction count"]` |
| 3 | SET | `idoCnt = 0` — Initialize move counter |
| 4 | CALL | `mvNo = getData(resultData, MOVE_NO_04)` — Get spare-device delivery number `[-> MOVE_NO_04="shelf-move number"]` |
| 5 | FOR | `i = 0; i < datas.getCount(); i++` — Iterate all rows |

**Block 4.2.1** — [FOR: Count identical MOVE_NO] (L1084–1088)

> Counts how many rows share the same spare-device delivery number. This count becomes the total move count for this group.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `data = datas.getDataBean(i)` — Get row at index i |
| 2 | IF | `mvNo.equals(getData(data, MOVE_NO_04))` — Same spare-device delivery number |

**Block 4.2.1.1** — [IF: MOVE_NO matches] (L1086)

> Increment move counter for matching rows.

| # | Type | Code |
|---|------|------|
| 1 | SET | `idoCnt += 1` |

**Block 4.2.2** — [After loop: set move count] (L1090)

| # | Type | Code |
|---|------|------|
| 1 | SET | `idoNo = Integer.toString(idoCnt)` — Convert count to string |

**Block 5** — [Record Counter Increment] (L1093)

| # | Type | Code |
|---|------|------|
| 1 | SET | `record_count++` — Increment shared cumulative record counter |

**Block 6** — [Move Destination Code Resolution] (L1096–1112)

> Determines the move destination location code with the same fallback precedence as source: warehouse -> construction company -> pre-booking office.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `sokoSkCd = getData(resultData, MV_SK_SOKO_CD_04)` — Get move destination warehouse code `[-> MV_SK_SOKO_CD_04="move destination warehouse code"]` |
| 2 | CALL | `kojiSkCd = getData(resultData, MV_SK_KOJI_CD_04)` — Get move destination construction company code `[-> MV_SK_KOJI_CD_04="move destination construction company code"]` |
| 3 | CALL | `ofcSkCd = getData(resultData, MV_SK_OFFICE_CD_04)` — Get move destination pre-booking office code `[-> MV_SK_OFFICE_CD_04="move destination pre-booking office code"]` |
| 4 | SET | `skCd = ""` — Initialize move destination code |
| 5 | IF | `!JDKCommonUtil.isNull(sokoSkCd)` — Destination is a warehouse |

**Block 6.1** — [IF: sokoSkCd not null] (L1099)

> Move destination is a warehouse.

| # | Type | Code |
|---|------|------|
| 1 | SET | `skCd = sokoSkCd` |

**Block 6.2** — [ELSE-IF: kojiSkCd not null] (L1104)

> Move destination is a construction company.

| # | Type | Code |
|---|------|------|
| 1 | SET | `skCd = kojiSkCd` |

**Block 6.3** — [ELSE-IF: ofcSkCd not null] (L1109)

> Move destination is a pre-booking office.

| # | Type | Code |
|---|------|------|
| 1 | SET | `skCd = ofcSkCd` |

**Block 7** — [CSV Record Assembly] (L1114–1128)

> Builds the final CSV header record by joining 12 fields with commas. Each field value is wrapped in double quotes via `dqot()`.

| # | Type | Code |
|---|------|------|
| 1 | SET | `return join(",", dqot(RECORD_KIHON), dqot(getData(resultData, SJI_YMD_04)), dqot(lotNo), dqot(mtCd), dqot(getData(resultData, MV_MT_SHELF_CD_04)), dqot(mdlNo), dqot(seizoNo), dqot(getData(resultData, GDS_STAT_CD_04)), dqot(sjiNo), dqot(skCd), dqot(getData(resultData, MV_SK_SHELF_CD_04)), dqot(idoNo))` |
| 2 | - | `RECORD_KIHON = "7G"` — Record type code (basic/standard record) |
| 3 | - | Field order: `record_type, instruction_date, lot_no, move_source_code, move_source_shelf_code, model_number, serial_number, goods_status_code, instruction_count, move_destination_code, move_destination_shelf_code, move_count` |
| 4 | - | `SJI_YMD_04="instruction date"` — The instruction date field |
| 5 | - | `MV_MT_SHELF_CD_04="move source shelf code"` |
| 6 | - | `GDS_STAT_CD_04="goods status code"` — Product condition/status |
| 7 | - | `MV_SK_SHELF_CD_04="move destination shelf code"` |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `lotNo` | Field | Shelf-move lot number — a batch-level identifier grouping related inventory transfers |
| `CSV_LIST` | Constant | Key for the shelf-move result information list stored in the form bean (CSV output list) |
| `MV_MT_SOKO_CD_04` | Constant | Move source warehouse code — the source warehouse identifier for the inventory transfer |
| `MV_MT_KOJI_CD_04` | Constant | Move source construction company code — the source contractor identifier when the source is not a warehouse |
| `MV_MT_OFFICE_CD_04` | Constant | Move source pre-booking office code — the source pre-booking office identifier |
| `MV_MT_SHELF_CD_04` | Constant | Move source shelf code — the shelf/section within the source location |
| `MV_SK_SOKO_CD_04` | Constant | Move destination warehouse code — the destination warehouse identifier |
| `MV_SK_KOJI_CD_04` | Constant | Move destination construction company code — the destination contractor identifier |
| `MV_SK_OFFICE_CD_04` | Constant | Move destination pre-booking office code — the destination pre-booking office identifier |
| `MV_SK_SHELF_CD_04` | Constant | Move destination shelf code — the shelf/section within the destination location |
| `TKKIKI_MDL_CD_04` | Constant | Indoor device model code — the model number of a standard indoor unit |
| `TKKIKI_SETHIN_MDL_CD_04` | Constant | Indoor device set product model code — the model number of a bundled/set product |
| `HUZOKUHIN_MDL_CD_04` | Constant | Accessory model code — the model number of an accessory item |
| `KIKI_SEIZO_NO_04` | Constant | Device manufacturing serial number — unique serial ID for a normal device |
| `TKKIKI_SETHIN_SEIZO_NO_04` | Constant | Indoor device set product serial number — unique serial ID for a set product |
| `SHITEI_WAY_04` | Constant | Specification method code — determines whether the row uses serial number assignment ("2") or quantity specification (other values) |
| `SJI_CNT_04` | Constant | Instruction count — quantity-based count of items in the transfer (used in quantity mode) |
| `SJI_YMD_04` | Constant | Instruction date — the date the instruction was issued (YYYY-MM-DD or similar format) |
| `GDS_STAT_CD_04` | Constant | Goods status code — the current condition/status of the goods (e.g., available, damaged, etc.) |
| `MOVE_NO_04` | Constant | Shelf-move number — spare-device delivery number used to group related transfer rows |
| `RECORD_KIHON` | Constant | `"7G"` — CSV record type code for basic/standard header records |
| `record_count` | Field | Cumulative output record counter — tracks total CSV records generated across the file export |
| `dqot()` | Method | Double-quote wrapper — wraps a value in double quotes for proper CSV field formatting |
| `shiteiCd` | Variable | Specification method code (local) — `"2"` means serial number assignment mode, any other value means quantity mode |
| `mtCd` | Variable | Resolved move source location code — warehouse, contractor, or office code |
| `skCd` | Variable | Resolved move destination location code — warehouse, contractor, or office code |
| `mdlNo` | Variable | Resolved device model number — normal, set product, or accessory model |
| `seizoNo` | Variable | Resolved manufacturing serial number — empty in quantity mode |
| `sjiNo` | Variable | Instruction count — hardcoded to `"1"` in serial mode, read from data in quantity mode |
| `idoNo` | Variable | Move count — hardcoded to `"1"` in serial mode, computed by MOVE_NO group count in quantity mode |
| `idoCnt` | Variable | Intermediate move counter used during the MOVE_NO iteration loop |
| K-Opticom | Term | The telecommunications service provider; the system owner and operator |
| Shelf-move (棚移動) | Term | Inventory transfer — the business process of moving stock from one location to another |
| Spare-device delivery (予備機器配送) | Term | Delivery of backup/reserve equipment — identified by MOVE_NO grouping |
| FTTH | Business term | Fiber To The Home — fiber-optic broadband service (commonly handled in the shelf-move domain for customer equipment) |
| X31SDataBeanAccessArray | Type | Framework data bean access array — in-memory collection for iterating over form-bean data rows |
| X31SDataBeanAccess | Type | Framework single-row data bean — represents one row of form data with key-value access |
