# Purchase Requisition Lifecycle

## Overview

Purchase Requisition Lifecycle governs how an internal request for goods or services is created, reviewed, approved, and ultimately converted into a purchase order. A `PurchaseRequisition` captures a requester's need before any supplier commitment exists, recording the requested items, estimated costs, desired delivery dates, and an optional suggested supplier. It is the upstream "pre-PO" step that ensures spending is justified and authorized before procurement begins.

The lifecycle uses a single `status` state machine: a requisition starts in draft, is submitted for approval, and can be approved, rejected back to draft for revision, cancelled, or closed. Supplier assignment is optional at this stage because the final sourcing decision may happen later during purchase order creation. Budget validation is not enforced within the purchase module; the requisition emits domain events that downstream accounting modules can subscribe to for budget checks. Separation of duties requires that the requester and the approver are different users.

## Business Purpose

- Allow departments to formally request goods or services before committing to a supplier
- Provide an auditable approval gate so that spending is authorized before procurement acts
- Capture estimated costs and justification early enough for budget holders to review
- Decouple the "what do we need" decision from the "which supplier" decision
- Enable requesters to suggest a supplier without mandating one, preserving sourcing flexibility
- Enforce separation of duties between the person requesting and the person approving
- Give rejected requisitions a clear path back to draft for revision and resubmission
- Serve as the source document that feeds downstream purchase order creation

## Process Flow

```mermaid
flowchart TD
    A[Create Purchase Requisition] --> B["status: DRAFT"]
    B --> C[Add lines, estimated prices, justification]
    C --> D{Submit?}
    D -->|No| C
    D -->|Yes| E["status: SUBMITTED"]
    E --> F{Recall?}
    F -->|Yes| B
    E --> G{Review decision}
    G -->|Reject| H["status: REJECTED → back to DRAFT"]
    H --> B
    G -->|Approve| I["status: APPROVED"]
    I --> J{Convert to PO?}
    J -->|Yes| K["status: CONVERTED"]
    B --> L["status: CANCELLED"]
    E --> L
    I --> M["status: CLOSED"]
```

## Scenario Patterns

- **Standard stock replenishment request**: A warehouse operative creates a requisition for replenishment items with estimated prices, submits it, and the procurement manager approves it for conversion into a purchase order
- **Rejected for revision**: An approver rejects a requisition because the justification is insufficient or the estimated cost is unreasonable, and the requisition returns to draft with the rejection reason preserved for the requester to address
- **Requester recall before approval**: A requester realizes they submitted the wrong quantity and recalls the submitted requisition back to draft before the approver has reviewed it
- **Service item request**: A requester creates a line referencing a service-type item (e.g., consulting hours, maintenance contract) with an appropriate unit of measure and estimated price
- **Suggested supplier override**: A requester suggests a preferred supplier on several lines, but procurement later creates the purchase order with a different supplier based on better terms
- **Multi-department consolidation**: Several requisitions from different departments for the same item category are approved independently, then consolidated into a single purchase order during conversion
- **Cancellation of obsolete request**: A requisition is cancelled while still in draft or submitted status because the underlying project or need has been withdrawn
- **Partial conversion**: Some lines of an approved requisition are converted into a purchase order immediately while remaining lines stay open for later sourcing
- **Close without conversion**: An approved requisition is closed without conversion because the need was fulfilled through existing stock or an alternative channel

## Test Cases

- Creating a purchase requisition with a valid requester, company, and at least one line should succeed
- A purchase requisition line must require a description, quantity greater than zero, and a non-negative estimated unit price
- Purchase requisitions are always created with `status` = `DRAFT`
- A `DRAFT` requisition can be revised freely, including adding, removing, and editing lines
- Submitting a purchase requisition without any lines should fail
- Submitting a purchase requisition should transition `status` from `DRAFT` to `SUBMITTED`
- A requester should be able to recall a `SUBMITTED` requisition back to `DRAFT` before it is approved or rejected
- The approver and the requester must be different users; self-approval should be rejected
- Approving a requisition should transition `status` to `APPROVED`
- Rejecting a requisition should record the rejection reason and return `status` to `DRAFT`
- A requisition line must reference an item and a unit of measure
- A requisition line may omit the suggested supplier; supplier assignment is optional
- Cancelling a requisition should only be allowed when `status` is `DRAFT` or `SUBMITTED`
- Cancelling an `APPROVED` or `CONVERTED` requisition should fail
- Converting an approved requisition should transition `status` from `APPROVED` to `CONVERTED`
- Closing a requisition should only be allowed when `status` is `APPROVED` and no further conversion is expected
- Each requisition line should expose the requested quantity and estimated total amount
- Purchase requisition totals must be isolated per company
- Only authorized users with the appropriate role should be able to submit, approve, reject, or cancel requisitions

## Reference Links

- [Odoo Purchase documentation](https://www.odoo.com/documentation/19.0/applications/inventory_and_mrp/purchase.html)
- [Oracle Fusion Cloud Procurement guide](https://docs.oracle.com/en/cloud/saas/procurement/index.html)
- [SAP procurement overview](https://help.sap.com/docs/SAP_S4HANA_CLOUD)
