# Business Logic — modUtil.GetNextBatchNumber() [14 LOC]

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

## 1. Role

### modUtil.GetNextBatchNumber()

This utility function generates the next unique batch identifier for data import operations within the Microsoft Access application. It queries the `tblImportBatch` table to find the maximum existing `BatchID`, then returns that value incremented by one — or `1` if no records exist yet. This ensures every import run is assigned a distinct batch number, enabling traceability of imported records and their associated error logs. The function serves as a shared utility called by the import orchestrator (`modImport.RunImport`) and any other process that needs a monotonically increasing batch token. It implements a simple auto-increment pattern commonly used in standalone database applications that lack native auto-number fields or sequence objects. Because it is a module-level function in a standard `.bas` module, it has no object state or constructor dependencies — it operates purely on the connected database via DAO.

> **Correction to metadata:** The function is a `Public Function` returning `Long`, not a `void Sub`. The signature is `Public Function GetNextBatchNumber() As Long`.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["GetNextBatchNumber"])
    SETUP(["Open max(BatchID) from tblImportBatch"])
    CHECK{"IsNull(rsMaxID)"}
    SET_ONE["Set GetNextBatchNumber to 1"]
    SET_PLUS["Set GetNextBatchNumber to MaxID + 1"]
    CLOSE["Close rs and db, release objects"]
    RETURN(["Return As Long"])

    START --> SETUP --> CHECK
    CHECK --> |True| SET_ONE --> CLOSE
    CHECK --> |False| SET_PLUS --> CLOSE
    CLOSE --> RETURN
```

**Processing description:**

1. **Setup** — Opens a DAO recordset executing `SELECT Max(BatchID) AS MaxID FROM tblImportBatch`. This aggregates across all prior import batches to find the highest assigned ID.
2. **Null check** — Evaluates whether `MaxID` is `NULL` (i.e., the table is empty or has no rows). This is the only conditional branch.
3. **Initialization branch (True)** — When no prior batch exists, returns `1` to start the sequence.
4. **Increment branch (False)** — When at least one batch record exists, returns the current maximum plus `1` to produce the next sequential ID.
5. **Cleanup** — Closes the recordset, releases the DAO objects, and returns.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| - | (none) | - | This function takes no parameters. It derives its value entirely from database state. |

**External state read:**

| Source | Type | Business Description |
|--------|------|---------------------|
| `tblImportBatch` (DB table) | Table | Stores import batch metadata; the `BatchID` column tracks unique identifiers for each import session. |
| `CurrentDb()` | DAO function | Returns the current DAO Database object, representing the open Access front-end's connected database. |

## 4. CRUD Operations / Called Services

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `db.OpenRecordset("SELECT Max(BatchID) AS MaxID FROM tblImportBatch")` | N/A | `tblImportBatch` | Reads the maximum existing `BatchID` from the import batch tracking table to determine the next sequential number. |

**Classification:** This is a pure **Read** operation — it performs an aggregate query (`Max()`) to retrieve metadata without modifying any data. There are no service component (SC) codes because this is a VBA utility function operating directly on the Access database via DAO.

## 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: Read on tblImportBatch

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

**Caller details — `modImport.RunImport()`:**

This is the import orchestrator module. `RunImport` calls `GetNextBatchNumber` at the start of an import cycle to assign a fresh batch token before processing any rows. The returned batch ID is used to tag all import records and any errors that occur during processing, enabling post-import audit and re-import isolation.

## 6. Per-Branch Detail Blocks

**Block 1** — EXEC `(L7–12)` Initialize DAO connection and execute aggregate query

| # | Type | Code |
|---|------|------|
| 1 | SET | `Dim db As DAO.Database` |
| 2 | SET | `Dim rs As DAO.Recordset` |
| 3 | SET | `Set db = CurrentDb()` |
| 4 | SET | `Set rs = db.OpenRecordset("SELECT Max(BatchID) AS MaxID FROM tblImportBatch")` |

**Block 2** — IF `(IsNull(rs!MaxID))` (L13–15)

> Determines whether any import batches have been recorded. This is the sole branching point in the function.

**Block 2.1** — IF-TRUE `(IsNull(rs!MaxID) = True)` (L13–14)

> The `tblImportBatch` table is empty — no prior batches exist. Initialize the sequence at 1.

| # | Type | Code |
|---|------|------|
| 1 | SET | `GetNextBatchNumber = 1` |

**Block 2.2** — IF-FALSE `(IsNull(rs!MaxID) = False)` (L15)

> At least one batch record exists. Increment the maximum existing BatchID by 1 to produce the next unique number.

| # | Type | Code |
|---|------|------|
| 1 | SET | `GetNextBatchNumber = rs!MaxID + 1` |

**Block 3** — EXEC `(L16–18)` Clean up DAO resources

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `rs.Close` |
| 2 | SET | `Set rs = Nothing` |
| 3 | SET | `Set db = Nothing` |

**Block 4** — RETURN `(L19)` Return the computed batch number

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `End Function` (returns `As Long`) |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `BatchID` | Field | Batch identifier — a monotonically increasing integer that uniquely tags each data import run |
| `tblImportBatch` | DB Table | Import batch metadata table storing import session records and their associated batch IDs |
| `DAO.Database` | Type | Data Access Object database connection — the VBA DAO library's representation of the open Access database |
| `CurrentDb()` | Function | DAO function that returns the current connected database object |
| `IsNull()` | Function | VBA function that checks whether a Variant/field value is NULL (no record or no data) |
| `modImport` | Module | Import orchestrator module that coordinates the data import workflow |
| `RunImport` | Sub | Entry point of the import module — calls `GetNextBatchNumber` to seed the batch ID before processing |
| `modUtil` | Module | Shared utility module providing cross-cutting helper functions (batch number generation, error logging, SQL formatting) |
| `LogError` | Sub | Utility procedure in `modUtil` that logs errors to the `tblErrorLog` table, tagged with a batch ID for traceability |
| `tblErrorLog` | DB Table | Error logging table that stores import errors linked to a specific batch via `BatchID`, `RowNo`, and a timestamp |
| `As Long` | Type | 32-bit signed integer return type; sufficient for batch IDs in the millions |
| `Recordset` | Type | DAO recordset — a cursor-based result set returned from a database query |
