---
title: Print-control batch header lifecycle
summary: Creates, retrieves, updates, and deletes a print-control batch header record that groups documents queued for a single print run.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Services.Printing.Remote
reference_type: package
operation_id: OP-002
trigger: A caller creates a new batch header directly or as part of building a document batch, retrieves an existing header by its sequence number, updates header fields, or deletes the header
---

# Print-control batch header lifecycle

`clsXPrintControl` represents the header record for a print-control batch, stored in `XPRINT_CONTROL`. It captures the output directory, duplex mode, processed date, IDM (imaging) path, XML file name, and MD5 hash for a set of documents queued together. This operation covers the header's full CRUD lifecycle. Unlike the deferred print queue, `XPRINT_CONTROL` has no live sequence generation — `XPrintControlSeqNum` must be supplied by the caller.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-002 |
| **Trigger** | Caller creates a header (`NewXPrintControl`, directly or via [Create a print batch with documents](create-print-batch-with-documents.md)); caller retrieves a header by sequence number (`GetXPrintControl`); caller updates header fields and saves; caller deletes a header |
| **Inputs** | `XPrintControlSeqNum` (caller-supplied), directory name, duplex mode, processed date, IDM path name, XML file name, MD5 hash |
| **Outputs** | Inserted, updated, or removed row in `XPRINT_CONTROL`; populated `clsXPrintControl` on retrieve; error message on row-count contention |
| **Primary components** | `clsXPrintControl.Create`, `clsXPrintControl.BeforeInsert`/`AfterInsert`, `clsXPrintControl.BeforeRetrieve`/`AfterRetrieve`, `clsXPrintControl.BeforeUpdate`/`AfterUpdate`, `clsXPrintControl.BeforeDelete`/`AfterDelete`, `clsXPrintControl.DuplexMode` |
| **Entry point** | `Services\SAIF.Services.Printing.Remote\clsXPrintControl.vb` |

## Steps

