# Item Lifecycle

## Overview

PipelineItem is a generic work item that moves through stages on a pipeline. It has title, description, current stage reference, lifecycle (DRAFT/OPEN/CLOSED), assignee (userId), priority (LOW/MEDIUM/HIGH/URGENT), due date, and position (for ordering within a stage). Items belong to one pipeline. Domain modules extend items with their own fields by holding a foreign key to PipelineItem, and may run their own domain-specific approval workflows on the wrapping entity.

The item has an explicit `lifecycle` field orthogonal to the stage category. Lifecycle tracks the item's own readiness:

- **DRAFT** — item is being prepared by its creator; meant to be hidden from operational lists (kanban boards, external-facing queries) so that consumers see only intentionally published items. Equivalent to a saved-but-unpublished GitHub Issue draft. The module's queries return all lifecycles — the hiding itself is performed by consuming apps filtering on the `lifecycle` field.
- **OPEN** — item is published and being worked on. The default lifecycle for active items.
- **CLOSED** — item is explicitly closed and meant to be excluded from active work boards (again via consumer-side `lifecycle` filtering). Independent of the stage category; closing is an explicit action by the operator (or by a domain-specific wrapper command), never an automatic side effect of moving to a DONE-category stage.

PipelineStage category (NOT_STARTED/IN_PROGRESS/DONE/CANCELED) is a property of the PipelineStage the item is in, while item lifecycle reflects the item's own state. The two are independent: an item in a DONE-category stage can still be lifecycle=OPEN if the operator has not explicitly closed it.

## Business Purpose

- Provide a domain-agnostic work item that any pipeline can use
- Track assignment, priority, and position without domain-specific logic
- Enable visual workflow with drag-and-drop reordering within stages
- Maintain clear item lifecycle independent of stage configuration
- Support a draft state so creators can prepare items before publishing them to downstream consumers

## Process Flow

```mermaid
flowchart TD
    A[Create PipelineItem on Pipeline] --> B{Pipeline Active?}
    B -->|No| C[Reject — Pipeline Archived]
    B -->|Yes| D[Place in First PipelineStage, lifecycle=DRAFT or OPEN, position=last]
    D --> E[PipelineItem in DRAFT or OPEN]
    E --> F[Update Title/Description/Priority]
    E --> G[Assign to User]
    E --> H[Reorder within PipelineStage — update position]
    E --> I[Move to Next PipelineStage]
    E -->|Operator closes| J[closePipelineItem → lifecycle=CLOSED]
    E -->|Operator publishes draft| K[openPipelineItem: DRAFT → OPEN]
    E -->|Operator deletes| M[deletePipelineItem → hard delete with dependent rows]
    J -->|Operator reopens| L[reopenPipelineItem: CLOSED → OPEN]
```

## Scenario Patterns

- Create an item on a pipeline — it is placed in the first stage with lifecycle OPEN (or DRAFT if the caller requests a draft)
- Save an item as a draft, refine it over time, and explicitly publish it with `openPipelineItem` once it is ready to appear in operational lists
- Assign an item to a user so it appears on their personal task list
- Change priority from MEDIUM to HIGH when a deadline is approaching
- Reorder items within a stage by updating position (drag-and-drop)
- Move an item forward to the next stage as work progresses — moving does not change lifecycle on its own
- Operator explicitly closes an item with `closePipelineItem`, regardless of which stage it sits in
- Reopen a CLOSED item with `reopenPipelineItem` to bring it back to OPEN
- Permanently delete a mistakenly created item with `deletePipelineItem` — a hard delete that also removes the item's comments, label attachments, change history, and stage transitions; items that simply finished their work should be closed, not deleted, so their history survives

## Test Cases

- Creating item with title and pipeline succeeds, lifecycle is OPEN by default
- Creating item with `asDraft=true` succeeds and lifecycle is DRAFT
- PipelineItem is placed in the first stage (lowest position) by default
- PipelineItem position is set to the end of the target stage's item list
- Updating item title succeeds
- Assigning item to a valid user succeeds
- Creating item on an archived pipeline fails
- Reordering item within stage updates position correctly
- Moving item to DONE-category stage keeps lifecycle OPEN (no auto-close)
- Closing an OPEN item with closePipelineItem sets lifecycle to CLOSED
- Publishing a DRAFT item with openPipelineItem sets lifecycle to OPEN
- Reopening a CLOSED item with reopenPipelineItem sets lifecycle to OPEN
- CLOSED items cannot be moved to a new stage (must reopen first)
- Deleting an item removes it together with its dependent rows (comments, labels, history, transitions)

## Reference Links

- [Odoo Project Tasks](https://www.odoo.com/documentation/19.0/applications/services/project/tasks.html)
- [Linear Conceptual Model](https://linear.app/docs/conceptual-model)
- [GitHub Issue States (open / closed / draft)](https://docs.github.com/en/issues)
