Back to ER Diagram
RFQ & Quotation

RFQ Workflow & Quotation Evaluation

Complete documentation of the Request for Quotation process including vendor invitation, quotation collection, technical/commercial evaluation, comparison matrix, and vendor selection for Purchase Order creation.

PostgreSQL
27 Tables
Schema: procurement
Scoring System

RFQ Process Overview

A Request for Quotation (RFQ) is sent to multiple vendors to solicit competitive bids for required items. The process ensures fair evaluation and selection of the best vendor based on price, quality, and delivery capabilities.

Approved PR
Create RFQ
Invite Vendors
PUBLISHED
Collect Quotations
CLOSED
Technical Evaluation
Commercial Evaluation
Compare & Select
Create PO
3
RFQ Types
5
Vendor Response States
5
Quotation Statuses
2
Scoring Dimensions

RFQ Types

STANDARD

Regular RFQ with open bidding. All invited vendors can submit quotes until deadline. Quotes visible for comparison after closing.

EMERGENCY

Expedited RFQ for urgent requirements. Shorter deadline, fewer vendors invited. May skip some evaluation steps.

REVERSE_AUCTION

Real-time competitive bidding where vendors can see lowest bid and submit lower offers. Continues until auction end time.

Sealed Bid Option

When is_sealed_bid = true, quotations are hidden until deadline passes. Ensures fair competition without influence.

Database Schema

procurement.rfqs

  • id, rfq_number - Primary key and unique reference
  • pr_id - Legacy single-PR link (see rfq_purchase_requests for multi-PR)
  • company_id, department_id, buyer_id
  • rfq_date, submission_deadline
  • validity_period - Days quotation must remain valid
  • rfq_type - STANDARD, EMERGENCY, REVERSE_AUCTION
  • title, description, terms_conditions
  • delivery_location_id, required_delivery_date
  • allow_partial_quotes, require_item_wise_quote
  • is_sealed_bid - Hide quotes until deadline
  • status - DRAFT, PUBLISHED, CLOSED, CANCELLED

procurement.rfq_items

  • rfq_id, line_number
  • pr_item_id - Source PR item reference
  • item_id, item_code, item_description
  • specifications - Detailed technical specs
  • quantity, uom_id
  • target_unit_price - Budget reference
  • required_date

procurement.rfq_vendors

  • rfq_id, vendor_id
  • invited_at, invited_by
  • invitation_sent, invitation_sent_at
  • invitation_email
  • response_status - PENDING, VIEWED, QUOTED, DECLINED, NO_RESPONSE
  • responded_at, decline_reason
  • access_token, token_expires_at - Portal access

procurement.rfq_purchase_requests Junction Table

Enables multiple PRs to be consolidated into a single RFQ for demand aggregation and volume pricing.

  • id - Primary key
  • rfq_id - FK to rfqs (many RFQ items from multiple PRs)
  • pr_id - FK to purchase_requests (source PR)
  • added_by - User who linked the PR to RFQ
  • added_at - Timestamp
  • remarks - Notes on consolidation reason

procurement.quotations

  • quotation_number, rfq_id, vendor_id
  • quotation_date, validity_date
  • vendor_reference - Vendor's quote number
  • payment_terms_id, delivery_terms_id, delivery_days
  • subtotal, discount_*, tax_amount, total_amount
  • technical_score, commercial_score, overall_score
  • is_technically_qualified, is_commercially_qualified
  • is_selected, selected_at, selection_reason
  • status - RECEIVED, UNDER_EVALUATION, SHORTLISTED, SELECTED, REJECTED

procurement.quotation_comparisons

  • rfq_id - Reference to RFQ
  • comparison_date, prepared_by
  • recommended_quotation_id
  • recommendation_reason
  • comparison_criteria - JSONB with evaluation weights
  • comparison_matrix - JSONB with detailed comparison
  • approved_by, approved_at
  • status - DRAFT, SUBMITTED, APPROVED

procurement.bid_negotiations Offline Negotiation

