---
title: Deferred print queue lifecycle
summary: Creates, retrieves, updates, and purges deferred (queued) print requests awaiting later batch processing.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Services.Printing.Remote
reference_type: package
operation_id: OP-001
trigger: A caller enqueues a print request for later processing, a batch job retrieves eligible items, or a cleanup job purges a processed item
---

# Deferred print queue lifecycle

A deferred print item represents a print request that cannot be printed immediately and is queued in `XDEFERRED_PRINT` for later batch processing. `clsXDeferredPrint` and `clsXDeferredPrintCollection` together provide the full lifecycle for this entity: enqueue a new item, retrieve eligible items for processing, update an existing item, and purge an item once it has been handled.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-001 |
| **Trigger** | Caller creates a new deferred print item (enqueue); a batch process retrieves items by printed-date cutoff or document description; a caller updates an existing item; a caller deletes a processed item by its sequence number |
| **Inputs** | Copies count, document description, duplex code, file name, printed date, ten sort values, XML payload text, create user; for retrieval, a printed-date cutoff or a document description; for delete, `XdeferredSeqNum` |
| **Outputs** | Inserted, updated, or removed row in `XDEFERRED_PRINT`; collection of `clsXDeferredPrint` for retrieval; error message on row-count contention |
| **Primary components** | `clsXDeferredPrint.Create`, `clsXDeferredPrint.BeforeInsert`/`AfterInsert`, `clsXDeferredPrint.BeforeUpdate`/`AfterUpdate`, `clsXDeferredPrint.BeforeDelete`/`AfterDelete`, `clsXDeferredPrintCollection.BeforeRetrieve`/`AfterRetrieve` |
| **Entry point** | `Services\SAIF.Services.Printing.Remote\clsXDeferredPrint.vb`, `Services\SAIF.Services.Printing.Remote\clsXDeferredPrintCollection.vb` |

## Steps

1. **Enqueue a new deferred print item.** Caller invokes `clsXDeferredPrint.NewXdeferredPrint(...)`, which calls `Create()`.
   - If the criteria's `XdeferredSeqNum` is `0`: `Create()` calls `MyCriteria.DataPortalInfo.GetNextSeqNum("XDeferred_SEQ")` to generate the primary key.
   - Otherwise: the caller-supplied `XdeferredSeqNum` is used as-is.
