diff --git a/SQL/site_data.sql b/SQL/site_data.sql index 75770fc..43668db 100644 --- a/SQL/site_data.sql +++ b/SQL/site_data.sql @@ -174,11 +174,11 @@ ALTER TABLE members_products ADD p_file INT DEFAULT 0; ALTER TABLE members_products ADD url_status INT DEFAULT 0 -INSERT INTO merms_products (name,description,status,product_id, banner) VALUES ('Personal Website','Your personal professional web presence',1,'A000001', 'banner.jpg'); -INSERT INTO merms_products (name,description,status,product_id, banner) VALUES ('Professional Website','Your healthcare practice online presence ',1,'A000002', 'banner.jpg'); -INSERT INTO merms_products (name,description,status,product_id, banner) VALUES ('Personal Blog','Blog to share your health care view',1,'A000003', 'banner.jpg'); -INSERT INTO merms_products (name,description,status,product_id, banner) VALUES ('Professional Blog','Booster your practice with engaging contents',1,'A000004', 'banner.jpg'); -INSERT INTO merms_products (name,description,status,product_id, banner) VALUES ('Practice EMR','Get Open EMR for practice management',1,'A000005', 'banner.jpg'); +-- INSERT INTO merms_products (name,description,status,product_id, banner) VALUES ('Personal Website','Your personal professional web presence',1,'A000001', 'banner.jpg'); +-- INSERT INTO merms_products (name,description,status,product_id, banner) VALUES ('Professional Website','Your healthcare practice online presence ',1,'A000002', 'banner.jpg'); +-- INSERT INTO merms_products (name,description,status,product_id, banner) VALUES ('Personal Blog','Blog to share your health care view',1,'A000003', 'banner.jpg'); +-- INSERT INTO merms_products (name,description,status,product_id, banner) VALUES ('Professional Blog','Booster your practice with engaging contents',1,'A000004', 'banner.jpg'); +-- INSERT INTO merms_products (name,description,status,product_id, banner) VALUES ('Practice EMR','Get Open EMR for practice management',1,'A000005', 'banner.jpg'); INSERT INTO products (name,description,status,product_id, banner) VALUES ('Personal Website','Your personal professional web presence',1,'A000001', 'banner.jpg'); INSERT INTO products (name,description,status,product_id, banner) VALUES ('Professional Website','Your healthcare practice online presence ',1,'A000002', 'banner.jpg'); @@ -187,8 +187,28 @@ INSERT INTO products (name,description,status,product_id, banner) VALUES ('Profe INSERT INTO products (name,description,status,product_id, banner) VALUES ('Practice EMR','Get Open EMR for practice management',1,'A000005', 'banner.jpg'); +CREATE TABLE members_products_settings ( + id SERIAL, + uid uuid DEFAULT uuid_generate_v4(), + member_id INT REFERENCES members(id), + subscription_uid VARCHAR(150), + product_id VARCHAR(25) REFERENCES products(product_id), + settings_key VARCHAR(100) NOT NULL, + setting_type VARCHAR(15) NOT NULL, + setting_value TEXT, + status INT DEFAULT 0, + added timestamp without time zone DEFAULT now(), + updated timestamp without time zone DEFAULT now() + ); + ALTER TABLE ONLY members_products_settings + ADD CONSTRAINT members_products_settings_id_key UNIQUE (id); +ALTER TABLE members_products_settings +ADD CONSTRAINT members_products_settings_unique_member_key +UNIQUE (member_id, product_id, settings_key); +ALTER TABLE members_products_settings OWNER TO merms_panel; +-- member_id,subscription_uid,product_id,settings_key,setting_type,setting_value CREATE TABLE provision_plans ( diff --git a/app/api/routes/routes.py b/app/api/routes/routes.py index 55dc15b..d06323c 100644 --- a/app/api/routes/routes.py +++ b/app/api/routes/routes.py @@ -172,10 +172,18 @@ def myproduct_dash(): @api.route("/panel/myproduct/settings", methods=["POST"]) def myproduct_settings(): data = request.get_json() - logger.info(f"Route MyProduct Settings Data ==>>>> {data}") + logger.info(f"Route Save MyProduct Settings Data ==>>>> {data}") response = MyProductsService.process_settings(data) return response +@api.route("/panel/myproduct/settings/values", methods=["POST"]) +def myproduct_settings_values(): + data = request.get_json() + logger.info(f"Route Get MyProduct Settings Data ==>>>> {data}") + response = MyProductsService.process_settings_values(data) + return response + + # /panel/myproduct/subscription @api.route("/panel/myproduct/subscription", methods=["POST"]) diff --git a/app/api/services/account.py b/app/api/services/account.py index 0a0e6ea..f21565c 100644 --- a/app/api/services/account.py +++ b/app/api/services/account.py @@ -1,14 +1,14 @@ from flask import session, jsonify -from app.models.loan import Loan +# from app.models.loan import Loan from app.utils.logger import logger from app.api.services.base_service import BaseService from app.api.schemas.eligibility_check import EligibilityCheckSchema from marshmallow import ValidationError from app.api.enums import TransactionType -from app.api.integrations import SimbrellaIntegration +# from app.api.integrations import SimbrellaIntegration from app.extensions import db -from app.models import Offer, RACCheck, Members, MembersActions -from app.api.services.offer_analysis import OfferAnalysis +from app.models import Members, MembersActions +# from app.api.services.offer_analysis import OfferAnalysis from app.api.helpers.response_helper import ResponseHelper from werkzeug.security import generate_password_hash, check_password_hash from app.api.schemas.user import UserSchema diff --git a/app/api/services/myproduct.py b/app/api/services/myproduct.py index c09c091..6c25f06 100644 --- a/app/api/services/myproduct.py +++ b/app/api/services/myproduct.py @@ -3,7 +3,7 @@ from app.utils.logger import logger from app.api.services.base_service import BaseService from marshmallow import ValidationError from app.extensions import db -from app.models import MembersProducts, Products, Members, ProductsDetails, ProductsDetails, ProvisionActions +from app.models import MembersProducts, Products, Members, ProductsDetails, ProductsDetails, ProvisionActions, MembersProductsSettings from app.api.helpers.response_helper import ResponseHelper from app.api.schemas.myproduct import MyProductSchema from app.api.schemas.provision import ProvisionSchema @@ -176,7 +176,6 @@ class MyProductsService(BaseService): product_subscription_external_url = memberSubscription.external_url product_subscription_internal_url = memberSubscription.internal_url - # "banner": "banner.jpg", result_data = { "myproudct": { "result": "Reveived under development ", @@ -184,19 +183,10 @@ class MyProductsService(BaseService): } } - # my_dict = {"apple": 1, "banana": 2, "cherry": 3} - for key in settings.keys(): - # logger.info(f"settings_key : {key}") - # logger.info(f"settings_value : {settings[key]}") # Accessing value using the key - # logger.info(f"subscription_uid: {memberSubscription.uid}") - # logger.info(f"product_id : {product_id}") - # logger.info(f"member_id : {member_id}") setting_value = settings[key] subscription_uid = memberSubscription.uid - MembersProducts.save_update_product_settings(member_id,subscription_uid,product_id,key, 'TXT', setting_value) - - + MembersProductsSettings.save_update_product_settings(member_id,subscription_uid,product_id,key, 'TXT', setting_value) # Simulate processing response_data = { @@ -324,3 +314,54 @@ class MyProductsService(BaseService): db.session.rollback() return ResponseHelper.internal_server_error() + @staticmethod + def process_settings_values(data): + try: + with db.session.begin(): + logger.info(f"Incoming MyProduct data ==>>>> {data}") + validated_data = MyProductsService.validate_data(data, MyProductSchema()) + token = validated_data.get('token') + uid = validated_data.get('uid') + member_data = Members.get_member_by_uid(uid) + member_id = member_data.id + product_id = validated_data.get('product_id') + + product_subscription_uid = '' + product_subscription_external_url = '' + product_subscription_internal_url = '' + product_data = Products.get_product_by_product_id(product_id) + product_description = ProductsDetails.get_product_details_with_product_id('A000002') + productDataStatus = product_data.status + + memberSubscription = MembersProducts.get_member_product_by_product_member_id(member_id, product_id) + settings_data = [] + if memberSubscription is not None: + logger.info(f"Incoming MyProduct data ==>>>> {memberSubscription}") + product_subscription_uid = memberSubscription.uid + settings_data = MembersProductsSettings.get_product_settings_by_product_id_and_member_id(product_id, member_id) + + # Simulate processing + response_data = { + "settings": settings_data, + "member_id": member_id, + "product_subscription_uid": product_subscription_uid, + } + + return ResponseHelper.success(data=response_data) + + except ValidationError as err: + + logger.error(f"Validation Error: {getattr(err, 'messages', str(err))}") + db.session.rollback() + return ResponseHelper.unprocessable_entity(result_description="Validation exception") + + except ValueError as err: + logger.error(f"{getattr(err, 'messages', str(err))}") + db.session.rollback() + return ResponseHelper.error(result_description=str(err)) + + except Exception as e: + logger.error(f"An error occurred: {str(e)}", exc_info=True) + db.session.rollback() + return ResponseHelper.internal_server_error() + diff --git a/app/models/__init__.py b/app/models/__init__.py index ad289c7..8b92821 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -20,10 +20,14 @@ from .products_details import ProductsDetails from .provision_actions import ProvisionActions from .password_reset import PasswordReset from .member_product_refresh import MembersProductsRefresh +from .members_products_settings import MembersProductsSettings + __all__ = ['Members','Customer', 'Account', 'Products', - 'MembersProducts', 'MembersActions', 'MembersPending', 'ProductsDetails', 'ProvisionActions', 'MembersProductsRefresh', - 'PasswordReset','Loan', 'Transaction', 'Repayment', + 'MembersProducts', 'MembersActions', 'MembersPending', 'ProductsDetails', + 'ProvisionActions', 'MembersProductsRefresh','MembersProductsSettings', + 'PasswordReset', + 'Loan', 'Transaction', 'Repayment', 'LoanCharge', 'Offer', 'Charge', 'RACCheck', 'LoanRepaymentSchedule', 'TransactionOffer', 'RepaymentsData', 'Salary'] \ No newline at end of file diff --git a/app/models/members_products.py b/app/models/members_products.py index 4a22a53..2543e09 100644 --- a/app/models/members_products.py +++ b/app/models/members_products.py @@ -95,15 +95,15 @@ class MembersProducts(db.Model): return subscription - @classmethod - def save_update_product_settings(cls, member_id,subscription_uid,product_id,settings_key,setting_type,setting_value ): - logger.info(f"settings_key : {settings_key}") - logger.info(f"setting_type : {setting_type}") - logger.info(f"settings_value : {setting_value}") - logger.info(f"subscription_uid: {subscription_uid}") - logger.info(f"product_id : {product_id}") - logger.info(f"member_id : {member_id}") - return 0 + # @classmethod + # def save_update_product_settings(cls, member_id,subscription_uid,product_id,settings_key,setting_type,setting_value ): + # logger.info(f"settings_key : {settings_key}") + # logger.info(f"setting_type : {setting_type}") + # logger.info(f"settings_value : {setting_value}") + # logger.info(f"subscription_uid: {subscription_uid}") + # logger.info(f"product_id : {product_id}") + # logger.info(f"member_id : {member_id}") + # return 0 def to_dict(self): """ diff --git a/app/models/members_products_settings.py b/app/models/members_products_settings.py new file mode 100644 index 0000000..5d95ad4 --- /dev/null +++ b/app/models/members_products_settings.py @@ -0,0 +1,168 @@ +from datetime import datetime, timezone, timedelta +from itertools import product +from app.extensions import db +from sqlalchemy.exc import IntegrityError +from sqlalchemy.orm import relationship +from dateutil.relativedelta import relativedelta +from datetime import timedelta +import logging +from sqlalchemy import and_, or_, not_ +from sqlalchemy.sql import func +import uuid + +logger = logging.getLogger(__name__) + +class MembersProductsSettings(db.Model): + __tablename__ = 'members_products_settings' + + id = db.Column( + db.Integer, + primary_key=True, + autoincrement=True, + ) + + uid = db.Column(db.String(150), nullable=False) + member_id = db.Column(db.Integer, nullable=False) + product_id = db.Column(db.String(25), nullable=False) + subscription_uid = db.Column(db.String(150), nullable=False) + settings_key = db.Column(db.String(100), nullable=False) + setting_type = db.Column(db.String(15), nullable=False) + setting_value = db.Column(db.String(3500), nullable=False) + status = db.Column(db.Integer, nullable=True, default=0) + added = db.Column(db.DateTime(timezone=True), server_default=func.now()) + updated = db.Column(db.DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) + + # name = db.Column(db.String(100), nullable=False) + # description = db.Column(db.String(250), nullable=False) + + # products_settings = relationship( + # "Products", + # primaryjoin="MembersProductsSettings.product_id == Products.product_id", + # foreign_keys=[product_id], + # back_populates="members_products_settings", + # ) + + @classmethod + def get_product_settings_by_subscription_uid(cls, subscription_uid): + myproduct_settings = cls.query.filter_by(subscription_uid=str(subscription_uid)).all() + if not myproduct_settings: + return None + return myproduct_settings + + @classmethod + def get_product_settings_by_product_id_and_member_id(cls, product_id, member_id): + myproduct_settings = cls.query.filter_by(product_id=str(product_id) ,member_id=member_id).all() + if not myproduct_settings: + return None + return myproduct_settings + + @classmethod + def get_product_settings_by_settings_key_and_subscription_uid(cls, settings_key, subscription_uid): + myproduct_settings = cls.query.filter_by(settings_key=str(settings_key) ,subscription_uid=str(subscription_uid)).first() + if not myproduct_settings: + return None + return myproduct_settings + + @classmethod + def create_settings_entry(cls, member_id,subscription_uid,product_id,settings_key,setting_type,setting_value): + logger.info(f" Data for Subscription Data {member_id} ,{product_id} {setting_type}") + product_settings = cls( + uid=str(uuid.uuid4()), + member_id=member_id, + product_id=product_id, + subscription_uid=subscription_uid, + settings_key=settings_key, + setting_type =setting_type, + setting_value=setting_value, + added=datetime.now(timezone.utc), + updated=datetime.now(timezone.utc) + ) + + try: + logger.info(f" About to Insert Subscription Settngs {settings_key} {member_id} ") + db.session.add(product_settings) + db.session.flush() + except IntegrityError as err: + logger.error(f" Error inserting subscription settings data {err} -- ") + raise ValueError(f"Database integrity error: {err}") + return product_settings + + @classmethod + def update_settings_entry(cls, members_products_settings_id, setting_value): + # Retrieve Reset + update_p = cls.query.get(members_products_settings_id) + + if not update_p: + raise ValueError(f"Reset with ID {members_products_settings_id} does not exist.") + + if update_p.setting_value == setting_value: + return + + + @classmethod + def save_update_product_settings(cls, member_id,subscription_uid,product_id,settings_key,setting_type,setting_value ): + logger.info(f"settings_key : {settings_key}") + logger.info(f"setting_type : {setting_type}") + logger.info(f"settings_value : {setting_value}") + logger.info(f"subscription_uid: {subscription_uid}") + logger.info(f"product_id : {product_id}") + logger.info(f"member_id : {member_id}") + + current_settings = cls.get_product_settings_by_settings_key_and_subscription_uid(settings_key,subscription_uid) + + if current_settings: + members_products_settings_id = current_settings.id + logger.info(f"members_products_settings_id : {members_products_settings_id}") + cls.update_settings_entry(members_products_settings_id, setting_value) + else: + cls.create_settings_entry(member_id,subscription_uid,product_id,settings_key,setting_type,setting_value) + return 0 + + def to_dict(self): + """ + Convert the Loan object to a dictionary format for JSON serialization. + """ + return { + 'id': self.id, + 'uid': self.uid, + 'product_id': self.product_id, + 'subscription_uid': self.subscription_uid, + 'member_id': self.member_id, + 'settings_key': self.settings_key, + 'setting_type': self.setting_type, + 'setting_value': self.setting_value, + 'status': self.status, + 'added': self.added, + 'updated': self.updated + } + + def __repr__(self): + return f'' + +# ''' +# id SERIAL, +# uid uuid DEFAULT uuid_generate_v4(), +# member_id INT REFERENCES members(id), +# subscription_uid VARCHAR(150), +# product_id VARCHAR(25) REFERENCES products(product_id), +# settings_key VARCHAR(100) NOT NULL, +# setting_type VARCHAR(15) NOT NULL, +# setting_value TEXT, +# status INT DEFAULT 0, +# added timestamp without time zone DEFAULT now(), +# updated timestamp without time zone DEFAULT now() +# ''' + + # @classmethod + # def get_dash_recent_subscription(cls, limit): + # member_product = cls.query.order_by(cls.id.desc()).limit(limit).all() + # if not member_product: + # return None + # return member_product + # + # @classmethod + # def get_member_product_by_product_member_id(cls, member_id, product_id): + # member_product = cls.query.filter_by(member_id=str(member_id), product_id=str(product_id)).first() + # if not member_product: + # return None + # return member_product \ No newline at end of file diff --git a/app/models/products.py b/app/models/products.py index 08f737d..8f831e8 100644 --- a/app/models/products.py +++ b/app/models/products.py @@ -40,6 +40,13 @@ class Products(db.Model): back_populates="products", ) + # products_settings = relationship( + # "MembersProductsSettings", + # primaryjoin="Products.product_id == MembersProductsSettings.product_id", + # foreign_keys="MembersProductsSettings.product_id", + # back_populates="products", + # ) + # members_products = relationship( # "MembersProducts",