Tracks multi-round offline negotiation cycles with counter-offers, meeting details, and revised terms.

  • bid_id - FK to vendor_bids
  • round_number - Sequential round (1, 2, 3...)
  • negotiation_mode - ONLINE, OFFLINE_MEETING, EMAIL, PHONE
  • counter_amount - Vendor's counter-offer amount
  • negotiated_amount - Agreed amount for this round
  • revised_payment_terms, revised_delivery_terms, revised_warranty_terms
  • meeting_date, meeting_location, meeting_notes
  • vendor_response, vendor_response_date
  • status - INITIATED, COUNTER_OFFERED, ACCEPTED, REJECTED, ESCALATED
  • approved_by, approved_at

procurement.negotiation_items

Line-item level negotiation — price, quantity, and delivery per item per round.

  • negotiation_id - FK to bid_negotiations
  • rfq_item_id - FK to rfq_items
  • original_unit_price, negotiated_unit_price
  • original_quantity, negotiated_quantity
  • original_delivery_days, negotiated_delivery_days
  • remarks

procurement.negotiation_attachments

Documents exchanged during negotiation — meeting minutes, revised quotes, vendor letters.

  • negotiation_id - FK to bid_negotiations
  • document_type - MOM, REVISED_QUOTE, VENDOR_LETTER, COUNTER_OFFER, APPROVAL_NOTE
  • file_name, file_path, file_size
  • uploaded_by, uploaded_at

procurement.negotiation_approvals

Approval workflow for negotiated terms before PO creation.

  • negotiation_id - FK to bid_negotiations
  • approval_level - 1, 2, 3 (multi-level)
  • approver_id - FK to users
  • status - PENDING, APPROVED, REJECTED, RETURNED
  • remarks, approved_at

rfq.rfq_approvals

RFQ approval workflow tracking multi-level authorization before publishing.

  • id - Primary key
  • rfq_id - FK to rfqs
  • approval_level - Sequential level (1, 2, 3...)
  • approver_id - FK to users
  • status - PENDING, APPROVED, REJECTED, RETURNED
  • remarks - Approver comments
  • approved_at - Timestamp of action
  • created_at, updated_at

rfq.rfq_types

Configuration table for RFQ type definitions such as open, limited, and single-source procurement.

  • id - Primary key
  • type_code - Unique code (OPEN, LIMITED, SINGLE_SOURCE)
  • type_name - Display name
  • description - Detailed description of the type
  • min_vendors - Minimum vendors required
  • max_vendors - Maximum vendors allowed (NULL for unlimited)
  • requires_justification - Whether single-source justification is needed
  • is_active - Soft enable/disable flag
  • created_at, updated_at

rfq.bid_types

Bid type definitions controlling how vendor bids are submitted and opened (sealed, two-envelope, etc.).

  • id - Primary key
  • type_code - Unique code (SEALED, TWO_ENVELOPE, OPEN, ELECTRONIC)
  • type_name - Display name
  • description - Explanation of bid handling rules
  • requires_technical_envelope - Whether technical bid is separate
  • requires_commercial_envelope - Whether commercial bid is separate
  • auto_open - Whether bids open automatically at deadline
  • is_active - Soft enable/disable flag
  • created_at, updated_at

rfq.rfq_attachments

File attachments on RFQs including specifications, drawings, terms documents, and scope of work.

  • id - Primary key
  • rfq_id - FK to rfqs
  • document_type - SPECIFICATION, DRAWING, TERMS, SCOPE_OF_WORK, OTHER
  • file_name - Original file name
  • file_path - Storage path or URL
  • file_size - Size in bytes
  • mime_type - MIME content type
  • uploaded_by - FK to users
  • uploaded_at - Timestamp

rfq.rfq_purchase_requests Junction Table

Junction table linking RFQs to Purchase Requests for multi-PR consolidation into a single RFQ.

  • id - Primary key
  • rfq_id - FK to rfqs
  • pr_id - FK to purchase_requests
  • added_by - User who linked the PR
  • added_at - Timestamp
  • remarks - Notes on consolidation reason

