# Business Logic — JBSbatKKDelKhChk.canDelMlad() [50 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.business.service.JBSbatKKDelKhChk` |
| Layer | Service (Batch processing service component) |
| Module | `service` (Package: `eo.business.service`) |

## 1. Role

### JBSbatKKDelKhChk.canDelMlad()

This method performs the **email address deletion eligibility check** (消去可否チェック処理(メールアドレス)) as part of a customer data purge (消去) batch processing workflow in the K-Opticom customer management system. It determines whether a given email address (MLAD) associated with an option service contract (OPSVKEI_NO) may be safely deleted from the system without violating data integrity or leaving orphaned cancellation orders.

The method implements a **two-stage gate pattern**: first, it verifies that the option service contract line item (KK_T_OP_SVC_KEI) has no remaining records matching the email address, operational service contract number, and operation date — confirming the contract line has been fully terminated. If this first gate fails (records still exist), deletion is immediately denied. If the first gate passes, a second gate checks the order settings table (KK_T_ODR_SET) to ensure no cancellation SOD (Service Order Data / 解約SOD) has been issued for the email address. A cancellation SOD indicates the customer has requested service termination, which must take precedence over the data purge — deletion is blocked in this case.

This method is a **shared utility** called by `JBSbatKKDelKhChk.execute()`, the main batch entry point for deletion eligibility checks. It handles only the **email address** branch of the broader deletion eligibility framework (the sibling method `canDelMailalias` handles email alias data). The method returns a boolean: `true` means the email address is eligible for deletion; `false` means it must be preserved.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["canDelMlad(inMap)"])
    START --> INIT["Initialize canDel = false; nextRec = null"]
    INIT --> BUILD1["Build selectWhereParam[OPSVKEI_NO, MLAD, opeDate]"]
    BUILD1 --> EXEC1["executeKK_T_OP_SVC_KEI_KK_SELECT_039(selectWhereParam)"]
    EXEC1 --> FETCH1["nextRec = db_KK_T_OP_SVC_KEI.selectNext()"]
    FETCH1 --> CHECK1{nextRec == null
(No contract line found)}
    CHECK1 -->|true| SETDEL["canDel = true
(Contract line absent - first gate passes)"]
    CHECK1 -->|false| DENY1["canDel = false
(Contract line exists - deny deletion)"]
    SETDEL --> CHECK_DEL{canDel == true
(First gate passed?)}
    DENY1 --> CHECK_DEL
    CHECK_DEL -->|false| RETURN_FALSE["return false
(Delete not permitted)"]
    CHECK_DEL -->|true| INIT2["Initialize kk1041NextRec = null"]
    INIT2 --> BUILD2["Build kk1041SelectWhereParam[SVKEI_NO, OPSVKEI_NO, MLAD]"]
    BUILD2 --> EXEC2["executeKK_T_ODR_SET_KK_SELECT_026(kk1041SelectWhereParam)"]
    EXEC2 --> FETCH2["kk1041NextRec = db_KK_T_ODR_SET.selectNext()"]
    FETCH2 --> CHECK2{kk1041NextRec == null
(No cancellation SOD found)}
    CHECK2 -->|true| ALLOW["canDel = true
(No cancellation SOD - allow deletion)"]
    CHECK2 -->|false| DENY2["canDel = false
(Cancellation SOD exists - deny deletion)"]
    DENY2 --> LOG["Build error log: '解約オダが未発行のため消去オダ発行をスキップしました'"]
    LOG --> ERROR["printBusinessErrorLog(EKKB1200AI, log)"]
    ERROR --> RETURN_DENY["return false
(Delete not permitted)"]
    ALLOW --> RETURN_TRUE["return true
(Delete permitted)"]
    RETURN_FALSE --> END(["end"])
    RETURN_TRUE --> END
    RETURN_DENY --> END
```

**Processing Summary:**
- **Stage 1 (Contract Line Check):** Queries the `KK_T_OP_SVC_KEI` (Option Service Contract) table for records matching the service contract number, email address, and operation date. If no record exists, the first gate passes (`canDel = true`). If records exist, the email address is still in active use and deletion is denied.
- **Stage 2 (Cancellation SOD Check — ANK-2897-00-00 enhancement):** Only reached if Stage 1 passes. Queries the `KK_T_ODR_SET` (Order Settings) table for cancellation SOD records. If a cancellation SOD exists, deletion is blocked to prevent data loss during active cancellation processing. If no cancellation SOD exists, deletion is permitted.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `inMap` | `JBSbatServiceInterfaceMap` | Input message carrying the email address deletion eligibility check request. Contains the option service contract number (OPSVKEI_NO), email address (MLAD), service contract number (SVKEI_NO), and related identifiers as string key-value pairs. Acts as the single contract object threading all business keys through the batch processing pipeline. |

**Instance Fields / External State:**

| Field | Type | Business Description |
|-------|------|---------------------|
| `db_KK_T_OP_SVC_KEI` | `JBSbatCommonDBInterface` | Database abstraction for the `KK_T_OP_SVC_KEI` (Option Service Contract) table — used to execute SELECT queries and iterate results via `selectNext()` |
| `db_KK_T_ODR_SET` | `JBSbatCommonDBInterface` | Database abstraction for the `KK_T_ODR_SET` (Order Settings) table — used to check for cancellation SOD records |
| `opeDate` | `String` | Operation date (運用日) — the batch processing date, used as a query filter in the contract line check |
| `commonItem` | `JBSbatCommonItem` | Common item context — provides access to the logging subsystem (`getLogPrint().printBusinessErrorLog`) for audit trail entries |

## 4. CRUD Operations / Called Services

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

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `db_KK_T_OP_SVC_KEI.selectNext` | JBSbatKK_T_OP_SVC_KEI | `KK_T_OP_SVC_KEI` | Reads option service contract records via KK_SELECT_039 SQL to verify no active contract lines reference the email address |
| R | `db_KK_T_ODR_SET.selectNext` | JBSbatKK_T_ODR_SET | `KK_T_ODR_SET` | Reads order settings records via KK_SELECT_026 SQL to detect whether a cancellation SOD has been issued |
| - | `JBSbatKKIFM160.getString` (x6 calls) | JBSbatKKIFM160 | - | Extracts string values (OPSVKEI_NO, SVKEI_NO, MLAD) from the input message map `inMap` |
| - | `JBSbatKKDelKhChk.executeKK_T_OP_SVC_KEI_KK_SELECT_039` | JBSbatKKDelKhChk | - | Executes the SQL query (KK_SELECT_039) against `KK_T_OP_SVC_KEI` with parameterized WHERE clause |
| - | `JBSbatKKDelKhChk.executeKK_T_ODR_SET_KK_SELECT_026` | JBSbatKKDelKhChk | - | Executes the SQL query (KK_SELECT_026) against `KK_T_ODR_SET` with parameterized WHERE clause |
| - | `JKKBatOneTimeLogWriter.printBusinessErrorLog` | JKKBatchMessage | - | Writes business error log entry with message key `EKKB1200AI` and context parameters |

## 5. Dependency Trace

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

No screen/batch entry points found within 8 hops. Direct callers found: 1 methods.
Terminal operations from this method: `printBusinessErrorLog` [-], `executeKK_T_OP_SVC_KEI_KK_SELECT_039` [-], `executeKK_T_ODR_SET_KK_SELECT_026` [-], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R], `getString` [R]

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Batch: JBSbatKKDelKhChk.execute() | `JBSbatKKDelKhChk.execute()` → `JBSbatKKDelKhChk.canDelMlad(inMap)` | `executeKK_T_OP_SVC_KEI_KK_SELECT_039 [R] KK_T_OP_SVC_KEI`, `executeKK_T_ODR_SET_KK_SELECT_026 [R] KK_T_ODR_SET`, `printBusinessErrorLog [E] EKKB1200AI` |

**Notes:** This method is a private utility called exclusively from `execute()`, the primary batch processing loop. `execute()` handles dispatch to this and other deletion eligibility check methods (e.g., `canDelMailalias`) based on the deletion target type.

## 6. Per-Branch Detail Blocks

**Block 1** — `[INIT]` (L664)

> Initializes local variables before any processing.

| # | Type | Code |
|---|------|------|
| 1 | SET | `canDel = false` // 消去可否 — initialization: default to NOT deletable |
| 2 | SET | `nextRec = null` // 次レコード — initialization: no next record yet |

**Block 2** — `[BUILD PARAMS]` (L668-672)

> Constructs the WHERE clause parameter array for querying the option service contract table.

| # | Type | Code |
|---|------|------|
| 1 | SET | `selectWhereParam[0] = inMap.getString(JBSbatKKIFM160.OPSVKEI_NO)` // オプションサービス契約番号 (Option Service Contract Number) |
| 2 | SET | `selectWhereParam[1] = inMap.getString(JBSbatKKIFM160.MLAD)` // メールアドレス (Email Address) |
| 3 | SET | `selectWhereParam[2] = opeDate` // 運用日 (Operation Date) — instance field from batch context |

**Block 3** — `[EXECUTE CONTRACT LINE QUERY]` (L674-676)

> Queries `KK_T_OP_SVC_KEI` to check if the option service contract line still references this email address.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `executeKK_T_OP_SVC_KEI_KK_SELECT_039(selectWhereParam)` // Executes KK_SELECT_039 SQL against KK_T_OP_SVC_KEI |
| 2 | CALL | `nextRec = db_KK_T_OP_SVC_KEI.selectNext()` // Fetches next row; null means no matching records |

**Block 4** — `[IF: No contract line found → first gate passes]` (L677-680)
Condition: `nextRec == null`

> If the option service contract table has no records for this email address, the contract line is absent — the first deletion gate passes, and `canDel` is set to `true`.

| # | Type | Code |
|---|------|------|
| 1 | SET | `canDel = true` // 消去可否 — contract line not found, deletion eligible |

**Block 5** — `[ELSE: Contract line exists → deny deletion]` (implicit L677-680)
Condition: `nextRec != null`

> If a matching contract line IS found, `canDel` remains `false`. Deletion is denied because the email address is still referenced by an active option service contract line.

**Block 6** — `[IF: First gate result check]` (L683-686)
Condition: `!canDel` (i.e., first gate failed)

> ANK-2897-00-00 ADD: Early return if the first check determined deletion is NOT allowed. Prevents unnecessary second-stage processing.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return canDel` // Returns false — deletion denied because contract line still exists |

**Block 7** — `[INIT STAGE 2]` (L689-690)

> Prepares for the cancellation SOD check.

| # | Type | Code |
|---|------|------|
| 1 | SET | `kk1041NextRec = null` // 次レコード — initialization for second query |

**Block 8** — `[BUILD STAGE 2 PARAMS]` (L692-696)

> Constructs the WHERE clause for the cancellation SOD check against `KK_T_ODR_SET`.

| # | Type | Code |
|---|------|------|
| 1 | SET | `kk1041SelectWhereParam[0] = inMap.getString(JBSbatKKIFM160.SVKEI_NO)` // サービス契約番号 (Service Contract Number) |
| 2 | SET | `kk1041SelectWhereParam[1] = inMap.getString(JBSbatKKIFM160.OPSVKEI_NO)` // オプションサービス契約番号 (Option Service Contract Number) |
| 3 | SET | `kk1041SelectWhereParam[2] = inMap.getString(JBSbatKKIFM160.MLAD)` // メールアドレス (Email Address) |

**Block 9** — `[EXECUTE CANCELLATION SOD QUERY]` (L699-701)

> Queries `KK_T_ODR_SET` to check for cancellation SOD records.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `executeKK_T_ODR_SET_KK_SELECT_026(kk1041SelectWhereParam)` // Executes KK_SELECT_026 SQL against KK_T_ODR_SET |
| 2 | CALL | `kk1041NextRec = db_KK_T_ODR_SET.selectNext()` // Fetches next row; null means no cancellation SOD exists |

**Block 10** — `[IF: Cancellation SOD exists → deny deletion]` (L704-712)
Condition: `kk1041NextRec != null`

> 解約SODが発行されているか判定 (Determine if a cancellation SOD has been issued). If a cancellation SOD record is found, deletion is blocked to prevent data loss during cancellation processing. An error log is written with the message key `EKKB1200AI` indicating that the deletion order was skipped because no cancellation order was issued.

| # | Type | Code |
|---|------|------|
| 1 | SET | `canDel = false` // 消去可否 — cancellation SOD found, deletion denied |
| 2 | SET | `log = "解約オダが未発行のため消去オダ発行をスキップしました。オペションサービス契約番号[" + inMap.getString(JBSbatKKIFM160.OPSVKEI_NO) + "]"` // Error message: deletion order skipped because cancellation order not issued, includes OPSVKEI_NO |
| 3 | CALL | `commonItem.getLogPrint().printBusinessErrorLog("EKKB1200AI", new String[]{log})` // Writes business error log with message key and context |

**Block 11** — `[RETURN]` (L713)

> Returns the final deletion eligibility decision.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return canDel` // true = email address may be deleted; false = deletion blocked |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `MLAD` | Field | Email Address — the customer's email address being evaluated for purge/deletion |
| `OPSVKEI_NO` | Field | Option Service Contract Number — the identifier for an option service line item attached to a base service contract |
| `SVKEI_NO` | Field | Service Contract Number — the primary identifier for a customer's service contract line |
| `opeDate` | Field | Operation Date — the batch processing date used as a query filter for contract records |
| `KK_T_OP_SVC_KEI` | Table | Option Service Contract table — stores option-level service contract line items; referenced in the first deletion gate |
| `KK_T_ODR_SET` | Table | Order Settings table — stores order configuration records; used to detect cancellation SOD (解約SOD) that would block deletion |
| SOD | Acronym | Service Order Data — telecom order fulfillment entity representing a service order (e.g., registration, change, cancellation) |
| 解約SOD | Business term | Cancellation SOD — a service order indicating the customer has requested service termination; takes priority over data purge operations |
| 消去 | Business term | Data Purge / Deletion — the batch process that removes customer personal data (email addresses, etc.) per data retention policy |
| 消去可否チェック | Business term | Deletion Eligibility Check — the gate mechanism that determines whether customer data can be safely purged |
| 運用日 | Business term | Operation Date — the processing date of the batch job, used as a temporal filter in queries |
| KK_SELECT_039 | SQL Key | SQL definition key for querying `KK_T_OP_SVC_KEI` with parameters: OPSVKEI_NO, MLAD, opeDate |
| KK_SELECT_026 | SQL Key | SQL definition key for querying `KK_T_ODR_SET` with parameters: SVKEI_NO, OPSVKEI_NO, MLAD |
| EKKB1200AI | Message Key | Business error log message key — logged when a deletion order is skipped due to absence of a cancellation order |
| JBSbatServiceInterfaceMap | Type | Input message container — maps string keys to values; carries all business identifiers between batch processing stages |
