# Business Logic — modUtil.LogError() [7 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `modUtil.LogError` |
| Layer | Utility (Common Component) |
| Module | `modUtil` (Package: `vba-source/modUtil.bas`) |

## 1. Role

### modUtil.LogError()

`LogError` is a shared utility procedure that records errors encountered during the batch import process into the `tblErrorLog` table in the Microsoft Access backend. It accepts a batch identifier, a row number (or `0` for file-level errors), and a human-readable error description, then persists the record immediately via a parameter-free SQL INSERT. Its primary purpose is to provide an auditable, queryable error trail so that operators and support staff can diagnose failed import runs without re-running the process.

The method implements the **logging utility** design pattern — it is a pure write-side effect procedure called from multiple decision points within the import pipeline. Specifically, it is invoked when a workbook cannot be opened after retry (file-level error, `rowNo = 0`) and when individual rows fail validation against the expected transaction schema (`rowNo = r`, a positive row number).

As a shared module (`modUtil`), `LogError` is not tied to any single form or screen. It is the system's centralized error-logging primitive, consumed by `modImport.RunImport` during Excel file processing. This decouples error recording from the import logic, making the import procedure cleaner and enabling the error log to be queried independently (e.g., via a dedicated error review form or an export report).

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["LogError(batchID, rowNo, msg)"])
    STEP1["Open DAO database connection"]
    STEP2["Build SQL INSERT into tblErrorLog"]
    STEP3["Execute INSERT with escaped msg"]
    STEP4["Release database connection"]
    END_NODE(["Return — void"])

    START --> STEP1
    STEP1 --> STEP2
    STEP2 --> STEP3
    STEP3 --> STEP4
    STEP4 --> END_NODE
```

**Processing flow:**

1. **Open database connection** — Uses the DAO `CurrentDb()` accessor to obtain a reference to the active Access database.
2. **Build and execute SQL INSERT** — Constructs a static `INSERT INTO tblErrorLog (...) VALUES (...)` statement inline via VBA string concatenation. The `ErrorMsg` value is escaped by replacing all single quotes (`'`) with doubled single quotes (`''`) to prevent SQL syntax errors from messages containing apostrophes. The timestamp is set to the current server/local time via the `Now()` SQL function.
3. **Release database connection** — Sets the `DAO.Database` object to `Nothing` to free resources.

There are no conditional branches — the method always executes a single write path.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `batchID` | Long | Import batch identifier — the primary key of the batch run that generated this error. Links the error record to `tblImportBatch` for traceability. |
| 2 | `rowNo` | Long | Row number in the source spreadsheet where the error occurred. Value `0` indicates a file-level or pre-row error (e.g., workbook could not be opened). Positive values pin the error to a specific row for targeted correction. |
| 3 | `msg` | String | Human-readable error description — explains why the row or file was rejected. Single quotes are escaped automatically to ensure safe insertion into the database. |

**External state read by this method:** None (purely stateless — operates entirely through the DAO `CurrentDb()` accessor).

## 4. CRUD Operations / Called Services

### Database Tables (code↔DB map)

| Access Table | Foreign-key reference → |
|---|---|
| tblErrorLog | tblImportBatch |

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| C | `LogError` | — | `tblErrorLog` | Inserts a new error record with batch ID, row number, escaped error message, and server timestamp. |

This method performs a single **Create** operation: it inserts a row into `tblErrorLog`. There are no read, update, or delete operations, and no service component (SC) or business component (CBS) methods are called.

## 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: Create `tblErrorLog`

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Module: `modImport` | `RunImport` -> `modUtil.LogError` | `tblErrorLog [C]` |

**Caller details:**

- **`modImport.RunImport`** — The primary batch import procedure. It calls `LogError` at two decision points:
  1. When the Excel workbook cannot be opened after the maximum retry attempts: `LogError batchID, 0, "Could not open file after N attempts: <filePath>"` (file-level error, row 0).
  2. When an individual row fails validation (Amount, RefNo, or TxnDate does not pass `clsTransaction.IsValid`): `LogError batchID, r, "Invalid row: Amount/RefNo/TxnDate failed validation"` (row-level error, row number `r`).

## 6. Per-Branch Detail Blocks

**Block 1** — [PROCESS] `(no conditions — single-path procedure)` (L22)

> Opens the database connection and prepares the DAO object for writing.

| # | Type | Code |
|---|------|------|
| 1 | DIM | `Dim db As DAO.Database` |
| 2 | SET | `Set db = CurrentDb()` |

**Block 2** — [EXEC] `(single INSERT execution)` (L24–26)

> Constructs and executes the SQL INSERT statement. The `Replace(msg, "'", "''")` call escapes single quotes to prevent SQL injection / syntax errors in the `ErrorMsg` column.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `db.Execute "INSERT INTO tblErrorLog (BatchID, RowNo, ErrorMsg, [Timestamp]) VALUES (" & batchID & ", " & rowNo & ", '" & Replace(msg, "'", "''") & "', Now())"` |

**Block 3** — [PROCESS] `(cleanup)` (L27)

> Releases the DAO database object to free memory.

| # | Type | Code |
|---|------|------|
| 1 | SET | `Set db = Nothing` |
| 2 | RETURN | *(implicit — Sub returns void)* |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `batchID` | Field | Import batch identifier — a unique sequential number assigned to each import run, correlating error records to a specific file import session via `tblImportBatch`. |
| `rowNo` | Field | Spreadsheet row number — the 1-based line index in the source Excel file where an error was detected. Value `0` denotes a file-level error not tied to any row. |
| `tblErrorLog` | Table | Error log table — stores one record per import failure, enabling post-run error review and remediation. Columns: `BatchID`, `RowNo`, `ErrorMsg`, `[Timestamp]`. |
| `tblImportBatch` | Table | Import batch header table — the parent entity referenced by `tblErrorLog.BatchID`. Tracks the overall import session metadata. |
| `CurrentDb()` | API | DAO method — returns a `DAO.Database` object bound to the currently open Access frontend/backend, used for executing ad-hoc SQL statements. |
| `Now()` | SQL function | Access SQL built-in — returns the current date and time at the moment of execution, used to timestamp each error record. |
| `Replace(msg, "'", "''")` | Technique | SQL escape pattern — doubles single quotes within the error message so that the embedded apostrophes do not break the surrounding SQL string literal. |
| DAO | Acronym | Data Access Objects — Microsoft's legacy object model for accessing Access/Jet database engines from VBA. |
| `modUtil` | Module | Utility module — a standard VBA code module (`.bas`) containing shared helper procedures used across the application. |
| `modImport` | Module | Import processing module — handles reading Excel files and loading transactions into the database. |