rfq.vendor_bid_attachments

Supporting documents submitted by vendors alongside their bids, such as catalogs, certificates, and technical datasheets.

  • id - Primary key
  • bid_id - FK to vendor_bids
  • vendor_id - FK to vendors
  • document_type - CATALOG, CERTIFICATE, DATASHEET, SAMPLE_REPORT, OTHER
  • file_name - Original file name
  • file_path - Storage path or URL
  • file_size - Size in bytes
  • uploaded_by - FK to users
  • uploaded_at - Timestamp

rfq.auction_vendors

Vendors participating in reverse auctions, tracking their registration, status, and real-time bidding activity.

  • id - Primary key
  • auction_id - FK to reverse auction RFQ
  • vendor_id - FK to vendors
  • registration_date - When vendor registered for auction
  • status - REGISTERED, ACTIVE, DISQUALIFIED, WITHDRAWN
  • last_bid_amount - Most recent bid submitted
  • last_bid_at - Timestamp of last bid
  • total_bids - Count of bids placed
  • is_winner - Whether vendor won the auction

rfq.bid_scoring_templates

Reusable scoring template definitions that define evaluation frameworks for bid assessment.

  • id - Primary key
  • template_name - Descriptive name
  • description - Template purpose and usage notes
  • category - TECHNICAL, COMMERCIAL, COMBINED
  • total_weight - Sum of all criteria weights (should equal 100)
  • is_default - Whether this is the default template
  • is_active - Soft enable/disable flag
  • created_by - FK to users
  • created_at, updated_at

rfq.bid_scoring_criteria

Individual scoring criteria within a scoring template, defining what is evaluated and how it is weighted.

  • id - Primary key
  • template_id - FK to bid_scoring_templates
  • criteria_name - Name of the criterion
  • description - What this criterion evaluates
  • weight - Percentage weight (e.g., 25 for 25%)
  • max_score - Maximum achievable score
  • scoring_type - NUMERIC, PASS_FAIL, RATING_SCALE
  • sort_order - Display ordering
  • is_mandatory - Whether criterion must be scored

rfq.bid_shortlists

Shortlisted vendors after initial evaluation, tracking which bids advance to detailed assessment or negotiation.

  • id - Primary key
  • rfq_id - FK to rfqs
  • bid_id - FK to vendor_bids
  • vendor_id - FK to vendors
  • shortlisted_by - FK to users
  • shortlisted_at - Timestamp
  • technical_score - Score at time of shortlisting
  • commercial_score - Score at time of shortlisting
  • ranking - Rank among shortlisted vendors
  • remarks - Justification for shortlisting

rfq.bid_clarifications

Bid clarification Q&A between buyers and vendors during evaluation to resolve ambiguities in submissions.

  • id - Primary key
  • rfq_id - FK to rfqs
  • bid_id - FK to vendor_bids
  • vendor_id - FK to vendors
  • question - Clarification question text
  • asked_by - FK to users (buyer)
  • asked_at - Timestamp of question
  • response - Vendor's clarification response
  • responded_at - Timestamp of response
  • status - PENDING, ANSWERED, CLOSED

rfq.auction_line_items

Individual line items within a reverse auction, tracking per-item bidding and current lowest offers.

  • id - Primary key
  • auction_id - FK to reverse auction RFQ
  • rfq_item_id - FK to rfq_items
  • item_description - Item description for auction display
  • quantity, uom_id - Required quantity and unit
  • start_price - Opening price / ceiling price
  • reserve_price - Minimum acceptable price (hidden)
  • current_lowest_bid - Real-time lowest bid amount
  • current_lowest_vendor_id - FK to vendors (current leader)
  • bid_decrement - Minimum bid reduction required

rfq.rate_contract_terms

