AppMatic Tech builds enterprise procurement SaaS platforms with template-enforced bid engines, append-only audit logs, row-level vendor access control, and WhatsApp Business API and email notifications, on React, Next.js, Laravel, and MySQL, as delivered for a pharmaceutical manufacturer's vendor management system. AppMatic Tech is based in Ahmedabad, India, with 330+ products shipped since 2017.
What makes enterprise procurement software hard to build?
Procurement software that works for a five-person team managing ten vendors is architecturally trivial. The same software managing procurement for a pharmaceutical manufacturer generating ₹1,000 crore in annual revenue, with dozens of vendor relationships, hundreds of bid rounds across five procurement categories, and an audit requirement covering every bid decision, requires a different set of design decisions at the data layer, the bid engine layer, and the notification layer.
AppMatic Tech built a vendor and enquiry management SaaS platform from scratch for exactly this use case. The system covers vendor onboarding, category-wise enquiry templates, bid submission, automated totaling, final vendor selection, WhatsApp Business API notifications to vendors, and a configurable stakeholder email loop. This article documents the architecture decisions behind each layer.
How should a procurement SaaS database be designed?
The data model is the foundation of a procurement system's correctness. Errors at the schema level, including ambiguous relationships, missing audit fields, and inconsistent state representations, produce bugs that are expensive to trace in production because they manifest as incorrect bid totals or missing approval records, not as application crashes.
Core Entity Relationships
A procurement system's schema revolves around five core entities:
Vendors: the companies that submit bids. Each vendor record holds company registration data, contact information, bank details (for purchase order processing), and approval status. Vendor status is a finite state machine: PENDING_REVIEW, APPROVED, SUSPENDED. Only approved vendors can receive enquiries.
Categories: the procurement categories that structure all enquiries. Examples: Raw Materials, Packaging, Active Pharmaceutical Ingredients, Solvents, Laboratory Supplies. Categories are managed by the admin and do not change frequently.
Enquiries: the events that initiate a procurement cycle. Each enquiry belongs to one category, has a defined bid window (open date, close date), and targets a subset of approved vendors in that category. Enquiry status: DRAFT, OPEN, BIDS_RECEIVED, UNDER_REVIEW, SELECTED, CLOSED.
Bid Items: the line items within a vendor's bid response. A vendor's bid for an enquiry consists of one or more line items matching the enquiry template's required fields (item name, unit, quantity, unit price, delivery timeline). Bid totals are computed from bid item line records, not stored as a standalone field; storing computed totals independently from line items creates a consistency risk if line items are ever amended.
Selections: the vendor selection records that close a procurement cycle. Each selection records: enquiry ID, selected vendor ID, selection timestamp, selecting user ID, and the winning bid total at the time of selection. Selections are immutable after creation; they form the audit trail.
Audit Log Table
Every state transition in the procurement system, including enquiry status changes, bid submissions, vendor approvals, and vendor selections, is written to a separate audit log table as an immutable append-only record:
audit_log (
id, event_type, entity_type, entity_id,
actor_user_id, actor_role, old_state, new_state,
event_timestamp, metadata (JSON)
)
The audit log is never updated or deleted. It answers the questions a procurement auditor will ask: "Who approved this vendor?" "When was this enquiry opened?" "Which user selected vendor X for the Q3 raw material purchase?"
Avoiding the Computed Total Trap
A common procurement system design mistake is storing a total_bid_value field on the vendor bid record and updating it whenever a line item changes. This creates a correctness problem: if a line item is amended after submission closes, the stored total may not match the sum of line items.
AppMatic Tech's bid engine computes totals on read using a SQL aggregation query over the bid item line records, not from a stored total. The comparison view, showing each vendor's total side by side, executes fresh aggregation queries on each view load during the review window. This approach is slightly more expensive computationally than reading a stored value, but it is always correct and eliminates an entire class of data consistency bugs.
How does a procurement bid engine work?
The bid engine is the component that enforces template-consistent bid submission, validates bid data, computes totals, and generates the comparison view.
Template-Enforced Bid Submission
An enquiry is created from a template that defines the required line items: item name, unit of measurement options, quantity, unit price, and optional notes. The vendor's bid submission form is generated from the template definition. This means the bid form structure is determined by the template, not by the vendor; every vendor responds to exactly the same fields in exactly the same structure.
This template enforcement is what makes automated comparison possible. Bids that arrive as free-form documents or emails require manual normalisation before comparison. Template-enforced bids require zero normalisation; the line items are already in the same structure.
Bid Validation
Before a bid submission is accepted, the bid engine validates:
- All required line item fields are populated
- Unit prices are numeric and positive
- Delivery timeline is within the enquiry's accepted range (if configured)
- The submission timestamp is within the enquiry's open window
Validation failures return specific field-level error messages to the vendor portal. The bid is not partially saved; it is either complete and valid, or rejected with error detail.
Comparison View Logic
The comparison view renders vendor bids side by side for the procurement manager's review. The view executes one aggregation query per vendor in the enquiry, returning each vendor's total bid value and line-item breakdown. The results are sorted by total bid value ascending to surface the lowest bid by default, with the ability to sort by other criteria (delivery timeline, specific line item prices).
The comparison view is read-only for all roles except the procurement manager role. The final selection action is restricted to the procurement manager role and triggers the selection record creation and the vendor notification workflow.
How should procurement notifications reach vendors and stakeholders?
The notification layer must deliver WhatsApp messages to vendors and email to internal stakeholders reliably, with an audit trail of delivery confirmations.
Event-Driven Notification Triggers
Notifications are triggered by domain events, not by direct calls from the application code. The bid engine and procurement workflow emit events (ENQUIRY_PUBLISHED, BID_RECEIVED, VENDOR_SELECTED) that are consumed by the notification service.
This event-driven model decouples the notification logic from the core application. The procurement manager who clicks "Publish Enquiry" does not wait for WhatsApp messages to be dispatched before the UI confirms the publish action. The event is published to a queue, and the notification service processes it asynchronously.
WhatsApp Business API Integration
The WhatsApp Business API (via Meta's official API) sends structured message templates to vendor phone numbers registered in the vendor record. WhatsApp message templates must be pre-approved by Meta before use; the template submission and approval process (typically 24–72 hours) must be completed before the system goes live.
Approved templates for a procurement system typically include:
- Enquiry notification: "A new enquiry [ENQUIRY_ID] for [CATEGORY] is open for your bids. Deadline: [DATE]. Log in at [URL]."
- Bid deadline reminder: "Reminder: The bid deadline for enquiry [ENQUIRY_ID] is in 24 hours."
- Selection notification: "Your bid for [ENQUIRY_ID] has been selected. The purchase order will follow."
- Rejection notification: "The procurement team has completed evaluation for [ENQUIRY_ID]. Thank you for your participation."
WhatsApp delivery confirmations (sent, delivered, read) are received via webhook and written to the notification audit log.
Stakeholder Email Loop
The email notification engine maintains a notification_rules table that defines the CC and BCC configuration for each notification event type per organisational unit. The procurement manager can configure: "All enquiry publications go to procurement@, finance@, and quality@ as CC." This configuration is stored and applied automatically rather than requiring manual CC selection on every notification.
AppMatic Tech uses SMTP with a transactional email service (SendGrid or equivalent) for reliable email delivery with bounce handling and delivery status callbacks.
Which access control model does procurement software need?
A multi-role procurement system requires fine-grained access control:
- Vendor role: Can see only their own submitted bids and active enquiries addressed to them. Cannot see other vendors' bids under any circumstances.
- Procurement manager role: Can create enquiries, view all submitted bids in comparison view, and execute the final vendor selection.
- Finance role: Read access to selection records and purchase order data. No bid management capability.
- Quality role: Read access to vendor compliance documents and selection records. No bid management capability.
- Admin role: Full system access including vendor approval, user management, and notification configuration.
Row-level access control on the bid items and vendor records ensures that a vendor's pricing data is never accessible to other vendors through API responses, even if the same endpoint is used for all vendors. Every query on bid data filters by the authenticated user's vendor ID.
How does AppMatic Tech build procurement platforms?
AppMatic Tech builds custom procurement, vendor management, and B2B SaaS platforms for enterprise clients. For a delivered example, see how AppMatic Tech built the Pharma vendor and enquiry management SaaS. For related architecture guidance, read how to choose a tech stack for an AI-native SaaS product and MCP server for CRM and ERP integration. Contact the team at contact@appmatictech.com to discuss the architecture requirements of a procurement or vendor management system.
Vendor notifications over WhatsApp, including templates, messaging limits, and the October 2026 pricing changes, are covered in WhatsApp Business API integration.
Frequently Asked Questions
- Should a procurement system store bid totals?
- No. A stored total drifts from the sum of its line items whenever a line item is amended. AppMatic Tech computes bid totals on read with a SQL aggregation over the bid item records, which costs slightly more compute than reading a stored value but is always correct and removes an entire class of consistency bugs.
- What prevents vendors from seeing competitors' bid prices?
- The API that serves the vendor portal filters every bid query by the authenticated vendor's ID. The comparison endpoint that shows all bids side by side is restricted to procurement manager and admin roles, and a vendor-role token receives HTTP 403 on any request to it.
- How are vendor banking details secured in a procurement platform?
- AppMatic Tech stores bank account details with AES-256 column-level encryption at rest, with the decryption key held in AWS Key Management Service rather than application configuration. Bank fields are returned only to admin and finance roles through a dedicated endpoint, never in general vendor profile queries.
- How does a procurement system handle tenders with multiple lots?
- AppMatic Tech implements multi-lot enquiries, where one enquiry contains several lots, each with its own template. Vendors can bid on all lots or a subset, and the comparison view shows per-lot breakdowns plus a total across lots, so the procurement team can select different vendors for different lots in the same enquiry.
- Do WhatsApp Business API messages need approval before launch?
- Yes. WhatsApp message templates must be pre-approved by Meta before use, so AppMatic Tech submits the procurement templates, such as new enquiry, deadline reminder, selection, and rejection notices, well before go-live. Delivery receipts for sent, delivered, and read states arrive by webhook and are written to the notification audit log.

