End-to-end procurement document lifecycle management, relationships, and status tracking from requisition to payment.
The Document Flow system manages the complete lifecycle of procurement documents from creation to archival. It tracks document relationships, maintains audit trails, enforces sequential dependencies, and ensures proper document numbering and versioning.
Internal request to procure items/services
Solicitation sent to vendors
Price/terms response from vendor
Official order to vendor
Receiving acknowledgment
Payment request from vendor
Adjustment documents
Long-term agreement
Purchase requisition header information
Request for quotation headers
Vendor quotation responses
Purchase order headers
Goods receipt note headers
Vendor invoice headers
Auto-increment sequences for document numbers
File attachments for any document
Complete audit trail for document changes
┌─────────────────────────────────────────────────────────────────────────────────┐
│ PROCUREMENT DOCUMENT FLOW │
└─────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ REQUISITION │ Internal need identified
│ (PR-2024-001) │
└────────┬─────────┘
│ Approved
▼
┌──────────────────┐ ┌──────────────────┐
│ RFQ │─────►│ RFQ VENDORS │ Sent to 3-5 vendors
│ (RFQ-2024-001) │ │ (Multiple Rows) │
└────────┬─────────┘ └──────────────────┘
│ Vendors respond
▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ QUOTATION 1 │ │ QUOTATION 2 │ │ QUOTATION 3 │
│ (QT-2024-001) │ │ (QT-2024-002) │ │ (QT-2024-003) │
└────────┬─────────┘ └──────────────────┘ └──────────────────┘
│ Selected
▼
┌──────────────────┐
│ PURCHASE ORDER │ Legal commitment
│ (PO-2024-001) │
└────────┬─────────┘
│ Goods shipped
├─────────────────────────────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ GRN 1 │ │ GRN 2 │ (Partial deliveries)
│ (GRN-2024-001) │ │ (GRN-2024-002) │
└────────┬─────────┘ └────────┬─────────┘
│ │
└─────────────┬───────────────────┘
▼
┌──────────────────┐
│ VENDOR INVOICE │ Payment request
│ (INV-2024-001) │
└────────┬─────────┘
│ Three-way match
▼
┌──────────────────┐
│ PAYMENT │ Funds released
│ (PAY-2024-001) │
└──────────────────┘
One PR can generate multiple RFQs for different categories
rfqs.pr_id → purchase_requisitions.id
One RFQ receives multiple quotations from vendors
quotations.rfq_id → rfqs.id
Selected quotation becomes PO basis
purchase_orders.quotation_id → quotations.id
One PO can have multiple GRNs for partial deliveries
grns.po_id → purchase_orders.id
One PO can have multiple invoices
vendor_invoices.po_id → purchase_orders.id
Framework contract can have multiple release POs
purchase_orders.contract_id → contracts.id
| Document | Format Pattern | Example | Resets |
|---|---|---|---|
| Purchase Requisition | PR-{YYYY}-{NNNNN} |
PR-2024-00142 | Annually |
| RFQ | RFQ-{YYYY}-{NNNNN} |
RFQ-2024-00089 | Annually |
| Quotation | QT-{YYYY}-{NNNNN} |
QT-2024-00312 | Annually |
| Purchase Order | PO-{YYYY}-{NNNNN} |
PO-2024-00067 | Annually |
| GRN | GRN-{YYYY}{MM}-{NNNN} |
GRN-202403-0024 | Monthly |
| Invoice | INV-{VENDOR}-{NNNNN} |
INV-ABC-00156 | Never |
| Contract | CON-{YYYY}-{NNN} |
CON-2024-012 | Annually |
public class DocumentNumberService { public async Task<string> GenerateDocumentNumber( DocumentType docType, Dictionary<string, string> parameters = null) { // Use transaction to ensure unique numbers await using var transaction = await _sequenceRepo.BeginTransactionAsync(); try { // Get or create sequence for this document type var sequence = await _sequenceRepo.GetSequenceAsync( docType, DateTime.UtcNow.Year); // Increment and save sequence.CurrentValue++; await _sequenceRepo.UpdateAsync(sequence); await transaction.CommitAsync(); // Format the number return FormatDocumentNumber(sequence, parameters); } catch { await transaction.RollbackAsync(); throw; } } }
public class DocumentValidationService { public async Task<ValidationResult> ValidateDocumentCreation( DocumentType docType, Guid? parentDocId) { var errors = new List<string>(); switch (docType) { case DocumentType.RFQ: // RFQ requires approved PR var pr = await _prRepo.GetByIdAsync(parentDocId.Value); if (pr.Status != PrStatus.Approved) errors.Add("PR must be approved before creating RFQ"); break; case DocumentType.PurchaseOrder: // PO requires selected quotation within validity var quote = await _quoteRepo.GetByIdAsync(parentDocId.Value); if (!quote.IsSelected) errors.Add("Quotation must be selected"); if (quote.ValidityDate < DateTime.UtcNow) errors.Add("Quotation has expired"); break; case DocumentType.GRN: // GRN requires PO sent to vendor var po = await _poRepo.GetByIdAsync(parentDocId.Value); if (po.Status < PoStatus.SentToVendor) errors.Add("PO must be sent to vendor"); break; } return new ValidationResult { IsValid = errors.Count == 0, Errors = errors }; } }
| Event Type | Description | Data Captured |
|---|---|---|
| CREATE | Document created | Full document snapshot |
| UPDATE | Document modified | Old values, new values, changed fields |
| STATUS_CHANGE | Status transition | From status, to status, trigger action |
| APPROVAL | Approval action taken | Approver, action, comments |
| REVISION | New revision created | Revision number, reason, changes |
| ATTACHMENT | File attached/removed | File details, action type |
ProKure Database Documentation - Document Flow Logic v1.0
Part of the ProKure Procurement Management System