Tender Management API - Fetching Tenders by Organization with User-Specific Filters
1. Key Features:
- Pagination and Filtering: The API allows pagination (
page,limit) and filtering bysearchName,tenderStatus, andorganization_idto retrieve relevant tender data. - User-Specific Access Control: It incorporates user role-based filtering, allowing different roles (e.g.,
procurement_manager,procurement_officer, reviewers) to access tenders based on their permissions. - Sorting and Grouping: It fetches tenders sorted by
unique_tender_idandcreated_atin descending order, ensuring that the latest tenders are grouped and returned. - Reviewer Data Embedding: Embeds detailed information about reviewers for each tender, including their email and role.
- Process and Template Details: Each tender is enriched with details from related
process_idandtemplate_iddata. - Search Functionality: Supports searching by
template_data.nameand returns the filtered results.
2. Key Functionalities:
-
Data Fetching:
- The route uses query parameters (
page,limit,searchName,tenderStatus, etc.) to retrieve filtered tender data from MongoDB. - It performs aggregation queries to handle sorting, grouping, and pagination. The use of
aggregateallows for complex data transformations like sorting byunique_tender_idandcreated_at, grouping byunique_tender_id, and counting the total tenders after the filters are applied.
- The route uses query parameters (
-
User Role Filtering:
- The user’s role (
user_type) is retrieved based onuser_id. This determines how the query will filter the tenders, e.g., aprocurement_managercan access tenders they are reviewing, while aprocurement_officercan only access tenders they created. - The filtering logic involves conditions like checking if the user is a reviewer in various stages (
reviewers_TOR,reviewers_EOI, etc.) or if the user is the creator of the tender.
- The user’s role (
-
Pagination:
- The
skipparameter is used to calculate how many tenders to skip based on the page number and limit, ensuring that only a subset of tenders is returned in each request. - The
limitis set to 5 tenders per page, which is hardcoded but could be adjusted to suit the requirements.
- The
-
Reviewer Data Embedding:
- The code extracts all reviewer IDs for the fetched tenders, queries the
user_collectionto fetch reviewer details, and then embeds these details (e.g., email, role) into each tender. - This ensures that each tender has enriched reviewer information without needing additional database queries for each individual reviewer.
- The code extracts all reviewer IDs for the fetched tenders, queries the
-
Template and Process Details:
- The tender’s
process_idis used to fetch related process details (if available). Similarly, template IDs (template_id_tor,template_id_eoi) are resolved and embedded into the tender document for comprehensive data representation.
- The tender’s
-
Search Filtering:
- If a
searchNamequery parameter is provided, the tenders are filtered based on a case-insensitive regex match to thetemplate_data.name, ensuring that only tenders whose templates contain the search term are included in the response.
- If a
3. Data Fetching and Step Handling:
Data Fetching:
- MongoDB Aggregation Pipeline:
- The
aggregatepipeline in MongoDB is used to perform complex operations like sorting, grouping, and limiting the returned data. The key stages of the aggregation are:$match: Filters tenders based onquerycriteria (liketenderStatus,organization_id, etc.).$sort: Sorts the tenders first byunique_tender_id(ascending) and then bycreated_at(descending).$group: Groups the tenders byunique_tender_id, ensuring that only the latest tender per group is returned.$replaceRoot: Replaces the root document with thelatestTenderfrom the previous aggregation stage.$skipand$limit: Implement pagination by skipping a certain number of records and limiting the results to a maximum count.
- The
Step Handling:
-
Pagination: The
pageandlimitparameters allow for pagination, with theskipcalculated based on the current page and limit. This enables the API to return a subset of tenders at a time, which is crucial for efficient data retrieval in large datasets. -
User-Specific Filters: Based on the role of the user (if
user_idis provided), the query is adjusted to either show all tenders a user is involved with (e.g.,procurement_managerrole) or restrict tenders to those created by the user (e.g.,procurement_officerrole). -
Data Enrichment:
- Reviewer IDs: After retrieving the tenders, the code gathers all reviewer IDs across different stages and fetches their details from the
user_collectionin bulk, reducing the number of database queries. - Process and Template Information: For each tender, the
process_idand template IDs are resolved and added to the tender object to enrich the returned data.
- Reviewer IDs: After retrieving the tenders, the code gathers all reviewer IDs across different stages and fetches their details from the
Example Code for Reference:
# Example of data fetching and processing using MongoDB aggregationlatest_tenders = list(tenders_collection.aggregate([ {"$match": query}, # Step 1: Apply user-specific query filters {"$sort": {"unique_tender_id": 1, "created_at": -1}}, # Step 2: Sort by tender ID and creation date {"$group": {"_id": "$unique_tender_id", "latestTender": {"$first": "$$ROOT"}}}, # Step 3: Group by tender ID {"$replaceRoot": {"newRoot": "$latestTender"}}, # Step 4: Replace root with the latest tender {"$skip": skip}, # Step 5: Implement pagination {"$limit": limit} # Step 6: Limit results to the specified number]))This code fetches tenders by applying multiple filters (status, organization, etc.), enriches them with reviewer and process data, and supports pagination.