Tender Management API with Data Insertion, Update, and Review Handling
Key Features:
-
Tender Creation Endpoint (
/createNew):- Accepts POST requests to create new tenders.
- Automatically assigns system-generated fields (e.g.,
created_at,serial_id, andid). - Stores tender information in a MongoDB database.
- Returns a success message along with the
tender_idandserial_id.
-
Tender Update Endpoint (
/update-tender-by-serial-id):- Accepts PUT requests to update an existing tender by its
serial_id. - Updates specific fields in the tender, ensuring missing fields are filled with defaults or existing values.
- Provides validation for input data, such as checking if
serial_idexists and if nested fields likedetailsEOIanddetailsTORare valid objects. - Manages reviewer data and sends notifications (though the actual email-sending is commented out).
- Returns the status of the update operation.
- Accepts PUT requests to update an existing tender by its
-
MongoDB Integration:
- Both endpoints interact with MongoDB to insert new documents or update existing ones using the
serial_idas the unique identifier.
- Both endpoints interact with MongoDB to insert new documents or update existing ones using the
-
Error Handling and Logging:
- Detailed error handling is implemented, including logging for debugging, checks for missing fields, and handling unexpected errors during execution.
-
Custom Validation:
- The code checks the structure of incoming data to ensure that necessary fields are present and appropriately formatted (e.g.,
submission_deadlineas a date, nested objects as dictionaries).
- The code checks the structure of incoming data to ensure that necessary fields are present and appropriately formatted (e.g.,
Key Functionalities:
-
Tender Creation (
create_tender_new):- Data Processing: The incoming request data is copied, auto-generated fields (like
created_atandserial_id) are added, and then it is inserted into the MongoDB collection. - Unique ID Assignment: The
uuid.uuid4().hexensures that each tender gets a unique ID. - Response: On successful insertion, the system returns the tender’s ID and serial ID in a JSON response.
tender_data = request.json.copy()tender_data['created_at'] = datetime.now(timezone.utc)tender_data['serial_id'] = get_next_serial_id()tender_data['id'] = uuid.uuid4().hexresult = tender_collection.insert_one(tender_data)return jsonify({"message": "Tender created successfully","tender_id": str(result.inserted_id),"serial_id": tender_data['serial_id']}), 201 - Data Processing: The incoming request data is copied, auto-generated fields (like
-
Tender Update (
update_tender_by_serial_id):- Data Validation: Checks whether the
serial_idis present in the request and whether nested fields are correctly formatted as dictionaries. - Field Update Logic: The code iterates over a predefined set of fields (
fields_with_defaults), updating the existing document with either the new values or the current values from the database if the field is missing. - Sending Notifications: Although not fully implemented, the reviewer information (
reviewers_TOR,reviewers_EOI) is processed, and email notifications are prepared to notify the relevant procurement managers about the updates.
updates = {}for field, default_value in fields_with_defaults.items():updates[field] = data.get(field, existing_tender.get(field, default_value))result = tender_collection.update_one({'serial_id': serial_id}, {'$set': updates}) - Data Validation: Checks whether the
-
Error Handling:
- Try-Except Blocks: For both the tender creation and update processes, the code uses try-except blocks to catch and handle any exceptions. This ensures that if an error occurs (e.g., missing required fields, database errors), the system can respond with meaningful error messages.
- Response on Error: If the operation fails, it returns a JSON response with an error message and details of the exception.
except Exception as e:return jsonify({"error": "An unexpected error occurred","details": str(e)}), 500
Data Fetching and Step Handling:
-
Fetching Data:
- In the update endpoint, data is fetched from MongoDB using
find_onebased on theserial_id. This fetches the existing tender document so that updates can be made to it. - The
get_tender_collectionmethod is responsible for retrieving the MongoDB collection, and data is fetched using MongoDB’sfind_onemethod to locate the document.
existing_tender = tender_collection.find_one({"serial_id": serial_id}) - In the update endpoint, data is fetched from MongoDB using
-
Step Handling:
- The tender’s step is stored in the database, although it is not actively manipulated in the provided code. The
stepfield is part of the data structure for both tender creation and update, suggesting that it may be used later to track the progress of the tender. - The update process involves updating various steps or stages (such as
reviewers_TOR,reviewers_EOI) based on the data provided. This suggests that the tender may be in different phases, and different actions may be triggered based on the current step.
updates['step'] = data.get('step', existing_tender.get('step', None)) - The tender’s step is stored in the database, although it is not actively manipulated in the provided code. The
-
Information Flow:
- In tender creation, the flow starts with the frontend sending a request with tender data. The backend processes the data, assigns additional fields like
serial_idandid, and inserts the data into the database. - In tender update, the frontend sends updated tender information (with
serial_id), which is validated and merged with existing data before being saved back to the database. This also involves handling specific fields like submission deadlines, reviewer information, and status changes.
- In tender creation, the flow starts with the frontend sending a request with tender data. The backend processes the data, assigns additional fields like
Code Example for Reference:
Tender Creation:
tender_data = request.json.copy()tender_data['created_at'] = datetime.now(timezone.utc)tender_data['serial_id'] = get_next_serial_id()tender_data['id'] = uuid.uuid4().hex
tender_collection = get_tender_collection()result = tender_collection.insert_one(tender_data)
return jsonify({ "message": "Tender created successfully", "tender_id": str(result.inserted_id), "serial_id": tender_data['serial_id']}), 201Tender Update:
updates = {}for field, default_value in fields_with_defaults.items(): updates[field] = data.get(field, existing_tender.get(field, default_value))
result = tender_collection.update_one({'serial_id': serial_id}, {'$set': updates})This code demonstrates the key features of creating and updating tenders, managing errors, and handling data flow between the frontend and MongoDB.