diff --git a/Kafka/docker-compose.yml b/Kafka/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..f0490b975bf467484029471bbf6a46d5681733e3 --- /dev/null +++ b/Kafka/docker-compose.yml @@ -0,0 +1,29 @@ +version: "3.2" + +services: + zookeeper: + image: wurstmeister/zookeeper + container_name: zookeeper + ports: + - "2181:2181" + networks: + - kafka_network + + kafka: + image: wurstmeister/kafka + container_name: kafka + ports: + - "9092:9092" + depends_on: + - zookeeper + environment: + KAFKA_ADVERTISED_HOST_NAME: kafka + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_BOOTSTRAP_SEVERS: kafka:9092 + networks: + - kafka_network + +networks: + kafka_network: + external: true + #driver: bridge diff --git a/Orders_Microservice_Group3/0.0.0.0 b/Orders_Microservice_Group3/0.0.0.0 new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Orders_Microservice_Group3/Dockerfile b/Orders_Microservice_Group3/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..1091fe8833907601a28e831b25bab0c4a9455afe --- /dev/null +++ b/Orders_Microservice_Group3/Dockerfile @@ -0,0 +1,64 @@ +FROM python:3.11.4 + +#Copy requirements +COPY requirements.txt /order_ms/ + +COPY app /order_ms/ + +#Set working direcroty +WORKDIR /order_ms + +#Install dependencies +RUN pip install --no-cache-dir -r requirements.txt + +#Install other libraries in container +RUN apt-get update && apt-get install -y \ + unixodbc \ + unixodbc-dev \ + iputils-ping\ + apt-transport-https \ + gcc\ + curl \ + gnupg \ + freetds-dev \ + tdsodbc \ + && rm -rf /var/lib/apt/lists/* + +#Install ODBC Driver for Microsoft SQL Server Section... +#Source: https://learn.microsoft.com/en-us/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server?view=sql-server-ver16&tabs=debian18-install%2Calpine17-install%2Cdebian8-install%2Credhat7-13-install%2Crhel7-offline + +#Add Microsoft repository GPG key +RUN curl https://packages.microsoft.com/keys/microsoft.asc | tee /etc/apt/trusted.gpg.d/microsoft.asc + +#Add the Microsoft SQL Server repository for Debian 12 +RUN curl https://packages.microsoft.com/config/debian/12/prod.list | tee /etc/apt/sources.list.d/mssql-release.list + + +#Add Microsoft GPG key +RUN curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-archive-keyring.gpg + +#Add the Microsoft SQL Server repository for Debian 12 +RUN echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" > /etc/apt/sources.list.d/mssql-release.list + +#Update package list +RUN apt-get update + +#Install ODBC Driver 17 for SQL Server +RUN ACCEPT_EULA=Y apt-get install -y msodbcsql17 + +#Install mssql-tools +RUN ACCEPT_EULA=Y apt-get install -y mssql-tools +RUN bash -c "echo 'export PATH=\"$PATH:/opt/mssql-tools/bin\"' >> ~/.bashrc && source ~/.bashrc" + + +#RUN echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc && source ~/.bashrc + +#Install unixodbc-dev and kerberos library +RUN apt-get install -y libgssapi-krb5-2 + + +#Set environment variables for ODBC configuration +ENV ODBCINI=/etc/odbc.ini +ENV ODBCSYSINI=/etc + +CMD ["python", "index.py"] \ No newline at end of file diff --git a/Orders_Microservice_Group3/__pycache__/config.cpython-311.pyc b/Orders_Microservice_Group3/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..101ebab0c3bf83308915c60456759b6a5076dd5b Binary files /dev/null and b/Orders_Microservice_Group3/__pycache__/config.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/__init__.py b/Orders_Microservice_Group3/app/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8ffbc3af6baf3cdf9034964801c376d9ae17c7b6 --- /dev/null +++ b/Orders_Microservice_Group3/app/__init__.py @@ -0,0 +1,44 @@ +# from flask import Flask + +# from .controllers.AddToCartController import AddToCart_bp +# from .controllers.CheckOutController import checkout_bp +# from .controllers.DeleteFromItemController import DeleteCart_bp +# from .controllers.FetchCartController import cart_bp + + +# def create_app(): +# app = Flask(__name__) +# app.register_blueprint(AddToCart_bp) +# app.register_blueprint(checkout_bp) +# app.register_blueprint(DeleteCart_bp) +# app.register_blueprint(cart_bp) + + +# return app + +from flask import Flask +from flask_cors import CORS +import os + +from app.controllers.AddToCartController import AddToCart_bp +from app.controllers.CheckOutController import checkout_bp +from .controllers.DeleteFromItemController import DeleteCart_bp +from .controllers.FetchCartController import cart_bp +from .subscriber.UpdateProductSubscriber import start_kafka_consumer + +def create_app(): + app = Flask(__name__) + CORS(app) + + app.config.from_object('config') + + app.register_blueprint(AddToCart_bp) + app.register_blueprint(checkout_bp) + app.register_blueprint(DeleteCart_bp) + app.register_blueprint(cart_bp) + + # Optionally start Kafka consumer based on configuration + if app.config.get('START_KAFKA_CONSUMER', False): + start_kafka_consumer() + + return app \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/__pycache__/__init__.cpython-311.pyc b/Orders_Microservice_Group3/app/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..45f09827829da5b30358373d313d7bf931794085 Binary files /dev/null and b/Orders_Microservice_Group3/app/__pycache__/__init__.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/__pycache__/__init__.cpython-312.pyc b/Orders_Microservice_Group3/app/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58ee95c249f77ea8b7a423614344f4c1dee19f9e Binary files /dev/null and b/Orders_Microservice_Group3/app/__pycache__/__init__.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/__pycache__/config.cpython-311.pyc b/Orders_Microservice_Group3/app/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86c246b8cffc2ff3f0cfd64293963826bce4eba9 Binary files /dev/null and b/Orders_Microservice_Group3/app/__pycache__/config.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/config.py b/Orders_Microservice_Group3/app/config.py new file mode 100644 index 0000000000000000000000000000000000000000..14dd59325bb1f27ad20bc68b4e9a1f18dfa9d4f8 --- /dev/null +++ b/Orders_Microservice_Group3/app/config.py @@ -0,0 +1,6 @@ +DEBUG = True +SECRET_KEY = 'Group3' +PORT = 5003 +START_KAFKA_CONSUMER = True +HOST = '0.0.0.0' +KAFKA_SERVER = "kafka:9092" \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/controllers/AddToCartController.py b/Orders_Microservice_Group3/app/controllers/AddToCartController.py new file mode 100644 index 0000000000000000000000000000000000000000..16ff26afba66251af41977d07baa3d7f6158553f --- /dev/null +++ b/Orders_Microservice_Group3/app/controllers/AddToCartController.py @@ -0,0 +1,51 @@ +from flask import Blueprint, jsonify, request, json, session + +from models.AddToCart import add_item_shopping_cart +from models.CheckPriceAndQuantity import check_availability_and_price + +import requests + +AddToCart_bp = Blueprint("AddToCart", __name__) + + +@AddToCart_bp.route("/cart/AddToCart", methods=["POST"]) +def add_item(): + #user_id = 1 # Temporarily bypass authentication for testing + + user_id = session.get("user_id") + if not user_id: + return jsonify({"error": "User not logged in"}), 401 + + data = request.get_json() + ProductID = data.get("ProductID") + CartQuantity = data.get("CartQuantity") + UnitPrice = data.get("UnitPrice") + + # Check for required data + if not ProductID or not CartQuantity or UnitPrice is None: + return jsonify({"error": "Product ID, quantity, and unit price are required."}), 400 + + # Call the CheckPriceAndQuantity function + inventory_check = check_availability_and_price(ProductID, CartQuantity, UnitPrice, user_id) + + # If there's an issue with availability or price, return the message from the inventory check + if not inventory_check.get("available") or not inventory_check.get("price_correct"): + return jsonify({ + "error": inventory_check.get("message"), # Message from inventory check + "available_quantity": inventory_check.get("available_quantity"), + "current_price": inventory_check.get("current_price") + }), 400 + + cart_item_data = { + "UserID": user_id, + "ProductID": ProductID, + "UnitPrice": UnitPrice, + "CartQuantity": CartQuantity + } + + # Update cart item data with the current price + cart_item_data["UnitPrice"] = inventory_check["current_price"] + + # If the checks pass, add the item to the shopping cart + add_cart_item_message = add_item_shopping_cart(cart_item_data) + return jsonify(add_cart_item_message) diff --git a/Orders_Microservice_Group3/app/controllers/CheckOutController.py b/Orders_Microservice_Group3/app/controllers/CheckOutController.py new file mode 100644 index 0000000000000000000000000000000000000000..1f2d33b14dfd5ab6e2de330d476dc995b5f53a89 --- /dev/null +++ b/Orders_Microservice_Group3/app/controllers/CheckOutController.py @@ -0,0 +1,41 @@ +from flask import Blueprint, request, jsonify, session +from models.CheckOut import checkout_cart +from publishers.kafkaPublishers import publish_product_updated_event + +checkout_bp = Blueprint('checkout', __name__) + +@checkout_bp.route('/cart/checkout', methods=['POST']) +def handle_checkout(): + user_id = session.get("user_id") # Retrieve the user ID from session; ensure the user is logged in + #user_id = 1 + if not user_id: + return jsonify({"error": "User not logged in", "UserID" : user_id}), 401 + + data = request.get_json() + if not data or 'address' not in data: + return jsonify({"error": "Missing required fields: address"}), 400 + + address = data['address'] + + # Call the checkout function with the provided data + checkout_result = checkout_cart(user_id, address) + + # Check for errors in the result and return appropriate responses + if 'error' in checkout_result: + return jsonify({"error": checkout_result["error"]}), 500 # or another appropriate status code + + # If checkout is successful, publish an event to Kafka for each item purchased + for item in checkout_result.get('item_details', []): # Ensure that item_details are included in checkout_result + event_data = { + "ProductID": item['ProductID'], + "QuantityPurchased": item['Quantity'] + } + publish_product_updated_event(event_data) + + return jsonify({ + "message": "Checkout completed successfully", + "TransactionID": checkout_result.get("TransactionID", "Unknown") + }), 200 + + + diff --git a/Orders_Microservice_Group3/app/controllers/DeleteFromItemController.py b/Orders_Microservice_Group3/app/controllers/DeleteFromItemController.py new file mode 100644 index 0000000000000000000000000000000000000000..5520377bdab4b3877269318d6f601eb15869d77e --- /dev/null +++ b/Orders_Microservice_Group3/app/controllers/DeleteFromItemController.py @@ -0,0 +1,21 @@ +from models.DeleteItemCartModel import delete_item_from_cart +from flask import Blueprint, jsonify, request, json, session + +DeleteCart_bp = Blueprint("delete", __name__) + + + +@DeleteCart_bp.route("/cart/delete/<int:cart_item_id>", methods=['DELETE']) +def delete_item(cart_item_id): + #user_id = 1 + user_id = session.get("user_id") + + if not user_id: + return jsonify({"error": "You need to be logged in to delete items from the cart."}), 401 + + # Call the function to delete the item from the cart + result = delete_item_from_cart(user_id, cart_item_id) + + if "error" in result: + return jsonify(result), 404 # Or another appropriate status code based on the error + return jsonify(result), 200 \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/controllers/FetchCartController.py b/Orders_Microservice_Group3/app/controllers/FetchCartController.py new file mode 100644 index 0000000000000000000000000000000000000000..2c6e905b798388ada7b3eda8c80d969e66062e2c --- /dev/null +++ b/Orders_Microservice_Group3/app/controllers/FetchCartController.py @@ -0,0 +1,21 @@ +from flask import Blueprint, jsonify, request, json, session +from models.FetchKart import get_user_cart_items +import requests + +cart_bp = Blueprint("cart", __name__) + +@cart_bp.route("/cart", methods=["GET"]) +def fetch_user_cart(): + + #user_id = 5 + + user_id = session.get("user_id") + + if not user_id: + return jsonify({"error": "User ID is required."}), 400 + + cart_data = get_user_cart_items(user_id) + if "error" in cart_data: + return jsonify({"error": cart_data["error"]}), 500 + + return jsonify(cart_data) \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/controllers/OrderHistoryController.py b/Orders_Microservice_Group3/app/controllers/OrderHistoryController.py new file mode 100644 index 0000000000000000000000000000000000000000..804480e4714e705551f5353d4be59d5020f3d041 --- /dev/null +++ b/Orders_Microservice_Group3/app/controllers/OrderHistoryController.py @@ -0,0 +1,18 @@ +from flask import Blueprint, jsonify, session +from models.order_history import fetch_order_history + +order_history_bp = Blueprint('order_history', __name__) + +@order_history_bp.route('/order/history', methods=['GET']) +def order_history(): + user_id = session.get('user_id') + #user_id = 1 + if not user_id: + return jsonify({"error": "Authentication required to view order history."}), 401 + + order_history_data = fetch_order_history(user_id) + + if 'error' in order_history_data: + return jsonify({"error": order_history_data["error"]}), 500 + + return jsonify({"order_history": order_history_data}), 200 \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/controllers/UpdateProductController.py b/Orders_Microservice_Group3/app/controllers/UpdateProductController.py new file mode 100644 index 0000000000000000000000000000000000000000..ba1a39398981f74841fda90072bb5ef0f32408b1 --- /dev/null +++ b/Orders_Microservice_Group3/app/controllers/UpdateProductController.py @@ -0,0 +1,7 @@ +from flask import Blueprint, jsonify, request, json, session +from models.UpdateProduct import UpdateProduct +from subscriber.UpdateProductSubscriber import consume_product_updated_event + +import requests + + diff --git a/Orders_Microservice_Group3/app/controllers/__pycache__/AddToCart.cpython-312.pyc b/Orders_Microservice_Group3/app/controllers/__pycache__/AddToCart.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..61f056c0c6c1d44e3037c3caa6a159cbe1c2d4dd Binary files /dev/null and b/Orders_Microservice_Group3/app/controllers/__pycache__/AddToCart.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/controllers/__pycache__/AddToCartController.cpython-311.pyc b/Orders_Microservice_Group3/app/controllers/__pycache__/AddToCartController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97c0db86ef890aa773e3911eb8cb923b45158d13 Binary files /dev/null and b/Orders_Microservice_Group3/app/controllers/__pycache__/AddToCartController.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/controllers/__pycache__/AddToCartController.cpython-312.pyc b/Orders_Microservice_Group3/app/controllers/__pycache__/AddToCartController.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0f2978378b85343616505d320886ec0171822f64 Binary files /dev/null and b/Orders_Microservice_Group3/app/controllers/__pycache__/AddToCartController.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/controllers/__pycache__/CheckOutController.cpython-311.pyc b/Orders_Microservice_Group3/app/controllers/__pycache__/CheckOutController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..510d3c9c3eb0884b1e6afd398e7694964bd0042f Binary files /dev/null and b/Orders_Microservice_Group3/app/controllers/__pycache__/CheckOutController.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/controllers/__pycache__/CheckOutController.cpython-312.pyc b/Orders_Microservice_Group3/app/controllers/__pycache__/CheckOutController.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e365f5bde611cb80404546ffa04313ef6241fc51 Binary files /dev/null and b/Orders_Microservice_Group3/app/controllers/__pycache__/CheckOutController.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/controllers/__pycache__/DeleteFromItemController.cpython-311.pyc b/Orders_Microservice_Group3/app/controllers/__pycache__/DeleteFromItemController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..27cfe415a7050583d7a3462ce0a183d05dd71968 Binary files /dev/null and b/Orders_Microservice_Group3/app/controllers/__pycache__/DeleteFromItemController.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/controllers/__pycache__/DeleteFromItemController.cpython-312.pyc b/Orders_Microservice_Group3/app/controllers/__pycache__/DeleteFromItemController.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da076fa047163edc36e0bf3b2339a6b74d0b7478 Binary files /dev/null and b/Orders_Microservice_Group3/app/controllers/__pycache__/DeleteFromItemController.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/controllers/__pycache__/FetchCartController.cpython-311.pyc b/Orders_Microservice_Group3/app/controllers/__pycache__/FetchCartController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..53d9a1b05291e8a728ade7d7d25a829e4c7ba8fa Binary files /dev/null and b/Orders_Microservice_Group3/app/controllers/__pycache__/FetchCartController.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/controllers/__pycache__/FetchCartController.cpython-312.pyc b/Orders_Microservice_Group3/app/controllers/__pycache__/FetchCartController.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dfc13a9f5c15cb3c4f0eba233881f4a60cc6c9a3 Binary files /dev/null and b/Orders_Microservice_Group3/app/controllers/__pycache__/FetchCartController.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/controllers/__pycache__/OrderHistoryController.cpython-311.pyc b/Orders_Microservice_Group3/app/controllers/__pycache__/OrderHistoryController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b860e83af0ea0d5e99f82ca0488580230806fdbb Binary files /dev/null and b/Orders_Microservice_Group3/app/controllers/__pycache__/OrderHistoryController.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/controllers/__pycache__/UpdateProductController.cpython-311.pyc b/Orders_Microservice_Group3/app/controllers/__pycache__/UpdateProductController.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..23e96840e525d88b7815e326927bd300b7099792 Binary files /dev/null and b/Orders_Microservice_Group3/app/controllers/__pycache__/UpdateProductController.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/hello_world.py b/Orders_Microservice_Group3/app/hello_world.py new file mode 100644 index 0000000000000000000000000000000000000000..df9ab9f16ad0c309cd6fbe9a539a12b1a821d2fb --- /dev/null +++ b/Orders_Microservice_Group3/app/hello_world.py @@ -0,0 +1,9 @@ +from flask import Flask +app = Flask(__name__) + +@app.route('/') +def hello_world(): + return 'Hello World' + +if __name__ == '__main__': + app.run() \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/index.py b/Orders_Microservice_Group3/app/index.py new file mode 100644 index 0000000000000000000000000000000000000000..c42090f982e2bb0fa249815b4100e57fd5c6357d --- /dev/null +++ b/Orders_Microservice_Group3/app/index.py @@ -0,0 +1,127 @@ +from flask import Flask, jsonify, request, render_template, session, abort, redirect, url_for, make_response +import requests +import subscriber +from flask_cors import CORS +from config import DEBUG, SECRET_KEY, PORT, HOST +import os + +# Importing blueprints from the controllers +from controllers.AddToCartController import AddToCart_bp +from controllers.CheckOutController import checkout_bp +from controllers.DeleteFromItemController import DeleteCart_bp +from controllers.FetchCartController import cart_bp +from controllers.OrderHistoryController import order_history_bp + +# Setting up Flask application +app = Flask(__name__) +CORS(app) + + +@app.route('/cart', methods=['POST']) +def get_session_id(): + session_id = session.get('user_id') + if session_id: + return jsonify({'session_id': session_id}) + else: + return jsonify({'message': 'Session ID not found'}) + +# @app.route('/') +# def index(): + +# return render_template("index.html") + + +# Register blueprints for different parts of the application +app.register_blueprint(AddToCart_bp) +app.register_blueprint(checkout_bp) +app.register_blueprint(DeleteCart_bp) +app.register_blueprint(cart_bp) +app.register_blueprint(order_history_bp) + + + +try: + + # Check for the existence of the /proc/self/cgroup file + with open("/proc/self/cgroup", "r") as cgroup_file: + cgroup_info = cgroup_file.read() + + # Check if the cgroup information contains 'docker' keyword + if 'docker' in cgroup_info: + print("Running inside Docker container") + app.secret_key = os.environ.get('SECRET_KEY') + +except FileNotFoundError: + # If the file doesn't exist + print("Running on a local Windows machine") + + app.secret_key = SECRET_KEY + + +if __name__ == '__main__': + + subscriber.start_kafka_consumer() + + # Running the Flask application + app.run(host=HOST, debug=DEBUG, port=PORT) + + + + + + + + + +# from flask import Flask, redirect, url_for, request, render_template, make_response, session, abort +# from flask_cors import CORS +# from flask import jsonify +# from config import DEBUG, SECRET_KEY, PORT +# import os +# import requests +# import subscribers + +# from controllers.AddToCartController import AddToCart_bp +# from controllers.CheckOutController import checkout_bp +# from controllers.DeleteFromItemController import DeleteCart_bp +# from controllers.FetchCartController import cart_bp +# from controllers.UpdateProductController import cart_bp + + +# app = Flask(__name__) +# CORS(app) + + +# app.secret_key = SECRET_KEY + + +# # Read user microservice URL from environment variable +# USER_MICROSERVICE_URL = os.getenv('USER_MICROSERVICE_URL', 'http://127.0.0.1:5000') + + +# @app.route('/cart', methods=['POST']) +# def get_session_id(): +# session_id = session.get('user_id') +# if session_id: +# return jsonify({'session_id': session_id}) +# else: +# return jsonify({'message': 'Session ID not found'}) + +# @app.route('/') +# def index(): +# return render_template("index.html") + + + +# # app.register_blueprint(AddToCart_bp) +# # app.register_blueprint(checkout_bp) +# # app.register_blueprint(DeleteCart_bp) +# # app.register_blueprint(cart_bp) + + + +# if __name__ == '__main__': + +# subscribers.start_kafka_consumer() + +# app.run(debug=DEBUG, port=PORT) \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/models/AddToCart.py b/Orders_Microservice_Group3/app/models/AddToCart.py new file mode 100644 index 0000000000000000000000000000000000000000..b5df717131fa80ac5f91a8de62fa7a1deb48d9ec --- /dev/null +++ b/Orders_Microservice_Group3/app/models/AddToCart.py @@ -0,0 +1,35 @@ +import pyodbc +from flask import jsonify +from decimal import Decimal +from models.database_connection import connect_db + +def add_item_shopping_cart(data): + + try: #error handling + connection = connect_db() + cursor = connection.cursor() + + insert_cart_item_query = '''INSERT INTO dbo.ShoppingCart (UserID, ProductID, UnitPrice, CartQuantity) +VALUES (?, ?, ?, ?);''' + cursor.execute(insert_cart_item_query, (data["UserID"], data["ProductID"], data["UnitPrice"], data["CartQuantity"])) + + connection.commit() + + return {"message": "Item added to cart successfully"} + + except pyodbc.Error as e: + print(f"Database error in add_item_to_cart: {e}") + connection.rollback() + return {"Error": f"Unexpected error: {str(e)}"} + + except Exception as e: + print(f"Unexpected error occurred in add_item_to_cart: {e}") + connection.rollback() + return {"Error": "Unexpected error"} + + finally: + if cursor: + cursor.close() + if connection: + connection.close() + diff --git a/Orders_Microservice_Group3/app/models/CheckOut.py b/Orders_Microservice_Group3/app/models/CheckOut.py new file mode 100644 index 0000000000000000000000000000000000000000..d047f9f222fb12d24401bdaaf45f4d5decb620c7 --- /dev/null +++ b/Orders_Microservice_Group3/app/models/CheckOut.py @@ -0,0 +1,111 @@ +from models.database_connection import connect_db +from flask import Blueprint, request, jsonify, session + +from decimal import Decimal +import pyodbc +from datetime import datetime + + + +def checkout_cart(user_id, address): + try: + connection = connect_db() + connection.autocommit = False + cursor = connection.cursor() + + # Fetch cart items for the user + cursor.execute(""" + SELECT ProductID, CartQuantity, FORMAT(UnitPrice, 'N2') AS UnitPrice + FROM ShoppingCart + WHERE UserID = ? + """, (user_id,)) + cart_items = cursor.fetchall() + + if not cart_items: + return {"error": "No items in the cart to checkout."} + + total_price = 0 + item_details = [] + + # Verify availability and price for each cart item + for item in cart_items: + ProductID, CartQuantity, UnitPrice = item + UnitPrice_decimal = Decimal(UnitPrice) # Convert string to Decimal for precise calculations + + # Fetch the current availability and unit price from the product data + cursor.execute(""" + SELECT QuantityAvailable, FORMAT(UnitPrice, 'N2') AS UnitPrice + FROM ProductData + WHERE ProductID = ? + """, (ProductID,)) + row = cursor.fetchone() + if row: + available_quantity, current_price = row + current_price_decimal = Decimal(current_price) + + if available_quantity < CartQuantity: + connection.rollback() + return {"error": f"Not enough inventory for ProductID {ProductID}."} + + if current_price_decimal != UnitPrice_decimal: + cursor.execute(""" + UPDATE ShoppingCart + SET UnitPrice = ? + WHERE ProductID = ? AND UserID = ? + """, (current_price, ProductID, user_id)) + connection.commit() + return {"error": f"Price has changed for ProductID {ProductID}. Updated price in cart."} + + + new_quantity = available_quantity - CartQuantity + cursor.execute(""" + UPDATE ProductData + SET QuantityAvailable = ? + WHERE ProductID = ? + """, (new_quantity, ProductID)) + + + TotalItemPrice = CartQuantity * current_price_decimal + total_price += TotalItemPrice + item_details.append({ + "ProductID": ProductID, + "Quantity": CartQuantity, + "UnitPrice": current_price_decimal, + "TotalItemPrice": TotalItemPrice + }) + + # Insert a new order group + cursor.execute(""" + INSERT INTO OrderGroup (CustomerID, TotalPrice, TransactionDate, Location, OrdersStatus) + OUTPUT INSERTED.OrderGroupID + VALUES (?, ?, ?, ?, 'Processing') + """, (user_id, total_price, datetime.now(), address)) + OrderGroupID = cursor.fetchone()[0] + + # Insert cart items into OrderItem table + for item in item_details: + cursor.execute(""" + INSERT INTO OrderItem (OrderGroupID, ProductID, Quantity, TotalItemPrice) + VALUES (?, ?, ?, ?) + """, (OrderGroupID, item["ProductID"], item["Quantity"], item["TotalItemPrice"])) + + # Delete the cart items from the ShoppingCart + cursor.execute("DELETE FROM ShoppingCart WHERE UserID = ?", (user_id,)) + connection.commit() + + return { + "success": "Checkout completed successfully.", + "TransactionID": OrderGroupID, + "item_details": item_details # Include item details for post-processing + } + + except pyodbc.Error as e: + print(f"Database error during checkout: {e}") + connection.rollback() + return {"error": "Database error during checkout"} + + finally: + if cursor: + cursor.close() + if connection: + connection.close() \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/models/CheckPriceAndQuantity.py b/Orders_Microservice_Group3/app/models/CheckPriceAndQuantity.py new file mode 100644 index 0000000000000000000000000000000000000000..ebb2581fde514c083ccabe2ebca1d59246247249 --- /dev/null +++ b/Orders_Microservice_Group3/app/models/CheckPriceAndQuantity.py @@ -0,0 +1,66 @@ +from models.database_connection import connect_db +import pyodbc + +from decimal import Decimal + + + +def check_availability_and_price(product_id, requested_quantity, expected_price, user_id): + connection = connect_db() + try: + cursor = connection.cursor() + # Fetch the current available quantity and price + cursor.execute(""" + SELECT QuantityAvailable, FORMAT(UnitPrice, 'N2') AS UnitPrice + FROM ProductData + WHERE ProductID = ? + """, (product_id,)) + + row = cursor.fetchone() + if row: + available_quantity, current_price = row + current_pricefloat = float(current_price) # Convert formatted price back to float if necessary for comparisons + + response_data = { + "available_quantity": available_quantity, + "current_price": current_price, + "available": available_quantity >= requested_quantity, + "price_correct": current_pricefloat == expected_price + } + + messages = [] + if not response_data["available"]: + messages.append(f"We apologize, but there are only {available_quantity} items available.") + + # Check if the price has changed + if not response_data["price_correct"]: + messages.append(f"The price has changed. The current price is now {current_pricefloat}.") + # Update the ShoppingCart with the new price + cursor.execute(""" + UPDATE ShoppingCart + SET UnitPrice = ? + WHERE ProductID = ? AND UserID = ? + """, (current_price, product_id, user_id)) + connection.commit() + + if messages: + response_data["message"] = " ".join(messages) + return response_data + else: + # All checks passed + return response_data + + else: + return {"available": False, "message": "Product not found."} + + except pyodbc.Error as e: + print(f"Database error in check_availability_and_price: {e}") + connection.rollback() + return {"available": False, "message": f"Database error: {str(e)}"} + + finally: + if cursor: + cursor.close() + if connection: + connection.close() + diff --git a/Orders_Microservice_Group3/app/models/DeleteItemCartModel.py b/Orders_Microservice_Group3/app/models/DeleteItemCartModel.py new file mode 100644 index 0000000000000000000000000000000000000000..2ca2a67930c83e98fd019405659321f84bb1a0d3 --- /dev/null +++ b/Orders_Microservice_Group3/app/models/DeleteItemCartModel.py @@ -0,0 +1,40 @@ +from flask import jsonify +from models.database_connection import connect_db +import pyodbc + +def delete_item_from_cart(user_id, cart_item_id): + + try: # error handling + connection = connect_db() + cursor = connection.cursor() + + # SQL query to delete the item from the cart based on cart_item_id and UserID + delete_cart_item_query = '''DELETE FROM dbo.ShoppingCart WHERE UserID = ? AND CartItemID = ?;''' + cursor.execute(delete_cart_item_query, (user_id, cart_item_id)) + + # Committing the transaction to the database + connection.commit() + + # Check if the delete operation was successful + if cursor.rowcount == 0: + return {"error": "Item not found or could not be deleted"} + + return {"message": "Item deleted successfully"} + + except pyodbc.Error as e: + print(f"Database error in delete_item_from_cart: {e}") + # Rollback the transaction in case of an error + connection.rollback() + return {"error": "Database error during item deletion"} + + except Exception as e: + print(f"Unexpected error occurred in delete_item_from_cart: {e}") + # Rollback the transaction in case of an unexpected error + connection.rollback() + return {"error": "Unexpected error during item deletion"} + + finally: + if cursor: + cursor.close() + if connection: + connection.close() \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/models/FetchKart.py b/Orders_Microservice_Group3/app/models/FetchKart.py new file mode 100644 index 0000000000000000000000000000000000000000..b9bd2df5c1a4e1bf7e88703f3630617a51609a1e --- /dev/null +++ b/Orders_Microservice_Group3/app/models/FetchKart.py @@ -0,0 +1,48 @@ +import pyodbc +from datetime import datetime +from models.database_connection import connect_db + + +from models.database_connection import connect_db +from flask import jsonify +import pyodbc + +def get_user_cart_items(user_id): + try: + connection = connect_db() + cursor = connection.cursor() + + query = "SELECT * FROM ShoppingCart WHERE UserID = ?" + cursor.execute(query, (user_id,)) + + # Fetch all rows for the user_id + rows = cursor.fetchall() + + # Prepare a list of dictionaries to hold cart item data + cart_items = [] + Total_Price = 0 + for row in rows: + Total_item_price = row.CartQuantity * row.UnitPrice + cart_item = { + "CartItemID": row.CartItemID, + "UserID": row.UserID, + "ProductID": row.ProductID, + "UnitPrice": row.UnitPrice, + "CartQuantity": row.CartQuantity, + "AddedDate": row.AddedDate, + "TotalItemPrice": Total_item_price + } + cart_items.append(cart_item) + Total_Price += Total_item_price + + return {"CartItems": cart_items, "TotalPrice": Total_Price} + + except pyodbc.Error as e: + print(f"Database error in get_user_cart_items: {e}") + return {"error": "Database error"} + + finally: + if cursor: + cursor.close() + if connection: + connection.close() \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/models/UpdateProduct.py b/Orders_Microservice_Group3/app/models/UpdateProduct.py new file mode 100644 index 0000000000000000000000000000000000000000..a472d4bae015dec5be5f841f0ceac0da88228f62 --- /dev/null +++ b/Orders_Microservice_Group3/app/models/UpdateProduct.py @@ -0,0 +1,55 @@ +#from confluent_kafka import Producer +import json +import pyodbc +from flask import jsonify +#from flask import jsonify +from models.database_connection import connect_db + +#subscriber + +def UpdateProduct(product_id, quantity, price): + try: + connection = connect_db() + connection.autocommit = False + cursor = connection.cursor() + + # SQL MERGE statement to insert or update + sql_product_data = """ + MERGE INTO ProductData AS target + USING (SELECT ? AS ProductID, ? AS QuantityAvailable, ? AS UnitPrice) AS source + ON target.ProductID = source.ProductID + WHEN MATCHED THEN + UPDATE SET QuantityAvailable = source.QuantityAvailable, UnitPrice = source.UnitPrice + WHEN NOT MATCHED BY TARGET THEN + INSERT (ProductID, QuantityAvailable, UnitPrice) + VALUES (source.ProductID, source.QuantityAvailable, source.UnitPrice); + """ + cursor.execute(sql_product_data, (product_id, quantity, price)) + + # Update ShoppingCart to reflect new prices + sql_shopping_cart = """ + UPDATE ShoppingCart + SET UnitPrice = ? + WHERE ProductID = ? + """ + cursor.execute(sql_shopping_cart, (price, product_id)) + + connection.commit() + return {"success": "Product information updated successfully."} + + except pyodbc.Error as e: + print(f"Database error during product update: {e}") + connection.rollback() + return {"error": f"Database error during product update: {e}"} + + except Exception as e: + print(f"Unexpected error occurred: {e}") + connection.rollback() + return {"error": f"Unexpected error: {e}"} + + finally: + if cursor: + cursor.close() + if connection: + connection.close() + diff --git a/Orders_Microservice_Group3/app/models/__init__.py b/Orders_Microservice_Group3/app/models/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..7cf5b4c542f1443c20eb27c463b645ba727a4ad8 --- /dev/null +++ b/Orders_Microservice_Group3/app/models/__init__.py @@ -0,0 +1,15 @@ +from flask import Flask +from flask_cors import CORS + + +#from app.models import models + +app = Flask(__name__) +CORS(app) + +#db = sqlAlchemy + +#from app import routes + +if __name__ == '__main__': + app.run(debug=True) diff --git a/Orders_Microservice_Group3/app/models/__pycache__/AddToCart.cpython-311.pyc b/Orders_Microservice_Group3/app/models/__pycache__/AddToCart.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ddd270469158b1323dbea0108fe0f694fa8263d9 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/AddToCart.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/AddToCart.cpython-312.pyc b/Orders_Microservice_Group3/app/models/__pycache__/AddToCart.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd1c0a1653bfb72c78ee6c043d7d6b69b87afbd3 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/AddToCart.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/CheckOut.cpython-311.pyc b/Orders_Microservice_Group3/app/models/__pycache__/CheckOut.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab02bef1ebefdfcc2317bcec2dd48f95f799223b Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/CheckOut.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/CheckOut.cpython-312.pyc b/Orders_Microservice_Group3/app/models/__pycache__/CheckOut.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa7bdb081e740a0063e28ae61d22f4e633ced122 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/CheckOut.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/CheckPriceAndQuantity.cpython-311.pyc b/Orders_Microservice_Group3/app/models/__pycache__/CheckPriceAndQuantity.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c79d5db4c1eefa4213fb9c763d66403f25f4861c Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/CheckPriceAndQuantity.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/CheckPriceAndQuantity.cpython-312.pyc b/Orders_Microservice_Group3/app/models/__pycache__/CheckPriceAndQuantity.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..83a41ba36819661015f476b957f0f91566c55176 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/CheckPriceAndQuantity.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/DeleteItemCartModel.cpython-311.pyc b/Orders_Microservice_Group3/app/models/__pycache__/DeleteItemCartModel.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7084c58d824a608c98d1ce39a68872d6a9dc1284 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/DeleteItemCartModel.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/DeleteItemCartModel.cpython-312.pyc b/Orders_Microservice_Group3/app/models/__pycache__/DeleteItemCartModel.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a2ea66674acb226f5185fc19100366ff091f702e Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/DeleteItemCartModel.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/FetchKart.cpython-311.pyc b/Orders_Microservice_Group3/app/models/__pycache__/FetchKart.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bed234c22c7b1ebd9c17c3faf94d2966bb327360 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/FetchKart.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/FetchKart.cpython-312.pyc b/Orders_Microservice_Group3/app/models/__pycache__/FetchKart.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8566e4c71881890ccfe8d200cc358919b41a2a62 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/FetchKart.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/UpdateProduct.cpython-311.pyc b/Orders_Microservice_Group3/app/models/__pycache__/UpdateProduct.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5411ca5c9766993a6b7cd19baecd897ec1b7db06 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/UpdateProduct.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/__init__.cpython-311.pyc b/Orders_Microservice_Group3/app/models/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e9bc8be7b53872e499459cc9155650cec52f4f2 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/__init__.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/__init__.cpython-312.pyc b/Orders_Microservice_Group3/app/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1a6cdeed180b8b57206cfa994f5e6fd4dc67512a Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/__init__.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/database_connection.cpython-311.pyc b/Orders_Microservice_Group3/app/models/__pycache__/database_connection.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a76c64f94ba987629cbf450158caf7e238505000 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/database_connection.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/database_connection.cpython-312.pyc b/Orders_Microservice_Group3/app/models/__pycache__/database_connection.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f93efc54c77937369eb7735c897e3beaf7600747 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/database_connection.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/models/__pycache__/order_history.cpython-311.pyc b/Orders_Microservice_Group3/app/models/__pycache__/order_history.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..793a28e25ca43b12911abbe33cac99eae7e28750 Binary files /dev/null and b/Orders_Microservice_Group3/app/models/__pycache__/order_history.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/models/database_connection.py b/Orders_Microservice_Group3/app/models/database_connection.py new file mode 100644 index 0000000000000000000000000000000000000000..3d1c7c3be68df935bc40493fefbc35adaf05e1c1 --- /dev/null +++ b/Orders_Microservice_Group3/app/models/database_connection.py @@ -0,0 +1,25 @@ +import pyodbc +import os + + +print("Outside db connection function") +#Connect to database +def connect_db(): + print("In CONNECT DB") + try: + + server = '34.39.6.180' + database = 'ordermanagementdatabase' + username = 'sqlserver' + password = 'WebTechGroup3' + driver = 'ODBC Driver 17 for SQL Server' + + connection_string = f'DRIVER={driver};SERVER={server};DATABASE={database};UID={username};PWD={password};Trusted_Connection=no;' + + return pyodbc.connect(connection_string) + + except Exception as e: + # If the file doesn't exist + print("Unexpected error occured {e}") + + return False diff --git a/Orders_Microservice_Group3/app/models/order_history.py b/Orders_Microservice_Group3/app/models/order_history.py new file mode 100644 index 0000000000000000000000000000000000000000..7337ee09987d039d6af53d4ff22d0838ca109329 --- /dev/null +++ b/Orders_Microservice_Group3/app/models/order_history.py @@ -0,0 +1,59 @@ +import pyodbc +from models.database_connection import connect_db + +def fetch_order_history(user_id): + try: + # Open database connection + connection = connect_db() + cursor = connection.cursor() + + # Fetch the order history for the user + cursor.execute(""" + SELECT og.OrderGroupID, og.CustomerID, og.TransactionDate, og.Location, og.OrdersStatus, og.TotalPrice, oi.OrderItemID, oi.ProductID, oi.UnitPrice, oi.Quantity, oi.TotalItemPrice + FROM OrderGroup og + INNER JOIN OrderItem oi ON og.OrderGroupID = oi.OrderGroupID + WHERE og.CustomerID = ? + ORDER BY og.TransactionDate DESC;""", (user_id,)) + + # Fetch all records and close cursor and connection + records = cursor.fetchall() + cursor.close() + connection.close() + + # Process the fetched data into a structured format for the API response + order_history = {} + for record in records: + # Unpack the fetched row + order_group_id, customer_id, transaction_date, location, orders_status, total_price, order_item_id, product_id, unit_price, quantity, total_item_price = record + + + if order_group_id not in order_history: + order_history[order_group_id] = { + "CustomerID": customer_id, + "TransactionDate": transaction_date, + "Location": location, + "OrdersStatus": orders_status, + "TotalPrice": total_price, + "Items": [] + } + + # Append this item to the items list for the order group + order_history[order_group_id]["Items"].append({ + "OrderItemID": order_item_id, + "ProductID": product_id, + "UnitPrice": unit_price, + "Quantity": quantity, + "TotalItemPrice": total_item_price + }) + + # Convert to list of order histories + order_history_list = list(order_history.values()) + return order_history_list + + except pyodbc.Error as e: + # Close cursor and connection in case of error + if cursor: + cursor.close() + if connection: + connection.close() + return {"error": str(e)} diff --git a/Orders_Microservice_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-311.pyc b/Orders_Microservice_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2b0a2c94e95fffa6a67092d66f9fe3958cd432c Binary files /dev/null and b/Orders_Microservice_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-312.pyc b/Orders_Microservice_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..432486e9bcb7f12b1184b584251c58df46243066 Binary files /dev/null and b/Orders_Microservice_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-312.pyc differ diff --git a/Orders_Microservice_Group3/app/publishers/kafkaPublishers.py b/Orders_Microservice_Group3/app/publishers/kafkaPublishers.py new file mode 100644 index 0000000000000000000000000000000000000000..0e198a82934f6d9032e5cb5ee8a610b5cc1da03a --- /dev/null +++ b/Orders_Microservice_Group3/app/publishers/kafkaPublishers.py @@ -0,0 +1,44 @@ +from kafka import KafkaProducer +from kafka.admin import KafkaAdminClient, NewTopic +from config import KAFKA_SERVER + +import json + +producer = KafkaProducer(bootstrap_servers=KAFKA_SERVER) + + +#Creates the topic +def create_Quantity_updated_topic(): + + admin_client = KafkaAdminClient(bootstrap_servers=KAFKA_SERVER) + + # Define the topic name + topic_name = "QuantityUpdateFromOrders" + num_partitions = 1 + replication_factor = 1 + + # Retrieve the list of existing topics + topic_metadata = admin_client.list_topics() + + # Check if the topic already exists + if topic_name not in topic_metadata: + # Define the configuration for the new topic + new_topic = NewTopic(name=topic_name, num_partitions=num_partitions, replication_factor=replication_factor) + # Create the new topic + admin_client.create_topics(new_topics=[new_topic], validate_only=False) + + +def publish_product_updated_event(event_data): + # Serialize the event data to JSON + event_json = json.dumps(event_data) + # Publish the event to the Kafka topic + data_to_send = producer.send("QuantityUpdateFromOrders", value=event_json.encode("utf-8")) + try: + record_metadata = data_to_send.get(timeout=10) + print("Message sent successfully!") + print("Topic:", record_metadata.topic) + print("Partition:", record_metadata.partition) + print("Offset:", record_metadata.offset) + except Exception as e: + print("Failed to send message:", e) + producer.flush() diff --git a/Orders_Microservice_Group3/app/run.py b/Orders_Microservice_Group3/app/run.py new file mode 100644 index 0000000000000000000000000000000000000000..507f9d423bdba63ec48425668bdca4f4a8e28c05 --- /dev/null +++ b/Orders_Microservice_Group3/app/run.py @@ -0,0 +1,7 @@ + +from app import create_app + +app = create_app() + +if __name__ == '__main__': + app.run(debug=app.config['DEBUG'], port=app.config['PORT']) \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/subscriber/UpdateProductSubscriber.py b/Orders_Microservice_Group3/app/subscriber/UpdateProductSubscriber.py new file mode 100644 index 0000000000000000000000000000000000000000..1de212e9d7060e9fb32be1b8071e27beed83abf7 --- /dev/null +++ b/Orders_Microservice_Group3/app/subscriber/UpdateProductSubscriber.py @@ -0,0 +1,39 @@ +import sys +print(sys.path) +from threading import Thread +from kafka import KafkaConsumer +import json +import logging +from config import KAFKA_SERVER + +#KAFKA_SERVER= "localhost:9092" +TOPIC_NAME = "product_updated_topic" + + +from models.UpdateProduct import UpdateProduct + +def consume_product_updated_event(): + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + logging.info("Consuming product updated event...") + + # Create KafkaConsumer listening on the product_updated_topic + consumer = KafkaConsumer("product_updated_topic", bootstrap_servers=KAFKA_SERVER) + + for message in consumer: + product_data_str = message.value.decode("utf-8") + product_data = json.loads(product_data_str) + logging.info("Received product update: {}".format(product_data)) + + # Call your UpdateProduct function passing the dictionary containing product details + UpdateProduct(product_id=product_data['product_id'], + quantity=product_data['quantity'], + price=product_data['price']) + +def start_kafka_consumer(): + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + logging.info("Starting Kafka consumer...") + + # Starting the consumer in a separate thread + kafka_thread = Thread(target=consume_product_updated_event) + kafka_thread.daemon = True + kafka_thread.start() \ No newline at end of file diff --git a/Orders_Microservice_Group3/app/subscriber/__init__.py b/Orders_Microservice_Group3/app/subscriber/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..4006e98f1130d14171b31be230321054cc4fca01 --- /dev/null +++ b/Orders_Microservice_Group3/app/subscriber/__init__.py @@ -0,0 +1,5 @@ +print("Subscribers package initialized") + +from subscriber.UpdateProductSubscriber import consume_product_updated_event + +from subscriber.UpdateProductSubscriber import start_kafka_consumer diff --git a/Orders_Microservice_Group3/app/subscriber/__pycache__/UpdateProductSubscriber.cpython-311.pyc b/Orders_Microservice_Group3/app/subscriber/__pycache__/UpdateProductSubscriber.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..347dfdcb2d1cb3528ea4579548142eb62d88f351 Binary files /dev/null and b/Orders_Microservice_Group3/app/subscriber/__pycache__/UpdateProductSubscriber.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/subscriber/__pycache__/__init__.cpython-311.pyc b/Orders_Microservice_Group3/app/subscriber/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6f5f6208ebc6c55c800f135380842c5ebd5009ab Binary files /dev/null and b/Orders_Microservice_Group3/app/subscriber/__pycache__/__init__.cpython-311.pyc differ diff --git a/Orders_Microservice_Group3/app/subscriber/import pyodbc.txt b/Orders_Microservice_Group3/app/subscriber/import pyodbc.txt new file mode 100644 index 0000000000000000000000000000000000000000..192c306ea69eb14b1066fa4500d4abba9ad0ca09 --- /dev/null +++ b/Orders_Microservice_Group3/app/subscriber/import pyodbc.txt @@ -0,0 +1,45 @@ +import pyodbc +from datetime import datetime +from app.models.database_connection import connect_db +from your_kafka_module import kafka_produce # Import the Kafka producer function + +def order_service_consumer(): + consumer = Consumer({ + 'bootstrap.servers': 'localhost:9092', + 'group.id': 'orders-group', + 'auto.offset.reset': 'earliest' + }) + consumer.subscribe(['product_changes']) + + while True: + message = consumer.poll(1.0) + if message is None: + continue + if message.error(): + print("Consumer error: {}".format(message.error())) + continue + + data = json.loads(message.value().decode('utf-8')) + if data['type'] == 'quantity_update': + # Update orders database based on quantity change + update_orders_database(data['product_id'], data['quantity_sold']) + +def update_orders_database(product_id, quantity_sold): + connection = connect_db() + try: + cursor = connection.cursor() + # Update logic here, e.g., flagging orders as fulfilled + cursor.execute("UPDATE Orders SET Status = 'Updated' WHERE product_id = ?", (product_id,)) + connection.commit() + finally: + cursor.close() + connection.close() + + + + + + + + +kafka-console-producer.bat --broker-list localhost:9092 --topic product_update_topic diff --git a/Orders_Microservice_Group3/config.py b/Orders_Microservice_Group3/config.py new file mode 100644 index 0000000000000000000000000000000000000000..cdd27f126d1eef015410d18492f2803aa62304d9 --- /dev/null +++ b/Orders_Microservice_Group3/config.py @@ -0,0 +1,10 @@ +import os + +DEBUG = True +SECRET_KEY = "Group3" + +PORT = 5003 + +KAFKA_SERVER= "kafka:9092" + +HOST = "0.0.0.0" diff --git a/Orders_Microservice_Group3/debug_consumer.py b/Orders_Microservice_Group3/debug_consumer.py new file mode 100644 index 0000000000000000000000000000000000000000..d89bad3946a34b5cc074c4c4336dab727d293f02 --- /dev/null +++ b/Orders_Microservice_Group3/debug_consumer.py @@ -0,0 +1,6 @@ +import logging +from .app.subscriber.UpdateProductSubscriber import consume_product_updated_event + +if __name__ == '__main__': + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + consume_product_updated_event() \ No newline at end of file diff --git a/Orders_Microservice_Group3/docker-compose.yml b/Orders_Microservice_Group3/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..7184b10fa8c5bdc804ec5350f1931f28f1ae6a1e --- /dev/null +++ b/Orders_Microservice_Group3/docker-compose.yml @@ -0,0 +1,24 @@ +version: "3.2" + +services: + + orders-microservice: + build: + context: . + dockerfile: Dockerfile + no_cache: true + image: orders-microservice:3.0 + container_name: orders-microservice + ports: + - "5003:5003" + environment: + #DATABASE_URL: "DRIVER={ODBC Driver 17 for SQL Server};SERVER=orders-database,1433;DATABASE=Orders;UID=sa;PWD=WebTechGroup3;" + KAFKA_SERVER: "kafka:9092" + SECRET_KEY: Group3 + networks: + - kafka_network + +networks: + kafka_network: + external: true + #driver: bridge \ No newline at end of file diff --git a/Orders_Microservice_Group3/requirements.txt b/Orders_Microservice_Group3/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..ed705a7c38f2b94cff3180d09f4c4af1e946bc93 Binary files /dev/null and b/Orders_Microservice_Group3/requirements.txt differ diff --git a/Orders_Microservice_Group3/run.py b/Orders_Microservice_Group3/run.py new file mode 100644 index 0000000000000000000000000000000000000000..b26a5df89d454bbe8e2b02f9de58accf3f4b2e9e --- /dev/null +++ b/Orders_Microservice_Group3/run.py @@ -0,0 +1,36 @@ +# from flask import Flask +# from app.__init__ import create_app +# app = Flask(__name__) + +# # Define the route for the root URL "/" +# @app.route('/') +# def home(): +# # This is the view function that returns a response +# return "Welcome to the Flask App!" + +# # Check if this is the script being run as the main program and start the app +# if __name__ == '__main__': +# app.run(debug=True) + +# from flask import Flask +# from flask_cors import CORS + + +# #from app.models import models + +# app = Flask(__name__) +# CORS(app) + +# #db = sqlAlchemy + +# #from app import routes + +# if __name__ == '__main__': +# app.run(debug=True) + +from app import create_app # Adjusted import to reference the app package + +app = create_app() + +if __name__ == '__main__': + app.run(debug=True) \ No newline at end of file diff --git a/Product_MicroService_Group3 b/Product_MicroService_Group3 new file mode 160000 index 0000000000000000000000000000000000000000..2adf1a709995e5d8a04d8bb921f90e3405b3b3a4 --- /dev/null +++ b/Product_MicroService_Group3 @@ -0,0 +1 @@ +Subproject commit 2adf1a709995e5d8a04d8bb921f90e3405b3b3a4 diff --git a/User_MicroService_Group3/User_Management.bak b/User_MicroService_Group3/User_Management.bak deleted file mode 100644 index 8286826a43c0de28f2cdc67078940fdafcfd9f9a..0000000000000000000000000000000000000000 Binary files a/User_MicroService_Group3/User_Management.bak and /dev/null differ diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..ed16d574aa7b320109a1b0ae8e05aea21cc7e514 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,84 @@ +version: "3.2" + +services: + + # Orders microservice + orders-microservice: + image: amychude/group3:orders-microservice-3.0 + container_name: orders-microservice-3.0 + ports: + - "5003:5003" + environment: + #DATABASE_URL: "DRIVER={ODBC Driver 17 for SQL Server};SERVER=orders-database-2.0,1433;DATABASE=Orders;UID=sa;PWD=WebTechGroup3;" + KAFKA_SERVER: "kafka:9092" + SECRET_KEY: "Group3" + depends_on: + - kafka + networks: + - kafka_network + command: > + /bin/bash -c "sleep 60 && python index.py" + + + # Product microservice + product-microservice: + image: amychude/group3:product-microservice-3.0 + container_name: product-microservice-3.0 + ports: + - "5001:5001" + environment: + #DATABASE_URL: "DRIVER={ODBC Driver 17 for SQL Server};SERVER=product-database-2.0,1433;DATABASE=Products;UID=sa;PWD=WebTechGroup3;" + KAFKA_SERVER: "kafka:9092" + SECRET_KEY: "Group3" + depends_on: + - kafka + networks: + - kafka_network + command: > + /bin/bash -c "sleep 60 && python index.py" + + + # User microservice + user-microservice: + image: amychude/group3:user-microservice-3.0 + container_name: user-microservice-3.0 + ports: + - "5000:5000" + environment: + #DATABASE_URL: "DRIVER={ODBC Driver 17 for SQL Server};SERVER=user-database-2.0,1433;DATABASE=User_Management;UID=sa;PWD=WebTechGroup3;" + KAFKA_SERVER: "kafka:9092" + SECRET_KEY: "Group3" + depends_on: + - kafka + networks: + - kafka_network + command: > + /bin/bash -c "sleep 60 && python index.py" + + # Kafka service + kafka: + image: amychude/group3:kafka-2.0 + container_name: kafka-2.0 + ports: + - "9092:9092" + environment: + KAFKA_ADVERTISED_HOST_NAME: kafka + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_BOOTSTRAP_SEVERS: kafka:9092 + depends_on: + - zookeeper + networks: + - kafka_network + + # Zookeeper service + zookeeper: + image: amychude/group3:zookeeper-2.0 + container_name: zookeeper-2.0 + ports: + - "2181:2181" + networks: + - kafka_network + +networks: + kafka_network: + driver: bridge