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.
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.
Regular RFQ with open bidding. All invited vendors can submit quotes until deadline. Quotes visible for comparison after closing.
Expedited RFQ for urgent requirements. Shorter deadline, fewer vendors invited. May skip some evaluation steps.
Real-time competitive bidding where vendors can see lowest bid and submit lower offers. Continues until auction end time.
When is_sealed_bid = true, quotations are hidden until deadline passes. Ensures fair competition without influence.
id, rfq_number - Primary key and unique referencepr_id - Legacy single-PR link (see rfq_purchase_requests for multi-PR)company_id, department_id, buyer_idrfq_date, submission_deadlinevalidity_period - Days quotation must remain validrfq_type - STANDARD, EMERGENCY, REVERSE_AUCTIONtitle, description, terms_conditionsdelivery_location_id, required_delivery_dateallow_partial_quotes, require_item_wise_quoteis_sealed_bid - Hide quotes until deadlinestatus - DRAFT, PUBLISHED, CLOSED, CANCELLEDrfq_id, line_numberpr_item_id - Source PR item referenceitem_id, item_code, item_descriptionspecifications - Detailed technical specsquantity, uom_idtarget_unit_price - Budget referencerequired_daterfq_id, vendor_idinvited_at, invited_byinvitation_sent, invitation_sent_atinvitation_emailresponse_status - PENDING, VIEWED, QUOTED, DECLINED, NO_RESPONSEresponded_at, decline_reasonaccess_token, token_expires_at - Portal accessEnables multiple PRs to be consolidated into a single RFQ for demand aggregation and volume pricing.
id - Primary keyrfq_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 RFQadded_at - Timestampremarks - Notes on consolidation reasonquotation_number, rfq_id, vendor_idquotation_date, validity_datevendor_reference - Vendor's quote numberpayment_terms_id, delivery_terms_id, delivery_dayssubtotal, discount_*, tax_amount, total_amounttechnical_score, commercial_score, overall_scoreis_technically_qualified, is_commercially_qualifiedis_selected, selected_at, selection_reasonstatus - RECEIVED, UNDER_EVALUATION, SHORTLISTED, SELECTED, REJECTEDrfq_id - Reference to RFQcomparison_date, prepared_byrecommended_quotation_idrecommendation_reasoncomparison_criteria - JSONB with evaluation weightscomparison_matrix - JSONB with detailed comparisonapproved_by, approved_atstatus - DRAFT, SUBMITTED, APPROVEDTracks multi-round offline negotiation cycles with counter-offers, meeting details, and revised terms.
bid_id - FK to vendor_bidsround_number - Sequential round (1, 2, 3...)negotiation_mode - ONLINE, OFFLINE_MEETING, EMAIL, PHONEcounter_amount - Vendor's counter-offer amountnegotiated_amount - Agreed amount for this roundrevised_payment_terms, revised_delivery_terms, revised_warranty_termsmeeting_date, meeting_location, meeting_notesvendor_response, vendor_response_datestatus - INITIATED, COUNTER_OFFERED, ACCEPTED, REJECTED, ESCALATEDapproved_by, approved_atLine-item level negotiation — price, quantity, and delivery per item per round.
negotiation_id - FK to bid_negotiationsrfq_item_id - FK to rfq_itemsoriginal_unit_price, negotiated_unit_priceoriginal_quantity, negotiated_quantityoriginal_delivery_days, negotiated_delivery_daysremarksDocuments exchanged during negotiation — meeting minutes, revised quotes, vendor letters.
negotiation_id - FK to bid_negotiationsdocument_type - MOM, REVISED_QUOTE, VENDOR_LETTER, COUNTER_OFFER, APPROVAL_NOTEfile_name, file_path, file_sizeuploaded_by, uploaded_atApproval workflow for negotiated terms before PO creation.
negotiation_id - FK to bid_negotiationsapproval_level - 1, 2, 3 (multi-level)approver_id - FK to usersstatus - PENDING, APPROVED, REJECTED, RETURNEDremarks, approved_atRFQ approval workflow tracking multi-level authorization before publishing.
id - Primary keyrfq_id - FK to rfqsapproval_level - Sequential level (1, 2, 3...)approver_id - FK to usersstatus - PENDING, APPROVED, REJECTED, RETURNEDremarks - Approver commentsapproved_at - Timestamp of actioncreated_at, updated_atConfiguration table for RFQ type definitions such as open, limited, and single-source procurement.
id - Primary keytype_code - Unique code (OPEN, LIMITED, SINGLE_SOURCE)type_name - Display namedescription - Detailed description of the typemin_vendors - Minimum vendors requiredmax_vendors - Maximum vendors allowed (NULL for unlimited)requires_justification - Whether single-source justification is neededis_active - Soft enable/disable flagcreated_at, updated_atBid type definitions controlling how vendor bids are submitted and opened (sealed, two-envelope, etc.).
id - Primary keytype_code - Unique code (SEALED, TWO_ENVELOPE, OPEN, ELECTRONIC)type_name - Display namedescription - Explanation of bid handling rulesrequires_technical_envelope - Whether technical bid is separaterequires_commercial_envelope - Whether commercial bid is separateauto_open - Whether bids open automatically at deadlineis_active - Soft enable/disable flagcreated_at, updated_atFile attachments on RFQs including specifications, drawings, terms documents, and scope of work.
id - Primary keyrfq_id - FK to rfqsdocument_type - SPECIFICATION, DRAWING, TERMS, SCOPE_OF_WORK, OTHERfile_name - Original file namefile_path - Storage path or URLfile_size - Size in bytesmime_type - MIME content typeuploaded_by - FK to usersuploaded_at - TimestampJunction table linking RFQs to Purchase Requests for multi-PR consolidation into a single RFQ.
id - Primary keyrfq_id - FK to rfqspr_id - FK to purchase_requestsadded_by - User who linked the PRadded_at - Timestampremarks - Notes on consolidation reasonSupporting documents submitted by vendors alongside their bids, such as catalogs, certificates, and technical datasheets.
id - Primary keybid_id - FK to vendor_bidsvendor_id - FK to vendorsdocument_type - CATALOG, CERTIFICATE, DATASHEET, SAMPLE_REPORT, OTHERfile_name - Original file namefile_path - Storage path or URLfile_size - Size in bytesuploaded_by - FK to usersuploaded_at - TimestampVendors participating in reverse auctions, tracking their registration, status, and real-time bidding activity.
id - Primary keyauction_id - FK to reverse auction RFQvendor_id - FK to vendorsregistration_date - When vendor registered for auctionstatus - REGISTERED, ACTIVE, DISQUALIFIED, WITHDRAWNlast_bid_amount - Most recent bid submittedlast_bid_at - Timestamp of last bidtotal_bids - Count of bids placedis_winner - Whether vendor won the auctionReusable scoring template definitions that define evaluation frameworks for bid assessment.
id - Primary keytemplate_name - Descriptive namedescription - Template purpose and usage notescategory - TECHNICAL, COMMERCIAL, COMBINEDtotal_weight - Sum of all criteria weights (should equal 100)is_default - Whether this is the default templateis_active - Soft enable/disable flagcreated_by - FK to userscreated_at, updated_atIndividual scoring criteria within a scoring template, defining what is evaluated and how it is weighted.
id - Primary keytemplate_id - FK to bid_scoring_templatescriteria_name - Name of the criteriondescription - What this criterion evaluatesweight - Percentage weight (e.g., 25 for 25%)max_score - Maximum achievable scorescoring_type - NUMERIC, PASS_FAIL, RATING_SCALEsort_order - Display orderingis_mandatory - Whether criterion must be scoredShortlisted vendors after initial evaluation, tracking which bids advance to detailed assessment or negotiation.
id - Primary keyrfq_id - FK to rfqsbid_id - FK to vendor_bidsvendor_id - FK to vendorsshortlisted_by - FK to usersshortlisted_at - Timestamptechnical_score - Score at time of shortlistingcommercial_score - Score at time of shortlistingranking - Rank among shortlisted vendorsremarks - Justification for shortlistingBid clarification Q&A between buyers and vendors during evaluation to resolve ambiguities in submissions.
id - Primary keyrfq_id - FK to rfqsbid_id - FK to vendor_bidsvendor_id - FK to vendorsquestion - Clarification question textasked_by - FK to users (buyer)asked_at - Timestamp of questionresponse - Vendor's clarification responseresponded_at - Timestamp of responsestatus - PENDING, ANSWERED, CLOSEDIndividual line items within a reverse auction, tracking per-item bidding and current lowest offers.
id - Primary keyauction_id - FK to reverse auction RFQrfq_item_id - FK to rfq_itemsitem_description - Item description for auction displayquantity, uom_id - Required quantity and unitstart_price - Opening price / ceiling pricereserve_price - Minimum acceptable price (hidden)current_lowest_bid - Real-time lowest bid amountcurrent_lowest_vendor_id - FK to vendors (current leader)bid_decrement - Minimum bid reduction requiredTerms and conditions for rate contracts established through RFQ outcomes, defining pricing validity and volume commitments.
id - Primary keyrfq_id - FK to originating RFQvendor_id - FK to vendorscontract_number - Unique contract referenceeffective_from, effective_to - Contract validity periodprice_basis - FIXED, ESCALATION, INDEX_LINKEDmin_order_quantity, max_order_quantitycommitted_volume - Agreed volume commitmentpenalty_terms - Penalty clauses (JSONB)status - DRAFT, ACTIVE, EXPIRED, TERMINATEDDocuments exchanged during negotiation rounds including meeting minutes, revised quotes, and counter-offer letters.
id - Primary keynegotiation_id - FK to bid_negotiationsround_number - Negotiation round referencedocument_type - MOM, REVISED_QUOTE, VENDOR_LETTER, COUNTER_OFFER, APPROVAL_NOTEfile_name, file_path, file_sizeuploaded_by - FK to usersuploaded_at - TimestampApproval workflow for negotiation outcomes, ensuring negotiated terms are authorized before proceeding to PO creation.
id - Primary keynegotiation_id - FK to bid_negotiationsapproval_level - Sequential level (1, 2, 3...)approver_id - FK to usersstatus - PENDING, APPROVED, REJECTED, RETURNEDremarks - Approver comments or conditionsapproved_at - Timestamp of actiondelegated_to - FK to users (if approval is delegated)Buyers select vendors to invite based on item categories, past performance, and qualification status. System can suggest vendors from approved vendor list.
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 ) );
Email notifications are sent with RFQ details and portal link. System tracks invitation delivery and vendor response.
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 |
Each quotation undergoes two-dimensional evaluation:
Assesses technical capability and compliance:
Result: technical_score (0-100) and is_technically_qualified
Assesses pricing and commercial terms:
Result: commercial_score (0-100) and is_commercially_qualified
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.
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" } }
Buyer prepares comparison with recommended quotation and justification. The recommendation considers overall score, price, delivery, and strategic factors.
For high-value RFQs, the selection may require approval from procurement manager or committee. The quotation_comparisons record tracks approval.
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';
PO is created from selected quotation, pulling vendor, pricing, terms, and line item details.
The PO maintains quotation_id reference for complete audit trail from PR → RFQ → Quotation → PO.
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;
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;
Invite at least 3 qualified vendors for competitive bidding. Include mix of existing suppliers and new potential vendors.
Allow sufficient time for vendors to prepare quality quotations. Complex RFQs need 2-3 weeks; simple items may need only 3-5 days.
Provide detailed specifications and evaluation criteria upfront. Ambiguous requirements lead to non-comparable quotations.