Terms and conditions for rate contracts established through RFQ outcomes, defining pricing validity and volume commitments.

  • id - Primary key
  • rfq_id - FK to originating RFQ
  • vendor_id - FK to vendors
  • contract_number - Unique contract reference
  • effective_from, effective_to - Contract validity period
  • price_basis - FIXED, ESCALATION, INDEX_LINKED
  • min_order_quantity, max_order_quantity
  • committed_volume - Agreed volume commitment
  • penalty_terms - Penalty clauses (JSONB)
  • status - DRAFT, ACTIVE, EXPIRED, TERMINATED

rfq.negotiation_attachments

Documents exchanged during negotiation rounds including meeting minutes, revised quotes, and counter-offer letters.

  • id - Primary key
  • negotiation_id - FK to bid_negotiations
  • round_number - Negotiation round reference
  • document_type - MOM, REVISED_QUOTE, VENDOR_LETTER, COUNTER_OFFER, APPROVAL_NOTE
  • file_name, file_path, file_size
  • uploaded_by - FK to users
  • uploaded_at - Timestamp

rfq.negotiation_approvals

Approval workflow for negotiation outcomes, ensuring negotiated terms are authorized before proceeding to PO creation.

  • id - Primary key
  • negotiation_id - FK to bid_negotiations
  • approval_level - Sequential level (1, 2, 3...)
  • approver_id - FK to users
  • status - PENDING, APPROVED, REJECTED, RETURNED
  • remarks - Approver comments or conditions
  • approved_at - Timestamp of action
  • delegated_to - FK to users (if approval is delegated)

Vendor Invitation Flow

1

Select Vendors

Buyers select vendors to invite based on item categories, past performance, and qualification status. System can suggest vendors from approved vendor list.

2

Generate Access Tokens

Each invited vendor receives a unique access token for the vendor portal. Token has expiry aligned with submission deadline.

-- Generate secure access token for vendor
INSERT INTO procurement.rfq_vendors (
    rfq_id, vendor_id, invited_by,
    access_token, token_expires_at
) VALUES (
    :rfq_id,
    :vendor_id,
    :buyer_id,
    encode(gen_random_bytes(32), 'hex'),
    (
        SELECT submission_deadline + INTERVAL '1 day'
        FROM procurement.rfqs
        WHERE id = :rfq_id
    )
);
3

Send Invitations

Email notifications are sent with RFQ details and portal link. System tracks invitation delivery and vendor response.

4

Track Responses

As vendors view and respond to RFQ, their response_status is updated.

Response Status Description
PENDING Invitation sent, no vendor action yet
VIEWED Vendor accessed RFQ via portal
QUOTED Vendor submitted quotation
DECLINED Vendor declined to quote (with reason)
NO_RESPONSE No response by deadline

Quotation Evaluation

Each quotation undergoes two-dimensional evaluation:

Technical Evaluation

Assesses technical capability and compliance:

  • Specification compliance
  • Quality certifications
  • Delivery capability
  • Past performance
  • Technical documentation

Result: technical_score (0-100) and is_technically_qualified

Commercial Evaluation

Assesses pricing and commercial terms:

  • Unit pricing competitiveness
  • Discount structure
  • Payment terms favorability
  • Delivery timeline
  • Warranty/support terms

Result: commercial_score (0-100) and is_commercially_qualified

Overall Score Calculation

overall_score = (technical_score * tech_weight) + (commercial_score * comm_weight)
Weights are configurable per RFQ based on procurement strategy. Typical split: 40% technical, 60% commercial.

Comparison Matrix

The quotation comparison creates a side-by-side analysis stored as JSONB for flexibility:

-- Example comparison_criteria JSON
{
  "technical_weight": 0.4,
  "commercial_weight": 0.6,
  "criteria": [
    { "name": "Unit Price", "weight": 0.30 },
    { "name": "Delivery Time", "weight": 0.20 },
    { "name": "Quality Score", "weight": 0.25 },
    { "name": "Payment Terms", "weight": 0.15 },
    { "name": "Warranty", "weight": 0.10 }
  ]
}

