# (DD16) Business Logic — LoanService.borrowBook() [13 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `service.LoanService` |
| Layer | Service |
| Module | `service` (Package: `service`) |

## 1. Role

### LoanService.borrowBook()

This method performs the core loan initiation flow for the library domain: it verifies that a requested book exists, verifies that the requesting member exists, checks whether the book is currently available, and if so creates a new loan record while marking the book as unavailable. Business-wise, it is the entry point for a “borrow a book” transaction and enforces the basic eligibility rules before a loan is created.

The method implements a simple routing-and-validation pattern: it resolves the requested resources first, exits early with a user-facing message on any validation failure, and only proceeds to state mutation when all preconditions are satisfied. In effect, it acts as a guard clause sequence around the loan creation step.

Its role in the larger system is a service-layer orchestration method consumed by the console UI. The UI collects the book ID and member ID, delegates to this method, and displays the returned status message directly to the user. Because of that, the method is responsible not only for business state changes but also for producing human-readable outcome messages.

The method has three failure branches and one success branch. It returns “Book not found” when the book ID does not resolve, “Member not found” when the member ID does not resolve, and “Book is currently unavailable” when the book has already been borrowed. Only the final branch creates a loan ID, persists the loan in memory, and confirms success.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START["borrowBook(bookId, memberId)"]
    A["bookRepo.findById(bookId)"]
    B["memberRepo.findById(memberId)"]
    C{"book.isEmpty()?"}
    D["Return \"Book not found: \" + bookId"]
    E{"member.isEmpty()?"}
    F["Return \"Member not found: \" + memberId"]
    G{"book.get().isAvailable()?"}
    H["Return \"Book is currently unavailable.\""]
    I["book.get().setAvailable(false)"]
    J["UUID.randomUUID().toString().substring(0, 6).toUpperCase()"]
    K["Create loanId = \"L\" + randomId"]
    L["loans.add(new Loan(loanId, book.get(), member.get()))"]
    M["Return \"Borrowed successfully. Loan ID: \" + loanId"]
    START --> A
    A --> B
    B --> C
    C -- "true" --> D
    C -- "false" --> E
    E -- "true" --> F
    E -- "false" --> G
    G -- "false" --> H
    G -- "true" --> I
    I --> J
    J --> K
    K --> L
    L --> M
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `bookId` | `String` | Business identifier of the book the member wants to borrow. It is used to locate the target inventory item and drives the first validation branch; if no book exists for this identifier, the method stops immediately with a not-found message. |
| 2 | `memberId` | `String` | Business identifier of the member requesting the loan. It is used to resolve the borrower record and drives the second validation branch; if no member exists for this identifier, the method stops immediately with a not-found message. |

Instance fields and external state read by the method: `bookRepo`, `memberRepo`, and `loans`.

## 4. CRUD Operations / Called Services

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

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `Book.isAvailable` | Book | - | Checks whether the book can still be borrowed |
| U | `Book.setAvailable` | Book | - | Marks the selected book as unavailable after the loan is created |

Analyze all method calls within this method and classify each as a CRUD operation.
Use the pre-computed evidence above. If SC Code or Entity/DB is missing, try to infer from:
- The **SC Code** (Service Component code, e.g., `EKK0361A010SC`, `EKK1081D010CBS`) — look at the class name of the called method or its containing class.
- The **Entity/DB tables** — search for table name constants (often `KK_T_*` pattern), SQL references, or entity names in the called method's source code.

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `findById` | - | Book repository / in-memory store | Retrieves the book record for the provided book ID |
| R | `findById` | - | Member repository / in-memory store | Retrieves the member record for the provided member ID |
| R | `isAvailable` | Book | - | Confirms whether the requested book is still available for lending |
| U | `setAvailable` | Book | - | Updates the in-memory book state to unavailable |
| C | `new Loan(...)` | - | Loan in-memory collection | Creates a new loan object linking the book and member |
| C | `loans.add(...)` | - | Loan list / in-memory store | Persists the new loan into the active loan collection |
| R | `UUID.randomUUID()` | - | - | Generates a unique identifier fragment for the new loan ID |
| R | `toString()` / `substring()` / `toUpperCase()` | - | - | Formats the generated UUID fragment for displayable loan ID creation |

## 5. Dependency Trace

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

No screen/batch entry points found within 8 hops. Direct callers found: 1 method.
Terminal operations from this method: `setAvailable` [-], `isAvailable` [-]

Trace who calls this method and what this method ultimately calls.
Use the pre-computed evidence and caller search results from Step 2 above.

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Screen:ConsoleUI | `ConsoleUI.borrowBook()` -> `LoanService.borrowBook()` | `Book.isAvailable [R]`, `Book.setAvailable [U]`, `loans.add [C]` |

## 6. Per-Branch Detail Blocks

**Block 1** — [SEQUENCE] `(borrow request entry)` (L23)

> The method begins by resolving both target business entities required to validate the loan transaction.

| # | Type | Code |
|---|------|------|
| 1 | SET | `Optional<Book> book = bookRepo.findById(bookId);` |
| 2 | SET | `Optional<Member> member = memberRepo.findById(memberId);` |

**Block 2** — [IF] `(book.isEmpty())` (L26)

> Rejects the transaction if the requested book cannot be located.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return "Book not found: " + bookId;` |

**Block 3** — [IF] `(member.isEmpty())` (L27)

> Rejects the transaction if the borrower record cannot be located.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return "Member not found: " + memberId;` |

**Block 4** — [IF] `(!book.get().isAvailable())` (L28)

> Rejects the transaction when the book is already on loan or otherwise unavailable.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `book.get().isAvailable();` |
| 2 | RETURN | `return "Book is currently unavailable.";` |

**Block 5** — [SEQUENCE] `(successful borrow path)` (L30-L34)

> The successful path updates the book state, generates a new loan identifier, stores the loan, and returns a success message.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `book.get().setAvailable(false);` |
| 2 | SET | `String loanId = "L" + UUID.randomUUID().toString().substring(0, 6).toUpperCase();` |
| 3 | CALL | `new Loan(loanId, book.get(), member.get());` |
| 4 | EXEC | `loans.add(new Loan(loanId, book.get(), member.get()));` |
| 5 | RETURN | `return "Borrowed successfully. Loan ID: " + loanId;` |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `bookId` | Field | Identifier of the book requested for borrowing. |
| `memberId` | Field | Identifier of the member who wants to borrow the book. |
| `bookRepo` | Technical term | Book repository used to locate book records. |
| `memberRepo` | Technical term | Member repository used to locate borrower records. |
| `loans` | Collection | Active in-memory collection of loan records. |
| `Loan` | Domain entity | Loan record that links one borrowed book to one member. |
| `isAvailable` | Method | Checks whether the book is available for borrowing. |
| `setAvailable` | Method | Updates the book availability status. |
| `UUID` | Technical term | Java utility for generating unique identifiers. |
| `loanId` | Field | Generated identifier for the newly created loan. |
| `borrow` | Business term | To take a book out on loan from the library. |
| `available` | Business term | State indicating that a book can still be borrowed. |
| `unavailable` | Business term | State indicating that a book is already borrowed and cannot be loaned again. |
| `ConsoleUI` | Screen | Console-based user interface that collects input and displays service results. |
| `Optional` | Technical term | Wrapper type used to represent a value that may or may not exist. |
