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

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

## 1. Role

### modUtil.GetNextBatchNumber()

This utility function assigns a unique sequential batch identifier used to group and track import operations across the Accounts Receivable (AR) reconciliation system. It queries the `tblImportBatch` table to find the highest existing `BatchID` and returns the next integer value, ensuring that each import run receives a distinct, monotonically increasing batch key. The method serves as a shared utility (called via `modUtil`, a standard VBA module prefix for utility/procedure collections) and is invoked by the import pipeline — specifically `modImport.RunImport()` — to tag every row and record belonging to a single import run. Its role in the larger system is that of a lightweight database-backed sequence generator, providing a simple auto-increment strategy without relying on Access AutoNumber fields. This avoids race conditions in scenarios where the batch ID must be known before any rows are inserted into the table, allowing the batch key to be reserved at the start of the import.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["GetNextBatchNumber()"])
    STEP_DB["Open CurrentDb()"]
    STEP_QRY["Query: SELECT Max(BatchID) AS MaxID FROM tblImportBatch"]
    STEP_CHECK{"Is MaxID NULL?"}
    STEP_DEFAULT["Set return = 1"]
    STEP_INCREMENT["Set return = MaxID + 1"]
    STEP_CLOSE["Close recordset, release resources"]
    STEP_RET["Return batch number (Long)"]

    START --> STEP_DB
    STEP_DB --> STEP_QRY
    STEP_QRY --> STEP_CHECK
    STEP_CHECK -- "Yes (empty table / no rows)" --> STEP_DEFAULT
    STEP_CHECK -- "No (existing records)" --> STEP_INCREMENT
    STEP_DEFAULT --> STEP_CLOSE
    STEP_INCREMENT --> STEP_CLOSE
    STEP_CLOSE --> STEP_RET
```

**Requirements:**
- Every if/else, loop, and method call is represented as a node.
- Diamond node for the `IsNull(rs!MaxID)` condition check.
- Both branches are shown: the default path (when the table has no records) and the increment path (when records exist).

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| - | (none) | - | This function takes no parameters. It derives its result entirely from the current state of `tblImportBatch` in the Access database. |

**External state read:**
| Source | Description |
|--------|-------------|
| `tblImportBatch.BatchID` | The maximum value of the `BatchID` column in the import batch tracking table. If no rows exist, the aggregate returns NULL. |

## 4. CRUD Operations / Called Services

### Database Tables (code↔DB map)

| Access Table | Foreign-key reference → |
|---|---|
| `tblImportBatch` | — |

### Analysis of database operations

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `OpenRecordset("SELECT Max(BatchID) AS MaxID FROM tblImportBatch")` | — | `tblImportBatch` | Reads the maximum existing `BatchID` to determine the next sequential batch number. This is a pure read (aggregate) — no data is modified. |

**How to classify:**
- **R** (Read): The method performs a `SELECT MAX(...)` query against `tblImportBatch`. This is a read-only operation that returns a single scalar value.

## 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: `tblImportBatch` (Read)

Trace who calls this method and what this method ultimately calls.

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

**Instructions:**
- `modImport.RunImport()` is the sole known caller, located in `modImport.bas` at line 28.
- No screen entry points (`KKSV*`) or batch entry points were found. This method is called directly by the import pipeline module.

## 6. Per-Branch Detail Blocks

> Each branch of the control flow is displayed as a hierarchical block structure.

**Block 1** — [SET] (L9)

> Open the Access database connection and execute the query to find the maximum BatchID.

| # | Type | Code |
|---|------|------|
| 1 | SET | `Dim db As DAO.Database` | Local DAO database object declaration |
| 2 | SET | `Dim rs As DAO.Recordset` | Local DAO recordset object declaration |
| 3 | SET | `Set db = CurrentDb()` | Opens the current Access database |
| 4 | SET | `Set rs = db.OpenRecordset("SELECT Max(BatchID) AS MaxID FROM tblImportBatch")` | Executes aggregate query on `tblImportBatch` to get the highest BatchID |

**Block 2** — [IF] (`IsNull(rs!MaxID)`) (L10)

> Determines whether the `tblImportBatch` table is empty. If there are no rows, `Max(BatchID)` returns NULL, meaning this is the first batch and we should start numbering from 1.

| # | Type | Code |
|---|------|------|
| 1 | SET | `GetNextBatchNumber = 1` | [Default path] First batch — initialize batch number to 1 |

**Block 2.1** — [ELSE] (L12)

> The table already has records. The maximum `BatchID` was found, so increment it by 1 to get the next available batch number.

| # | Type | Code |
|---|------|------|
| 1 | SET | `GetNextBatchNumber = rs!MaxID + 1` | [Increment path] Next batch = current max + 1 |

**Block 3** — [SET / CLEANUP] (L14–16)

> Close the recordset and release COM/DAO objects to prevent memory leaks — standard VBA cleanup pattern.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `rs.Close` | Closes the recordset |
| 2 | SET | `Set rs = Nothing` | Releases the recordset object |
| 3 | SET | `Set db = Nothing` | Releases the database object |

**Block 4** — [RETURN] (L17)

> Returns the computed batch number to the caller.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `GetNextBatchNumber` | Function return — batch number (Long) |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `BatchID` | Field | Batch identifier — a unique integer used to group all records belonging to a single import run in the AR reconciliation system |
| `tblImportBatch` | Table | Import batch tracking table — stores one row per import batch, with `BatchID` as the primary sequencing key |
| `CurrentDb()` | API | VBA DAO function that returns a reference to the current Access database |
| `DAO.Recordset` | Type | VBA Data Access Objects recordset — a cursor-based interface for reading rows from an Access table |
| `modUtil` | Module | Standard VBA utility module — a collection of shared helper procedures (prefixed with `mod`) used across the application |
| `modImport.RunImport()` | Method | The import pipeline entry point that reads source data and loads it into the AR reconciliation system; calls `GetNextBatchNumber()` to obtain a fresh batch key at the start of each run |
| `IsNull()` | API | VBA function that returns `True` if the supplied expression has a NULL value |
| `Long` | Type | VBA 32-bit signed integer type — used for `BatchID` to support a large range of sequential batch numbers |

---

*Document generated from `ar-reconciliation-vba-access/vba-source/modUtil.bas`, lines 7–20.*
