From 9cab449aaac279201a7f0eadadf30651d7f737ac Mon Sep 17 00:00:00 2001 From: "CHIEFSOFT\\ameye" Date: Tue, 26 Aug 2025 06:43:32 -0400 Subject: [PATCH] payment session --- SQL/site_data.sql | 33 +++++++++++++ app/api/routes/routes.py | 26 +++++----- app/api/services/account.py | 2 +- app/api/services/myproduct.py | 16 +++--- app/api/services/products.py | 6 +-- app/api/services/subscription.py | 8 +-- app/models/__init__.py | 4 +- app/models/payments.py | 85 ++++++++++---------------------- app/models/payments_session.py | 60 ++++++++++++++++++++++ 9 files changed, 152 insertions(+), 88 deletions(-) create mode 100644 app/models/payments_session.py diff --git a/SQL/site_data.sql b/SQL/site_data.sql index ecdc1ef..254ac34 100644 --- a/SQL/site_data.sql +++ b/SQL/site_data.sql @@ -460,6 +460,39 @@ CREATE TABLE subscription_options_items ( ADD CONSTRAINT subscription_options_items_id_key UNIQUE (id); +CREATE TABLE payments_session( + id SERIAL, + uid uuid DEFAULT uuid_generate_v4(), + member_id INT REFERENCES members(id), + option_name VARCHAR(100) REFERENCES subscription_options(option_name), + processor VARCHAR(25) NOT NULL, + session_id VARCHAR(150) NOT NULL, + status INT DEFAULT 1, + added timestamp without time zone DEFAULT now(), + updated timestamp without time zone DEFAULT now() + ); + ALTER TABLE ONLY payments_session + ADD CONSTRAINT payments_session_id_key UNIQUE (id); + +ALTER TABLE payments_session OWNER TO merms_panel; + +-- +-- __tablename__ = 'payments_session' +-- +-- id = db.Column( +-- db.Integer, +-- primary_key=True, +-- autoincrement=True, +-- ) +-- uid = db.Column(db.String(150), nullable=True) +-- member_id = db.Column(db.Integer, nullable=False) +-- product_id = db.Column(db.String(25), nullable=False) +-- processor = db.Column(db.String(25), nullable=False) +-- session_id = db.Column(db.String(150), nullable=False) +-- status = db.Column(db.Integer, nullable=True, default=1) +-- 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()) + CREATE TABLE payments ( id SERIAL, uid uuid DEFAULT uuid_generate_v4(), diff --git a/app/api/routes/routes.py b/app/api/routes/routes.py index 833f6e3..34dd032 100644 --- a/app/api/routes/routes.py +++ b/app/api/routes/routes.py @@ -138,14 +138,14 @@ def merms_account_product_url(): @api.route("/panel/account/products/url", methods=["POST"]) def myproduct_url(): data = request.get_json() - logger.info(f"Route Product URL Data ==>>>> {data}") + # logger.info(f"Route Product URL Data ==>>>> {data}") response = ProductsService.product_url_request(data) return response @api.route("/panel/account/products/refresh", methods=["POST"]) def myproduct_refresh(): data = request.get_json() - logger.info(f"Route Product URL Data ==>>>> {data}") + # logger.info(f"Route Product URL Data ==>>>> {data}") response = ProductsService.myproduct_refresh_request(data) return response @@ -154,14 +154,14 @@ def myproduct_refresh(): def get_myproduct_templates(): # Call the Template service data = request.get_json() - logger.info(f"Route Product Template Data ==>>>> {data}") + # logger.info(f"Route Product Template Data ==>>>> {data}") response = MyProductsService.mpproduct_template_data(data) return response @api.route("/panel/contacts", methods=["POST"]) def merms_contacts(): data = request.get_json() - logger.info(f"Route ContactService URL Data ==>>>> {data}") + # logger.info(f"Route ContactService URL Data ==>>>> {data}") response = ContactService.process_request(data) return response @@ -178,28 +178,28 @@ def merms_products(): @api.route("/panel/myproduct/dash", methods=["POST"]) def myproduct_dash(): data = request.get_json() - logger.info(f"Route MyProduct Data ==>>>> {data}") + # logger.info(f"Route MyProduct Data ==>>>> {data}") response = MyProductsService.process_request(data) return response @api.route("/panel/myproduct/settings", methods=["POST"]) def myproduct_settings(): data = request.get_json() - logger.info(f"Route Save 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}") + # logger.info(f"Route Get MyProduct Settings Data ==>>>> {data}") response = MyProductsService.process_settings_values(data) return response @api.route("/panel/subscription/products", methods=["POST"]) def subscription_products(): data = request.get_json() - logger.info(f"Route Subscription Product Data ==>>>> {data}") + # logger.info(f"Route Subscription Product Data ==>>>> {data}") response = SubscriptionService.subscription_available_products(data) return response @@ -207,7 +207,7 @@ def subscription_products(): @api.route("/panel/subscription/start", methods=["POST"]) def subscription_sessuib_start(): data = request.get_json() - logger.info(f"Route Subscription Session Start ==>>>> {data}") + # logger.info(f"Route Subscription Session Start ==>>>> {data}") response = SubscriptionService.subscription_session_start(data) return response @@ -216,7 +216,7 @@ def subscription_sessuib_start(): @api.route("/panel/myproduct/subscription", methods=["POST"]) def myproduct_subscription(): data = request.get_json() - logger.info(f"Route MyProduct Data ==>>>> {data}") + # logger.info(f"Route MyProduct Data ==>>>> {data}") response = MyProductsService.process_subscription(data) return response @@ -224,14 +224,14 @@ def myproduct_subscription(): @api.route("/panel/myproduct/provision", methods=["POST"]) def myproduct_provision(): data = request.get_json() - logger.info(f"Route MyProduct Data ==>>>> {data}") + # logger.info(f"Route MyProduct Data ==>>>> {data}") response = MyProductsService.process_provision(data) return response @api.route("/panel/myproduct/provision-actions", methods=["POST"]) def myproduct_provision_actions(): data = request.get_json() - logger.info(f"Route MyProduct Provision Actions ==>>>> {data}") + # logger.info(f"Route MyProduct Provision Actions ==>>>> {data}") response = MyProductsService.process_provision_actions(data) return response @@ -247,7 +247,7 @@ def stripe_payments_webhook(): @api.route("/panel/account/calendar", methods=["POST"]) def mycalendar_dash(): data = request.get_json() - logger.info(f"Route Calendar Data ==>>>> {data}") + # logger.info(f"Route Calendar Data ==>>>> {data}") response = AccountService.process_calendar(data) return response diff --git a/app/api/services/account.py b/app/api/services/account.py index ea6c30f..2323550 100644 --- a/app/api/services/account.py +++ b/app/api/services/account.py @@ -77,7 +77,7 @@ class AccountService(BaseService): "completed": random.randint(0, 10) } - logger.info(f"Member Actions Error: {action_data}") + # logger.info(f"Member Actions : {action_data}") return ResponseHelper.success(data=action_data) diff --git a/app/api/services/myproduct.py b/app/api/services/myproduct.py index af51ec7..14f55b8 100644 --- a/app/api/services/myproduct.py +++ b/app/api/services/myproduct.py @@ -27,7 +27,7 @@ class MyProductsService(BaseService): def mpproduct_template_data(data): try: with db.session.begin(): - logger.info(f"Incoming MyProduct data ==>>>> {data}") + # logger.info(f"Incoming MyProduct data ==>>>> {data}") validated_data = MyProductsService.validate_data(data, MyProductSchema()) token = validated_data.get('token') uid = validated_data.get('uid') @@ -98,7 +98,7 @@ class MyProductsService(BaseService): def process_provision(data): try: with db.session.begin(): - logger.info(f"Incoming MyProduct data ==>>>> {data}") + # logger.info(f"Incoming MyProduct data ==>>>> {data}") validated_data = MyProductsService.validate_data(data, ProvisionSchema()) token = validated_data.get('token') uid = validated_data.get('uid') @@ -158,7 +158,7 @@ class MyProductsService(BaseService): def process_subscription(data): try: with db.session.begin(): - logger.info(f"Incoming MyProduct data ==>>>> {data}") + # logger.info(f"Incoming MyProduct data ==>>>> {data}") validated_data = MyProductsService.validate_data(data, MyProductSchema()) token = validated_data.get('token') uid = validated_data.get('uid') @@ -238,7 +238,7 @@ class MyProductsService(BaseService): memberSubscription = MembersProducts.get_member_product_by_product_member_id(member_id, product_id) if memberSubscription is not None: - logger.info(f"Incoming MyProduct data ==>>>> {memberSubscription}") + # logger.info(f"Incoming MyProduct data ==>>>> {memberSubscription}") productDataStatus = memberSubscription.status product_subscription_uid = memberSubscription.uid # product_subscription_external_url = memberSubscription.external_url @@ -291,7 +291,7 @@ class MyProductsService(BaseService): def process_request(data): try: with db.session.begin(): - logger.info(f"Incoming MyProduct data ==>>>> {data}") + # logger.info(f"Incoming MyProduct data ==>>>> {data}") validated_data = MyProductsService.validate_data(data, MyProductSchema()) token = validated_data.get('token') uid = validated_data.get('uid') @@ -307,7 +307,7 @@ class MyProductsService(BaseService): memberSubscription = MembersProducts.get_member_product_by_product_member_id(member_id, product_id) if memberSubscription is not None: - logger.info(f"Incoming MyProduct data ==>>>> {memberSubscription}") + # logger.info(f"Incoming MyProduct data ==>>>> {memberSubscription}") productDataStatus = memberSubscription.status product_subscription_uid = memberSubscription.uid product_subscription_external_url = memberSubscription.external_url @@ -363,7 +363,7 @@ class MyProductsService(BaseService): def process_settings_values(data): try: with db.session.begin(): - logger.info(f"Incoming MyProduct data ==>>>> {data}") + # logger.info(f"Incoming MyProduct data ==>>>> {data}") validated_data = MyProductsService.validate_data(data, MyProductSchema()) token = validated_data.get('token') uid = validated_data.get('uid') @@ -379,7 +379,7 @@ class MyProductsService(BaseService): 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}") + # logger.info(f"Incoming MyProduct data ==>>>> {memberSubscription}") product_subscription_uid = memberSubscription.uid settings_data_result = MembersProductsSettings.get_product_settings_by_product_id_and_member_id( product_id, member_id) diff --git a/app/api/services/products.py b/app/api/services/products.py index fef211e..1be9898 100644 --- a/app/api/services/products.py +++ b/app/api/services/products.py @@ -55,7 +55,7 @@ class ProductsService(BaseService): products = Products.get_user_product_list(member_id) product_data=[] - logger.info(f"Product Data ****** *****: {products}") + # logger.info(f"Product Data ****** *****: {products}") for t in products: currentStatus = t.status @@ -65,7 +65,7 @@ class ProductsService(BaseService): if filtered_list: product_sub_result = filtered_list[0] currentStatus = product_sub_result["status"] - logger.info(f"Member Product Filtered Sub Data Status ****** *****: {currentStatus}") + # logger.info(f"Member Product Filtered Sub Data Status ****** *****: {currentStatus}") icon_style = '' st_text = "Activate Now" product_icon = "fa-cart-plus", @@ -232,7 +232,7 @@ class ProductsService(BaseService): products = MembersProducts.get_member_productlist_by_member_id(member_id) product_data=[] - logger.info(f"Product Data ****** *****: {products}") + # logger.info(f"Product Data ****** *****: {products}") for t in products: diff --git a/app/api/services/subscription.py b/app/api/services/subscription.py index c02640f..8028a14 100644 --- a/app/api/services/subscription.py +++ b/app/api/services/subscription.py @@ -6,7 +6,7 @@ from app.api.helpers.response_helper import ResponseHelper from app.api.schemas.user import UserSchema from app.api.schemas.subscription_session import SubscriptionSession from marshmallow import ValidationError -from app.models import Members, MembersProducts, SubscriptionOptions, SubscriptionOptionsItems +from app.models import Members, MembersProducts, SubscriptionOptions, SubscriptionOptionsItems, PaymentsSession from app.extensions import db from app.api.integrations import StripeIntegration @@ -152,7 +152,7 @@ class SubscriptionService(BaseService): def subscription_session_start(data): try: with db.session.begin(): - logger.info(f"Incoming MyProduct data ==>>>> {data}") + # logger.info(f"Incoming MyProduct data ==>>>> {data}") validated_data = SubscriptionService.validate_data(data, SubscriptionSession()) token = validated_data.get('token') uid = validated_data.get('uid') @@ -168,7 +168,9 @@ class SubscriptionService(BaseService): return [] stripe_session = StripeIntegration.create_checkout_session_subscription(priceId, customerId) - logger.info(f"Inside Stripe_Session ===== : {stripe_session}") + logger.info(f"Inside Stripe_Session ===== : {stripe_session}") + logger.info(f"Inside Stripe_Session ID ===== : {stripe_session.id}") + PaymentsSession.add_payment_session(member_id, option_name, 'STRIPE', stripe_session.id) # # product_id = validated_data.get('product_id') # product_subscription_uid='' diff --git a/app/models/__init__.py b/app/models/__init__.py index a4a2489..1180f32 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -25,7 +25,7 @@ from .members_profile import MembersProfile from .subscription_options import SubscriptionOptions from .subscription_options_items import SubscriptionOptionsItems from .products_templates import ProductsTemplates - +from .payments_session import PaymentsSession @@ -34,7 +34,7 @@ __all__ = ['Members','Customer', 'Account', 'Products', 'MembersProducts', 'MembersActions', 'MembersPending', 'ProductsDetails', 'ProvisionActions', 'MembersProductsRefresh','MembersProductsSettings', 'PasswordReset','MembersProfile','SubscriptionOptions','SubscriptionOptionsItems', - 'ProductsTemplates', + 'ProductsTemplates','PaymentsSession', 'Loan', 'Transaction', 'Repayment', 'LoanCharge', 'Offer', 'Charge', 'RACCheck', 'LoanRepaymentSchedule', diff --git a/app/models/payments.py b/app/models/payments.py index d3c9553..1550647 100644 --- a/app/models/payments.py +++ b/app/models/payments.py @@ -3,75 +3,44 @@ from app.extensions import db from app.models.charge import Charge from sqlalchemy.orm import relationship from sqlalchemy.sql import func +from sqlalchemy.exc import IntegrityError -class Offer(db.Model): +class Payments(db.Model): __tablename__ = 'payments' - id = db.Column(db.String, primary_key=True) - product_id = db.Column(db.String, nullable=False) - min_amount = db.Column(db.Float, nullable=False) - max_amount = db.Column(db.Float, nullable=False) - tenor = db.Column(db.Integer, nullable=False) - schedule = db.Column(db.Integer, nullable=True) - interest_rate = db.Column(db.Float, default=3.0) - management_rate = db.Column(db.Float, default=1.0) - insurance_rate = db.Column(db.Float, default=1.0) - vat_rate = db.Column(db.Float, default=7.5) - list_order = db.Column(db.Integer, nullable=True) - max_daily_loans = db.Column(db.Integer, nullable=True) - max_active_loans = db.Column(db.Integer, nullable=True) - max_life_loans = db.Column(db.Integer, nullable=True) - created_at = db.Column(db.DateTime(timezone=True), server_default=func.now()) - updated_at = db.Column(db.DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) - - charges = relationship( - "Charge", - primaryjoin="Offer.id == Charge.offer_id", - foreign_keys="Charge.offer_id", - back_populates="offer", + id = db.Column( + db.Integer, + primary_key=True, + autoincrement=True, ) + uid = db.Column(db.String(150), nullable=True) + member_id = db.Column(db.Integer, nullable=False) + product_id = db.Column(db.String(25), nullable=False) + processor = db.Column(db.String(25), nullable=False) + status = db.Column(db.Integer, nullable=True, default=1) + 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()) @classmethod - def get_all_offers(cls): - """ - Return all offers in dictionary format. - """ - offers = cls.query.all() + def add_payment(cls, customer_id, account_id, transaction_id, data=None): - if not offers: - raise ValueError(f"No available offers") - return offers + # Save the response + rac_check = cls( + customer_id=customer_id, + account_id=account_id, + transaction_id=transaction_id, + added=datetime.now(timezone.utc), + updated=datetime.now(timezone.utc) + ) - @classmethod - def is_valid_offer(cls, offer_id): - offer = cls.query.filter_by(id=str(offer_id)).first() + try: + db.session.add(rac_check) + except IntegrityError as err: + raise ValueError(f"Database integrity error: {err}") + return rac_check - if not offer: - return False - return offer - @classmethod - def get_offer_by_id(cls, offer_id): - """ - Return an offer by its ID. - """ - offer = cls.query.filter_by(id=str(offer_id)).first() - - if not offer: - raise ValueError(f"Offer with ID {offer_id} not found") - return offer - - @classmethod - def get_offer_by_product_id(cls, product_id): - """ - Return an offer by its product ID. - """ - offer = cls.query.filter_by(product_id=str(product_id)).first() - - if not offer: - raise ValueError(f"Offer with Product ID {product_id} not found") - return offer def to_dict(self): return { diff --git a/app/models/payments_session.py b/app/models/payments_session.py new file mode 100644 index 0000000..b7e6f3f --- /dev/null +++ b/app/models/payments_session.py @@ -0,0 +1,60 @@ +from datetime import datetime, timezone +from app.extensions import db +from app.models.charge import Charge +from sqlalchemy.orm import relationship +from sqlalchemy.sql import func +from sqlalchemy.exc import IntegrityError +import uuid + +class PaymentsSession(db.Model): + __tablename__ = 'payments_session' + + id = db.Column( + db.Integer, + primary_key=True, + autoincrement=True, + ) + uid = db.Column(db.String(150), nullable=True) + member_id = db.Column(db.Integer, nullable=False) + option_name = db.Column(db.String(100), nullable=False) + processor = db.Column(db.String(25), nullable=False) + session_id = db.Column(db.String(150), nullable=False) + status = db.Column(db.Integer, nullable=True, default=1) + 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()) + + @classmethod + def add_payment_session(cls, member_id, option_name, processor, session_id): + + # save the response + session_data = cls( + uid=str(uuid.uuid4()), + member_id=member_id, + option_name=option_name, + processor=processor, + session_id=session_id, + added=datetime.now(timezone.utc), + updated=datetime.now(timezone.utc) + ) + + try: + db.session.add(session_data) + except IntegrityError as err: + raise ValueError(f"database integrity error: {err}") + return session_data + + def to_dict(self): + return { + "id": self.id, + "uid": self.uid, + "member_id": self.member_id, + "option_name": self.option_name, + "processor": self.processor, + "session_id": self.session_id, + "status": self.status, + "added": self.added, + "updated": self.updated + } + + def __repr__(self): + return f'' \ No newline at end of file