---
title: Purge deleted tasks
summary: Physically removes previously soft-deleted TASK rows for a source/category slice that have aged past a caller-supplied retention window.
status: draft
owner: SAIF
last_reviewed: 2026-07-30
library: SAIF.Business.Tasks
reference_type: package
operation_id: OP-TASK-03
trigger: A batch or administrative caller invokes clsTaskCollection.PurgeTasks directly
---

# Purge deleted tasks

Unlike the rest of the task lifecycle, purge is a standalone shared function on `clsTaskCollection` that bypasses the normal BOF CRUD save path entirely. It calls the Oracle `Task_Purge` procedure directly with a source code, category code, and a retention window in days, and Oracle deletes only rows that have already been soft-deleted and have aged past the threshold.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-TASK-03 |
| **Trigger** | Caller invokes `clsTaskCollection.PurgeTasks(inDataPortalInfo, inTaskSourceCode, inTaskCategoryCode, inKeepDays)` |
| **Inputs** | `IDataPortalInfo`, task source code, task category code, keep-days retention value |
| **Outputs** | Count of physically deleted rows |
| **Primary components** | `clsTaskCollection.PurgeTasks` |
| **Entry point** | `Business\SAIF.Business.Tasks\clsTaskCollection.vb` |

## Steps

1. **Caller invokes the shared purge function** with a data-portal info, a task source code, a task category code, and a keep-days value (passed as a string).
2. **Build the portal request.** The function creates a new portal request and data request, sets `RequestType = Scalar`, `CommandType = StoredProcedure`, and the SQL statement to `PK82036_Task.Task_Purge`.
3. **Bind parameters.** `intasksourcecode`, `intaskcategorycode`, and `inkeepdays` are bound as input parameters; `outdelrows` is bound as a string output parameter.
4. **Execute the procedure.** The request is processed through `inDataPortalInfo.ProcessPortalRequest`, which calls `PK82036_Task.Task_Purge` ([SQL-015](../sql/SQL-015-task-purge.md), [TASK](../database-tables.md#task)).
   - The procedure deletes rows only where `TASK_SOURCE_CODE`, `TASK_CATEGORY_CODE`, and `DELETE_FLAG = 'Y'` all match the requested slice ([BR-021](../business-rules.md#br-021-task-purge-is-limited-to-deleted-rows-in-the-requested-source-and-category-slice)).
   - Within that slice, only rows where `TRUNC(update_date) < TRUNC(SYSDATE - TO_NUMBER(inkeepdays))` are removed, so rows soft-deleted more recently than the keep-days threshold survive even though they match the source/category slice ([BR-022](../business-rules.md#br-022-task-purge-retention-is-enforced-by-whole-day-age)).
5. **Return the deleted-row count.** The function reads `outdelrows`, converts it to an integer, and returns it to the caller as the number of rows physically removed.

## Process flow

```mermaid
flowchart TD
	Start([Caller invokes PurgeTasks<br>with source, category, keep-days]) --> Build[Build scalar stored-procedure<br>request: Task_Purge]
	Build --> Exec[Execute PK82036_Task.Task_Purge]
	Exec --> Filter[Oracle filters rows:<br>matching source AND category<br>AND DELETE_FLAG = 'Y']
	Filter --> Age{update_date older than<br>keep-days threshold?}
	Age -->|Yes| Delete[Physically delete row]
	Age -->|No| Keep([Row retained])
	Delete --> Count[Accumulate deleted-row count]
	Count --> Return([Return outdelrows to caller])
```

## Failure and edge-case behavior

- Purge only ever affects rows already marked `DELETE_FLAG = 'Y'` by the [task record lifecycle](task-record-lifecycle.md)'s soft-delete step; an active row can never be physically removed by this operation regardless of age.
- The retention comparison truncates both sides to whole days (`TRUNC(update_date)` vs. `TRUNC(SYSDATE - keepdays)`), so a row soft-deleted earlier the same calendar day as the threshold boundary is not purged until the next day rolls over.
- `inKeepDays` is accepted and bound as a string rather than a numeric type; a non-numeric value would fail inside the Oracle `TO_NUMBER` conversion rather than being validated by this class before the call.*
- This function does not go through the standard `Save()`/business-rule pipeline used by the rest of the lifecycle, so none of the field-level validation rules (category, source, priority, mail ID) apply to a purge request.

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

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

## Sources
- `Business\SAIF.Business.Tasks\clsTaskCollection.vb`