-- Example comparison_matrix JSON
{
  "items": [
    {
      "item_id": "uuid-1",
      "item_description": "Widget A",
      "vendors": [
        {
          "vendor_id": "vendor-uuid-1",
          "vendor_name": "Acme Corp",
          "unit_price": 45.00,
          "delivery_days": 14,
          "technical_score": 85,
          "commercial_score": 78,
          "overall_score": 80.8
        },
        {
          "vendor_id": "vendor-uuid-2",
          "vendor_name": "Global Supplies",
          "unit_price": 42.50,
          "delivery_days": 21,
          "technical_score": 90,
          "commercial_score": 82,
          "overall_score": 85.2
        }
      ]
    }
  ],
  "summary": {
    "lowest_total": "vendor-uuid-2",
    "fastest_delivery": "vendor-uuid-1",
    "highest_score": "vendor-uuid-2"
  }
}

Quotation Selection

1

Prepare Recommendation

Buyer prepares comparison with recommended quotation and justification. The recommendation considers overall score, price, delivery, and strategic factors.

2

Approval (if required)

For high-value RFQs, the selection may require approval from procurement manager or committee. The quotation_comparisons record tracks approval.

3

Mark Selection

Selected quotation is marked and linked for PO creation.

-- Mark quotation as selected
UPDATE procurement.quotations
SET
    is_selected = true,
    selected_at = CURRENT_TIMESTAMP,
    selected_by = :user_id,
    selection_reason = :reason,
    status = 'SELECTED'
WHERE id = :quotation_id;

-- Update other quotations as rejected
UPDATE procurement.quotations
SET status = 'REJECTED'
WHERE rfq_id = :rfq_id
  AND id != :quotation_id
  AND status = 'SHORTLISTED';
4

Create Purchase Order

PO is created from selected quotation, pulling vendor, pricing, terms, and line item details.

Traceability

The PO maintains quotation_id reference for complete audit trail from PR → RFQ → Quotation → PO.

Query Examples

RFQ Response Summary

SELECT
    r.rfq_number,
    r.title,
    r.submission_deadline,
    COUNT(rv.id) AS vendors_invited,
    SUM(CASE WHEN rv.response_status = 'QUOTED' THEN 1 ELSE 0 END) AS quotes_received,
    SUM(CASE WHEN rv.response_status = 'DECLINED' THEN 1 ELSE 0 END) AS declined,
    SUM(CASE WHEN rv.response_status = 'PENDING' THEN 1 ELSE 0 END) AS pending
FROM procurement.rfqs r
LEFT JOIN procurement.rfq_vendors rv ON r.id = rv.rfq_id
WHERE r.status = 'PUBLISHED'
GROUP BY r.id, r.rfq_number, r.title, r.submission_deadline;

Quotation Ranking by RFQ

SELECT
    r.rfq_number,
    v.vendor_name,
    q.quotation_number,
    q.total_amount,
    q.technical_score,
    q.commercial_score,
    q.overall_score,
    q.is_technically_qualified,
    q.is_commercially_qualified,
    RANK() OVER (
        PARTITION BY r.id
        ORDER BY q.overall_score DESC
    ) AS rank_by_score,
    RANK() OVER (
        PARTITION BY r.id
        ORDER BY q.total_amount ASC
    ) AS rank_by_price
FROM procurement.quotations q
JOIN procurement.rfqs r ON q.rfq_id = r.id
JOIN vendor.vendors v ON q.vendor_id = v.id
WHERE q.is_technically_qualified = true
  AND q.is_commercially_qualified = true
ORDER BY r.rfq_number, q.overall_score DESC;

Best Practices

Vendor Selection

Invite at least 3 qualified vendors for competitive bidding. Include mix of existing suppliers and new potential vendors.

Adequate Timeline

Allow sufficient time for vendors to prepare quality quotations. Complex RFQs need 2-3 weeks; simple items may need only 3-5 days.

Clear Specifications

Provide detailed specifications and evaluation criteria upfront. Ambiguous requirements lead to non-comparable quotations.