Skip to content

Dashboard for Tender Management with Data Aggregation and Budget Calculation

Key Features:

  1. Tender Retrieval and Filtering: The code defines an endpoint that retrieves tender data from a database with various filters such as tenderStatus, organization_id, and user_id. The filtering also depends on the user’s role (e.g., procurement manager or procurement officer).

  2. Budget Calculation: It calculates the total budget for each tender by examining the activity_type (CQS, RFQ, DSSP) and retrieving the associated budget data from the database.

  3. Pagination: The code implements pagination by using page and limit query parameters, allowing users to retrieve a subset of the tender data at a time.

  4. User Role Filtering: The code filters tenders based on the user’s role and associated tender review responsibilities. It considers whether the user is a procurement manager or officer and applies the relevant filters for access.

  5. Tender Grouping and Sorting: Tenders are grouped by their unique_tender_id, sorted by creation date, and the most recent tender for each ID is selected.

  6. Progress Calculation: For tenders with specific activity types (CQS, RFQ, DSSP), the code calculates their progress and appends this information to the tender objects.

  7. Contracted vs Non-contracted Tender Separation: It distinguishes between contracted and non-contracted tenders and separately calculates the total count for each category.


Key Functionalities:

  1. Data Retrieval from MongoDB:

    • The code uses MongoDB aggregation to retrieve tenders, sorting and filtering them based on multiple parameters like status, user_id, and activity_type. This is implemented using the aggregate() method.

    • Example:

      top_five_tenders = list(tenders_collection.aggregate([
      {"$match": query},
      {"$sort": {"unique_tender_id": 1, "created_at": -1}},
      {"$group": {
      "_id": "$unique_tender_id",
      "latestTender": {"$first": "$$ROOT"}
      }},
      {"$replaceRoot": {"newRoot": "$latestTender"}},
      {"$project": {
      "status": 1,
      "evaluation_status": 1,
      "manager_status": 1,
      "bidder_evaluation": 1,
      "manager_status_phase_two": 1,
      "detailsEOI": 1,
      "serial_id": 1,
      "activity_type": 1,
      "estimated_price": 1,
      "title": 1
      }},
      {"$sort": {"serial_id": -1}},
      {"$skip": skip},
      {"$limit": 7}
      ]))
    • This code retrieves a set of tenders, grouping by unique_tender_id, sorting by serial_id, and limiting the results for pagination.

  2. Budget Calculation Logic:

    • CQS activity type: It queries an associated collection for the budget details of each tender.

    • RFQ and DSSP: For these activity types, it retrieves the estimated_price directly from the tender document.

    • Example:

      if tender.get('activity_type') == 'CQS':
      tender_document = tender_awards_collection_phase_two.find_one({
      "tender_id": str(tender['serial_id'])
      })
      if tender_document and 'details' in tender_document and 'currency_and_award_amount_(in_figures)' in tender_document['details']:
      budget = int(tender_document['details']['currency_and_award_amount_(in_figures)'])
  3. Role-Based Access: Based on the user’s role, different filters are applied to the tender query. Procurement officers have a more restrictive query, while procurement managers can access multiple review categories (e.g., reviewers_TOR, reviewers_EOI, etc.).

    • Example:
      if user_type == 'procurement_manager':
      query['$or'] = [
      {'reviewers_TOR': user_id},
      {'reviewers_EOI': user_id},
      {'reviewers_ITQ': user_id},
      {'reviewers_RFQ': user_id}
      ]
      elif user_type == 'procurement_officer':
      query['user_id'] = user_id
  4. Pagination Handling: The endpoint handles pagination by accepting page and limit as query parameters and calculating the number of results to skip.

    • Example:
      skip = max(0, (page - 1) * limit)
  5. Return Structure: The response returns a JSON object that includes:

    • List of contracted and non-contracted tenders.

    • Total budget for all tenders.

    • Budget details per tender, including title and serial ID.

    • Example:

      return jsonify({
      "contracted_tenders": contracted_tenders,
      "non_contracted_tenders": non_contracted_tenders,
      "budget_total": total_budget,
      "budget_details": budget_details,
      "status": True
      }), 200

Data Fetching and Step Handling:

  1. Data Fetching: The code fetches data from two main collections (tenders_collection and tender_awards_phase_two_collection) in MongoDB:

    • The first collection is queried for tender data, where filters based on user role and tender status are applied.
    • The second collection fetches additional tender award details (e.g., budgets) for calculation.
  2. Step Handling:

    • Step 1: Extract query parameters (page, limit, searchName, etc.).
    • Step 2: Determine the user role (user_type) and apply appropriate filters to the tenders query.
    • Step 3: Perform data aggregation to retrieve tenders and perform grouping, sorting, and pagination.
    • Step 4: Calculate the budget for each tender, based on the activity type (CQS, RFQ, DSSP), and accumulate the total.
    • Step 5: Return the results as a structured JSON response, including contracted and non-contracted tenders and the total budget.
  3. Flow of Information:

    • The process begins with fetching the query parameters (e.g., page, tenderStatus).
    • Based on these, data is fetched from MongoDB using aggregation pipelines.
    • Budget information is then calculated, depending on the tender’s activity type.
    • The final result is returned in a JSON format that includes the requested tender data and calculated budget details.

This implementation covers key features like role-based access control, pagination, data aggregation, and budget calculation, all central to tender management and display in the dashboard.