2. **Persist the new item.** `BeforeInsert` binds all 17 column parameters (copies count, document description, duplex code, file name, sequence number, create user, printed date, and ten sort values) and executes [SQL-004](../sql/SQL-004-saif-services-printing-remote.md) (`INSERT INTO XDEFERRED_PRINT ...`, [XDEFERRED_PRINT](../database-tables.md#xdeferred_print)).
   - `AfterInsert` checks `RowsAffected <> 1` and calls `AddErrorMessage("InsertError", "Insert Failed")` on contention ([BR-001](../business-rules.md#br-001-row-count-contention-check)).
3. **Retrieve deferred prints for processing.** Caller invokes `clsXDeferredPrintCollection.GetXdeferredPrintCollection(inPrintedDate)` (retrieve-by-date) or the `inDocumentDescr` overload (retrieve-by-description). `Criteria.New` sets `RetrieveType` (`byDate` or `byDocDescr`); for the by-date path it also computes `ThirtyDaysAgoDate = Today.AddDays(-30)`.
4. **Assemble the retrieval SQL.** `BeforeRetrieve` appends a `WHERE` clause and a ten-column sort order to the base `RetrieveSQL` text depending on `RetrieveType`, producing [SQL-010](../sql/SQL-010-saif-services-printing-remote.md) ([XDEFERRED_PRINT](../database-tables.md#xdeferred_print)):
   - `byDate`: `WHERE XDEFERRED_PRINT.PRINTED_DATE < :PrintedDate OR XDEFERRED_PRINT.CREATE_DATE < :ThirtyDaysAgoDate` — a supplied cutoff date, or the 30-day default, makes an item eligible regardless of its current print status ([BR-002](../business-rules.md#br-002-deferred-print-retentioneligibility-rule)).
   - `byDocDescr`: `WHERE XDEFERRED_PRINT.DOCUMENT_DESCR = :DocumentDescr AND XDEFERRED_PRINT.PRINTED_DATE IS NULL` — only items not yet printed for the given description are returned.
5. **Load the retrieved rows.** `AfterRetrieve` iterates the `IDataReader` and constructs a `clsXDeferredPrint` per row via `Load()`/`Fill()`, adding each to the collection.
6. **Update an existing item.** Caller marks an existing `clsXDeferredPrint` dirty and saves it. `BeforeUpdate` binds all mutable columns (copies count, document description, duplex code, file name, sequence number, printed date, ten sort values, XML payload as an NCLOB parameter) and executes [SQL-015](../sql/SQL-015-saif-services-printing-remote.md) (`UPDATE XDEFERRED_PRINT ...`, [XDEFERRED_PRINT](../database-tables.md#xdeferred_print)).
   - `AfterUpdate` checks `RowsAffected <> 1` and adds `UpdateError` on contention ([BR-001](../business-rules.md#br-001-row-count-contention-check)).
7. **Purge a deferred print item.** Caller invokes the delete lifecycle on a `clsXDeferredPrint` instance, supplying `XdeferredSeqNum`. `BeforeDelete` binds `:XdeferredSeqNum` and executes [SQL-019](../sql/SQL-019-saif-services-printing-remote.md) (`DELETE XDEFERRED_PRINT WHERE XDEFERRED_SEQ_NUM = :XdeferredSeqNum`, [XDEFERRED_PRINT](../database-tables.md#xdeferred_print)).
   - `AfterDelete` has its row-count contention check commented out in source — no live post-delete validation applies for this delete path, unlike every other insert/update/delete in this library.*

## Process flow

The following diagram visualizes the four lifecycle actions available on the deferred print queue.

```mermaid
flowchart TD
	Start([Caller selects an action]) --> Which{Which action?}
	Which -->|Enqueue| Seq[Create: assign or generate XdeferredSeqNum]
	Seq --> Ins[Insert into XDEFERRED_PRINT]
	Ins --> InsCheck{RowsAffected = 1?}
	InsCheck -->|No| InsErr([InsertError added])
	InsCheck -->|Yes| InsOk([Item queued])
	Which -->|Retrieve for processing| RetType{RetrieveType?}
	RetType -->|byDate| DateWhere[WHERE PrintedDate < cutoff<br>OR CreateDate < 30 days ago]
	RetType -->|byDocDescr| DescWhere[WHERE DocumentDescr = value<br>AND PrintedDate IS NULL]
	DateWhere --> Load[Load matching rows into collection]
	DescWhere --> Load
	Which -->|Update| Upd[Update mutable columns by seq num]
	Upd --> UpdCheck{RowsAffected = 1?}
	UpdCheck -->|No| UpdErr([UpdateError added])
	UpdCheck -->|Yes| UpdOk([Item updated])
	Which -->|Purge| Del[Delete by XdeferredSeqNum]
	Del --> NoCheck([AfterDelete check is commented out —<br>no contention validation])
```

## Failure and edge-case behavior

- Insert and update both add an error message when `RowsAffected <> 1`, but delete does not — the delete contention check exists in source but is commented out, so a purge that affects zero or multiple rows is not reported.*
- Retrieval by date treats a stale `CREATE_DATE` (more than 30 days old) as eligible for reprocessing even if the item was never printed, alongside items whose `PRINTED_DATE` is before the supplied cutoff ([BR-002](../business-rules.md#br-002-deferred-print-retentioneligibility-rule)).
- Retrieval by document description additionally requires `PRINTED_DATE IS NULL`, so already-printed items are excluded from that path even if the description matches.
- A single-item retrieve-by-key path (`GetXdeferredPrint`) is defined only as commented-out source (dead code; corresponds to dead [SQL-009](../sql/SQL-009-saif-services-printing-remote.md)) — no live single-item retrieval exists for this entity.*
- Several `Criteria` SQL properties are dead code not reachable from any lifecycle method: the `CreateSQL` sequence-select properties on both classes ([SQL-001](../sql/SQL-001-saif-services-printing-remote.md), [SQL-002](../sql/SQL-002-saif-services-printing-remote.md)) and the collection-level Insert/Update/Delete properties ([SQL-005](../sql/SQL-005-saif-services-printing-remote.md), [SQL-016](../sql/SQL-016-saif-services-printing-remote.md), [SQL-020](../sql/SQL-020-saif-services-printing-remote.md)).

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.

## 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\clsXDeferredPrint.vb`
- `Services\SAIF.Services.Printing.Remote\clsXDeferredPrintCollection.vb`
