Complete documentation of the PR workflow from creation through approval to conversion into RFQs and Purchase Orders. Includes status transitions, approval routing, and item lifecycle management.
A Purchase Requisition (PR) is the formal internal document that initiates the procurement process. It flows through creation, approval, and conversion stages before goods are ultimately ordered.
| Status | Description | Allowed Actions | Next States |
|---|---|---|---|
| DRAFT | Initial state. PR is being prepared by requester. | Edit, Add Items, Delete, Submit | PENDING_APPROVAL |
| PENDING_APPROVAL | Submitted for approval. Waiting at current_approval_level. | Approve, Reject, Recall (by requester) | APPROVED, REJECTED, DRAFT (recall) |
| APPROVED | Fully approved. Ready for sourcing/ordering. | Create RFQ, Create PO, Cancel | CLOSED, CANCELLED |
| REJECTED | Rejected by an approver. Requires revision. | Revise & Resubmit, Cancel | DRAFT, CANCELLED |
| CANCELLED | Permanently cancelled. No further actions. | None (Terminal) | - |
| CLOSED | All items ordered. PR lifecycle complete. | View Only (Terminal) | - |
Regular purchase requisition for routine procurement needs. Follows standard approval workflow based on amount thresholds.
Time-sensitive requirement. May bypass certain approval levels or have expedited workflow. Requires justification.
Pre-approved requisition for recurring needs over a period. Items can be released against the blanket PR as needed.
For capital expenditure items (assets). Requires additional approval levels and may need budget committee sign-off.
id - UUID primary keypr_number - Unique PR number (auto-generated)company_id, department_id - Organizational contextrequester_id - User who created the PRcost_center_id, project_id - Budget allocationpr_date, required_date - Key datespriority - LOW, MEDIUM, HIGH, CRITICALpr_type - STANDARD, URGENT, BLANKET, CAPITALstatus - Current workflow statuscurrent_approval_level - Tracks approval progresstotal_amount - Sum of all line itemscustom_data - JSONB for extensibilitypr_id - Parent PR referenceline_number - Sequential line numberitem_id - Reference to inventory.items (optional)item_description - Free text descriptionquantity, uom_id - Quantity and unitestimated_unit_price - Budget estimatesuggested_vendor_id - Preferred vendor (optional)status - PENDING, IN_RFQ, ORDERED, CANCELLEDrfq_id, po_id - Conversion referencesgl_account_id, cost_center_id - Accountingpr_id - Parent PR referenceapproval_level - Level in approval chainapprover_id - Assigned approverdelegate_id - Delegated approver (if any)action - APPROVED, REJECTED, RETURNEDaction_date - When action was takencomments - Approver's notesstatus - PENDING, APPROVED, REJECTEDdue_date - SLA deadline for approvalreminded_at - Last reminder sentFile attachments associated with purchase requests, such as specifications, quotes, or supporting documents.
id - UUID primary keypr_id - Parent PR referencefile_name - Original uploaded file namefile_path - Storage path or URL to the filefile_type - MIME type (e.g., application/pdf, image/png)file_size - Size in bytesuploaded_by - User who uploaded the attachmentuploaded_at - Timestamp of uploaddescription - Optional description or label for the fileis_deleted - Soft-delete flag for attachment removalTracks revision history when a PR is modified after rejection or recalled for changes. Preserves an audit trail of all previous versions.
id - UUID primary keypr_id - Parent PR referencerevision_number - Sequential revision counterrevised_by - User who made the revisionrevised_at - Timestamp of revisionchange_summary - Description of what changedprevious_total_amount - Total amount before revisionnew_total_amount - Total amount after revisionprevious_status - PR status before revisionsnapshot_data - JSONB snapshot of the PR state before changesRecords budget availability check results performed during PR submission or approval. Ensures requested amounts fall within allocated budgets.
id - UUID primary keypr_id - Parent PR referencecost_center_id - Cost center checked againstbudget_period_id - Budget period referenceallocated_amount - Total budget allocated for the periodcommitted_amount - Amount already committed from prior PRsrequested_amount - Amount requested in this PRavailable_amount - Remaining budget after commitmentscheck_result - PASS, FAIL, WARNINGchecked_at - Timestamp of the budget checkchecked_by - User or system that performed the checkoverride_approved_by - Approver who authorized budget override (if any)Consolidation records for batching multiple approved PRs into a single sourcing event. Groups similar items across PRs to achieve volume discounts.
id - UUID primary keyconsolidation_number - Unique consolidation reference numbercompany_id - Company context for the consolidationcreated_by - Procurement officer who initiated consolidationcreated_at - Timestamp of consolidation creationstatus - DRAFT, CONFIRMED, CONVERTED, CANCELLEDpr_ids - Array of PR IDs included in this consolidationtotal_items - Count of consolidated line itemstotal_amount - Combined value of consolidated itemsrfq_id - Resulting RFQ created from consolidation (if any)notes - Consolidation notes or rationaleRecords short closure of partially fulfilled PRs. When remaining items are no longer needed, a short closure finalizes the PR without ordering the full quantity.
id - UUID primary keypr_id - Parent PR referencepr_item_id - Specific line item being short-closed (optional)original_quantity - Originally requested quantityordered_quantity - Quantity already orderedclosed_quantity - Remaining quantity being short-closedreason - Justification for short closureclosed_by - User who initiated the short closureclosed_at - Timestamp of short closureapproved_by - Approver who authorized the short closureapproved_at - Timestamp of short closure approvalstatus - PENDING, APPROVED, REJECTEDWhen a PR is submitted, the system determines the approval chain based on the approval matrix configuration. Factors include: total amount, department, cost center, and PR type.
-- On PR submission, determine approval levels UPDATE pr.purchase_requests SET status = 'PENDING_APPROVAL', submitted_at = CURRENT_TIMESTAMP, current_approval_level = 1 WHERE id = :pr_id;
For each required approval level, a pr_approvals record is created with the designated approver and SLA due date.
-- Create approval records for each level INSERT INTO pr.pr_approvals (pr_id, approval_level, approver_id, due_date, status) SELECT :pr_id, al.level_number, CASE al.approver_type WHEN 'DEPARTMENT_HEAD' THEN d.head_id WHEN 'COST_CENTER_OWNER' THEN cc.owner_id ELSE al.approver_id END, CURRENT_TIMESTAMP + (al.sla_hours || ' hours')::INTERVAL, 'PENDING' FROM approval.approval_levels al JOIN approval.approval_matrix am ON al.matrix_id = am.id WHERE am.document_type = 'PR' AND :total_amount BETWEEN am.min_amount AND am.max_amount;
Each approver reviews and takes action. When approved, current_approval_level increments. When all levels complete, PR status changes to APPROVED.
-- On approval action UPDATE pr.pr_approvals SET action = 'APPROVED', action_date = CURRENT_TIMESTAMP, status = 'APPROVED', comments = :comments WHERE pr_id = :pr_id AND approval_level = :current_level; -- Check if more levels exist UPDATE pr.purchase_requests SET current_approval_level = current_approval_level + 1, status = CASE WHEN current_approval_level >= :max_level THEN 'APPROVED' ELSE 'PENDING_APPROVAL' END, approved_at = CASE WHEN current_approval_level >= :max_level THEN CURRENT_TIMESTAMP ELSE NULL END WHERE id = :pr_id;
If any approver rejects, the entire PR is rejected. The rejection_reason is captured and the requester is notified to revise and resubmit.
A rejection at any level halts the workflow. The PR returns to REJECTED status and must be revised before resubmission. Previous approval records are preserved for audit.
Each PR line item has its own status to track progression through sourcing and ordering:
| Item Status | Description | Reference Updated |
|---|---|---|
| PENDING | Item approved but not yet sourced | - |
| IN_RFQ | Item included in an RFQ for quotations | rfq_id populated |
| ORDERED | Item converted to a Purchase Order | po_id populated |
| CANCELLED | Item cancelled (not needed) | - |
A PR automatically transitions to CLOSED status when all line items have status = ORDERED or CANCELLED. This is evaluated after each PO creation or item cancellation.
Selected PR items can be grouped into an RFQ for competitive bidding:
For known vendors or contract items, skip RFQ:
SELECT pr.pr_number, pr.total_amount, pr.pr_date, u.full_name AS requester, pa.approval_level, pa.due_date FROM pr.pr_approvals pa JOIN pr.purchase_requests pr ON pa.pr_id = pr.id JOIN admin.users u ON pr.requester_id = u.id WHERE pa.approver_id = :user_id AND pa.status = 'PENDING' AND pa.approval_level = pr.current_approval_level ORDER BY pa.due_date;
SELECT pr.pr_number, pi.line_number, pi.item_description, pi.quantity, uom.symbol, pi.estimated_total, v.vendor_name AS suggested_vendor FROM pr.pr_items pi JOIN pr.purchase_requests pr ON pi.pr_id = pr.id JOIN master.units_of_measure uom ON pi.uom_id = uom.id LEFT JOIN vendor.vendors v ON pi.suggested_vendor_id = v.id WHERE pr.status = 'APPROVED' AND pi.status = 'PENDING' ORDER BY pr.required_date;
SELECT pr.pr_number, pr.status AS pr_status, COUNT(*) AS total_items, SUM(CASE WHEN pi.status = 'PENDING' THEN 1 ELSE 0 END) AS pending, SUM(CASE WHEN pi.status = 'IN_RFQ' THEN 1 ELSE 0 END) AS in_rfq, SUM(CASE WHEN pi.status = 'ORDERED' THEN 1 ELSE 0 END) AS ordered, SUM(CASE WHEN pi.status = 'CANCELLED' THEN 1 ELSE 0 END) AS cancelled FROM pr.purchase_requests pr JOIN pr.pr_items pi ON pr.id = pi.pr_id WHERE pr.company_id = :company_id GROUP BY pr.id, pr.pr_number, pr.status;
Provide detailed item descriptions and specifications. Include required_date for urgency prioritization. Suggest vendors when known to speed sourcing.
Configure reasonable SLA hours per approval level. Enable escalation for overdue approvals. Send reminders before SLA breach.
Validate budget availability before PR submission. Track committed amounts from approved PRs against cost center budgets.