1. **Create a header.** Caller invokes `clsXPrintControl.NewXPrintControl(inDataportal, inXPrintControlSeqNum)`. `Create()` simply copies `XPrintControlSeqNum` from the criteria — no sequence is generated procedurally, so the caller must supply a unique value.
   - The `IDMPathName` backing field defaults to `"PROMPT"` at construction, indicating the imaging destination path is not yet resolved ([BR-006](../business-rules.md#br-006-idm-path-default)).
2. **Persist the header.** `BeforeInsert` binds 7 parameters (directory name, duplex code, processed date, sequence number, IDM path name, XML file name, MD5 hash) and executes [SQL-007](../sql/SQL-007-saif-services-printing-remote.md) (`INSERT INTO XPRINT_CONTROL ...`, [XPRINT_CONTROL](../database-tables.md#xprint_control)). The duplex mode is translated from the `DuplexModes` enum to one of four fixed 5-character codes before binding ([BR-004](../business-rules.md#br-004-duplex-mode-controlled-vocabulary)).
   - `AfterInsert` checks `RowsAffected <> 1` and adds `InsertError` on contention ([BR-001](../business-rules.md#br-001-row-count-contention-check)).
3. **Retrieve a header by key.** Caller invokes `clsXPrintControl.GetXPrintControl(inSeqNum)`. `BeforeRetrieve` binds `:XPrintControlSeqNum` and executes [SQL-013](../sql/SQL-013-saif-services-printing-remote.md) (`SELECT ... FROM XPRINT_CONTROL WHERE XPRINT_CONTROL_SEQ_NUM = :XPrintControlSeqNum`, [XPRINT_CONTROL](../database-tables.md#xprint_control)).
   - `AfterRetrieve` reads the single-row `clsSAIFDataReader` and calls `Fill()` to populate the object, then marks it old (not dirty).
4. **Update a header.** Caller modifies header properties (marking the object dirty) and saves. `BeforeUpdate` binds the same seven columns, plus `XPrintControlSeqNum` a second time for the `WHERE` predicate, and executes [SQL-017](../sql/SQL-017-saif-services-printing-remote.md) (`UPDATE XPRINT_CONTROL SET ...`, [XPRINT_CONTROL](../database-tables.md#xprint_control)).
   - `AfterUpdate` checks `RowsAffected <> 1` and adds `UpdateError` on contention ([BR-001](../business-rules.md#br-001-row-count-contention-check)).
5. **Delete a header.** Caller invokes the delete lifecycle on a `clsXPrintControl` instance. `BeforeDelete` binds `:XprintControlSeqNum` and executes [SQL-022](../sql/SQL-022-saif-services-printing-remote.md) (`DELETE XPRINT_CONTROL WHERE XPRINT_CONTROL_SEQ_NUM = :XPrintControlSeqNum`, [XPRINT_CONTROL](../database-tables.md#xprint_control)).
   - `AfterDelete` checks `RowsAffected <> 1` and adds `DeleteError` on contention ([BR-001](../business-rules.md#br-001-row-count-contention-check)).
6. **Duplex mode translation (cross-cutting).** The `DuplexMode` property getter maps a stored code to the `DuplexModes` enum (`DEFLT`, `HORIZ`→`HORIZONTAL`, `VERTL`→`VERTICAL`, `SIMPL`→`SIMPLEX`); the setter performs the reverse mapping when a caller assigns a `DuplexModes` value. Any stored code that does not match one of the four recognized values falls through the getter with no explicit `Return`, yielding an implicit default value rather than an error.** ([BR-004](../business-rules.md#br-004-duplex-mode-controlled-vocabulary))

## Process flow

The following diagram visualizes the four CRUD actions available on the print-control batch header.

```mermaid
flowchart TD
	Start([Caller selects an action]) --> Which{Which action?}
	Which -->|Create| Seq[Create: copy caller-supplied<br>XPrintControlSeqNum]
	Seq --> Ins[Insert into XPRINT_CONTROL]
	Ins --> InsCheck{RowsAffected = 1?}
	InsCheck -->|No| InsErr([InsertError added])
	InsCheck -->|Yes| InsOk([Header created])
	Which -->|Retrieve| Ret[Select by XPrintControlSeqNum]
	Ret --> Fill[Fill object from reader,<br>mark old]
	Which -->|Update| Upd[Update all mutable columns<br>by seq num]
	Upd --> UpdCheck{RowsAffected = 1?}
	UpdCheck -->|No| UpdErr([UpdateError added])
	UpdCheck -->|Yes| UpdOk([Header updated])
	Which -->|Delete| Del[Delete by XPrintControlSeqNum]
	Del --> DelCheck{RowsAffected = 1?}
	DelCheck -->|No| DelErr([DeleteError added])
	DelCheck -->|Yes| DelOk([Header removed])
```

## Failure and edge-case behavior

- `XPRINT_CONTROL` has no live sequence generation in this library — `XPrintControlSeqNum` must be supplied by the caller; the commented-out `CreateSQL` scalar (`DIRECTORY_NAME_NEXTVAL`, dead [SQL-003](../sql/SQL-003-saif-services-printing-remote.md) on the collection class) is a CodeGen2 template artifact, not a real Oracle sequence.*
- `DuplexMode`'s getter has no `Return` for an unrecognized stored code — VB semantics yield the default enum value (`SIMPLEX`, ordinal 0) implicitly rather than raising an error.**
- All four CRUD actions add an error message uniformly on `RowsAffected <> 1`, unlike the deferred print queue's delete path, which has this check commented out.
- Two other Insert/Update/Delete `Criteria` properties exist on the sibling collection class (`clsXPrintControlCollection`) but are dead/unwired from any `Before*` method: [SQL-008](../sql/SQL-008-saif-services-printing-remote.md) (Insert) and [SQL-018](../sql/SQL-018-saif-services-printing-remote.md) (Update).

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with `**` could not be confirmed; treat as unknown until verified.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

## Sources
- `Services\SAIF.Services.Printing.Remote\clsXPrintControl.vb`
