From 74f693e78c81038a75ea06c672fcb72c3bf2773e Mon Sep 17 00:00:00 2001 From: "cc02503@surrey.ac.uk" <cc02503@surrey.ac.uk> Date: Tue, 7 May 2024 00:09:40 +0100 Subject: [PATCH] Final commit for Advanced Web Project. Added docker and docker compose files for containerisation. Bug were also removed after testing. --- Kafka/docker-compose.yml | 27 +--- Orders_Microservice_Group3/0.0.0.0 | 0 Orders_Microservice_Group3/Dockerfile | 64 +++++++++ .../__pycache__/config.cpython-311.pyc | Bin 0 -> 346 bytes Orders_Microservice_Group3/app/__init__.py | 44 ++++++ .../app/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 1617 bytes .../app/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 963 bytes .../app/__pycache__/config.cpython-311.pyc | Bin 0 -> 413 bytes Orders_Microservice_Group3/app/config.py | 6 + .../app/controllers/AddToCartController.py | 51 +++++++ .../app/controllers/CheckOutController.py | 41 ++++++ .../controllers/DeleteFromItemController.py | 21 +++ .../app/controllers/FetchCartController.py | 21 +++ .../app/controllers/OrderHistoryController.py | 18 +++ .../controllers/UpdateProductController.py | 7 + .../__pycache__/AddToCart.cpython-312.pyc | Bin 0 -> 1337 bytes .../AddToCartController.cpython-311.pyc | Bin 0 -> 2297 bytes .../AddToCartController.cpython-312.pyc | Bin 0 -> 1911 bytes .../CheckOutController.cpython-311.pyc | Bin 0 -> 2034 bytes .../CheckOutController.cpython-312.pyc | Bin 0 -> 1688 bytes .../DeleteFromItemController.cpython-311.pyc | Bin 0 -> 1309 bytes .../DeleteFromItemController.cpython-312.pyc | Bin 0 -> 1068 bytes .../FetchCartController.cpython-311.pyc | Bin 0 -> 1242 bytes .../FetchCartController.cpython-312.pyc | Bin 0 -> 1079 bytes .../OrderHistoryController.cpython-311.pyc | Bin 0 -> 1262 bytes .../UpdateProductController.cpython-311.pyc | Bin 0 -> 606 bytes Orders_Microservice_Group3/app/hello_world.py | 9 ++ Orders_Microservice_Group3/app/index.py | 127 ++++++++++++++++++ .../app/models/AddToCart.py | 35 +++++ .../app/models/CheckOut.py | 111 +++++++++++++++ .../app/models/CheckPriceAndQuantity.py | 66 +++++++++ .../app/models/DeleteItemCartModel.py | 40 ++++++ .../app/models/FetchKart.py | 48 +++++++ .../app/models/UpdateProduct.py | 55 ++++++++ .../app/models/__init__.py | 15 +++ .../__pycache__/AddToCart.cpython-311.pyc | Bin 0 -> 2562 bytes .../__pycache__/AddToCart.cpython-312.pyc | Bin 0 -> 2279 bytes .../__pycache__/CheckOut.cpython-311.pyc | Bin 0 -> 5426 bytes .../__pycache__/CheckOut.cpython-312.pyc | Bin 0 -> 4606 bytes .../CheckPriceAndQuantity.cpython-311.pyc | Bin 0 -> 3407 bytes .../CheckPriceAndQuantity.cpython-312.pyc | Bin 0 -> 2444 bytes .../DeleteItemCartModel.cpython-311.pyc | Bin 0 -> 2649 bytes .../DeleteItemCartModel.cpython-312.pyc | Bin 0 -> 2212 bytes .../__pycache__/FetchKart.cpython-311.pyc | Bin 0 -> 2319 bytes .../__pycache__/FetchKart.cpython-312.pyc | Bin 0 -> 4020 bytes .../__pycache__/UpdateProduct.cpython-311.pyc | Bin 0 -> 3021 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 591 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 470 bytes .../database_connection.cpython-311.pyc | Bin 0 -> 1269 bytes .../database_connection.cpython-312.pyc | Bin 0 -> 624 bytes .../__pycache__/order_history.cpython-311.pyc | Bin 0 -> 2474 bytes .../app/models/database_connection.py | 25 ++++ .../app/models/order_history.py | 59 ++++++++ .../kafkaPublishers.cpython-311.pyc | Bin 0 -> 2390 bytes .../kafkaPublishers.cpython-312.pyc | Bin 0 -> 2023 bytes .../app/publishers/kafkaPublishers.py | 44 ++++++ Orders_Microservice_Group3/app/run.py | 7 + .../app/subscriber/UpdateProductSubscriber.py | 39 ++++++ .../app/subscriber/__init__.py | 5 + .../UpdateProductSubscriber.cpython-311.pyc | Bin 0 -> 2315 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 518 bytes .../app/subscriber/import pyodbc.txt | 45 +++++++ Orders_Microservice_Group3/config.py | 10 ++ Orders_Microservice_Group3/debug_consumer.py | 6 + Orders_Microservice_Group3/docker-compose.yml | 24 ++++ Orders_Microservice_Group3/requirements.txt | Bin 0 -> 560 bytes Orders_Microservice_Group3/run.py | 36 +++++ Product_MicroService_Group3/Dockerfile | 47 ++++++- .../app/__pycache__/config.cpython-311.pyc | Bin 390 -> 416 bytes Product_MicroService_Group3/app/config.py | 4 +- .../getReviewsController.cpython-311.pyc | Bin 2399 -> 2441 bytes .../app/controllers/addReviewController.py | 24 ++-- .../app/controllers/getProductController.py | 4 +- .../app/controllers/getReviewsController.py | 2 + .../app/controllers/productHomeController.py | 5 +- .../controllers/updateProductController.py | 10 +- Product_MicroService_Group3/app/index.py | 25 +++- .../database_connection.cpython-311.pyc | Bin 807 -> 1265 bytes .../updateProductQuantity.cpython-311.pyc | Bin 0 -> 2500 bytes .../app/models/addReview.py | 6 +- .../app/models/database_connection.py | 31 +++-- .../app/models/updateProduct.py | 4 +- .../app/models/updateProductQuantity.py | 47 +++++++ .../kafkaPublishers.cpython-311.pyc | Bin 2336 -> 2387 bytes .../app/publishers/kafkaPublishers.py | 16 +-- .../UpdateProductQuantitySubscriber.py | 32 +++++ .../app/subscribers/__init__.py | 9 +- ...eProductQuantitySubscriber.cpython-311.pyc | Bin 0 -> 2182 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 523 -> 712 bytes .../subscribers/updateUsernameSubscriber.py | 9 +- .../docker-compose.yml | 24 ++++ User_MicroService_Group3/Dockerfile | 45 ++++++- User_MicroService_Group3/Dockerfile.userdb | 27 ++++ User_MicroService_Group3/Dockerfile.userms | 62 +++++++++ .../app/__pycache__/config.cpython-311.pyc | Bin 348 -> 407 bytes User_MicroService_Group3/app/config.py | 4 +- .../showReviewsController.cpython-311.pyc | Bin 2018 -> 2061 bytes .../app/controllers/logoutController.py | 2 +- .../app/controllers/showReviewsController.py | 27 ++-- User_MicroService_Group3/app/index.py | 22 ++- .../database_connection.cpython-311.pyc | Bin 793 -> 1257 bytes .../models/__pycache__/login.cpython-311.pyc | Bin 4431 -> 3056 bytes .../app/models/changePassword.py | 2 +- .../app/models/database_connection.py | 30 +++-- .../app/models/fetchUsername.py | 4 +- User_MicroService_Group3/app/models/login.py | 16 +-- User_MicroService_Group3/app/models/signup.py | 8 +- .../kafkaPublishers.cpython-311.pyc | Bin 2334 -> 2385 bytes .../app/publishers/kafkaPublishers.py | 16 +-- User_MicroService_Group3/docker-compose.yml | 24 ++++ User_MicroService_Group3/entrypoint.sh | 13 ++ docker-compose.yml | 84 ++++++++++++ 112 files changed, 1651 insertions(+), 140 deletions(-) create mode 100644 Orders_Microservice_Group3/0.0.0.0 create mode 100644 Orders_Microservice_Group3/Dockerfile create mode 100644 Orders_Microservice_Group3/__pycache__/config.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/__init__.py create mode 100644 Orders_Microservice_Group3/app/__pycache__/__init__.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/__pycache__/__init__.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/__pycache__/config.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/config.py create mode 100644 Orders_Microservice_Group3/app/controllers/AddToCartController.py create mode 100644 Orders_Microservice_Group3/app/controllers/CheckOutController.py create mode 100644 Orders_Microservice_Group3/app/controllers/DeleteFromItemController.py create mode 100644 Orders_Microservice_Group3/app/controllers/FetchCartController.py create mode 100644 Orders_Microservice_Group3/app/controllers/OrderHistoryController.py create mode 100644 Orders_Microservice_Group3/app/controllers/UpdateProductController.py create mode 100644 Orders_Microservice_Group3/app/controllers/__pycache__/AddToCart.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/controllers/__pycache__/AddToCartController.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/controllers/__pycache__/AddToCartController.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/controllers/__pycache__/CheckOutController.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/controllers/__pycache__/CheckOutController.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/controllers/__pycache__/DeleteFromItemController.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/controllers/__pycache__/DeleteFromItemController.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/controllers/__pycache__/FetchCartController.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/controllers/__pycache__/FetchCartController.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/controllers/__pycache__/OrderHistoryController.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/controllers/__pycache__/UpdateProductController.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/hello_world.py create mode 100644 Orders_Microservice_Group3/app/index.py create mode 100644 Orders_Microservice_Group3/app/models/AddToCart.py create mode 100644 Orders_Microservice_Group3/app/models/CheckOut.py create mode 100644 Orders_Microservice_Group3/app/models/CheckPriceAndQuantity.py create mode 100644 Orders_Microservice_Group3/app/models/DeleteItemCartModel.py create mode 100644 Orders_Microservice_Group3/app/models/FetchKart.py create mode 100644 Orders_Microservice_Group3/app/models/UpdateProduct.py create mode 100644 Orders_Microservice_Group3/app/models/__init__.py create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/AddToCart.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/AddToCart.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/CheckOut.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/CheckOut.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/CheckPriceAndQuantity.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/CheckPriceAndQuantity.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/DeleteItemCartModel.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/DeleteItemCartModel.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/FetchKart.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/FetchKart.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/UpdateProduct.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/__init__.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/__init__.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/database_connection.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/database_connection.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/models/__pycache__/order_history.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/models/database_connection.py create mode 100644 Orders_Microservice_Group3/app/models/order_history.py create mode 100644 Orders_Microservice_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-312.pyc create mode 100644 Orders_Microservice_Group3/app/publishers/kafkaPublishers.py create mode 100644 Orders_Microservice_Group3/app/run.py create mode 100644 Orders_Microservice_Group3/app/subscriber/UpdateProductSubscriber.py create mode 100644 Orders_Microservice_Group3/app/subscriber/__init__.py create mode 100644 Orders_Microservice_Group3/app/subscriber/__pycache__/UpdateProductSubscriber.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/subscriber/__pycache__/__init__.cpython-311.pyc create mode 100644 Orders_Microservice_Group3/app/subscriber/import pyodbc.txt create mode 100644 Orders_Microservice_Group3/config.py create mode 100644 Orders_Microservice_Group3/debug_consumer.py create mode 100644 Orders_Microservice_Group3/docker-compose.yml create mode 100644 Orders_Microservice_Group3/requirements.txt create mode 100644 Orders_Microservice_Group3/run.py create mode 100644 Product_MicroService_Group3/app/models/__pycache__/updateProductQuantity.cpython-311.pyc create mode 100644 Product_MicroService_Group3/app/models/updateProductQuantity.py create mode 100644 Product_MicroService_Group3/app/subscribers/UpdateProductQuantitySubscriber.py create mode 100644 Product_MicroService_Group3/app/subscribers/__pycache__/UpdateProductQuantitySubscriber.cpython-311.pyc create mode 100644 Product_MicroService_Group3/docker-compose.yml create mode 100644 User_MicroService_Group3/Dockerfile.userdb create mode 100644 User_MicroService_Group3/Dockerfile.userms create mode 100644 User_MicroService_Group3/docker-compose.yml create mode 100644 User_MicroService_Group3/entrypoint.sh create mode 100644 docker-compose.yml diff --git a/Kafka/docker-compose.yml b/Kafka/docker-compose.yml index ac67edd7..f0490b97 100644 --- a/Kafka/docker-compose.yml +++ b/Kafka/docker-compose.yml @@ -1,11 +1,11 @@ -version: "3" +version: "3.2" services: zookeeper: image: wurstmeister/zookeeper container_name: zookeeper ports: - - "2182:2182" + - "2181:2181" networks: - kafka_network @@ -14,31 +14,16 @@ services: 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 - - user-microservice: - image: user-microservice:1.0 - container_name: user-microservice - depends_on: - - kafka - - zookeeper - networks: - - kafka_network - - product-microservice: - image: product-microservice:1.0 - container_name: product-microservice - depends_on: - - kafka - - zookeeper - networks: - - kafka_network networks: kafka_network: - driver: bridge \ No newline at end of file + 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 00000000..e69de29b diff --git a/Orders_Microservice_Group3/Dockerfile b/Orders_Microservice_Group3/Dockerfile new file mode 100644 index 00000000..1091fe88 --- /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 GIT binary patch literal 346 zcmZ3^%ge<81UAp4(vpGnV-N=hn4pZ$azMs(h7^Vr#vFzyh7_hK#uVl#rWBSa<`mW_ zmK4Td22Hk?AjN(mx7gf^@=FVhGdqPD7^?Vk@{<#DGV+T{tSk*IjWk(rG36KEVs&wK z3U$B573}I9<Qfw1?HYNDCBQ!@<Q9*&qno#5e6VX!m}}5VhR+})e-%4h#e^2878S?1 zW#+|%=4F-v*_kDk3i)XY#id0>sg*H~DP@Uy$*Cy{;i*XqA*sn3dHFf{>6I~wP;uSz z)Fj=4qWrAX<dPWwq7<M3@xGbKMfpHu%QBNw;~{R2NzTtp%S_iRsQkrYlbfGXnv-f* y!~=8#BM=v>0f`UHjEsyo7&sfi@Bs%;1M3Z5(FU#u?A#435BTI7ctEfS6r=!nn`Bb} literal 0 HcmV?d00001 diff --git a/Orders_Microservice_Group3/app/__init__.py b/Orders_Microservice_Group3/app/__init__.py new file mode 100644 index 00000000..8ffbc3af --- /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 GIT binary patch literal 1617 zcmbVM-D?wB6u*<XNv27fiq;R*Z9`jZ1KK`VP-=Av(JWPLrD+j{z-2OX(~h0VggZBt zh)R@#E9~o{FM{kt-QE5(lO?cWpiuD1w?N-~^4v+A4+Rm=oH_i?nRCv)_nb5L!|-qn z0o`iNl@`JXeH6+ug^s}CCV)4{K!#)?TT&%S;E)xvWmOKaY+)6H4O?M5qDBH+*oxYU zssN4{QESMKsj&bnR@_dgi2x5-!*)_l0*>t<b;OYKC>{SKmQ723IA>|@766=GS<Np4 zNMsCS&B<zvlVSz*xV}mCEvG8fPf{mp_%^jDr#+{r-t`}KxxiamX-gxzQ+BI1Wx81I zm@oht-ow8j-5bP3(j(%><p6yb?0emB&k%>w9n;gVzDnpRdL(iN^j@s+4H?p4MiKMA zFJ~`+CwlmYW0F4+bK)mrPJS<@uLi-$^?W<X2pRG&)OfF3XO`q=dtSQ$_qwX65DW`m z_9M{9lDXlJ=GQW-Yvf)gcP~S-E6e%y`*&7z=>!wC_Z33QnoS8|q5(`)(T|syV-u(N zi0a%w$>@gZa>_{2s?rKG%bbZ0u!s<f5JMtJ-k_X`1Hk;rTBYKOF-U!`WfuzTE@f^Z zXO;`=Wpf*_$!jU6lya+#(OMy6Y-?qm8mWi0m|COyX4$cvjaorFvR`>ji&rYl5!)%O zFar{h`=-tuNV{$7l>Ek=YUOGH7A+8BmQ7B`Y^CPMbVfB!3E0^vY~~ku-G4#U(SB^? zPv!O8A9MBWK30A|^<rsfslIf8qdRy1$LIgU=igp$;Hf5_^6(T`JGOU=4LsAtGajC4 zb!|5qc)E$FJv`mB-E81=6Q@0#?%A$2@MIHDdU&!OK}vk*$*botpL=I6|4kdw`DS#! zjim7SzH+glj5U=pPZ>LiC+l|)VYeuK!Vj0kFW>1{EWq%aGB@a%A97rO5)L^F4d=|U zEGW=y_eRKejX~S|iLX7g;;vY!@;*n=T7RlPUFY)1!CWkHYWKN{0r1EBU2~M{o8p@3 z^9m+p!mSovotZ_-X4fkQwB`YGjH=G_U3)M<L9_lr>@=iir$BsG7Hx2}=q)x5su(Qy z1BkXPNmBa~lFoVPY(KZq1#ggBXs8}M2WZh7<Q7`+2DycP^#-|x=Dk5~q1)adxABNH L(njBk;2>WBmA8cC literal 0 HcmV?d00001 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 GIT binary patch literal 963 zcma)4&x_MQ6rMCmleXKfcu?#?0}9&1?j95tbyb#1{Q>SC+(ih1A)QRO*_~v<WKs#N z(1SOx!e0Cb#6LwZLct~2lZfn1=xtBVq|LU1q7U-&y*FRpy!YjOtk<hRSo82)?}q}w zHyIRGnt@42fFs}mPaz;sY()WH$x}%wP;E8G8qosX)^n_ra$wj-j?2UhDt1L+<2A6W zsoAQW$f7MJ(>uhC4^G6LGFsa7ydBzh8He3S#5L5%=zu1(u>KGe%<=r(KvOD`)e2Ju zkk90ka7Td4+PU#!67XS`dj$@`zFwTq-@IJlf~owCY5q4eS6H(DS##-6HJ=NCwps?0 zqh%(9p&MWbv-1q^`7y@~c1eOG=7*fgiI^OL8PdrXg_x=vMX?;*I!)VmoZT3+*y;G8 zvm5#YfqkA@v}eT$V>op-y@4Ad>{%~x*V@6TA5ud1QpcU;S6<@oO2p_sM%>wEo+tpH z`G`?bcHkonA2FIlHyv@Q1EC-K9KzKo&8moDmt!dMY*{oTn~NU{Hw0g+jko5TwPE{M zGrnle&sy`{#z?y{kM54N>+|T|NNdfb^^tb<xVAieIuW(NR;!ljJ-J#_y{;fCbfJWZ zHdoJ<tbLZuCCe@^vf6U>wiCWUl9FcE7D>~E>@XTU;W${JO5wBLZtY->`f_y_SaSGW zh4+9pB(4j0YHkG7O9;NtE{IV6vG|g3KUGCh#^B<2aC;2a$Kb&j+?r@*rICO73(yzm Apa1{> literal 0 HcmV?d00001 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 GIT binary patch literal 413 zcmXw0&1%9x5Z-9~!A4rBr3azpST7>&p;$`6#?*pnB#D)V1xd532IH=5jG*+8dmo^e z-b){(_Z~y8eSv~EPu<jZ24=pQ59ar+SS$c8AH9pw6Zc<9@Grt2*qm_i0uZnO5-b6w ztQ5y-l(s}9S{alvKqYI&*%qV0{M>y$1Yn)3ReyC|nA)SMeOa&7&$^XtoN1~z{Z?Es zR7F?KVOxEO#h#{{amg?nI!`oi+l`^3b&Y;U)noBaGt5}pWeruoSM_(WN#@$VDwnYD zW9CD9wsIy=Be==jC5BDv1T#z)KJ0Op65E4)!U^WPi<L}AvJo(bS5Tn=^RYajYziA_ zX%hz{S((_LhshZGvP<Lvew0n@ObGSp*u_577~*w?9oJ!$_g=aV9`4qL_IwT<N=ELu zI$v$`S2KzN4_`Bh51U-lKjr2-EeJxCm%>a`JPHd@ZZ8z0<MJmcMY#hG_sgM_C`-Qb E10#%kw*UYD literal 0 HcmV?d00001 diff --git a/Orders_Microservice_Group3/app/config.py b/Orders_Microservice_Group3/app/config.py new file mode 100644 index 00000000..14dd5932 --- /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 00000000..16ff26af --- /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 00000000..1f2d33b1 --- /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 00000000..5520377b --- /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 00000000..2c6e905b --- /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 00000000..804480e4 --- /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 00000000..ba1a3939 --- /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 GIT binary patch literal 1337 zcmZ`&&2QX96rb_8cbhD2K3dW&H9~wCC0mJJDjHR^joK86G$=_6D@&HMGrRHPua3Q; z8@$pYAwEuoQ-j2zM^HHMe{eBcp+-X`sNlk_Rf>dqV#d2pRHTmVH*e<s=Djz+_vYuZ zu@Yco{rq_I!Z85;<cnfRBjsS5DR%(^2ztPWb?6Iq!58bIFV!VquFH_y1W)nRx|-{v zr`0t9V2C8F?+HUc^%5?%PZrLPW+Wq}1%Ffv9MV1mdn0rGSXVUlzxm3Pseak(;E1?E zLe+L025z%URf2DKaGX$y?@%?yaqNbH3F)+hknJYex8uz)irk=OHyn~IQ;AR8`dL1m zWgsf8+*n;>CsZFNn<0uDN67&ovxUh1gMXP|EWjQ}U;${4?pCb%T;$$^DQxr8{~Jiy z8=db7&q0WX2=O@x=@22M0+CXY2&vSsBx(_iv+BYEh19073Q~|VR4O9vJE<opdVx*l z0@qWHJfupoy9!Kwnd%9n+3v)c&{9M~)M+HPi>P+H;{=JDbZMy*xQWf`)4){5goI@K zt(76rxV|`N6u>#d36R0TMh-R{f(>3qmta(LcNjaSM3r?G>G~qoM=rR!&d#jl{<Zf< zQB9d}j;YqdiJiBA$TY%xmuO6wDph&TJXHxfi9^P@slvqzOwe)O2E#t#W;(^&=4j7n z{p7T8%!xII<LT#D-nMvlv31oAESA(3(-{Ls*fin}A-HQ@LR(JIz{t3TH;gsh*bG81 zY;`SXv_Jnb-k4`Bws9k|ZV<#A*zdUw5;C`2j6nMu2|Lj_%ZVbZ5e5kfJ&y;xgwR@e zg=Jiex>PGVoK#tMyqxh46MgVV0hO8lwZF<I?w3#hQa(K>SNn_m$EWU|`sUQ`+~D}@ z{de~(6JOu?>dtOyP<f@l^sMb+dFtB_zMsj=3lA#OyK46GdUo>WpmHnw(8?-SrdiDY z#LWKG8U9VqKGx-FrN8`S98}N!ba60yIg?&|P(G1OyfG-7nPeWYoPaq-<)-Jv9})hT zhV|ivBMKLsT{_7wTk}JNy|{LG&%B6K8@=+FYPKCXKDKSD=0)0wsLZHJaL&OGfV{;0 z%`)*+TVT#Q9==FkV@v+#;&+&MBti&(2MfP~g?|(P&;JH04@(m}S9g~NrC0mvA5i<E f`f2scPww5kx74o=;QV7@625sL0-=^`d4&G}{X$@% literal 0 HcmV?d00001 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 GIT binary patch literal 2297 zcma)7O-vg{6rQzry=!c27sn<kIN4B;;($UDD-~(eRQxm%O$t;bMYY_nHai1s*dJ$h zjY?`%SL&gM9-?00kV8&15j}9J)MJl5?xK~jR*Dp<>Y+DBX)ZZ+W^D|nLdtmj_RX7b z-t2qxzS&>8ySo5s-_KuKyvYOb7ai<3wxzs!Oq2}(0c13wGet%Z6+?Qs7}nV$t8+z; zp>rWEqVq*Q(8HRbM~l%wXSJ?kR|p^mawxVH0$`i`o2?i}@h9E;qr*=af&3EltI&yu z(I3DTfo->;#RO#MLB8uBYRPkcbV943GFA=S=kHslp)RiZJVp;H$g+KwT72F@mZh3T zp7FCXgpz6_U9y(Va#=N&Bt^zHndw)Sk+LGmtFo%e_f$=_*Cg415^=4d89zD>;T?05 zU>_z&>5|d5!Dr`Y=kE{~ypHT;6Ix39Wr;#k48r99$|gzJ05)?ldB3egW{c?C?eRLW zxkEU*K4_h(SZAutllGc@41L1T5r3g$k>MlA@Uckt2$HRaFk21dP?fEv?dZY&kb@ER zNJNld49x>Oc7Upes^KbI1zV)(w)YDUtaDZFn3#ml{c+}4WV91$%^ZHaV^?)`t~wSM zdrMrr69>B=AIWtyCsjZ)LGlO_kJ<G|m4oq9?IcwrkiAAm_94ntBb|QN`HtxL&RIg0 z<c!Z(EQBQ$`q4RT!ir)~Px*0L%%4|e!zQKfNADV{Jx6QZ=Mcswet5YB6{n|0#0M?h zh)6ggRtQ!Mh#|@tiIi<BM(~3Ah*YB=ZE;9Les=(p6cb~l5Q6H2i1HHhd)g3b-?QJX zR0ztjn~ckcaSsU`XQ}8VBG3AfyCjO~DV(IXcc@6w2_939`QasGW6By|Aeuy(k7-$9 zTA5fNA}`<sooAtJ%S|uTLEy?ys>UkW-Nb8Ba1;0m%JSx2LGgZuUL6OvRwx#AEVkO4 z-zGmO(U-JJvc9G)mu3w#h1FG5nlhD&PTX6iIWlV+vQ{DqUnM$8zGyCr^ECLi(xh3z z77`asyiyv6tFoaWC{8ZRnud%eWQnRFE}(nj9i%K9re-dw$STcZNc>2jsR}m9-mByc zrJLBSlnW)fTrMf5VPlgxAaB*avnJcd3*|LmprO%Q5sM@m%27)vCs_lp1(3}Cw6d9Z z6N6r2uy*tBSdSO$b7MI#ma9$GQztfrpM}jnH#Ov?hHBIGbnnL4&tsc2ZhF{D57%!0 z57CH#c%}gu?ki^VcJujk+8O!ic{01nJ7@1Yy<fP=1uwbad|7gmB}XW|j)306&eh+w zKc}6AuidQVWu@9I_0zW(JG~n_z4@&h8}?$u4Zv}!osahlH+Bm*{`k%<EO>>5z(}0e zGlP4XbGw;yPfxj-f|n`O2QKXmT-hDC;=KQ<J8;VzxK+=M?By=*<}U7>adYEdZoI*> zC%YPeh?js(#r~zDA%N~wBg&>yWFnesBtZJzdge6kCkGo*E*l{`W+SzkMhd)ld1urc zn5fM>`p{+1kT`OMo$GG@gx5deu&18KdYtq*H<tHed56uvB3UO~^|?h&wpK8`@|)#L zOBzS02+BOAn-FQ%h4xVfrS12(%#-vh7Vvo7fcxwYDBugNucGA(l4Qs_k|aOgb|c*@ z`y8nn8wEx14B)eL&oe~45v~#M6%Ad-=gE+Maja)VG{OwS)WJ39?fMH)a5{S(eByNW z7a&;+elL<Ie_Y$_d$Q~%N4?}|Elv(Rl-Og^yG+_SF|-qT`i;Y+U1rQ<#u}j^=6nMX P@iGiTS34|$ISA!H&)Yin literal 0 HcmV?d00001 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 GIT binary patch literal 1911 zcmah~O>7fK6rNr0Z*0dV#tAe8mH-kiA)#1Qfu>X;5y&kKR3xBUmR6gcNwQ(RYi8GJ zO&!&Ts%JQnN*sEm4Tl_i?6Fc0wPh+tBdY$;3pYn;FPu8F_BvE*)RA}g?YwW^-+XWU zV?5pm==k>1_|i`@058}_IE1dS`y~|~0SF*xgCdvbihQ0gM)HxOkQa(#UgVgLx22+- zmjgLsD@8T02C`uH<@<PmI4Gj%Cf~7{kD=J=aOi074J9Zqb5E5J2h}gYW>=l>uLzmG zm+UJe67`B*MkQ=HK9N^F*Rhr=M8@b|8F@Yt*b0$7<aw6sWH>TtK&V?jD(c>fTPj)3 zvThpKr<x<?3Nr8N#+qT-#-e3genmGNs8iD>nj`8og!AqU#okX$uq_k41tQ$MaciEM zkc-G)aiM4K<pBUKCWz2y_YW>89=8sBDs{$cw+!JodxvSRb5(9td|lI#A-~z(zs~Q2 zi1ZMVeGozqAyj!RR3n(L3blmKq74QVp=5C(3d&3TE#Rx6w#ru{Rbi9mMaQ~W75_6* zCESk>?1NB4gm-z*_deLZ5W9~)`ak+usE6^#y$W?Qs{)!4tpe<SEUZga5ylSFys8ou zrs&&`vMkxCN}-K)`L%fEaP=0*B<5bS<00xz?836?=VnQa(dMJF;rNtPL|t$!|0ZJ< z5fR2NzJI<8)pE0A+PyArOrz}6$`q>w6x0liG{$QSBRFn7piYR|Wvh)yJOJsYi!m~3 zD-<c^jb%gzdJsLdOyXvlq8z`&?Mws@(17tEn}+C=5s0+lA)K4V3AT2CO-ZJZFykXp zmXWUqofV-HX4eB|)W8Y@DMT*Q-MR&d01e;h7-9PZOC(`AYt*@mD|*m!q@T4@rzshp zq*;&dt#vc;m~pK;UOkw(RA4cBg{ziRpcP%CGOe!WE@>Xiu2PtWYldSYsNF$}+B`B> z9M^W2D+Qywe)bczc(#PyRa&pY4GgIP{X@&dE;YMGPe;Fo-Et{gFiNF@={i1kZJRml z_5Dn5alBL^3X7WEEciGLG)^BcP0y$Xe(O)vuKgJuXhnw`(cxxvq&B;qJord?sB8>3 zlc#FA?bOht$%m60bIsJ5+Vy|yb|er>e|7yyu0Hne^TgnWTtB{0AG+O4+^K(Ds3!__ zrSO*ohO%21zq5bHH3x6kZnWu^;a2o$BYJe>vuDvWTko~9R~y-@-+%rrdxzTCPM>V0 zPdC!1pB!$cv)iL@wMH*AMlaOge!n^T!S={lYvf#G<lNS==E(GpEF9|F1wt~~RzN)2 zR)u7;4FomW?gyziw$n%1@6gE|RUDLRbL}KJaeix}F?yvo_u!p|aEwMalHI!8JaVNj z9DW`hsHaXhqnWyp*`?K?okGMV+wksUc8zpc#OQ@3HnEF{9Hg}$FS-!f-gvL<0n3Q? znrepK+(Ac8J233CfRRM${u6ja(RIftB3&o3o+*8?L_~VZJ_-))8-PcdZ;ei`lqu@C zY@^Hg4E<y+?d9myj&L0JE13EjO#LkZZt@q9djS%^Ck|~4f4$O7Ow?kuRD6GnOEtJu d{otuB>B*;cF4g2FclZ<Bo4XOfUks$c)jy6(<U0TW literal 0 HcmV?d00001 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 GIT binary patch literal 2034 zcmah~O>7fK6rQoY-u3SW2NJne%DSN~uJ}>f0^&y%B}NG#h-pAnmaEmWGqyKg@4B<Q zsS-I-4n1(-ke-?Y2cKvvdf?ClM~)oVXeF$bDn+U|a5Dlfoch*@9So{Entgun?R(#w z_cQC?Q>i$D#eF|hITuCfpFkL_$S(701DM|sK?LilflIg%Duo*1Qn(Q*MR1@G>0BdP ziuU=i&NqaTfKdohOd>RPKZMW&cy?APPUG#wKzjF=a3osAfAXXDMEC{W2eSu5(^8Ve z7EwO_BGBX`e(Zwo&?eIi+vgem$)Of7OO|P9l@*`2sAXxUk;i^Ytx>gZI<~AT%m&3& z)48o{R!wd)lQ^m^J58e4l*n|M0+=wcUriqmJdO`!KT=#+ya51wgW5HdSnBX>!0_;d z;d$lbplUYI!CD&f1m6e#!BAd9EoAMtxq&5unzj%L-wTb}kw_)9i0mN7?phjj>Afng z;TC2Q!nN=+X5%BsQNnBQ#V105+ros)4uH{G$bP3!Ez}B)c4jS1qOI^UV%bsj7U=g- zK8O_SM+&!xxeo&ZL*i958l`}K{B$kSijc$}CP>LWiKOm@);K%0htuLltA^3t>5((0 zTmKbbBx9rT$-WPIkO?x#k6-h7$D&Nu$ZF;$Fp^=~l5SS3lt`M95BVHr%w&EvczLOy z{R$cTyg~?rkz{E&?y7WEgXuJ?QZTm~1ILO+bz+^7cFnX6aME4}o=MH74Vh3|(R9m? z6?bO#Qo$FlJBndz_DVj)GJxvu8z_nnQ)`Mv$?Cz`-PxB^v(eNkOu1w^stPBmIJ&;# zr*1ICuoTsXy8@W}O`~p@KL=UBkXx2grR)G;zjy*9&olT`AU|BCHVa0U1vBUiAj-kL zW5IYb0Z2Z|g0}b(xK|1r3s`Y*i)1K+quYKY$jguS@0=XiSpm4zUvK}KJyQ<KXO)%4 zidri#7_`8&Wm+zns?&g5YL$!d)-)8oeA9pz%z{ElW<^?b7^5rYS<_(_m2R1=UjB|O zD~1Z0&(;)Or$&`p&?xB^y)E6KYRxdAc^b9K3yc7cd{tAK39*+omCAF>bedn6m1eW7 znug6x0Dx2V%evs$vqRmn=87-Y6ocqg9;C`7$S5d^bsjpoj-ICv+^uisJLyAS`q28^ zb|TY5n7fYu7AM@?iN{~Klb2z4#4Db7<;kKe7G0tEJdyDdA9oT{USev!&`pSe%N4wF zx?OO`55orMP2SDTx|4;Dc+nFtKDJ!(vMXHPPG>ew-!<3g-bB&lq4wO?t<J;=Z{o!I zLNAI0apSnl=V15!+Xo*`db!i?<e83m))UV@g6QX6;XGLGlb(%DKOLKHUwe3=Gj_@w zJJmxR_f?<ViEL-5HtSyY%Wm$o_L7&I>2cwScn<-&6MrM1*yrt~jxgg1Gj4xFHr?@W zy4l0evPYg~k8H`0v`%*3%g%$}{wVnEkG@3VB>y@f5ImOb@!@0=UU11*P)KwwpYpki zu2^*zd~Ev@xHF6W(G(jdp}KW!(4YQD`XB9n@S$_Z>Pn@q6nFjrK<<yLFUYc?G^i~5 zi9zq=+fAQ?=G$<=A<!R)<$`zzfxH#YK^RA;-?BW2&{|||0_lY@#$9yM{lDEsd3SVo zQNbPE+v&+W+Ge~x-$@_!(nr@5+c^0QXP)AWJ3hTt+4{l7nGQbb;gh}4Cm1RO<YgFz MPK{{#>i)_91*`-T^#A|> literal 0 HcmV?d00001 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 GIT binary patch literal 1688 zcmZuxO>Epm6rS<V+WV6@*;HMYs;#2}>Y^r5fu?GyP-y}wmD&WQRncmZ<#=W{-gxb0 zY^U02Bjv!MNJxYeJ@l~0pd!&@j~tN@(ymr0tpy?oIP{j1oXUka&YA{^kvuc+`MvM` z%s2DH&`<`!`0>tE^;-?0-?@+sX|UN_gUwfnAc7s#z-8PJ%0fddiw&tPVXhY(xsfWT z;=Sl74YjOdBp`~3MAHw11DtY(X6l6m{KZOSlB(fvl*EpxpP~nY-{o8@UCKP=Qb~%^ zSDcVGne7IV!ssU<^<h)@J=d<bBE_e^Z+mVDM?=;!wN|_^Ff5Y=pg7(PmmJ$)Hk!;M zp%oZmlb8V|23@59rY81l!&BU2Dv={;VSe!@04NO_EPKSaUZjnX0)hzN-V%=cgV#|T z`C0(d!5{(=ZTw&$6R9dJqJVqEqn`9PQNWtiy^h<MNknerRm}d2m^y^0aKttyauIyj zg@9)ik2Y!xNk7*`BDBR-#PWwTYlD`19YRxMG_jr@fE-##x`q<GS@iKs5KU@JB*PJ4 z&GMDx?hEU3kWJj$a#A@)pT8`jL(zxY{~u+TXh{?@a$iXN$tcgPl)v$mw=$9`V;)<} z-|{KbT`$lbuU4Z(w_W>7Fo+bB5C&ve)34h=3Ad(mve*nvsy20qe^DP;*qdN)?{lY| z9ngkBXkgloAEg%#i1NW~q<$EhZeRzklE6lJ_|ZhM5Hf4o^eI_8IWr)fZh4KSLxEbl zA6gb9Q4JlZ6%E~Frt6zl00ae0<(9kRdUxECz?tRyW{t8Vfc^A)m`W)o!@@W{BDF>X zgHxRGvyDU$nHn2KN(l8EHi;zQvdQ4~qDV`aYd`}+Cx|3oR+Nc(Zg4w41$KHoo_{fO zvBI0^SKhbX$}QJkg*{ZNdsRrEG1{uUOIA(Sf^u%tCH*F~mR%3J-Kv-a{lp!*Gy%7& zPOYFa&j<h**KLb=0J~~i)R<#l*nG2MHk%d8a|7l%4i6YNY(5NT{?$!3TamVGy2PPI zQU%i?SzfOHH%uF7H-)s3jkzb;{Lk9adrEiwT(>aY*Ump0>uQ&}>ZL!j`R(knUiMf& zdwgT|Nmkpu(3$OxogP@vbPKb6?Y-~(u6C`fUfUVYZ(jJ!+nC!=p~5Sjxvks%qvtl} zA&9DNPW6=W*sXK&VWBsEp<B4v*WP}#*wrp~)yrTrs&9{+>W!T0+<17UKXU#rB+GBy zm3E59@2&KTuRk7twNvknpM55aM>BUb`zlJm)~Wxbp54uY-TpAjjXfTF>v8e)cJWNF zcxKCZWcQ0#!TLyQ4~aPi0;F@hikQpoB2mumLHX!LX(*Dbj_I#3{)of`IiLzZ(`XEO zJlXIFb^OVsy$7s0!T$`NKxqEtidkJT7Y?38kYhqcs$sZhgBnJZP1<iPH6t0$FMxXn z5xz!joX0&0({uF_gbE${4l98OHwgJxVA>Ti#=oNJKAQdoP5g<j{x)2=m+4&X4^M1l kcW`bS=X*Hc9XqvE-TJ7D^L;%1OgMpadm<9f$GbSjKN$YT7ytkO literal 0 HcmV?d00001 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 GIT binary patch literal 1309 zcmZWo&1)M+6rb7E?n;qmIf<R7rPNy-N_B`$2qYw!gjROa5+^CxAw*retanDz#`~en z><SbV;zJJ&80tbHKKkUgxPL)UKK8gOf`)~Fp@)*2is>b%yxEO}l?*d)-+S{ue{c4e zQt1SO^~u_W`o9uF{|I5Ya&MWVAAos|2qM@;9<E_5c*&JKxh8wLTFz5yil^38PpfGd zNr=isrujXHw+|;<wE`{drn!ci;g{ry(!jr~<Mu@R9_@k2{?H87iX^{^Duq`<Q^Cm$ zp)L)n>4elX>n!k0+hSowNeW-O5p6NY4-@Sn4}7QINi;?uMU;n0PG}O1Q_dY=)GWy3 z*#+UekVy-R;CodlvfvK6mZ(e1E6Z!kkXQ3)*bE4_@u)O}1XePfqXQt%QF!d`;fN=A z5BU9&`~-I~KOHLI@^%r4$j&=fBv+SKQK$`V5bEMC8b|AiM5M0NM(pJAXkBSMA5qds z$MU^rp$dzNb|=vyPMPVDM4^lY?D6FXL8SYX5<Lv`b*j5TqXB~B3ps;L7n9(+7=<1- zsV)GVcYcC)ou7fc`V%^+<X9d)iQJ$e6NNB=T18GKj>FAL!bWA3M{dZ4g|6$b|EOLy z?m<=Du)L1lH17Izi8*a*ECqJtQ9tCyH*g#HmTTPe;ev4|?C3#VUyT@}9itjVj8px7 zz&4C8NZayl=%CuPT$lO{%0)Bx>AJo~?WP|<gAV1!T}B{|dE2pB0J+<aP0gDuh*}p7 ztJN~>zz<mf0idd-^gZ5y_P+)os-v6vRwpTD5T);lO+!Nh1s(#~ME|R(d}eE7r_!4| z*PlGMdGoM%YJjk^j$f9~>}c_)wfKW?du5|vHsbHBxNOCF3w$Q$b}#?B(kor*m#%Ey zIMgP$KZ~`qu)%A){p{)1(_J|(&&Bz<m&H@tm!4hUy1rA5i?eZV_6YK#JC%v#BQJo$ z_<UA+S~d*rwos;nNtC*4@eL-PcQ!6naN;dybIhBjZ+X--lTsF=D*l@FR-yn#Ax&HT z4Y3*Fa2m+#{34``TzZXt45IiI_>VvaGRF7?T8zi{`<izQM&jYrhuejn&v(D-O`Y#g xo!=}C@<=NGji>*@)A7uugR=)GVm#f$xBB?jK$^h%00H?=M$!r%Q>FT};5R<8UiAO~ literal 0 HcmV?d00001 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 GIT binary patch literal 1068 zcmYjQ%}>-o6rX9g?ZUb&K~PML)Q}kW031vt65<C4Y6Lt8G1kVW?94*3AL~qa&6+iG zFkZZ1qLCv<4gL`xO}vy4V;nVVJaN<DiIZ<yKql$y`~1E4ew}_O7TXb==xJy5OAeu5 z(%3s-r)QhN>lGr1U>^n8!dU8xuLP>4201GiXqFb}mL3?Efsul!N>rL(SF&=ejkYcI zWcoo#aztCeZ}q)AVmv|Xy9rjInJ>3(Nvn)S51~GdspG{oaH=c{oQlihvL@Qb{5q{M zFN}q;#G}xwHig0H{W|5b$VrbdIOW^}MbAJU_6^D6q0AZ@h1wD6$iO{vUg(!6rY2@5 zpsx|ocrhZpf)C6sSyAEHZh-(+@FU#9ycF-}5QV57Uf;DzuBzNbv8+f>3%AhT#*Y-D zw3G&7#sAeUWxrBOEBA2^M06P`8#7xPU<!>g7O{uJx1+ilQcBD?GUuu3M+*yJc%ihj zbxp}2HzkE;yhu&C_@MV3T6ix&Y`q7#vce=PlM|O!ap)j9!l-k~9FGW{QC|0BF0)M2 z+<7@ZV$VU0+ml{s&xKwCbT4k2QPt#i#%R;NL>g{bfr)O>d2^Ol7Q+ZeY})Rwf8YU~ zAE>ctiB@9!1|tCAOnVg;0c^voQ0EGZ>a{brTdUcXD2!R;`?BHX^m0tXPS;?&@%_kP zttkrG-s#6>-7xE6c=#NMW%Q$?w0z}rq3dhu$f}W?w34HDHcNJL*G)=pl6U{=sH1;v z`1RCg@!ay{52It{)P~Uu$t#U#kJr?s)Su-0zZSYy&OW=aI-V5zl3d?50Hc}mA#nnR z91J4p&Ihyk(%FFSY3WSK6<XDI`8_5tR7SZjHA9L#2$6T3&<&{Lh+>8@F7N4lO=v(w zOw)bdASQn;CimLOk3!43PtUXCV9JZb$3Xm6F~;A}#qVhJBO3kLd2IFc+SSd@f#u@w m6G$n2!rdFVJLx(5uJ>Jgg1a~I^*>5GHn&xzOyN{bd;9~*Y$X{0 literal 0 HcmV?d00001 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 GIT binary patch literal 1242 zcma)5&1>976ra(@O5W{SuAL?^VT(eO5<zfV+>qJ?hjiVzp)@HtCLjbt(ad@k>tj2k zb=cs-QVPi-hlL#C<DT3W=a5UGe?w1N*n<%i0wIUqwz$3I)HjN~jonM1X5P$u^XB*F zedxz(wTyrUYo9bq3PLZ1a7Z8*wBLi}DI$pA5JlL=kz`AeY|D{iE0JoeSe!{=Dbj4M z*vp}A>k^`vD0E^+LTDG}8?wu^+^-x;Z?8lprFHyFJ8Dn#AJ7h%?T$_DcZj@-tcgE_ z#!~Z%&%-utu^>)!?H*6!pwY=SM!#)Sp5}_s<Qk`(2T5$<d}f`dZkto)`W{Q&Af*w% znJYqgpnfElTweL&HdtyAO`8ef{@62YRG2c%{ojB+MJa~mfbNa=1n<CpcPxL0wh*65 z#oYrU5|M*rRzzt?t0>hDZ4lf#hJ%T;g*OqKJ&Lsj`q}Zd|KO?x?pxlsj(LV`mTu-+ zk(GetDrGET4^FH>mdqQ=X24C6&VW%e7xW;i;4fg7!o*W^84}7wt1umyC9$f|P88WC zUg~jCdeeOUOMTH1h}`j_j^A`{#dMhko77oO{B}g+lsn(RX%c&(vlhbv<3ZXnlZLt4 zW{h^6deUZ`ns*Ym;anq|UhGq1)|*}!(s-S6Gl<PQ^safE`pq~All6dd=N2P?<9;3Z zECJt}flu8Pmb6>*j@N2AeiElF0RVW_b(;FkI@G^DR?f9LxzP~%e>;XvLpY~l^83KL z=<hNzPCnk)wg!{uhLh*ID=#Y3BZSqfzZ)mFwe0NW?9^uiV_|44{5qc*OPRj(YU+dj z%3$i^aOz_B#-29Wvoh@rjN(Fn_NU9kv-8=hPY1@Op>gRs&y2-PUwl=W?kx-|wPB@} zDYboYjjU>}HbReYFwu~2N+62NN`e)&nTirZLq1o;_7%id)F{^v{tlk&t{Zz1b=_Pm z3U;@ZtB{_Q7GeI3*o?q>7uak43V^jky2Q?aD0-Ve0XC8`#(U^W_W#Bn`Zzl}_K?vn zzR`!Ma^jKIyT1M9pnQH<KHt?|VEtk3``V-X{rCD>w>H2RhWNrrs^a%Y2-u%8lB^?| ILR~!iAB~JaJOBUy literal 0 HcmV?d00001 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 GIT binary patch literal 1079 zcmZ8f&1(}u6rb6T?545ZQmeIS%8Dp1XgyR>ODSr#wTSglMOXsMc4yLV+>bc3siZ`R zAby<8tv&XrRK%nBFL+4_qKt})Uc6cAsV8T)X)HdNH}7kHGw(O=U3YgE;PUEGZ}F4@ zzz^Z<2=`OjT;kg@Kmfr2gwTeeWJ{rJ%b{W`p=zs8<fI@IYPOcza-iF~1TaJj&aO$@ zFm@O2Dh+JgyERf#W*)xOcIuG+5UjNe>^)W4%Kj3brLyd$pn}W9j}oSpXdL;)D$@wQ zTfsD8iij|cVoLouvLM?#j}xatF>ySXB#xipkj^kgI7{j&u`zk-%1vIWg*aJ=5%qRI zOXZHt*XCQUmO;|VmD>Gu0^BHx>i-16HMkwR4{CrKiMCUKBqaNtEK-WnEJ(6D*&67a zgGj2uML_y?pRMueATQp9pr!~N{8|Tl7Fd}Xrll<Sh^d&6m@M_*;;fj{mrb9Vf<B*M zH0(F{YyCf5St=3jFvTVFl*yb%B1VDeTv-z77P)N7DRL8+3OY=4t1&TJ5V*83=|_cI zk-x}oKdG8=(WDhZaJ6s|ExM71k$D@>nK!Yw5XC_}UoE)p_{n>C?qr$7CF~`I8w7Cx z=eqBan8Pmm9(JZkTq%zf+;X|##Zf}yAV@F7iMKGpKXjrK94=RxQ55liBS7}@mmc7Y zE^t)`e=@+>|15YKeCQck?-^RDwtB4k)c0K9XJh}0);xT+IdHCJoPRUYG{&3y_|M)W zt5dDs6ZPqjT2I4T*AAw2tAo$at{)z04xDZoXI|5$G1}Bef9Coc=UcgaQ^{}gyMWcr z)MDV$J4B4sHl2cFk`YRL9P8&@4Tmwp0Ue$c55LA6N;zkGd&Vi#9Vc=_>^MwIKVYuR zRL)6))81YH(l7A(xZ2XkI9MgX<Kz%`#U#=TT>X|IgkQnfdocC|oc;uijbk9!-<Vvv m+Uh!5*S<mhasEO6$-UKmt6DwZg2y+c930w|fn=ptdc$8TM-mnQ literal 0 HcmV?d00001 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 GIT binary patch literal 1262 zcmZ`2O=#Oz_&v#roSN8ayw)}JphCuK*iuFo(qx@S>yGTQW}6$58i7#to?|tVp7);Q z;gUfH>!tM2otooLSx0urvBw>Ed@hC+K_O6b=q)2V_0&&_W9pQBy!Yw*f8U>epO`p< z04}b4+I*-W^eSOaATuD2wt#qo2qM@+K5k%NX(+zhP;nwtyo|3kG>jBPF;VH*4#e4o zdkhVo>c3@AxOcxKL$r1L=P7%l|AKbFY<Fnd7$?~}s*Jx*Bo#Ftzu`r+&D|i3^?QN^ zZnGQff(qfXpn~IKlZH;qVw_NJwOkQ0-i;?l*!%e_DSzcetuB3a8(ejthAl>fGkhBe z4Xz6J=sBP#D8%p?z`Y?&@D9+sL;feUi9|6>d<Q@jqPnN7NT#XOQK+BTAn-aB2NPuz zcMva+#@YmVdFb|DTrG|J?(1Wl_&qB<v8rTm#d;*5S1yS)$~oirXRb$Kiw2?V*da94 z;Pi*c<&+p9GdeE)(MY>z47xYt{t9)w{{iAjDX;$qRLSt<`B+`2Ax{>Gk0nxt=Mw4E z$T%!whqg#I#xUMIt1X%<kd82Izw5Nj<$&JgZikvTnG^YtlrX;qEemYVTnRwIg&TGa z)->u7=d^3qSi}W2RvF(guak})IFNX)WqTeC)~PVuz*wbsjoZ{|1<YgXE*0i-vMj>- z#&tM@w>z#wttHN)_N-~Q+or>UkTVDXS*505AFowyD4%I})7n#%R4N_-+Cm5UbB{K* zE4}=5KR>;-w4a+gL|D6nUlz`9>+;ffvh;ngQ12J&a%D{x)?{|=p#1UE)n0k7U!Ieh z^ZR;UPEAWaIRl^By`}!8YqIo3uTbq5s(-1nP?Oo(L2l~tvixvf7O(bl3;o=}vssy| z%1reL5<#~rXJW1C*<ynyyL>#6bU+{Yj8IR^j7%gQR-Co0!1k$S#giji>ux*NpgSQ= z%l!lKvq{WJKyR|wAYSCrD!%}1@;`{50UfFs;}_@?`Tyqy`b>_V{o=*P3)|MyR<AhU xFV0IexsT8OgG<kGNnW_TH@EkZ#HAiy?Bm5lC5OK}M1cNPk@ES7Bo(JAz6FG>PObm| literal 0 HcmV?d00001 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 GIT binary patch literal 606 zcma)2O=}x55S6^US=+^gLaqVRn-4LC+)5}kf##B=h13+5h0S_3Zk6g|J6bvHA&?(Y z=uas9H-=u!o(etnPzdCfQzXYV>@B0w)6*L<ANnyE^og_Ue=ldh-1)~}{#$2F?hYOK zP8eZS5J?j%J4r_dNg%@{lu;5<AM1!M87J|I2cj!`NpHnN(NFp;JSU^*uTMCNn%<$X zP$E}V6JHvw_^fVXgs&D%)r4MYVgtr-twyvNOiGql@E$d@MdgIuLMvk>WaXoj+0_G< z!5ma|HhR`XGm)Dw7`Sp6dWbx1d59e}J5n<cX57k*T_1X3?9>#<r-1G7`9{Z{f7o3& zY<`kEcPIDXj$Wk`18CB>T%{Am=Z^EL9_rc9SVXAPH*B7(0@&~)Ootz!_^h<hpXxMU z>w8x)-E&i2LQ$pfkhuieDKAjFv~ylSc8uDV`)OX5sr!TqwGh5wYmTE$U|iPs-2*qP q74RCLyC$jI=EA{kKq+04gT>Q)Nydw|FUiTG?Z3(P&1T`YEAjxNCcmHn literal 0 HcmV?d00001 diff --git a/Orders_Microservice_Group3/app/hello_world.py b/Orders_Microservice_Group3/app/hello_world.py new file mode 100644 index 00000000..df9ab9f1 --- /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 00000000..c42090f9 --- /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 00000000..b5df7171 --- /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 00000000..d047f9f2 --- /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 00000000..ebb2581f --- /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 00000000..2ca2a679 --- /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 00000000..b9bd2df5 --- /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 00000000..a472d4ba --- /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 00000000..7cf5b4c5 --- /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 GIT binary patch literal 2562 zcmcgu-)q}O96wo-b53n1&iX5H)2MA)YL>Q?!IpH{k1kHOK<2h{vbLEvqe$mOjV!q* zIf*@Il(C1d6w08`hcW0=M#%<w*dI{(>sbzl8bP73r@a|UA@phAvlFLIHW)44>8sQC z?!Mp8eLvqjo%Cxc)QX@S89bRD6A=27H8zTGU3u0I$}OZJjWf_Bd-@D6<D2wxOy><g zBTNc4T`<Iqf6@=S_yd}3(YPdv`Tt@ti5Ta#T(T`wPv@B$C#s%N3{YED%QT7Vq_ioO zTc43VFx))c&*q@Mg#yTVX><t&mf^0KMXt!*era^0AE7OFK8;)Ci@w_%%r*@{EAmBP z*4gNT7T?qonp)y!D=jPm;&KC(Ll6&(eOqac2lC|CT6C`HqdOrg$p7}T)uYJKU4Z_d zY?CO74k4$u!gb_J{*4)W5xu-9IBgqkgfv_fen!9emLQYMjcnGqu(jA$wnnA}v{vV> zO|zoVjKr{YPW4@cU9%{BC%j44^%>?lXXj=-z*yPBc*koq4*uVa=FtLw5zTXl(3{HN zJldEe7D^Pp8BHXIzZjQB6XRzjZOS^HoUyW5-JBj$s3RSnun8TF_ep1|rR7wIsS~E| zoTa)-`Xpv^E~l7|?&M>wU!ESD7*0w@KkAd#CHB7OuOoPY27(u8Ab7!-5xkZRv2A6V z6naJ-l93cmBbww`lFCA{bE*o%>6~HY3%zm0QKl4|NQ6?0O1jCcQ#!b%94o~fPD!3P z%mxb`6DC>6!Vv^$HS<$a;l$QH$x_uErC{=pScUej4zV3ngw5yq!Oga)*FqMEnsW$r zSecCOc%o`pHZ-$&3ywY-WX58a>ZapiY8l3qqRx7}?NBc;yr7b-qg!T7^aKs4HBL?F zqao(GTQ^}ToEo({&&xSN^BzZR7KX&ii>0AcGRwCuE1A4HBcCxzoa%E#j$3LjLrlk( z&%&r>DuxV;Fb6uUoMfe?B;%f!hb$mNr1KV?l}~GPim5_EhGrDQAm%i&S#HjgDQTRj zGp1!&(>k%`GgJed)aSZNfiIndoss&KTDj~yvXafp8A~IE4QSf9#a8=xHt+3jES9~# z+iJXM6qv9R%<hA;_6n*BU1HCZT|Ga^H|49Xl}Pk)<lt)LU@6jDj`UvjR|W3iUKj6w zio-X;*TU|eV=KbSg+Ib~g}YysKR)Ls&$}1Ya#C~Cm)zNWIbCp1d|SfBGA_Ef_!M_M z#+|FUvxK8%9CdN@X?v#|9dz41sCJ=XM-_2_XeHQjW9-`4kBRGvtBJ~vU97XG65Rbb zxNkMMuN2&04(@krQsrS}?RgYDuMbucFZOR%PjJW$_ph9T3Z#Sw%6P!V0~HoQbQMQS zxVwzIUEE!1-{W?^`@6bw;7<CtG^kA4-g9x2RNG%QytTEp=MfYH8oYRHv#P~6beD6( zLm(v_FXOn2<Np%h+iqK*i<_kCe~pN$5eNn%TdM|N9mW0(cFp&vkA2dO?sd0~`1yN% z1M$85{lgsS_m2o80rX&R2=oVsV<Q~@FwFWNwz2+4oCx|OKhN~QiIILjhG_)gJTYx3 z_AF%|dap&R|IkqOVfMP}oBB9=RoN+&TK~skZ!3EnYa96vdIl<@T~NKigW!@g$cOX* uG}+hJ{u(OSHXK($p)0kkf;!!1si3IaEEROpZI-IAkL#(T?G=?^hQ9$>Xl}Fs literal 0 HcmV?d00001 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 GIT binary patch literal 2279 zcmcIlO-vg{6rS;}?KLc5lZMoB8a4zeu>!bKe-bEdiok7=QW9!t2z6^MyK7iu@4B;V zz>aB3RVj&7i9-)PRK2&N2YTy~B;?e~T6KlHr4mxqLvK)WsK}*n`~xISN>sHY%kSHH z?|n0G=DjyRG&Iy97^MYo{1%JQJ^E1_OciWT0r&#RNXAJtPNgG>Q;u;5uFNsxjKU<i zn%kaC)bHUMl9?r3!DVkY=}NiB-GH5+qH!*ZgRbAHdMJo(cf!y$HJ;6>Qcq~qP>2zF zL)Ai~nmPkmHM4>q7mN%cN;cFd&xo3&$iii1LKsn`DNRr6li841o$s7gCOXqZPbiWZ zx=3Uoh`p^!L<ia#RZ?Pa5<QcC0amS(bWH=Rm^>j>cUs;rjgOwl_PT?fh6kCu+NH7q zLi0F}6SY&T&QY<ecgT32$vYCxeab4#GkG{yKYW2?s*<frCzWw_309^9BUr~>!TbMf z>%eKcWVed*4&sH?Jo{}bc+WDAi4WNR(I$c-=p-`BnL_;&{NEYd5qW=}HJfT0nai_Z zqOTl#w|xyKd^PQ!+}nxlk?YJuHBFwac~TY?OO7j$ZS(9$?6v<estV&QHlL}j3vmoT z6i5BPh=c#X_dAQ`m@8-&pF~e{8rPoUj%QJgGuSYc`(SV=5`Jey7#te8D996fS7b_0 zr&VpTUnHh*nik{WK!<RN=yFCfDTJytFA=Du4uRSXXGG0}5)Ib9+jn6!91%{R?+~iL z;48MP!eD!L8EnrkgU#<}u-z%eFvLkE*E(n_DM6HFD05R6B)SzNBT1l+XOhWmu6;l> z#R<_+1ceZt2&zV{V=B1COg%;&dIZ}UrpjFNsHV)Nq0oV?Y~CZ}ptn3cC+Lzy8;tyT zuAKK#hhRN{Hi~Q)xEVUJ-O8LIWlRMo^i)bUZKsrko@2YxSsfY-si(%yG*LCv=7^q5 zPKeU9%@`)JJ>fY?Nt>#!1)Vl4Luk9b3FZi`LAyoO;3~{=Xq7lW%qS#lW5u97MxbM7 zp}!|uZl6(TpV7y)&*&4{XY_IHGy3HA85Ps%XiArrqyd!jh)yrEE1k7lcJINcCQ^CJ z<S1;CwjLt|&Gcim$sTpKt{-mwJbI(9<O{6%+6un5AARjNT$?Ozd)DHPZ*Yx^jW-*u zBc03a^4NEcE9}a9h1Z9z$YpCxDnw)}p0K8~g?P>iT`h9?4X$~O^A|XOkqc~i{Z^pY zYI=3+DB_z-eDmUkn-@MC`nmpaiEmlsj}`c1Kk>&m8N|2zc|QOqi@i5{|3HlM+&b4_ zd0$)}UhcOV&lS1u5@ih(xImG6uH-#p1v<Z#mQO6jzaF#vFI!D#i`>~Q??G!kxbH*! zVanfG=0CrJzc;ML{vtQ<D8K)V)znesI<{N~l5YBd@4*&-kl~K;799I0eZIbKbgTPN z7&Eu|&i;1hb~mQDhYhpnPCF0y&hsY*dYM%ponLLH^Q*m1z;`hN_%3@Ye1-{nh!^N= zXFMqy(}X^Oki%KSX49fMWxF6P6iv2|gY2rLM;Fa!TB@<?b4yd2R!%u3zCqgn5uwlC z4%Z7VnWXX>X@gJt=o+WsZ<E0o|AHERMgDuJu7sHD+yZyKX`#vTUM-^hZ|J3M_84v@ HC&2bEGAA$< literal 0 HcmV?d00001 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 GIT binary patch literal 5426 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 literal 0 HcmV?d00001 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 GIT binary patch literal 4606 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 S&PS;8iFukJx+VBUi2ettxJzdM literal 0 HcmV?d00001 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 GIT binary patch literal 3407 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 Rd;KPVjvJ_>{e&jK;V<DBF|7aq literal 0 HcmV?d00001 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 GIT binary patch literal 2444 zcmb_e%}*Og6rc6_+v_g~2`OKLLqkl8lL$3U5ot@ogeE{JBt=1Ptz~z>Ys{`QyM}<4 zHisTSYDKFaQYnd)W1<||zo0@2IrXv*RB^Vc)TrvAhf1d8P?1Y#jMqR9$t5H0%$xV| zn>X*hdD@@-elH;7!L!)p-w=R5=*AkhGO^W0h#NozB9j3#%s9hP+Lp16+sMjh*ctn{ zo$%~mf^o;ZE$aA-8b%q@D=4yz1T85}43Vv?7YWh~pApzHFkPJFqx-F6WWE73hBE26 zzq5cv)&q1lz1OBJsc6`Bd)iTE?pZ`e2b0YG@--Mhv|M|{|3`7?4t!I0B#8c^bJ3-F zEM47ozwFhbdk@!E;d*qZ?j|2IodAGPp6O$N1n8E1(K`heeY#g<4-+u8M)#$C7V7RQ z+I8nmAUbZd79#Q0D>`3l<I>&4#=XzRhYyIJw0{@bqI92yOmMwjgsppZI}VYE1TCH2 z)ru?eg2iDH`<LpBf>9v)L{9YIvb|2sBR~sTKBcQHYIkh`cxaK+YAlWz(7Bu7b|ovM zAbny`J7mdq&WZumqTUL&E2NMYxzD*TUS}*yh;z&wxW--qbIcL&y3pr<g&7SEEzEl1 zo-rC9i1%EAALn>kleGEnSzgNU6B+atyev!FFqQ<gPrq;E;vgKxikK6$US8w(3CH^5 zBXLXmQ7=3T->=A{cC(7N(34lo=b3&XhcS}1WR@OfdMYZWzr;xj3XuyMc9VQ8G>;+3 zXO)aHB`pvaCvqCpQV0_!`4l-b4;R8v($I_wD?l+!ALPQxODP0PkTAuoP)PCe6cS^Q zvdcb{#gYnTWe#pLv26yLt{J4N{1ob2s48EZNHsXA<YX}xwUzwBT<HWFj|pBy5Miuf zD9Pj$BuppEu1FaY;3O}LJ9q7b3!(iMoiNH_+OJF}@kmv$=|b0#kkgRqo<y3EQe=ef zB{`qXB3U%;X+@GvhmcWJWID6+iZ~&djyOHubdbx+n#rmfj`~e+b|+^^Ni?f4x|&0( zhQ!@G1kklC2{U2sB*JRJk|JZ;7)%x`bC@<=OnaeOvoCK+ai>F@2lvBN_<oGktRkx@ zDUu+W?s8C7lR+wl-&2tgZhzg=nYgSXtS0&-IYA0>me3@4P?>}(t(W;kw>Zno0utdE znt+#(kdkRt%qRFVzkLo(w39oh$)yq(u}A=tgOY$rpztiIwB$Lg<gy(J63E1iBBG3% z=%L9Pre)YIi`IjPW#`TMm!%O$i2JlS)t^YSzYd;;>%ObMe!ggnIhqRLy2s&2J{(yO zw=6je?!Zc5IZy=lTCV5@!NW_RKKIx?^+gT@YgUwHWj)Ze#6Ix_3MV`AT)V+F-tj+e zIevF=y`|IOnx8wt(e}Hat-sl2aFL=Dw7y$tK3!-yVRXdv4RJynox}O&;Z2XDA+R)9 z41n4<mii0T@J`*M>h?mY_D1mApb_aYdOtCG#*DF)0i}&l`gfwx^r-q&MPbAkO&KGS zA*BsCy%EYh3mz&QkNt4w-kBf!*N>n5#{a#P4;>?Bn+E__Rp6>t29^iD8hYZZDR2iL zbM<+y{ui#X$O7(Qu^L2LjgE8q>i*5ZtCatJ9waI&UCUkn0GnfgdFu8Xp$}HWtE>^| z-EhYX4H4s1_u7$F{=w1JTI0m|eDK1C`@*L4RlqNbL5lZc)B7sTZS^$C<5wTH^*X_W zdOMldoYnDGcI|LuJi@NM!%+H+J>CW$MjV8G*veA6t+g-AMxACOsioLXEyZY+(^f#* zSLsiNJ|p_FaW$DtSNXY=9&@RH?tv{L0Jxb<+wLxclFOj?a4Xr;UkH_&6<LO1egkj+ S3jBY9x-IufrU@S<{Qm&Hpku@U literal 0 HcmV?d00001 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 GIT binary patch literal 2649 zcmcguU1%Fe5Z=@2thFu6l^rK>WLp<I4Jfn;p`|HlV#l#$$23veI3dIwsHeM?eevm5 z-8;pWu}dg@NJAhL3MnmxJh_y-<f-JbG(XQLBd|CK6#CRRK?s;Ub@n9Lah#UolCD;x z*_qjyZ)WFK_ftnl8-j80#L?U@5<-9QMRNoi%(HiZxr2113nt17(}KYHfEmb()1uFd zW^g*F2fsqok}gi6g!Cuhnh?CuRhwEyt^{nGMlFkIPDanBwWe!s24Rs1-)G+gy@Ohj zBXDtjtiaE`<^nATmI8NQ(rzfwD|VtTEC-jwyD!JtFkT8Sp(P;~SOM+54GRH*Z;oTz z*y<bX#H+!kksg@yJ+Py?s0R&UNo2bqF3)M(*ybm|dLZV%vYkRxNSE}MHydFHIpIy% zS3^zy0AlL0<V2fmg!Iso^aJ`aumY!XZ{tM#8n$j)ZE~;X4%Nbjparf#D=kZ3NN==m zeuR0!*|mx1H5s-3=ZxC^?~LZrf_MeZ3q#P8Z>I0&Q8PxOJ-s-ZOr1?#Ov&RH&YzR@ zEIm9mOA7_Vni*4>BVRs~x{#7D*@R6d<&*M=Jep3*Tr=sAd|mVr<4=nx5ymK6JjfNY zMIAXui<T}^CTp~4>b@vTWSyAAA-WgJ6Wdm2$YQU*p&^#-qNaf&S2WGiVj`(JYF4$0 z?E97ttFb*}K#)w1(R@Y&EXU==p;t`xB7+oUZdc!9P;2r1OBPuuz<ovZhDWMtMaE$H z53b+dw(E7y6YY#&AYKbNv?=pKWPxZ!hk$_Q^M>PLM(3dtmg7m9No`ORN>tBko|NK+ z^P~bG_RUN)t7>yzYidCw1qXm9TD(vZjv!;`UYI9b&mUIJ3mA+T=HYkO3+b1oZuNPQ zu#zVby9M;JKVIA)JFf6EwG}mA(q@(O7D+PW8c~u|E9Qyi*vcoMrIu<cmn={)+i*%U z&B;@|TqR|ULY73nOxc_=s$Wwr4Qe<xtC}XUW{Azpd6{J8i$t5Xs7YrGVk_sF4t_G{ z42?nh?3$sG%mkyw!h4EZC@6Uf&}}8@_XqC@-eu>w@Nl8z^)&L@dhl#7<izh<`!ndl z>!=poFU6ns#J^F#Rc^FZqp`K<;A(WR96eBp9=Op`Ye9pC;NpQQj@*vijJSK=y&rne z=N=g^<B1BMaPb6~w05uI-c{UN#<2>Hxi|*0aM!Jo@6^@yxZ57D?uxnnDYtvPHVE<> z5?W)`aM$g#H_v{ZzLma_uD17ZVZ0jNy%z3U4fmD91C{WA>(819n%WSG?sH=wxShvp z13UDw{yff6ov5LpbV_)cKE)kw<m7|>Kwy^fa0L&$c=&hRwT5G>I9A5}72NOQ{_0zM z+}>fgbHv44X02<dnAX?VpLe4$<R6qy`=FZC2X*GxPu<8Fm}NX!!ILhY{2NfG+|E%K zZ<+of?4;O$X}#9X@%UV1=egNw=(I0K2TqTm-y$NXBc0=W#fOnZ@{suOn85iDgX1yu z=uijnkB%kAyT!*cmp|Um<xjdL;GgUjIUhSR(I&!^E#*wro@4wi#oJeZ2oCFwdoR;? zzv7QKzg<`dC%ox@M$dpEwg<=yd;<0rO)|{-Vaflw?T>*#uL(jG^}1VU6&-cA&MNA- S?tf~*At7Ev+X?Ffe}4hwkAg1% literal 0 HcmV?d00001 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 GIT binary patch literal 2212 zcmcIl%}*Og6rbJo;suPsID8uLVy8`A2~w$Ts!{@RVv`^NQ9@`GWXZC3*JRCl*PUHs zY?)G3J%Cy%haOU?>K_ns=@IpmCgjx1(z?RkCQ_xIdNU=53NC%)kJ3T~QI$SvXWzW{ z<~Q$aX1;4_X+l8f-fv5M!y@!6nbe7{F?+8Ab03LFq!g5*<|&Hsv_hwtd8WcMif!H| z+CD+^Y>o-AzmbIj%CaYQO_dWlV4DO@RVBfQit!nt4ou8oQ^dfx*A3%+)QAj<hzV^} ze`tj+&`Dx*g#OYqBDG>GFiC=SgbKC-Do_b}qqZl70Ly;F2&Q!`&@)NyxL%|eUqc87 zL`Jm9RDr>5VAp)y?r%6WcEMgJ+RUO^B(h?|%SH4f!%_Dv>8x{y|Fa0+SYZuUT_V~G z?3d^(dZU(k3a!#fcU^n<Ka35sz{!+A-+@M0VLxP7UuHfkh*`=wQ{VZRzm5OF-=_cD z-z-{Y?w~B?M=z3%)fecFEUIG$nrHICP<SeQE6h*aygto~acy|^u9i;A>cW*6Hu&4u z!Z*YGoG#(X5Py*$=YumLo@gcwDODA{hshbRSP5ed=U*iXUeydfp=DH&*Dx<=8AYs! z;u0@PieyNlWlu@E9$S#|J(UGDF|TI?0ThXhqU7>{P|S$MW4gpwuz6XnEsx5uNi>1A zR8#<8M)<t{h^d&t5CTu^s%vCT&A&CLO3P`uEhMpqs0l&_W0;-*{mQXb{{|jt#x|0M z1_0DGY}ut{Nyr!y2((m6HY^TnS;&NHSgfFEIw;aPO^gc`8zzaf*fe-tF;kRyOjxuU z!^?t{Ho);fgJsV^38J!SIY_|O_+eJR{=f*6+r{dvCbE*2s?`S>3Fj<I(i=d}S7`s! zD<ct7Q#~>vtC2ZXUIJb=a=ey+3P3_~k)XH~Qw7M(Z7I&*l7zderf3VfNUSCw%1ZH} zG}e-k&d7Bv0zh<H7BEDHmt;YTUd37_{bnSVPDfH2c%?@|mC}=PlLne5!r^qz>ZrN= z&zj<HaF<-X`WjpxAEB~sko7+8@O~ayYbv=sJ1*b0%lCup>{>&)0r_Og<OWKd^PY3v zX?6{LZQtxO&rcM&tDtOj?{GcaTu+hnz|7HpZ+w0Hi`e(g-qIP5*&jCD6T3bTmq0VM zKK0qmPt6@AN9T^CZ`;xLqhp}VAV+7}k6gW`=YrY#&hEfz#(zBbl5IxUM}J2)_7e4! zYcbp2-5lI>o6d_xZtNGXeTVaGbDkpCUux?zd&bPx@gg_A+kP7I!E-lqbP&|bRn*YK z8xOCT&TB<(@)+tRvo%=cg1aQ<6N5V_y9waIuJbg@eSHQh@^P^JvLAgr!oc{*?+$yJ zM;8V|H1oKN0{(HgE$l;Ev;+7p=U}*(**Z_;TW=8glU^41Ctil|zH<|e3^X^JP-6Nb zCQq?701Y!-ZJ1%PcKoBYN1k*!Ib^tn45UFGpgkB7?t)>T8-;ZlMH<8XFeQ(UPF|Zb XLs8T-)bk9z{WEIWv-v46?gROs!3qri literal 0 HcmV?d00001 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 GIT binary patch literal 2319 zcmcIm&2JM&6rbJo+G}THC(tB(8E=ymV#0U1Kur;~LmLqiih~f5k>%`8k`4B*JG)MB zSQk|F;36bisS-#{B~Ga-E*yI39sYnda>Z&@B&42tTM1Q)IQ7jM=ZhXHB*rsue)Ha& zH}Acf+3_!(oe>0OU+UP*d@n+O(LuYgZ@{ZD0QZrC6sCx#XwMdz5;Mgx6mvzk#7%K; z;XpA^;-`3@-<rpNi>87KlSRqk-_-PYl5qv4U}94(VZaet*EB4fd1V?#p?O2s)S0Tx zym5neVQ3t*SAT+Y_hD#mkgkB>5wupRF&6W1gS5>@Xp0`JFg4C%AGX6?R|I5n7MfvJ zK=x=&&LGgHUc6PdSPsmh8n3XmpcTlVYuQ@J3e5-FlK}H=yacEw04Lby01j=y!UnuH zYl}6S8^2hB!YzktVT*t0Z*H64?yc|&<mJ&?ZXlkZB`kG<55c>W7H<WWz%pyG<O7Ja zqdjY5zd25r&yXI-_W#n&qAVIf=8koH^RRNO3?g!&7BS=PF+vJ&MSem*vs*n@f=Wnb zWcDf?!CK_&$ourRwZbB^h;DFK(IPVd`~QA&vxwSjB!%&%;q1uRNP1E_Af3B3aY4$? z>E*Jj&87>)l&*X+a%n`mY+y2)kxolz2tA$2kQ<@WQ4^O&Gj6aYcEcBmu2f_bSmDc> zYF;F&j9rmxepxAKrfOE*@L5H{N(L^Y8=ch6LXq0=6_czRZW}e+h%fX7OZ!2+FkLXP zgbC4!q-xSEHuDv5Dldcayb3mqQ<BU3@}=lz{bY>L%isp(3NduzhVTt6SHJ;b2AlF+ zp;#pJKoNR|3B3%2-U338IT3-l!9ux=HO1xSqHbU}Sgz{IwCwUD)Ek#C6IC;l9d5{X zNLALpFRHGQZfb!4s)9+?4G?`1B3pOa?eL?_w-UvH*zIa@XheB14EYPM>AMUzsHf6; zdA*W8m80o5a)nY=p36;WI78G0oXhBPrGz!p$Xx`ft`&+o*pmgounm$vBV{Xu;A$?d zLsqbKMJLyDXO)G5CSyfP)2v`^78^9#SManniRC#>FY2=@HgXe00Xz8%s!SjuWC7gF ze@^sD`Qsd<Dp%4KTr_g$Xm-!T{v0k>-R=LeV`LD5IRVZ11HKWrk;i_-Ctma<e#rfp zt4Eyf-Os!GpLO>)x(A!xgZ1FcuG4ki5u*2^ccR}{9xOhXZwSezkhF!Q7ermX_io*} z)rd*Wm{bn{qjv|`=<Ta_INSR?B!&<Aq@H#X{msOY#{<6|Y9!9s;+~g#KU~(FUGe1u zPFz~P)*{kCQ##s${l~qSurul*AoWpi8|v(PF2<jU@ds){9BPU~wm9U7efI9*hB#b5 zUqAmczW?z}JC=s(MUlA8Lri$LBW}Alc4zFn@w?;oai^n)G82y2`&``fOx)8D_cq17 zwqHFCB&+|#VCLPFhgg1ioxBh_?dT`JGeDp=gj7>V*+R<c>a%wy?brcZ*i<14@3{Qx z>Z%umrJ-N-BJXa+I11bQ&1Z+war7h}%bet%9PG)Q;GQxJ;HPXLlR{5V@D!iqC{7(2 z8Rn890)G(@p--Q?t96<V!~5-j1M+VkZ+f}>Yt7FT3&wRqUn~DW{fb@zL}UQSYas>G zD@FV%Ny3o6M8-`ZkYk2%Q0Hy`=b*T~xjN{Wy}5c*3}TLNVLE81y}7R0^aA^sgooZH IWC+&(7xaNX+yDRo literal 0 HcmV?d00001 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 GIT binary patch literal 4020 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 Z2AR;8X$CRheuBC{{hWJ?36Xcf@V^oFl+OSF literal 0 HcmV?d00001 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 GIT binary patch literal 3021 zcmcgu&2JM&6rc5a?TxWX9H7(~$ne>iMu8OQA%R3Du}!4lq}VAUwPbB}*NI{6HM8q{ z$*EA)LyC}4rAi#CN}Om~F8m3Iuk$*xgtZb9QcpcpvV@Q#PJLsq*ZBac0@3k!_RX93 z@q6#h?9T5#p9euZey%SQaU=8>oiv-nB3_>X;x3Yq#3*R0@nohLm^&0lj-6r|%3~F0 zj+^3ucK(Q_ToRK&A?|N#A|7H)_ccw;XETdHdPFs!mqk4-O^dAMf<9dEr}NhY#=EEu z=?rBz+I@IDXim^FD={TDZLgQudrh#m3?;T`IVHz3S90Fl=+%}laV1n@N{$SBA8b9a z?Lk27vg^HCu9BmKGLEe}fXHc^-au?dM3W_PS*GM9yTJpuLC_|*YLr;A2dw`m*#t_U zBS`n!#?Un=a-$tZL|S(1{^lGZ$yIXyihgt4hrB+pbITy`*4C10QCpEo?xuw-BRa0a zrdW1=@BWmrH9X8S`tBC0cf`eibX;u>3;%aq^Jsy+isqRk=u>5J9yNW0Jn^XT50u@5 zt#&DLITpdA@#Hw3AgWXp^$|fAa5#Z=fy~IdEjXDNjmL0zA~F^kPU0adVJVD`^fcz* z6otH=)fdBaLRJx`71`oX=Ck?)$%=A_YH4bbh_Y>WJZ^dFwawx4mQagji(k1IiQ`M* z<nYDF2u{MpUZDX^PK<<;5uAu5@is6mtJ{`(unn;#WwUG#b>H#vr0xI0Rh$e%{*v2~ zjK&j@%SqgA2i3D3(FV66+X)Th+wj<AB!RmdscL1Rr<s>`L}1C<s6zv`$))dXvYDV+ zwNS|BXNCpRsxZx(tqyq@vb7-a%aK;OH?5g&ttg7JrY(i6SaCL=QAtkFvuYj}3zDGA z61IdgMMYWcT{=!T*|ea^SSCazSSk`ggA0uvXesq$ldCT;1t;_JLIFM}V5p&>ieixv zS?b42om&_CacBpjFJ{vt6m?ZpbGfW;x<ElwiRqRXWU;8rz-TORqM~XrEi9_=u`;;` zMPzaXK%|>IQ59uc5U-nUkp)pM(3nEJ>9LTevy#c*u(o|&N0jYvABYnAPBlBU8%nyV z0qGD-Kjmmv5z-=5!DM8O2Vq)%+TQ*-+@G4%WTK^n+@d&}8qdokBs(XkMpUtwlk>Wk znt)X`FDNOf+8oeu^st)237VP3)G(YgNbnVvTu+6iIUz4X_J(H#MUnF}vIbScSLA7& zl*QS+s;DzrSxb!*3GAdVWkmuxA#-qM(=nnJ3#U^;p^(a{lB{T{$$Cw#YWEfvP2VOC z*#~jZ8;2H!5A01;b9~8lz1-9FbLyAWil>T?t#~T@fvP|F!hd+pf4J;FTJaxUan)RH z2fPOVd2KgpYrnJe)=p#Z7po^8&OYLdP_)d)Dtye~V>OqPN(E{jTdI5Y?86hriSuQC zu)+@-{NO9T^93JR;{#<rSmA>PAFOr+j9}DgkJa`eZ)XiLZNaLy^Um0<v7h3%<16v% zjy;swRrP-M!n=RXyT9x`Sn(b->b=Io%KDoiXx=_oLo63#HjXcOpRu$5;SCs|m-> zKVa|!RSF`w#s|y%0SMQCh&%QgfykpnFwou}HTX@v*72d(*4NkH_>mW4V7b$+p^oh2 zYS`F$5_*|GRpCz={HgaK>su9!Kp*YxUm5(SUUPi}vYH=20mAi~_rtAd7hymB5I%e1 z7<zoHJ?dm1pXnLd#Xi9d&`%CIqi*zcmk;QtxF<5iKJ!xkGauzY8{&X|?qq>}?mij) znhm*4C%vi?9~d>cj3Q{)>3tNL`x-mEmmX63dP-Z@SbCJ{8>POr|3I&SL?i&iTmBrV z6cu@pV3^Vim6n77_6)<kLOX8Oe^unWS^rg0z}Vbhp*~}Cukk%hR}F0+NEaCX7fb{2 A<NyEw literal 0 HcmV?d00001 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 GIT binary patch literal 591 zcmZWlzi$&U6t-hu(?p3FLt(iAhAc>k4OK`eRl`z(NUKVbCF^>ANv!zn$j(Iy(-l>v zBO5CVAOwF*Kn&5Xu&_ny)(IQhA>!#hzt8V|?}z=V*{mZk_jex-e|i5iTyBJ1gUfRd z-XVbmRw%;*j03KyN=60*qY45H^dm;-i?@F=h<ublv>C++s34O{;Mm&`z2CZ~Z#Y4} z{#Pfq`Y2et`a5vjxQzBy;wB!@PVZ&E+~zz>q~`oE<OH1Lqv!2v84Ux=hL@D}znG`S zI!i;q*XSez&P$R^rzNqu{){d||Emw3$Lz>~bu7si>6rC2>{&SnwrA2j13h!>h0hwD zD0ZZM!a6xy#AX=xb8BJ2IwrRc;$vec?5UV1It3AT#)(p(N8n<q<6}694<Q|Eqs&Nx zV?8T;AATTHYy9lFOo4Z;$)}H)-;ZTRfO3p;spX9G2h+vX_O1`+3ZB?oe(Ui2Zsw0Q z!5FVlYq_Z_ba%O_>pH473b=T7YR*hSR)`j~=%3ckYDI0`K(ul3>O0w4lART;zUjX1 ZzP(p;ztPqY+FIV|njm_|Gi=ij{sTezpy2=j literal 0 HcmV?d00001 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 GIT binary patch literal 470 zcmYjNu}T9$5Z%r0nHUl+EJSTmSeQZ)>_h|+jEx4=AcTeGay!w}yW3+g7dfklf?{Ro zH;Dd;ognBzDsAi{=~B6?2AyK(&6_uGhj}a(^GL__;#l)t=QmRfgZzTNr@<`}NMH~7 zxQ?;G8873LI>9J|00X_pKkB-rYXa7=#t5h&$8!j&39yceL-W5Z=)*sCGLnpxvmd5i z#;LX8+0n5EbiKN>o8~z8Z8zY2&-4T|;)CsSHno~YrOdu*{u^^gsz^~o=$XLwf%BBu zVVDvX2Y0A%{0E)&WmbzoMQp<jSS@hd8oRBeB%7ruRtgffCfau3fGF)lqqGOkVIVzu zkTCm~pFe@de5m9RI4xFHLL2Zc*HKd2wp|B!Maei^V)|?5O95WQIClfL#rZ;*400=) zj6GOY<9Z=;!f07PJ%TarqRB3r`OKqi;cD|-cE~HDo!yJkUIEd<)#($NdZF3N%30-R Qwo`eglRbjyv@!?&0(e7y1ONa4 literal 0 HcmV?d00001 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 GIT binary patch literal 1269 zcmZWp-)kdP6ux&dnM@M1vD>Z1;+BiQN?_Y&t+;BekS0+J+SI1CY#9iXxi@VzxfAc5 z*)}m*`rtzZUwqmJ5qwg_mj(ZVzWF$TK9m7rLHgiZpfAflc_vBQjh;)sbIzQZbLRWb zkY5vt7y|ol^Ir821);x#<kCXp;NmR^9wCY-uA{w?$9q^oOrgpz7@^<cH!_T9=v%ZG zqPT=o>OaB7jrM%eb!3e)LMz0wIcJtrvpK1{d>B~cXNN8h7|gx!03IRdsxyM=|D6>@ zRO!ORE~aW%q2X?bYF(8^I_i&z>Kz0a?O?!IM*)m?LVz#)6z_(eOKvdbOW-}SPIz)c z3B86K?Xrr{>qyLXwTX91Og@3pebA??J=Exp(l|QAhv+DDA06UUa-*GC=OkC$*eK+- zNq(&zUwM0J<-MhMmhQfr_GfKDnP`~Y+-D8O9cnse#gxpC%CGB^i3d#hiCtFNX4b*S z!giZ0?c2rtT8`vJ4Qk}>JyNv=DSiGaDGl##NAg?iUlg`h+j^!{*cwK$Og_7vUCWjV ztL<=RXFVUd&0TP_nQh@phtYEGYD=r!&a_|I;q0ghYh#o!Az*}US+0QW8`k|OrTXEf zsBy>Fnk}1FEI%^dvL7uRS*#gsI~DP@F$4XImhQqOZZ?>&H%%!IfxfTNAs2t@`b#NG z2iouZn8^q%gN*Fi<J|kk4m6O4*=Sh@Mv=3j4o2R#+(15QY(mxMX5HA~fk3k6w1{0L zC07X6GIF*nBqO`F_{zxA2PU_GQSQL3*BReulGHc>u}Ppdx9j$PjY*>zY)F<rt69Ph z_|z;`9<9PKn@yu(Q&yM8CByPHiKS-CkB!qZt%zx060nhdfMfKR8tpCj)wxr3&Qs?G z%8TKdCsXr1?QHr^Pd}TU58zdRsdP^psOa`5%FopS3j7EkPh@}U&)2-&@<dwY&!?l< z(_cPM&V2vSn_uoH)2GR_r>CEu$8Qag8lJg^b3NhRxYO4cPxVDlUwo3h)pIY;Q?Nl4 zZU--Cfz=PoS&U9_Ec-_2B%aKY&<P1coKl4jRbR2C2oxAf@f*5;5Q&=r&-4#KN4L&C z6hWKdFF@u11|f{`8A==v&l!py56?hDSUV1T+M9i}aEcZ@v@lR_VtDKSgLn!0{0l0> BVS)ev literal 0 HcmV?d00001 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 GIT binary patch literal 624 zcmYLH&ubGw6rR~6+mg7IR>Tr73to&i9#kqA6Nt@5#hS)!s!|q~&CaxLU3Zq5O?B4< za_}M^JbDoS0P!Mt>7P*W67VAHrJxsYLT)|zHre2V`QGn&-(%*RqT~_C*E37I7cfG< z5@#+_YD`wZc#jAo*hM>tNUzZj4sj{-Cn;#zY1vfe05fnVO#tY@L#Q8Ok{O^6h-3#C zF!wPxlmeJGll}Rec>wf4`kdx<RFYd!v7zbryIbw@=0<D1eO)v3hnw1yc1P3oSl;4< zauJ<xbnZRUI@MQ@Q+3J@C?8gIt&_x}e5FzE)^FE!ts1RXy1Xv}O3V%BdDIRZ=2b%~ zDkUkF{g9EK9WU6kR4Eh7VtQA+NUXr>S%SvPX%hNO5pc)b6Uol1s-C>HZyMXsAdIHt z8QY!%EQAw;D%({>pK}@-b#h>NHYMs~+EcsKe(Euo?S+Pw#>+2guk3TS56q0&Zsr5W z<}Bgi*wnnkS>L~ASiWyOXN0=Km@_l~6T9MvaXxiT(&Ggnn1v&*0*uhHa%t53ar)fo z?s4(Pq5S3LVRUrys5sW2jaS`q_U!M%^1Irb+PHZ6dtq&yU7J7`DoH$f-|1bS5I>dJ j$@e)~yah!1F0Jt;aFdr43c%kC#`q^vCh`I<Ps{%Sq_nKp literal 0 HcmV?d00001 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 GIT binary patch literal 2474 zcma)8O>7fK6rNrGt?l)1APs>e8z+LgB0))8LP|>2#v!B)4#YtSWMnP7o5ZcN>&~tN zsdf>ndT>!B+Nu(%M5UbQ50@T$tOUI~k)^EWgj8|p%?K(XPJOd>>^NMQtlzwO^Ua(0 zzIi*FUqYb(f_8LbWbuq2p?~OLx3LZ7xd6&NBqNzApsTcJ3(N|8m1U6Z`UYKf$xH?% z-TzW}I?0fLq^YVR89Dj7#86|S@zA^A_xu)kzK8tC*faY8CLT6`2w9BDZ0?zDPN01_ z)?_z#<7|OIlNl2&G7n(xVRN2AfTj_=*7kXI0nYsz2n_8w@W;FvE{`m?=}Mt%)0W5d zWP^~Q*Ya7M<+lP>(BiF-6}BQ))byI}RR;5>&*V(M88CxO!1jHxn%)W6pZ15Efyu6x zzUgV2_b4WBhRm=TF{85kzUKij`mo6=gVxU(p%&P5Z~9uJme!tgyALa7#xiIC8POL0 zbEu<w8$@{8ikmDx@aB91_6<3eJ;uS^oq(Bmdt`Y=Vy{50TJc-)OryWS+(0*7SI`Y6 z=}n7kz(hdU(=t=DQ<DpVwlqA4Wd%=TtyG*z9jAuLl5S`#3T_M+u&C;yWaKq9B^rtY znbjnb8k~XSK+hPWQPLg5f@X+?3pg)PaK665jG?SJ4)enouqKxzqcOUq=8YEiVo6ku zys_pibo|hT&U{<=XXoe63$4f@?6&Edbb4xD_;hY2T?bJo5Q;FD-k-7XVKc-A2W^fn zpPQPWY9|F&eAI@Sn@_=JpIo7^ePju#sm$c*q?ZI*q>{)!5aD*|B>Y}3NuWg}@z4}> zOfRschXfs5om1j(5=#6{HVL;&B?-6lNIVM08cqf=y&Z^GDq&s2#HZX;q>`Z!Zc#C$ zWwB5o9;u+|3h|1?qN2*gUC8SO@ve%6lA;rDaZQ6ek9el2H{#L_oa`XJlCI!fUT)rt zP$W1;_wivx(y*+P5J<o*gEI}U5pUg2!gcc!Ekx=dC^gEE4x&b@2y-%2A>j&*5^VU> zbGlQ2Bxum;%N1$)?e3Ka?wp{C_0n_n5)@to#(mi+JJ`rs?JTIfh_{8Cb2wlWy#sRE z^E&OSuYRBWAbSZo(6i#onzWpqQ<W6XuPWJ;CY4qc)zGsSU{+JbLKY5d6?7<fL0c3u zC5)A|?4$<gp$L~X{6+R-c~w*;MHVLMc_`|Vq6>LdxU5_k78Ge&)e72DUeU92lu<o* zJ}+T7FuV$>=bUPOHw$N%UD0Hvpl90>87{7o4(FtEZFW2iiP6u2{x@71w^5Bf>FIxZ zu<!fqkJ)m-jvd~KCAMRUt=M2SHdyx7yvQH98@>~+Ay3yxEr8xT{l`1cf*${w7YGDc zK}1o<p?fEOII$HUsKy7%KAQ{Q<?ry{hS$U8u+7DHxUOxkYm4iya@`fK8+;x*Tn^ct zJvG$nk2s=yw&q5QY=M1-P)K6S>5b1S$?-o={dKLfkgJGlrTA5ieo3cU=w{f9w9Bv( z3%;Vgo7XClQFxvthU{Zww(zz+IAVj|(^m`mM&dOD;=9m>x)mL&9YCS(jo~Vv{PkFs zAKl@{xA}3q@3`G_j6O#O?Zjv;=sgYjf_R3!p~wp=VAv4<#Zhl!b7&`VayxNyD{-ot zIJMO?UhNr&%<M>ih3kL$G#Fc-fEAwpmUt43)ez%9Z1eHEvv+2{O|PfRX*+n38vAU% zbB8~&%^%s~d#ikJh3~baZ~fe{aq*|l`<<1DP~rAJFQL^!umkjZFC6FBlLM1S(W9f0 z)P(EN`xB`#*W(ce^v7c!kV!Z00ubr0m&!1_V&ZjCS8|R2Zs=P~Zwse7enZbeMR*9r tD{caolnTljJPJelz17D-)Lab1*eG<{`LoeTrTwY7#~8@|b%94<_5bYWm?8iG literal 0 HcmV?d00001 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 00000000..3d1c7c3b --- /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 00000000..7337ee09 --- /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 GIT binary patch literal 2390 zcmaJDTTB~AaL;#VpKVM+FbQ#!#vxIO36C^Q5u%|IbwZ@j7#g5aEGO>eZVeaCch=q+ z0<tSBY85`Ks#5smixR;{ek%2|P5aT$Gdc-$Qlv-~ANixoPn56Do*!UHyWX9fot>ST zot>HW&!JENLHmC6<ID{&LVwdqt+7?)O%jl&NJcWFqAZhS7>avTPnJ!xSuV-Bb5`ZE z-lW&XIn|f+c@So>cY|ML5L$;(X-Pr$eut8N*#|Hna}y{gyrxSr#tDsznOSk1=yG1d zB<69Bx`bglt7vgm!J6p^2|Pck=M)Lpn?{F6Mu*cA*KdD){dVFR<Fq``b<;43m`fX& z%wb|kRjuxa2T0HK=1%}mky*D1A=Be>xL|{6w73XoEiy7&^uS;XXk{Po-mX<Z*Xz?F zS6~X<97DQIU!916<|(in+$vbHUh^(0@*tDj<J!Xt{4^u;8{SpWxL(&vJv`x#m@h%7 zc&GiVyr`LqxiFQJMH7z@Jv&BZIR9&U#u)2xnwZ5-vzE`Mb0PswMb`}H7{NJJkwiL6 zXGF==$q0BopyBznNu6vsp*c}isLZsksS7clP(uks3UY#~VwhDvLVfFmB!VexWpB*u zG>P=;(o*H_0xmsGO(7vFrkQSPu28es6hV*Z`1iC^HBq;{dmbN5O~IuaDKWbs&7{UO ze2pk`ICV{z@>z%sBQ*}Ix+bcrDGe5g0q%(Endn5G5WJ9z>v>|}=pCKRriSG?QIoJ7 zjn9axinVEML=`Q12S12TVrfRxRef5)Myle&^esgqIt?gA!s#1C&*wf#iMd=Vmwx~* zn4w0^x`A7t_vRLy(^Y5Gt|py#??$e8hqS}lf-sE707_`5_1rJ2)fz9i#_iU4>C0U& zI@Vpfx!rcWl-NEQvAE+vIo`3=*0b5xQ*P_C+xkigAPL8oKeT+E(09V8R=R$@Z+%0o zuu%>hcGy_*zY@Y*LdT}iv9_=_`&XMKbd-fLTNtxyeb<kK3$XhQSb?N{8G)$t-E7$g zYGbxMtn(Gnfm~tCeUZFUk8vu!)?}u@yg%M$PouOAwlVUH9zQC0R%ompYBG1Q(iB;f zMp?DV-bUFBYFPCZ*oXB@ZPa>zQvgn(CiQ<g{lMw}FHWuV95TbTRfNtX5-D;GHU$dY zLHTzf?~B~GoF-Jh^UOSY#NI{ojee(rb*ME~s7e)y1rvlm0E>Ly%=8REQRN}w^Y}F- z!pvtXS*+*H#mFse7~(XJ8jx#IBQHrX&*W8g;q0P!lGcjB#lU#2v<xo##xfZLn}drd zMnpx0R5NwDRgPvWat32f4)+l9)#2rQHfK0Ou3GjTj`BHPtVz0z9d;U<4xb|m6o1|= z6^_4N!W^&es&V|+A4xbz>zKo5)Vwhh<DCGW16$K>QK{mt!X`?AEQB`#^c*2r(utg| z*B=HOG{D@lLrwtZoUSH%x?-YP&tz8t=>wiKFpPfyKqj}e{S;ZgS#IgHTRKZOcUnJq zI`rd^b@sF02DjpqoAF6&Dpii(v*Y)E7%I2kw_EQ+wtIYh_jcr?tw`5qr0e-*E7Dbt z^xKjCr6Vtekk#B(7B1StMN7B{)1{f^BX)aFS?INeUQ6huBz1YrKJ{r?=(mM_OX#O0 zW%-PKvac*$vV}{Q+uyznhIbLeckcmLdgoe8T|TJT-`_&pWnl|^ceth}iN}dD7q+>u zRqMt{IQ8%R@cA#g(2K4>yqSG*<!Ic`{^92Vj|Cmxt&N110w?I=z3!_}c}d)N!z<}p zMwxb>74ji4k|+hVM7rL6h6vT--o`uOY8L(<sQ7bo1!%Mq8BYL!l?=0u&RC6o8(p^E w*AH{PLcx;zdlhV78d|$*1qaH(0XsNQ5_W|aW}MkY`{0ET)3%Ea1J}@h0YqqJA^-pY literal 0 HcmV?d00001 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 GIT binary patch literal 2023 zcmaJ>O>7fK6rT0&+UqzD<i{a#`7r?%oZy5Xfr^1j)FMc<I8;hh5xKaV-Ep#Jy}O#- zO>ksau2iW=?V((n9DAxj<j`X;l`49v)Qhbc8I4-C6<oL>!l6npeY5sDDMB5~Gw;29 zGw=6%zeb}y2-Ze+vM?D$=qY3T#dnCUX&}~+id0TVC2pSM7#+|9C4QbS3G;%-^SU@M z1`y^{VMBb#weQXc)!^r7KBR_Vm&$xndd@y1IU0RmF5H%H5L0y(Op*b**ArY;OPZ0< zHEcLk%How-)6$gecAsu4vc6>6PWt@G^QRwhw12@g9or$YmA5fj#>7_ICfmCR2lIdH z8`##6)A0vE3>yL8yDC!oD)?Isz@M+6q91Yl4R3$gp{qiLs|d>+IpVOly#<m$g@<T6 z_o^bi5%Rz8oE34AQ-d3!hk>??LuL3Sr7VGzBf@Ubkq=$ja5SepXQ{G-r-@mbAu5FR zoVlLlsbI(@O#2MCl(%F8nwn|Ybbw$>*A$s?`GTxCCYgq0_8532@37q2G`cM78hbNu z8hSY?5P{i?=$h?xR0xZRMiqjYR{L5qNPA^gjJ(pWMvo`YGcQOK^hqDP)Yq1lup@&B znTB@^v)B^e+Ws<=&douY?A)|w<mL>G)eB-xn1zJx5`xRQ%j&XhC|FH=gclOCSXnYm z-CQi^<c>VGf)`R2F^gDna_!9IuWJf1S@ksq=dTjewa(;Z%gR~q0z|jO?A`XdtjkYY zWqP0!r=Re=>t$SR2Tn%7ZH5VZ0k#@?Hh83dZn`;mwf4b_AR0JPyY?hDT+2Qgjn{=? zkPMHtVyQ+fwHceLWr3Fl)(<v9$DR%C|91R`TlG&!bI86M{!<!iNn;IZ?0)(F?O$Sb zY3#8y^CFC-<6B?_Dc$x2hULv`-S0rUyLF45_F*^tRYBcm<{Va7Z@sArRj$Gn!@kDO zsdnM8!TSwb4TMo8P>k$o`P6Q3S9ymug16M5?+1r=NkbLB$ok~9<=gp>t^~S!UsDA3 zjk;mb9r$0}om}jDgI-6(fOrHsL%zmQM24%vF8_Nf!jAo$F!rj#r@~iL?Q?}&L3j9@ zXoX8gvV`@_s^~g})H^WVL;#(OpEDtFAxA4=({)zk*RgHOi#TD!fP>ao6yOW4u9pw5 z24@*w)2lr<e0Zl<Lo<bfjh*!BzG+$00UeIXuBwSr`<-;MmkLGOG^nV$CCjD~K*XD< zRA72Ehz-S5G36JrLq&^dFjqwnvozctBQ$7wW@z}z9R*u#mQb;vyY^C2q&;{Ue9e34 z?$DmWUM2y|!1x6_dk9ucqUO7UfWtPMDjxm`D*-*wfn~n!qSM8lXMjwB&O!Lw8?XWH z`eSSHd-3&aoBhXX*Pac&wRY*=rTXCuKc!ol*+yozK9}3feEjvL&B0rM%s@yy@g)9s zD?Z+ckAHu<9v|O~pS!!~Hz`{08*fSzK-^tg-_sgNHAYfRX_E2!`b=y8*~b2}P3aut zwe>@-(W%DhR8u<nDu~4B7unCUkA<PXUx}zU_7ZX83GcmQ_xoGYL_?bR=LHY4ZJSMu zA1@zz?-Y7;DxBHNKT7vzBK*%05$I%?irx$&4AL~>(Uaa__2#fQdI^i0B-qB@@>1~t zkx@po)NM-_OHfrEze~;l%Z7!06gIHWalfNOf1uM(QRJ`4NPXf$Gjg#ey_EX78{F3M JC>Qfy`4?Ol0UrPW literal 0 HcmV?d00001 diff --git a/Orders_Microservice_Group3/app/publishers/kafkaPublishers.py b/Orders_Microservice_Group3/app/publishers/kafkaPublishers.py new file mode 100644 index 00000000..0e198a82 --- /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 00000000..507f9d42 --- /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 00000000..1de212e9 --- /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 00000000..4006e98f --- /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 GIT binary patch literal 2315 zcmc&#%}*Og6rZ)n_SzUs3WOwvut7qK)y6cTO_Q`ugvbYJ2t)xI$#uJ0b_cU$z3a}b zkszjWB@Q{{ST&ba%83$@Lyq|$s#fc0E3B0wRqClXSG1R$`eyxwNu?e;yZd%N-n@_B zy!YnE?(P_Z_VA0d%Rhw>`kfD&E!gPne*>MzNJE-npbQEiA`rA1XtHe!2<^gGZvy8F z7{NTwV80(ULiune?DqvDl8N|o#Eb}kY((?1ObpgSnJyTIjd;F0(+%Uu7RvN!BG7~; z%%fEF4=#Q-C3xY56-pEhdfm5_<@?H%WwK(PP?(6{n!J8%Ql7td_w#Fay@3L?w4!Ru z#e$~TM3Zf+psRe}qCat`zN|J3_kR(f-0l7E!J)^<Zn=ffYO8M_*wKbT6P^dQ0hHYq zFhb}4CY(qM9)`@0wnb{#_K&1K^E}ika}$-&RrKY9O`#;LhMT*da=YJZTDVisX23qu zW?F6OECmkn1v~t1+Z}m&z_PZa(jk93r2z_q2YEH|cxzY+YSE5StUY?(wGEngTiONm zsH7nXh4}27)Yxf-skWXcDJGqf#!ee#jTolV8s`aPN)A?^1-y{I=!KUpnpf<N(R#q> zW=?7Zh|~xW351w-I-RB*SO}COOO|Cbn<@pF5xPbw+Xxly<ueyHl6Q$p^fjU#l5t6T zu<6B`fv0Pp_;pb+ZQWk?LItX;Bo(ARAe<&R>E&wTUc|6+Ik3m;T2h#<f_=++&cion zug`f{H^FYqxgkA~7g|${BJsi+Q7w&lc$HZucxWjaqjAo~BO!%7QEjA!7inPO^)}6d zY*1uy%ZneJVO)s>?aj-nOW8$mm}Qmxy1J5`Gs#s7&StM#DrA~zv+NyMwM@mxE}F1F z88|3e%hG(2QnH?%vWk=u>7GUJXD78a#Z&>PsTIXAh?yfy(oN|eS&|lrx?)=3yiQnl zj%pxBzOAd&;$Q<-@(pSg3lmwTP{^|45>u(ZL}<1nd*@s8>B71<-0)g%I@U~m|77V& z@Q?$~Tp(ri8h5#P@Q2(J!<qQX!Ey!5E|#GK3tKbJkq;~Qyo=8}`262t)I019fADkM zNi0?pi*91EJpEf=vWCRagijtus>#tOpYA2cUnR$1L@LP(Zt{X79(z5Q{BFY;Jy#i= za0e$I#$StxM{#H1+}^;&R|6MczE>Hz;SSuWh|{h(?TFK$D0=ki(2n7r`nWps?#^fK z$Vb(o(>sIi(Aioj5S{oF0r`uQTAOq?t=I>@kjhE3@k8Y)wEqi`|EHjJlr!8}95$iy zmyp~lWF_?PrED9l--WN<_+0{pAUsQX4Wqm$ZJe056>9UW_HPBL8UK*ZkjY_K%n^Gb zB~o4j={ubCanjETN63#3NGyfqc}g)Zj^8Qw`6VOU{-wkC9U#$RpkBYvA=j6i+UOW( zfRD*Q{yW6ZRB+nGX$Pm_<oi$jdg`*%ccs#I#qGONo~fQVS)PFit>WH2eDoDQTEWL$ ze9URSbOdyydc7c9XMTAxZ4Va|d&P^^%>^`k*SwH#Wxb5>V(f$9g~4j5H1)y~TbR3Z zb4s3_ynW5<&qHl7Sh^$A{L12k<U9Ec`RaWv-iV*Tj-o*>({Yf_L1H^VYC%B|swh_W zpDGHKLuGYq<=ezoqMWFrA*b`Lq7kR_t)i~7|5Q;=*?->VsfAI`SUCni;e7{<AAD;# TAwZtA$Y?}3UPEsa-;;j;9se+} literal 0 HcmV?d00001 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 GIT binary patch literal 518 zcmZuu%}N6?5YBd65y6{Raq(h%5kyZSqEztWAJig9Af(B(4c#WoBwMH_-@-RgicjGi zRPZ1@37)(Oy?JuhUj&EA<O?(T=I>^HevXl>Y^}BL=zcC9-x7a;=>~x-R${<3yN(#U zrSmBf(~&NvQNMIv`oJ;a_&g?DZm?SAVyTh0yh76g^hqXFPj(<N)&wI{a{>CL;HgEE zMdhr|`yeuOI#)sDnU(>xfC1P*0Si7z45BC7Jt@9|@u*gwR5CO+OqTsmqSfZd-;+<K z-vY2`2+L$fY+B@f8`U>?(^F|&_J^v=k1gz>835mNii)wp^AqwqD^uRI<Unu2Fmdgq zkt4#8*IkYtk~4=rzN-h)D$q&2E7KHg2RwC}oIxu&1=Y1KbsYnqAEPE7acC4e$~`a& z#6G$_Tjw&%_-`Lvh+<MgtY*Wv*{wbeCWUP*7FI04?~r+oqbPc0mCMR_X62q$A6RwF Ts!!}-{8yh?ef*!|ERnne??<EG literal 0 HcmV?d00001 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 00000000..192c306e --- /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 00000000..cdd27f12 --- /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 00000000..d89bad39 --- /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 00000000..7184b10f --- /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 GIT binary patch literal 560 zcmZ9Jy-veW423--@hC;@4W%qhl^Bqi7?^KLN<&HlNi)F11K+Vpgiz!mK0iM8{r)QL zXtlN0SY^H4@U85^Hq_G2?aX%GKf&2k!V^fcOBl&3SO?4K2iPZD;Mei@N>A>evv+|) zm43a2?wBp#Yx*%e96Pjf$?hY@5{Bkpx%w77GcnY16<++q7PfVl!DmP<R_s>W6G^ip z(r;W_v%vt8!Ja*NXCs~1J+==09qC(pfth9xZ4en6`g_u4?(t?HxE@H-&OXW!cesbs z!yMr~xT>02@>_c@d359|xtOx7L4-z@o}}+MR3ugYDQ)qGGcx7qFH(|mV(1lDKH<@~ PZT!7Pb{Av1Yb5;vqmxi% literal 0 HcmV?d00001 diff --git a/Orders_Microservice_Group3/run.py b/Orders_Microservice_Group3/run.py new file mode 100644 index 00000000..b26a5df8 --- /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/Dockerfile b/Product_MicroService_Group3/Dockerfile index e51666e8..ae9cf476 100644 --- a/Product_MicroService_Group3/Dockerfile +++ b/Product_MicroService_Group3/Dockerfile @@ -1,22 +1,65 @@ FROM python:3.11.4 +#Copy requirements COPY requirements.txt /product_ms/ COPY app /product_ms/ +#Set working direcroty WORKDIR /product_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/* -# Set environment variables for ODBC configuration if needed + +#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 + + +RUN apt-get install -y libgssapi-krb5-2 + + +#Set environment variables for ODBC configuration ENV ODBCINI=/etc/odbc.ini ENV ODBCSYSINI=/etc diff --git a/Product_MicroService_Group3/app/__pycache__/config.cpython-311.pyc b/Product_MicroService_Group3/app/__pycache__/config.cpython-311.pyc index 24ec9fb0533112f07ac3fe8e36eedc6a3f03e748..333b2f6a931f7163b6335d840c3370775f00b552 100644 GIT binary patch delta 96 zcmZo;Uck(|oR^o20SJQp&C@C;@=7u)O;nfTWQ$@=VGL%_WS{7z!dt~@Xk@Nu0EC8` rY!eH#*>16T_y>nfoV}5Y7pRjFh>LY6hcT-2Jzy7VU;)7*ZlE9l(!Ufr delta 69 zcmZ3$+{VnioR^o20SIDE8Pbv`@=7wwO;nd-WejG}WSi)x!lcPMv0i)PhK*c2KsAg& TT&yuUn^B#!fv16|2&54J-$e~+ diff --git a/Product_MicroService_Group3/app/config.py b/Product_MicroService_Group3/app/config.py index 96b98372..dd7fdaa8 100644 --- a/Product_MicroService_Group3/app/config.py +++ b/Product_MicroService_Group3/app/config.py @@ -6,4 +6,6 @@ SECRET_KEY = "Group3" PORT = 5001 -KAFKA_SERVER= "kafka:9092" \ No newline at end of file +KAFKA_SERVER= "kafka:9092" + +HOST = "0.0.0.0" \ No newline at end of file diff --git a/Product_MicroService_Group3/app/controllers/__pycache__/getReviewsController.cpython-311.pyc b/Product_MicroService_Group3/app/controllers/__pycache__/getReviewsController.cpython-311.pyc index 6c78e2bcbd74045dce7a609453092db0728bf0ef..935fb47d5ddd11cd0ad7865e16dcd71b61d40f11 100644 GIT binary patch delta 369 zcmcaF)G5rnoR^o20SKzurPHz}@=7x9o2YJCpTdyBlEanD9mUPaz{HTsn8KRMvy6#> zVKop#KooB(?*cv;51CG3OJPrET*HB?K83S|VHr@_YPixUexS+Rshn%LmN5dwffxd! z1X5VJTNt7QC*JVp<?(iO^LC66b`1)14ce^0$i>LWGg+Idl97M%Ql_V@5<o3nllz%# zHcPXVFfj^Gp1@|rC@}djn>N2VP^w52MyO2w%l3~^X!0L+OHsDu{JgZx^de56<So|h z#I)?hBCg4{94h)C<BAkudR8(NNrKoQlYVj7<mRW8=A_ycnE<&U#}?n1Jb}YS=mvxQ f1ynTo3P(KmikJ)BRu{Rgu5epTw&#>#0ht5<#k@=d delta 335 zcmeAazAwbPoR^o20SHRw3#R!^<dtOHG*R8Mo{1rqF@+_SYZ(&*!)hRgfGF-%?gczB z9x|Q6n!=XOxP~27eF{el!!n?<)o`Uzyg-vVQ#jXfEn@_V12F_d@uhILFhudE@B}kx z^1ht-+GVpnBReA__hfgbN=ClP2brF-iUXB$PF~GiBT&Vclb@WJlaXIsVr6MyX|!3L zrG$x5X!0C3BS!wo=h?LR#eiyyL|}ySWKQ;fi~^H6I4n6>vlG*@6N@+}hjFOrgN!Va zhbddhP$U6jgEar*u*uC&Da}c>D>4FdK@KfGK6xdF%jEwY@jMrFZ7*=!UF5dA!fiJ> KlT(HTqz?cr*F%;7 diff --git a/Product_MicroService_Group3/app/controllers/addReviewController.py b/Product_MicroService_Group3/app/controllers/addReviewController.py index 4f85e35e..eec24c94 100644 --- a/Product_MicroService_Group3/app/controllers/addReviewController.py +++ b/Product_MicroService_Group3/app/controllers/addReviewController.py @@ -1,5 +1,6 @@ from flask import Blueprint, jsonify, request, json, session from models.addReview import add_user_review +from config import HOST, PORT import requests @@ -13,20 +14,20 @@ def get_username_from_user_microservice(productID): user_id = session.get("user_id") - if user_id: - if request.method == 'GET': + if user_id: #Check if session is set + if request.method == "GET": product_id = productID - response = requests.post('http://localhost:5000/user/getUsername', json={'id': user_id}) + response = requests.post(f"{HOST}:{PORT}/user/getUsername", json={"id": user_id}) #Send http request to user microservice if response.status_code == 200: - username = response.json()['username'] + username = response.json()["username"] userID = user_id - session['username'] = username - session['productID'] = product_id - + session["username"] = username + session["productID"] = product_id + #Data in json format rating_info = { "UserID" : userID, "ProductID" : product_id, @@ -47,14 +48,14 @@ def get_username_from_user_microservice(productID): - +#Add a product review with the username gotten @add_review_bp.route("/product/<int:productID>/addReview", methods=["POST"]) def add_review(productID): user_id = session.get("user_id") if user_id: - if request.method == 'POST': + if request.method == "POST": data = request.get_json() review = data.get("review") @@ -63,7 +64,7 @@ def add_review(productID): username = session.get('username') product_id = session.get('productID') - if review.strip() != "": + if review.strip() != "": #Check if review is empty if username is None: return {"error": "Username is not available"} @@ -72,6 +73,7 @@ def add_review(productID): if product_id is None: return {"error": "Product ID is not available"} + #Check if rating is valid if isinstance(rating, int) and 1 <= rating <= 5: review_info = { @@ -82,7 +84,7 @@ def add_review(productID): "Username" : username } - user_review_message = add_user_review(review_info) + user_review_message = add_user_review(review_info) #Send data to database return user_review_message else: diff --git a/Product_MicroService_Group3/app/controllers/getProductController.py b/Product_MicroService_Group3/app/controllers/getProductController.py index 88c9f2c6..4ae868d3 100644 --- a/Product_MicroService_Group3/app/controllers/getProductController.py +++ b/Product_MicroService_Group3/app/controllers/getProductController.py @@ -4,7 +4,7 @@ from models.getProduct import get_product display_product_bp = Blueprint("product",__name__) - +#Display product with a given product ID @display_product_bp.route("/product/<int:productID>", methods=["GET"]) def display_product(productID): @@ -20,7 +20,7 @@ def display_product(productID): # Convert to JSON #json_user_data = json.dumps(user_data) - product, images, reviews = get_product(product_id) #Send user info to database + product, images, reviews = get_product(product_id) #Retrieve product data from database customers = [review_data["CustomerID"] for review_data in reviews] diff --git a/Product_MicroService_Group3/app/controllers/getReviewsController.py b/Product_MicroService_Group3/app/controllers/getReviewsController.py index 3ecdc45c..f55b5c96 100644 --- a/Product_MicroService_Group3/app/controllers/getReviewsController.py +++ b/Product_MicroService_Group3/app/controllers/getReviewsController.py @@ -34,9 +34,11 @@ def get_review(): producer = KafkaProducer(bootstrap_servers = KAFKA_SERVER) def send_review_message(reviews): + #Publish message metadata =producer.send("customer_reviews", json.dumps(reviews).encode("utf_8")) try: record_metadata = metadata.get(timeout=10) + #Print out message for confirmation in logs print("Message sent successfully!") print("Topic:", record_metadata.topic) print("Partition:", record_metadata.partition) diff --git a/Product_MicroService_Group3/app/controllers/productHomeController.py b/Product_MicroService_Group3/app/controllers/productHomeController.py index 4acfaf5e..3ca6998d 100644 --- a/Product_MicroService_Group3/app/controllers/productHomeController.py +++ b/Product_MicroService_Group3/app/controllers/productHomeController.py @@ -4,7 +4,7 @@ from models.productHome import get_product_by_section product_home_bp = Blueprint("home",__name__) - +#Display products on home page @product_home_bp.route("/product/home", methods=["POST"]) def product_section(): @@ -20,8 +20,7 @@ def product_section(): # Convert to JSON #json_user_data = json.dumps(user_data) - products = get_product_by_section(category_id) #Send user info to database - #customers = [review_data["CustomerID"] for review_data in reviews] + products = get_product_by_section(category_id) #Get products return jsonify({"products" : products, "session" : user_id}) diff --git a/Product_MicroService_Group3/app/controllers/updateProductController.py b/Product_MicroService_Group3/app/controllers/updateProductController.py index 70d31a74..3b499c40 100644 --- a/Product_MicroService_Group3/app/controllers/updateProductController.py +++ b/Product_MicroService_Group3/app/controllers/updateProductController.py @@ -7,7 +7,7 @@ import requests update_product_bp = Blueprint("updateProduct",__name__) - +#Update a product @update_product_bp.route("/product/updateProduct", methods=["POST"]) def update_product(): @@ -22,8 +22,10 @@ def update_product(): product_id = data.get("product_id") #username = session.get('username') + #Check if price is int or float if isinstance(data.get("price"), (int, float)): - + + #Check if quantity is int if isinstance(data.get("quantity"), int): info = { "quantity" : quantity, @@ -31,7 +33,7 @@ def update_product(): "product_id" : product_id } - update = update_product_info(info) + update = update_product_info(info) #Send updated info to database if "message" in update: event_data = {"quantity" : quantity, "price" : price, "product_id" : product_id} publish_product_updated_event(event_data) @@ -51,4 +53,4 @@ def update_product(): return {"error" : "null"} else: - return {"error" : "You need to be logged in to add a review"} \ No newline at end of file + return {"error" : "You need to be logged in to update a product"} \ No newline at end of file diff --git a/Product_MicroService_Group3/app/index.py b/Product_MicroService_Group3/app/index.py index 676b86d8..fa5047e5 100644 --- a/Product_MicroService_Group3/app/index.py +++ b/Product_MicroService_Group3/app/index.py @@ -3,7 +3,7 @@ from flask_cors import CORS from flask import jsonify -from config import DEBUG, SECRET_KEY, PORT +from config import DEBUG, SECRET_KEY, PORT, HOST import os import requests import subscribers @@ -21,11 +21,24 @@ app = Flask(__name__) CORS(app) -app.secret_key = SECRET_KEY +#Check if applcation is running in docker to get or set app secret key +try: -# Read user microservice URL from environment variable -USER_MICROSERVICE_URL = os.getenv('USER_MICROSERVICE_URL', 'http://127.0.0.1:5000') + #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 #subscribers.consume_username_updated_event() @@ -55,9 +68,9 @@ app.register_blueprint(update_product_bp) - if __name__ == '__main__': subscribers.start_kafka_consumer() + subscribers.start_price_updated_consumer() - app.run(debug=DEBUG, port=PORT) \ No newline at end of file + app.run(host=HOST, debug=DEBUG, port=PORT) \ No newline at end of file diff --git a/Product_MicroService_Group3/app/models/__pycache__/database_connection.cpython-311.pyc b/Product_MicroService_Group3/app/models/__pycache__/database_connection.cpython-311.pyc index 005839d68435047d092e0b3a8b7c4d965cb7ff3d..faa64fe46341a4279d6dc734d086cc8516d4bdde 100644 GIT binary patch literal 1265 zcmZWo&2Jk;6rcU@dTryHBn=f2jYdF;ERhc|QVS+Xj%^@PiQ70KYP6EI-WewbduN&1 zZDM0rIdJfS3#T3s5+@KsLhvW##&Ip>5Uqq%3FW}eQZ7|by!A&@!yE1Iy|=Ub-u!-V z_vd6Xj=<#7?b>fLLVt(J#FTMx`7Q*H5kW+1p#71T_9YonnaDp$2>lAz$RtFRZ_vI% zq%umY|AaTU+KVO66?H-}sbY)SHnrS3vvJL{hk-SIcjyv;Vc$z1;4yNaS4PnNzrA9J z$X)2zm5ADvNu;X~t*eq~NBtfVy@LQ_9SJbrkpUAO1@NUG65WV9;Rap40Nx|(M5a5G z(HqFsCc6l|iTFZSn>tf+`V9#^0DZdJBaK`ukE0{$2puaA(2<l*ZMBn|HqMu}wu<>3 zT-azQGViV2d4J_jW+jseW*yFmXSt$j+U5amQrit;;;V+B{2}E*a*tMbsCD=WXP%R3 z-z*h2^0>h3u!rBdjcbhK^8LHGJbbzxEo^UoUff=9>)CQ~dl<#Dh1^bVBUdi2w<Foz z%|htz?SZ?I-Qk{aDXHY24`|(H+4gI@Ha&J=Vw7OYIkaGw<#EWqrrnRzY7lXF9ge9v zEk>$V5FHOVh!u}5>V$(%M+0rlKqsbaR!u<z-Gf`U*@Vb3g*alI1R5D~31+T7l8SJl z{6Qd55rsM6kv;n(|ADa!1%zQXTh^gbvguF<qrfaLlua1-V3*lu!`QV$fkfSHVOGOs zk8|2G^33Cc;yuQ{G;-vjX<NW3e`q!u)IOjB*KG`9<4|pzHP}I&LdDT=DxcLY&O(vv z7OjkCVVI6%G#Q}{VN57iu2`%%tsp*5E2PTjfJ#V5^Z`!LUuvwk+E*9O)CFH%7|1V2 z=AX<g_O$c4rJjC1w;00f05fYnZJ?r?pUOYh1}O9+{Cz6>Q-5*K->XceHT%VM6#M$C z7peJgANh-`{nXl7YR%Wzo?axb50Dy}zk&-r>0f)huP>kJ%f7z+Bz3*#P1aMeK@1)T zFKz&<?^bgXI+fzNTgqu7mBY#@jzFANxemL5%mfb=7)tRAx`Yt%S%7EyhoGa^pdazD zO!)hYJitJaB<UO_PloFp#ZHE6pdm>+iTK)EeYA9jmVC4{P-i7L_5Xpt0(JfcMblqs delta 567 zcmey!xty(jIWI340}v=_{7TJYWMFs<;=lkCl<`>v$e7NM!jQt4!w|)g!qmbL#hAhv z%%I8q5~Rd08LALWaRNzZApRTyB!IdYYk@jy8B>^RnNnD4nNwJ67-lo1u+=aE$$Iu0 zCLqO8!we)j=W^DvlmHz810V-MKn=?>AbT~O544)g?-qx1MrLAeVs_#!j)0>4l+xsq z;woNe4^Ky5M{h^=+{)yPTMSjwE<v7Qu0gid!GS&s!Kp=MsYSKc!LC6dv8u`M7^U<i ztV4=Qi%U{d;+^yJ@=}vaGV}9nD^rWDHJNU)6;$S@BqiTsPliZovQAE8QWqD5a)B!2 zi%W_!^U{l1fi9iAk?CkXKac_96c+%A28IW`;tg&$_$3=WZt%;42*C!A4=fCl-b_2# zJ}`i22zf#SnRg*F5rvykfXs!kFR+L{<reI*yC9`~kz3~qx6TC?ozD#MKwCALir9fv z5y&Yk8HxlzY(60Ii^C=t7*08<c11!!E+{yQ)q%tZW=2NF8w|V+VEBQ9lTr5r1114B F2mr29h*SUo diff --git a/Product_MicroService_Group3/app/models/__pycache__/updateProductQuantity.cpython-311.pyc b/Product_MicroService_Group3/app/models/__pycache__/updateProductQuantity.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a2b40c54d9e58ea7ca34020c7460ff6c144c331 GIT binary patch literal 2500 zcmcguUq~EB7@xhp_2$fZdNwNN{If($xf-vSv;<62WA&04QfqsPja`s+chrr0yVu!0 z^{!_Lr4MNcghC+?rI07n;$vU>SP}zy+>-;3g+ih9p>GEgko2YB+#k;~Z7B)q?Ck6} z^ZomM-^_gMgQliN1a0WEp~XK1gnna_YV%Zxy|;n5hg76;I+|l&kIp4La~_V-yv`@Q zbKVlo>B5|#dcQ<-4JsE$5#bMJVlu+Hz8jWlXp3ne8x_+qh+@yH3kp|p!9ES}^6>6` z4C6iINA@A^CNQ?(Ew>FW%iTZ3t*#?<M9yPFP}Qb#o1n9Gpa+mW8+_JtpLu<*W%(=w z*LkoGGjDCS=-GtyY*kZ)I0T5i2f~MldPLw;P#ZKZ>!HWN^C5IKm7^M2j<$jI|0Ekn zany(GK+W0>UzP4hRNnB`WyF{Dev7{I9L)=O!&R-r-=oM>tok)h@mz<4u;KmO`zoU< zdsyS_)*7O}iKy|VBRckfN3@34`Rizn>qD<9e`~1fBNCX*w2s=My-Y+^w&excBGG6x z6Q7wHADxbg>Vg@aqNbWs>@i^L=8_nXO^b2cR8~Gr$%d`jY4O65`Jgx=&R&Uq6ca0| z6XO@ek#laSsxg(K$})ITUH^fE>q`*Jl9x!PyDBE8l7NY*qLoq<U@oR~J)IdCuiz93 zr6v_Mqart-ECZeYv;u5cbcGm`$pq_lGVjb7WIYK*2aK1kn2M63F#9)anU<q!kw(fc zx!VBBmPuV9Nj1ZEePo>|DVxB$nMi21D=4~Y!8DmRp~_J|)4|l#^#xg3as9D%g(Pjw zG$MlQW!rF26k(0BitHXQ=i*R|gr;4NSgZ_)tUdd2Y*?DH2(=_Rkye(a4-7I+wN)aG zn@TD{4BL{XfNL7EF3lLgpcdObb5V?^C?#oW%!DY2IBU`sX;fX64FwW1wk+#9F_wtM zax+U7#A%`|8zvkDjex~U&fnJ*YQ_m&)f6&+nVPBO8A(nirG%*x-IB`aE5g<NjV9A> z$8&L&4;AfzxLDD#L@25^QPKOl(EEE^@7K~d(yhiqD7+gwxf42>3-#wi{kIx^!A(x^ zWDfV`ai4?xiY-V?a}Mq*;Nach?V!^!@V)Asxs;DyescWDN`7L_8T=%Nr974#EEOA( z|FvD*xq~}%IGo2}2Zw)c>2$izInC#bT`166M4Ufd2(;e4cKg~_lXoU>O%{%|vBlm( zpnW&cwG-&d1$y#<9;eicJaG1(hC%br`6A+lQ?;RlbmXT|CpZE<hcD*wMF(Fj;MQFn z-ofD<?#|<G2X_}*I-C=4I?V$PuImun3j*5T-+vlH0RYYm(b`Z#H1V_S1Sg>9@YOuN z>fo#YfasLdJm}!MUTk;?M8yz*0c88dz>8b4uE0t8Vl?_*4|>?s96QTD9E^<n`A6*> z(2qL2v0=3BZvuL|JrX<3Z;!C`$B3;zJ}of%EYIlSw=PBah>tddIagTJWow19zXA6| z`5Z^t<zzK-zVg$;?q{h2_~1S)X~t6N-2Q;}Knc-y7@pztpqtXkyR;jo>~F)Gh5^n9 l#}!c1&C*jqolbo(pdqKe7f|qK=_%qjxZWaqexO}o_%G+OWhnpv literal 0 HcmV?d00001 diff --git a/Product_MicroService_Group3/app/models/addReview.py b/Product_MicroService_Group3/app/models/addReview.py index 8f67372f..7946a664 100644 --- a/Product_MicroService_Group3/app/models/addReview.py +++ b/Product_MicroService_Group3/app/models/addReview.py @@ -6,20 +6,20 @@ from models.database_connection import connect_db def add_user_review(data): - try: #error handling + try: #Error handling connection = connect_db() cursor = connection.cursor() - #insert data into reviews and ratings table + #Insert data into reviews and ratings table insert_user_query = '''INSERT INTO dbo.ReviewsAndRatings (CustomerID, ProductID, Review, rating, Username) VALUES (?, ?, ?, ?, ?);''' cursor.execute(insert_user_query, (data["UserID"], data["ProductID"], data["Review"], data["Rating"], data["Username"])) - #commit changes to database if no errors + #Commit changes to database if no errors connection.commit() return {"message" : "Review added successfully"} diff --git a/Product_MicroService_Group3/app/models/database_connection.py b/Product_MicroService_Group3/app/models/database_connection.py index 0986cea0..4179c446 100644 --- a/Product_MicroService_Group3/app/models/database_connection.py +++ b/Product_MicroService_Group3/app/models/database_connection.py @@ -1,14 +1,25 @@ import pyodbc +import os - +#Code to connect to the database +print("Outside db connection function") #Connect to database def connect_db(): - - server = 'Chiamaka' - database = 'Products' - username = 'CHIAMAKA\amych' - password = '' - - connection_string = f'DRIVER={{SQL Server}};SERVER={server};DATABASE={database};UID={username};PWD={password};Trusted_Connection=yes;' - - return pyodbc.connect(connection_string) \ No newline at end of file + print("In CONNECT DB") + try: + + server = '34.89.83.33' + database = 'productsmanagement' + 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/Product_MicroService_Group3/app/models/updateProduct.py b/Product_MicroService_Group3/app/models/updateProduct.py index 4ad88367..90ab9981 100644 --- a/Product_MicroService_Group3/app/models/updateProduct.py +++ b/Product_MicroService_Group3/app/models/updateProduct.py @@ -23,7 +23,7 @@ WHERE - #commit changes to database if no errors + #Commit changes to database if no errors connection.commit() return {"message" : "Product updated successfully"} @@ -35,7 +35,7 @@ WHERE except Exception as e: #more error handling print(f"Unexpected error occured in add_review: {e}") - connection.rollback() + connection.rollback() #Rollback if errors return {"Error" : "Unexpected error"} finally: diff --git a/Product_MicroService_Group3/app/models/updateProductQuantity.py b/Product_MicroService_Group3/app/models/updateProductQuantity.py new file mode 100644 index 00000000..ff9022bc --- /dev/null +++ b/Product_MicroService_Group3/app/models/updateProductQuantity.py @@ -0,0 +1,47 @@ +import pyodbc +from flask import jsonify +from models.database_connection import connect_db +import logging + + + +def update_product_quantity(data): + + try: #error handling + + connection = connect_db() + cursor = connection.cursor() + print("At the database...") + + #Collect image information from database + #stock_query = "SELECT StockQuantity FROM dbo.ProductCatalog WHERE ProductID = ?" + #cursor.execute(stock_query, data["ProductID"]) + #stock = cursor.fetchall() + + #insert data into reviews and ratings table + update_product_query = '''UPDATE dbo.ProductCatalog SET StockQuantity = StockQuantity - ? WHERE ProductID= ?;''' + cursor.execute(update_product_query, (data["QuantityPurchased"], data["ProductID"])) + + + + #commit changes to database if no errors + connection.commit() + + return {"message" : "Quantity updated successfully"} + #return {"message" : stock} + + except pyodbc.Error as e: #more error handling + print(f"Database error in update_product_quantity: {e}") + connection.rollback() + return {"Error" : "Database error"} + + except Exception as e: #more error handling + print(f"Unexpected error occured in update_product_quantity: {e}") + connection.rollback() + return {"Error" : "Unexpected error"} + + finally: + if cursor: + cursor.close() + if connection: + connection.close() \ No newline at end of file diff --git a/Product_MicroService_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-311.pyc b/Product_MicroService_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-311.pyc index 0dc8ca0740bb9e53a5d54a2c55ad96fb36f17dbe..ffc53d552abe70db16ea1ef55d9e215d78d8c986 100644 GIT binary patch delta 374 zcmZ1=bXkaZIWI340}vczmrg61$ScVhHBnvNB$q9UjgcXRA%!J}J&K))A(b(eZ4K)( zMh1q}Knwv<94Txq3{jjZ>_Cz$g=J!yg`g(mEgo-2H*d%IVAr59*C4-%`?Vd80M$=t zD1mEaU?^dN8N$G@h7r}+T80#+TE-OSS|%W7u3=cfG+B{Rc(O60lqx$yR}EtgQw{SP zmSxO9Cjl`8)UwtvOio}C<EUXxXG~#T!!~&Wqa+i%-{cL9IUKA-EI?I7Y@6ko+!!Uf zf$ZWYAko0^R9Jay&IMuTi^9%Vgq=6nGjC*ORM>3DF2TsiJ=u#xnd=r?a(-S~W_l6Z z<SY(7E)$?GkY|e9CokeK(!RkUe*qOeVBl^5!w1|F9kwfME^u31<hHoNZ87;BhY<j} CGf{&8 delta 358 zcmcaCv_Ob=IWI340}!M%38qC(<dtOfo2ag?5yi^Hkjj|CvW9gTBLl-~AclY_wiLD& zhA8$Fb|A@-!aT9bLeTFQUrv5<VopYWafy|sfu+&J)7oacfa<3+l)yCtEnr;3glbqV zLke>((2`mvAZD&%Sim^hj8Qk46=oR&Lk(jMQw=lF5zIhG05JsAvI5n@c`#8BUBjBr zn8LP(eHjx_JrF|xBSQ*9Fc@oc_!Y4M1t%Y5%wc9JV%coU<i;ok@_%tNkZ53dDy)3L z%<Y1(`$b{*E5h!Zr!a41W|ZIT#xB9g$T>NlLwRyPhc=fnP%X%3#buL^a2QEFVBl^5 b!w1|F9kv&=tuJufT;#U7!fi8Ik<$nOER9GD diff --git a/Product_MicroService_Group3/app/publishers/kafkaPublishers.py b/Product_MicroService_Group3/app/publishers/kafkaPublishers.py index d03504a6..f316dd3b 100644 --- a/Product_MicroService_Group3/app/publishers/kafkaPublishers.py +++ b/Product_MicroService_Group3/app/publishers/kafkaPublishers.py @@ -9,30 +9,30 @@ producer = KafkaProducer(bootstrap_servers=KAFKA_SERVER) #Creates the topic def create_product_updated_topic(): - # Create KafkaAdminClient instance + admin_client = KafkaAdminClient(bootstrap_servers=KAFKA_SERVER) - # Define the topic name and configuration + #Set topic name topic_name = "product_updated_topic" num_partitions = 1 replication_factor = 1 - # Retrieve the list of existing topics + #Get topics topic_metadata = admin_client.list_topics() - # Check if the topic already exists + #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) #Function is called in updateProfileControllers.py 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 + #Publish the event data_to_send = producer.send("product_updated_topic", value=event_json.encode("utf-8")) try: record_metadata = data_to_send.get(timeout=10) diff --git a/Product_MicroService_Group3/app/subscribers/UpdateProductQuantitySubscriber.py b/Product_MicroService_Group3/app/subscribers/UpdateProductQuantitySubscriber.py new file mode 100644 index 00000000..f8c86dee --- /dev/null +++ b/Product_MicroService_Group3/app/subscribers/UpdateProductQuantitySubscriber.py @@ -0,0 +1,32 @@ +from kafka import KafkaConsumer + +from config import KAFKA_SERVER + +from models.updateProductQuantity import update_product_quantity + +from threading import Thread + + +import json +import logging + +#This function is called in the "__init__.py" file in the "subscribers" folder +def consume_product_price_updated_event(): + #Logging information + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + logging.info("Consuming product price updated event...") + consumer = KafkaConsumer("QuantityUpdateFromOrders", bootstrap_servers=KAFKA_SERVER) + for message in consumer: + product_data_str = message.value.decode("utf-8") + product_data = json.loads(product_data_str) + print("I am here") + print(product_data) + update_product_quantity(product_data) + +def start_price_updated_consumer(): + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + logging.info("Starting Kafka price updated consumer...") + print("Hello from kafka consumer") + kafka_thread = Thread(target=consume_product_price_updated_event) + kafka_thread.daemon = True #Threading to avoid blocking of the Flask server logs + kafka_thread.start() \ No newline at end of file diff --git a/Product_MicroService_Group3/app/subscribers/__init__.py b/Product_MicroService_Group3/app/subscribers/__init__.py index 377b8371..2e03bd03 100644 --- a/Product_MicroService_Group3/app/subscribers/__init__.py +++ b/Product_MicroService_Group3/app/subscribers/__init__.py @@ -1,5 +1,10 @@ print("Subscribers package initialized") -from subscribers.updateUsernameSubscriber import consume_username_updated_event -from subscribers.updateUsernameSubscriber import start_kafka_consumer \ No newline at end of file +from subscribers.updateUsernameSubscriber import start_kafka_consumer + +from subscribers.UpdateProductQuantitySubscriber import start_price_updated_consumer + +from subscribers.UpdateProductQuantitySubscriber import consume_product_price_updated_event + +from subscribers.updateUsernameSubscriber import consume_username_updated_event \ No newline at end of file diff --git a/Product_MicroService_Group3/app/subscribers/__pycache__/UpdateProductQuantitySubscriber.cpython-311.pyc b/Product_MicroService_Group3/app/subscribers/__pycache__/UpdateProductQuantitySubscriber.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4071d3b04bf8e013fb60c7483a77dbdb9b06a94d GIT binary patch literal 2182 zcmc&#%}*Og6rZ(c?KPMHqUFn^*(L(v14J!{qLx-gd^8ah8a^6iIaw{cV`JD4cV>+Q zG7^UzsMKSnUQ&q@RYVT`8+xy_jvNK8goM;nr5upBaq63~*I?+Sr;caeyqP!i-kW*v z{rp>7TML5rzWhn<iHy)+d=j=uow-;7<`-llQ?igPWh9C75i4RxGf}}uEo{pfS@773 z+3`$V@Uo?36xb_UiA=(by+D~3GY+)Xl$TLj`I{R^OF`S5p4-x=T!)oxLSZ2}H#s{u zsV&beeLu4V^PW=C)IFjVscV)DPy3;yJ6^%t0a0vagA(0bFzU{V0RxS~caf2}=N{0o zZ8mr>T!L{kyer)Cb>s+U$Bh-K`8?Mvni)L;UB?Z5urCqH5HhhRUbeRKT5i_4hstOg zJ$tq%m8H#Cc<L}7a@R*Q)@)}l;&oohHybv~ksJG>-iKHF%y_dDyuBtZ-@Z%F)!Ez9 zpPrkDM{waXJvgj0!z<V%&D0TfaM&W-#B%h;+$N0ad62$}1hNnYv7Ae7-P;|mg}mV8 z)p}%MEEq(sh1*m?mE(<$jt0F?>JeWRi7-oDdy$%iGRT0=b=UQnNA;q{2;GLoUAg4t zM#gs&k5%1PHwY!^WDvL9d>%{%t?N1~7+^YA$OriG!t7#z3l6x%BTISe1oF0Sl}HdX ziQ$?gz?;l<z<F0USs;Upjz^(bP#On{QP0{SUcYG25oRf*tgeA$LGt<v;}%qCmw!xs zo?Qi(Sys1qjE(G~L#AnAn`Eb50}8?MSoS-Rx{hvTR~-;g205>~Id!>2DcQ+Rxh2Yo z`qZUc*-3L-cMM{xQyaQv5hqWWT5!~-WL;e$#)jj<^$P?v)=TKyf<fJ7crSQw?HlTr ziep*5Sj@80Ix}ctox4?g?D~l?0?UmJqs5)zLH+)X(i8#I>H*Y50O<hS_zryR7|1?4 z#jRD`^K1U4<&Qo0u~xxa6>GqN;KjV(`9%d!RPlt5Cr;Z3{JWq1IpMdjRod68?Q8pw zPP$U(NR~$hIf$R6?!Wx<UFzYR)WhH7mDG4OHSR0Dr#-2kcm4aHR(i&&J!1#SQ>E=- ztD^K*m4098=QFFKq^e5FS5l|Sy~AWh8L28GzUb$zq52DO7yUc1ya&nu1uVA;xt04_ zYhE(s5CYI?0;oM?#>z-*fJ_-3Dp$L&xFcYBq-u==Ih1;Qf%46i!_DsSvZqsz*R4SA z8&w;Y1QhOW-y>pKu9|~_Rkt|GtD%%*H)zQdZzY|eJUwVTCmoz{fTP`<aBvg}1l6b$ zo7W-Z#^HEUDAYXh2f#QEt26~P7!W%kC3$X#sTkU&4`53le9Qv!pRy4r{FcEA9;)IY z9}k^&^}YRg+V7gFbj?(|X7=Y#`ajyAhs-{~9q(}W8{A#Ny;a=nhn?O9gMdV`@LRx5 z5CgXWhib4hU<2A%Y_#U`jk*(v6C`T4g{QB*%m<*d_ISL=#NA#YVMsj1r7{6JOBVTx zra{i%i2VrUJSs`j3A*Pu_p|0HNYBvMese!V1AcQqk0B|!-^za{=+3_QoyQUq)M$fr N$E3b<bejlQ{{en~9|8aX literal 0 HcmV?d00001 diff --git a/Product_MicroService_Group3/app/subscribers/__pycache__/__init__.cpython-311.pyc b/Product_MicroService_Group3/app/subscribers/__pycache__/__init__.cpython-311.pyc index 3983da2bfc76957fedcc9a12c59acbeee1d68af6..64318b1c819099d356bc3ebd32e9e922a9efef7f 100644 GIT binary patch delta 354 zcmeBXIl;=eoR^o20SKI`4by5FC-O-!`b<>UQDx3$iDF@7NMTH2$zjfAjba6}S#ub3 z*`nBhY_?zqP4<ZinlU29C5c5P@!5%K*@^MV`FX{qxv52(jJISU;sr&S$*J+B1u2Oo zsVT_v%22iO1x5KOrO72g8d+s(S!!O%#5N^nKcF>-jVy0z7ndd#Cl_TVr4|+Ig@Vls zfanY?P0TCFEU65JD=1<CdZ>sMM6gZ#eyEZc$YKQI;&dSKftit!@dg8H1M3Ag^@|J| rR~R%dFlc;WV_<Y+yujd!j2<wATtGz+7@{wrq6ZBA7qFosZlGNNiAZtZ delta 148 zcmX@X+RehZoR^o20SNrK+0u?MOyrYbG?}Qb!^@b<9L3DYkirtopvgM1LUR(M{KR<@ z%zm0Ila&~an2J~?_c9&|0_kJ~;$jCN@qw9<k?{rtYXj>AHuZ}P8dn%JE-+|3VDP_y QiXJeyUciQmIDm!#0J;|?jsO4v diff --git a/Product_MicroService_Group3/app/subscribers/updateUsernameSubscriber.py b/Product_MicroService_Group3/app/subscribers/updateUsernameSubscriber.py index 4235a17f..7f020bb2 100644 --- a/Product_MicroService_Group3/app/subscribers/updateUsernameSubscriber.py +++ b/Product_MicroService_Group3/app/subscribers/updateUsernameSubscriber.py @@ -15,7 +15,7 @@ def consume_username_updated_event(): logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logging.info("Consuming username updated event...") consumer = KafkaConsumer("profile_updated_topic", bootstrap_servers=KAFKA_SERVER) - for message in consumer: + for message in consumer: #Consume data profile_data_str = message.value.decode("utf-8") profile_data = json.loads(profile_data_str) print("I am here") @@ -27,8 +27,5 @@ def start_kafka_consumer(): logging.info("Starting Kafka consumer...") print("Hello from kafka consumer") kafka_thread = Thread(target=consume_username_updated_event) - kafka_thread.daemon = True # Daemonize the thread so it will be automatically killed when the main thread exits - kafka_thread.start() - -# Call the start_kafka_consumer function to start the Kafka consumer thread - \ No newline at end of file + kafka_thread.daemon = True #Threading to avoid blocking of the Flask server logs + kafka_thread.start() \ No newline at end of file diff --git a/Product_MicroService_Group3/docker-compose.yml b/Product_MicroService_Group3/docker-compose.yml new file mode 100644 index 00000000..84a862be --- /dev/null +++ b/Product_MicroService_Group3/docker-compose.yml @@ -0,0 +1,24 @@ +version: "3.2" + +services: + + product-microservice: + build: + context: . + dockerfile: Dockerfile + no_cache: true + image: product-microservice:3.0 + container_name: product-microservice + ports: + - "5001:5001" + environment: + #DATABASE_URL: "DRIVER={ODBC Driver 17 for SQL Server};SERVER=product-database,1433;DATABASE=Products;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/User_MicroService_Group3/Dockerfile b/User_MicroService_Group3/Dockerfile index 3e7d584f..7148b367 100644 --- a/User_MicroService_Group3/Dockerfile +++ b/User_MicroService_Group3/Dockerfile @@ -1,22 +1,65 @@ FROM python:3.11.4 +#Copy requirements COPY requirements.txt /user_ms/ COPY app /user_ms/ +#Set working direcroty WORKDIR /user_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/* -# Set environment variables for ODBC configuration if needed + +#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 diff --git a/User_MicroService_Group3/Dockerfile.userdb b/User_MicroService_Group3/Dockerfile.userdb new file mode 100644 index 00000000..c7d3ab70 --- /dev/null +++ b/User_MicroService_Group3/Dockerfile.userdb @@ -0,0 +1,27 @@ +FROM mcr.microsoft.com/mssql/server:2022-latest + +# Set environment variables +ENV SA_PASSWORD WebTechGroup3 +ENV ACCEPT_EULA=Y + +COPY User_Management.bak /var/opt/mssql/data/ + + + + +# Change user permissions +USER root + +RUN chown -R mssql:mssql /var/opt/mssql/data + +COPY entrypoint.sh /usr/local/bin/entrypoint.sh + + +# Expose the default SQL Server port +EXPOSE 1433 + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] + + +# Define the default command to run when the container starts +CMD ["/opt/mssql/bin/sqlservr"] \ No newline at end of file diff --git a/User_MicroService_Group3/Dockerfile.userms b/User_MicroService_Group3/Dockerfile.userms new file mode 100644 index 00000000..3e73e5fa --- /dev/null +++ b/User_MicroService_Group3/Dockerfile.userms @@ -0,0 +1,62 @@ +FROM python:3.11.4 + +#Copy requirements +COPY requirements.txt /user_ms/ + +COPY app /user_ms/ + +#Set working direcroty +WORKDIR /user_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/* + + +#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 + +#Optional: Install mssql-tools and add to PATH +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 + +#Optional: Install unixodbc-dev and kerberos library +RUN apt-get install -y libgssapi-krb5-2 + +#Set environment variables for ODBC configuration if needed +ENV ODBCINI=/etc/odbc.ini +ENV ODBCSYSINI=/etc + +CMD ["python", "index.py"] \ No newline at end of file diff --git a/User_MicroService_Group3/app/__pycache__/config.cpython-311.pyc b/User_MicroService_Group3/app/__pycache__/config.cpython-311.pyc index 105819a92eef07108a2fb4558af6e0b1ad972654..091813a29718206a89d166b99bce03396b05d34c 100644 GIT binary patch delta 166 zcmcb^G@Y4uIWI340}y-<Fi$I)$SWDF1msL-NMT4}%wdRPNMVX%Oks{<N@0m&PGOB= zNnwj(O<@dX&}4rJ(&ZO&i_N_#zqG(OvqPAHp^7UzF)cgM%F@8nsEXY{4-7TgCdSAL z-{SFhbn|wM4|WX-a}B!1;^7}Wv0^<JFVGN1ATHLOY{;l2{D5D&f#(6cKm!X17I6b* E0J3T)Q~&?~ delta 107 zcmbQve20m5IWI340}zCI{7H43$SY|k1>{U;NMT4}%wdRPNMVX%Oks{<N@0m&PGJmY z&}4lHQtcOVi_N_#zqG(OvqPAHL6c=-rR>C2>$tdqa*RM+tUNi1QHisGrGcf06UYYu D2AUTr diff --git a/User_MicroService_Group3/app/config.py b/User_MicroService_Group3/app/config.py index 3217efec..0405b913 100644 --- a/User_MicroService_Group3/app/config.py +++ b/User_MicroService_Group3/app/config.py @@ -6,4 +6,6 @@ SECRET_KEY = "Group3" PORT = 5000 -KAFKA_SERVER = "kafka:9092" \ No newline at end of file +KAFKA_SERVER = "kafka:9092" + +HOST = "0.0.0.0" \ No newline at end of file diff --git a/User_MicroService_Group3/app/controllers/__pycache__/showReviewsController.cpython-311.pyc b/User_MicroService_Group3/app/controllers/__pycache__/showReviewsController.cpython-311.pyc index d12a61ce3d85861ca4a71b737865e07616283d1c..51d9ad122d7784716c744cb4a8122c6254d70f40 100644 GIT binary patch delta 363 zcmaFF-z&hooR^o20SNRsrPF*S@=7wUnW%1Plfsa~lEab98O6!Sz{HTsn8KRMwTy{@ zVKop#KooZ>X9`;idkV)K<|v*N{uHhj#wgxY?ge}kJ8T*GCmwT^)nvTI<L&6??HC{I z8WiRlbc?$<BfmT-wJbBWym+$);~Yjt!OcgR(imA4fo2M9Hel&wWK#w*i)1J7XSFj0 zi59T{2~DOVH4s|{NECxyprBBs0Hkj5fDDW;f|yvO4HVLxY{Ztxs{~>(7V(29fyoQl zH26e8%Gr|h^U^ZYi#R5qWRo`&0tyv@?6}2RlwVqs3f8}pp$McIZ2T_{o80`A(wtPg zB4eN!BM=v#n=Hrfu5p7w{sJm`AS69ObB6B<i;F@gSA<L&_&;zkNU2S(W>01TnFj!r C@KnYC delta 333 zcmeAbc*M`UoR^o20SJPZ3a05#<dtMxFj3vmfQccMF@+_SV;K_z!)hRgfGExs))clB z_7sje%u!q^{3%>5j8WXFoC|m+KV%f0xKe|Wcj6^i*<0Mj8TsWwsb!g|<;7KeIr+(n zIT`uIC03ROmPVUR80RoD3T(c}l*Y)a05q3>vkglpBbySCStK+0G^?E{NVJFrNN6$@ zse;(jK%yAr3I&BCc_4L*2V_Bf5yXZfEufIbWIMJ*UPT~Fld*^oMDa~t!=@1?0#eQq zAD@?)n;IW~iyv8Id{RM?AW*(Y0i=kvD8IBM6>Qi_h9ZzjV7q>C*yQG?l;)(`6&V7> b7=gHW&t!9U_sJ93MH#gwFJn(;0VxIm{hd%} diff --git a/User_MicroService_Group3/app/controllers/logoutController.py b/User_MicroService_Group3/app/controllers/logoutController.py index 241e00d3..e296c4da 100644 --- a/User_MicroService_Group3/app/controllers/logoutController.py +++ b/User_MicroService_Group3/app/controllers/logoutController.py @@ -10,7 +10,7 @@ def logout(): user_id = session.get("user_id") #get session data - if user_id: #if user is logges in + if user_id: #if user is logged in if request.method == 'POST': diff --git a/User_MicroService_Group3/app/controllers/showReviewsController.py b/User_MicroService_Group3/app/controllers/showReviewsController.py index 924ede66..42d85347 100644 --- a/User_MicroService_Group3/app/controllers/showReviewsController.py +++ b/User_MicroService_Group3/app/controllers/showReviewsController.py @@ -5,47 +5,48 @@ from config import KAFKA_SERVER show_reviews_bp = Blueprint("showReviews", __name__) -# Kafka consumer configuration + consumer_conf = { "bootstrap_servers": KAFKA_SERVER, - "group_id": "show_reviews_group", # Specify a unique group ID for this consumer - "auto_offset_reset": "earliest" # Start consuming from the beginning of the topic + "group_id": "show_reviews_group", + "auto_offset_reset": "earliest" } -# Function to consume reviews published by product microservice +#Function to consume reviews published by product microservice def consume_reviews(num_reviews=1): consumer = KafkaConsumer("customer_reviews", **consumer_conf) reviews = [] - # Iterate over messages received by the consumer + for message in consumer: - # Decode the message from bytes to a string using UTF-8 encoding + review_data_str = message.value.decode("utf-8") - # Parse the JSON-encoded message to extract the review data + review_data = json.loads(review_data_str) - # Append the review data to the list of reviews + reviews.append(review_data) - # Exit the loop after consuming the specified number of reviews + if len(reviews) >= num_reviews: break - # Close the consumer to release resources + consumer.close() return reviews -# Route to show reviews for a user + +#Route to show reviews for a user @show_reviews_bp.route("/user/showReviews", methods=["POST"]) def show_reviews(): - # Collect user id from session + #Collect user id from session user_id = session.get("user_id") if user_id: # Check if user is logged in if request.method == 'POST': - # Call function to consume reviews + #Call function to consume reviews reviews = consume_reviews() return jsonify(reviews) diff --git a/User_MicroService_Group3/app/index.py b/User_MicroService_Group3/app/index.py index a22a9736..2ee61fb8 100644 --- a/User_MicroService_Group3/app/index.py +++ b/User_MicroService_Group3/app/index.py @@ -10,7 +10,7 @@ from controllers.logoutController import logout_bp from controllers.fetchUsernameController import fetch_username_bp from controllers.showReviewsController import show_reviews_bp -from config import DEBUG, SECRET_KEY, PORT +from config import DEBUG, SECRET_KEY, PORT, HOST import os import requests import publishers @@ -20,7 +20,6 @@ import publishers app = Flask(__name__) CORS(app) -app.secret_key = SECRET_KEY @app.route('/') def index(): @@ -51,6 +50,23 @@ app.register_blueprint(show_reviews_bp) publishers.create_profile_updated_topic() +#Check if application is running in docker to collect or set secret key +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 @app.route("/userIDs", methods=["POST"]) @@ -61,4 +77,4 @@ def userIDs(): return 'hi' if __name__ == '__main__': - app.run(debug=DEBUG, port=PORT) \ No newline at end of file + app.run(host=HOST, debug=DEBUG, port=PORT) \ No newline at end of file diff --git a/User_MicroService_Group3/app/models/__pycache__/database_connection.cpython-311.pyc b/User_MicroService_Group3/app/models/__pycache__/database_connection.cpython-311.pyc index ee658c793e4a505d7b70e54b3c82b148e4f6561e..d54224fd06a5210d5b85dad1790380d510110bd7 100644 GIT binary patch literal 1257 zcmZWo&1>UE6d%cwEZgh2*=)Krbi-`Ff}#0bN@(2_9NTRJyUA{xG;9zUSu;-DI+8jg zZDQA2a_GT_UV7R?DfHB`6iWYv+<KHDhae~fN)CH7<g)CkPqLk?+c)U<-qV|TPrvs@ zzopYj1k$^|Tzf7e^iSvvB{ncFm%w<22qHoQ?e?{>D~O1SMEq4i=y!PfA|Mj`9__}6 zP)1qlMfh^PHND|FyiO=4Rcu(MNe!oNnYiYfkzowZMk)mu*1hxro+0NdGlJ^>t(8DT z^q`_A5XlpX?8S)UNhIEuenLcTBfvyk08F+;z*IX1c;n}kCp$xKP~~gj-IumJTA_^I zMUFCzBJ>_&Q=T&NP3h4S0(uPn@sy_u87mL0L*Wn|#U7(WA)8rmrPoYc*jQgL6}E73 zwKaC{qq)V8m*<ui!)GbD;d07|?&wvW(;&gWZGiuTvLL-ft6S9A|AJYreXn(AqqthY zMOKFxUR=gCi{bL4`?wtKZpDk6YhRT%S6XVWT-uDRWUiRs%CF|jrInVP+g>Y%>fsKk z+qo^~a)**i;c7Z7rj={Gy=~GX8^%Qmri?)e%P?F9-gngdJSzpV&FZETD0b5#RU?QG zrW+(mM+UXSDQDw>GGL%y(NaT_rhY&J)z&#bv=|8#5^)K}uWv|&JCJ@a5Gaqs5O7~! z{ZaTt+lB;O(+`@)zP4e~s1I7vGTZ}dI$V1QQOndD+O`=sh}WGawraTSGDe$P!Eza= zc*kPjXnFEPHw|D^*w-5kYVJ{v>n4U~<FMPN)v)&Jlt%?C59$W9!VcFBTIml$(`{Qj zun28%ZOE^3O<~S%2FZb2Ayqa3Ji-gby8y@NZz<84?@Cjr(v&Yv^~5*i$@B5M9p!A| zZbv<vm=56`fboTn(v#4gFU4PKJrwFb{yF0PrM@2XcPb-p&3xVM+rIkNMP~Acr~dSO zH?we>S@6|`mlvs9JtWDK*Knbx{jm?b>g=gH>#MWpnOhxqxL$(v60jXKzYVN@oX-pB zL`de}kDa74c^o^zGT2#(sSpiBi?eW=Q7fLKOE3|;3Ghn&6#D2k=w~cU6aM%-573JV pf^de?$I&`NiQ{OUBl%eNl@GdT<`m8NXr?FK6yTfx5A03I@-J`xT-pEt delta 564 zcmaFKIg_n^IWI340}#yOd!Jg!$iVOz#DM`ODC4sTkTIPhg&~D8harj~g{g%hiZO*T zm_d{IB}j>1GE^a$;slb+K>RrZNC0&))&h0ZGNv%sGNrK8GN-WCFwAC1VXI*TlJ)F0 zOhAgGh8ak5&gHCSDFHeH2D0Gn8kS{1_G&mEXf>DLEe_|5%*5Qp?8ICAp~b01@xF<9 ziRr1isd*(;yv`n;j=qlGj_kRW$r-m8s-#_lJi}arY^#F<eH4OIi^@`qYORAOKVekV zldujcDlINaO^J8T&&x|qF3HT#v#m@mw$^02#a2+6pOTb(i#-`4rO7%unMr-}BqkxA zVpgC#6+qzEoXK06N+w$~o7VFK#X#c41wf*K;Q_CBgWC;$g$9os{PG||u)*U43xlLL z(+;)|3?Ldpp3p$%U5HFX;bs&db0O>tETT`j1$*o+NNHc>*15v1bAd(YGebPkR!ycN zb|6&*a>`1EA^{Ma4@mstu*uC&Da}c>D-r^7L19^}4kSJ>Gcq#XVBl>4!w(#sjJh8f IFbS|h00z&6@&Et; diff --git a/User_MicroService_Group3/app/models/__pycache__/login.cpython-311.pyc b/User_MicroService_Group3/app/models/__pycache__/login.cpython-311.pyc index 54f0eb17fc5e099f4eaf6dcc17f1775c07a610e1..b77602b227dc0fa7d1be7ce1a7e1b0b2398dca15 100644 GIT binary patch delta 809 zcmaixO=uHA6o6+kJDW{5n{76mZql?NHl?<~BK{Cbm7-Z9dXd)XLGjeCLW?$KvXUxB zN)d@S!#fCy;zd1p5i01_4d~Gb?WNFzNbdm;7QHy5NhlQb!Ta{j&%W9H=JRmd(q3s= z5b;=ka`;-Jq1_+*h!J{(0?6ghZaDZQAHD9)VB`{LkT|?iD1237&{D&4&FA=P1aus4 z{Ib9fWTcwp5O^H80@J}EI#lz!7~c7^X$O^%gKGY}{wj9O?imP;Aoh0?3uZ@mZ>pkY zatT%OxP0!mc6Kp+x_H4plfGCgo?m-UK4C@Oq)Tjm(S;S756erp%FgWECM_~nX0So` zVFP~9VkW~+^7E{y{6AJuTe7IRrD*l?7bUf>q*_X93ufeszoo=?w$%ve`XROM*4-T* z+o}l>-Gpa)a;7`irao%&waN%@x>^VobmZx}ohDw&DCCHj(|Fw^hMgqMB<1y7&mVt5 z=1F*de~aOv@**NRK8MU>ZbrI??)VlYcpgZ?Wqf?Ngfhqt^R1m&P`Xt|SQNOh|5=Sf zT+N1dTU`r>N*L#1Ry#VWGKn{3hCoz6Tnmc{^b1%5ae;(DL|{N52^-p|xu2I~JS%2L z?I1N_S{{J$aGth8$J#PH4IlBhLWBP@JGIAbmiJse6)ni<L;pcePu6XVcrl|eLA(h~ z)RTs7kfuRx3m)|4M#LpE@i|ObVnQ1War{(H+$cLYuV0;FS@_m>@<0NcZPY^nr^I+K H{&e^ai;lmE delta 1649 zcmeHH%}*0S6rb7I?e=4r!qOHkrRAeGh>)f#CWbFTS`s8p3<smp#K>}hpe5UyYEncA z8YL#i%)zViAP0}cBNu4l=tndXZu$r48bTzVe6P)-v7nH6bY|z5H*aQsGxPTM#;keO zsLrdZlR)_z`!@RNv3gGkG9I@*v+Kev$qC~kzeH=fPwuei1jCaPp2|E%8=aKosNv1g zQuin&!%&+@rV^=2W!zy|VPc$_k~3bbPl(R=M;hFL(q~adDA9qk)TZQHa+YR%KM5>K z{+_n{i6&f5lO;FUd6K0~aJ^k`<fbGGwKVgvlw3#&tCT9dTRa(%MkZ3}(RJJ8&6Iv+ zWL=6IM#@;1CXKOc8Gcu6pjCWcjC;axS{YjUGbQ9UF~vG5#J@QFyji-?WBQ1qnS?rO z*A(s1(A?02<iq6s<eJNi&d{3T`=A8gDuFjj@SPHTUHnW2BU_s_u#(?##s<xb{c`|Q zk*2uI7L-jlQM`Q78J#w5|A5YP3z7$UP3Jz@rmdsF;&dm(ZKk)YuZ=9Vx#NDe)T#9g zY`H>=*O9!Sf+z3R;$D_-Ku^Idfv4bSXxBv(3LAltZx<U_4BEyl;1l8?nO{bq!@vui z$}ijITrpkH*%(D(@HQH;TQcWS8io#vTo?H{dQseQ3W#<udB8(L%Wnjrd)#BMs$Z0M zA*lbG-pj5fqS6;O<Y7v?_<-Yhk79@r4x<V|L#RfmLGU188XK63#sP$b2!4cGgaCi( zh<KX8Y=xHY5K7u_ENXwa!;I`x7M3c^Lwvw_?0?>rJq%~92w~pzLCj}*t54UHB^Cu- zu6HL?wj9;^+gYB9iAs`hSHV*dw1k}%Jm^`mOW;{i8QPW6L=SIqoe1OWW#Df#><ASI j3cz=J=hc*cePXoRIKpRLr&>caWRh(dq+#rrLy_SJA2*sA diff --git a/User_MicroService_Group3/app/models/changePassword.py b/User_MicroService_Group3/app/models/changePassword.py index 7cb162b6..3e7403d6 100644 --- a/User_MicroService_Group3/app/models/changePassword.py +++ b/User_MicroService_Group3/app/models/changePassword.py @@ -16,7 +16,7 @@ def check_old_password(data): - # Check if the email already exists + #Check if the email already exists email_check_query = "SELECT COUNT(*) FROM dbo.User_table WHERE UserID = ?" cursor.execute(email_check_query, user_id) #executes the query count = cursor.fetchone()[0] diff --git a/User_MicroService_Group3/app/models/database_connection.py b/User_MicroService_Group3/app/models/database_connection.py index 8bad5678..94574287 100644 --- a/User_MicroService_Group3/app/models/database_connection.py +++ b/User_MicroService_Group3/app/models/database_connection.py @@ -1,14 +1,24 @@ import pyodbc +import os - +print("Outside db connection function") #Connect to database def connect_db(): - - server = 'Chiamaka' - database = 'User_Management' - username = 'CHIAMAKA\amych' - password = '' - - connection_string = f'DRIVER={{SQL Server}};SERVER={server};DATABASE={database};UID={username};PWD={password};Trusted_Connection=yes;' - - return pyodbc.connect(connection_string) \ No newline at end of file + print("In CONNECT DB") + try: + + server = "35.197.217.212" + database = "userdatabase" + 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/User_MicroService_Group3/app/models/fetchUsername.py b/User_MicroService_Group3/app/models/fetchUsername.py index 437cac41..98c4cb13 100644 --- a/User_MicroService_Group3/app/models/fetchUsername.py +++ b/User_MicroService_Group3/app/models/fetchUsername.py @@ -16,7 +16,7 @@ def get_username(id): row = cursor.fetchone() #fetch data if row: - return row[0] # Assuming the username is in the first column + return row[0] else: return None @@ -29,7 +29,7 @@ def get_username(id): return None except Exception as e: #error handling - print(f"Unexpected error occured in fetch_user_info: {e}") + print(f"Unexpected error occured in get_username: {e}") return None finally: diff --git a/User_MicroService_Group3/app/models/login.py b/User_MicroService_Group3/app/models/login.py index 6e344a76..f790b893 100644 --- a/User_MicroService_Group3/app/models/login.py +++ b/User_MicroService_Group3/app/models/login.py @@ -7,7 +7,7 @@ from models.database_connection import connect_db def fetch_user(email): try: #error handling - + print("In FETCH USER") connection = connect_db() cursor = connection.cursor() @@ -31,16 +31,12 @@ def fetch_user(email): print(f"Unexpected error occured in fetch_user: {e}") return None - finally: - if cursor: - cursor.close() - if connection: - connection.close() - + +#Fetch user's password def fetch_password(email): try: @@ -73,8 +69,4 @@ def fetch_password(email): print(f"Unexpected error occured in fetch_user: {e}") return None - finally: - if cursor: - cursor.close() - if connection: - connection.close() \ No newline at end of file + \ No newline at end of file diff --git a/User_MicroService_Group3/app/models/signup.py b/User_MicroService_Group3/app/models/signup.py index 71474133..63031efd 100644 --- a/User_MicroService_Group3/app/models/signup.py +++ b/User_MicroService_Group3/app/models/signup.py @@ -4,7 +4,7 @@ import pyodbc from models.database_connection import connect_db - +#Create a new user def new_user(data): try: #error handling @@ -38,12 +38,6 @@ VALUES (?, ?, ?, ?, ?, ?, ?);''' insert_authinfo_query = '''INSERT INTO dbo.AuthInfo (PasswordHash, PasswordSalt, Iterations, TempPlainText, UserID) VALUES (?, ?, ?, ?, ?);''' cursor.execute(insert_authinfo_query, (data["hash"], data["salt"], data["iterations"], data["password"], UserID)) - - - - - - diff --git a/User_MicroService_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-311.pyc b/User_MicroService_Group3/app/publishers/__pycache__/kafkaPublishers.cpython-311.pyc index f298ced069dad7e7a1242f27879c71831e59724d..ab88574606876c33991d2d1f9cf5c27a3e73f26b 100644 GIT binary patch delta 386 zcmbOybWw<RIWI340}v#0NvB<!$ScVhHBnvNB$q9UjgcXRA%!J}J&K))A(b(eZ4K)( zMh1q}Knwv<94Txq3{jjZ>_Cz$g=J!yg`g(mEgo-2H*d%IVAr59*C4-%`?Vd80M$=t zD1mEaU?^dN8N$G@h7r}+T80#+TE-OSS|%W7u3=cfG+B{Rc=82Sexq8J8paxyGR7jE z5_W_EKryBo<~1zKn1QYXVhE^Z1!`phY2{?7VNGXDVO_&Ec><#(6T9E!4U9P)tVJw9 zg+*+e<(ZrrC3%4C;wB)`!0=R9d27xEVdsm&&R2w;H`g$4VrEp@tj{jN$jCj}gF~6? z7F%+DURq{)5!>Vp4m~atpe~TtirXhI;4smYzrcWk9x!k>fZ+pfi4NNpHW#=pE^=F3 L;kKCkhQkN|6*^R< delta 346 zcmca8G*5_kIWI340}#Y76HMDakynz@Z=$-oMieU(Ln>nm%No{Yj0_B`ffxd!*izV9 z7^2uy*nuQR3iHG!3qikMd^!2ai8&eh#U)mj29`z>Pivd)0;-?RPy*M;z>vbYh6&ZM zT80$nTA(GhOhC+B!?1vH@<tZn$)1c->Z~ve85n99YnW=7fev8?Is}Lzpq3S=o*ATG zlc9z+oiT-N4f`@Cpb8*{07ixshF~z(<nSwE0}4()$e6>-QpB>^l*yS<3gqkJW+2hP z@Kjj&f|=U|VfTx|?pK7}H&0~V#LTF$*@az#k&$z9EQj*sUJh+8W1w1)e~QZ{AL1~P e;BElJ2iy`JwimRmFL2vj<hHrOZ8KS((+B`(?MgWS diff --git a/User_MicroService_Group3/app/publishers/kafkaPublishers.py b/User_MicroService_Group3/app/publishers/kafkaPublishers.py index 7d41460e..279b149b 100644 --- a/User_MicroService_Group3/app/publishers/kafkaPublishers.py +++ b/User_MicroService_Group3/app/publishers/kafkaPublishers.py @@ -10,31 +10,31 @@ producer = KafkaProducer(bootstrap_servers=KAFKA_SERVER) #Creates the topic def create_profile_updated_topic(): - # Create KafkaAdminClient instance + admin_client = KafkaAdminClient(bootstrap_servers=KAFKA_SERVER) - # Define the topic name and configuration + # Define the topic name topic_name = "profile_updated_topic" num_partitions = 1 replication_factor = 1 - # Retrieve the list of existing topics + #Get topics topic_metadata = admin_client.list_topics() - # Check if the topic already exists + #Check if the topic 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) #Function is called in updateProfileControllers.py #Topic message is collected from ProductMicroservice/Subsribers/updateUsernameSubscriber.py def publish_username_updated_event(event_data): - # Serialize the event data to JSON + event_json = json.dumps(event_data) - # Publish the event to the Kafka topic + #Publish the event to the Kafka topic data_to_send = producer.send("profile_updated_topic", value=event_json.encode("utf-8")) try: record_metadata = data_to_send.get(timeout=10) diff --git a/User_MicroService_Group3/docker-compose.yml b/User_MicroService_Group3/docker-compose.yml new file mode 100644 index 00000000..8ff3f2bc --- /dev/null +++ b/User_MicroService_Group3/docker-compose.yml @@ -0,0 +1,24 @@ +version: "3.2" + +services: + + user-microservice: + build: + context: . + dockerfile: Dockerfile + no_cache: true + image: user-microservice:3.0 + container_name: user-microservice + ports: + - "5000:5000" + environment: + #DATABASE_URL: "DRIVER={ODBC Driver 17 for SQL Server};SERVER=user-database,1433;DATABASE=User_Management;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/User_MicroService_Group3/entrypoint.sh b/User_MicroService_Group3/entrypoint.sh new file mode 100644 index 00000000..268cd4a0 --- /dev/null +++ b/User_MicroService_Group3/entrypoint.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Start SQL Server in the background +/opt/mssql/bin/sqlservr & + +# Wait for 5 minutes (300 seconds) +sleep 300 + +# Log in and restore database +/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -Q "RESTORE DATABASE User_Management FROM DISK = '/var/opt/mssql/data/User_Management.bak' WITH MOVE 'User_Management.mdf' TO '/var/opt/mssql/data/User_Management.mdf', MOVE 'User_Management_log.ldf' TO '/var/opt/mssql/data/User_Management_log.ldf';" + +# Keep the script running indefinitely +wait %1 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..ed16d574 --- /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 -- GitLab