# ConvertPurchaseRequisitionToPurchaseOrder

## Permission Scope

purchaseRequisition

## Overview

ConvertPurchaseRequisitionToPurchaseOrder transforms an approved purchase requisition into a new purchase order in `DRAFT` status. Each generated purchase order line is linked to its source requisition line through a `PurchaseRequisitionLineAllocation` record, preserving end-to-end traceability. The requisition transitions to `CONVERTED` status after successful conversion.

## Business Rules

- Target purchase requisition must exist
- Only requisitions with `status` = `APPROVED` can be converted
- A requisition that has already been converted cannot be converted again
- A supplier must be specified: either from the requisition's suggested supplier or provided at conversion time
- The supplier must exist, be active, and carry the `SUPPLIER` role
- If the suggested supplier has become inactive since approval, conversion fails
- Generated PO line quantities must match their source requisition line quantities
- Generated PO line items must match their source requisition line items
- Supplier pricing rules are resolved and applied as default unit prices on generated PO lines when available
- A receiving site may be specified at conversion time as the default delivery destination for the generated purchase order; when provided it must reference a valid site
- A payment term must be specified at conversion time
- The generated purchase order must be associated with the same company as the source requisition
- After successful conversion the requisition status transitions to `CONVERTED`
- Conversion must not modify the source requisition's line data

## Process Flow

```mermaid
flowchart TD
    A[Receive convert request] --> B{Purchase requisition exists?}
    B -->|No| C[Return PURCHASE_REQUISITION_NOT_FOUND]
    B -->|Yes| D{Status is APPROVED?}
    D -->|No| E[Return PURCHASE_REQUISITION_NOT_APPROVED]
    D -->|Yes| F{Already converted?}
    F -->|Yes| G[Return PURCHASE_REQUISITION_ALREADY_CONVERTED]
    F -->|No| H{Supplier resolved?}
    H -->|No| I[Return SUPPLIER_REQUIRED]
    H -->|Yes| J{Supplier active and valid?}
    J -->|No| K[Return supplier error]
    J -->|Yes| L{Payment term exists and active?}
    L -->|No| L2[Return payment term error]
    L -->|Yes| L3[Resolve supplier pricing and snapshot payment term]
    L3 --> M[Generate PO lines from PR lines and record allocations]
    M --> N["Create Purchase Order in DRAFT"]
    N --> O["Set requisition status to CONVERTED"]
    O --> P[Return converted requisition and created PO]
```

## External Dependencies

- [business-partner::GetPartner](../../../business-partner/docs/queries/GetPartner.md) - Validate supplier identity, status, and supplier role
- [purchase::createPurchaseOrder](./CreatePurchaseOrder.md) - Create the draft purchase order from converted lines
- [purchase::CalculatePurchasePrice](../queries/CalculatePurchasePrice.md) - Resolve supplier pricing rules for default PO line prices
- [purchase::GetSupplierProfile](../queries/GetSupplierProfile.md) - Retrieve supplier profile for reference (payment term is provided by caller)

## Error Scenarios

- **PURCHASE_REQUISITION_NOT_FOUND**: Referenced purchase requisition does not exist
- **PURCHASE_REQUISITION_NOT_APPROVED**: Purchase requisition is not in `APPROVED` status
- **PURCHASE_REQUISITION_ALREADY_CONVERTED**: Purchase requisition has already been converted
- **SUPPLIER_REQUIRED**: No supplier was specified and the requisition has no suggested supplier
- **SUPPLIER_NOT_FOUND**: Referenced supplier partner does not exist
- **SUPPLIER_NOT_ACTIVE**: Referenced supplier is not in ACTIVE status
- **PARTNER_NOT_SUPPLIER**: Referenced partner does not carry the SUPPLIER role
- **RECEIVING_SITE_NOT_FOUND**: Referenced receiving site does not exist
- **PAYMENT_TERM_NOT_FOUND**: Referenced purchase payment term does not exist
- **PAYMENT_TERM_INACTIVE**: Referenced purchase payment term is inactive

## Test Cases

- converts an approved requisition into a draft purchase order
- sets requisition status to CONVERTED after successful conversion
- uses suggested supplier from requisition when available
- requires supplier to be specified when no suggested supplier exists
- records line allocation in PurchaseRequisitionLineAllocation table
- preserves requisition line quantities on generated PO lines
- preserves requisition line items on generated PO lines
- resolves supplier pricing rules as default unit prices on PO lines
- uses specified payment term on generated PO
- associates generated PO with the same company as the source requisition
- does not modify source requisition line data
- returns error when purchase requisition does not exist
- returns error when purchase requisition is not approved
- returns error when purchase requisition is already converted
- returns error when no supplier is specified and no suggested supplier exists
- returns error when supplier does not exist
- returns error when supplier is inactive
- returns error when supplier is not classified as a supplier
- falls back to first line suggestedSupplierId when no input supplierId is provided
- converts requisition line without price rule using estimatedUnitPrice
- snapshots item name and SKU onto PO lines
- returns error when specified receiving site does not exist
- returns error when specified payment term does not exist
- returns error when specified payment term is inactive
