Compare commits

1 Commits

Author SHA1 Message Date
CHIEFSOFT\ameye 5c7b31cc24 git ignore 2025-08-30 05:04:31 -04:00
96 changed files with 2241 additions and 8924 deletions
-20
View File
@@ -20,7 +20,6 @@ DATABASE_HOST=10.20.30.60
DATABASE_PORT=5432
DATABASE_NAME=merms_panel
ALLOWED_SIGNUP_EMAIL_RESUSE=0
KAFKA_BROKER = '10.10.10.120:9092'
SIMBRELLA_BASE_URL00="http://10.10.11.17:6337"
@@ -29,26 +28,13 @@ SIMBRELLA_APP_ID="app1"
SIMBRELLA_API_KEY="testtest-api-key-12345"
#JWT_SECRET_KEY=dce6bd64f7d7101de4f
# support@mermsemr.com
# F7f220a7f.may12002!
# twillo recovery - BPR7DMFHP53D919YWYWB6R5F
MAIL_SERVER=smtp.gmail.com
MAIL_PORT= 465
MAIL_USERNAME=message@chiefsoft.com
MAIL_PASSWORD=may12002!
# MAIL_USERNAME=support@mermsemr.com
# MAIL_PASSWORD="aoqz xuqc rlrv ltzd"
# F7f220a7f.may12002!
SEND_EMAIL_FROM=support@mermsemr.com
SEND_EMAIL_PASS=F7f220a7f.may12002!
JWT_SECRET_KEY=dce6bd64f7d7101de4fed7cfc185a12851611a79bd60bbfdcc5b414b85f1fdb75e0905691c2a77ce94a7351b261fab4e183e17731ed40089f68f7290a793119f285d8ec7902d248ce15e8b1d4996ebacf5e7bcb06a38ac7ce0736f17d5c2895a499661d27095ac20aa174f9af2fba9a849dd2e6fd0aad8aa7e1ecc030c11eb8dc8dcb71d32233de3530d04f85918b9582f8b02587a7350aa34232825d4831707c7c5775026f3fdd92c5df555e6ff8b785525922709830206bbd49c371fb6e16bcab01ffccaf904108bb9789c578bce6afbb33bc77960051e680b2428d1f026473e71ef0f9997b2a6dc496e1c40509a1d289e3ff8b384c2d49e1d7719f9f4aaa1
OPENAI_API_KEY = "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"
START_URL_PATTERN =".devprov.mermsemr.com"
#Publishable key
STRIPE_PUB_KEY="pk_test_51RqL5WLjZLojw6IZmEpwFidNZSl9lLlVUHNvuFZNEz1eTR9XXepnyyVhfvXe9cp4eMnqkDPpoe9wxLLRSV0dxRee00UfhayUOT"
@@ -59,9 +45,3 @@ STRIPE_SUCCESS_URL="https://qa-panel.mermsemr.com/subscription-success?session_i
STRIPE_CANCEL_URL="https://qa-panel.mermsemr.com/subscription"
# UPLOAD PATHS
UPLOAD_FOLDER="/app/uploads/DEV"
MEDIA_SERVER="https://qa-media.mermsemr.com"
AWS_ACCESS_KEY_ID=AKIAZAI4GVFJEGM4JHET
AWS_SECRET_ACCESS_KEY=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
+4 -24
View File
@@ -9,7 +9,7 @@ BASIC_AUTH_PASSWORD=password
SWAGGER_URL="/documentation"
API_URL="/swagger.json"
THIS_SITE_URL="https://panel.mermsemr.com"
THIS_SITE_URL="http://localhost:8090"
SWAGGER_URL="/documentation"
API_URL="/swagger.json"
@@ -18,9 +18,8 @@ DATABASE_USER=merms_panel
DATABASE_PASSWORD=merms_panel
DATABASE_HOST=10.13.3.60
DATABASE_PORT=5432
DATABASE_NAME=merms_panel
DATABASE_NAME=merms_panel_live
ALLOWED_SIGNUP_EMAIL_RESUSE=0
KAFKA_BROKER = '10.10.10.120:9092'
SIMBRELLA_BASE_URL00="http://10.10.11.17:6337"
@@ -34,31 +33,12 @@ MAIL_SERVER=smtp.gmail.com
MAIL_PORT= 465
MAIL_USERNAME=message@chiefsoft.com
MAIL_PASSWORD=may12002!
# MAIL_USERNAME=support@mermsemr.com
# MAIL_PASSWORD="aoqz xuqc rlrv ltzd"
# F7f220a7f.may12002!
JWT_SECRET_KEY=dce6bd64f7d7101de4fed7cfc185a12851611a79bd60bbfdcc5b414b85f1fdb75e0905691c2a77ce94a7351b261fab4e183e17731ed40089f68f7290a793119f285d8ec7902d248ce15e8b1d4996ebacf5e7bcb06a38ac7ce0736f17d5c2895a499661d27095ac20aa174f9af2fba9a849dd2e6fd0aad8aa7e1ecc030c11eb8dc8dcb71d32233de3530d04f85918b9582f8b02587a7350aa34232825d4831707c7c5775026f3fdd92c5df555e6ff8b785525922709830206bbd49c371fb6e16bcab01ffccaf904108bb9789c578bce6afbb33bc77960051e680b2428d1f026473e71ef0f9997b2a6dc496e1c40509a1d289e3ff8b384c2d49e1d7719f9f4aaa1
OPENAI_API_KEY = "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"
START_URL_PATTERN =".liveprov.mermsemr.com"
#Publishable key
STRIPE_PUB_KEY="pk_live_51RqL5OQ8vepTmh4AbXAnFmbgWDNJys2sfDcsLPVnOKRFx8EVOBOlO2RRN4lRNh6wNPhAj1A28xL3R0wHlMJ4WECo00rOM5iOto"
STRIPE_PUB_KEY_0="pk_test_51RqL5WLjZLojw6IZmEpwFidNZSl9lLlVUHNvuFZNEz1eTR9XXepnyyVhfvXe9cp4eMnqkDPpoe9wxLLRSV0dxRee00UfhayUOT"
STRIPE_PUB_KEY="pk_test_51RqL5WLjZLojw6IZmEpwFidNZSl9lLlVUHNvuFZNEz1eTR9XXepnyyVhfvXe9cp4eMnqkDPpoe9wxLLRSV0dxRee00UfhayUOT"
#Secret key
STRIPE_PRIV_KEY="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"
STRIPE_PRIV_KEY_0="sk_test_51RqL5WLjZLojw6IZZa921BftQWmxZ4JDxrHUrFZvc5kwJhxtK3ijZguUw42c4Rl5yjmpkdYlbpslDOaMGtOSrsL100oaN72Lne"
STRIPE_PRIV_KEY="sk_test_51RqL5WLjZLojw6IZZa921BftQWmxZ4JDxrHUrFZvc5kwJhxtK3ijZguUw42c4Rl5yjmpkdYlbpslDOaMGtOSrsL100oaN72Lne"
STRIPE_SUCCESS_URL="https://panel.mermsemr.com/subscription-success?session_id={CHECKOUT_SESSION_ID}"
STRIPE_CANCEL_URL="https://panel.mermsemr.com/subscription"
# UPLOAD PATHS
UPLOAD_FOLDER="/app/uploads/LIVE"
MEDIA_SERVER="https://media.mermsemr.com"
# CACHE
CACHE_SERVER = "172.16.4.20"
CACHE_PORT = 6378
CACHE_PASSWORD = "7f079034e166ecf52d82cbec9876e4dc8a154b0c37248f3fa1734d4eeab938d5"
CACHE_DEFAULT_EXPIRE = 21600
-5
View File
@@ -31,8 +31,6 @@ SIMBRELLA_BASE_URL="https://bank-emulator.dev.simbrellang.net"
VALID_APP_ID=app1
VALID_API_KEY=test-api-key-12345
ALLOWED_SIGNUP_EMAIL_RESUSE=0
START_URL_PATTERN =".devprov.mermsemr.com"
# Event Bus Broker Configuration
KAFKA_BROKER = '10.10.10.120:9092'
@@ -43,6 +41,3 @@ STRIPE_PUB_KEY="pk_test_51RqL5WLjZLojw6IZmEpwFidNZSl9lLlVUHNvuFZNEz1eTR9XXepnyyV
#Secret key
STRIPE_PRIV_KEY="sk_test_51RqL5WLjZLojw6IZZa921BftQWmxZ4JDxrHUrFZvc5kwJhxtK3ijZguUw42c4Rl5yjmpkdYlbpslDOaMGtOSrsL100oaN72Lne"
# UPLOAD PATHS
UPLOAD_FOLDER="/app/uploads/DEV"
MEDIA_SERVER="https://qa-media.mermsemr.com"
-12
View File
@@ -24,7 +24,6 @@ DATABASE_HOST=10.20.30.60
DATABASE_PORT=5432
DATABASE_NAME=merms_panel
ALLOWED_SIGNUP_EMAIL_RESUSE=0
KAFKA_BROKER = '10.10.10.120:9092'
# DATABASE_HOST=10.20.30.60
@@ -45,14 +44,7 @@ MAIL_SERVER=smtp.gmail.com
MAIL_PORT= 465
MAIL_USERNAME=message@chiefsoft.com
MAIL_PASSWORD=may12002!
# MAIL_USERNAME=support@mermsemr.com
# MAIL_PASSWORD="aoqz xuqc rlrv ltzd"
# F7f220a7f.may12002!
JWT_SECRET_KEY=dce6bd64f7d7101de4fed7cfc185a12851611a79bd60bbfdcc5b414b85f1fdb75e0905691c2a77ce94a7351b261fab4e183e17731ed40089f68f7290a793119f285d8ec7902d248ce15e8b1d4996ebacf5e7bcb06a38ac7ce0736f17d5c2895a499661d27095ac20aa174f9af2fba9a849dd2e6fd0aad8aa7e1ecc030c11eb8dc8dcb71d32233de3530d04f85918b9582f8b02587a7350aa34232825d4831707c7c5775026f3fdd92c5df555e6ff8b785525922709830206bbd49c371fb6e16bcab01ffccaf904108bb9789c578bce6afbb33bc77960051e680b2428d1f026473e71ef0f9997b2a6dc496e1c40509a1d289e3ff8b384c2d49e1d7719f9f4aaa1
OPENAI_API_KEY = "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"
START_URL_PATTERN =".devprov.mermsemr.com"
#Publishable key
STRIPE_PUB_KEY="pk_test_51RqL5WLjZLojw6IZmEpwFidNZSl9lLlVUHNvuFZNEz1eTR9XXepnyyVhfvXe9cp4eMnqkDPpoe9wxLLRSV0dxRee00UfhayUOT"
@@ -61,7 +53,3 @@ STRIPE_PRIV_KEY="sk_test_51RqL5WLjZLojw6IZZa921BftQWmxZ4JDxrHUrFZvc5kwJhxtK3ijZg
STRIPE_SUCCESS_URL="https://qa-panel.mermsemr.com/subscription-success?session_id={CHECKOUT_SESSION_ID}"
STRIPE_CANCEL_URL="https://qa-panel.mermsemr.com/subscription"
# UPLOAD PATHS
UPLOAD_FOLDER="/app/uploads/DEV"
MEDIA_SERVER="https://qa-media.mermsemr.com"
+2 -3
View File
@@ -27,6 +27,5 @@ STRIPE_PUB_KEY="pk_test_51RqL5WLjZLojw6IZmEpwFidNZSl9lLlVUHNvuFZNEz1eTR9XXepnyyV
#Secret key
STRIPE_PRIV_KEY="sk_test_51RqL5WLjZLojw6IZZa921BftQWmxZ4JDxrHUrFZvc5kwJhxtK3ijZguUw42c4Rl5yjmpkdYlbpslDOaMGtOSrsL100oaN72Lne"
# UPLOAD PATHS
UPLOAD_FOLDER="/app/uploads/DEV"
MEDIA_SERVER="https://qa-media.mermsemr.com"
SIMBRELLA_BASE_URL=***************
+5 -1
View File
@@ -7,4 +7,8 @@ migrations/*.pycg
./vscode
.vscode/settings.json
.idea
.idea/
.idea/
.idea/*
.idea/inspectionProfiles/Project_Default.xml
.idea/misc.xml
.idea/.gitignore
-16
View File
@@ -44,8 +44,6 @@ MAIL_USERNAME=message@chiefsoft.com
MAIL_PASSWORD=may12002!
JWT_SECRET_KEY=dce6bd64f7d7101de4fed7cfc185a12851611a79bd60bbfdcc5b414b85f1fdb75e0905691c2a77ce94a7351b261fab4e183e17731ed40089f68f7290a793119f285d8ec7902d248ce15e8b1d4996ebacf5e7bcb06a38ac7ce0736f17d5c2895a499661d27095ac20aa174f9af2fba9a849dd2e6fd0aad8aa7e1ecc030c11eb8dc8dcb71d32233de3530d04f85918b9582f8b02587a7350aa34232825d4831707c7c5775026f3fdd92c5df555e6ff8b785525922709830206bbd49c371fb6e16bcab01ffccaf904108bb9789c578bce6afbb33bc77960051e680b2428d1f026473e71ef0f9997b2a6dc496e1c40509a1d289e3ff8b384c2d49e1d7719f9f4aaa1
START_URL_PATTERN =".liveprov.mermsemr.com"
#Publishable key
STRIPE_PUB_KEY="pk_test_51RqL5WLjZLojw6IZmEpwFidNZSl9lLlVUHNvuFZNEz1eTR9XXepnyyVhfvXe9cp4eMnqkDPpoe9wxLLRSV0dxRee00UfhayUOT"
#Secret key
@@ -55,17 +53,3 @@ STRIPE_SUCCESS_URL="https://panel.mermsemr.com/subscription-success?session_id={
STRIPE_CANCEL_URL="https://panel.mermsemr.com/subscription"
# UPLOAD PATHS
UPLOAD_FOLDER="/app/uploads/LIVE"
MEDIA_SERVER="https://media.mermsemr.com"
AWS_ACCESS_KEY_ID=AKIAZAI4GVFJEGM4JHET
AWS_SECRET_ACCESS_KEY=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
SYSTEM_SERVERS_AIRPLAY=http://10.13.2.20:8080/
SYSTEM_SERVERS_KAFKA=http://10.10.10.120:19000/
SYSTEM_SERVERS_ANSIBLE=http://10.13.2.18:3000/
SYSTEM_SERVERS_INT_HAPROXY=http://10.13.2.22:5555/
SYSTEM_SERVERS_PROVISION=http://10.13.3.15:8094/
SYSTEM_SERVERS_EVENT_MANAGER=http://10.13.3.15:5005/
SYSTEM_SERVERS_SOCKET_MANAGER=http://10.13.3.15:5006/
+1 -10
View File
@@ -39,8 +39,6 @@ SIMBRELLA_API_KEY="testtest-api-key-12345"
JWT_SECRET_KEY=dce6bd64f7d7101de4f
START_URL_PATTERN =".devprov.mermsemr.com"
# APP_PORT=14700
# FLASK_APP=project/__init__.py
# FLASK_DEBUG=1
@@ -56,11 +54,4 @@ START_URL_PATTERN =".devprov.mermsemr.com"
# MAIL_PORT= 465
# MAIL_USERNAME=message@chiefsoft.com
# MAIL_PASSWORD=may12002!
# JWT_SECRET=dce6bd64f7d7101de4f
# UPLOAD PATHS
UPLOAD_FOLDER="/app/uploads/DEV"
MEDIA_SERVER="https://qa-media.mermsemr.com"
AWS_ACCESS_KEY_ID=AKIAZAI4GVFJEGM4JHET
AWS_SECRET_ACCESS_KEY=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
# JWT_SECRET=dce6bd64f7d7101de4f
-56
View File
@@ -1,56 +0,0 @@
"MERMS-Web" was successfully created and added to the next step.
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
Configure your application
Configure your application with the settings below.
Server smtp.sendgrid.net
Ports
25, 587 (for unencrypted/TLS connections)
465 (for SSL connections)
Username apikey
Password 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
Create an API key
This allows your application to authenticate to our API and send mail. You can enable or disable additional permissions on the API keys page.
"Chief-Works" was successfully created and added to the next step.
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
Configure your application
Configure your application with the settings below.
Server smtp.sendgrid.net
Ports
25, 587 (for unencrypted/TLS connections)
465 (for SSL connections)
Username apikey
Password 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
SMTP credentials
IAM user name
ses-smtp-user.20260425-142515
SMTP user name
AKIAZAI4GVFJOPMTPLPL
SMTP password
BBawlUaS79J04F++4PvIhd2ULJT61vLOWvGNQKIPM6q+
Hide
SMTP credentials
IAM user name
ses-smtp-user.20260425-144948
SMTP user name
AKIAZAI4GVFJK2G2HEHE
SMTP password
BE9Lc5jMU1m58Jlfeey20IQ7OPz5jBA3q8BhMwVJjLD7
Hide
+9 -725
View File
@@ -46,15 +46,7 @@ ALTER TABLE members ALTER COLUMN password TYPE VARCHAR(250);
ALTER TABLE members ADD country VARCHAR(3);
ALTER TABLE members ADD stripe_customer_id VARCHAR(100)
ALTER TABLE members ADD profile_completed timestamp without time zone DEFAULT NULL;
ALTER TABLE members ADD option_name VARCHAR(100) REFERENCES subscription_options(option_name);
ALTER TABLE members ADD next_billing timestamp without time zone;
ALTER TABLE members ADD trial_end timestamp without time zone;
ALTER TABLE members ADD last_login timestamp without time zone DEFAULT now();
-- bALTER TABLE members ADD option_name VARCHAR(100) REFERENCES subscription_options(option_name);
ALTER TABLE members ADD phone VARCHAR(25);
ALTER TABLE members ADD full_address VARCHAR(150);
ALTER TABLE members ADD option_name VARCHAR(100) REFERENCES subscription_options(option_name)
CREATE TABLE members_profile(
id SERIAL,
@@ -72,7 +64,6 @@ ALTER TABLE ONLY members_profile
ALTER TABLE members_profile OWNER TO merms_panel
ALTER TABLE members_profile ADD url_name VARCHAR(25);
@@ -114,38 +105,6 @@ CREATE TABLE products (
ALTER TABLE products ADD banner VARCHAR(100);
UPDATE products set banner = 'p'||id||'.jpg'
ALTER TABLE products ADD start_url VARCHAR(100);
ALTER TABLE products ADD list_order INT DEFAULT 0;
ALTER TABLE products ADD contacts INT DEFAULT 0;
ALTER TABLE products ADD comments INT DEFAULT 0;
UPDATE products SET contacts = 1 WHERE product_id IN ('A000001','A000002');
UPDATE products SET comments = 1 WHERE product_id IN ('A000003','A000004');
ALTER TABLE products ADD blog_product_id VARCHAR(25);
UPDATE products SET blog_product_id='A000003' WHERE product_id = 'A000001';
UPDATE products SET blog_product_id='A000004' WHERE product_id = 'A000002';
--- initial set
UPDATE products SET list_order = 10*id;
UPDATE products SET name='Open-EMR' WHERE product_id = 'A000005';
--- DEVELOPMENT
UPDATE products SET start_url = 'A1.devprov.mermsemr.com' WHERE product_id = 'A000001';
UPDATE products SET start_url = 'A2.devprov.mermsemr.com' WHERE product_id = 'A000002';
UPDATE products SET start_url = 'A3.devprov.mermsemr.com' WHERE product_id = 'A000003';
UPDATE products SET start_url = 'A4.devprov.mermsemr.com' WHERE product_id = 'A000004';
UPDATE products SET start_url = 'A5.devprov.mermsemr.com' WHERE product_id = 'A000005';
--- PRODUCTION
UPDATE products SET start_url = '.pers.mermsemr.com' WHERE product_id = 'A000001';
UPDATE products SET start_url = '.prov.mermsemr.com' WHERE product_id = 'A000002';
UPDATE products SET start_url = 'p.forum.mermsemr.com' WHERE product_id = 'A000003';
UPDATE products SET start_url = 'v.forum.mermsemr.com' WHERE product_id = 'A000004';
UPDATE products SET start_url = '.ehr.mermsemr.com' WHERE product_id = 'A000005';
CREATE TABLE products_details (
id SERIAL,
@@ -269,53 +228,6 @@ merms_panel=# select product_id,description from products;
A000005 | Get Open EMR for practice management
(5 rows)
CREATE TABLE products_colorstyle (
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
product_id VARCHAR(25) REFERENCES products(product_id),
name VARCHAR(55) NOT NULL,
color_style VARCHAR(55) NOT NULL,
color_code VARCHAR(9) NOT NULL,
status INT DEFAULT 0,
added timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY products_colorstyle
ADD CONSTRAINT products_colorstyle_id_key UNIQUE (id);
ALTER TABLE products_colorstyle OWNER TO merms_panel;
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000001','Blue','blue-theme.css','0000FF');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000001','Crocus','crocus-theme.css','9172EC');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000001','Green','green-theme.css','00FF00');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000001','Magenta','magenta-theme.css','FF00FF');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000001','Pink','pink-theme.css','FFC0CB');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000001','Purple','purple-theme.css','800080');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000001','Skyblue','skyblue-theme.css','87CEEB');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000001','Red','red-theme.css','FF0000');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000001','Violet','violet-theme.css','8F00FF');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000002','Blue','blue-theme.css','0000FF');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000002','Crocus','crocus-theme.css','9172EC');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000002','Green','green-theme.css','00FF00');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000002','Magenta','magenta-theme.css','FF00FF');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000002','Pink','pink-theme.css','FFC0CB');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000002','Purple','purple-theme.css','800080');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000002','Skyblue','skyblue-theme.css','87CEEB');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000002','Red','red-theme.css','FF0000');
INSERT INTO products_colorstyle (product_id, name, color_style, color_code ) VALUES ('A000002','Violet','violet-theme.css','8F00FF');
ALTER TABLE members_products ADD colorstyle VARCHAR(55);
{`nav-link ${(activeTab == value.controls || (index == 0 & !activeTab)) && 'active show'}`}
CREATE TABLE products_templates (
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
@@ -332,9 +244,6 @@ ALTER TABLE members_products ADD colorstyle VARCHAR(55);
ALTER TABLE products_templates OWNER TO merms_panel;
INSERT INTO products_templates(product_id,name,provision_name,status)
VALUES(
'A000001',
@@ -380,89 +289,6 @@ VALUES(
''
);
ALTER TABLE products_templates ADD flavor VARCHAR(10);
UPDATE products_templates SET provision_name='registry.chiefsoft.com/a000002/business-web-web0002d:latest', flavor='P1' WHERE ID =4;
UPDATE products_templates SET provision_name='registry.chiefsoft.com/a000002/business-web-web0002d:latest', flavor='P2' WHERE ID =5;
UPDATE products_templates SET provision_name='registry.chiefsoft.com/a000001/personal-web-web0002a:latest', flavor='P1' WHERE ID =1;
UPDATE products_templates SET provision_name='registry.chiefsoft.com/a000001/personal-web-web0002a:latest', flavor='P2' WHERE ID =2;
UPDATE products_templates SET provision_name='registry.chiefsoft.com/a000001/personal-web-web0002a:latest', flavor='P3' WHERE ID =3;
INSERT INTO products_templates(product_id,name,provision_name,status,flavor)
VALUES(
'A000002',
'Practice 3',
'registry.chiefsoft.com/a000002/business-web-web0002d:latest',
1,
'P3'
);
INSERT INTO products_templates(product_id,name,provision_name,status,flavor)
VALUES(
'A000002',
'Practice 4',
'registry.chiefsoft.com/a000002/business-web-web0002d:latest',
1,
'P4'
);
INSERT INTO products_templates(product_id,name,provision_name,status,flavor)
VALUES(
'A000002',
'Practice 5',
'registry.chiefsoft.com/a000002/business-web-web0002d:latest',
1,
'P5'
);
INSERT INTO products_templates(product_id,name,provision_name,status,flavor)
VALUES(
'A000002',
'Practice 6',
'registry.chiefsoft.com/a000002/business-web-web0002d:latest',
1,
'P6'
);
INSERT INTO products_templates(product_id,name,provision_name,status,flavor)
VALUES(
'A000002',
'Practice 7',
'registry.chiefsoft.com/a000002/business-web-web0002d:latest',
1,
'P7'
);
INSERT INTO products_templates(product_id,name,provision_name,status,flavor)
VALUES(
'A000002',
'Practice 8',
'registry.chiefsoft.com/a000002/business-web-web0002d:latest',
1,
'P8'
);
INSERT INTO products_templates(product_id,name,provision_name,status,flavor)
VALUES(
'A000002',
'Practice 9',
'registry.chiefsoft.com/a000002/business-web-web0002d:latest',
1,
'P9'
);
INSERT INTO products_templates(product_id,name,provision_name,status,flavor)
VALUES(
'A000002',
'Practice 10',
'registry.chiefsoft.com/a000002/business-web-web0002d:latest',
1,
'P10'
);
CREATE TABLE members_products (
id SERIAL,
@@ -488,9 +314,8 @@ ALTER TABLE members_products ADD primary_server VARCHAR(100);
ALTER TABLE members_products ADD db_status INT DEFAULT 0;
ALTER TABLE members_products ADD provision_status INT DEFAULT 0;
ALTER TABLE members_products ADD p_file INT DEFAULT 0;
ALTER TABLE members_products ADD url_status INT DEFAULT 0;
ALTER TABLE members_products ADD product_template VARCHAR(100);
ALTER TABLE members_products ADD custom_template VARCHAR(100);
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');
@@ -504,54 +329,6 @@ INSERT INTO products (name,description,status,product_id, banner) VALUES ('Perso
INSERT INTO products (name,description,status,product_id, banner) VALUES ('Professional Blog','Booster your practice with engaging contents',1,'A000004', 'banner.jpg');
INSERT INTO products (name,description,status,product_id, banner) VALUES ('Practice EMR','Get Open EMR for practice management',1,'A000005', 'banner.jpg');
-- NEW PRODUCT------------------------------------------------------
INSERT INTO products (name,description,status,product_id, banner, start_url)
VALUES ('MERMs Practice',
'Get Merms EMR for your Practice Management',
5,
'A000006',
'p6.jpg',
'm.ehr.mermsemr.com');
-- UPDATE products SET start_url = 'm.ehr.mermsemr.com' WHERE product_id = '';
INSERT INTO products_details (product_id,details) VALUES ('A000006', '
<p><b>OpenEMR</b> is the most popular open source electronic health records and medical practice management solution. Merms EMR is a community of passionate volunteers and contributors dedicated to guarding OpenEMR status as a free, open source software solution for medical practices with a commitment to openness, kindness and cooperation.
</p><p>
Activate to deploy MERMS Emr for your practice
</p>');
UPDATE products_details SET sale_text =
'<br>
<hr>
Start free for 1 month, and customize your product with additional features as you see fit. You''re in control-you can cancel anytime.
<hr>
<br>' WHERE product_id= 'A000006';
INSERT INTO products_templates(product_id,name,provision_name,status)
VALUES(
'A000006',
'Template F01',
'registry.chiefsoft.com/products/merms-emr-001:latest',
1);
INSERT INTO products_templates(product_id,name,provision_name,status)
VALUES(
'A000006',
'Template F02',
'registry.chiefsoft.com/products/merms-emr-002:latest',
1);
-- UPDATE products SET start_url = 'm.ehr.mermsemr.com' WHERE product_id = 'A000006';
-- UPDATE products SET status = 5 WHERE product_id = 'A000006';
-- END 000 Product --------------------------------------------------
CREATE TABLE members_products_settings (
id SERIAL,
@@ -618,9 +395,6 @@ CREATE TABLE provision_actions (
ALTER TABLE ONLY provision_actions
ADD CONSTRAINT provision_actions_id_key UNIQUE (id);
ALTER TABLE provision_actions ADD percent_completed INT DEFAULT 5;
{"id": "3", "action": "Verifying your product..." , "date": "10-10-2010 11:00 AM"},
{"id": "2", "action": "URL assigned - Progress on the URL " , "date": "10-10-2010 11:30 AM"},
{"id": "1", "action": "Initiating product creation" , "date": "10-12-2010 11:30 AM"},
@@ -719,29 +493,23 @@ ALTER TABLE payments_session OWNER TO merms_panel;
-- 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())
ALTER TABLE members ADD option_name VARCHAR(100) REFERENCES subscription_options(option_name);
CREATE TABLE payments (
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
member_id INT REFERENCES members(id),
option_name VARCHAR(100) REFERENCES subscription_options(option_name),
option_type VARCHAR(25),
payment_uid VARCHAR(100) UNIQUE NOT NULL,
amount INT DEFAULT 0,
description VARCHAR(100) NOT NULL,
list_order INT DEFAULT 0,
status INT DEFAULT 1,
added timestamp without time zone DEFAULT now(),
sub_start timestamp without time zone,
next_billing timestamp without time zone,
sub_stop timestamp without time zone
added timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY payments
ADD CONSTRAINT payments_id_key UNIQUE (id);
ALTER TABLE payments OWNER TO merms_panel;
{'payment_uid': UUID('360b8829-45e0-4419-bcf0-18f4087f14b9'), 'member_id': 1, 'option_name': 'STATRTER001'}
@@ -805,124 +573,6 @@ INSERT INTO subscription_options_items (option_name,description,list_order)
VALUES('PREMIUM001','',0);
DROP TABLE subscription_generative;
CREATE TABLE subscription_generative(
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
member_id INT REFERENCES members(id),
practice VARCHAR(100) NOT NULL,
specialization VARCHAR(100) NOT NULL,
product_id VARCHAR(25) NOT NULL,
subscription_uid VARCHAR(100) NOT NULL,
status INT DEFAULT 0,
added timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY subscription_generative
ADD CONSTRAINT subscription_generative_id_key UNIQUE (id);
ALTER TABLE subscription_generative OWNER TO merms_panel;
CREATE TABLE generative_results(
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
member_id INT REFERENCES members(id) NOT NULL,
product_id VARCHAR(25) NOT NULL,
var_name VARCHAR(100) NOT NULL,
subscription_uid VARCHAR(100) NOT NULL,
text_result TEXT,
status INT DEFAULT 0,
added timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY generative_results
ADD CONSTRAINT generative_results_id_key UNIQUE (id);
ALTER TABLE generative_results OWNER TO merms_panel;
CREATE TABLE office_users(
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
username VARCHAR(25) UNIQUE NOT NULL,
password VARCHAR(100) NOT NULL,
firstname VARCHAR(25) NOT NULL,
lastname VARCHAR(25) NOT NULL,
acc_level INT DEFAULT 10,
status INT DEFAULT 0,
added timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY office_users
ADD CONSTRAINT office_users_id_key UNIQUE (id);
ALTER TABLE office_users ALTER COLUMN password TYPE VARCHAR(250);
ALTER TABLE office_users OWNER TO merms_panel;
INSERT INTO office_users (username, password, firstname, lastname, acc_level) VALUES ('mermsadmin','password','Merms','Admin',1000);
INSERT INTO office_users (username, password, firstname, lastname, acc_level) VALUES ('adminsanya','password','Sanya','Ameye',1000);
-- Dr.Sanya.Alan1!
CREATE TABLE products_contacts(
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
username VARCHAR(25) UNIQUE NOT NULL,
product_id VARCHAR(25) NOT NULL,
subscription_uid VARCHAR(100) NOT NULL,
title VARCHAR(100) NOT NULL,
sender VARCHAR(120) NOT NULL,
message TEXT,
status INT DEFAULT 0,
added timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY products_contacts
ADD CONSTRAINT products_contacts_id_key UNIQUE (id);
ALTER TABLE products_contacts OWNER TO merms_panel;
CREATE TABLE custom_templates (
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
custom_id VARCHAR(25) UNIQUE NOT NULL,
provision_name VARCHAR(250),
added timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY custom_templates
ADD CONSTRAINT custom_templates_id_key UNIQUE (id);
ALTER TABLE custom_templates OWNER TO merms_panel;
INSERT INTO custom_templates(custom_id,provision_name) VALUES('icare_template','registry.chiefsoft.com/custom/mermsicare-mermshostedicare-001:latest');
INSERT INTO custom_templates(custom_id,provision_name) VALUES('kevkem_template','registry.chiefsoft.com/custom/mermskevkem-mermshostedicare-001:latest');
INSERT INTO custom_templates(custom_id,provision_name) VALUES('sanya_pers_template','registry.chiefsoft.com/custom/mermssanyaameye-mermshosted-pers-sanyamaeye-001:latest');
icare_template
registry.chiefsoft.com/custom/mermsicare-mermshostedicare-001:latest
kevkem_template
registry.chiefsoft.com/custom/mermskevkem-mermshostedicare-001:latest
new_l = {
"uid": "425611f2-c692-4404-b93d-76ca7a5ce7" + str(x),
"title": "Contact Random Item on " + str(x),
"category": cat_list[random.randint(0, 3)],
"added": calDate,
"sender": "Firstname Lastname" + str(random.randint(1, 4)),
"message": dummy_message()
}
@@ -1074,26 +724,10 @@ VALUES
CREATE TABLE members_webfiles (
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
member_id INT REFERENCES members(id) NOT NULL,
member_uid VARCHAR(100) NOT NULL,
file_group VARCHAR(25) NOT NULL,
filename VARCHAR(100) NOT NULL,
save_filename VARCHAR(100) NOT NULL,
file_type VARCHAR(50) NOT NULL,
file_size INT DEFAULT 0,
status INT DEFAULT 1,
added timestamp without time zone DEFAULT now(),
updated timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY members_webfiles
ADD CONSTRAINT members_webfiles_id_key UNIQUE (id);
ALTER TABLE members ADD profile_picture VARCHAR(100);
@@ -1127,331 +761,6 @@ grant all privileges on database merms_panel to merms_panel;
CREATE TABLE country (
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
code VARCHAR(2) UNIQUE NOT NULL,
description VARCHAR(100) UNIQUE NOT NULL,
status INT DEFAULT 0,
signup INT DEFAULT 0,
added timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY country
ADD CONSTRAINT country_id_key UNIQUE (id);
ALTER TABLE country OWNER TO merms_panel;
INSERT INTO country(code,description) VALUES('AC','Acension Island');
INSERT INTO country(code,description) VALUES('AF','Afghanistan');
INSERT INTO country(code,description) VALUES('AL','Albania');
INSERT INTO country(code,description) VALUES('DZ','Algeria');
INSERT INTO country(code,description) VALUES('AS','American Samoa');
INSERT INTO country(code,description) VALUES('AD','Andorra');
INSERT INTO country(code,description) VALUES('AO','Angola');
INSERT INTO country(code,description) VALUES('AI','Anguilla');
INSERT INTO country(code,description) VALUES('AG','Antigua');
INSERT INTO country(code,description) VALUES('AR','Argentina');
INSERT INTO country(code,description) VALUES('AM','Armenia');
INSERT INTO country(code,description) VALUES('AW','Aruba');
INSERT INTO country(code,description) VALUES('AT','Austria');
INSERT INTO country(code,description) VALUES('AZ','Azerbaijan');
INSERT INTO country(code,description) VALUES('BS','Bahamas');
INSERT INTO country(code,description) VALUES('BH','Bahrain');
INSERT INTO country(code,description) VALUES('BD','Bangladesh');
INSERT INTO country(code,description) VALUES('BB','Barbados');
INSERT INTO country(code,description) VALUES('BY','Belarus');
INSERT INTO country(code,description) VALUES('BE','Belgium');
INSERT INTO country(code,description) VALUES('BZ','Belize');
INSERT INTO country(code,description) VALUES('BJ','Benin');
INSERT INTO country(code,description) VALUES('BM','Bermuda');
INSERT INTO country(code,description) VALUES('BT','Bhutan');
INSERT INTO country(code,description) VALUES('BO','Bolivia');
INSERT INTO country(code,description) VALUES('BA','Bosnia Herzegovina');
INSERT INTO country(code,description) VALUES('BW','Botswana');
INSERT INTO country(code,description) VALUES('BR','Brazil');
INSERT INTO country(code,description) VALUES('BN','Brunei');
INSERT INTO country(code,description) VALUES('BG','Bulgaria');
INSERT INTO country(code,description) VALUES('BF','Burkina Faso');
INSERT INTO country(code,description) VALUES('BI','Burundi');
INSERT INTO country(code,description) VALUES('KH','Cambodia');
INSERT INTO country(code,description) VALUES('CM','Cameroon');
INSERT INTO country(code,description) VALUES('CV','Cape Verde');
INSERT INTO country(code,description) VALUES('KY','Cayman Islands');
INSERT INTO country(code,description) VALUES('CF','Central African Republic');
INSERT INTO country(code,description) VALUES('TD','Chad');
INSERT INTO country(code,description) VALUES('CL','Chile');
INSERT INTO country(code,description) VALUES('CN','China');
INSERT INTO country(code,description) VALUES('CO','Colombia');
INSERT INTO country(code,description) VALUES('KM','Comoros Islands');
INSERT INTO country(code,description) VALUES('CD','Congo Democratic Republic');
INSERT INTO country(code,description) VALUES('CG','Congo Republic');
INSERT INTO country(code,description) VALUES('CK','Cook Islands');
INSERT INTO country(code,description) VALUES('CR','Costa Rica');
INSERT INTO country(code,description) VALUES('HR','Croatia');
INSERT INTO country(code,description) VALUES('CU','Cuba');
INSERT INTO country(code,description) VALUES('CY','Cyprus');
INSERT INTO country(code,description) VALUES('CZ','Czech Republic');
INSERT INTO country(code,description) VALUES('DK','Denmark');
INSERT INTO country(code,description) VALUES('DG','Diego Garcia');
INSERT INTO country(code,description) VALUES('DJ','Djibouti');
INSERT INTO country(code,description) VALUES('DM','Dominica');
INSERT INTO country(code,description) VALUES('DO','Dominican Republic');
INSERT INTO country(code,description) VALUES('EC','Ecuador');
INSERT INTO country(code,description) VALUES('EG','Egypt');
INSERT INTO country(code,description) VALUES('SV','El Salvador');
INSERT INTO country(code,description) VALUES('GQ','Equatorial Guinea');
INSERT INTO country(code,description) VALUES('ER','Eritrea');
INSERT INTO country(code,description) VALUES('EE','Estonia');
INSERT INTO country(code,description) VALUES('ET','Ethiopia');
INSERT INTO country(code,description) VALUES('FO','Faeroe Islands');
INSERT INTO country(code,description) VALUES('FK','Falkland Islands (Malvinas)');
INSERT INTO country(code,description) VALUES('FJ','Fiji Islands');
INSERT INTO country(code,description) VALUES('FI','Finland');
INSERT INTO country(code,description) VALUES('FR','France');
INSERT INTO country(code,description) VALUES('TF','French Antilles (Martinique)');
INSERT INTO country(code,description) VALUES('GF','French Guiana');
INSERT INTO country(code,description) VALUES('PF','French Polynesia');
INSERT INTO country(code,description) VALUES('GA','Gabon');
INSERT INTO country(code,description) VALUES('GM','Gambia');
INSERT INTO country(code,description) VALUES('GE','Georgia');
INSERT INTO country(code,description) VALUES('DE','Germany');
INSERT INTO country(code,description) VALUES('GI','Gibraltar');
INSERT INTO country(code,description) VALUES('GR','Greece');
INSERT INTO country(code,description) VALUES('GL','Greenland');
INSERT INTO country(code,description) VALUES('GD','Grenada');
INSERT INTO country(code,description) VALUES('GP','Guadeloupe');
INSERT INTO country(code,description) VALUES('GU','Guam');
INSERT INTO country(code,description) VALUES('GT','Guatemala');
INSERT INTO country(code,description) VALUES('GN','Guinea');
INSERT INTO country(code,description) VALUES('GH','Ghana');
INSERT INTO country(code,description) VALUES('GW','Guinea Bissau');
INSERT INTO country(code,description) VALUES('GY','Guyana');
INSERT INTO country(code,description) VALUES('HT','Haiti');
INSERT INTO country(code,description) VALUES('HN','Honduras');
INSERT INTO country(code,description) VALUES('HK','Hong Kong');
INSERT INTO country(code,description) VALUES('HU','Hungary');
INSERT INTO country(code,description) VALUES('IS','Iceland');
INSERT INTO country(code,description) VALUES('IN','India');
INSERT INTO country(code,description) VALUES('ID','Indonesia');
INSERT INTO country(code,description) VALUES('IR','Iran');
INSERT INTO country(code,description) VALUES('IQ','Iraq');
INSERT INTO country(code,description) VALUES('IE','Ireland');
INSERT INTO country(code,description) VALUES('IL','Israel');
INSERT INTO country(code,description) VALUES('IT','Italy');
INSERT INTO country(code,description) VALUES('CI','Ivory Coast');
INSERT INTO country(code,description) VALUES('JP','Japan');
INSERT INTO country(code,description) VALUES('JO','Jordan');
INSERT INTO country(code,description) VALUES('KZ','Kazakhstan');
INSERT INTO country(code,description) VALUES('KE','Kenya');
INSERT INTO country(code,description) VALUES('KI','Kiribati');
INSERT INTO country(code,description) VALUES('KW','Kuwait');
INSERT INTO country(code,description) VALUES('KG','Kyrgyzstan');
INSERT INTO country(code,description) VALUES('LA','Laos');
INSERT INTO country(code,description) VALUES('LV','Latvia');
INSERT INTO country(code,description) VALUES('LB','Lebanon');
INSERT INTO country(code,description) VALUES('LS','Lesotho');
INSERT INTO country(code,description) VALUES('LR','Liberia');
INSERT INTO country(code,description) VALUES('LY','Libya');
INSERT INTO country(code,description) VALUES('LI','Liechtenstein');
INSERT INTO country(code,description) VALUES('LT','Lithuania');
INSERT INTO country(code,description) VALUES('LU','Luxembourg');
INSERT INTO country(code,description) VALUES('MO','Macau');
INSERT INTO country(code,description) VALUES('MK','Macedonia');
INSERT INTO country(code,description) VALUES('MG','Madagascar');
INSERT INTO country(code,description) VALUES('MW','Malawi');
INSERT INTO country(code,description) VALUES('MY','Malaysia');
INSERT INTO country(code,description) VALUES('MV','Maldives');
INSERT INTO country(code,description) VALUES('ML','Mali');
INSERT INTO country(code,description) VALUES('MT','Malta');
INSERT INTO country(code,description) VALUES('MH','Marshall Islands');
INSERT INTO country(code,description) VALUES('MR','Mauritania');
INSERT INTO country(code,description) VALUES('MU','Mauritius');
INSERT INTO country(code,description) VALUES('MX','Mexico');
INSERT INTO country(code,description) VALUES('MD','Moldova');
INSERT INTO country(code,description) VALUES('MC','Monaco');
INSERT INTO country(code,description) VALUES('MN','Mongolia');
INSERT INTO country(code,description) VALUES('MS','Montserrat');
INSERT INTO country(code,description) VALUES('MA','Morocco');
INSERT INTO country(code,description) VALUES('MZ','Mozambique');
INSERT INTO country(code,description) VALUES('MM','Myanmar');
INSERT INTO country(code,description) VALUES('NA','Namibia');
INSERT INTO country(code,description) VALUES('NR','Nauru');
INSERT INTO country(code,description) VALUES('NP','Nepal');
INSERT INTO country(code,description) VALUES('NL','Netherlands');
INSERT INTO country(code,description) VALUES('AN','Netherlands Antilles');
INSERT INTO country(code,description) VALUES('NC','New Caledonia');
INSERT INTO country(code,description) VALUES('NI','Nicaragua');
INSERT INTO country(code,description) VALUES('NE','Niger');
INSERT INTO country(code,description) VALUES('NN','Niue');
INSERT INTO country(code,description) VALUES('KP','North Korea');
INSERT INTO country(code,description) VALUES('NO','Norway');
INSERT INTO country(code,description) VALUES('OM','Oman');
INSERT INTO country(code,description) VALUES('PK','Pakistan');
INSERT INTO country(code,description) VALUES('PW','Palau');
INSERT INTO country(code,description) VALUES('PL','Palestine');
INSERT INTO country(code,description) VALUES('PA','Panama');
INSERT INTO country(code,description) VALUES('PG','Papua New Guinea');
INSERT INTO country(code,description) VALUES('PY','Paraguay');
INSERT INTO country(code,description) VALUES('PE','Peru');
INSERT INTO country(code,description) VALUES('PH','Philippines');
INSERT INTO country(code,description) VALUES('PT','Portugal');
INSERT INTO country(code,description) VALUES('PR','Puerto Rico');
INSERT INTO country(code,description) VALUES('QA','Qatar');
INSERT INTO country(code,description) VALUES('RE','Reunion Island');
INSERT INTO country(code,description) VALUES('RO','Romania');
INSERT INTO country(code,description) VALUES('RU','Russia');
INSERT INTO country(code,description) VALUES('RW','Rwanda');
INSERT INTO country(code,description) VALUES('SH','Saint Helena');
INSERT INTO country(code,description) VALUES('KN','Saint Kitts and Nevis');
INSERT INTO country(code,description) VALUES('LC','Saint Lucia');
INSERT INTO country(code,description) VALUES('SP','Saint Pierre and Miquelon');
INSERT INTO country(code,description) VALUES('VC','Saint Vincent and The Grenadines');
INSERT INTO country(code,description) VALUES('SM','San Marino');
INSERT INTO country(code,description) VALUES('JM','Jamaica');
INSERT INTO country(code,description) VALUES('ST','Sao Tome and Principe');
INSERT INTO country(code,description) VALUES('SA','Saudi Arabia');
INSERT INTO country(code,description) VALUES('SN','Senegal');
INSERT INTO country(code,description) VALUES('CS','Serbia and Montenegro');
INSERT INTO country(code,description) VALUES('SC','Seychelles');
INSERT INTO country(code,description) VALUES('SL','Sierra Leone');
INSERT INTO country(code,description) VALUES('SK','Slovakia');
INSERT INTO country(code,description) VALUES('SI','Slovenia');
INSERT INTO country(code,description) VALUES('SB','Solomon Islands');
INSERT INTO country(code,description) VALUES('SO','Somalia');
INSERT INTO country(code,description) VALUES('KR','South Korea');
INSERT INTO country(code,description) VALUES('ES','Spain');
INSERT INTO country(code,description) VALUES('LK','Sri Lanka');
INSERT INTO country(code,description) VALUES('SD','Sudan');
INSERT INTO country(code,description) VALUES('SR','Suriname');
INSERT INTO country(code,description) VALUES('SZ','Swaziland');
INSERT INTO country(code,description) VALUES('SE','Sweden');
INSERT INTO country(code,description) VALUES('CH','Switzerland');
INSERT INTO country(code,description) VALUES('SY','Syria');
INSERT INTO country(code,description) VALUES('TW','Taiwan');
INSERT INTO country(code,description) VALUES('TJ','Tajikistan');
INSERT INTO country(code,description) VALUES('TZ','Tanzania');
INSERT INTO country(code,description) VALUES('TH','Thailand');
INSERT INTO country(code,description) VALUES('TG','Togo');
INSERT INTO country(code,description) VALUES('TO','Tonga');
INSERT INTO country(code,description) VALUES('TT','Trinidad and Tobago');
INSERT INTO country(code,description) VALUES('TN','Tunisia');
INSERT INTO country(code,description) VALUES('TR','Turkey');
INSERT INTO country(code,description) VALUES('TM','Turkmenistan');
INSERT INTO country(code,description) VALUES('TC','Turks and Caicos');
INSERT INTO country(code,description) VALUES('TV','Tuvalu');
INSERT INTO country(code,description) VALUES('UG','Uganda');
INSERT INTO country(code,description) VALUES('UA','Ukraine');
INSERT INTO country(code,description) VALUES('AE','United Arab Emirates');
INSERT INTO country(code,description) VALUES('UY','Uruguay');
INSERT INTO country(code,description) VALUES('UZ','Uzbekistan');
INSERT INTO country(code,description) VALUES('VU','Vanuatu');
INSERT INTO country(code,description) VALUES('VE','Venezuela');
INSERT INTO country(code,description) VALUES('VN','Vietnam');
INSERT INTO country(code,description) VALUES('BV','Virgin Islands (British)');
INSERT INTO country(code,description) VALUES('VI','Virgin Islands (U.S.)');
INSERT INTO country(code,description) VALUES('00','Virtual');
INSERT INTO country(code,description) VALUES('WF','Wallis and Futuna');
INSERT INTO country(code,description) VALUES('EH','Western Samoa');
INSERT INTO country(code,description) VALUES('YE','Yemen');
INSERT INTO country(code,description) VALUES('ZR','Zaire');
INSERT INTO country(code,description) VALUES('ZM','Zambia');
INSERT INTO country(code,description) VALUES('ZW','Zimbabwe');
INSERT INTO country(code,description) VALUES('US','United States');
INSERT INTO country(code,description) VALUES('NG','Nigeria');
INSERT INTO country(code,description) VALUES('AU','Australia');
INSERT INTO country(code,description) VALUES('CA','Canada');
INSERT INTO country(code,description) VALUES('NZ','New Zealand');
INSERT INTO country(code,description) VALUES('SG','Singapore');
INSERT INTO country(code,description) VALUES('ZA','South Africa');
INSERT INTO country(code,description) VALUES('GB','United Kingdom');
UPDATE country SET signup=1, status = 1 WHERE code IN ('US','CA','GB', 'NG', 'NL', 'NZ', 'ZA');
CREATE TABLE signup (
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
email VARCHAR(100) NOT NULL,
firstname VARCHAR(25) NOT NULL,
lastname VARCHAR(25) NOT NULL,
loc INET,
status INT DEFAULT 0,
added timestamp without time zone DEFAULT now(),
updated timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY signup
ADD CONSTRAINT signup_id_key UNIQUE (id);
CREATE TABLE products_contacts (
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
member_id INT REFERENCES members(id),
product_id VARCHAR(25) NOT NULL,
subscription_uid VARCHAR(100) NOT NULL,
title VARCHAR(100),
email VARCHAR(100),
sender VARCHAR(100),
message TEXT,
status INT DEFAULT 0,
added timestamp without time zone DEFAULT now(),
updated timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY products_contacts
ADD CONSTRAINT products_contacts_id_key UNIQUE (id);
logger.info(f"Process_save_contacts IN -> : {data}", exc_info=True)
message = data.get('message', '')
subscription_uid = data.get('subscription_uid', '')
title = data.get('title', '')
email = data.get('email', '')
sender = data.get('sender', '')
memSubb = MembersProducts.get_member_product_by_subscription_uid(subscription_uid)
if memSubb:
member_id = memSubb.member_id,
product_id = memSubb.product_id
if message != '' and title != '' and email != '' and sender != '':
logger.info(f"Ready to save data: {data}", exc_info=True)
merms_panel=> \d products_colorstyle
Table "public.products_colorstyle"
Column | Type | Collation | Nullable | Default
-------------+-----------------------------+-----------+----------+-------------------------------------------------
id | integer | | not null | nextval('products_colorstyle_id_seq'::regclass)
uid | uuid | | | uuid_generate_v4()
product_id | character varying(25) | | |
name | character varying(55) | | not null |
color_style | character varying(55) | | not null |
color_code | character varying(9) | | not null |
status | integer | | | 0
added | timestamp without time zone | | | now()
Indexes:
"products_colorstyle_id_key" UNIQUE CONSTRAINT, btree (id)
Foreign-key constraints:
"products_colorstyle_product_id_fkey" FOREIGN KEY (product_id) REFERENCES products(product_id)
merms_panel=>
merms_panel=>
merms_panel=>
merms_panel=>
merms_panel=>
merms_panel=>
ALTER TABLE subscription_options ADD country_code VARCHAR(3);
UPDATE subscription_options SET country_code ='US';
@@ -1459,28 +768,3 @@ UPDATE subscription_options SET country_code ='US';
merms_panel=# \d subscription_options
Table "public.subscription_options"
Column | Type | Collation | Nullable | Default
-------------------+-----------------------------+-----------+----------+--------------------------------------------------
id | integer | | not null | nextval('subscription_options_id_seq'::regclass)
uid | uuid | | | uuid_generate_v4()
display_name | character varying(25) | | not null |
option_name | character varying(100) | | not null |
monthly | integer | | | 0
status | integer | | | 1
added | timestamp without time zone | | | now()
updated | timestamp without time zone | | | now()
stripe_product_id | character varying(100) | | |
stripe_price_id | character varying(100) | | |
Indexes:
"subscription_options_display_name_key" UNIQUE CONSTRAINT, btree (display_name)
"subscription_options_id_key" UNIQUE CONSTRAINT, btree (id)
"subscription_options_option_name_key" UNIQUE CONSTRAINT, btree (option_name)
Referenced by:
TABLE "members" CONSTRAINT "members_option_name_fkey" FOREIGN KEY (option_name) REFERENCES subscription_options(option_name)
TABLE "payments" CONSTRAINT "payments_option_name_fkey" FOREIGN KEY (option_name) REFERENCES subscription_options(option_name)
TABLE "payments_session" CONSTRAINT "payments_session_option_name_fkey" FOREIGN KEY (option_name) REFERENCES subscription_options(option_name)
TABLE "subscription_options_items" CONSTRAINT "subscription_options_items_option_name_fkey" FOREIGN KEY (option_name) REFERENCES subscription_options(option_name)
+1 -4
View File
@@ -1,5 +1,2 @@
from .transaction_type import TransactionType
from .loan_status import LoanStatus
from .settings_items_data import SettingsItemsData
from .generatives_list import GenerativesList
from .kafka_messages import KafkaMessage
from .loan_status import LoanStatus
-977
View File
@@ -1,977 +0,0 @@
class CountryList:
@staticmethod
def get_signup_country_list():
return [
{
"description": "Afghanistan",
"code": "AF"
},
{
"description": "Åland Islands",
"code": "AX"
},
{
"description": "Albania",
"code": "AL"
},
{
"description": "Algeria",
"code": "DZ"
},
{
"description": "American Samoa",
"code": "AS"
},
{
"description": "AndorrA",
"code": "AD"
},
{
"description": "Angola",
"code": "AO"
},
{
"description": "Anguilla",
"code": "AI"
},
{
"description": "Antarctica",
"code": "AQ"
},
{
"description": "Antigua and Barbuda",
"code": "AG"
},
{
"description": "Argentina",
"code": "AR"
},
{
"description": "Armenia",
"code": "AM"
},
{
"description": "Aruba",
"code": "AW"
},
{
"description": "Australia",
"code": "AU"
},
{
"description": "Austria",
"code": "AT"
},
{
"description": "Azerbaijan",
"code": "AZ"
},
{
"description": "Bahamas",
"code": "BS"
},
{
"description": "Bahrain",
"code": "BH"
},
{
"description": "Bangladesh",
"code": "BD"
},
{
"description": "Barbados",
"code": "BB"
},
{
"description": "Belarus",
"code": "BY"
},
{
"description": "Belgium",
"code": "BE"
},
{
"description": "Belize",
"code": "BZ"
},
{
"description": "Benin",
"code": "BJ"
},
{
"description": "Bermuda",
"code": "BM"
},
{
"description": "Bhutan",
"code": "BT"
},
{
"description": "Bolivia",
"code": "BO"
},
{
"description": "Bosnia and Herzegovina",
"code": "BA"
},
{
"description": "Botswana",
"code": "BW"
},
{
"description": "Bouvet Island",
"code": "BV"
},
{
"description": "Brazil",
"code": "BR"
},
{
"description": "British Indian Ocean Territory",
"code": "IO"
},
{
"description": "Brunei Darussalam",
"code": "BN"
},
{
"description": "Bulgaria",
"code": "BG"
},
{
"description": "Burkina Faso",
"code": "BF"
},
{
"description": "Burundi",
"code": "BI"
},
{
"description": "Cambodia",
"code": "KH"
},
{
"description": "Cameroon",
"code": "CM"
},
{
"description": "Canada",
"code": "CA"
},
{
"description": "Cape Verde",
"code": "CV"
},
{
"description": "Cayman Islands",
"code": "KY"
},
{
"description": "Central African Republic",
"code": "CF"
},
{
"description": "Chad",
"code": "TD"
},
{
"description": "Chile",
"code": "CL"
},
{
"description": "China",
"code": "CN"
},
{
"description": "Christmas Island",
"code": "CX"
},
{
"description": "Cocos (Keeling) Islands",
"code": "CC"
},
{
"description": "Colombia",
"code": "CO"
},
{
"description": "Comoros",
"code": "KM"
},
{
"description": "Congo",
"code": "CG"
},
{
"description": "Congo, The Democratic Republic of the",
"code": "CD"
},
{
"description": "Cook Islands",
"code": "CK"
},
{
"description": "Costa Rica",
"code": "CR"
},
{
"description": "Cote D'Ivoire",
"code": "CI"
},
{
"description": "Croatia",
"code": "HR"
},
{
"description": "Cuba",
"code": "CU"
},
{
"description": "Cyprus",
"code": "CY"
},
{
"description": "Czech Republic",
"code": "CZ"
},
{
"description": "Denmark",
"code": "DK"
},
{
"description": "Djibouti",
"code": "DJ"
},
{
"description": "Dominica",
"code": "DM"
},
{
"description": "Dominican Republic",
"code": "DO"
},
{
"description": "Ecuador",
"code": "EC"
},
{
"description": "Egypt",
"code": "EG"
},
{
"description": "El Salvador",
"code": "SV"
},
{
"description": "Equatorial Guinea",
"code": "GQ"
},
{
"description": "Eritrea",
"code": "ER"
},
{
"description": "Estonia",
"code": "EE"
},
{
"description": "Ethiopia",
"code": "ET"
},
{
"description": "Falkland Islands (Malvinas)",
"code": "FK"
},
{
"description": "Faroe Islands",
"code": "FO"
},
{
"description": "Fiji",
"code": "FJ"
},
{
"description": "Finland",
"code": "FI"
},
{
"description": "France",
"code": "FR"
},
{
"description": "French Guiana",
"code": "GF"
},
{
"description": "French Polynesia",
"code": "PF"
},
{
"description": "French Southern Territories",
"code": "TF"
},
{
"description": "Gabon",
"code": "GA"
},
{
"description": "Gambia",
"code": "GM"
},
{
"description": "Georgia",
"code": "GE"
},
{
"description": "Germany",
"code": "DE"
},
{
"description": "Ghana",
"code": "GH"
},
{
"description": "Gibraltar",
"code": "GI"
},
{
"description": "Greece",
"code": "GR"
},
{
"description": "Greenland",
"code": "GL"
},
{
"description": "Grenada",
"code": "GD"
},
{
"description": "Guadeloupe",
"code": "GP"
},
{
"description": "Guam",
"code": "GU"
},
{
"description": "Guatemala",
"code": "GT"
},
{
"description": "Guernsey",
"code": "GG"
},
{
"description": "Guinea",
"code": "GN"
},
{
"description": "Guinea-Bissau",
"code": "GW"
},
{
"description": "Guyana",
"code": "GY"
},
{
"description": "Haiti",
"code": "HT"
},
{
"description": "Heard Island and Mcdonald Islands",
"code": "HM"
},
{
"description": "Holy See (Vatican City State)",
"code": "VA"
},
{
"description": "Honduras",
"code": "HN"
},
{
"description": "Hong Kong",
"code": "HK"
},
{
"description": "Hungary",
"code": "HU"
},
{
"description": "Iceland",
"code": "IS"
},
{
"description": "India",
"code": "IN"
},
{
"description": "Indonesia",
"code": "ID"
},
{
"description": "Iran, Islamic Republic Of",
"code": "IR"
},
{
"description": "Iraq",
"code": "IQ"
},
{
"description": "Ireland",
"code": "IE"
},
{
"description": "Isle of Man",
"code": "IM"
},
{
"description": "Israel",
"code": "IL"
},
{
"description": "Italy",
"code": "IT"
},
{
"description": "Jamaica",
"code": "JM"
},
{
"description": "Japan",
"code": "JP"
},
{
"description": "Jersey",
"code": "JE"
},
{
"description": "Jordan",
"code": "JO"
},
{
"description": "Kazakhstan",
"code": "KZ"
},
{
"description": "Kenya",
"code": "KE"
},
{
"description": "Kiribati",
"code": "KI"
},
{
"description": "Korea, Democratic People'S Republic of",
"code": "KP"
},
{
"description": "Korea, Republic of",
"code": "KR"
},
{
"description": "Kuwait",
"code": "KW"
},
{
"description": "Kyrgyzstan",
"code": "KG"
},
{
"description": "Lao People'S Democratic Republic",
"code": "LA"
},
{
"description": "Latvia",
"code": "LV"
},
{
"description": "Lebanon",
"code": "LB"
},
{
"description": "Lesotho",
"code": "LS"
},
{
"description": "Liberia",
"code": "LR"
},
{
"description": "Libyan Arab Jamahiriya",
"code": "LY"
},
{
"description": "Liechtenstein",
"code": "LI"
},
{
"description": "Lithuania",
"code": "LT"
},
{
"description": "Luxembourg",
"code": "LU"
},
{
"description": "Macao",
"code": "MO"
},
{
"description": "Macedonia, The Former Yugoslav Republic of",
"code": "MK"
},
{
"description": "Madagascar",
"code": "MG"
},
{
"description": "Malawi",
"code": "MW"
},
{
"description": "Malaysia",
"code": "MY"
},
{
"description": "Maldives",
"code": "MV"
},
{
"description": "Mali",
"code": "ML"
},
{
"description": "Malta",
"code": "MT"
},
{
"description": "Marshall Islands",
"code": "MH"
},
{
"description": "Martinique",
"code": "MQ"
},
{
"description": "Mauritania",
"code": "MR"
},
{
"description": "Mauritius",
"code": "MU"
},
{
"description": "Mayotte",
"code": "YT"
},
{
"description": "Mexico",
"code": "MX"
},
{
"description": "Micronesia, Federated States of",
"code": "FM"
},
{
"description": "Moldova, Republic of",
"code": "MD"
},
{
"description": "Monaco",
"code": "MC"
},
{
"description": "Mongolia",
"code": "MN"
},
{
"description": "Montserrat",
"code": "MS"
},
{
"description": "Morocco",
"code": "MA"
},
{
"description": "Mozambique",
"code": "MZ"
},
{
"description": "Myanmar",
"code": "MM"
},
{
"description": "Namibia",
"code": "NA"
},
{
"description": "Nauru",
"code": "NR"
},
{
"description": "Nepal",
"code": "NP"
},
{
"description": "Netherlands",
"code": "NL"
},
{
"description": "Netherlands Antilles",
"code": "AN"
},
{
"description": "New Caledonia",
"code": "NC"
},
{
"description": "New Zealand",
"code": "NZ"
},
{
"description": "Nicaragua",
"code": "NI"
},
{
"description": "Niger",
"code": "NE"
},
{
"description": "Nigeria",
"code": "NG"
},
{
"description": "Niue",
"code": "NU"
},
{
"description": "Norfolk Island",
"code": "NF"
},
{
"description": "Northern Mariana Islands",
"code": "MP"
},
{
"description": "Norway",
"code": "NO"
},
{
"description": "Oman",
"code": "OM"
},
{
"description": "Pakistan",
"code": "PK"
},
{
"description": "Palau",
"code": "PW"
},
{
"description": "Palestinian Territory, Occupied",
"code": "PS"
},
{
"description": "Panama",
"code": "PA"
},
{
"description": "Papua New Guinea",
"code": "PG"
},
{
"description": "Paraguay",
"code": "PY"
},
{
"description": "Peru",
"code": "PE"
},
{
"description": "Philippines",
"code": "PH"
},
{
"description": "Pitcairn",
"code": "PN"
},
{
"description": "Poland",
"code": "PL"
},
{
"description": "Portugal",
"code": "PT"
},
{
"description": "Puerto Rico",
"code": "PR"
},
{
"description": "Qatar",
"code": "QA"
},
{
"description": "Reunion",
"code": "RE"
},
{
"description": "Romania",
"code": "RO"
},
{
"description": "Russian Federation",
"code": "RU"
},
{
"description": "RWANDA",
"code": "RW"
},
{
"description": "Saint Helena",
"code": "SH"
},
{
"description": "Saint Kitts and Nevis",
"code": "KN"
},
{
"description": "Saint Lucia",
"code": "LC"
},
{
"description": "Saint Pierre and Miquelon",
"code": "PM"
},
{
"description": "Saint Vincent and the Grenadines",
"code": "VC"
},
{
"description": "Samoa",
"code": "WS"
},
{
"description": "San Marino",
"code": "SM"
},
{
"description": "Sao Tome and Principe",
"code": "ST"
},
{
"description": "Saudi Arabia",
"code": "SA"
},
{
"description": "Senegal",
"code": "SN"
},
{
"description": "Serbia and Montenegro",
"code": "CS"
},
{
"description": "Seychelles",
"code": "SC"
},
{
"description": "Sierra Leone",
"code": "SL"
},
{
"description": "Singapore",
"code": "SG"
},
{
"description": "Slovakia",
"code": "SK"
},
{
"description": "Slovenia",
"code": "SI"
},
{
"description": "Solomon Islands",
"code": "SB"
},
{
"description": "Somalia",
"code": "SO"
},
{
"description": "South Africa",
"code": "ZA"
},
{
"description": "South Georgia and the South Sandwich Islands",
"code": "GS"
},
{
"description": "Spain",
"code": "ES"
},
{
"description": "Sri Lanka",
"code": "LK"
},
{
"description": "Sudan",
"code": "SD"
},
{
"description": "Suriname",
"code": "SR"
},
{
"description": "Svalbard and Jan Mayen",
"code": "SJ"
},
{
"description": "Swaziland",
"code": "SZ"
},
{
"description": "Sweden",
"code": "SE"
},
{
"description": "Switzerland",
"code": "CH"
},
{
"description": "Syrian Arab Republic",
"code": "SY"
},
{
"description": "Taiwan, Province of China",
"code": "TW"
},
{
"description": "Tajikistan",
"code": "TJ"
},
{
"description": "Tanzania, United Republic of",
"code": "TZ"
},
{
"description": "Thailand",
"code": "TH"
},
{
"description": "Timor-Leste",
"code": "TL"
},
{
"description": "Togo",
"code": "TG"
},
{
"description": "Tokelau",
"code": "TK"
},
{
"description": "Tonga",
"code": "TO"
},
{
"description": "Trinidad and Tobago",
"code": "TT"
},
{
"description": "Tunisia",
"code": "TN"
},
{
"description": "Turkey",
"code": "TR"
},
{
"description": "Turkmenistan",
"code": "TM"
},
{
"description": "Turks and Caicos Islands",
"code": "TC"
},
{
"description": "Tuvalu",
"code": "TV"
},
{
"description": "Uganda",
"code": "UG"
},
{
"description": "Ukraine",
"code": "UA"
},
{
"description": "United Arab Emirates",
"code": "AE"
},
{
"description": "United Kingdom",
"code": "GB"
},
{
"description": "United States",
"code": "US"
},
{
"description": "United States Minor Outlying Islands",
"code": "UM"
},
{
"description": "Uruguay",
"code": "UY"
},
{
"description": "Uzbekistan",
"code": "UZ"
},
{
"description": "Vanuatu",
"code": "VU"
},
{
"description": "Venezuela",
"code": "VE"
},
{
"description": "Viet Nam",
"code": "VN"
},
{
"description": "Virgin Islands, British",
"code": "VG"
},
{
"description": "Virgin Islands, U.S.",
"code": "VI"
},
{
"description": "Wallis and Futuna",
"code": "WF"
},
{
"description": "Western Sahara",
"code": "EH"
},
{
"description": "Yemen",
"code": "YE"
},
{
"description": "Zambia",
"code": "ZM"
},
{
"description": "Zimbabwe",
"code": "ZW"
}
]
-74
View File
@@ -1,74 +0,0 @@
from app.utils.logger import logger
class GenerativesList:
@staticmethod
def get_generative_list(product_id: str):
logger.info(f"get_generative_list ****** *****: {product_id}")
data = [
{"name": 'banner_text',
"prompt": 'Write about a 30-character title text for a REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'banner_description',
"prompt": 'Write a short introduction text about 100 characters for a REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'about_title',
"prompt": 'Write about a 30-character about page title text for a REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'about_description',
"prompt": 'Write three paragraphs about a REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
]
if product_id =='A000001':
data = [
{"name": 'site_title',
"prompt": 'Write about a 15-character title text for a Personal Website for REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'site_description',
"prompt": 'Write a short introduction text about 100 characters for a Personal Website for REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'banner_text',
"prompt": 'Write about a 30-character banner text for a Personal Website for REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'banner_description',
"prompt": 'Write a short introduction text about 100 characters for a Personal Website for REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'about_title',
"prompt": 'Write about a 30-character about page title text for a Personal Website for REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'about_description',
"prompt": 'Write three paragraphs about a REPLACE_THIS for a Personal Website with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'footer_description',
"prompt": 'Write a footer text about about 30 characters for a REPLACE_THIS for a Personal Website with specialization in REPLACE_ANOTHER website.',
"active": True},
]
if product_id =='A000002':
data = [
{"name": 'site_title',
"prompt": 'Write about a 15-character title text for a Business Website for REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'site_description',
"prompt": 'Write a short introduction text about 100 characters for a Business Website for REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'banner_text',
"prompt": 'Write about a 30-character banner text for a Business Website for REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'banner_description',
"prompt": 'Write a short introduction text about 100 characters for a Business Website for REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'about_title',
"prompt": 'Write about a 30-character about page title text for a Business Website for REPLACE_THIS with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'about_description',
"prompt": 'Write three paragraphs about a REPLACE_THIS for a Business Website with specialization in REPLACE_ANOTHER website.',
"active": True},
{"name": 'footer_description',
"prompt": 'Write a footer text about about 30 characters for a REPLACE_THIS for a Business Website with specialization in REPLACE_ANOTHER website.',
"active": True},
]
return data
# Personal Website - A000001
# Business Website - A000002
-6
View File
@@ -1,6 +0,0 @@
from enum import Enum
class KafkaMessage(str, Enum):
REFRESH_PRODUCT_SETTINGS = "REFRESH_PRODUCT_SETTINGS"
FLUTTER_PAYMENT_RECEIVED = "FLUTTER_PAYMENT_RECEIVED"
SITE_TRAFFIC_DATA = "SITE_TRAFFIC_DATA"
-84
View File
@@ -1,84 +0,0 @@
from symtable import Class
class SettingsItemsData:
@staticmethod
def get_site_settings_data():
data = {
"site_title": {"name": 'Title', "controls": 'TEXT', "active": True, "list_order": 0},
"site_description": {"name": 'Description', "controls": 'TEXTAREA', "active": True, "list_order": 1},
"site_logo_text": {"name": 'Logo Text', "controls": 'TEXT', "active": True, "list_order": 2,
"extra": {"maxlength": 25}},
"site_contact_email": {"name": 'Email', "controls": 'TEXT', "active": True, "list_order": 3},
"site_contact_phone": {"name": 'Phone', "controls": 'TEXT', "active": True, "list_order": 4},
}
return data
@staticmethod
def get_site_social_settings_data():
data = {
"facebook": {"name": 'Facebook', "controls": 'TEXT', "active": True, "list_order": 0},
"twitter": {"name": 'Twitter', "controls": 'TEXT', "active": True, "list_order": 1},
"youtube": {"name": 'Youtube', "controls": 'TEXT', "active": True, "list_order": 2},
}
return data
@staticmethod
def get_site_home_settings():
data = {
"banner_text": {"name": 'Banner Text', "controls": 'TEXT', "active": True, "list_order": 0},
"banner_description": {"name": 'Banner Description', "controls": 'TEXTAREA', "active": True,
"list_order": 1},
}
return data
@staticmethod
def get_site_footer_settings():
data = {
"footer_description": {"name": 'Footer Description', "controls": 'TEXTAREA', "active": True,
"list_order": 0},
"boolean_footer_show_email": {"name": 'Show email in footer', "controls": 'SELECT_NO_YES', "active": True,
"list_order": 1},
"boolean_footer_show_made_by": {"name": 'Show made by in footer', "controls": 'SELECT_NO_YES',
"active": True, "list_order": 2},
"boolean_footer_show_socials": {"name": 'Show social in footer', "controls": 'SELECT_NO_YES',
"active": True, "list_order": 3},
}
return data
@staticmethod
def get_site_testimonial_settings():
data = {
"boolean_testimonial_show": {"name": 'Show testimonial section', "controls": 'SELECT_NO_YES',
"active": True, "list_order": 0},
"testimonial_description": {"name": 'Description', "controls": 'TEXT', "active": True, "list_order": 1},
}
return data
@staticmethod
def get_site_about_items():
data = {
"about_title": {"name": 'About Title', "controls": 'TEXT', "active": True, "list_order": 0},
"about_description": {"name": 'About Details', "controls": 'TEXTAREA', "active": True, "list_order": 1},
"about_extra_1": {"name": 'Extra About us', "controls": 'TEXTAREA', "active": True, "list_order": 2},
"about_extra_2": {"name": 'More About us', "controls": 'TEXTAREA', "active": True, "list_order": 3},
}
return data
@staticmethod
def get_site_contact_items():
data = {
"contact_title": {"name": 'Contact Title', "controls": 'TEXT', "active": True, "list_order": 0},
"contact_introduction": {"name": 'Extra Introduction', "controls": 'TEXTAREA', "active": True,
"list_order": 1},
}
return data
@staticmethod
def get_site_blog_connect_settings():
data = {
"boolean_blog_connect_show": {"name": 'Show Blog Section', "controls": 'SELECT_NO_YES',
"active": True, "list_order": 0},
}
return data
+1 -2
View File
@@ -1,3 +1,2 @@
from .kafka import KafkaIntegration
from .merms_stripe import StripeIntegration
from .generative_engine import GenerativeEngineIntegration
from .merms_stripe import StripeIntegration
-43
View File
@@ -1,43 +0,0 @@
import stripe
import json
import logging
from app.config import settings, Config
# import openai
from flask import jsonify
from openai import OpenAI
logger = logging.getLogger(__name__)
class GenerativeEngineIntegration:
OPENAI_API_KEY = Config.OPENAI_API_KEY
@staticmethod
def ask_generative(generative_prompt):
try:
# response = GenerativeEngine.openai.chat.completions.create(
# model="gpt-3.5-turbo", # Or other suitable model
# messages=[{"role": "user", "content": generative_prompt}]
# )
client = OpenAI(api_key=GenerativeEngineIntegration.OPENAI_API_KEY)
response = client.responses.create(
model="gpt-4.1",
input=generative_prompt
)
# input = "Tell me a three sentence bedtime story about a unicorn."
# logger.info(response)
json_response = json.loads(response.json())
# json_response = response.json()
# logger.info(json_response.keys())
# logger.info(json_response)
# logger.info(json_response["output"])
# logger.info(json_response["output"][0])
# logger.info(json_response["output"][0]["content"][0]["text"])
# chatgpt_response = response.choices[0].message.content
return json_response
except Exception as e:
logger.error(f"ChatGpt Call Error {e}")
return None
+6 -20
View File
@@ -1,37 +1,23 @@
import stripe
import json
import logging
from app.config import settings, Config
from app.config import settings
logger = logging.getLogger(__name__)
stripe.api_key = settings.STRIPE_PRIV_KEY
class StripeIntegration:
STRIPE_SUCCESS_URL = Config.STRIPE_SUCCESS_URL
STRIPE_CANCEL_URL= Config.STRIPE_CANCEL_URL
@staticmethod
def transction_hx(limit=30):
logger.info(f"Inside Stripe_Transaction Hx ===== :")
invoice_items = stripe.InvoiceItem.list(limit)
return invoice_items
@staticmethod
def create_customer(stripe_customer):
logger.info(f"Inside Stripe_Customer ===== : {stripe_customer}")
# customer = stripe.Customer.create(
# email= stripe_customer["email"],
# name=stripe_customer["name"],
# payment_method="pm_card_visa",
# description="Customer for Merms Subscription",
# invoice_settings={"default_payment_method": "pm_card_visa"},
# )
#
customer = stripe.Customer.create(
email= stripe_customer["email"],
name=stripe_customer["name"],
description="Customer for MERMS Subscription",
payment_method="pm_card_visa",
description="Customer for Merms Subscription",
invoice_settings={"default_payment_method": "pm_card_visa"},
)
# payment_method="pm_card_visa", # Replace with a valid payment method ID or attach one later
return customer
@@ -72,8 +58,8 @@ class StripeIntegration:
},
],
mode='subscription',
success_url= StripeIntegration.STRIPE_SUCCESS_URL,
cancel_url=StripeIntegration.STRIPE_CANCEL_URL,
success_url='https://qa-panel.mermsemr.com/subscription-success?session_id={CHECKOUT_SESSION_ID}',
cancel_url='https://qa-panel.mermsemr.com/subscription',
)
return checkout_session
except stripe.error.StripeError as e:
+847 -595
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -3,4 +3,3 @@ from marshmallow import Schema, fields
class LoginSchema(Schema):
username = fields.Str(required=True)
password = fields.Str(required=True)
turnstileToken = fields.Str(required=False)
@@ -1,8 +0,0 @@
from marshmallow import Schema, fields
class MyProductExternalUrlSchema(Schema):
token = fields.Str(required=True)
uid = fields.Str(required=True)
subscription_uid = fields.Str(required=True)
external_url = fields.Str(required=True)
@@ -1,8 +0,0 @@
from marshmallow import Schema, fields
class MyProductSetColorStyleSchema(Schema):
token = fields.Str(required=True)
uid = fields.Str(required=True)
product_id = fields.Str(required=True)
color_style_uid = fields.Str(required=True)
@@ -1,8 +0,0 @@
from marshmallow import Schema, fields
class MyProductSetTemplateSchema(Schema):
token = fields.Str(required=True)
uid = fields.Str(required=True)
product_id = fields.Str(required=True)
template_uid = fields.Str(required=True)
@@ -1,8 +0,0 @@
from marshmallow import Schema, fields
class MyProductTemplateImageSchema(Schema):
token = fields.Str(required=True)
uid = fields.Str(required=True)
product_id = fields.Str(required=True)
file_uid = fields.Str(required=True)
image_id = fields.Str(required=True)
-11
View File
@@ -1,11 +0,0 @@
from marshmallow import Schema, fields
class OfficeMemberDataSchema(Schema):
member_uid = fields.Str(required=True)
member_account_name = fields.Str(required=True)
member_firstname = fields.Str(required=True)
member_full_address = fields.Str(required=True)
member_lastname = fields.Str(required=True)
member_email = fields.Str(required=True)
member_phone = fields.Str(required=True)
-6
View File
@@ -1,6 +0,0 @@
from marshmallow import Schema, fields
class ProfileLinksSchema(Schema):
token = fields.Str(required=True)
uid = fields.Str(required=True)
# url_list = fields.Str( required=False)
-2
View File
@@ -4,8 +4,6 @@ class RegisterSchema(Schema):
email = fields.Str(required=True)
firstname = fields.Str(required=True)
lastname = fields.Str(required=True)
turnstileToken = fields.Str(required=False)
# isChecked = fields.Int(required=False)
-6
View File
@@ -1,6 +0,0 @@
from marshmallow import Schema, fields
class ReportSchema(Schema):
token = fields.Str(required=True)
uid = fields.Str(required=True)
page = fields.Int(required=True)
-1
View File
@@ -2,4 +2,3 @@ from marshmallow import Schema, fields
class ResetPassStart(Schema):
username = fields.Str(required=True)
turnstileToken = fields.Str(required=False)
+1 -2
View File
@@ -5,5 +5,4 @@ class StartProfileSchema(Schema):
uid = fields.Str(required=True)
practice =fields.Str(required=True)
specialization =fields.Str(required=True)
introduction = fields.Str(required=True)
url_name = fields.Str(required=True)
introduction = fields.Str(required=True)
-11
View File
@@ -1,11 +0,0 @@
from marshmallow import Schema, fields
class UserUpdateSchema(Schema):
token = fields.Str(required=True)
uid = fields.Str(required=True)
account_name = fields.Str(account_name=False)
firstname = fields.Str(required=True)
lastname = fields.Str(required=True)
# email =fields.Str(required=True)
full_address = fields.Str(required=False)
phone = fields.Str(required=False)
+2 -12
View File
@@ -7,22 +7,12 @@ from app.api.services.myproduct import MyProductsService
from app.api.services.contacts import ContactService
from app.api.services.office_auth import OfficeAuthService
from app.api.services.web_contents import WebContentsService
from app.api.services.subscriptions import SubscriptionsService
from app.api.services.subscription import SubscriptionService
from app.api.services.common_data import CommonDataService
from app.api.services.genaratives import GenerativesService
from app.api.services.comments import CommentsService
from app.api.services.file_upload import FileUploadService
from app.api.services.reports import ReportService
from app.api.services.automation_calls import AutomationCalls
#WEBSITE
from app.api.services.website import WebsiteService
# OFFICE
from app.api.services.office_customer import OfficeCustomerService
from app.api.services.office_dashboard import OfficeDashboardService
from app.api.services.office_users import OfficeUsersService
from app.api.services.office_templates import OfficeTemplatesService
from app.api.services.office_country import OfficeCountryService
+52 -405
View File
@@ -1,18 +1,18 @@
from app.api.schemas.user_update import UserUpdateSchema
from flask import session, jsonify
# 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.extensions import db
from app.models import Members, MembersActions, MembersProfile, Payments, MembersProducts, ProvisionActions, \
ProductsContacts
from app.models import Members, MembersActions, MembersProfile
# 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
from app.api.schemas.start_profile import StartProfileSchema
from app.api.schemas.profile_links import ProfileLinksSchema
# from sendgrid import SendGridAPIClient
# from sendgrid.helpers.mail import Mail
import datetime
import jwt
@@ -20,15 +20,7 @@ import random
from app.config import Config
from app.notifications.mail_factory import send_email_factory
class AccountService(BaseService):
JWT_SECRET_KEY = Config.JWT_SECRET_KEY
SEND_EMAIL_FROM = Config.SEND_EMAIL_FROM
SEND_EMAIL_PASS = Config.SEND_EMAIL_PASS
THIS_SITE_URL = Config.THIS_SITE_URL
@staticmethod
def process_bar_request(data):
@@ -36,81 +28,17 @@ class AccountService(BaseService):
"last_update": datetime.datetime.utcnow(),
"top_bar": [
{"id": "1", "description": "Contacts", "last_update": "10-10-2010 11:00 AM",
"value": random.randint(0, 10), "data_span": 'Last 2 months', "link": "#", "extra_style": ''},
"value": random.randint(0, 10), "data_span": 'Last 2 months',"link":"#", "extra_style" : ''},
{"id": "2", "description": "Site Traffic", "last_update": "10-10-2010 11:30 AM",
"value": random.randint(0, 10), "data_span": 'Past 12 hours', "link": "#", "extra_style": ''},
"value": random.randint(0, 10), "data_span": 'Past 12 hours',"link":"#", "extra_style" : ''},
{"id": "3", "description": "Appointments", "last_update": "10-12-2010 11:30 AM",
"value": random.randint(0, 10), "data_span": 'Last 14 days', "link": "#", "extra_style": ''},
"value": random.randint(0, 10), "data_span": 'Last 14 days',"link":"#", "extra_style" : ''},
{"id": "4", "description": "Upgrade Account", "last_update": "10-12-2010 11:30 AM",
"value": "Free Trial", "data_span": 'End: 10/10/2025', "link": "/subscription",
"extra_style": " billing "}
]
"value": "Free Trial", "data_span": 'End: 10/10/2025',"link":"/subscription", "extra_style" : " billing "}
]
}
return ResponseHelper.success(data=bar_data)
@staticmethod
def process_bar_data(data):
try:
with db.session.begin():
validated_data = AccountService.validate_data(data, UserSchema())
user_token = validated_data.get('token')
uid = str(validated_data.get('uid'))
member_data = Members.get_member_by_uid(uid)
logger.error(f"Member_Data ID ::: {member_data.id}")
member_id = member_data.id
option_name = member_data.option_name # "Free Trial"
if option_name is not None and option_name != "":
next_bill = f"Bill: {member_data.next_billing}"
view_sub = "Account"
bill_style = " next_billing "
else:
option_name = "Free Trial"
next_bill = f"Ends: {member_data.trial_end}"
view_sub = "Upgrade Account"
bill_style = " billing "
# int(member_data.id)
contacts_count = ProductsContacts.get_member_contact_count(member_id,90)
# contacts_count = 0 # random.randint(0, 10)
appointments_count = 0
site_traffic_count = 0
bar_data = {
"last_update": datetime.datetime.utcnow(),
"top_bar": [
{"id": "1", "description": "Contacts", "last_update": "10-10-2010 11:00 AM",
"value": contacts_count, "data_span": 'Last 2 months', "link": "/contacts", "extra_style": ''},
{"id": "2", "description": "Appointments", "last_update": "10-12-2010 11:30 AM",
"value": appointments_count, "data_span": 'Last 14 days', "link": "/appointments",
"extra_style": ''},
{"id": "3", "description": "Site Traffic", "last_update": "10-10-2010 11:30 AM",
"value": site_traffic_count, "data_span": 'Past 12 hours', "link": "/traffic",
"extra_style": ''},
{"id": "4", "description": view_sub, "last_update": "10-12-2010 11:30 AM",
"value": option_name, "data_span": next_bill, "link": "/subscription",
"extra_style": bill_style}
]
}
return ResponseHelper.success(data=bar_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()
def process_action_request(data):
@@ -124,20 +52,21 @@ class AccountService(BaseService):
member_actions = MembersActions.get_recent_member_actions(member_data.id)
member_actions_data = []
if member_actions:
for t in member_actions:
member_actions_data.append({
'id': t.id,
'uid': t.uid,
'member_id': t.member_id,
'member_uid': t.member_uid,
'action_label': t.action_label,
'action_name': t.action_name,
'status_description': t.status_description,
'status': t.status,
'added': t.added,
'updated': t.updated
})
for t in member_actions:
member_actions_data.append({
'id': t.id,
'uid': t.uid,
'member_id': t.member_id,
'member_uid': t.member_uid,
'action_label': t.action_label,
'action_name': t.action_name,
'status_description': t.status_description,
'status': t.status,
'added': t.added,
'updated': t.updated
})
action_data = {
"recent_actions": member_actions_data,
@@ -168,6 +97,8 @@ class AccountService(BaseService):
db.session.rollback()
return ResponseHelper.internal_server_error()
@staticmethod
def process_request(data):
try:
@@ -182,15 +113,14 @@ class AccountService(BaseService):
# Simulate processing
response_data = {
"member_id": member.id,
"uid": str(uid),
"uid": str(uid),
"username": member.username,
"account_name": member.account_name,
"profile_completed": member.profile_completed,
"firstname": member.firstname,
"firstname":member.firstname,
"lastname": member.lastname,
"email": member.email,
"room": member.uid,
"picture": 'https://media.mermsemr.com/media/show/merms-profile',
"room": member.uid,
"token": user_token
}
@@ -212,6 +142,7 @@ class AccountService(BaseService):
db.session.rollback()
return ResponseHelper.internal_server_error()
@staticmethod
def process_startprofile(data):
try:
@@ -223,17 +154,6 @@ class AccountService(BaseService):
practice = str(validated_data.get('practice'))
specialization = str(validated_data.get('specialization'))
introduction = str(validated_data.get('introduction'))
url_name = str(validated_data.get('url_name'))
# verify is anybody is using this url name
urlNammeData = MembersProfile.get_any_member_profile_by_url_name(url_name)
if urlNammeData:
return {
"error": 'Duplicate url name',
"error_message": 'Try another url name',
"url_name": url_name,
}, 400
profile_uid = ''
profile_completed = None
member = Members.get_member_by_uid(uid)
@@ -241,27 +161,24 @@ class AccountService(BaseService):
# Simulate processing
member_data = {
"member_id": member.id,
"uid": str(uid),
"uid": str(uid),
"username": member.username,
"account_name": member.account_name,
"firstname": member.firstname,
"firstname":member.firstname,
"lastname": member.lastname,
"email": member.email,
"room": member.uid,
"room": member.uid,
"token": user_token
}
current_profile = MembersProfile.get_member_profile_by_member_id(member.id)
if current_profile is not None:
profile_uid = current_profile.uid
profile_uid=current_profile.uid
profile_completed = member.profile_completed
else:
profile_result = MembersProfile.create_member_profile(member.id, practice, specialization,
introduction, url_name)
if profile_result:
profile_uid = profile_result.uid
current_profile = MembersProfile.get_member_profile_by_member_id(member.id)
if profile_uid is not None and profile_uid != '' and current_profile is not None:
profle_result = MembersProfile.create_member_profile(member.id, practice, specialization, introduction)
if profle_result:
profile_uid = profle_result.uid
if profile_uid is not None and profile_uid != '':
profile_completed = Members.set_member_profile_completed(member_data['uid'])
result_data = {
@@ -288,6 +205,7 @@ class AccountService(BaseService):
db.session.rollback()
return ResponseHelper.internal_server_error()
@staticmethod
def process_calendar(data):
try:
@@ -297,42 +215,15 @@ class AccountService(BaseService):
user_token = validated_data.get('token')
uid = str(validated_data.get('uid'))
member = Members.get_member_by_uid(uid)
if not member:
return {
"error": 'Invalid Request',
"uid": uid,
}, 400
member_id = member.id
dList = []
# LET get the ptovison actions
prov_actions = ProvisionActions.get_provision_action_calendar_member_id(member_id=member_id, limit=100)
if prov_actions:
for prov_action in prov_actions:
new_l = {"uid": prov_action.uid,
"title": prov_action.action, "start": prov_action.added,
"category": 3}
dList.append(new_l)
member_actions = MembersActions.get_recent_member_calendar_actions_member_id(member_id=member_id,
limit=100)
if member_actions:
for member_action in member_actions:
new_l = {"uid": member_action.uid,
"title": member_action.action_label, "start": member_action.added,
"category": 1}
dList.append(new_l)
# sample_range = random.randint(20, 60)
# for x in range(sample_range):
# timeMin = random.randint(1440, 2880)
# calDate = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeMin * random.randint(0, 20))
# new_l = {"uid": "425611f2-c692-4404-b93d-76ca7a5ce7" + str(x),
# "title": "Calendar Random Item on " + str(x), "start": calDate,
# "category": random.randint(1, 4)}
# dList.append(new_l)
sample_range = random.randint(20, 60)
for x in range(sample_range):
timeMin = random.randint(1440, 2880)
calDate = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeMin * random.randint(0, 20))
new_l = {"uid": "425611f2-c692-4404-b93d-76ca7a5ce7" + str(x),
"title": "Calendar Random Item on " + str(x), "start": calDate,
"category": random.randint(1, 4)}
dList.append(new_l)
calendar_data = {
"last_update": datetime.datetime.utcnow(),
@@ -373,248 +264,4 @@ class AccountService(BaseService):
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
db.session.rollback()
return ResponseHelper.internal_server_error()
@staticmethod
def process_payments_data(data):
try:
with db.session.begin():
validated_data = AccountService.validate_data(data, UserSchema())
user_token = validated_data.get('token')
uid = str(validated_data.get('uid'))
member_data = Members.get_member_by_uid(uid)
member_payments = Payments.get_member_payments_by_member_id(member_data.id)
member_payments_data = []
for t in member_payments:
member_payments_data.append({
'id': t.id,
'uid': t.uid,
'option_name': t.option_name,
'option_type': t.option_type,
'payment_uid': t.payment_uid,
'amount': round(t.amount * 0.01, 2),
'status': t.status,
'added': t.added
})
action_data = {
"member_payments": member_payments_data,
"last_update": datetime.datetime.utcnow(),
}
# logger.info(f"Member Actions : {action_data}")
return ResponseHelper.success(data=action_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()
@staticmethod
def process_profile_data(data):
try:
with db.session.begin():
validated_data = AccountService.validate_data(data, UserSchema())
user_token = validated_data.get('token')
uid = str(validated_data.get('uid'))
member_data = Members.get_member_by_uid(uid)
file_url = BaseService.get_profile_picture_url(member_data.profile_picture)
personal_data = {
"firstname": member_data.firstname,
"lastname": member_data.lastname,
"account_name": member_data.account_name,
"email": member_data.email,
"phone": member_data.phone,
"full_address": member_data.full_address,
"picture": 'https://media.mermsemr.com/media/show/merms-profile' if file_url == '' else file_url,
"country": member_data.country,
}
external_links = {
"facebook_url": "facebook.com",
"twitter_url": "twitter.com",
"blogger_url": "blogger.com",
"google_url": "google.com",
"linked_url": "linkedin.com",
"website_url": "www.mysite.com",
}
profile_data = {
"personal_data": personal_data,
"external_links": external_links,
}
return ResponseHelper.success(data=profile_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()
@staticmethod
def update_profile_data(data):
try:
with db.session.begin():
validated_data = AccountService.validate_data(data, UserUpdateSchema())
user_token = validated_data.get('token')
uid = str(validated_data.get('uid'))
member_data = Members.get_member_by_uid(uid)
if member_data:
firstname = str(validated_data.get('firstname'))
lastname = str(validated_data.get('lastname'))
account_name = str(validated_data.get('account_name'))
phone = str(validated_data.get('phone'))
full_address = str(validated_data.get('full_address'))
# email = str(validated_data.get('email'))
profile_data = {
"firstname": firstname,
"lastname": lastname,
"account_name": account_name,
"phone": phone,
"full_address": full_address,
# "email": email,
}
Members.set_member_update_profile(uid, profile_data)
# Read the saved data
member_data = Members.get_member_by_uid(uid)
personal_data = {
"firstname": member_data.firstname,
"lastname": member_data.lastname,
"account_name": member_data.account_name,
"email": member_data.email,
"phone": member_data.phone,
"full_address": member_data.full_address,
"country": member_data.country,
}
external_links = {
"facebook_url": "facebook.com",
"twitter_url": "twitter.com",
"blogger_url": "blogger.com",
"google_url": "google.com",
"linked_url": "linkedin.com",
"website_url": "www.mysite.com",
}
profile_data = {
"personal_data": personal_data,
"external_links": external_links,
}
return ResponseHelper.success(data=profile_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()
@staticmethod
def update_profile_link_data(data):
try:
with db.session.begin():
url_list = data["url_list"]
data.pop("url_list")
validated_data = AccountService.validate_data(data, ProfileLinksSchema())
user_token = validated_data.get('token')
uid = str(validated_data.get('uid'))
member_data = Members.get_member_by_uid(uid)
if member_data:
for key in url_list.keys():
url_list_value = url_list[key]
logger.info(f"URL LIST : {key} : {url_list_value}")
external_links = {
"facebook_url": "https://facebook.com",
"twitter_url": "twitter.com",
"blogger_url": "blogger.com",
"google_url": "google.com",
"linked_url": "linkedin.com",
"website_url": "www.mysite.com",
}
profile_data = {
"external_links": external_links,
}
return ResponseHelper.success(data=profile_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()
@staticmethod
def process_test_email(data):
logger.info(f"Email Test Enter 001", exc_info=True)
send_email_factory(
to_email="ameye@chiefsoft.com",
subject="Test from Merms",
html_content="<strong>Hello from AWS SES</strong>"
)
logger.info(f"Email Test", exc_info=True)
return ResponseHelper.internal_server_error()
-67
View File
@@ -1,67 +0,0 @@
from flask import session, jsonify
from app.api.schemas.user_update import UserUpdateSchema
# 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.extensions import db
from app.models import Members, MembersActions, MembersProfile, Payments, MembersProducts, ProvisionActions
# 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
from app.api.schemas.start_profile import StartProfileSchema
from app.api.schemas.profile_links import ProfileLinksSchema
from app.api.integrations import StripeIntegration
from flask_mail import Mail, Message
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import datetime
import jwt
import random
from app.config import Config
import smtplib, ssl
from email.message import EmailMessage
class AutomationCalls(BaseService):
JWT_SECRET_KEY = Config.JWT_SECRET_KEY
SEND_EMAIL_FROM = Config.SEND_EMAIL_FROM
SEND_EMAIL_PASS = Config.SEND_EMAIL_PASS
THIS_SITE_URL = Config.THIS_SITE_URL
@staticmethod
def process_stripe_payment_refresh(data):
stripe_transactions = StripeIntegration.transction_hx()
print(stripe_transactions)
logger.info(f"Return Stripe_Transaction Hx ===== : {stripe_transactions}")
bar_data = {
"last_update": datetime.datetime.utcnow(),
"top_bar": [
{"id": "1", "description": "Contacts", "last_update": "10-10-2010 11:00 AM",
"value": random.randint(0, 10), "data_span": 'Last 2 months', "link": "#", "extra_style": ''},
{"id": "2", "description": "Site Traffic", "last_update": "10-10-2010 11:30 AM",
"value": random.randint(0, 10), "data_span": 'Past 12 hours', "link": "#", "extra_style": ''},
{"id": "3", "description": "Appointments", "last_update": "10-12-2010 11:30 AM",
"value": random.randint(0, 10), "data_span": 'Last 14 days', "link": "#", "extra_style": ''},
{"id": "4", "description": "Upgrade Account", "last_update": "10-12-2010 11:30 AM",
"value": "Free Trial", "data_span": 'End: 10/10/2025', "link": "/subscription",
"extra_style": " billing "}
]
}
return ResponseHelper.success(data=bar_data)
+214 -235
View File
@@ -1,18 +1,18 @@
# from app.models import Customer, Account, Transaction
from app.api.enums import TransactionType
from flask import jsonify
from marshmallow import ValidationError
import logging
from app.api.integrations import KafkaIntegration
from app.config import Config
from app.models import MembersWebfiles
logger = logging.getLogger(__name__)
from app.api.integrations import StripeIntegration
from flask_mail import Mail, Message
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import datetime
import jwt
import requests
import redis
import json
from app.notifications.mail_factory import send_email_factory
class BaseService:
TRANSACTION_TYPE = None
@@ -22,25 +22,6 @@ class BaseService:
SEND_EMAIL_PASS = Config.SEND_EMAIL_PASS
THIS_SITE_URL = Config.THIS_SITE_URL
CACHE_SERVER = Config.CACHE_SERVER
CACHE_PORT = Config.CACHE_PORT
CACHE_PASSWORD = Config.CACHE_PASSWORD
CACHE_DEFAULT_EXPIRE = Config.CACHE_DEFAULT_EXPIRE
MEDIA_SERVER = Config.MEDIA_SERVER
@staticmethod
def get_profile_picture_url(profile_uid):
file_url = ''
if profile_uid is None or profile_uid == '':
return file_url
selectedFile = MembersWebfiles.get_member_webfiles_by_file_uid(profile_uid)
if selectedFile:
file_url = (
BaseService.MEDIA_SERVER + "/" + selectedFile.file_group + "/" + str(
selectedFile.uid) + "/" + selectedFile.filename).lower()
return file_url
@staticmethod
def addStripeCustomer(customerData):
customer_data = {
@@ -51,64 +32,46 @@ class BaseService:
logger.info(f"Stripe_Customer ===== : {stripe_customer}")
return stripe_customer
@staticmethod
def send_completepass_mail(signup_email, pending_uid, pending_id, firstname, lastname):
msg_body = f"""
Hello {firstname},
# html_body = f"""\
# <html>
# <head></head>
# <body style="font-size:14px;line-height:1.5;">
# <table width="550px" border="0" cellpadding="3" cellspacing="3" background-color="#F0F8FF" style="font-size:16px">
# <tr>
# <td style="text-align:center">
# <img style="width:150px; height:auto;" src="mermsemr.com/images/logo-pink.png" />
# </td>
# </tr>
# <tr>
# <td>
# Hello <b>{firstname}!</b>
# </td>
# </tr>
# <tr>
# <td>
# Password Reset Completed<br>
# </td>
# </tr>
#
# <tr>
# <td>
# For any support<br>
# Reach Out<br>
# support@mermsemr.com<br>
# https://www.mermsemr.com/
# </td>
# </tr>
# </table>
# </body>
# </html>
# """
html_body = f"""
<table width="550px" border="0" cellpadding="3" cellspacing="3" background-color="#F0F8FF" style="font-size:16px">
<tr>
<td>
Hello <b>{firstname}!</b>
</td>
</tr>
<tr>
<td>
Password Reset Completed<br>
</td>
</tr>
</table>
"""
Password Reset Completed
For any Support
Reach Out
support@mermsemr.com
"""
sender_email = BaseService.SEND_EMAIL_FROM
sender_password = BaseService.SEND_EMAIL_PASS
receiver_email = signup_email
subject = "Reset Password Completed"
body = msg_body
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = sender_email
msg['To'] = receiver_email
msg.attach(MIMEText(body, 'plain')) # or 'html' for HTML content
try:
# For Gmail, use 'smtp.gmail.com' and port 587 (TLS) or 465 (SSL)
# For other providers, consult their documentation for SMTP server and port
server = smtplib.SMTP('smtp.gmail.com', 587)
# server.starttls() # Enable TLS encryption
server.login(sender_email, sender_password)
server.sendmail(sender_email, receiver_email, msg.as_string())
print("Email sent successfully!")
except Exception as e:
print(f"Error sending email: {e}")
logger.error(f"Error sending email: {e}")
finally:
server.quit() # Close the connection
send_email_factory(
to_email=receiver_email,
subject=subject,
html_content=html_body
)
@staticmethod
def send_resetpass_mail(signup_email, pending_uid, pending_id, firstname, lastname):
@@ -127,115 +90,46 @@ class BaseService:
{"user": pending_member, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=3330)},
BaseService.JWT_SECRET_KEY, algorithm='HS256'
)
panel_url = BaseService.THIS_SITE_URL # "https://qa-panel.mermsemr.com"
panel_url = BaseService.THIS_SITE_URL #"https://qa-panel.mermsemr.com"
link_url = str(panel_url) + '/accreset/' + jwt_part
# html_body = f"""\
# <html>
# <head></head>
# <body style="font-size:14px;line-height:1.5;">
# <table width="550px" border="0" cellpadding="3" cellspacing="3" background-color="#F0F8FF" style="font-size:16px">
# <tr>
# <td style="text-align:center">
# <img style="width:150px; height:auto;" src="mermsemr.com/images/logo-pink.png" />
# </td>
# </tr>
# <tr>
# <td>
# Hello <b>{firstname}!</b>
# </td>
# </tr>
# <tr>
# <td>
# You received this message for account reset password<br>
# </td>
# </tr>
# <tr>
# <td>
# Follow the link: <a href="{link_url}">link</a> to reset your password.<br>
# </td>
# </tr>
# <tr>
# <td>
# For any support<br>
# Reach Out<br>
# support@mermsemr.com<br>
# https://www.mermsemr.com/
# </td>
# </tr>
# </table>
# </body>
# </html>
# """
msg_body = f"""
Hello {firstname},
html_body = f"""\
<table width="550px" border="0" cellpadding="3" cellspacing="3" background-color="#F0F8FF" style="font-size:16px">
<tr>
<td>
Hello <b>{firstname}!</b>
</td>
</tr>
<tr>
<td>
You received this message for account reset password<br>
</td>
</tr>
<tr>
<td>
Follow the link: <a href="{link_url}">link</a> to reset your password.<br>
</td>
</tr>
</table>
"""
You received this message for account reset password
Follow the link:{link_url}
For any Support
Reach Out
support@mermsemr.com
"""
sender_email = BaseService.SEND_EMAIL_FROM
sender_password = BaseService.SEND_EMAIL_PASS
receiver_email = signup_email
subject = "Reset Password Email"
body = msg_body
send_email_factory(
to_email=receiver_email,
subject=subject,
html_content=html_body
)
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = sender_email
msg['To'] = receiver_email
msg.attach(MIMEText(body, 'plain')) # or 'html' for HTML content
def send_verify_signup_mail(signup_email, pending_uid, pending_id, firstname, lastname):
pending_member = {
"email": signup_email,
"pending_uid": pending_uid,
"first_name": firstname,
"last_name": lastname,
"pending_id": pending_id,
}
jwt_part = jwt.encode(
{"user": pending_member, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=3330)},
BaseService.JWT_SECRET_KEY, algorithm='HS256'
)
panel_url = BaseService.THIS_SITE_URL # "https://qa-panel.mermsemr.com"
link_url = str(panel_url) + '/csignup/' + jwt_part
receiver_email = signup_email
subject = "Verify your MERMS(AI) Account Setup"
html_body = f"""\
<div style="font-weight: 700; font-size: 18px; margin-bottom: 16px;">
Hello <b>{firstname}!</b>,
</div>
<p style="margin: 0 0 16px 0;">
You have received this message for your account verification.
</p>
<p style="margin: 0 0 24px 0;">
Follow the link: <a href="{link_url}">link</a> to complete the verification process.
</p>
"""
send_email_factory(
to_email=receiver_email,
subject=subject,
html_content=html_body
)
try:
# For Gmail, use 'smtp.gmail.com' and port 587 (TLS) or 465 (SSL)
# For other providers, consult their documentation for SMTP server and port
server = smtplib.SMTP('smtp.gmail.com', 587)
# server.starttls() # Enable TLS encryption
server.login(sender_email, sender_password)
server.sendmail(sender_email, receiver_email, msg.as_string())
print("Email sent successfully!")
except Exception as e:
print(f"Error sending email: {e}")
logger.error(f"Error sending email: {e}")
finally:
server.quit() # Close the connection
@classmethod
@@ -246,79 +140,164 @@ class BaseService:
logger.info(f"Processing {cls.TRANSACTION_TYPE} request")
return schema.load(data)
@classmethod
def get_or_create_customer(cls, validated_data):
"""
Check if a customer exists; if not, create one.
"""
customer = Customer.query.filter_by(id=validated_data.get("customerId")).first()
if not customer:
customer = Customer.create_customer(
id=validated_data.get("customerId"),
msisdn=validated_data.get("msisdn"),
country_code=validated_data.get("countryCode"),
account_id=validated_data.get("accountId"),
)
return customer
@classmethod
def validate_account_ownership(cls, account_id, customer_id):
"""
Check if the provided account belongs to the customer.
"""
is_valid = Account.is_valid_account(account_id, customer_id)
return is_valid
@classmethod
def log_transaction(cls, validated_data):
"""
Create a new transaction.
"""
channel = "USSD" if validated_data.get("channel") is None else validated_data.get("channel")
return Transaction.create_transaction(
transaction_id = validated_data.get("transactionId"),
customer_id = validated_data.get('customerId', None),
account_id = validated_data.get("accountId", None),
type = cls.TRANSACTION_TYPE,
channel = channel,
)
@classmethod
def async_send_settings_refresh_to_kafka(cls, settings_data, subscription_uid, topic):
KafkaIntegration.send_setting_refresh_request(settings_data=settings_data, subscription_uid=subscription_uid,
topic=topic)
KafkaIntegration.send_setting_refresh_request(settings_data = settings_data, subscription_uid =subscription_uid, topic = topic)
KafkaIntegration.flush()
@classmethod
def async_send_to_kafka(cls, loan_data, request_id, topic):
KafkaIntegration.send_loan_request(loan_data=loan_data, request_id=request_id, topic=topic)
KafkaIntegration.send_loan_request(loan_data = loan_data, request_id = request_id, topic = topic)
KafkaIntegration.flush()
@staticmethod
def get_site_imges_data(provision_uid, primary_server, provision_port, selected_flavor):
destination_server = "http://" + str(primary_server) + ":" + str(provision_port)
api_url = destination_server + "/api/props"
try:
payload = {'provision_uid': provision_uid, 'flavor': selected_flavor}
logger.info(f"api_url: {str(api_url)}")
logger.info(f"selected_flavor: {str(selected_flavor)}")
# Make the GET request
res_data = []
response = requests.get(api_url, params=payload)
if response.status_code == 200:
logger.info(f"Response Site Images: {res_data}")
# Convert the JSON response to a Python dictionary
res_data = response.json()
logger.info(f"Response Site Images: {res_data}")
else:
res_data={}
@classmethod
def calculate_charges(cls, offer, amount):
"""
Calculates and returns the charges for the given offer and amount.
Args:
offer (Offer): The offer object that contains the charges.
amount (float): The requested loan amount.
Returns:
dict: A dictionary containing the calculated charges.
"""
if not offer or not offer.charges:
logger.error(f"No charges found for offer ID {offer.id}")
return {"error": "No charges found for the offer"}
response_data = {
"provision_uid": str(provision_uid),
"data": res_data,
# "product_id": product_id,
}
loan_charges = offer.charges
tenor = offer.schedule # offer.tenor // 30 # Convert to months
interest = cls.get_charge_detail(rates = offer.interest_rate, charges = loan_charges, code = "INTEREST", amount = amount)
management = cls.get_charge_detail(rates = offer.management_rate, charges = loan_charges, code = "MGTFEE", amount = amount)
insurance = cls.get_charge_detail(rates = offer.insurance_rate, charges = loan_charges, code = "INSURANCE", amount = amount)
vat = cls.get_charge_detail(rates = offer.vat_rate, charges = loan_charges, code = "VAT", amount = amount, management_fee = management["fee"])
return response_data
# Separate fees into upfront and postpaid
upfront_fees = [
fee["fee"]
for fee in [interest, management, insurance, vat]
if fee["due_days"] == 0
]
except Exception as e:
logger.error(f"An error occurred while get_site_imges_data data: {str(e)}", exc_info=True)
return None
postpaid_fees = [
fee["fee"]
for fee in [interest, management, insurance, vat]
if fee["due_days"] != 0
]
vat_test = vat["fee"]
logger.info(f"VAT fee == *************** : {vat_test}")
@staticmethod
def write_cache_data(cacheSection, cacheId, cacheData):
# Up-front payment: (only those fees due immediately i.e due_days == 0)
# upfront_payment = sum(upfront_fees)
if offer.schedule == 1:
upfront_payment = vat["fee"] + management["fee"] + insurance["fee"] + interest["fee"]
interest_amount = interest["fee"]
repayment_amount = amount
else:
upfront_payment = vat["fee"] + insurance["fee"]+management["fee"]
interest_amount = interest["fee"]*offer.schedule
repayment_amount = amount + interest_amount
try:
cacheKey = "MERMS-" + cacheSection + '-' + cacheId # note theh use of -
logger.info(f"write_cache_data () key {cacheKey}", exc_info=True)
# Define connection parameters and connect
r = redis.Redis(host=BaseService.CACHE_SERVER, port=BaseService.CACHE_PORT,
password=BaseService.CACHE_PASSWORD,
decode_responses=True)
if r.exists(cacheKey):
r.unlink(cacheKey)
# Repayment amount: (principal + only those fees not due immediately i.e due_days != 0)
# repayment_amount = amount + (sum(postpaid_fees) * tenor)
# Set a key 'foo' with value 'bar'
json_string = json.dumps(cacheData, indent=4)
r.set(cacheKey, json_string, ex=BaseService.CACHE_DEFAULT_EXPIRE)
# Total amount: (upfront_payment + repayment_amount)
total_amount = upfront_payment + repayment_amount
# Verify by getting the value
value = r.get(cacheKey)
print(f"Value of {cacheKey}: {value}") # Output: Value of 'foo': bar
# Calculate the installment amount
installment_amount = repayment_amount / offer.schedule
response_data = {
"session_details": value,
# "product_id": product_id,
}
return {
"interest": interest,
"interest_amount": interest_amount,
"management": management,
"insurance": insurance,
"vat": vat,
"upfront_payment": round(upfront_payment, 2),
"repayment_amount": round(repayment_amount, 2),
"installment_amount": round(installment_amount, 2),
"total_amount": round(total_amount, 2)
}
@classmethod
def get_charge_detail(cls, rates, charges, code, amount, management_fee= 0.0):
"""
Get details for a specific charge code from a list of loan charges.
Returns default values if not found.
"""
fee = 0.0
if code == "VAT" and management_fee > 0:
fee = management_fee * rates / 100
else:
fee = amount * rates / 100
return {
"rate": rates,
"fee": round(fee, 2),
"due_days": 30,
"code": code,
"description" : "have no idea how to get this yet"
}
# if charge.code == code:
# if code == "VAT" and management_fee > 0:
# fee = management_fee * rates / 100
# else:
# fee = amount * rates / 100
#
# return {
# "rate": rates,
# "fee": round(fee, 2),
# "due_days": charge.due
# }
# return {"rate": 0, "fee": 0, "due_days": 0}
return response_data
except Exception as e:
logger.error(f"An error occurred while write_cache_data data: {str(e)}", exc_info=True)
return None
-99
View File
@@ -1,99 +0,0 @@
from flask import session, jsonify
# 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.extensions import db
from app.models import MembersProducts, Products, Members
# 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.register import RegisterSchema
from app.api.schemas.products import ProductsSchema
from app.api.schemas.user import UserSchema
import datetime
import jwt
import random
from app.config import Config
class CommentsService(BaseService):
@staticmethod
def process_comments_request(data):
try:
with db.session.begin():
logger.info(f"Incoming ContactService data ==>>>> {data}")
validated_data = CommentsService.validate_data(data, UserSchema())
token = validated_data.get('token')
uid = validated_data.get('uid')
member_data = Members.get_member_by_uid(uid)
member_id = member_data.id
contacts_product_list = Products.get_comments_supported_product_list(member_id)
category_data = []
for t in contacts_product_list:
category_data.append({
'cid': t.product_id,
'category_uid': t.uid,
'description': t.name,
})
cat_list = [ 'A000004', 'A000003']
dList = []
sample_range = random.randint(20, 60)
for x in range(sample_range):
calDate = datetime.datetime.utcnow() + datetime.timedelta(minutes=180 * random.randint(1, 20))
new_l = {
"uid": "425611f2-c692-4404-b93d-76ca7a5ce7" + str(x),
"title": "Random Site Comments Item on " + str(x),
"category": cat_list[random.randint(0, 1)],
"added": calDate,
"sender": "Firstname Lastname" + str(random.randint(1, 4)),
"message": dummy_message()
}
dList.append(new_l)
response_data = {
"last_update": datetime.datetime.utcnow(),
"member_id": member_id,
"category": category_data,
"contacts": dList
}
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()
def dummy_message():
dmm = "Dmummy Message" + str(random.randint(100, 400))
mss = f"""
{dmm}I truly believe Augustines words are true and if you look at history you know it is true. There are many people in the world with amazing talents who realize only a small percentage of their potential. We all know people who live this truth.
We also know those epic stories, those modern-day legends surrounding the early failures of such supremely successful folks as Michael Jordan and Bill Gates. We can look a bit further back in time to Albert Einstein or even further back to Abraham Lincoln. What made each of these people so successful? Motivation.
We know this in our gut, but what can we do about it? How can we motivate ourselves? One of the most difficult aspects of achieving success is staying motivated over the long haul.
"""
return mss
+66 -108
View File
@@ -1,13 +1,25 @@
from flask import session, jsonify
# 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.extensions import db
from app.models import MembersProducts, Products, Members, ProductsContacts
from app.models import MembersProducts, Products, Members
# 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.register import RegisterSchema
from app.api.schemas.products import ProductsSchema
from app.api.schemas.user import UserSchema
import datetime
import jwt
import random
from app.config import Config
class ContactService(BaseService):
@@ -15,7 +27,7 @@ class ContactService(BaseService):
@staticmethod
def process_request(data):
try:
with (db.session.begin()):
with db.session.begin():
logger.info(f"Incoming ContactService data ==>>>> {data}")
validated_data = ContactService.validate_data(data, UserSchema())
token = validated_data.get('token')
@@ -23,75 +35,57 @@ class ContactService(BaseService):
member_data = Members.get_member_by_uid(uid)
member_id = member_data.id
contacts_product_list = Products.get_contact_supported_product_list(member_id)
category_data = []
for t in contacts_product_list:
category_data.append({
'cid': t.product_id,
'category_uid': t.uid,
'description': t.name,
})
cat_list = ['A000002', 'A000004', 'A000001', 'A000003']
page = 1
limit = 20
category_data = [
{
"cid": "1",
"description": "category 01"
},
{
"cid": "2",
"description": "category 02"
},
{
"cid": "3",
"description": "category 03"
},
{
"cid": "4",
"description": "category 04"
}
]
# SUPPORTED_CATEGORY = "SELECT name AS title,product_id from products WHERE product_id IN ('A000002','A000004','A000001','A000003')"
# with connection:
# with connection.cursor(cursor_factory=psycopg2.extras.DictCursor) as cursor:
# cursor.execute(SUPPORTED_CATEGORY)
# select_Res = cursor.fetchall()
#
# print(select_Res)
# contacts_category = json.dumps([dict(ix) for ix in select_Res])
# print(contacts_category)
# array_cat = json.loads(contacts_category)
dList = []
contacts_data , total_count= ProductsContacts.get_all_contacts(member_id, page=1, limit=20)
if contacts_data:
for t in contacts_data:
new_l = {
"uid": str(t.uid),
"title": t.title,
"category": t.product_id,
"added": t.added,
"sender": t.sender,
"message": t.message,
}
dList.append(new_l)
sample_range = random.randint(20, 60)
for x in range(sample_range):
calDate = datetime.datetime.utcnow() + datetime.timedelta(minutes=180 * random.randint(1, 20))
new_l = {
"uid": "425611f2-c692-4404-b93d-76ca7a5ce7" + str(x),
"title": "Contact Random Item on " + str(x),
"category": cat_list[random.randint(0, 3)],
"added": calDate,
"sender": "Firstname Lastname" + str(random.randint(1, 4)),
"message": dummy_message()
}
dList.append(new_l)
# membersSubList, total_count = MembersProducts.get_all_subscriptions(product_id, member_id, page, limit)
# # Convert loans to dictionary format
# member_sub_data = []
# for subs in membersSubList:
# member_sub_data.append({
# 'id': subs.id,
# 'member_id': subs.member_id,
# 'product_id': subs.product_id,
# 'internal_url': subs.internal_url,
# 'external_url': subs.external_url,
# 'dns_group': subs.dns_group,
# 'status': subs.status,
# 'updated': subs.updated,
# "added": subs.added,
# })
# sample_range = random.randint(20, 60)
# for x in range(sample_range):
# calDate = datetime.datetime.utcnow() + datetime.timedelta(minutes=180 * random.randint(1, 20))
# new_l = {
# "uid": "425611f2-c692-4404-b93d-76ca7a5ce7" + str(x),
# "title": "Contact Random Item on " + str(x),
# "category": cat_list[random.randint(0, 3)],
# "added": calDate,
# "sender": "Firstname Lastname" + str(random.randint(1, 4)),
# "message": ContactService.dummy_message()
# }
# dList.append(new_l)
total_pages = (total_count + limit - 1) // limit
response_data = {
"last_update": datetime.datetime.utcnow(),
"member_id": member_id,
"member_id":member_id,
"category": category_data,
"contacts": dList,
'pagination': {
'total_count': total_count,
'total_pages': total_pages,
'current_page': page,
'limit': limit,
'has_next': page < total_pages,
'has_prev': page > 1
}
"contacts": dList
}
return ResponseHelper.success(data=response_data)
@@ -112,49 +106,13 @@ class ContactService(BaseService):
db.session.rollback()
return ResponseHelper.internal_server_error()
@staticmethod
def dummy_message():
dmm = "Dmummy Message" + str(random.randint(100, 400))
mss = f"""
{dmm}I truly believe Augustines words are true and if you look at history you know it is true. There are many people in the world with amazing talents who realize only a small percentage of their potential. We all know people who live this truth.
We also know those epic stories, those modern-day legends surrounding the early failures of such supremely successful folks as Michael Jordan and Bill Gates. We can look a bit further back in time to Albert Einstein or even further back to Abraham Lincoln. What made each of these people so successful? Motivation.
We know this in our gut, but what can we do about it? How can we motivate ourselves? One of the most difficult aspects of achieving success is staying motivated over the long haul.
"""
return mss
def dummy_message():
dmm = "Dmummy Message" + str(random.randint(100, 400))
mss = f"""
{dmm}I truly believe Augustines words are true and if you look at history you know it is true. There are many people in the world with amazing talents who realize only a small percentage of their potential. We all know people who live this truth.
@staticmethod
def process_save_contacts(data):
logger.info(f"Process_save_contacts IN -> : {data}", exc_info=True)
try:
message = data.get('message', '')
subscription_uid = data.get('subscription_uid', '')
title = data.get('title', '')
email = data.get('email', '')
sender = data.get('sender', '')
contact_result = None
memSubb = MembersProducts.get_member_product_by_subscription_uid(subscription_uid)
if memSubb:
member_id = memSubb.member_id,
product_id = memSubb.product_id
if message != '' and title != '' and email != '' and sender != '':
logger.info(f"Ready to save data: {data}", exc_info=True)
contact_result = ProductsContacts.add_product_contact(
member_id, product_id, subscription_uid, title, email, sender, message
)
# if contact_result and contact_result.uid != '':
#
response_data = {
"last_message": datetime.datetime.utcnow(),
"subscription_uid": subscription_uid,
"result": contact_result.uid if contact_result and contact_result.uid != '' else None,
}
return ResponseHelper.success(data=response_data)
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
return ResponseHelper.internal_server_error()
We also know those epic stories, those modern-day legends surrounding the early failures of such supremely successful folks as Michael Jordan and Bill Gates. We can look a bit further back in time to Albert Einstein or even further back to Abraham Lincoln. What made each of these people so successful? Motivation.
We know this in our gut, but what can we do about it? How can we motivate ourselves? One of the most difficult aspects of achieving success is staying motivated over the long haul.
"""
return mss
+59 -59
View File
@@ -1,60 +1,60 @@
# from flask import request, jsonify
# from app.api.helpers.response_helper import ResponseHelper
# # from app.api.services.base_service import BaseService
# from marshmallow import ValidationError
# from app.utils.logger import logger
# # from app.api.schemas.customer_consent import CustomerConsentSchema
from flask import request, jsonify
from app.api.helpers.response_helper import ResponseHelper
# from app.api.services.base_service import BaseService
# from app.api.enums import TransactionType
# from app.extensions import db
#
#
# class CustomerConsentService(BaseService):
# TRANSACTION_TYPE = TransactionType.CUSTOMER_CONSENT
#
# @staticmethod
# def process_request(data):
# """
# Process the CustomerConsent request.
#
# Args:
# data (dict): The request data.
#
# Returns:
# dict: A standardized response.
# """
# try:
# with db.session.begin():
# validated_data = CustomerConsentService.validate_data(data, CustomerConsentSchema())
# account_id = validated_data.get('accountId')
# customer_id = validated_data.get('customerId')
#
# if(CustomerConsentService.validate_account_ownership(account_id = account_id, customer_id = customer_id)):
#
# transaction = CustomerConsentService.log_transaction(validated_data = validated_data)
#
# if not transaction:
# logger.error(f"Failed to log transaction")
# return ResponseHelper.error(result_description="Failed to log transaction.")
# else:
# return ResponseHelper.error(result_description="Invalid Customer or Account")
#
#
# db.session.commit()
# return ResponseHelper.success(result_description="Request is received")
#
# 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()
from marshmallow import ValidationError
from app.utils.logger import logger
# from app.api.schemas.customer_consent import CustomerConsentSchema
from app.api.services.base_service import BaseService
from app.api.enums import TransactionType
from app.extensions import db
class CustomerConsentService(BaseService):
TRANSACTION_TYPE = TransactionType.CUSTOMER_CONSENT
@staticmethod
def process_request(data):
"""
Process the CustomerConsent request.
Args:
data (dict): The request data.
Returns:
dict: A standardized response.
"""
try:
with db.session.begin():
validated_data = CustomerConsentService.validate_data(data, CustomerConsentSchema())
account_id = validated_data.get('accountId')
customer_id = validated_data.get('customerId')
if(CustomerConsentService.validate_account_ownership(account_id = account_id, customer_id = customer_id)):
transaction = CustomerConsentService.log_transaction(validated_data = validated_data)
if not transaction:
logger.error(f"Failed to log transaction")
return ResponseHelper.error(result_description="Failed to log transaction.")
else:
return ResponseHelper.error(result_description="Invalid Customer or Account")
db.session.commit()
return ResponseHelper.success(result_description="Request is received")
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()
-214
View File
@@ -1,214 +0,0 @@
from flask import jsonify
from app.api.enums import KafkaMessage
from app.api.services import MyProductsService
from app.config import settings
from app.models import Members, MembersWebfiles
from app.utils.logger import logger
from app.api.services.base_service import BaseService
from sqlalchemy import func, desc
from app.extensions import db
from app.api.types.data_types import MemberFileData
import os
from werkzeug.utils import secure_filename
import time
from app.api.helpers.response_helper import ResponseHelper
from app.api.schemas.user import UserSchema
class FileUploadService(BaseService):
UPLOAD_FOLDER = settings.UPLOAD_FOLDER # '/app/uploads' # '/uploads'
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
@staticmethod
def member_webfiles(data):
try:
validated_data = FileUploadService.validate_data(data, UserSchema())
user_token = validated_data.get('token')
member_uid = str(validated_data.get('uid'))
# Who is this
member_data = Members.get_member_by_uid(member_uid)
if not member_data:
return jsonify({"message": "User not found"}), 500
member_id = member_data.id
result_file_list = MembersWebfiles.get_member_webfiles_by_member_id(member_id)
file_list = []
if result_file_list:
for t in result_file_list:
file_list.append({
'id': t.id,
'file_uid': t.uid,
'member_id': t.member_id,
'member_uid': t.member_uid,
'file_group': t.file_group,
'filename': t.filename,
'save_filename': t.save_filename,
'file_type': t.file_type,
'status': t.status,
'file_size': t.file_size,
'added': t.added.isoformat() if t.added else None,
'updated': t.updated.isoformat() if t.updated else None
})
response_data = {
"file_list": file_list,
"media_server": settings.MEDIA_SERVER,
}
return ResponseHelper.success(data=response_data)
except Exception as e:
logger.error(f"An error occurred getting file list: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
# return file_list
@staticmethod
def process_profile_file_upload(upload_type: str, file, member_uid):
timestamp_integer = int(time.time())
## MAKE SURE WE HAVE BASE FOLDERS
if not os.path.isdir(FileUploadService.UPLOAD_FOLDER):
os.makedirs(FileUploadService.UPLOAD_FOLDER)
profile_path = FileUploadService.UPLOAD_FOLDER + "/PROFILE"
if not os.path.isdir(profile_path):
os.makedirs(profile_path)
file_uid = ""
try:
# Who is this
member_data = Members.get_member_by_uid(member_uid)
if not member_data:
return jsonify({"message": "User not found"}), 500
member_id = member_data.id
final_folder = f"W{member_id:010d}"
logger.info(f'POST CALLED 5 {file.filename}')
save_path = profile_path + "/" + final_folder
if not os.path.isdir(save_path):
os.makedirs(save_path)
filename = secure_filename(file.filename)
# This is to avert duplicate file name issues
save_filename = str(timestamp_integer) + "-" + filename
final_save_path = os.path.join(save_path, save_filename)
logger.info(f'POST CALLED 6 {final_save_path}')
file.save(final_save_path)
save_result = []
# Confirm file was created before stamping
if os.path.isfile(final_save_path):
logger.info(f"'{final_save_path}' was found in the folder '{final_save_path}'")
save_file_props = MemberFileData()
save_file_props.member_uid = member_uid
save_file_props.filename = filename
save_file_props.save_filename = save_filename
save_file_props.file_group = "PROFILE"
save_file_props.member_id = member_id
save_file_props.file_size = 0
save_file_props.file_type = filename.rsplit('.', 1)[1].lower()
save_result, file_uid = MembersWebfiles.create_file_profile(save_file_props)
logger.info(f"After Insert Members File Data {save_result} ")
with db.session.begin():
Members.set_member_profile_picture(str(member_uid), str(file_uid))
else:
logger.info(f"'{final_save_path}' was not found as a file in '{final_save_path}'")
file_url = BaseService.get_profile_picture_url(file_uid)
response_data = {
"picture": file_url,
"save_result": save_result,
"file_uid": file_uid,
}
return response_data
except Exception as e:
logger.error(f"An error occurred while uploading profile file: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
@staticmethod
def process_file_upload(upload_type: str, file, member_uid):
timestamp_integer = int(time.time())
## MAKE SURE WE HAVE BASE FOLDERS
if not os.path.isdir(FileUploadService.UPLOAD_FOLDER):
os.makedirs(FileUploadService.UPLOAD_FOLDER)
file_uid = ""
try:
# Who is this
member_data = Members.get_member_by_uid(member_uid)
if not member_data:
return jsonify({"message": "User not found"}), 500
member_id = member_data.id
final_folder = f"W{member_id:010d}"
save_path = FileUploadService.UPLOAD_FOLDER + "/WEBSITE"
if not os.path.isdir(save_path):
os.makedirs(save_path)
logger.info(f'POST CALLED 5 {file.filename}')
save_path = FileUploadService.UPLOAD_FOLDER + "/WEBSITE/" + final_folder
if not os.path.isdir(save_path):
os.makedirs(save_path)
filename = secure_filename(file.filename)
# This is to avert duplicate file name issues
save_filename = str(timestamp_integer) + "-" + filename
final_save_path = os.path.join(save_path, save_filename)
logger.info(f'POST CALLED 6 {final_save_path}')
file.save(final_save_path)
save_result = []
# Confirm file was created before stamping
if os.path.isfile(final_save_path):
logger.info(f"'{final_save_path}' was found in the folder '{final_save_path}'")
save_file_props = MemberFileData()
save_file_props.member_uid = member_uid
save_file_props.filename = filename
save_file_props.save_filename = save_filename
save_file_props.file_group = "WEBSITE"
save_file_props.member_id = member_id
save_file_props.file_size = 0
save_file_props.file_type = filename.rsplit('.', 1)[1].lower()
save_result, file_uid = MembersWebfiles.create_file_profile(save_file_props)
logger.info(f"After Insert Members File Data {save_result} ")
else:
logger.info(f"'{final_save_path}' was not found as a file in '{final_save_path}'")
response_data = {
"save_result": save_result,
"file_uid": file_uid,
}
return response_data
except Exception as e:
logger.error(f"An error occurred while uploading file: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in FileUploadService.ALLOWED_EXTENSIONS
-142
View File
@@ -1,142 +0,0 @@
from flask import session, jsonify
from app.api.integrations import GenerativeEngineIntegration
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 SubscriptionGenerative, GenerativeResults, MembersProductsSettings, MembersProfile
from app.api.enums import GenerativesList
class GenerativesService(BaseService):
@staticmethod
def process_generatives_list(current_subscription):
# catch - current_subscription process only for performance
logger.info("SELECT GENERATIVE")
planed_generate_list = SubscriptionGenerative.get_subscription_generative_list_by_status(0)
if planed_generate_list:
for t in planed_generate_list:
logger.info(f"SELECT GENERATIVE {t}")
practice_type = t.practice
specialization = t.specialization
subscription_uid = t.subscription_uid
product_id = t.product_id
member_id = t.member_id
status = t.status
SubscriptionGenerative.update_subscription_generative_status(subscription_uid,
status + 1) # move the status up
GenerativesService.process_generatives_action(member_id, practice_type, specialization,
subscription_uid, product_id)
GenerativesService.process_generatives_results_for_subscription(subscription_uid, product_id, member_id)
GenerativesService.process_prepare_logo_text(member_id, product_id, subscription_uid)
@staticmethod
def process_prepare_logo_text(member_id, product_id, subscription_uid):
try:
mem_profile = MembersProfile.get_member_profile_by_member_id(member_id)
if mem_profile and mem_profile.url_name:
MembersProductsSettings.save_generative_product_settings(member_id, subscription_uid,
product_id,
"site_logo_text",
'TXT', mem_profile.url_name)
except Exception as e:
logger.error(f"An error process_prepare_logo_text: {str(e)}", exc_info=True)
@staticmethod
def process_generatives_results_for_subscription(subscription_uid, product_id, member_id):
logger.info("PROCESS GENERATIVE")
try:
subscription_result = GenerativeResults.get_subscription_generative_by_subscription_uid(subscription_uid)
if subscription_result:
# with db.session.begin():
for sub in subscription_result:
var_name = sub.var_name
text_result = sub.text_result
if var_name == 'about_description':
paragraphs = text_result.split("\n\n")
MembersProductsSettings.save_generative_product_settings(member_id, subscription_uid,
product_id,
"about_description",
'TXT', str(paragraphs[0]))
MembersProductsSettings.save_generative_product_settings(member_id, subscription_uid,
product_id,
"about_extra_1",
'TXT', str(paragraphs[1]))
MembersProductsSettings.save_generative_product_settings(member_id, subscription_uid,
product_id,
"about_extra_2",
'TXT', str(paragraphs[2]))
else:
MembersProductsSettings.save_generative_product_settings(member_id, subscription_uid,
product_id,
var_name,
'TXT', text_result)
else:
logger.info(f"None on -> PROCESS GENERATIVE for {subscription_uid}")
except Exception as e:
logger.error(f"An error process_generatives_results_for_subscription: {str(e)}", exc_info=True)
@staticmethod
def process_generatives_action(member_id, practice_type, specialization, subscription_uid, product_id):
try:
logger.info("ENTER GENERATIVE")
generate_list = GenerativesList.get_generative_list(product_id)
for t in generate_list:
prompt_string = str(t["prompt"]).replace("REPLACE_THIS", practice_type).replace("REPLACE_ANOTHER",
specialization)
var_name = t["name"]
logger.info(f"GenerativesService ****** *****: {t['name']} {prompt_string}")
# json_response = None
json_response = GenerativeEngineIntegration.ask_generative(prompt_string)
if json_response is not None:
logger.info(json_response)
logger.info("1============================")
logger.info(json_response["output"])
logger.info("2============================")
logger.info(json_response["output"][0])
logger.info("3============================")
# logger.info(json_response["output"][0]["content"][0]["text"])
text_result = json_response["output"][0]["content"][0]["text"]
logger.info("4============================")
logger.info(
f"INSERT *****:{member_id} {product_id} {var_name} {subscription_uid} {text_result}")
GenerativeResults.create_generative_result(member_id, product_id, var_name, subscription_uid,
text_result)
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()
# GenerativeResults.create_generative_result(71, 'A000001', 'about_title',
# '35e2d3ba-b5a6-4c1b-b962-05661d55b6f4',
# 'Expert Neurologist: Brain & Nerve Care')
# with db.session.begin():
# INFO - INSERT *****:71 A000001 about_title 35e2d3ba-b5a6-4c1b-b962-05661d55b6f4 Expert Neurologist: Brain & Nerve Care
# GenerativeResults.create_generative_result(71, 'A000001', 'about_title',
# '35e2d3ba-b5a6-4c1b-b962-05661d55b6f4',
# 'Expert Neurologist: Brain & Nerve Care')
+36 -42
View File
@@ -5,7 +5,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 PasswordReset, Members
from app.models import PasswordReset, Members
from app.api.helpers.response_helper import ResponseHelper
from werkzeug.security import generate_password_hash, check_password_hash
from app.api.schemas.login import LoginSchema
@@ -37,8 +37,8 @@ class LoginService(BaseService):
}
return ResponseHelper.success(data=invalid_data)
reset_data = PasswordReset.create_reset(username=username)
BaseService.send_resetpass_mail(member.email, str(reset_data.uid), reset_data.id, member.firstname,
member.lastname) # pending_uid, pending_id, firstname, lastname
BaseService.send_resetpass_mail(member.email, str(reset_data.uid), reset_data.id, member.firstname,member.lastname) #pending_uid, pending_id, firstname, lastname
response_data = {
"error_message": "",
@@ -72,7 +72,7 @@ class LoginService(BaseService):
validated_data = LoginService.validate_data(data, ResetPassVerify())
reset_token = validated_data.get('reset_token')
logger.error("GOT HERE 000001 ")
data = {}
data ={}
if not reset_token:
return jsonify({'message': 'Error - missing reset_token '}), 403
try:
@@ -91,7 +91,7 @@ class LoginService(BaseService):
user_data = data["user"]
reset_data = PasswordReset.get_rest_with_uid(user_data["pending_uid"])
logger.error(f"GOT HERE 000003 {reset_data} id = {reset_data.id}")
if reset_data.status > 0:
if reset_data.status> 0:
invalid_data = {
"error_message": "The link is invalid please try again later",
"reset_message": "",
@@ -99,7 +99,7 @@ class LoginService(BaseService):
}
return ResponseHelper.success(data=invalid_data)
PasswordReset.update_status(reset_data.id, reset_data.status + 1)
PasswordReset.update_status(reset_data.id, reset_data.status+1)
response_data = {
"error_message": "",
@@ -137,15 +137,15 @@ class LoginService(BaseService):
reset_uid = validated_data.get('reset_uid')
new_password = validated_data.get('new_password')
logger.info("GOT HERE 000001 ")
data = {}
logger.error("GOT HERE 000001 ")
data ={}
if not reset_token:
return jsonify({'message': 'Error - missing reset_token '}), 403
try:
data = jwt.decode(reset_token, LoginService.JWT_SECRET_KEY, algorithms=["HS256"])
except:
return jsonify({'status': 'INVALID2', 'message': 'Link is invalid'}), 403
logger.info("GOT HERE 000002 ")
logger.error("GOT HERE 000002 ")
if not data:
invalid_data = {
"error_message": "The link is invalid please try again later",
@@ -155,14 +155,11 @@ class LoginService(BaseService):
return ResponseHelper.success(data=invalid_data)
user_data = data["user"]
logger.info(f"GOT HERE USER03 {user_data} ")
reset_data = PasswordReset.get_rest_with_uid(user_data["pending_uid"])
logger.info(f"GOT HERE RESET {reset_data} ")
logger.info(f"GOT HERE RESET DATA id = {reset_data.id}")
PasswordReset.update_status(reset_data.id, reset_data.status + 1)
username = reset_data.username
logger.error(f"GOT HERE 000003 {reset_data} id = {reset_data.id}")
username = user_data["username"]
member = Members.get_member_by_username(username)
if not member:
invalid_data = {
@@ -173,10 +170,10 @@ class LoginService(BaseService):
return ResponseHelper.success(data=invalid_data)
encrypted_pass = generate_password_hash(new_password)
Members.update_user_password(reset_data.id, member.uid, member.id, encrypted_pass)
Members.update_user_password(reset_data.id, member["uid"], member["id"], encrypted_pass)
# update_user_passowrd(cls, reset_id, member_uid, member_id, new_passwprd_hash)
BaseService.send_completepass_mail(member.email, str(reset_data.uid), reset_data.id, member.firstname,
member.lastname) # pending_uid, pending_id, firstname, lastname
member.lastname) # pending_uid, pending_id, firstname, lastname
response_data = {
"error_message": "",
@@ -221,7 +218,7 @@ class LoginService(BaseService):
}
return ResponseHelper.success(data=invalid_data)
pass_check = check_password_hash(member.password, password)
pass_check = check_password_hash(member.password, password)
logger.info("Password check: {}".format(pass_check))
if not member or not pass_check:
invalid_data = {
@@ -229,47 +226,44 @@ class LoginService(BaseService):
"message_key": "invalid_username_or_password",
}
return ResponseHelper.success(data=invalid_data)
#
# last_login
Members.set_member_last_login(member.uid)
user_data = {}
user_data["id"] = member.id,
user_data["member_id"] = member.id,
user_data["member_id"]= member.id,
user_data["uid"] = str(member.uid),
user_token = jwt.encode(
{"user": user_data, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=3330)},
Config.JWT_SECRET_KEY,
algorithm="HS256"
)
{"user": user_data, 'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=3330)},
Config.JWT_SECRET_KEY,
algorithm="HS256"
)
# price_create_result = StripeIntegration.create_product('AmeyeTEST', 9999)
# logger.info(f"Inside Stripe_Product ===== : {price_create_result}")
file_url = BaseService.get_profile_picture_url(member.profile_picture)
# Simulate processing
response_data = {
"member_id": member.id,
"uid": str(member.uid),
"uid": str(member.uid),
"username": member.username,
"account_name": member.account_name,
"firstname": member.firstname,
"firstname":member.firstname,
"lastname": member.lastname,
"room": member.uid,
"room": member.uid,
"profile_completed": member.profile_completed,
"picture": 'https://media.mermsemr.com/media/show/merms-profile' if file_url == '' else file_url,
"token": user_token
}
padded_member_id = str(member.id).zfill(6)
customer_data = {
"email": "support+" + padded_member_id + "@chiefsoft.com",
"email":"support+" + padded_member_id + "@chiefsoft.com",
"name": str(member.firstname) + ' ' + str(member.lastname),
}
if member and (member.stripe_customer_id is None or member.stripe_customer_id == ''):
if member and (member.stripe_customer_id is None or member.stripe_customer_id==''):
stripe_customer = BaseService.addStripeCustomer(customer_data)
logger.info(f"Stripe_Customer ===== : {stripe_customer}")
if stripe_customer is not None:
logger.info(f"Stripe_Customer ID ===== : {stripe_customer.id}")
Members.set_user_stripe_id(member.uid, member.id, stripe_customer.id)
Members.set_user_stripe_id( member.uid, member.id, stripe_customer.id)
return ResponseHelper.success(data=response_data)
@@ -300,7 +294,7 @@ class LoginService(BaseService):
}
return ResponseHelper.success(data=invalid_data)
pass_check = check_password_hash(member.password, password)
pass_check = check_password_hash(member.password, password)
logger.info("Password check: {}".format(pass_check))
if not member or not pass_check:
invalid_data = {
@@ -311,24 +305,24 @@ class LoginService(BaseService):
user_data = {}
user_data["id"] = member.id,
user_data["member_id"] = member.id,
user_data["member_id"]= member.id,
user_data["uid"] = str(member.uid),
user_token = jwt.encode(
{"user": user_data, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=3330)},
Config.JWT_SECRET_KEY,
algorithm="HS256"
)
{"user": user_data, 'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=3330)},
Config.JWT_SECRET_KEY,
algorithm="HS256"
)
# Simulate processing
response_data = {
"member_id": member.id,
"uid": str(member.uid),
"uid": str(member.uid),
"username": member.username,
"account_name": member.account_name,
"firstname": member.firstname,
"firstname":member.firstname,
"lastname": member.lastname,
"room": member.uid,
"room": member.uid,
"token": user_token
}
# customer_data=[]
+59 -664
View File
@@ -1,20 +1,10 @@
from urllib import request
from flask import session, jsonify
from app.api.enums import SettingsItemsData, KafkaMessage
from app.api.schemas.myproduct_external_url import MyProductExternalUrlSchema
from app.api.schemas.myproduct_set_colorstyle import MyProductSetColorStyleSchema
from app.api.schemas.myproduct_set_template import MyProductSetTemplateSchema
from app.api.schemas.myproduct_template_image import MyProductTemplateImageSchema
# from app.api.services import GenerativesService
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, \
MembersProductsSettings, ProductsTemplates, MembersProfile, SubscriptionGenerative, ProductsColorStyle, \
MembersWebfiles
MembersProductsSettings, ProductsTemplates
from app.api.helpers.response_helper import ResponseHelper
from app.api.schemas.myproduct import MyProductSchema
from app.api.schemas.provision import ProvisionSchema
@@ -28,102 +18,11 @@ from app.config import Config
class MyProductsService(BaseService):
START_URL_PATTERN = Config.START_URL_PATTERN
MEDIA_SERVER = Config.MEDIA_SERVER
@staticmethod
def process_provision_actions(data):
pass
@staticmethod
def process_set_colorstyle(data):
try:
with db.session.begin():
# logger.info(f"Incoming MyProduct data ==>>>> {data}")
validated_data = MyProductsService.validate_data(data, MyProductSetColorStyleSchema())
token = validated_data.get('token')
uid = validated_data.get('uid')
color_style_uid = validated_data.get('color_style_uid')
product_id = validated_data.get('product_id')
member_data = Members.get_member_by_uid(uid)
member_id = member_data.id
# is this a valid color scheme
colorStyle = ProductsColorStyle.get_colorstyle_by_product_id_and_uid(product_id, color_style_uid)
if colorStyle and colorStyle.color_style != '':
MembersProducts.set_member_product_colorstyle(member_id, product_id, color_style_uid)
response_data = {}
response_data = {
"product_id": product_id,
"color_style_uid": color_style_uid,
"last_update": datetime.datetime.utcnow(),
}
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()
@staticmethod
def process_set_template(data):
try:
with db.session.begin():
# logger.info(f"Incoming MyProduct data ==>>>> {data}")
validated_data = MyProductsService.validate_data(data, MyProductSetTemplateSchema())
token = validated_data.get('token')
uid = validated_data.get('uid')
template_uid = validated_data.get('template_uid')
member_data = Members.get_member_by_uid(uid)
member_id = member_data.id
response_data = {}
product_id = validated_data.get('product_id')
memberSubscription = MembersProducts.get_member_product_by_product_member_id(member_id, product_id)
MembersProducts.set_member_product_template(member_id, product_id, template_uid)
response_data = {
"subscription_uid": memberSubscription.uid,
"product_id": product_id,
"new_template_uid": template_uid,
"last_update": datetime.datetime.utcnow(),
}
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()
@staticmethod
def mpproduct_template_data(data):
try:
@@ -136,24 +35,42 @@ class MyProductsService(BaseService):
member_id = member_data.id
product_id = validated_data.get('product_id')
template_data = []
memberSubscription = MembersProducts.get_member_product_by_product_member_id(member_id, product_id)
if memberSubscription:
templates = ProductsTemplates.get_template_by_product_id(product_id)
for t in templates:
template_data.append({
# class MyProductSchema(Schema):
# token = fields.Str(required=True)
# uid = fields.Str(required=True)
# product_id = fields.Str(required=True)
templates = ProductsTemplates.get_template_by_product_id(product_id)
template_data = {
'template_16': {'title': 'Template Name-16', 'template_id': '02af24fd-2b1a-46ed-af21-87018e726408',
'banner': 'file-icon/svg.png', 'active': '0'},
'template_22': {'title': 'Template Name-22', 'template_id': '8b296894-42e4-4f2e-abd1-7c2a38d6e07b',
'banner': 'file-icon/svg.png', 'active': '0'},
'template_47': {'title': 'Template Name-47', 'template_id': 'ef2ffa1c-9272-42cd-9d33-0e614047b4f8',
'banner': 'file-icon/svg.png', 'active': '0'},
'template_25': {'title': 'Template Name-25', 'template_id': 'b3a7ba31-dc47-4a40-a5cc-fd1ff27d6b78',
'banner': 'file-icon/svg.png', 'active': '1'},
'template_49': {'title': 'Template Name-49', 'template_id': '60959c69-6672-4f69-a006-eeb7d210e605',
'banner': 'file-icon/svg.png', 'active': '0'},
'template_27': {'title': 'Template Name-27', 'template_id': 'e4acb98a-c584-45f2-bece-af677dcf0a1f',
'banner': 'file-icon/svg.png', 'active': '0'},
'template_51': {'title': 'Template Name-51', 'template_id': '975ee42e-3169-4978-92d7-d28e7e2ac014',
'banner': 'file-icon/svg.png', 'active': '0'},
'template_9': {'title': 'Template Name-9', 'template_id': 'fc8f0738-6500-4775-9895-2047cd275302',
'banner': 'file-icon/svg.png', 'active': '0'},
}
template_data =[]
for t in templates:
template_data.append({
'id': t.id,
'template_uid': t.uid,
'title': t.name,
'active': 1,
'banner': 'https://qa-panel.mermsemr.com/static/media/',
'added': t.added.isoformat() if t.added else None
})
})
response_data = {
"product_id": product_id,
"current_template_uid": memberSubscription.product_template if memberSubscription else None,
"custom_template_name": memberSubscription.custom_template if memberSubscription else '',
"templates": template_data,
"last_update": datetime.datetime.utcnow(),
}
@@ -177,62 +94,6 @@ class MyProductsService(BaseService):
db.session.rollback()
return ResponseHelper.internal_server_error()
@staticmethod
def mpproduct_colostyles_data(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')
color_style_data = []
memberSubscription = MembersProducts.get_member_product_by_product_member_id(member_id, product_id)
if memberSubscription:
colorStyles = ProductsColorStyle.get_colorstyle_by_product_id(product_id)
# templates = ProductsTemplates.get_template_by_product_id(product_id)
for t in colorStyles:
color_style_data.append({
'id': t.id,
'template_uid': t.uid,
'color_style_uid': t.uid,
'color_code': t.color_code,
'title': t.name,
'active': t.status,
'added': t.added.isoformat() if t.added else None
})
response_data = {
"product_id": product_id,
"current_colorstyle_uid": memberSubscription.colorstyle if memberSubscription else None,
"current_template_uid": memberSubscription.product_template if memberSubscription else None,
"custom_template_name": memberSubscription.custom_template if memberSubscription else '',
"color_styles": color_style_data,
"last_update": datetime.datetime.utcnow(),
}
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()
@staticmethod
def process_provision(data):
try:
@@ -246,38 +107,32 @@ class MyProductsService(BaseService):
product_id = validated_data.get('product_id')
product_data = Products.get_product_by_product_id(product_id)
# logger.error(f"Product with ID {product_id} does not exist.")
if not product_data:
return {
"message": "Please provide valid product_id",
"error_message": "Error - Please select a valid product to view",
"message": "Please provide product_id",
"data": None,
"error": f"Product with ID {product_id} does not exist."
"error": "Bad request"
}, 400
logger.info(f"GET HERE ******************************** : {data}", exc_info=True)
subscription = MembersProducts.get_member_product_by_product_member_id(member_id, product_id)
percent_completed=0
provision_activities = ProvisionActions.get_provision_action_by_product_uid(subscription.uid, 4)
provision_activities_data = []
activity_counter = 0
if provision_activities:
for t in provision_activities:
if activity_counter == 0:
percent_completed = t.percent_completed
activity_counter += 1
provision_activities_data.append({
'id': t.id,
'uid': t.uid,
'action': t.action,
'added': t.added.isoformat() if t.added else None,
})
for t in provision_activities:
provision_activities_data.append({
'id': t.id,
'uid': t.uid,
'action': t.action,
'added': t.added.isoformat() if t.added else None,
})
response_data = {
"subscription_uid": subscription.uid,
"subscription_id": subscription.id,
"last_update": datetime.datetime.utcnow(),
"percent_completed": percent_completed,
"percent_completed": random.randint(10, 99),
"activities": provision_activities_data
}
return ResponseHelper.success(data=response_data)
@@ -310,40 +165,15 @@ class MyProductsService(BaseService):
member_data = Members.get_member_by_uid(uid)
member_id = member_data.id
# getting the url-name part
url_name_part = str(random.randint(100000, 999999)) # Starr with random numbers
member_profile_data = MembersProfile.get_member_profile_by_member_id(member_id)
if member_profile_data and member_profile_data.url_name != None:
url_name_part = member_profile_data.url_name
product_id = validated_data.get('product_id')
product_data = Products.get_product_by_product_id(product_id)
configured_start_url = product_data.start_url
if configured_start_url == '':
configured_start_url = MyProductsService.START_URL_PATTERN
internal_url = url_name_part + configured_start_url # ".devprov.mermsemr.com" =
internal_url = internal_url.lower()
# let us see if this is in USE
anybodyUsingUrl = MembersProducts.get_member_product_by_internal_url(internal_url)
if anybodyUsingUrl:
return {
"message": "Unable to create URL",
"error_message": "Error - Please try again latter",
"data": None,
"error": f"Unable to create URL for the Product."
}, 400
if not product_data:
if not product_data:
return {
"message": "Please provide valid product_id",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"Product with ID {product_id} does not exist."
}, 400
return {
"message": "Please provide product_id",
"data": None,
"error": "Bad request"
}, 400
logger.info(f"GET HERE ******************************** : {data}", exc_info=True)
mumberSub = MembersProducts.get_member_product_by_product_member_id(member_id, product_id)
@@ -358,21 +188,12 @@ class MyProductsService(BaseService):
}
return ResponseHelper.success(data=response_data)
internal_url = str(random.randint(100000, 999999)) + ".devprov.mermsemr.com"
# INSERT_NEW_PRODUCT = "INSERT INTO members_products (member_id ,product_id,status,internal_url) VALUES (%s, %s, %s, %s)"
# val_insert = (member_id, product_id,6,internal_url)
status = 6
subscription = MembersProducts.create_subscription(member_id, product_id, status, internal_url)
# -let prepare the flags for auto generated stuffs
profile_data = MembersProfile.get_member_profile_by_member_id(member_id)
if profile_data:
practice = profile_data.practice
specialization = profile_data.specialization
subscription_uid = subscription.uid
SubscriptionGenerative.create_subscription_generative(member_id, practice, specialization,
product_id, subscription_uid)
# thread AI Here
# GenerativesService.process_generatives_list(subscription)
response_data = {
"subscription_uid": subscription.uid,
"subscription_id": subscription.id,
@@ -420,6 +241,15 @@ class MyProductsService(BaseService):
# logger.info(f"Incoming MyProduct data ==>>>> {memberSubscription}")
productDataStatus = memberSubscription.status
product_subscription_uid = memberSubscription.uid
# product_subscription_external_url = memberSubscription.external_url
# product_subscription_internal_url = memberSubscription.internal_url
# result_data = {
# "myproudct": {
# "result": "Reveived under development ",
# "message": "to be fixed"
# }
# }
for key in settings.keys():
setting_value = settings[key]
@@ -435,7 +265,7 @@ class MyProductsService(BaseService):
}
logger.error(f"Going for Thread ******************** ")
thread = Thread(target=MyProductsService.async_send_settings_refresh_to_kafka,
args=(response_data, subscription_uid, KafkaMessage.REFRESH_PRODUCT_SETTINGS))
args=(response_data, subscription_uid, "REFRESH_PRODUCT_SETTINGS"))
thread.start()
logger.error(f"After the Thread ******************** ")
@@ -472,20 +302,9 @@ class MyProductsService(BaseService):
product_subscription_external_url = ''
product_subscription_internal_url = ''
product_data = Products.get_product_by_product_id(product_id)
if not product_data:
return {
"message": "Please provide valid product_id",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"Product with ID {product_id} does not exist."
}, 400
product_description = ProductsDetails.get_product_details_with_product_id(product_id)
productDataStatus = product_data.status
product_template = ''
custom_template = ''
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}")
@@ -493,8 +312,6 @@ class MyProductsService(BaseService):
product_subscription_uid = memberSubscription.uid
product_subscription_external_url = memberSubscription.external_url
product_subscription_internal_url = memberSubscription.internal_url
product_template = memberSubscription.product_template
custom_template = memberSubscription.custom_template
# "banner": "banner.jpg",
myproduct_data = {
@@ -511,8 +328,6 @@ class MyProductsService(BaseService):
"product_uid": product_data.uid,
"promotion_text": "Start Free Today !",
"subscription_uid": product_subscription_uid,
'product_template': product_template,
'custom_template': custom_template,
"status": productDataStatus,
"subscription_text": "Start with your goals in mind and then work possible.ith yand Goals. If the plan doesn\u2019t support the vision then change it!",
"title": "Your personal professional web presence"
@@ -558,14 +373,6 @@ class MyProductsService(BaseService):
product_subscription_uid = ''
product_data = Products.get_product_by_product_id(product_id)
if not product_data:
return {
"message": "Please provide valid product_id",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"Product with ID {product_id} does not exist."
}, 400
product_description = ProductsDetails.get_product_details_with_product_id(product_id)
productDataStatus = product_data.status
@@ -607,415 +414,3 @@ class MyProductsService(BaseService):
logger.error(f"An error occurred: {str(e)}", exc_info=True)
db.session.rollback()
return ResponseHelper.internal_server_error()
@staticmethod
def product_configuration(data):
try:
with db.session.begin():
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_data = Products.get_product_by_product_id(product_id)
if not product_data:
return {
"message": "Please provide valid product_id",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"Product with ID {product_id} does not exist."
}, 400
product_description = ProductsDetails.get_product_details_with_product_id(product_id)
productDataStatus = product_data.status
memberSubscription = MembersProducts.get_member_product_by_product_member_id(member_id, product_id)
if memberSubscription is not None:
custom_template = "" if (
memberSubscription.custom_template is None or len(memberSubscription.custom_template)
== 0) else memberSubscription.custom_template
# logger.info(f"Incoming MyProduct data ==>>>> {memberSubscription}")
product_subscription_uid = memberSubscription.uid
subscription_template = "" if len(custom_template) > 0 else memberSubscription.product_template
settingsFields = SettingsItemsData.get_site_settings_data()
templateData = []
homeFields = SettingsItemsData.get_site_home_settings()
footerFields = SettingsItemsData.get_site_footer_settings()
contactFields = SettingsItemsData.get_site_contact_items()
socialFields = SettingsItemsData.get_site_social_settings_data()
aboutFields = SettingsItemsData.get_site_about_items()
testimonialFields = SettingsItemsData.get_site_testimonial_settings()
blogConnectFields = SettingsItemsData.get_site_blog_connect_settings()
blogConnect = False
if product_data.blog_product_id != None and product_data.blog_product_id != '':
blogConnect = True
blog_product_data = Products.get_product_by_product_id(product_data.blog_product_id)
settings_items = {}
if product_id == "A000001":
settings_items = {
"url_config_tab": {"title": 'URL Configuration', "controls": 'url-config', "active": '',
"custom": True, "data": {}, "list_order": 0},
"settings": {"title": 'Settings', "controls": 'settings', "active": 'active show',
"custom": False, "data": settingsFields, "list_order": 1},
"home_tab": {"title": 'Home Page', "controls": 'home', "active": '', "custom": False,
"data": homeFields, "list_order": 2},
"footer_tab": {"title": 'Footer', "controls": 'footer', "active": '', "custom": False,
"data": footerFields, "list_order": 3},
"about_tab": {"title": 'About Page', "controls": 'about', "active": '', "custom": False,
"data": aboutFields, "list_order": 4},
"contact_tab": {"title": 'Contact Page', "controls": 'contact', "active": '',
"custom": False,
"data": contactFields, "list_order": 5},
"social_tab": {"title": 'Socials', "controls": 'social', "active": '', "custom": False,
"data": socialFields, "list_order": 6},
"template_tab": {"title": 'Select Template', "controls": 'template', "active": '',
"custom": True,
"data": templateData, "list_order": 17},
"color_scheme_tab": {"title": 'Color Scheme', "controls": 'color-scheme', "active": '',
"custom": True, "data": {}, "list_order": 18}
}
if product_id == "A000002":
settings_items = {
"url_config_tab": {"title": 'URL Configuration', "controls": 'url-config', "active": '',
"custom": True, "data": {}, "list_order": 0},
"settings": {"title": 'Settings', "controls": 'settings', "active": 'active show',
"custom": False, "data": settingsFields, "list_order": 1},
"home_tab": {"title": 'Home Page', "controls": 'home', "active": '', "custom": False,
"data": homeFields, "list_order": 2},
"footer_tab": {"title": 'Footer', "controls": 'footer', "active": '', "custom": False,
"data": footerFields, "list_order": 3},
"about_tab": {"title": 'About Page', "controls": 'about', "active": '', "custom": False,
"data": aboutFields, "list_order": 4},
"contact_tab": {"title": 'Contact Page', "controls": 'contact', "active": '',
"custom": False,
"data": contactFields, "list_order": 5},
"testimonial_tab": {"title": 'Testimonials', "controls": 'testimonial', "active": '',
"custom": False,
"data": testimonialFields, "list_order": 6},
"social_tab": {"title": 'Socials', "controls": 'social', "active": '', "custom": False,
"data": socialFields, "list_order": 7},
"template_tab": {"title": 'Template', "controls": 'template', "active": '', "custom": True,
"data": templateData, "list_order": 18},
"color_scheme_tab": {"title": 'Color Scheme', "controls": 'color-scheme', "active": '',
"custom": True, "data": {}, "list_order": 19}
}
if product_id == "A000006":
settings_items = {
"merms_emr_settings": {"title": 'EMR Settings', "controls": 'merms-emr-settings', "active": '',
"custom": True, "data": {}, "list_order": 1},
"merms_emr_users": {"title": 'Users Admin', "controls": 'merms-emr-users', "active": '',
"custom": True, "data": {}, "list_order": 19},
}
if blogConnect:
settings_items["blog_connect_tab"] = {"title": 'Blog Connect', "controls": 'blog-connect-scheme',
"active": '',
"custom": False, "data": blogConnectFields, "list_order": 9}
# Simulate processing
response_data = {
"settings_items": settings_items,
"member_id": member_id,
"subscription_template": subscription_template,
"custom_template_name": custom_template,
"product_subscription_uid": product_subscription_uid,
"blog_connect": blogConnect
}
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()
@staticmethod
def set_external_url(data):
try:
with db.session.begin():
# logger.info(f"Incoming MyProduct data ==>>>> {data}")
validated_data = MyProductsService.validate_data(data, MyProductExternalUrlSchema())
token = validated_data.get('token')
uid = validated_data.get('uid')
subscription_uid = validated_data.get('subscription_uid')
external_url = validated_data.get('external_url')
member_data = Members.get_member_by_uid(uid)
if not member_data:
return {
"message": "Invalid User",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"User with UID {uid} does not exist."
}, 400
member_id = member_data.id
membersSubResult = MembersProducts.get_member_product_by_subscription_uid(subscription_uid)
if not membersSubResult:
return {
"message": "Invalid Subscription",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"Subscription with UID {subscription_uid} does not exist."
}, 400
logger.info(f"External URL Member Data: {member_data}")
if int(membersSubResult.member_id) != member_id:
return {
"message": "Mismatch subscription and User",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"Mismatch subscription and User."
}, 400
setUrlResult = MembersProducts.set_member_product_external_url(member_id, membersSubResult.product_id,
external_url)
# Simulate processing
response_data = {
"subscription_uid": subscription_uid,
"member_id": member_id,
"uid": 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()
@staticmethod
def template_configuration(data):
try:
with db.session.begin():
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_data = Products.get_product_by_product_id(product_id)
if not product_data:
return {
"message": "Please provide valid product_id",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"Product with ID {product_id} does not exist."
}, 400
product_description = ProductsDetails.get_product_details_with_product_id(product_id)
productDataStatus = product_data.status
memberSubscription = MembersProducts.get_member_product_by_product_member_id(member_id, product_id)
template_images = []
template_name = ''
if memberSubscription is not None:
custom_template = "" if (
memberSubscription.custom_template is None or len(memberSubscription.custom_template)
== 0) else memberSubscription.custom_template
# logger.info(f"Incoming MyProduct data ==>>>> {memberSubscription}")
product_subscription_uid = memberSubscription.uid
subscription_template = "" if len(custom_template) > 0 else memberSubscription.product_template
selected_flavor = ''
if product_id == "A000001" or product_id == "A000002": ## should be config or data driven not hard coded
settings_items = {}
if memberSubscription.product_template:
selectedTemplate = ProductsTemplates.get_template_by_uid(
str(memberSubscription.product_template))
if selectedTemplate:
selected_flavor = selectedTemplate.flavor
template_name = selectedTemplate.name
template_images = BaseService.get_site_imges_data(memberSubscription.uid,
memberSubscription.primary_server,
memberSubscription.provision_port,
selected_flavor)
web_files_list = MembersProductsSettings.get_member_websettings_by_member_setting_type(
member_id, "WEBFILES")
if web_files_list and template_images:
web_files_items = []
for t in web_files_list:
web_files_items.append({
'setting_key': t.settings_key,
'setting_value': t.setting_value,
})
template_images = MyProductsService._process_webimage_entry(web_files_items,
template_images)
# Simulate processing
response_data = {
"product_id": product_id,
"subscription_template": str(subscription_template),
"template_name": str(template_name),
"product_subscription_uid": str(product_subscription_uid),
"template_images": template_images
}
cacheId = str(product_subscription_uid).replace("-", "")
BaseService.write_cache_data("WEB_CONFIGURE", cacheId, response_data)
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()
@staticmethod
def _process_webimage_entry(web_files_items, template_images):
# logger.error(f"_process_webimage_entry web_files_items : {web_files_items}")
# logger.error(f"_process_webimage_entry template_images : {template_images}")
def find_key_value(current_key, web_files_items):
for tv in web_files_items:
if tv['setting_key'] == current_key:
return tv['setting_value']
return None
logger.error(f"_process_webimage_entry template_images DATA : {template_images['data']}")
if template_images and template_images['data']:
indx = 0
for t in template_images['data']:
current_key = template_images['data'][indx]['id']
saved_value = find_key_value(current_key, web_files_items)
template_images['data'][indx]['curr_val'] = '' if saved_value is None else saved_value
if saved_value:
template_images['data'][indx]['default_val'] = saved_value
indx = indx + 1
return template_images
@staticmethod
def template_set_media(data):
try:
with db.session.begin():
validated_data = MyProductsService.validate_data(data, MyProductTemplateImageSchema())
token = validated_data.get('token')
uid = validated_data.get('uid')
file_uid = validated_data.get('file_uid')
image_id = validated_data.get('image_id')
member_data = Members.get_member_by_uid(uid)
member_id = member_data.id
product_id = validated_data.get('product_id')
product_subscription_uid = ''
product_data = Products.get_product_by_product_id(product_id)
# Check if this media belong
selectedFile = MembersWebfiles.get_member_webfiles_by_member_file_uid(member_id, file_uid)
if not selectedFile:
return {
"message": "Please provide valid file_uid",
"error_message": "Error - Please select a valid file UID",
"data": None,
"error": f"File with ID {file_uid} does not exist."
}, 400
# Check if image key
if image_id is None or image_id == '':
return {
"message": "Please provide valid image_id",
"error_message": "Error - Please select a valid image_id",
"data": None,
"error": f"File with ID {image_id} does not exist."
}, 400
memberSubscription = MembersProducts.get_member_product_by_product_member_id(member_id, product_id)
if not memberSubscription:
return {
"message": "Please provide valid product_id",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"Product with ID {product_id} does not exist."
}, 400
# make this file
file_url = (
MyProductsService.MEDIA_SERVER + "/" + selectedFile.file_group + "/" + str(
selectedFile.uid) + "/" + selectedFile.filename).lower()
product_subscription_uid = memberSubscription.uid
setting_value = file_url
subscription_uid = memberSubscription.uid
# with db.session.begin():
MembersProductsSettings.save_update_product_settings(member_id, subscription_uid, product_id,
image_id,
'WEBFILES', setting_value)
# Simulate processing
response_data = {
"file_url": file_url,
"product_id": product_id,
"subscription_uid": str(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()
+29 -95
View File
@@ -4,9 +4,7 @@ from werkzeug.security import generate_password_hash, check_password_hash
import datetime
import jwt
from app.config import Config
from app.models import OfficeUsers
from app.utils.logger import logger
from app.extensions import db
class OfficeAuthService:
@staticmethod
@@ -21,101 +19,37 @@ class OfficeAuthService:
"test": "test123"
}
logger.info('ENTER API:: login')
try:
with db.session.begin():
member = OfficeUsers.get_office_user_by_username(username)
password_hash = generate_password_hash(password)
logger.info("Password generated = > {}".format(password_hash))
# Check if the provided credentials are valid
if username in valid_credentials and password == valid_credentials[username]:
# Generate JWT token with 15 minutes expiration
payload = {
'sub': username, # Subject (typically user ID)
'iat': datetime.datetime.utcnow(), # Issued at
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=15), # Expiration (15 minutes)
'role': 'admin' if username == 'admin' else 'user' # Role based on username
}
if not member:
invalid_data = {
"error_message": "invalid username or password",
"message_key": "invalid_username_or_password",
}
return invalid_data, 401
user_id = member.id
member_password = member.password
logger.info("Current Password = > {}".format(member_password))
if str(member_password).strip() == 'password':
updateResult = OfficeUsers.set_office_user_password(user_id, username, password_hash)
logger.info(f"Password Update Result = > {updateResult} ")
member_password= password_hash
member = OfficeUsers.get_office_user_by_username(username) # reload office
# Get the secret key from config
secret_key = Config.JWT_SECRET_KEY
pass_check = check_password_hash(member.password, password)
logger.info("Password check: {}".format(pass_check))
if not member or not pass_check:
invalid_data = {
"error_message": "invalid username or password",
"message_key": "invalid_username_or_password",
}
return invalid_data , 401
else:
payload = {
'sub': username, # Subject (typically user ID)
'iat': datetime.datetime.utcnow(), # Issued at
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=15), # Expiration (15 minutes)
'role': 'admin' if username == 'admin' else 'user' # Role based on username
}
# Get the secret key from config
secret_key = Config.JWT_SECRET_KEY
# Generate the token
token = jwt.encode(payload, secret_key, algorithm='HS256')
# Return the token and user info
return {
'jwt_token': token,
'user': {
'firstname': member.firstname,
'lastname': member.lastname,
'email':'support@mermsemr.com',
'username': username,
'role': 'admin' if username == 'admin' else 'user'
},
'expires_in': 900 # 15 minutes in seconds
}
# # Check if the provided credentials are valid
# if username in valid_credentials and password == valid_credentials[username]:
# # Generate JWT token with 15 minutes expiration
# payload = {
# 'sub': username, # Subject (typically user ID)
# 'iat': datetime.datetime.utcnow(), # Issued at
# 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=15), # Expiration (15 minutes)
# 'role': 'admin' if username == 'admin' else 'user' # Role based on username
# }
#
# # Get the secret key from config
# secret_key = Config.JWT_SECRET_KEY
#
# # Generate the token
# token = jwt.encode(payload, secret_key, algorithm='HS256')
#
# # Return the token and user info
# return {
# 'jwt_token': token,
# 'user': {
# 'username': username,
# 'role': 'admin' if username == 'admin' else 'user'
# },
# 'expires_in': 900 # 15 minutes in seconds
# }
# else:
# # Return error for invalid credentials
# return {
# 'error': 'Invalid credentials',
# 'message': 'The username or password is incorrect'
# }, 401
except Exception as e:
logger.error(f"An error occurred while get_office_country_list data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
# Generate the token
token = jwt.encode(payload, secret_key, algorithm='HS256')
# Return the token and user info
return {
'jwt_token': token,
'user': {
'username': username,
'role': 'admin' if username == 'admin' else 'user'
},
'expires_in': 900 # 15 minutes in seconds
}
else:
# Return error for invalid credentials
return {
'error': 'Invalid credentials',
'message': 'The username or password is incorrect'
}, 401
@staticmethod
def verify_token(token):
-71
View File
@@ -1,71 +0,0 @@
from flask import jsonify
from app.utils.logger import logger
from app.api.services.base_service import BaseService
from sqlalchemy import func, desc
from datetime import datetime, timedelta, timezone
from app.extensions import db
from app.models import Country
class OfficeCountryService(BaseService):
@staticmethod
def get_office_country_list():
logger.info('ENTER API::get get_office_country_list')
try:
account_result_data =[]
account_result = Country.get_all_countries()
if account_result:
for t in account_result:
account_result_data.append({
'id': t.id,
'country_uid': t.uid,
'code': t.code,
'description': t.description,
'status': t.status,
'signup': t.signup,
})
account_result = {
"country_data":account_result_data,
}
logger.info('RETURN API::get office account view')
logger.info(account_result)
return account_result
except Exception as e:
logger.error(f"An error occurred while get_office_country_list data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
@staticmethod
def set_office_country_list(data):
logger.info('ENTER API::get set_office_country_list')
try:
val_type = data.get('val_type', '')
country_uid = data.get('country_uid', '')
code = data.get('code', '')
val = data.get('val', 0)
country_result=[]
with db.session.begin():
if val_type == 'STATUS':
country_result = Country.set_country_status(country_uid, code, val)
if val_type == 'SIGNUP':
country_result = Country.set_country_signup(country_uid, code, val)
account_result = {
"set_country_data":country_result.id,
"value": val,
"message": "Updated"
}
logger.info('RETURN API::get office account view')
logger.info(account_result)
return account_result
except Exception as e:
logger.error(f"An error occurred while get_office_country_list data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
+1 -64
View File
@@ -4,74 +4,11 @@ from app.api.services.base_service import BaseService
from sqlalchemy import func, desc
from datetime import datetime, timedelta, timezone
from app.extensions import db
from app.models import (MembersProducts, Products, Members)
from app.api.schemas.office_member_data import OfficeMemberDataSchema
from app.api.helpers.response_helper import ResponseHelper
from marshmallow import ValidationError
from app.models import MembersProducts, Products, Members, ProductsDetails, ProductsDetails, ProvisionActions
class OfficeCustomerService(BaseService):
@staticmethod
def update_customer_data(data):
try:
with db.session.begin():
logger.info(f"Incoming BackOffice Member data ==>>>> {data}")
validated_data = OfficeCustomerService.validate_data(data, OfficeMemberDataSchema())
member_uid = validated_data.get('member_uid')
member_account_name = validated_data.get('member_account_name')
member_firstname = validated_data.get('member_account_name')
member_lastname = validated_data.get('member_account_name')
member_full_address = validated_data.get('member_account_name')
member_email = validated_data.get('member_account_name')
member_phone = validated_data.get('member_account_name')
member_data = Members.get_member_by_uid(member_uid)
member_id = member_data.id
if member_data and member_id:
member_account_name = validated_data.get('member_account_name')
member_firstname = validated_data.get('member_account_name')
member_lastname = validated_data.get('member_account_name')
member_full_address = validated_data.get('member_account_name')
member_email = validated_data.get('member_account_name')
member_phone = validated_data.get('member_account_name')
profile_data = {
"member_account_name": member_account_name,
"member_firstname": member_firstname,
"member_lastname": member_lastname,
"member_full_address": member_full_address,
"member_email": member_email,
"member_phone": member_phone,
}
Members.set_office_update_profile(member_uid, profile_data)
response_data = {
"last_update": datetime.datetime.utcnow(),
"member_id": member_id
}
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()
@staticmethod
def get_customer_data(filters=None):
try:
+132 -702
View File
@@ -1,725 +1,155 @@
from urllib import request
from flask import jsonify
from app.config import settings
from app.utils.logger import logger
from app.api.services.base_service import BaseService
from sqlalchemy import func, desc
from app.models import MembersProducts, Products, Payments, Members, CustomTemplates, ProductsTemplates, MembersProfile, \
ProductsDetails, MembersWebfiles, Signup
from datetime import datetime, timedelta, timezone
from app.extensions import db
from app.models import MembersProducts, Products, Members, ProductsDetails, ProductsDetails, ProvisionActions
class OfficeDashboardService(BaseService):
@staticmethod
def get_payments_data(filters):
try:
if filters is None:
filters = {}
# Extract filters
option_name = filters.get('option_name')
# member_id = filters.get('member_id')
# Extract pagination parameters
page = int(filters.get('page', 1))
limit = int(filters.get('limit', 20))
# Ensure page and limit are valid
if page < 1:
page = 1
if limit < 1 or limit > 100:
limit = 20
membersPayList, total_count = Payments.get_all_payments(option_name, None, page, limit)
# Convert loans to dictionary format
member_sub_data = []
for subs in membersPayList:
member_sub_data.append({
'id': subs.id,
'member_id': subs.member_id,
'option_name': subs.option_name,
'option_type': subs.option_type,
'payment_uid': subs.payment_uid,
'amount': subs.amount * 0.01,
'status': subs.status,
'sub_start': subs.sub_start,
'sub_stop': subs.sub_stop,
"added": subs.added,
})
# Calculate total pages
total_pages = (total_count + limit - 1) // limit
response_data = {
'payments': member_sub_data,
'count': len(member_sub_data),
'pagination': {
'total_count': total_count,
'total_pages': total_pages,
'current_page': page,
'limit': limit,
'has_next': page < total_pages,
'has_prev': page > 1
}
}
return response_data
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
def get_subscriptions_data():
pass
@staticmethod
def get_dashboard_data():
try:
subscription_data = []
# now = datetime.now()
# start_of_week = now - timedelta(days=now.weekday())
# start_of_week = start_of_week.replace(hour=0, minute=0, second=0, microsecond=0)
#
# # Calculate 24 hours ago
# last_24_hours = datetime.now(timezone.utc) - timedelta(hours=24)
#
# # Loans this week
# loans_this_week = db.session.query(
# func.sum(Loan.initial_loan_amount)
# ).filter(
# Loan.created_at >= start_of_week
# ).scalar() or 0
#
# # Payments this week
# payments_this_week = db.session.query(
# func.count(Transaction.id)
# ).filter(
# Transaction.created_at >= start_of_week,
# Transaction.type == 'PAYMENT'
# ).scalar() or 0
#
# # Request summary for the last 24 hours
# eligibility_check_count = db.session.query(
# func.count(Transaction.id)
# ).filter(
# Transaction.type == TransactionType.ELIGIBILITY_CHECK.value,
# Transaction.created_at >= last_24_hours
# ).scalar() or 0
#
# select_offer_count = db.session.query(
# func.count(Transaction.id)
# ).filter(
# Transaction.type == TransactionType.SELECT_OFFER.value,
# Transaction.created_at >= last_24_hours
# ).scalar() or 0
#
# provide_loan_count = db.session.query(
# func.count(Transaction.id)
# ).filter(
# Transaction.type == TransactionType.PROVIDE_LOAN.value,
# Transaction.created_at >= last_24_hours
# ).scalar() or 0
#
# repayment_count = db.session.query(
# func.count(Transaction.id)
# ).filter(
# Transaction.type == TransactionType.REPAYMENT.value,
# Transaction.created_at >= last_24_hours
# ).scalar() or 0
#
# # Recent transactions (not limited to 24 hrs, just latest 15)
# recent_transactions = Transaction.query.order_by(
# Transaction.id.desc()
# ).limit(15).all()
#
# recent_transactions_data = [{
# 'id': t.id,
# 'transaction_id': t.transaction_id,
# 'account_id': t.account_id,
# 'type': t.type,
# 'channel': t.channel,
# 'created_at': t.created_at.isoformat() if t.created_at else None,
# 'updated_at': t.updated_at.isoformat() if t.updated_at else None
# } for t in recent_transactions]
#
# # Final response
# dashboard_data = {
# "loans": {
# "value": float(loans_this_week),
# "currency": "Naira",
# "currency_text": "₦",
# "text": "this week"
# },
# "payments": {
# "value": payments_this_week,
# "currency": "Naira",
# "currency_text": "₦",
# "text": "this week"
# },
# "request_summary": {
# "eligibility_check": {"Eligibility": eligibility_check_count},
# "select_offer": {"Offers": select_offer_count},
# "provide_loan": {"Loans": provide_loan_count},
# "repayment": {"Repayments": repayment_count}
# },
# "recent_transactions": recent_transactions_data
# }
subscription = MembersProducts.get_dash_recent_subscription(15)
if subscription:
subscription_data = [{
'id': t.id,
'uid': t.uid,
'product_id': t.product_id,
'internal_url': t.internal_url,
'external_url': t.external_url,
'dns_group': t.dns_group,
'status': t.status,
'added': t.added,
'primary_server': t.primary_server,
'provision_port': t.provision_port,
'updated': t.updated
} for t in subscription]
sub_count = MembersProducts.get_subscription_counts(0)
subscription_data = [{
'id': t.id,
'uid': t.uid,
'product_id': t.product_id,
'internal_url': t.internal_url,
'external_url': t.external_url,
'dns_group': t.dns_group,
'status': t.status,
'added': t.added,
'updated': t.updated
} for t in subscription]
dashboard_data = {
"subscription": subscription_data,
"signups": {
"currency": "Naira",
"currency_text": "\u20a6",
"text": "last 30 days",
"value": int(sub_count)
},
"payments": {
"currency": "Dollars",
"currency_text": "\u0024",
"text": "this week",
"value": 0
},
"subscription":subscription_data,
"loans": {
"currency": "Naira",
"currency_text": "\u20a6",
"text": "this week",
"value": 159999.0
},
"payments": {
"currency": "Naira",
"currency_text": "\u0024",
"text": "this week",
"value": 0
},
"request_summary": {
"eligibility_check": {
"Started": 6
},
"provide_loan": {
"Scheduled": 2
},
"repayment": {
"Processing": 0
},
"select_offer": {
"Completed": 3
}
}
}
"request_summary": {
"eligibility_check": {
"Started": 6
},
"provide_loan": {
"Scheduled": 2
},
"repayment": {
"Processing": 0
},
"select_offer": {
"Completed": 3
}
}
}
return dashboard_data
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
@staticmethod
def get_office_products(filters):
products = Products.get_user_product_list(0)
product_data = []
for t in products:
product_data.append({
'id': t.id,
'uid': t.uid,
'product_id': t.product_id,
'description': t.description,
'name': t.name,
'status': t.status,
'added': t.added.isoformat() if t.added else None,
'updated': t.updated.isoformat() if t.updated else None,
'banner': t.banner,
})
products_result = {
"products": product_data,
}
return products_result
@staticmethod
def get_office_product_detail(filters):
product_id = filters.get('product_id')
product_data = []
products = Products.get_product_by_product_id(product_id)
if products:
product_data = {
'id': products.id,
'uid': products.uid,
'product_id': products.product_id,
'description': products.description,
'name': products.name,
'status': products.status,
'added': products.added.isoformat() if products.added else None,
'updated': products.updated.isoformat() if products.updated else None,
'banner': products.banner,
}
product_details = []
productDetails = ProductsDetails.get_product_details_with_product_id(product_id)
if productDetails:
product_details = {
'product_detail_id': productDetails.id,
'product_id': productDetails.product_id,
'details': productDetails.details,
'sale_text': productDetails.sale_text,
'added': productDetails.added.isoformat() if productDetails.added else None,
}
products_result = {
"product_configuration": product_data,
"product_details": product_details,
}
return products_result
@staticmethod
def get_office_product_update(filters):
product_id = filters.get('product_id')
product_data = []
products = Products.get_product_by_product_id(product_id)
if products:
product_data = {
'id': products.id,
'uid': products.uid,
'product_id': products.product_id,
'description': products.description,
'name': products.name,
'status': products.status,
'added': products.added.isoformat() if products.added else None,
'updated': products.updated.isoformat() if products.updated else None,
'banner': products.banner,
}
product_details = []
productDetails = ProductsDetails.get_product_details_with_product_id(product_id)
if productDetails:
product_details = {
'product_detail_id': productDetails.id,
'product_id': productDetails.product_id,
'details': productDetails.details,
'sale_text': productDetails.sale_text,
'added': productDetails.added.isoformat() if productDetails.added else None,
}
products_result = {
"update_result": [],
}
return products_result
@staticmethod
def get_office_product_templates(filters):
# Extract filters
product_id = filters.get('product_id')
provision_name = filters.get('provision_name')
# Extract pagination parameters
page = int(filters.get('page', 1))
limit = int(filters.get('limit', 20))
# Ensure page and limit are valid
if page < 1:
page = 1
if limit < 1 or limit > 100:
limit = 20
templates = ProductsTemplates.get_template_for_office(product_id, provision_name, page, limit)
templates_data = []
if templates:
for t in templates:
templates_data.append({
'id': t.id,
'uid': t.uid,
'product_id': t.product_id,
'provision_name': t.provision_name,
'status': t.status,
'added': t.added.isoformat() if t.added else None,
})
templates_result = {
"templates": templates_data,
"product_options": []
}
return templates_result
@staticmethod
def get_office_custom_templates(filters):
logger.info("ENTER :: Getting office custom templates")
templates = CustomTemplates.get_custom_template_for_office(filters)
templates_data = []
if templates:
for t in templates:
templates_data.append({
'id': t.id,
'uid': t.uid,
'custom_id': t.custom_id,
'provision_name': t.provision_name,
'added': t.added.isoformat() if t.added else None,
})
templates_result = {
"templates": templates_data,
}
return templates_result
@staticmethod
def get_office_account_view(filters):
logger.info('ENTER API::get office account view')
try:
# member_uid = filters.member_uid
member_uid = filters.get('member_uid')
account_result = Members.get_member_by_uid(member_uid)
account_data = {
"id": account_result.id,
"uid": str(account_result.uid),
"username": account_result.username,
"country": account_result.country,
"added": account_result.added,
"email": account_result.email,
"account_name": account_result.account_name,
"firstname": account_result.firstname,
"lastname": account_result.lastname,
"trial_end": account_result.trial_end,
}
member_id = account_result.id
logger.info(f"member_id :: member_uid: {member_id} :: {member_uid} ")
# "profile_comp leted": account_result.profile_completed,
# "next_billing": account_result.next_billing,
membersSubList = MembersProducts.get_member_productlist_by_member_id(account_result.id)
member_sub_data = []
if membersSubList:
for subs in membersSubList:
member_sub_data.append({
'id': subs.id,
'member_id': subs.member_id,
'subscription_uid': str(subs.uid),
'product_id': subs.product_id,
'internal_url': subs.internal_url,
'external_url': subs.external_url,
'dns_group': subs.dns_group,
'status': subs.status,
'primary_server': subs.primary_server,
'provision_port': subs.provision_port,
'product_template': subs.product_template,
'custom_template': subs.custom_template,
'updated': subs.updated,
"added": subs.added,
})
member_payments = Payments.get_member_payments_by_member_id(account_result.id)
member_payments_data = []
for t in member_payments:
member_payments_data.append({
'id': t.id,
'uid': t.uid,
'option_name': t.option_name,
'option_type': t.option_type,
'payment_uid': t.payment_uid,
'amount': round(t.amount * 0.01, 2),
'status': t.status,
'added': t.added
})
account_profile_data = []
current_profile = MembersProfile.get_member_profile_by_member_id(member_id)
if current_profile is None:
account_profile_data = []
else:
account_profile_data = {
'id': current_profile.id,
'profile_uid': current_profile.uid,
'member_id': current_profile.member_id,
'practice': current_profile.practice,
'specialization': current_profile.specialization,
'url_name': current_profile.url_name
}
account_result = {
"account": account_data,
"account_profile": account_profile_data,
"subscriptions": member_sub_data,
"payments": member_payments_data
}
logger.info('RETURN API::get office account view')
logger.info(account_result)
return account_result
except Exception as e:
logger.error(f"An error occurred while getting cusomer data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
@staticmethod
def get_subscription_view_data(filters=None):
try:
if filters is None:
filters = {}
# Extract filters
subscription_uid = filters.get('subscription_uid')
member_sub = []
flavor = ''
template_name = ''
product_templates_data = []
templates_data = []
membersSubResult = MembersProducts.get_member_product_by_subscription_uid(subscription_uid)
if membersSubResult:
if membersSubResult.product_template:
templateData = ProductsTemplates.get_template_by_uid(str(membersSubResult.product_template))
if templateData:
flavor = templateData.flavor
template_name = templateData.name
member_sub = {
'id': membersSubResult.id,
'flavor': flavor,
'template_name': template_name,
'subscription_uid': str(membersSubResult.uid),
'member_id': membersSubResult.member_id,
'product_id': membersSubResult.product_id,
'internal_url': membersSubResult.internal_url,
'external_url': membersSubResult.external_url,
'dns_group': membersSubResult.dns_group,
'product_template': membersSubResult.product_template,
'primary_server': membersSubResult.primary_server,
'provision_port': membersSubResult.provision_port,
'custom_template': membersSubResult.custom_template,
'status': membersSubResult.status,
'updated': membersSubResult.updated,
"added": membersSubResult.added,
}
templates = CustomTemplates.get_custom_template_for_office(filters)
if templates:
for t in templates:
templates_data.append({
'id': t.id,
'uid': t.uid,
'custom_id': t.custom_id,
'provision_name': t.provision_name,
'added': t.added.isoformat() if t.added else None,
})
product_templates = ProductsTemplates.get_template_by_product_id(membersSubResult.product_id)
if product_templates:
for t in product_templates:
product_templates_data.append({
'id': t.id,
'template_uid': t.uid,
'product_id': t.product_id,
'provision_name': t.provision_name,
'added': t.added.isoformat() if t.added else None,
})
response_data = {
'subscription': member_sub,
'available_templates': product_templates_data,
'available_custom_templates': templates_data
}
return response_data
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
@staticmethod
def get_office_sidebar(filters):
try:
if filters is None:
filters = {}
# Extract filters
option_name = filters.get('option_name')
# member_id = filters.get('member_id')
# Extract pagination parameters
page = int(filters.get('page', 1))
limit = int(filters.get('limit', 20))
# Ensure page and limit are valid
if page < 1:
page = 1
if limit < 1 or limit > 100:
limit = 20
membersPayList, total_count = Payments.get_all_payments(option_name, None, page, limit)
# Convert loans to dictionary format
member_sub_data = []
for subs in membersPayList:
member_sub_data.append({
'id': subs.id,
'member_id': subs.member_id,
'option_name': subs.option_name,
'option_type': subs.option_type,
'payment_uid': subs.payment_uid,
'amount': subs.amount * 0.01,
'status': subs.status,
'sub_start': subs.sub_start,
'sub_stop': subs.sub_stop,
"added": subs.added,
})
recentLogin = Members.get_recent_member_login(10)
if recentLogin:
recent_login_data = []
for subs in recentLogin:
recent_login_data.append({
'member_id': subs.id,
'firstname': subs.firstname,
'lastname': subs.lastname,
'username': subs.username,
'member_uid': subs.uid,
"added": subs.added,
})
# Calculate total pages
total_pages = (total_count + limit - 1) // limit
recent_payment_summary = {
"approved": 0,
"verified": 0,
"failed": 0,
"total": 0
}
recent_deployment_summary = {
"pending": 0,
"started": 0,
"stuck": 0,
"completed": 0
}
system_url = [
{
"name": "AirPlay System",
"url": settings.SYSTEM_SERVERS_AIRPLAY
},
{
"name": "Kafka",
"url": settings.SYSTEM_SERVERS_KAFKA
},
{
"name": "Ansible",
"url": settings.SYSTEM_SERVERS_ANSIBLE
},
{
"name": "Int HaProxy",
"url": settings.SYSTEM_SERVERS_ANSIBLE
},
{
"name": "Provision Server",
"url": settings.SYSTEM_SERVERS_PROVISION
},
{
"name": "Event Manager",
"url": settings.SYSTEM_SERVERS_EVENT_MANAGER
},
{
"name": "Socket Server",
"url": settings.SYSTEM_SERVERS_SOCKET_MANAGER
},
]
response_data = {
'system_url': system_url,
'recent_payment_summary': recent_payment_summary,
'recent_deployment_summary': recent_deployment_summary,
'recent_login': recent_login_data,
'recent_signup': recent_login_data,
'recent_deployment_error': [],
}
return response_data
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
@staticmethod
def get_file_upload_data(filters):
try:
if filters is None:
filters = {}
# Extract filters
file_group = filters.get('file_group')
member_id = filters.get('member_id')
# Extract pagination parameters
page = int(filters.get('page', 1))
limit = int(filters.get('limit', 20))
# Ensure page and limit are valid
if page < 1:
page = 1
if limit < 1 or limit > 100:
limit = 20
fileListData, total_count = MembersWebfiles.get_all_webfiles(file_group, file_group, page, limit)
# Convert loans to dictionary format
member_sub_data = []
if fileListData:
for subs in fileListData:
member_sub_data.append({
'id': subs.id,
'file_uid': subs.uid,
'member_id': subs.member_id,
'member_uid': subs.member_uid,
'file_group': subs.file_group,
'filename': subs.filename,
'save_filename': subs.save_filename,
'file_type': subs.file_type,
'status': subs.status,
'file_size': subs.file_size,
'added': subs.added.isoformat() if subs.added else None,
'updated': subs.updated.isoformat() if subs.updated else None
})
# Calculate total pages
total_pages = (total_count + limit - 1) // limit
response_data = {
'file_list': member_sub_data,
'media_server': settings.MEDIA_SERVER,
'count': len(member_sub_data),
'pagination': {
'total_count': total_count,
'total_pages': total_pages,
'current_page': page,
'limit': limit,
'has_next': page < total_pages,
'has_prev': page > 1
}
}
return response_data
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
@staticmethod
def get_recent_account_data(filters):
try:
if filters is None:
filters = {}
# Extract pagination parameters
page = int(filters.get('page', 1))
limit = int(filters.get('limit', 20))
# Ensure page and limit are valid
if page < 1:
page = 1
if limit < 1 or limit > 100:
limit = 20
membersList, total_count = Members.get_all_member(None, None, 1, 30)
# Convert loans to dictionary format
member_data = []
for member in membersList:
member_data.append({
'id': member.id,
'username': member.username,
'email': member.email,
'firstname': member.firstname,
'lastname': member.lastname,
'country': member.country,
'member_uid': member.uid,
'profile_completed': member.profile_completed,
"added": member.added,
})
response_data = {
'members': member_data,
'count': 30,
'pagination': {
'total_count': total_count,
'total_pages': 1,
'current_page': page,
'limit': limit,
'has_next': page < 1,
'has_prev': page > 1
}
}
return response_data
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
@staticmethod
def get_recent_signup_data(filters):
try:
if filters is None:
filters = {}
# Extract pagination parameters
page = int(filters.get('page', 1))
limit = int(filters.get('limit', 20))
email = filters.get('email')
firstname = filters.get('firstname')
lastname = filters.get('lastname')
# Ensure page and limit are valid
if page < 1:
page = 1
if limit < 1 or limit > 100:
limit = 20
membersList, total_count = Signup.get_all_start_signup(email, firstname, lastname, page, limit)
# Convert loans to dictionary format
member_data = []
for member in membersList:
member_data.append({
'id': member.id,
'email': member.email,
'firstname': member.firstname,
'lastname': member.lastname,
'member_uid': member.uid,
'status': member.status,
"added": member.added,
})
response_data = {
'members': member_data,
'count': 30,
'pagination': {
'total_count': total_count,
'total_pages': 1,
'current_page': page,
'limit': limit,
'has_next': page < 1,
'has_prev': page > 1
}
}
return response_data
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
-140
View File
@@ -1,140 +0,0 @@
from flask import jsonify
from app.utils.logger import logger
from app.api.services.base_service import BaseService
from sqlalchemy import func, desc
from datetime import datetime, timedelta, timezone
from app.extensions import db
from app.models import OfficeUsers, CustomTemplates, MembersProducts, ProductsTemplates, MembersProductsRefresh
class OfficeTemplatesService(BaseService):
@staticmethod
def set_office_custom_template(data):
logger.info('set_office_custom_template')
try:
with db.session.begin():
subscrtiption_uid = data.get('subscrtiption_uid', '')
custom_id = data.get('custom_id', '')
membersSubResult = MembersProducts.get_member_product_by_subscription_uid(subscrtiption_uid)
if not membersSubResult:
return {
"message": "Invalid Subscription",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"Subscription with UID {subscrtiption_uid} does not exist."
}, 400
member_id = membersSubResult.member_id
logger.info(f'set_office_custom_template {member_id} {subscrtiption_uid} {custom_id}')
MembersProducts.set_member_product_custom_template(member_id, subscrtiption_uid, custom_id)
office_users_result = {
"set_office_custom_template": [],
}
return office_users_result
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
office_users_result = {
"error": f"An error occurred: {str(e)}",
}
return office_users_result
@staticmethod
def set_office_user_template(data):
logger.info('set_office_user_template')
try:
subscrtiption_uid = data.get('subscrtiption_uid', '')
template_uid = data.get('template_uid', '')
selectProduct = None
selectedTemplate = None
selectProduct = MembersProducts.get_member_product_by_subscription_uid(subscrtiption_uid)
if selectProduct:
selectedTemplate = ProductsTemplates.get_template_by_uid(template_uid)
if selectedTemplate is None or selectedTemplate is None:
return jsonify({
'error': 'Missing credentials',
'message': 'Invalid credentials',
}), 400
office_users_result = {
"set_office_user_template": [],
}
return office_users_result
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
office_users_result = {
"error": f"An error occurred: {str(e)}",
}
return office_users_result
@staticmethod
def create_custom_template(data):
logger.info('create_custom_template')
try:
custom_id = data.get('custom_id', '')
provision_name = data.get('provision_name', '')
similarName = CustomTemplates.get_template_by_custom_id(custom_id)
if not similarName and provision_name != '':
# with db.session.begin():
custom_data = CustomTemplates.create_template(custom_id, provision_name)
else:
custom_data = {
"error": "Possible duplicate"
}
office_users_result = {
"custom_data": custom_data,
}
return office_users_result
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
office_users_result = {
"error": f"An error occurred: {str(e)}",
}
return office_users_result
@staticmethod
def office_template_rebuild(data):
logger.info('office_template_rebuild')
try:
with db.session.begin():
subscription_uid = data.get('subscription_uid', '')
custom_id = data.get('custom_id', '')
membersSubResult = MembersProducts.get_member_product_by_subscription_uid(subscription_uid)
if not membersSubResult:
return {
"message": "Invalid Subscription",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"Subscription with UID {subscription_uid} does not exist."
}, 400
member_id = membersSubResult.member_id
product_id = membersSubResult.product_id
logger.info(f'office_template_rebuild {member_id} {subscription_uid} {product_id}')
# with db.session.begin():
plannedRefresh = MembersProductsRefresh.create_subscription_refresh(member_id, product_id,
subscription_uid)
office_rebuild_result = {
"office_template_rebuild": [],
}
return office_rebuild_result
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
office_rebuild_result = {
"error": f"An error occurred: {str(e)}",
}
return office_rebuild_result
-43
View File
@@ -1,43 +0,0 @@
from flask import jsonify
from app.utils.logger import logger
from app.api.services.base_service import BaseService
from sqlalchemy import func, desc
from datetime import datetime, timedelta, timezone
from app.extensions import db
from app.models import OfficeUsers
class OfficeUsersService(BaseService):
@staticmethod
def get_office_users(filters):
logger.info('get office users')
try:
office_users = OfficeUsers.get_office_users_list()
office_users_data = []
if office_users:
for t in office_users:
office_users_data.append({
'id': t.id,
'uid': t.uid,
'username': t.username,
'firstname': t.firstname,
'lastname': t.lastname,
'acc_level': t.acc_level,
'status': t.status,
'added': t.added.isoformat() if t.added else None
})
office_users_result = {
"office_users": office_users_data,
}
return office_users_result
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
office_users_result = {
"error": f"An error occurred: {str(e)}",
}
return office_users_result
+5 -12
View File
@@ -184,22 +184,15 @@ class ProductsService(BaseService):
}
return ResponseHelper.success(data=response_data)
activeRefresh = MembersProductsRefresh.get_active_refresh_by_subscription_uid(subscription_uid)
if activeRefresh:
return {
"message": "Invalid Refresh",
"error_message": "Current active refresh found- please wait for 2 to 5 minutes and try again",
"member_id":member_id,
"uid": member_data.uid,
}, 400
MembersProductsRefresh.create_subscription_refresh(member_id,product_id, subscription_uid)
# if memberSubscription.uid != subscription_uid :
plannedRefresh = MembersProductsRefresh.create_subscription_refresh(member_id,product_id, subscription_uid)
#products = MembersProducts.get_member_productlist_by_member_id(member_id)
# Simulate processing
response_data = {
"message": "Rebuild Planned - will be completed in 90 seconds",
"error_message": "",
"refresh_uid": plannedRefresh.uid,
"products_data": [],
"member_id":member_id,
"uid": member_data.uid,
}
+6 -32
View File
@@ -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 MembersPending, Members, Country, Signup
from app.models import MembersPending, Members
from app.api.helpers.response_helper import ResponseHelper
from werkzeug.security import generate_password_hash, check_password_hash
@@ -31,7 +31,6 @@ class RegisterService(BaseService):
SEND_EMAIL_FROM = Config.SEND_EMAIL_FROM
SEND_EMAIL_PASS = Config.SEND_EMAIL_PASS
THIS_SITE_URL = Config.THIS_SITE_URL
ALLOWED_SIGNUP_EMAIL_RESUSE = Config.ALLOWED_SIGNUP_EMAIL_RESUSE
@staticmethod
def encrypt_password(self, password):
@@ -61,7 +60,7 @@ class RegisterService(BaseService):
previousAcc = Members.get_member_by_username(username)
if previousAcc:
response_data = {
"error_message": "Please try another username!",
"error_message": "try another username ",
"error_message_key": "use_another_username",
}
return ResponseHelper.error(data=response_data)
@@ -123,21 +122,10 @@ class RegisterService(BaseService):
data = jwt.decode(verify_link, RegisterService.JWT_SECRET_KEY, algorithms=["HS256"])
except:
return jsonify({'status': 'INVALID', 'message': 'Link is invalid'}), 403
country_list = []
country_data = Country.get_signup_countries(1)
for subs in country_data:
country_list.append({
'id': subs.id,
'code': subs.code,
'uid': str(subs.uid),
'description': subs.description
})
country = {
"last_update": datetime.datetime.utcnow(),
"list": country_list,
"lists": [
"list": [
{"code": "US", "description": "United States"},
{"code": "CA", "description": "Canada"},
]
@@ -168,7 +156,7 @@ class RegisterService(BaseService):
@staticmethod
def start_account_register(data):
def process_request(data):
try:
with db.session.begin():
@@ -176,24 +164,10 @@ class RegisterService(BaseService):
# Simulate processing
firstname = validated_data.get('firstname')
lastname = validated_data.get('lastname')
email = str(validated_data.get('email')).lower()
# Keep a record on signup table
Signup.add_signup(firstname, lastname, email)
if RegisterService.ALLOWED_SIGNUP_EMAIL_RESUSE== '0':
logger.info(f"RegisterService.ALLOWED_SIGNUP_EMAIL_RESUSE=0")
if Members.get_member_by_email(email) != None:
return {
"message": "Please use another email",
"error_message": "Please use another email or reset password",
"data": None,
"error": f"Please use another email."
}, 400
email = validated_data.get('email')
regData = MembersPending.add_members_pending( firstname, lastname, email)
BaseService.send_verify_signup_mail(regData.email, regData.uid, regData.id, firstname, lastname)
# send_register_mail(regData.email, regData.uid, regData.id, firstname, lastname)
send_register_mail(regData.email, regData.uid, regData.id, firstname, lastname)
response_data = {
"pending_id": regData.id,
-180
View File
@@ -1,180 +0,0 @@
from flask import session, jsonify
from app.api.schemas.report import ReportSchema
# 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.extensions import db
from app.models import MembersProducts, Products, Members, Payments, 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.register import RegisterSchema
from app.api.schemas.products import ProductsSchema
from app.api.schemas.user import UserSchema
import datetime
import jwt
import random
from app.config import Config
class ReportService(BaseService):
@staticmethod
def process_report_topic_request(data):
try:
with db.session.begin():
logger.info(f"Incoming ReportService data ==>>>> {data}")
validated_data = ReportService.validate_data(data, UserSchema())
token = validated_data.get('token')
uid = validated_data.get('uid')
member_data = Members.get_member_by_uid(uid)
member_id = member_data.id
topics_data = ReportService.configured_report_types()
response_data = {
"last_update": datetime.datetime.utcnow(),
"member_id": member_id,
"topics": topics_data,
}
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()
@staticmethod
def configured_report_types():
data = {
"topics": [
{"name": 'Payments', "url": 'payment', "active": True, "list_order": 0},
{"name": 'Product', "url": 'product', "active": True, "list_order": 1},
{"name": 'System', "url": 'system', "active": True, "list_order": 2},
]
}
return data
@staticmethod
def process_report_topic_item(report_type, data):
try:
with db.session.begin():
logger.info(f"Incoming ReportService Item Data ==>>>> {data}")
validated_data = ReportService.validate_data(data, ReportSchema())
token = validated_data.get('token')
uid = validated_data.get('uid')
page = validated_data.get('page')
member_data = Members.get_member_by_uid(uid)
member_id = member_data.id
response_data =[]
if report_type == "PAYMENT":
member_payments = Payments.get_member_payments_by_member_id(member_id)
member_payments_data = []
for t in member_payments:
member_payments_data.append({
'id': t.id,
'uid': t.uid,
'option_name': t.option_name,
'option_type': t.option_type,
'payment_uid': t.payment_uid,
'amount': round(t.amount * 0.01, 2),
'currency': '$',
'status': t.status,
'added': t.added
})
response_data = {
"last_update": datetime.datetime.utcnow(),
"member_id": member_id,
"payment": member_payments_data,
}
if report_type == "PRODUCT":
sub_status = []
member_subs = MembersProducts.get_member_productlist_by_member_id(member_id)
for tt in member_subs:
sub_status.append({
'product_id': tt.product_id,
'product_name': "Name for - " + tt.product_id,
'added': tt.added,
'subscription_uid': tt.uid,
'status': tt.status,
'internal_url': tt.internal_url,
'dns_group': tt.dns_group,
})
logger.info(f"Member Product Sub Data ****** *****: {sub_status}")
response_data = {
"last_update": datetime.datetime.utcnow(),
"member_id": member_id,
"product": sub_status,
}
if report_type == "SYSTEM":
member_actions = MembersActions.get_recent_member_actions(member_id)
member_actions_data = []
if member_actions:
for t in member_actions:
member_actions_data.append({
'id': t.id,
'uid': t.uid,
'member_id': t.member_id,
'member_uid': t.member_uid,
'action_label': t.action_label,
'action_name': t.action_name,
'status_description': t.status_description,
'status': t.status,
'added': t.added,
'updated': t.updated
})
response_data = {
"last_update": datetime.datetime.utcnow(),
"member_id": member_id,
"system": member_actions_data,
}
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()
+2 -2
View File
@@ -100,8 +100,8 @@ class SubscriptionService(BaseService):
price_create_result = StripeIntegration.create_product(t.display_name, t.monthly)
logger.info(f"Inside Stripe_Product ===== : {price_create_result}")
if price_create_result:
SubscriptionOptions.set_stripe_product_id(t.uid,price_create_result['product_id']) # only relevant if it is USA
SubscriptionOptions.set_stripe_price_id(t.uid,price_create_result['price_id']) # only relevant if it is USA
SubscriptionOptions.set_stripe_product_id(t.uid,price_create_result['product_id'])
SubscriptionOptions.set_stripe_price_id(t.uid,price_create_result['price_id'])
res_options.append({
'option_id': t.id,
-291
View File
@@ -1,291 +0,0 @@
from flask import jsonify
from app.utils.logger import logger
from app.api.services.base_service import BaseService
from sqlalchemy import func, desc
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, PaymentsSession, \
Payments
from app.extensions import db
from app.api.integrations import StripeIntegration
import json
class SubscriptionsService(BaseService):
# def get_all_subscriptions(cls, product_id=None, member_id=None, page=1, limit=20):
@staticmethod
def get_subscription_data(filters=None):
try:
if filters is None:
filters = {}
# Extract filters
product_id = filters.get('product_id')
member_id = filters.get('member_id')
# Extract pagination parameters
page = int(filters.get('page', 1))
limit = int(filters.get('limit', 20))
# Ensure page and limit are valid
if page < 1:
page = 1
if limit < 1 or limit > 100:
limit = 20
membersSubList, total_count = MembersProducts.get_all_subscriptions(product_id, member_id, page, limit)
# Convert loans to dictionary format
member_sub_data = []
for subs in membersSubList:
member_sub_data.append({
'id': subs.id,
'subscription_uid': str(subs.uid),
'member_id': subs.member_id,
'product_id': subs.product_id,
'internal_url': subs.internal_url,
'external_url': subs.external_url,
'dns_group': subs.dns_group,
'primary_server': subs.primary_server,
'provision_port': subs.provision_port,
'status': subs.status,
'updated': subs.updated,
"added": subs.added,
})
# Calculate total pages
total_pages = (total_count + limit - 1) // limit
response_data = {
'subscriptions': member_sub_data,
'count': len(member_sub_data),
'pagination': {
'total_count': total_count,
'total_pages': total_pages,
'current_page': page,
'limit': limit,
'has_next': page < total_pages,
'has_prev': page > 1
}
}
return response_data
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
@staticmethod
def subscription_available_products(data):
try:
with db.session.begin():
validated_data = SubscriptionsService.validate_data(data, UserSchema())
token = validated_data.get('token')
uid = validated_data.get('uid')
member_data = Members.get_member_by_uid(uid)
if not member_data:
invalid_data = {
"error_message": "Member Data",
"message_key": "invalid_member",
}
return ResponseHelper.success(data=invalid_data)
# option_name
member_id = member_data.id
option_name = member_data.option_name
trial_name = "TRIAL-90"
res_options = []
sub_options = SubscriptionOptions.get_subscription_options(1)
for t in sub_options:
if t.stripe_product_id is None or t.stripe_product_id.strip() == "" or t.stripe_price_id is None or t.stripe_price_id.strip() == "":
price_create_result = StripeIntegration.create_product(t.display_name, t.monthly)
logger.info(f"Inside Stripe_Product ===== : {price_create_result}")
if price_create_result:
SubscriptionOptions.set_stripe_product_id(t.uid, price_create_result['product_id'])
SubscriptionOptions.set_stripe_price_id(t.uid, price_create_result['price_id'])
res_options.append({
'option_id': t.id,
'package_uid': t.uid,
'display_name': t.display_name,
'option_name': t.option_name,
'monthly': round(t.monthly * 0.01, 2),
'currency': '$',
'payment_form': 'card_payment_usd',
'stripe_product_id': t.stripe_product_id,
'stripe_price_id': t.stripe_price_id,
"items": SubscriptionsService.subscription_items_data(t.option_name),
'added': t.added.isoformat() if t.added else None,
'updated': t.updated.isoformat() if t.updated else None
})
subscription_products_data = {
"current_product": {
"display_name": trial_name if option_name is None else option_name,
"subs": [
'Post Jobs',
'advanced instructors search',
'invite candidates',
'post events',
'Cancel Anytime'
],
"next_payment": member_data.next_billing if member_data.next_billing!=None else member_data.trial_end,
},
'stripe_customer_id': member_data.stripe_customer_id,
"options": res_options
}
return ResponseHelper.success(data=subscription_products_data)
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
@staticmethod
def subscription_items_data(option_name):
items_data = SubscriptionOptionsItems.get_subscription_item(option_name)
res_options_items = []
for t in items_data:
res_options_items.append({
'description': t.description
})
# return ['Post Jobs 222', 'advanced instructors search', 'invite candidates', 'post events',
# 'Cancel anytime']
return res_options_items
@staticmethod
def subscription_session_start(data):
try:
with db.session.begin():
# logger.info(f"Incoming MyProduct data ==>>>> {data}")
validated_data = SubscriptionsService.validate_data(data, SubscriptionSession())
token = validated_data.get('token')
uid = validated_data.get('uid')
customerId = validated_data.get('customerId')
priceId = validated_data.get('priceId')
member_data = Members.get_member_by_uid(uid)
member_id = member_data.id
option_name = validated_data.get('option_name')
sub_option = SubscriptionOptions.get_subscription_options_by_option_name(option_name)
if sub_option is None:
logger.error(f"Invalid Option Name")
return []
stripe_session = StripeIntegration.create_checkout_session_subscription(priceId, customerId)
if 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)
else:
stripe_error = f"Stripe Returned {stripe_session}"
db.session.rollback()
return ResponseHelper.error(result_description=str(stripe_error))
#
# 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)
# if memberSubscription is not None:
# logger.info(f"Incoming MyProduct data ==>>>> {memberSubscription}")
# productDataStatus = memberSubscription.status
# product_subscription_uid = memberSubscription.uid
# product_subscription_external_url = memberSubscription.external_url
# product_subscription_internal_url = memberSubscription.internal_url
# Simulate processing
response_data = {
"stripe_session": stripe_session.url,
"member_id": member_id,
"uid": 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()
@staticmethod
def subscription_webhook_start(data):
try:
with db.session.begin():
hook_data = data["data"]["object"]
# logger.info(f"***** HOOK Data ALL ==>>>> {hook_data}")
# json_hook_output = json.dumps(hook_data["data"])
for key, value in hook_data.items():
logger.info(f"**************** Key: {key}, *********** Value: {value}")
data_id = hook_data["id"]
amount_subtotal = hook_data["amount_subtotal"]
logger.info(f"HOOK Result DATA ==>>>> {data_id} {amount_subtotal}")
currentPaymentsession = PaymentsSession.get_payment_session_with_session_id(data_id)
logger.info(f"HOOK currentPaymentsession ==>>>> {currentPaymentsession}")
if currentPaymentsession:
payment_data = {
"payment_uid": currentPaymentsession.uid,
"member_id": currentPaymentsession.member_id,
"option_name": currentPaymentsession.option_name,
"amount": amount_subtotal,
"option_type": "MAIN",
"next_billing_days": 30
}
logger.info(f"HOOK payment_data ==>>>> {payment_data}")
paymentAddResult = Payments.add_payment(payment_data["member_id"], payment_data["payment_uid"], payment_data["option_name"],
payment_data["amount"], payment_data["option_type"], payment_data["next_billing_days"])
logger.info(f"HOOK paymentAddResult next_billing ==>>>> {paymentAddResult.next_billing}")
logger.info(f"HOOK paymentAddResult id ==>>>> {paymentAddResult.id}")
logger.info(f"HOOK paymentAddResult payment_uid ==>>>> {paymentAddResult.payment_uid}")
if paymentAddResult:
Members.set_user_option_name(payment_data["member_id"], payment_data["option_name"])
Members.set_user_next_billing(payment_data["member_id"], paymentAddResult.next_billing)
# Simulate processing
response_data = {
"data_id": data_id,
"member_id": "",
"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()
-167
View File
@@ -1,167 +0,0 @@
from flask import session, jsonify
from app.api.schemas.report import ReportSchema
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, Payments, MembersActions
from app.api.helpers.response_helper import ResponseHelper
from app.api.schemas.user import UserSchema
import datetime
class SystemReportService(BaseService):
@staticmethod
def process_report_topic_request(data):
try:
with db.session.begin():
logger.info(f"Incoming SystemReportService data ==>>>> {data}")
validated_data = SystemReportService.validate_data(data, UserSchema())
token = validated_data.get('token')
uid = validated_data.get('uid')
member_data = Members.get_member_by_uid(uid)
member_id = member_data.id
topics_data = SystemReportService.configured_report_types()
response_data = {
"last_update": datetime.datetime.utcnow(),
"member_id": member_id,
"topics": topics_data,
}
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()
@staticmethod
def configured_report_types():
data = {
"topics": [
{"name": 'Payments', "url": 'payment', "active": True, "list_order": 0},
{"name": 'Product', "url": 'product', "active": True, "list_order": 1},
{"name": 'System', "url": 'system', "active": True, "list_order": 2},
]
}
return data
@staticmethod
def process_report_topic_item(report_type, data):
try:
with db.session.begin():
logger.info(f"Incoming ReportService Item Data ==>>>> {data}")
validated_data = SystemReportService.validate_data(data, ReportSchema())
token = validated_data.get('token')
uid = validated_data.get('uid')
page = validated_data.get('page')
member_data = Members.get_member_by_uid(uid)
member_id = member_data.id
response_data =[]
if report_type == "PAYMENT":
member_payments = Payments.get_member_payments_by_member_id(member_id)
member_payments_data = []
for t in member_payments:
member_payments_data.append({
'id': t.id,
'uid': t.uid,
'option_name': t.option_name,
'option_type': t.option_type,
'payment_uid': t.payment_uid,
'amount': round(t.amount * 0.01, 2),
'currency': '$',
'status': t.status,
'added': t.added
})
response_data = {
"last_update": datetime.datetime.utcnow(),
"member_id": member_id,
"payment": member_payments_data,
}
if report_type == "PRODUCT":
sub_status = []
member_subs = MembersProducts.get_member_productlist_by_member_id(member_id)
for tt in member_subs:
sub_status.append({
'product_id': tt.product_id,
'product_name': "Name for - " + tt.product_id,
'added': tt.added,
'subscription_uid': tt.uid,
'status': tt.status,
'internal_url': tt.internal_url,
'dns_group': tt.dns_group,
})
logger.info(f"Member Product Sub Data ****** *****: {sub_status}")
response_data = {
"last_update": datetime.datetime.utcnow(),
"member_id": member_id,
"product": sub_status,
}
if report_type == "SYSTEM":
member_actions = MembersActions.get_recent_member_actions(member_id)
member_actions_data = []
if member_actions:
for t in member_actions:
member_actions_data.append({
'id': t.id,
'uid': t.uid,
'member_id': t.member_id,
'member_uid': t.member_uid,
'action_label': t.action_label,
'action_name': t.action_name,
'status_description': t.status_description,
'status': t.status,
'added': t.added,
'updated': t.updated
})
response_data = {
"last_update": datetime.datetime.utcnow(),
"member_id": member_id,
"system": member_actions_data,
}
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()
+13 -139
View File
@@ -1,14 +1,11 @@
from flask import jsonify
from app.api.enums import KafkaMessage
from app.api.services import MyProductsService
from app.utils.logger import logger
from app.api.services.base_service import BaseService
from sqlalchemy import func, desc
from app.extensions import db
from app.models import MembersProductsSettings, MembersProducts, ProductsColorStyle, ProductsTemplates
from threading import Thread
import requests
from app.models import MembersProductsSettings
class WebContentsService(BaseService):
@@ -17,70 +14,28 @@ class WebContentsService(BaseService):
def get_web_contents_data(provision_uid):
try:
web_contents_data = {
"last_update": "0",
"site_title": "my-site-title",
"site_description": "This is the site description in the header",
"site_logo_text": "MY-SITE-LOGO",
"site_contact_email": "email@email.com",
"site_description": "This is site description in the header",
"site_logo_text": "MY-GOOD-LOGO",
"site_contact_email": "email@specialemail.com",
"site_contact_phone": "911 111 1111",
"site_keywords": "Health, Practioner, myPage, telemedicine, Software, Mobile App, Health Specialty, Startup, Creative, Digital Health",
"site_keywords": "Responsive, HTML5, DSAThemes, Landing, Software, Mobile App, SaaS, Startup, Creative, Digital Product",
"facebook": "myface.facebook.com",
"twitter": "mytwit.twitter.com",
"youtube": "myyou.youtube.com",
"banner_description": "We focus on your better health outcomes ",
"banner_text": "This is the main business text on the web page",
"banner_description": "Naira",
"footer_description": "Any text under the logo on the footer",
"about_description": "Naira",
"banner_text": "Banner title for your new website. Adjust as needed.",
"banner_description": "A brief overview of your banner title. Tailor the text to accurately reflect the interests and demographics of your audience.",
"banner_text": "AMEYE01 marketing that drives results for your business",
"banner_description": "Mauris donec ociis magnis sapien ipsum sagittis sapien tempor and volute gravida aliquet quaerat vitae",
"about_title": "This is about title section",
"about_description": "We are a team of dedicated general healthcare practitioners committed to providing compassionate, comprehensive care to patients and families in our community.",
"about_extra_1": "With years of experience in primary medicine, we focus on building lasting relationships with patients while addressing their complete health and wellness needs. ",
"about_extra_2": "Our practice welcomes patients of all ages and offers a full range of services from preventive care to chronic disease management. ",
"about_description": "About Description - Mauris donec ociis magnis sapien ipsum sagittis sapien tempor and volute gravida aliquet quaerat vitae",
"about_extra_1": "About Extra 1 - Mauris donec ociis magnis sapien ipsum sagittis sapien tempor and volute gravida aliquet quaerat vitae",
"about_extra_2": "About - Extra 2 -Mauris donec ociis magnis sapien ipsum sagittis sapien tempor and volute gravida aliquet quaerat vitae ",
"contact_title": "Questions? Let's Talk",
"contact_introduction": "Want to learn more about us, or speak with an expert? Let us know what you are looking for, and well get back to you right away.",
"internal_template_style": ''
}
# web_contents_data[""] = ""
# Do we have this subsction
membersSubResult = MembersProducts.get_member_product_by_subscription_uid(provision_uid)
if membersSubResult:
member_sub = {
'id': membersSubResult.id,
'subscription_uid': str(membersSubResult.uid),
'member_id': membersSubResult.member_id,
'product_id': membersSubResult.product_id,
'internal_url': membersSubResult.internal_url,
'external_url': membersSubResult.external_url,
'dns_group': membersSubResult.dns_group,
'product_template': membersSubResult.product_template,
'primary_server': membersSubResult.primary_server,
'provision_port': membersSubResult.provision_port,
'custom_template': membersSubResult.custom_template,
'status': membersSubResult.status,
'updated': membersSubResult.updated,
"added": membersSubResult.added,
"contact_introduction": "Want to learn more about us, or speak with an expert? Let us know what you are looking for and well get back to you right away",
}
selected_flavor = ''
logger.info(
f"membersSubResult.product_template *****{membersSubResult.product_template} provision_uid={provision_uid} ")
if membersSubResult.product_template:
selectedTemplate = ProductsTemplates.get_template_by_uid(str(membersSubResult.product_template))
if selectedTemplate:
selected_flavor = selectedTemplate.flavor
# BaseService.get_site_imges_data(provision_uid, membersSubResult.primary_server,
# membersSubResult.provision_port, selected_flavor)
if membersSubResult.colorstyle is not None and membersSubResult.colorstyle != '':
# is this a valid olor scheme
colorStyle = ProductsColorStyle.get_colorstyle_by_product_id_and_uid(membersSubResult.product_id,
membersSubResult.colorstyle)
if colorStyle and colorStyle.color_style != '':
web_contents_data["internal_template_style"] = colorStyle.color_style
# web_contents_data ={}
settings_data_result = MembersProductsSettings.get_product_settings_by_subscription_uid(provision_uid)
if settings_data_result:
@@ -90,89 +45,8 @@ class WebContentsService(BaseService):
else:
web_contents_data[t.settings_key.strip()] = t.setting_value.strip()
# The template set up
# web_contents_data["web_images"]=[]
cacheId = str(provision_uid).replace("-", "")
BaseService.write_cache_data("WEB_DATA",cacheId, web_contents_data)
return web_contents_data
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
@staticmethod
def get_web_trafic_data(data):
provision_uid = data.get('provision_uid', '')
country = data.get('country', '')
region = data.get('region', '')
city = data.get('city', '')
latitude = data.get('latitude', '')
longitude = data.get('longitude', '')
membersSubResult = MembersProducts.get_member_product_by_subscription_uid(provision_uid)
if not membersSubResult:
return {
"message": "Invalid Subscription",
"error_message": "Error - Please select a valid product to view",
"data": None,
"error": f"Subscription with UID {provision_uid} does not exist."
}, 400
member_id = membersSubResult.member_id
product_id = membersSubResult.product_id
try:
response_data = {
"provision_uid": provision_uid,
"member_id": member_id,
"product_id": product_id,
"country": country,
"region": region,
"city": city,
"latitude": latitude,
"longitude": longitude,
}
logger.error(f"Going for Thread ******************** ")
thread = Thread(target=MyProductsService.async_send_settings_refresh_to_kafka,
args=(response_data, provision_uid, KafkaMessage.SITE_TRAFFIC_DATA))
thread.start()
logger.error(f"After the Thread ******************** ")
return response_data
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
# @staticmethod
# def get_site_imges_data(provision_uid, primary_server, provision_port, selected_flavor):
# destination_server = "http://" + str(primary_server) + ":" + str(provision_port)
# api_url = destination_server + "/api/props"
# try:
# payload = {'provision_uid': provision_uid, 'flavor': selected_flavor}
# logger.info(f"api_url: {str(api_url)}")
# logger.info(f"selected_flavor: {str(selected_flavor)}")
#
# # Make the GET request
# res_data = []
# response = requests.get(api_url, params=payload)
# if response.status_code == 200:
# logger.info(f"Response Site Images: {res_data}")
# # Convert the JSON response to a Python dictionary
# res_data = response.json()
# logger.info(f"Response Site Images: {res_data}")
#
# response_data = {
# "provision_uid": provision_uid,
# "data": res_data,
# # "product_id": product_id,
# }
#
# return response_data
#
# except Exception as e:
# logger.error(f"An error occurred while get_site_imges_data data: {str(e)}", exc_info=True)
# return None
-34
View File
@@ -1,34 +0,0 @@
from flask import jsonify
from app.api.enums import KafkaMessage
from app.api.services import MyProductsService
from app.utils.logger import logger
from app.api.services.base_service import BaseService
from sqlalchemy import func, desc
from app.extensions import db
from threading import Thread
class WebsiteService(BaseService):
@staticmethod
def save_web_contact_data(data):
provision_uid = data.get('provision_uid', '')
city = data.get('city', '')
latitude = data.get('latitude', '')
longitude = data.get('longitude', '')
try:
response_data = {
"provision_uid": provision_uid,
"city": city,
"latitude": latitude,
"longitude": longitude,
}
return response_data
except Exception as e:
logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True)
return jsonify({"message": "Internal Server Error"}), 500
-8
View File
@@ -1,8 +0,0 @@
class MemberFileData:
member_id: int
member_uid: str
file_group: str
filename: str
save_filename: str
file_type: str
file_size: str
+53 -34
View File
@@ -1,10 +1,9 @@
import os
from datetime import timedelta
class Config:
"""Base configuration for Flask app"""
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY", "")
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY", "")
SWAGGER_URL = os.getenv("SWAGGER_URL", "/documentation")
API_URL = os.getenv("API_URL", "/swagger.json")
@@ -15,24 +14,21 @@ class Config:
THIS_SITE_URL = os.getenv("THIS_SITE_URL", "https://qa-panel.mermsemr.com")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "qOLBHLMpSTfFrG9TEwA")
# Email Server
SEND_EMAIL_FROM = os.environ.get("SEND_EMAIL_FROM", "message@chiefsoft.com")
SEND_EMAIL_PASS = os.environ.get("SEND_EMAIL_PASS", "may12002!")
#Email Server
SEND_EMAIL_FROM = os.environ.get("SEND_EMAIL_FROM","message@chiefsoft.com")
SEND_EMAIL_PASS = os.environ.get("SEND_EMAIL_PASS","may12002!")
# Database Configuration
DATABASE_USER = os.environ.get("DATABASE_USER", "merms_panel")
DATABASE_PASSWORD = os.environ.get("DATABASE_PASSWORD", "merms_panel")
DATABASE_HOST = os.environ.get("DATABASE_HOST", "10.20.30.60")
DATABASE_USER = os.environ.get("DATABASE_USER","merms_panel")
DATABASE_PASSWORD = os.environ.get("DATABASE_PASSWORD","merms_panel")
DATABASE_HOST = os.environ.get("DATABASE_HOST","10.20.30.60")
DATABASE_PORT = os.environ.get("DATABASE_PORT", 5432)
DATABASE_NAME = os.environ.get("DATABASE_NAME", "merms_panel")
DATABASE_NAME = os.environ.get("DATABASE_NAME","merms_panel")
# Database Connection
SQLALCHEMY_DATABASE_URI = f"postgresql+psycopg2://{DATABASE_USER}:{DATABASE_PASSWORD}@{DATABASE_HOST}:{DATABASE_PORT}/{DATABASE_NAME}"
SQLALCHEMY_TRACK_MODIFICATIONS = False
START_URL_PATTERN = os.environ.get("START_URL_PATTERN", ".devprov.mermsemr.com")
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY", "secret-key")
JWT_ACCESS_TOKEN_EXPIRES = os.getenv("JWT_ACCESS_TOKEN_EXPIRES", timedelta(hours=1))
@@ -40,37 +36,60 @@ class Config:
"JWT_REFRESH_TOKEN_EXPIRES", timedelta(days=30)
)
ALLOWED_SIGNUP_EMAIL_RESUSE = os.getenv("ALLOWED_SIGNUP_EMAIL_RESUSE", '0')
# KAFKA_BROKER = 'dev-events.simbrellang.net:9085'
KAFKA_BROKER = os.getenv("KAFKA_BROKER", "10.10.10.120:9092")
STRIPE_SUCCESS_URL = os.environ.get("STRIPE_SUCCESS_URL",
"https://qa-panel.mermsemr.com/subscription-success?session_id={CHECKOUT_SESSION_ID}")
STRIPE_CANCEL_URL = os.environ.get("STRIPE_CANCEL_URL", "https://qa-panel.mermsemr.com/subscriptio")
# SIMBRELLA_ENDPOINT_RAC_CHECKS = os.getenv("SIMBRELLA_ENDPOINT_RAC_CHECKS", "RACCheck")
VALID_APP_ID = os.getenv("SIMBRELLA_APP_ID", "app1")
VALID_API_KEY = os.getenv("SIMBRELLA_API_KEY", "test-api-key-12345")
SIMBRELLA_BASE_URL = os.getenv("SIMBRELLA_BASE_URL", "http://127.0.0.1:6337")
SIMBRELLA_ENDPOINT_RAC_CHECKS = os.getenv("SIMBRELLA_ENDPOINT_RAC_CHECKS","api/rac-check")
RAC_RESULT_accountStatus = os.environ.get("RAC_RESULT_accountStatus", "true")
RAC_RESULT_bvnValidated = os.environ.get("RAC_RESULT_bvnValidated", "true")
RAC_RESULT_creditBureauCheck = os.environ.get("RAC_RESULT_creditBureauCheck", "false")
RAC_RESULT_crmsCheck = os.environ.get("RAC_RESULT_crmsCheck", "true")
RAC_RESULT_hasLien = os.environ.get("RAC_RESULT_hasLien", "false")
RAC_RESULT_hasPastDueLoan = os.environ.get("RAC_RESULT_hasPastDueLoan", "false")
RAC_RESULT_hasSalaryAccount = os.environ.get("RAC_RESULT_hasSalaryAccount", "true")
RAC_RESULT_isWhitelisted = os.environ.get("RAC_RESULT_isWhitelisted", "true")
RAC_RESULT_noBouncedCheck = os.environ.get("RAC_RESULT_noBouncedCheck", "true")
rac_true_rules = [
"rule1_45day_sal",
"rule2_2m_sal",
"rule3_no_bounced_check",
"rule4_current_loan_payments",
"rule5_no_past_due_fadv_loan",
"rule6_no_past_due_other_loan",
"rule7_consistent_salary_amount",
"rule8_whitelisted",
"rule9_regular_account",
"rule10_bvn_validation",
"rule11_CRC_no_delinquency",
"rule12_CRMS_no_delinquency",
"rule13_BVN_ignore",
"rule14_no_lien",
"rule15_null_ignore"
]
rac_false_rules = [
]
rac_salary_payments = [
"salarypaymenT_1",
"salarypaymenT_2",
"salarypaymenT_3",
"salarypaymenT_4",
"salarypaymenT_5",
"salarypaymenT_6"
]
STRIPE_PRIV_KEY = os.getenv("STRIPE_PRIV_KEY", "WRONG_KEY_SUPPLIED")
UPLOAD_FOLDER = os.environ.get("UPLOAD_FOLDER", "/app/uploads/DEV")
MEDIA_SERVER = os.environ.get("MEDIA_SERVER", "https://media.mermsemr.com")
CACHE_SERVER = os.environ.get("CACHE_SERVER", "10.10.33.35")
CACHE_PORT = os.environ.get("CACHE_PORT", 6378)
CACHE_PASSWORD = os.environ.get("CACHE_PASSWORD",
"7f079034e166ecf52d82cbec9876e4dc8a154b0c37248f3fa1734d4eeab938d5")
CACHE_DEFAULT_EXPIRE = os.environ.get("CACHE_DEFAULT_EXPIRE", 21600)
SYSTEM_SERVERS_AIRPLAY = os.environ.get("SYSTEM_SERVERS_AIRPLAY", "http://10.10.10.121:8080/")
SYSTEM_SERVERS_KAFKA = os.environ.get("SYSTEM_SERVERS_KAFKA", "http://10.10.10.120:19000/")
SYSTEM_SERVERS_ANSIBLE = os.environ.get("SYSTEM_SERVERS_ANSIBLE", "http://172.16.4.90:3000")
SYSTEM_SERVERS_INT_HAPROXY = os.environ.get("SYSTEM_SERVERS_INT_HAPROXY", "http://172.16.4.99:5555/")
SYSTEM_SERVERS_PROVISION = os.environ.get("SYSTEM_SERVERS_PROVISION", "http://10.13.3.15:8094")
SYSTEM_SERVERS_EVENT_MANAGER = os.environ.get("SYSTEM_SERVERS_EVENT_MANAGER", "http:;//10.13.3.15:5005")
SYSTEM_SERVERS_SOCKET_MANAGER = os.environ.get("SYSTEM_SERVERS_SOCKET_MANAGER", "http:;//10.13.3.15:5006")
settings = Config()
+25 -19
View File
@@ -1,4 +1,16 @@
# from .customer import Customer
from .account import Account
# from .loan import Loan
# from .transaction import Transaction
# from .repayment import Repayment
# from .loan_charge import LoanCharge
# from .offer import Offer
# from .charge import Charge
# from .rac_checks import RACCheck
# from .loan_repayment_schedule import LoanRepaymentSchedule
# from .transaction_offers import TransactionOffer
# from .repayments_data import RepaymentsData
# from .salary import Salary
from .members import Members
from .products import Products
from .members_products import MembersProducts
@@ -9,27 +21,21 @@ from .provision_actions import ProvisionActions
from .password_reset import PasswordReset
from .member_product_refresh import MembersProductsRefresh
from .members_products_settings import MembersProductsSettings
from .members_profile import MembersProfile
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
from .payments import Payments
from .subscription_generative import SubscriptionGenerative
from .generative_results import GenerativeResults
from .office_users import OfficeUsers
from .custom_templates import CustomTemplates
from .products_colorstyle import ProductsColorStyle
from .country import Country
from .members_webfiles import MembersWebfiles
from .signup import Signup
from .products_contacts import ProductsContacts
__all__ = ['Members', 'Account', 'Products',
'MembersProducts', 'MembersActions', 'MembersPending', 'ProductsDetails','ProductsContacts',
'ProvisionActions', 'MembersProductsRefresh', 'MembersProductsSettings', 'Signup',
'PasswordReset', 'MembersProfile', 'SubscriptionOptions', 'SubscriptionOptionsItems',
'ProductsTemplates', 'ProductsColorStyle', 'Payments', 'PaymentsSession',
'SubscriptionGenerative', 'GenerativeResults',
'CustomTemplates', 'Country',
'OfficeUsers']
__all__ = ['Members','Customer', 'Account', 'Products',
'MembersProducts', 'MembersActions', 'MembersPending', 'ProductsDetails',
'ProvisionActions', 'MembersProductsRefresh','MembersProductsSettings',
'PasswordReset','MembersProfile','SubscriptionOptions','SubscriptionOptionsItems',
'ProductsTemplates','PaymentsSession',
'Loan', 'Transaction', 'Repayment',
'LoanCharge', 'Offer', 'Charge', 'RACCheck', 'LoanRepaymentSchedule',
'TransactionOffer', 'RepaymentsData', 'Salary']
-77
View File
@@ -1,77 +0,0 @@
from datetime import datetime, timezone, timedelta
from app.extensions import db
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
import logging
logger = logging.getLogger(__name__)
class Country(db.Model):
__tablename__ = 'country'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
uid = db.Column(db.String(150), nullable=False)
code = db.Column(db.String(2), nullable=False)
description = db.Column(db.String(100), nullable=False)
status = db.Column(db.Integer, nullable=False, default=0)
signup = db.Column(db.Integer, nullable=False, default=0)
added = db.Column(db.DateTime(timezone=True), server_default=func.now())
@classmethod
def get_signup_countries(cls, signup):
country_list = cls.query.filter_by(signup=signup).order_by(cls.description.asc()).all()
if not country_list:
return None
return country_list
@classmethod
def get_all_countries(cls):
country_list = cls.query.order_by(cls.description.asc()).all()
if not country_list:
return None
return country_list
@classmethod
def set_country_status(cls, country_uid, code, val):
logger.info(f" Data for set_country_status Data {country_uid} ,{code} {val}")
country_data = cls.query.filter_by(uid=str(country_uid), code=str(code)).first()
if not country_data:
return None
logger.info("UPDT::")
country_data.status = int(val)
return country_data
@classmethod
def set_country_signup(cls, country_uid, code, val):
logger.info(f" Data for set_country_signup Data {country_uid} ,{code} {val}")
country_data = cls.query.filter_by(uid=str(country_uid), code=str(code)).first()
if not country_data:
return None
logger.info("UPDT::")
country_data.signup = val
return country_data
def to_dict(self):
return {
"id": self.id,
"uid": str(self.uid),
"code": self.code,
"description": self.description,
"status": self.status,
"signup": self.signup,
"added": self.added.isoformat() if self.added else None
}
'''
CREATE TABLE country (
id SERIAL,
uid uuid DEFAULT uuid_generate_v4(),
code VARCHAR(2) UNIQUE NOT NULL,
description VARCHAR(100) UNIQUE NOT NULL,
status INT DEFAULT 0,
signup INT DEFAULT 0,
added timestamp without time zone DEFAULT now()
);
ALTER TABLE ONLY country
ADD CONSTRAINT country_id_key UNIQUE (id);
'''
-70
View File
@@ -1,70 +0,0 @@
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
from dateutil.relativedelta import relativedelta
import logging
from sqlalchemy import and_, or_, not_
from sqlalchemy.sql import func
import uuid
logger = logging.getLogger(__name__)
class CustomTemplates(db.Model):
__tablename__ = 'custom_templates'
id = db.Column(db.String, primary_key=True)
uid = db.Column(db.String, nullable=False)
custom_id = db.Column(db.String, nullable=False)
provision_name = db.Column(db.String, nullable=False)
added = db.Column(db.DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
@classmethod
def get_template_by_custom_id(cls, custom_id):
templates = cls.query.filter_by(custom_id=str(custom_id)).first()
if not templates:
return None
return templates
@classmethod
def create_template(cls, custom_id,provision_name):
custom_data = cls(
uid=str(uuid.uuid4()),
custom_id=custom_id,
provision_name=provision_name,
added=datetime.now(timezone.utc)
)
try:
logger.info(f" About to Insert Subscription Data {custom_data.custom_id} ")
db.session.add(custom_data)
db.session.flush()
except IntegrityError as err:
logger.error(f" Error inserting custom data {err} -- ")
raise ValueError(f"Database integrity error: {err}")
return custom_data
@classmethod
def get_custom_template_for_office(cls, filters):
templates = cls.query.all()
if not templates:
raise ValueError(f"Templates not found")
return templates
def to_dict(self):
return {
"id": self.id,
"uid": self.uid,
"custom_id": self.product_id,
"provision_name": self.name,
"added": self.added.isoformat() if self.added else None
}
def __repr__(self):
return f'<CustomTemplates {self.id}>'
-95
View File
@@ -1,95 +0,0 @@
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 GenerativeResults(db.Model):
__tablename__ = 'generative_results'
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)
var_name = db.Column(db.String(100), nullable=False)
subscription_uid = db.Column(db.String(100), nullable=False)
text_result = db.Column(db.String(14000), nullable=False)
status = db.Column(db.Integer, nullable=True, default=0)
added = db.Column(db.DateTime(timezone=True), server_default=func.now())
@classmethod
def get_subscription_generative_by_subscription_uid(cls, subscription_uid):
subscription_generative = cls.query.filter_by(subscription_uid=str(subscription_uid)).all()
if not subscription_generative:
return None
return subscription_generative
@classmethod
def get_subscription_generative_list_by_status(cls, status):
subscription_generative = cls.query.filter_by(status=status).all()
if not subscription_generative:
return None
return subscription_generative
@classmethod
def update_subscription_generative_status(cls, subscription_uid, status):
subscription_generative = cls.query.filter_by(subscription_uid=str(subscription_uid)).first()
if not subscription_generative:
logger.error(f"SubscriptionGenerative with Sub UID {subscription_uid} does not exist.")
return None
subscription_generative.status =status
return status
@classmethod
def create_generative_result(cls, member_id,product_id,var_name,subscription_uid,text_result):
# create_generative_result(member_id,product_id,var_name,subscription_uid,text_result)
logger.info(f"GenerativeResults Create::Data {member_id} ,{product_id} ,{var_name} , {subscription_uid},{text_result} ")
subscription_generative_data = cls(
uid=str(uuid.uuid4()),
member_id=member_id,
var_name=var_name,
text_result=text_result,
product_id=product_id,
subscription_uid=subscription_uid,
added=datetime.now(timezone.utc)
)
try:
logger.info(f" About to Insert GenerativeResults Data {subscription_generative_data.member_id} ")
db.session.add(subscription_generative_data)
db.session.commit()
except IntegrityError as err:
logger.error(f" Error inserting GenerativeResults data {err} -- ")
raise ValueError(f"Database integrity error: {err}")
return subscription_generative_data
def to_dict(self):
return {
'id': self.id,
'uid': self.uid,
'member_id': self.member_id,
'product_id': self.product_id,
'var_name': self.var_name,
'subscription_uid': self.subscription_uid,
'text_result': self.text_result,
'status': self.status,
'added': self.added
}
def __repr__(self):
return f'<GenerativeResults {self.id}>'
+261 -261
View File
@@ -1,261 +1,261 @@
# from datetime import datetime, timezone, timedelta
# from itertools import product
# from app.extensions import db
# from app.models.customer import Customer
# from app.models.account import Account
# 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
#
# logger = logging.getLogger(__name__)
#
#
# class Loan(db.Model):
# __tablename__ = 'loans'
#
# id = db.Column(
# db.Integer,
# primary_key=True,
# autoincrement=True,
# )
# customer_id = db.Column(db.String(50), nullable=False)
# transaction_id = db.Column(db.String(50), nullable=True)
# original_transaction = db.Column(db.String(50), nullable=True)
# account_id = db.Column(db.String(50), nullable=False)
# offer_id = db.Column(db.String(20), nullable=False)
# product_id = db.Column(db.String(20), nullable=True)
# collection_type = db.Column(db.String(20), nullable=True)
# current_loan_amount = db.Column(db.Float, nullable=True)
# initial_loan_amount = db.Column(db.Float, nullable=False)
# default_penalty_fee = db.Column(db.Float, default=0)
# continuous_fee = db.Column(db.Float, default=0)
# upfront_fee = db.Column(db.Float, nullable=True, default=0.0)
# repayment_amount = db.Column(db.Float, nullable=True, default=0.0)
# installment_amount = db.Column(db.Float, nullable=True, default=0.0)
# status = db.Column(db.String(20), default='pending')
# tenor = db.Column(db.Integer, nullable=True)
# due_date = db.Column(db.DateTime, 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())
# eligible_amount = db.Column(db.Float, nullable=True, default=0.0)
# disburse_date = db.Column(db.DateTime, nullable=True)
# disburse_verify = db.Column(db.DateTime, nullable=True)
# reference = db.Column(db.String(50), nullable=True)
# disburse_result = db.Column(db.String(10), nullable=True)
# disburse_description = db.Column(db.String(100), nullable=True)
# verify_result = db.Column(db.String(10), nullable=True)
# verify_description = db.Column(db.String(100), nullable=True)
#
# # customer = relationship(
# # "Customer",
# # primaryjoin="Customer.id == Loan.customer_id",
# # foreign_keys=[customer_id],
# # back_populates="loans",
# # )
#
# loan_charges = relationship(
# "LoanCharge",
# primaryjoin="LoanCharge.loan_id == Loan.id",
# foreign_keys="LoanCharge.loan_id",
# back_populates="loan",
# )
#
# loan_repayment_schedules = relationship(
# "LoanRepaymentSchedule",
# primaryjoin="LoanRepaymentSchedule.loan_id == Loan.id",
# foreign_keys="LoanRepaymentSchedule.loan_id",
# back_populates="loan",
# )
#
#
# @classmethod
# def create_loan(
# cls,
# customer_id,
# account_id,
# offer_id,
# product_id,
# initial_loan_amount,
# collection_type,
# transaction_id,
# original_transaction,
# upfront_fee,
# repayment_amount,
# installment_amount,
# tenor,
# eligible_amount,
# reference,
# status = "pending",
# ):
# # Check if customer exists
# customer = Customer.is_valid_customer(customer_id)
# if not customer:
# raise ValueError("Customer does not exist")
#
# now = datetime.now(timezone.utc)
# due_date = now + timedelta(days=tenor)
#
# # Create and save the loan
# loan = cls(
# customer_id = customer_id,
# account_id = account_id,
# offer_id = offer_id,
# product_id = product_id,
# collection_type = collection_type,
# transaction_id = transaction_id,
# original_transaction = original_transaction,
# initial_loan_amount = initial_loan_amount,
# current_loan_amount = initial_loan_amount,
# upfront_fee = upfront_fee,
# repayment_amount = repayment_amount,
# installment_amount = installment_amount,
# due_date=due_date,
# tenor = tenor,
# status = status,
# eligible_amount =eligible_amount,
# reference = reference,
# created_at=datetime.now(timezone.utc),
# updated_at=datetime.now(timezone.utc)
# )
#
# try:
# db.session.add(loan)
# except IntegrityError as err:
# raise ValueError(f"Database integrity error: {err}")
# return loan
#
# @classmethod
# def has_active_loans(cls, customer_id):
# active_loans = cls.query.filter_by(
# customer_id=customer_id,
# status='active'
# ).count()
#
# if active_loans > 0:
# return False
# return True
#
#
# @classmethod
# def get_customer_loan(cls, loan_id, customer_id):
# """
# Get customer's active loans by loan_id.
# """
# loan = cls.query.filter_by(id = loan_id, customer_id = customer_id).first()
# if not loan:
# raise ValueError(f"Loan with ID {loan_id} does not exist or does not belong to customer {customer_id}.")
# return loan
#
# @classmethod
# def get_customer_original_loan(cls, customer_id, original_transaction):
# """
# Get customer's original loan offer.
# """
# original_loan = cls.query.filter(and_( cls.customer_id ==customer_id, cls.original_transaction==original_transaction, cls.transaction_id==original_transaction )).first()
# if not original_loan:
# return None
#
# logger.info(f" get_customer_original_loan ==>>>> {original_loan}")
# return original_loan
#
# @classmethod
# def get_customer_last_loan(cls, customer_id):
# """
# Get customer's active loans.
# """
# logger.info(f"get_customer_last_loan [customer_id] ==>>>> {customer_id}")
# # loan = cls.query.filter_by( cls.customer_id == customer_id).first()
# loan = cls.query.filter(and_( cls.customer_id ==customer_id, cls.status=='active')).first()
#
# if not loan:
# return None
# # loan = {
# # "original_transaction":"",
# # "eligible_amount": 0,
# # "loan_amount": 0,
# # "customer_id": customer_id,
# # "transaction_id": "",
# # "resultDescription": "No Active Loan"
# # }
# logger.info(f" get_customer_last_loan ==>>>> {loan}")
# return loan
#
# @classmethod
# def get_active_loans_by_original_transaction(cls, original_transaction_id):
# """
# Get all active loans with the same original_transaction ID.
# """
#
# active_loans = cls.query.filter_by(
# original_transaction=original_transaction_id,
# # status='active'
# ).all()
#
# return active_loans
#
#
# @classmethod
# def update_status(cls, loan_id, status):
# """
# Update the status of the loan with the given loan_id.
# """
# # Retrieve loan
# loan = cls.query.get(loan_id)
#
# if not loan:
# raise ValueError(f"Loan with ID {loan_id} does not exist.")
#
# if loan.status == status:
# return
#
# # Update loan status and the updated_at timestamp
# loan.status = status
#
#
# @classmethod
# def get_daily_loan_count(cls, customer_id, product_id):
# """
# Returns the count of loans created today for a customer.
# """
#
# start_of_day = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
# end_of_day = start_of_day + timedelta(days=1)
#
# return cls.query.filter_by(
# customer_id=customer_id,
# product_id=product_id,
# ).filter(
# cls.created_at >= start_of_day,
# cls.created_at < end_of_day
# ).count()
#
#
# def to_dict(self):
# """
# Convert the Loan object to a dictionary format for JSON serialization.
# """
# return {
# 'debtId': self.id,
# 'transactionId': self.transaction_id,
# 'loanRef': self.reference,
# 'productId': self.product_id,
# 'initialLoanAmount': self.initial_loan_amount,
# 'currentLoanAmount': self.current_loan_amount,
# 'defaultPenaltyFee': self.default_penalty_fee,
# 'continuousFee': self.continuous_fee,
# 'collectionType': self.collection_type,
# 'upfrontFee': self.upfront_fee,
# 'repaymentAmount': self.repayment_amount,
# 'installmentAmount': self.installment_amount,
# 'status': self.status,
# 'tenor': self.tenor,
# 'dueDate': self.due_date.isoformat() if self.due_date else None,
# 'loanDate': self.created_at.isoformat() if self.created_at else None,
# }
#
# def __repr__(self):
# return f'<Loan {self.id}>'
from datetime import datetime, timezone, timedelta
from itertools import product
from app.extensions import db
from app.models.customer import Customer
from app.models.account import Account
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
logger = logging.getLogger(__name__)
class Loan(db.Model):
__tablename__ = 'loans'
id = db.Column(
db.Integer,
primary_key=True,
autoincrement=True,
)
customer_id = db.Column(db.String(50), nullable=False)
transaction_id = db.Column(db.String(50), nullable=True)
original_transaction = db.Column(db.String(50), nullable=True)
account_id = db.Column(db.String(50), nullable=False)
offer_id = db.Column(db.String(20), nullable=False)
product_id = db.Column(db.String(20), nullable=True)
collection_type = db.Column(db.String(20), nullable=True)
current_loan_amount = db.Column(db.Float, nullable=True)
initial_loan_amount = db.Column(db.Float, nullable=False)
default_penalty_fee = db.Column(db.Float, default=0)
continuous_fee = db.Column(db.Float, default=0)
upfront_fee = db.Column(db.Float, nullable=True, default=0.0)
repayment_amount = db.Column(db.Float, nullable=True, default=0.0)
installment_amount = db.Column(db.Float, nullable=True, default=0.0)
status = db.Column(db.String(20), default='pending')
tenor = db.Column(db.Integer, nullable=True)
due_date = db.Column(db.DateTime, 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())
eligible_amount = db.Column(db.Float, nullable=True, default=0.0)
disburse_date = db.Column(db.DateTime, nullable=True)
disburse_verify = db.Column(db.DateTime, nullable=True)
reference = db.Column(db.String(50), nullable=True)
disburse_result = db.Column(db.String(10), nullable=True)
disburse_description = db.Column(db.String(100), nullable=True)
verify_result = db.Column(db.String(10), nullable=True)
verify_description = db.Column(db.String(100), nullable=True)
# customer = relationship(
# "Customer",
# primaryjoin="Customer.id == Loan.customer_id",
# foreign_keys=[customer_id],
# back_populates="loans",
# )
loan_charges = relationship(
"LoanCharge",
primaryjoin="LoanCharge.loan_id == Loan.id",
foreign_keys="LoanCharge.loan_id",
back_populates="loan",
)
loan_repayment_schedules = relationship(
"LoanRepaymentSchedule",
primaryjoin="LoanRepaymentSchedule.loan_id == Loan.id",
foreign_keys="LoanRepaymentSchedule.loan_id",
back_populates="loan",
)
@classmethod
def create_loan(
cls,
customer_id,
account_id,
offer_id,
product_id,
initial_loan_amount,
collection_type,
transaction_id,
original_transaction,
upfront_fee,
repayment_amount,
installment_amount,
tenor,
eligible_amount,
reference,
status = "pending",
):
# Check if customer exists
customer = Customer.is_valid_customer(customer_id)
if not customer:
raise ValueError("Customer does not exist")
now = datetime.now(timezone.utc)
due_date = now + timedelta(days=tenor)
# Create and save the loan
loan = cls(
customer_id = customer_id,
account_id = account_id,
offer_id = offer_id,
product_id = product_id,
collection_type = collection_type,
transaction_id = transaction_id,
original_transaction = original_transaction,
initial_loan_amount = initial_loan_amount,
current_loan_amount = initial_loan_amount,
upfront_fee = upfront_fee,
repayment_amount = repayment_amount,
installment_amount = installment_amount,
due_date=due_date,
tenor = tenor,
status = status,
eligible_amount =eligible_amount,
reference = reference,
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc)
)
try:
db.session.add(loan)
except IntegrityError as err:
raise ValueError(f"Database integrity error: {err}")
return loan
@classmethod
def has_active_loans(cls, customer_id):
active_loans = cls.query.filter_by(
customer_id=customer_id,
status='active'
).count()
if active_loans > 0:
return False
return True
@classmethod
def get_customer_loan(cls, loan_id, customer_id):
"""
Get customer's active loans by loan_id.
"""
loan = cls.query.filter_by(id = loan_id, customer_id = customer_id).first()
if not loan:
raise ValueError(f"Loan with ID {loan_id} does not exist or does not belong to customer {customer_id}.")
return loan
@classmethod
def get_customer_original_loan(cls, customer_id, original_transaction):
"""
Get customer's original loan offer.
"""
original_loan = cls.query.filter(and_( cls.customer_id ==customer_id, cls.original_transaction==original_transaction, cls.transaction_id==original_transaction )).first()
if not original_loan:
return None
logger.info(f" get_customer_original_loan ==>>>> {original_loan}")
return original_loan
@classmethod
def get_customer_last_loan(cls, customer_id):
"""
Get customer's active loans.
"""
logger.info(f"get_customer_last_loan [customer_id] ==>>>> {customer_id}")
# loan = cls.query.filter_by( cls.customer_id == customer_id).first()
loan = cls.query.filter(and_( cls.customer_id ==customer_id, cls.status=='active')).first()
if not loan:
return None
# loan = {
# "original_transaction":"",
# "eligible_amount": 0,
# "loan_amount": 0,
# "customer_id": customer_id,
# "transaction_id": "",
# "resultDescription": "No Active Loan"
# }
logger.info(f" get_customer_last_loan ==>>>> {loan}")
return loan
@classmethod
def get_active_loans_by_original_transaction(cls, original_transaction_id):
"""
Get all active loans with the same original_transaction ID.
"""
active_loans = cls.query.filter_by(
original_transaction=original_transaction_id,
# status='active'
).all()
return active_loans
@classmethod
def update_status(cls, loan_id, status):
"""
Update the status of the loan with the given loan_id.
"""
# Retrieve loan
loan = cls.query.get(loan_id)
if not loan:
raise ValueError(f"Loan with ID {loan_id} does not exist.")
if loan.status == status:
return
# Update loan status and the updated_at timestamp
loan.status = status
@classmethod
def get_daily_loan_count(cls, customer_id, product_id):
"""
Returns the count of loans created today for a customer.
"""
start_of_day = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
end_of_day = start_of_day + timedelta(days=1)
return cls.query.filter_by(
customer_id=customer_id,
product_id=product_id,
).filter(
cls.created_at >= start_of_day,
cls.created_at < end_of_day
).count()
def to_dict(self):
"""
Convert the Loan object to a dictionary format for JSON serialization.
"""
return {
'debtId': self.id,
'transactionId': self.transaction_id,
'loanRef': self.reference,
'productId': self.product_id,
'initialLoanAmount': self.initial_loan_amount,
'currentLoanAmount': self.current_loan_amount,
'defaultPenaltyFee': self.default_penalty_fee,
'continuousFee': self.continuous_fee,
'collectionType': self.collection_type,
'upfrontFee': self.upfront_fee,
'repaymentAmount': self.repayment_amount,
'installmentAmount': self.installment_amount,
'status': self.status,
'tenor': self.tenor,
'dueDate': self.due_date.isoformat() if self.due_date else None,
'loanDate': self.created_at.isoformat() if self.created_at else None,
}
def __repr__(self):
return f'<Loan {self.id}>'
+91 -91
View File
@@ -1,91 +1,91 @@
# from datetime import datetime, timezone, timedelta
# from app.extensions import db
# from sqlalchemy.orm import relationship
# from app.utils.logger import logger
# from sqlalchemy.sql import func
#
#
# class LoanCharge(db.Model):
# __tablename__ = 'loan_charges'
#
# id = db.Column(db.Integer, primary_key=True, autoincrement=True)
# loan_id = db.Column(db.Integer, nullable=False)
# transaction_id = db.Column(db.String(50), nullable=True)
# code = db.Column(db.String(50), nullable=False)
# amount = db.Column(db.Float, default=0.0)
# percent = db.Column(db.Float, default=0.0)
# description = db.Column(db.Text, nullable=True)
# due = db.Column(db.Integer, nullable=False)
# due_date = db.Column(db.DateTime, 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())
# # loan = relationship(
# # "Loan",
# # primaryjoin="LoanCharge.loan_id == Loan.id",
# # foreign_keys=[loan_id],
# # back_populates="loan_charges",
# # )
#
# @classmethod
# def create_charges_for_loan(cls, loan_id, transaction_id, charges, referenced_amount = 0.0):
# """
# Create loan charges for a given loan.
#
# Args:
# loan_id (int): ID of the loan to associate charges with.
# charges (list): A list of dictionaries with keys:
# code (str), amount (float), percent (float), description (str), due (int)
# """
# # if not charges or not isinstance(charges, list):
# # raise ValueError("Charges must be a non-empty list of dictionaries")
#
# if loan_id is None:
# raise ValueError("loan_id cannot be None")
#
# loan_charges = []
# now = datetime.now(timezone.utc)
#
#
# subset_keys = ['interest', 'management', 'insurance', 'vat']
# for item in subset_keys:
# charge = charges[item]
# due_days = charge['due_days'] # getattr(charge, "due_days", 0)
# amount = charge['fee'] # getattr(charge, "fee", 0.0)
# percent = charge['rate'] # getattr(charge, "rate", 0.0)
# code = charge['code'] # getattr(charge, "code","")
# description = charge['description'] # getattr(charge, "description", "")
#
# charge_obj = cls(
# loan_id = loan_id,
# transaction_id = transaction_id,
# code = code,
# amount = round(amount, 2),
# percent = percent,
# description = description,
# due = due_days,
# due_date = now + timedelta(days=due_days),
# created_at=datetime.now(timezone.utc),
# updated_at=datetime.now(timezone.utc)
# )
#
# db.session.add(charge_obj)
# loan_charges.append(charge_obj)
#
# return loan_charges
#
#
#
# def to_dict(self):
# return {
# 'id': self.id,
# 'loanId': self.loan_id,
# 'transactionId': self.transaction_id,
# 'code': self.code,
# 'amount': self.amount,
# 'percent': self.percent,
# 'description': self.description,
# 'due': self.due,
# }
#
# def __repr__(self):
# return f"<LoanCharge {self.id} - Loan {self.loan_id} - {self.code}>"
from datetime import datetime, timezone, timedelta
from app.extensions import db
from sqlalchemy.orm import relationship
from app.utils.logger import logger
from sqlalchemy.sql import func
class LoanCharge(db.Model):
__tablename__ = 'loan_charges'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
loan_id = db.Column(db.Integer, nullable=False)
transaction_id = db.Column(db.String(50), nullable=True)
code = db.Column(db.String(50), nullable=False)
amount = db.Column(db.Float, default=0.0)
percent = db.Column(db.Float, default=0.0)
description = db.Column(db.Text, nullable=True)
due = db.Column(db.Integer, nullable=False)
due_date = db.Column(db.DateTime, 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())
# loan = relationship(
# "Loan",
# primaryjoin="LoanCharge.loan_id == Loan.id",
# foreign_keys=[loan_id],
# back_populates="loan_charges",
# )
@classmethod
def create_charges_for_loan(cls, loan_id, transaction_id, charges, referenced_amount = 0.0):
"""
Create loan charges for a given loan.
Args:
loan_id (int): ID of the loan to associate charges with.
charges (list): A list of dictionaries with keys:
code (str), amount (float), percent (float), description (str), due (int)
"""
# if not charges or not isinstance(charges, list):
# raise ValueError("Charges must be a non-empty list of dictionaries")
if loan_id is None:
raise ValueError("loan_id cannot be None")
loan_charges = []
now = datetime.now(timezone.utc)
subset_keys = ['interest', 'management', 'insurance', 'vat']
for item in subset_keys:
charge = charges[item]
due_days = charge['due_days'] # getattr(charge, "due_days", 0)
amount = charge['fee'] # getattr(charge, "fee", 0.0)
percent = charge['rate'] # getattr(charge, "rate", 0.0)
code = charge['code'] # getattr(charge, "code","")
description = charge['description'] # getattr(charge, "description", "")
charge_obj = cls(
loan_id = loan_id,
transaction_id = transaction_id,
code = code,
amount = round(amount, 2),
percent = percent,
description = description,
due = due_days,
due_date = now + timedelta(days=due_days),
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc)
)
db.session.add(charge_obj)
loan_charges.append(charge_obj)
return loan_charges
def to_dict(self):
return {
'id': self.id,
'loanId': self.loan_id,
'transactionId': self.transaction_id,
'code': self.code,
'amount': self.amount,
'percent': self.percent,
'description': self.description,
'due': self.due,
}
def __repr__(self):
return f"<LoanCharge {self.id} - Loan {self.loan_id} - {self.code}>"
+72 -72
View File
@@ -1,72 +1,72 @@
# from datetime import datetime, timezone
# from app.extensions import db
# from sqlalchemy.orm import relationship
# from dateutil.relativedelta import relativedelta
# from sqlalchemy.sql import func
#
# class LoanRepaymentSchedule(db.Model):
# __tablename__ = 'loan_repayment_schedules'
#
# id = db.Column(db.Integer, primary_key=True, autoincrement=True)
# loan_id = db.Column(db.Integer, nullable=False)
# transaction_id = db.Column(db.String(50), nullable=True)
# product_id = db.Column(db.String(20), nullable=True)
# installment_number = db.Column(db.Integer, nullable=False)
# due_date = db.Column(db.DateTime, nullable=False)
# installment_amount= db.Column(db.Float, default=0.0)
# total_repayment_amount = db.Column(db.Float, default=0.0)
# paid = db.Column(db.Boolean, default=False)
# paid_at = db.Column(db.DateTime, 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())
# # loan = relationship(
# # "Loan",
# # primaryjoin="LoanRepaymentSchedule.loan_id == Loan.id",
# # foreign_keys=[loan_id],
# # back_populates="loan_repayment_schedules",
# # )
#
#
# @classmethod
# def add_repayment_schedule(cls, loan, num_schedules, transaction_id):
# """
# Add repayment schedules for a given loan.
# """
# now = datetime.now(timezone.utc)
# schedules = []
#
# for i in range(num_schedules):
# due_date = now + relativedelta(months=i + 1)
# schedule = LoanRepaymentSchedule(
# loan_id=loan.id,
# installment_number=i + 1,
# due_date=due_date,
# total_repayment_amount = round(loan.repayment_amount, 2),
# installment_amount=round(loan.installment_amount, 2),
# product_id = loan.product_id,
# transaction_id = transaction_id,
# created_at=datetime.now(timezone.utc),
# updated_at=datetime.now(timezone.utc)
# )
#
# db.session.add(schedule)
# schedules.append(schedule)
#
# return schedules
#
# def to_dict(self):
# return {
# 'id': self.id,
# 'loanId': self.loan_id,
# 'installmentNumber': self.installment_number,
# 'dueDate': self.due_date.isoformat(),
# 'principalAmount': self.principal_amount,
# 'interestAmount': self.interest_amount,
# 'totalInstallment': self.total_installment,
# 'paid': self.paid,
# 'paidAt': self.paid_at.isoformat() if self.paid_at else None
# }
#
# def __repr__(self):
# return f'<LoanRepaymentSchedule Loan:{self.loan_id} Installment:{self.installment_number}>'
from datetime import datetime, timezone
from app.extensions import db
from sqlalchemy.orm import relationship
from dateutil.relativedelta import relativedelta
from sqlalchemy.sql import func
class LoanRepaymentSchedule(db.Model):
__tablename__ = 'loan_repayment_schedules'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
loan_id = db.Column(db.Integer, nullable=False)
transaction_id = db.Column(db.String(50), nullable=True)
product_id = db.Column(db.String(20), nullable=True)
installment_number = db.Column(db.Integer, nullable=False)
due_date = db.Column(db.DateTime, nullable=False)
installment_amount= db.Column(db.Float, default=0.0)
total_repayment_amount = db.Column(db.Float, default=0.0)
paid = db.Column(db.Boolean, default=False)
paid_at = db.Column(db.DateTime, 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())
# loan = relationship(
# "Loan",
# primaryjoin="LoanRepaymentSchedule.loan_id == Loan.id",
# foreign_keys=[loan_id],
# back_populates="loan_repayment_schedules",
# )
@classmethod
def add_repayment_schedule(cls, loan, num_schedules, transaction_id):
"""
Add repayment schedules for a given loan.
"""
now = datetime.now(timezone.utc)
schedules = []
for i in range(num_schedules):
due_date = now + relativedelta(months=i + 1)
schedule = LoanRepaymentSchedule(
loan_id=loan.id,
installment_number=i + 1,
due_date=due_date,
total_repayment_amount = round(loan.repayment_amount, 2),
installment_amount=round(loan.installment_amount, 2),
product_id = loan.product_id,
transaction_id = transaction_id,
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc)
)
db.session.add(schedule)
schedules.append(schedule)
return schedules
def to_dict(self):
return {
'id': self.id,
'loanId': self.loan_id,
'installmentNumber': self.installment_number,
'dueDate': self.due_date.isoformat(),
'principalAmount': self.principal_amount,
'interestAmount': self.interest_amount,
'totalInstallment': self.total_installment,
'paid': self.paid,
'paidAt': self.paid_at.isoformat() if self.paid_at else None
}
def __repr__(self):
return f'<LoanRepaymentSchedule Loan:{self.loan_id} Installment:{self.installment_number}>'
+2 -7
View File
@@ -30,12 +30,7 @@ class MembersProductsRefresh(db.Model):
updated = db.Column(db.DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
@classmethod
def get_active_refresh_by_subscription_uid(cls, subscription_uid):
refresh_product = cls.query.filter_by(subscription_uid=str(subscription_uid), status=0).all()
if not refresh_product:
return None
return refresh_product
@classmethod
@@ -51,7 +46,7 @@ class MembersProductsRefresh(db.Model):
)
try:
logger.info(f" About to Insert Subscription REfresh Data {subscription.member_id} ")
logger.info(f" About to Insert Subscription Data {subscription.member_id} ")
db.session.add(subscription)
db.session.flush()
except IntegrityError as err:
+13 -127
View File
@@ -1,11 +1,10 @@
from datetime import datetime, timezone, timedelta
from datetime import datetime, timezone
from app.extensions import db
from sqlalchemy.sql import func
from sqlalchemy.exc import IntegrityError
import uuid
from app.utils.logger import logger
class Members(db.Model):
__tablename__ = 'members'
@@ -20,56 +19,36 @@ class Members(db.Model):
email = db.Column(db.String(100), nullable=False)
account_name = db.Column(db.String(100), nullable=True)
firstname = db.Column(db.String(25), nullable=False)
lastname = db.Column(db.String(25), nullable=True)
lastname = db.Column(db.String(100), nullable=True)
country = db.Column(db.String(3), nullable=True)
profile_completed = db.Column(db.DateTime(timezone=False))
stripe_customer_id = db.Column(db.String(100), nullable=True)
option_name = db.Column(db.String(100), nullable=True)
next_billing = db.Column(db.DateTime(timezone=False))
trial_end = db.Column(db.DateTime(timezone=False))
last_login = db.Column(db.DateTime(timezone=False), server_default=func.now(), onupdate=func.now())
phone = db.Column(db.String(25), nullable=True)
full_address = db.Column(db.String(150), nullable=True)
profile_picture = db.Column(db.String(100), nullable=True)
# "account_id": self.account_id,
def to_dict(self):
return {
"id": self.id,
"member_id": self.id,
"uid": str(self.uid),
"profile_completed": self.profile_completed,
"username": self.username,
"username": self.account_id,
"account_id": self.username,
"password": self.password,
"country": self.country,
"phone": self.phone,
"full_address": self.full_address,
"loc": self.loc,
"status": self.status,
"added": self.added.isoformat() if self.added else None,
"updated": self.updated.isoformat() if self.updated else None,
"last_login": self.last_login.isoformat() if self.last_login else None,
"email": self.email,
"account_name": self.account_name,
"firstname": self.firstname,
"lastname": self.lastname,
'option_name': self.option_name,
"next_billing": self.next_billing,
"trial_end": self.trial_end,
"stripe_customer_id": self.stripe_customer_id,
"profile_picture": self.profile_picture,
"stripe_customer_id": self.stripe_customer_id
}
def __repr__(self):
return f'<Members {self.id} - {self.uid}>'
@classmethod
def get_member_by_email(cls, email):
member = cls.query.filter_by(email=str(email)).first()
if not member:
return None
return member
@classmethod
def get_member_by_username(cls, username):
member = cls.query.filter_by(username=str(username)).first()
@@ -80,6 +59,7 @@ class Members(db.Model):
@classmethod
def get_member_by_uid(cls, uid):
member = cls.query.filter_by(uid=str(uid)).first()
if not member:
logger.info(f"User UID = {uid} found")
return None
@@ -96,83 +76,19 @@ class Members(db.Model):
member.profile_completed = datetime.now(timezone.utc)
return member.profile_completed
@classmethod
def set_member_profile_picture(cls, uid, picture_uid):
logger.info(f"Set_Member_Profile_Picture UID = {uid} Picture_UID = {picture_uid} ")
member = cls.query.filter_by(uid=str(uid)).first()
if not member:
logger.info(f"Set_Member_Profile_Picture UID = {uid} Not Found**")
raise ValueError(f"Member with UID {uid} does not exist.")
member.profile_picture = picture_uid
logger.info(f"*** Member_Profile_Picture UID = {uid} Picture_Picture = {member.profile_picture} ")
return member
@classmethod
def set_member_update_profile(cls, uid, profile_data):
member = cls.query.filter_by(uid=str(uid)).first()
if not member:
logger.info(f"User UID = {uid} found")
raise ValueError(f"Member with UID {uid} does not exist.")
member.full_address = profile_data["full_address"]
member.account_name = profile_data["account_name"]
member.firstname = profile_data["firstname"]
member.lastname = profile_data["lastname"]
member.phone = profile_data["phone"]
member.updated = datetime.now(timezone.utc)
return member
@classmethod
def set_office_update_profile(cls, uid, profile_data):
member = cls.query.filter_by(uid=str(uid)).first()
if not member:
logger.info(f"User UID = {uid} found")
raise ValueError(f"Member with UID {uid} does not exist.")
member.full_address = profile_data["member_full_address"]
member.account_name = profile_data["member_account_name"]
member.firstname = profile_data["member_firstname"]
member.lastname = profile_data["member_lastname"]
member.phone = profile_data["member_phone"]
member.email = profile_data["member_email"]
member.updated = datetime.now(timezone.utc)
return member
@classmethod
def set_member_last_login(cls, uid):
member = cls.query.filter_by(uid=str(uid)).first()
if not member:
logger.info(f"User UID = {uid} found")
return None
member.last_login = datetime.now(timezone.utc)
return member.last_login
@classmethod
def add_member(cls, firstname, lastname, email, username, password, country, trials_days=90):
# Get the current date and time
current_date = datetime.now()
# Calculate the date "next_billing_days" days from now
trial_end = current_date + timedelta(days=trials_days)
def add_member(cls, firstname, lastname, email, username,password, country):
# Save the response
member_data = cls(
uid=str(uuid.uuid4()),
firstname=firstname,
lastname=lastname,
username=username,
username =username,
email=email,
country=country,
password=password,
trial_end=trial_end,
added=datetime.now(timezone.utc),
updated=datetime.now(timezone.utc)
)
@@ -183,9 +99,10 @@ class Members(db.Model):
raise ValueError(f"Database integrity error: {err}")
return member_data
@classmethod
def update_user_password(cls, reset_id, member_uid, member_id, new_passwprd_hash):
member = cls.query.filter_by(uid=str(member_uid), id=member_id).first()
member = cls.query.filter_by(uid=str(member_uid),id=member_id).first()
if not member:
raise ValueError(f"Reset with UID {member_uid} does not exist.")
@@ -194,33 +111,14 @@ class Members(db.Model):
@classmethod
def set_user_stripe_id(cls, member_uid, member_id, stripe_customer_id):
member = cls.query.filter_by(uid=str(member_uid), id=member_id).first()
member = cls.query.filter_by(uid=str(member_uid),id=member_id).first()
if not member:
raise ValueError(f"Member with UID {member_uid} does not exist.")
raise ValueError(f"Reset with UID {member_uid} does not exist.")
# Update stripe_customer_id
member.stripe_customer_id = stripe_customer_id
return stripe_customer_id
@classmethod
def set_user_option_name(cls, member_id, option_name):
member = cls.query.filter_by(id=member_id).first()
if not member:
raise ValueError(f"Member with ID {member_id} does not exist.")
# Update stripe_customer_id
member.option_name = option_name
return option_name
@classmethod
def set_user_next_billing(cls, member_id, next_billing):
member = cls.query.filter_by(id=member_id).first()
if not member:
raise ValueError(f"Member with ID {member_id} does not exist.")
# Update next_billing
member.next_billing = next_billing
return next_billing
@classmethod
def get_all_member(cls, email=None, username=None, page=1, limit=20):
@@ -244,16 +142,4 @@ class Members(db.Model):
offset = (page - 1) * limit
query = query.limit(limit).offset(offset)
return query.all(), total_count
@classmethod
def get_recent_member_login(cls, limit=10):
query = cls.query
logger.info(f"Get Recent Member Login")
# Order by created_at descending (newest first)
query = query.order_by(cls.last_login.desc())
query = query.limit(limit).offset(0)
return query.all()
return query.all(), total_count
+1 -21
View File
@@ -40,30 +40,10 @@ class MembersActions(db.Model):
member_actions = cls.query.filter_by(member_id=member_id).order_by(cls.id.desc()).limit(4).all()
if not member_actions:
return None
raise ValueError(f"No Member Actions")
return member_actions
@classmethod
def get_recent_member_calendar_actions_member_id(cls, member_id, limit):
# member_actions = cls.query.limit(4).all()
member_actions = cls.query.filter_by(member_id=member_id).order_by(cls.id.desc()).limit(limit).all()
if not member_actions:
return None
return member_actions
# '''
# merms_panel=# select * from members_actions limit 2;
# id | uid | member_id | member_uid | action_label | action_name | status_description | status | adde
# d | updated
# ----+--------------------------------------+-----------+--------------------------------------+------------------------+----------------------+--------------------+--------+---------------
# -------------+----------------------------
# 1 | 91f112f3-c8ad-4533-bfa7-117f8e8781b4 | 2 | f995061e-a36c-4648-a3fc-d18e3d93e353 | Systems Status Checks | system_status_checks | processing | 0 | 2025-07-20 18:
# 52:08.011359 | 2025-07-20 18:52:08.011359
# 2 | 7fa90e2d-d4d2-40fd-bbad-c18be69f8967 | 1 | 2493007e-ab59-428a-8d34-ce66c8dea5ac | Systems Status Checks | system_status_checks | processing | 0 | 2025-07-20 18:
# 52:08.093698 | 2025-07-20 18:52:08.093698
# (2 rows)
# '''
def to_dict(self):
"""
Convert the Loan object to a dictionary format for JSON serialization.
+29
View File
@@ -55,9 +55,38 @@ class MembersPending(db.Model):
@classmethod
def get_member_by_username(cls, username):
"""
Return an offer by its ID.
"""
member = cls.query.filter_by(username=str(username)).first()
if not member:
raise ValueError(f"Username = {username} not found")
return member
# {
# "email": "ameye@chiefsoft.com",
# "firstname": "Olusesan",
# "lastname": "Ameye",
# "isChecked": true
# }
'''
merms_panel=# \d members_pending
Table "public.members_pending"
Column | Type | Collation | Nullable | Default
-----------+-----------------------------+-----------+----------+---------------------------------------------
id | integer | | not null | nextval('members_pending_id_seq'::regclass)
uid | uuid | | | uuid_generate_v4()
firstname | character varying(35) | | not null |
lastname | character varying(35) | | not null |
email | character varying(35) | | not null |
status | integer | | | 0
added | timestamp without time zone | | | now()
updated | timestamp without time zone | | | now()
Indexes:
"members_pending_id_key" UNIQUE CONSTRAINT, btree (id)
merms_panel=#
'''
+6 -63
View File
@@ -30,12 +30,6 @@ class MembersProducts(db.Model):
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())
product_template= db.Column(db.String(100), nullable=True)
custom_template = db.Column(db.String(100), nullable=True)
primary_server = db.Column(db.String(100), nullable=True)
provision_port = db.Column(db.Integer, nullable=True, default=0)
colorstyle = db.Column(db.String(55), nullable=True)
# name = db.Column(db.String(100), nullable=False)
# description = db.Column(db.String(250), nullable=False)
@@ -47,15 +41,6 @@ class MembersProducts(db.Model):
back_populates="members_products",
)
@classmethod
def get_subscription_counts(cls, member_id):
subscription_count = cls.query.filter_by(
status=7
).count()
if not subscription_count:
return 0
return subscription_count
@classmethod
def get_member_productlist_by_member_id(cls, member_id):
member_products = cls.query.filter_by(member_id=str(member_id))
@@ -79,51 +64,11 @@ class MembersProducts(db.Model):
@classmethod
def get_member_product_by_subscription_uid(cls, subscription_uid):
member_product = cls.query.filter_by(uid=str(subscription_uid)).first()
member_product = cls.query.filter_by(subscription_uid=str(subscription_uid)).all()
if not member_product:
return None
return member_product
@classmethod
def get_member_product_by_internal_url(cls, internal_url):
member_product = cls.query.filter_by(internal_url=str(internal_url)).all()
if not member_product:
return None
return member_product
@classmethod
def set_member_product_colorstyle(cls, member_id, product_id, colorstyle):
member_product = cls.query.filter_by(member_id=str(member_id), product_id=str(product_id)).first()
if not member_product:
return None
member_product.colorstyle = colorstyle
return colorstyle
@classmethod
def set_member_product_template(cls, member_id, product_id, product_template):
member_product = cls.query.filter_by(member_id=str(member_id), product_id=str(product_id)).first()
if not member_product:
return None
member_product.product_template = product_template
return product_template
@classmethod
def set_member_product_custom_template(cls, member_id, uid, custom_template):
member_product = cls.query.filter_by(member_id=str(member_id), uid=str(uid)).first()
if not member_product:
return None
logger.info(f'ACTION:::set_member_product_custom_template {member_id} {uid} {custom_template}')
member_product.custom_template = custom_template
return custom_template
@classmethod
def set_member_product_external_url(cls, member_id, product_id, external_url):
member_product = cls.query.filter_by(member_id=str(member_id), product_id=str(product_id)).first()
if not member_product:
return None
member_product.external_url = external_url
return external_url
@classmethod
def create_subscription(cls, member_id ,product_id,status,internal_url):
@@ -185,22 +130,20 @@ class MembersProducts(db.Model):
# return 0
def to_dict(self):
"""
Convert the Loan object to a dictionary format for JSON serialization.
"""
return {
'id': self.id,
'uid': self.uid,
'member_id': self.member_id,
# 'name': self.products.name,
# 'description': self.products.description,
'product_id': self.product_id,
'internal_url': self.internal_url,
'external_url': self.external_url,
'dns_group': self.dns_group,
'status': self.status,
'added': self.added,
'primary_server': self.primary_server,
'provision_port': self.provision_port,
'product_template': self.product_template,
'custom_template': self.custom_template,
'colorstyle': self.colorstyle,
'updated': self.updated
}
-50
View File
@@ -87,30 +87,6 @@ class MembersProductsSettings(db.Model):
raise ValueError(f"Database integrity error: {err}")
return product_settings
@classmethod
def create_generative_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.commit()
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
@@ -120,17 +96,8 @@ class MembersProductsSettings(db.Model):
raise ValueError(f"Reset with ID {members_products_settings_id} does not exist.")
update_p.setting_value = setting_value
# db.session.commit()
return
@classmethod
def get_member_websettings_by_member_setting_type(cls, member_id , setting_type):
setting_type_list = cls.query.filter_by(member_id=str(member_id), setting_type=str(setting_type)).all()
if not setting_type_list:
return None
return setting_type_list
@classmethod
def save_update_product_settings(cls, member_id,subscription_uid,product_id,settings_key,setting_type,setting_value ):
@@ -151,23 +118,6 @@ class MembersProductsSettings(db.Model):
cls.create_settings_entry(member_id,subscription_uid,product_id,settings_key,setting_type,setting_value)
return 0
@classmethod
def save_generative_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:
logger.info(f"*Block Refresh If key is already there ******* ")
else:
cls.create_generative_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.
+2 -12
View File
@@ -26,7 +26,6 @@ class MembersProfile(db.Model):
practice = db.Column(db.String(100), nullable=False)
specialization = db.Column(db.String(100), nullable=False)
introduction = db.Column(db.String(3500), nullable=True)
url_name = db.Column(db.String(25), nullable=True)
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())
@@ -44,13 +43,6 @@ class MembersProfile(db.Model):
return None
return member_profile
@classmethod
def get_any_member_profile_by_url_name(cls, url_name):
member_profile = cls.query.filter_by(url_name=str(url_name)).first()
if not member_profile:
return None
return member_profile
@classmethod
def get_member_product_by_product_member_id(cls, member_id, product_id):
@@ -61,7 +53,7 @@ class MembersProfile(db.Model):
@classmethod
def create_member_profile(cls, member_id ,practice,specialization,introduction,url_name):
def create_member_profile(cls, member_id ,practice,specialization,introduction):
# Create the subscription
'''
merms_panel=# select * from members_profile;
@@ -70,14 +62,13 @@ class MembersProfile(db.Model):
(0 rows)
'''
logger.info(f" Data for Profile Data {member_id} ,{practice} ,{specialization}, {introduction} {url_name} ")
logger.info(f" Data for Profile Data {member_id} ,{practice} ,{specialization}, {introduction} ")
profile_data = cls(
uid=str(uuid.uuid4()),
member_id=member_id,
practice=practice,
specialization=specialization,
introduction=introduction,
url_name = url_name,
added=datetime.now(timezone.utc),
updated=datetime.now(timezone.utc)
)
@@ -101,7 +92,6 @@ class MembersProfile(db.Model):
'practice': self.practice,
'specialization': self.specialization,
'introduction': self.dns_group,
'url_name': self.url_name,
'added': self.added,
'updated': self.updated
}
-148
View File
@@ -1,148 +0,0 @@
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
from app.api.types.data_types import MemberFileData
import uuid
logger = logging.getLogger(__name__)
class MembersWebfiles(db.Model):
__tablename__ = 'members_webfiles'
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)
member_uid = db.Column(db.String(100), nullable=False)
file_group = db.Column(db.String(25), nullable=False)
filename = db.Column(db.String(100), nullable=False)
save_filename = db.Column(db.String(100), nullable=False)
file_type = db.Column(db.String(50), nullable=False)
status = db.Column(db.Integer, nullable=True, default=1)
file_size = 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())
@classmethod
def create_file_profile(cls, file_data: MemberFileData):
logger.info(
f"File Data {file_data.member_id} {file_data.member_uid} {file_data.file_group} {file_data.filename} {file_data.save_filename} {file_data.file_type} {file_data.file_size} ")
file_uid = str(uuid.uuid4())
file_save_data = cls(
uid=str(file_uid),
member_id=file_data.member_id,
member_uid=file_data.member_uid,
file_group=file_data.file_group,
filename=file_data.filename,
save_filename=file_data.save_filename,
file_type=file_data.file_type,
file_size=file_data.file_size,
added=datetime.now(timezone.utc),
updated=datetime.now(timezone.utc)
)
try:
logger.info(f"About to Insert Members File Data {file_data.member_id} ")
db.session.add(file_save_data)
db.session.commit()
# db.session.flush()
except IntegrityError as err:
logger.error(f" Error inserting file_save_data data {err} -- ")
raise ValueError(f"Database integrity error: {err}")
save_result = {
'file_uid': file_uid
}
return save_result, file_uid
@classmethod
def get_member_webfiles_by_member_id(cls, member_id):
member_webfile = cls.query.filter_by(member_id=str(member_id), file_group='WEBSITE').order_by(
cls.added.desc()).all()
if not member_webfile:
return None
return member_webfile
@classmethod
def get_member_webfiles_by_member_file_uid(cls, member_id, file_uid):
member_webfile = cls.query.filter_by(member_id=str(member_id), uid=str(file_uid)).first()
if not member_webfile:
return None
return member_webfile
@classmethod
def get_member_webfiles_by_file_uid(cls, file_uid):
member_webfile = cls.query.filter_by(uid=str(file_uid)).first()
if not member_webfile:
return None
return member_webfile
# @classmethod
# def get_member_webfiles_by_member_file_group(cls, member_id , file_group):
# member_webfile = cls.query.filter_by(member_id=str(member_id), web_files_list=str(file_group)).all()
#
# if not member_webfile:
# return None
# return member_webfile
@classmethod
def get_all_webfiles(cls, file_group=None, member_id=None, page=1, limit=20):
query = cls.query
logger.info(f"Get all payments back")
if member_id:
query = query.filter(cls.member_id == member_id)
if file_group:
query = query.filter(cls.file_group == file_group)
# Order by created_at descending (newest first)
query = query.order_by(cls.added.desc())
# Get total count before pagination
total_count = query.count()
# Apply pagination
offset = (page - 1) * limit
query = query.limit(limit).offset(offset)
return query.all(), total_count
def to_dict(self):
"""
Convert the Loan object to a dictionary format for JSON serialization.
"""
return {
'id': self.id,
'uid': self.uid,
'member_id': self.member_id,
'member_uid': self.member_uid,
'file_group': self.file_group,
'filename': self.filename,
'save_filename': self.save_filename,
'file_type': self.file_type,
'status': self.status,
'file_size': self.file_size,
'added': self.added,
'updated': self.updated
}
def __repr__(self):
return f'<MembersWebfiles {self.id}>'
+94 -94
View File
@@ -1,94 +1,94 @@
# 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
#
# class Offer(db.Model):
# __tablename__ = 'offers'
#
# 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",
# # )
#
# @classmethod
# def get_all_offers(cls):
# """
# Return all offers in dictionary format.
# """
# offers = cls.query.all()
#
# if not offers:
# raise ValueError(f"No available offers")
# return offers
#
# @classmethod
# def is_valid_offer(cls, offer_id):
# offer = cls.query.filter_by(id=str(offer_id)).first()
#
#
# 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 {
# "offerId": self.id,
# "productId": self.product_id,
# "minAmount": self.min_amount,
# "maxAmount": self.max_amount,
# "tenor": self.tenor,
# "interest_rate": self.interest_rate,
# "management_rate": self.management_rate,
# "insurance_rate": self.insurance_rate,
# "vat_rate": self.vat_rate,
# "maxDailyLoans": self.max_daily_loans,
# "maxActiveLoans": self.max_active_loans,
# "maxLifeLoans": self.max_life_loans
#
# }
#
# def __repr__(self):
# return f'<LoanOffer {self.id}>'
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
class Offer(db.Model):
__tablename__ = 'offers'
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",
# )
@classmethod
def get_all_offers(cls):
"""
Return all offers in dictionary format.
"""
offers = cls.query.all()
if not offers:
raise ValueError(f"No available offers")
return offers
@classmethod
def is_valid_offer(cls, offer_id):
offer = cls.query.filter_by(id=str(offer_id)).first()
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 {
"offerId": self.id,
"productId": self.product_id,
"minAmount": self.min_amount,
"maxAmount": self.max_amount,
"tenor": self.tenor,
"interest_rate": self.interest_rate,
"management_rate": self.management_rate,
"insurance_rate": self.insurance_rate,
"vat_rate": self.vat_rate,
"maxDailyLoans": self.max_daily_loans,
"maxActiveLoans": self.max_active_loans,
"maxLifeLoans": self.max_life_loans
}
def __repr__(self):
return f'<LoanOffer {self.id}>'
-87
View File
@@ -1,87 +0,0 @@
from datetime import datetime, timezone, timedelta
from itertools import product
from app.extensions import db
from app.models.customer import Customer
from app.models.account import Account
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 json
logger = logging.getLogger(__name__)
class OfficeUsers(db.Model):
__tablename__ = 'office_users'
id = db.Column(
db.Integer,
primary_key=True,
autoincrement=True,
)
uid = db.Column(db.String(150), nullable=True)
username = db.Column(db.String(25), nullable=False)
password = db.Column(db.String(250), nullable=False)
firstname = db.Column(db.String(25), nullable=False)
lastname = db.Column(db.String(25), nullable=False)
acc_level = db.Column(db.Integer, nullable=True, default=10)
status = db.Column(db.Integer, nullable=True, default=0)
added = db.Column(db.DateTime(timezone=True), server_default=func.now())
@classmethod
def get_office_users_list(cls):
users_list = cls.query.all()
if not users_list:
raise ValueError(f"No available users")
return users_list
@classmethod
def get_office_user_id(cls, user_id):
users_list = cls.query.filter_by(id=user_id).first()
if not users_list:
logger.error(f"users_list with ID {user_id} does not exist.")
return None
return users_list
@classmethod
def get_office_user_by_username(cls, username):
logger.info(f"users_list looking for {username} .")
users_list = cls.query.filter_by(username=username).first()
logger.info(f"users_list looking for {username} after.")
if not users_list:
logger.error(f"users_list with ID {username} does not exist.")
return None
return users_list
@classmethod
def set_office_user_password(cls, user_id, username,password_hash):
selected_user = cls.query.filter_by(id=int(user_id), username=str(username)).first()
if not selected_user:
logger.error(f"users_list with ID {user_id} does not exist.")
return None
logger.info(f"Password Settings Action = > {user_id}, {username}, {password_hash} ")
selected_user.password = password_hash
return selected_user
def to_dict(self):
return {
'id': self.id,
'uid': self.uid,
'username': self.username,
'password': self.password,
'firstname': self.firstname,
'lastname': self.lastname,
'acc_level': self.acc_level,
'status': self.status,
'added': self.added
}
def __repr__(self):
return f'<Products {self.id}>'
+3 -3
View File
@@ -28,13 +28,13 @@ class PasswordReset(db.Model):
}
@classmethod
def get_rest_with_uid(cls, pending_uid):
def get_rest_with_uid(cls, pening_uid):
"""
Return all offers in dictionary format.
"""
pass_reset = cls.query.filter_by(uid = pending_uid).first()
pass_reset = cls.query.filter_by(uid = pening_uid).first()
if not pass_reset:
raise ValueError(f"Password Reset with UID {pending_uid} does not exist.")
raise ValueError(f"Password Reset with UID {pening_uid} does not exist.")
return pass_reset
@classmethod
+26 -78
View File
@@ -1,10 +1,10 @@
from datetime import datetime, timezone, timedelta
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
from app.utils.logger import logger
class Payments(db.Model):
__tablename__ = 'payments'
@@ -16,100 +16,48 @@ class Payments(db.Model):
)
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)
option_type = db.Column(db.String(25), nullable=False)
payment_uid = db.Column(db.String(100), nullable=False)
amount = db.Column(db.Integer, nullable=True, default=0)
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())
sub_start = db.Column(db.DateTime(timezone=True))
next_billing = db.Column(db.DateTime(timezone=True))
sub_stop = db.Column(db.DateTime(timezone=True))
'''
"payment_uid": currentPaymentsession.uid,
"member_id": currentPaymentsession.member_id,
"option_name": currentPaymentsession.option_name,
"amount": amount_subtotal,
"option_type": "MAIN"
'''
updated = db.Column(db.DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
@classmethod
def add_payment(cls, member_id, payment_uid, option_name,amount, option_type, next_billing_days=30):
# Get the current date and time
current_date = datetime.now()
# Calculate the date "next_billing_days" days from now
next_billing_date = current_date + timedelta(days=next_billing_days)
def add_payment(cls, customer_id, account_id, transaction_id, data=None):
# Save the response
pay_data = cls(
member_id=member_id,
payment_uid=payment_uid,
option_name=option_name,
amount=amount,
option_type=option_type,
rac_check = cls(
customer_id=customer_id,
account_id=account_id,
transaction_id=transaction_id,
added=datetime.now(timezone.utc),
sub_start=datetime.now(timezone.utc),
next_billing = next_billing_date
updated=datetime.now(timezone.utc)
)
try:
db.session.add(pay_data)
db.session.add(rac_check)
except IntegrityError as err:
raise ValueError(f"Database integrity error: {err}")
return pay_data
return rac_check
@classmethod
def get_member_payments_by_member_id(cls, member_id):
member_payments = cls.query.filter_by(member_id=str(member_id))
if not member_payments:
return None
return member_payments
@classmethod
def get_all_payments(cls, option_name=None, member_id=None, page=1, limit=20):
query = cls.query
logger.info(f"Get all payments back")
if member_id:
query = query.filter(cls.member_id == member_id)
if option_name:
query = query.filter(cls.option_name == option_name)
# Order by created_at descending (newest first)
query = query.order_by(cls.added.desc())
# Get total count before pagination
total_count = query.count()
# Apply pagination
offset = (page - 1) * limit
query = query.limit(limit).offset(offset)
return query.all(), total_count
def to_dict(self):
return {
"id": self.id,
"uid": self.uid,
"member_id": self.member_id,
"option_name": self.option_name,
"option_type": self.option_type,
"payment_uid": self.payment_uid,
"amount": self.amount,
"status": self.status,
"added": self.added,
"sub_start": self.sub_start,
"next_billing": self.next_billing,
"sub_stop": self.sub_stop
"offerId": self.id,
"productId": self.product_id,
"minAmount": self.min_amount,
"maxAmount": self.max_amount,
"tenor": self.tenor,
"interest_rate": self.interest_rate,
"management_rate": self.management_rate,
"insurance_rate": self.insurance_rate,
"vat_rate": self.vat_rate,
"maxDailyLoans": self.max_daily_loans,
"maxActiveLoans": self.max_active_loans,
"maxLifeLoans": self.max_life_loans
}
def __repr__(self):
return f'<Payments {self.id}>'
return f'<LoanOffer {self.id}>'
+3 -28
View File
@@ -27,15 +27,11 @@ class Products(db.Model):
product_id = db.Column(db.String(25), nullable=False)
name = db.Column(db.String(100), nullable=False)
description = db.Column(db.String(250), nullable=False)
start_url = db.Column(db.String(100), 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())
banner = db.Column(db.String(100), nullable=True)
list_order = db.Column(db.Integer, nullable=True, default=0)
contacts = db.Column(db.Integer, nullable=True, default=0)
comments = db.Column(db.Integer, nullable=True, default=0)
blog_product_id = db.Column(db.String(25), nullable=True)
members_products = relationship(
"MembersProducts",
@@ -72,26 +68,12 @@ class Products(db.Model):
logger.info(json_output)
return json_output
@classmethod
def get_contact_supported_product_list(cls, member_id):
product_list = cls.query.filter_by(contacts=1).all()
if not product_list:
return None
return product_list
@classmethod
def get_comments_supported_product_list(cls, member_id):
product_list = cls.query.filter_by(comments=1).all()
if not product_list:
return None
return product_list
@classmethod
def get_user_product_list(cls, member_id):
"""
Return all offers in dictionary format.
"""
product_list = cls.query.order_by(cls.list_order.asc()).all()
product_list = cls.query.all()
if not product_list:
raise ValueError(f"No available Products")
@@ -104,9 +86,7 @@ class Products(db.Model):
"""
productItem = cls.query.filter_by(product_id = product_id).first()
if not productItem:
# raise ValueError(f"pProduct with ID {product_id} does not exist.")
logger.error(f"Product with ID {product_id} does not exist.")
return None
raise ValueError(f"pProduct with ID {product_id} does not exist.")
return productItem
def to_dict(self):
@@ -117,14 +97,9 @@ class Products(db.Model):
'id': self.id,
'uid': self.uid,
'product_id': self.product_id,
'blog_product_id': self.blog_product_id,
'name': self.name,
'description' : self.description,
'start_url': self.start_url,
'status': self.status,
'list_order': self.list_order,
'contacts': self.contacts,
'comments': self.comments,
'added': self.added,
'updated': self.updated,
'banner': self.banner
-59
View File
@@ -1,59 +0,0 @@
from app.extensions import db
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
class ProductsColorStyle(db.Model):
__tablename__ = 'products_colorstyle'
id = db.Column(db.String, primary_key=True)
uid = db.Column(db.String, nullable=False)
product_id = db.Column(db.String, nullable=False)
name = db.Column(db.String, nullable=False)
color_style = db.Column(db.String, nullable=False)
color_code = db.Column(db.String, nullable=False)
status = db.Column(db.Integer, nullable=True, default=1)
added = db.Column(db.DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
@classmethod
def get_colorstyle_by_product_id(cls, product_id):
colorStyle = cls.query.filter_by(product_id=str(product_id)).all()
if not colorStyle:
return None
return colorStyle
@classmethod
def get_colorstyle_by_product_id_and_uid(cls, product_id, style_uid):
colorStyle = cls.query.filter_by(product_id=str(product_id), uid=str(style_uid)).first()
if not colorStyle:
return None
return colorStyle
@classmethod
def get_colorstyle_for_office(cls, filters):
colorStyle = cls.query.all()
if not colorStyle:
raise ValueError(f"Color Style not found")
return colorStyle
# @classmethod
# def get_template_by_uid(cls, template_uid):
# selTemplate = cls.query.filter_by(uif=template_uid).first()
# if not selTemplate:
# return None
# return selTemplate
def to_dict(self):
return {
"id": self.id,
"uid": self.uid,
"product_id": self.product_id,
"name": self.name,
"color_style": self.color_style,
"color_code": self.color_code,
"status": self.status,
"added": self.added.isoformat() if self.added else None
}
def __repr__(self):
return f'<ProductsColorStyle {self.id}>'
-113
View File
@@ -1,113 +0,0 @@
from app.extensions import db
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import relationship
from dateutil.relativedelta import relativedelta
import logging
from sqlalchemy import and_, or_, not_
from sqlalchemy.sql import func
from datetime import datetime, timezone
import uuid
logger = logging.getLogger(__name__)
class ProductsContacts(db.Model):
__tablename__ = 'products_contacts'
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)
subscription_uid = db.Column(db.String(100), nullable=False)
title = db.Column(db.String(100), nullable=True)
email = db.Column(db.String(100), nullable=True)
sender = db.Column(db.String(100), nullable=True)
message = db.Column(db.Text, nullable=True)
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())
# message = data.get('message', '')
# subscription_uid = data.get('subscription_uid', '')
# title = data.get('title', '')
# email = data.get('email', '')
# sender = data.get('sender', '')
#
@classmethod
def add_product_contact(cls, member_id ,product_id,subscription_uid,title,email,sender,message):
logger.info(f"Data for Product Contact: {member_id} ,{product_id} ,{subscription_uid} ")
product_contact_data = cls(
uid=str(uuid.uuid4()),
member_id=member_id,
product_id=product_id,
title=title,
email=email,
sender=sender,
message=message,
subscription_uid=subscription_uid,
added=datetime.now(timezone.utc),
updated=datetime.now(timezone.utc)
)
try:
logger.info(f"About to Insert Product Contact Data {product_contact_data.member_id} ")
db.session.add(product_contact_data)
db.session.commit()
except IntegrityError as err:
logger.error(f"Error inserting Contact Data {err} -- ")
raise ValueError(f"Database integrity error: {err}")
return product_contact_data
@classmethod
def get_member_contact_count(cls,member_id, day_limit):
logger.info(f"Counting Contact Data {member_id} for {day_limit} days -- ")
query = cls.query
query = query.filter(cls.member_id == member_id)
total_count = query.count()
return total_count
@classmethod
def get_all_contacts(cls,member_id, page=1, limit=20):
query = cls.query
logger.info(f"Get all customer back")
query = query.filter(cls.member_id == member_id)
# Order by created_at descending (newest first)
query = query.order_by(cls.added.desc())
# Get total count before pagination
total_count = query.count()
# Apply pagination
offset = (page - 1) * limit
query = query.limit(limit).offset(offset)
return query.all(), total_count
def to_dict(self):
return {
"id": self.id,
"uid": self.uid,
"product_id": self.product_id,
"member_id": self.member_id,
"subscription_uid": self.subscription_uid,
"title": self.title,
"email": self.email,
"sender": self.sender,
"message": self.message,
"status": self.status,
"added": self.added.isoformat() if self.added else None,
"updated": self.added.isoformat() if self.updated else None
}
def __repr__(self):
return f'<ProductsContacts {self.id}>'
+1 -1
View File
@@ -37,7 +37,7 @@ class ProductsDetails(db.Model):
"""
productItem = cls.query.filter_by(product_id = product_id).first()
if not productItem:
raise ValueError(f"Product with ID {product_id} does not exist.")
raise ValueError(f"pProduct with ID {product_id} does not exist.")
return productItem
+4 -42
View File
@@ -3,11 +3,6 @@ from app.extensions import db
from app.models.charge import Charge
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
import logging
logger = logging.getLogger(__name__)
class ProductsTemplates(db.Model):
__tablename__ = 'products_templates'
@@ -20,48 +15,16 @@ class ProductsTemplates(db.Model):
owner_uid = db.Column(db.String, nullable=False)
provision_name = db.Column(db.String, nullable=False)
added = db.Column(db.DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
flavor = db.Column(db.String, nullable=True)
@classmethod
def get_template_by_product_id(cls, product_id):
templates = cls.query.filter_by(product_id=str(product_id)).all()
if not templates:
# raise ValueError(f"Templates with Product ID {product_id} not found")
return None
raise ValueError(f"Templates with Product ID {product_id} not found")
return templates
@classmethod
def get_template_for_office(cls, product_id=None, provision_name=None, page=1, limit=20):
query = cls.query
logger.info(f"Get Templates for Office Product")
if product_id:
query = query.filter(cls.product_id == product_id)
if provision_name:
query = query.filter(cls.provision_name == provision_name)
# Order by created_at descending (newest first)
query = query.order_by(cls.added.desc())
# Get total count before pagination
total_count = query.count()
templates = query.all()
if not templates:
raise ValueError(f"Templates not found")
return templates
@classmethod
def get_template_by_uid(cls, template_uid):
selTemplate = cls.query.filter_by(uid=str(template_uid)).first()
if not selTemplate:
return None
return selTemplate
def to_dict(self):
return {
"id": self.id,
@@ -71,9 +34,8 @@ class ProductsTemplates(db.Model):
"status": self.status,
"owner_uid": self.owner_uid,
"provision_name": self.provision_name,
"flavor": self.flavor,
"added": self.added.isoformat() if self.added else None
"provision_name": self.provision_name
}
def __repr__(self):
return f'<ProductsTemplates {self.id}>'
return f'<LoanOffer {self.id}>'
+1 -20
View File
@@ -26,7 +26,7 @@ class ProvisionActions(db.Model):
product_uid = db.Column(db.String(100), nullable=False)
action = db.Column(db.String(100), nullable=False)
added = db.Column(db.DateTime(timezone=True), server_default=func.now())
percent_completed = db.Column(db.Integer, nullable=False)
@classmethod
@@ -47,24 +47,6 @@ class ProvisionActions(db.Model):
return provision_action
@classmethod
def get_provision_action_calendar_member_id(cls, member_id, limit):
provision_action = cls.query.all()
provision_action = cls.query.filter_by(member_id=member_id).order_by(cls.id.desc()).limit(limit).all()
if not provision_action:
return None
return provision_action
# '''
# merms_panel=# select * from provision_actions limit 2;
# id | uid | member_id | product_uid | action | added
# ----+--------------------------------------+-----------+--------------------------------------+-------------------------------+----------------------------
# 1 | 8b7db9fb-1404-4505-9858-7f418a6ae416 | 1 | df5bc060-18e0-4546-ae9a-89f7436f7cff | Allocating Provisioning Ports | 2025-07-12 21:21:02.036093
# 2 | d0e0fe16-4e0f-4cdc-856e-d8cfeb6c673f | 1 | 58645ef9-e334-45e0-8ce1-8ec637a20c50 | Allocating Provisioning Ports | 2025-07-13 15:02:04.388589
# (2 rows)
#
# '''
def to_dict(self):
"""
Convert the Loan object to a dictionary format for JSON serialization.
@@ -74,7 +56,6 @@ class ProvisionActions(db.Model):
'uid': self.uid,
'product_uid': self.product_uid,
'action': self.action,
'percent_completed': self.percent_completed,
'added': self.added,
}
-87
View File
@@ -1,87 +0,0 @@
from datetime import datetime, timezone, timedelta
from app.extensions import db
from sqlalchemy.sql import func
from sqlalchemy.exc import IntegrityError
import uuid
from app.utils.logger import logger
class Signup(db.Model):
__tablename__ = 'signup'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
uid = db.Column(db.String(150), nullable=False)
email = db.Column(db.String(100), nullable=False)
firstname = db.Column(db.String(25), nullable=False)
lastname = db.Column(db.String(25), nullable=True)
loc = db.Column(db.String(20), nullable=True)
status = db.Column(db.Integer, default=1)
added = db.Column(db.DateTime(timezone=False), server_default=func.now())
updated = db.Column(db.DateTime(timezone=False), server_default=func.now(), onupdate=func.now())
# "account_id": self.account_id,
def to_dict(self):
return {
"id": self.id,
"uid": str(self.uid),
"loc": self.loc,
"status": self.status,
"added": self.added.isoformat() if self.added else None,
"updated": self.updated.isoformat() if self.updated else None,
"email": self.email,
"firstname": self.firstname,
"lastname": self.lastname,
}
def __repr__(self):
return f'<Signup {self.id} - {self.uid}>'
@classmethod
def add_signup(cls, firstname, lastname, email):
# Save the response
signup_data = cls(
uid=str(uuid.uuid4()),
firstname=firstname,
lastname=lastname,
email=email,
added=datetime.now(timezone.utc),
updated=datetime.now(timezone.utc)
)
try:
db.session.add(signup_data)
except IntegrityError as err:
raise ValueError(f"Database integrity error: {err}")
return signup_data
@classmethod
def get_all_start_signup(cls, email=None, firstname=None, lastname=None, page=1, limit=20):
query = cls.query
logger.info(f"Get all customer back")
if firstname:
query = query.filter(cls.firstname == firstname)
if lastname:
query = query.filter(cls.lastname == lastname)
if email:
query = query.filter(cls.email == email)
# Order by created_at descending (newest first)
query = query.order_by(cls.added.desc())
# Get total count before pagination
total_count = query.count()
# Apply pagination
offset = (page - 1) * limit
query = query.limit(limit).offset(offset)
return query.all(), total_count
-102
View File
@@ -1,102 +0,0 @@
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 SubscriptionGenerative(db.Model):
__tablename__ = 'subscription_generative'
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)
practice = db.Column(db.String(100), nullable=False)
specialization = db.Column(db.String(100), nullable=False)
product_id = db.Column(db.String(25), nullable=False)
subscription_uid = db.Column(db.String(100), nullable=True)
status = db.Column(db.Integer, nullable=True, default=0)
added = db.Column(db.DateTime(timezone=True), server_default=func.now())
@classmethod
def get_subscription_generative_by_subscription_uid(cls, subscription_uid):
subscription_generative = cls.query.filter_by(subscription_uid=str(subscription_uid)).first()
if not subscription_generative:
return None
return subscription_generative
@classmethod
def get_subscription_generative_list_by_status(cls, status):
subscription_generative = cls.query.filter_by(status=status).all()
if not subscription_generative:
return None
return subscription_generative
@classmethod
def update_subscription_generative_status(cls, subscription_uid, status):
logger.info(
f"UPDATE SubscriptionGenerative::status subscription_uid = {subscription_uid} status = {status} ")
subscription_generative_data = cls.query.filter_by(subscription_uid=str(subscription_uid)).first()
if not subscription_generative_data:
logger.error(f"SubscriptionGenerative with Sub UID {subscription_uid} does not exist.")
return None
logger.info("UPDATE STATUS::Point-->")
subscription_generative_data.status = status
db.session.commit()
return subscription_generative_data.status
@classmethod
def create_subscription_generative(cls, member_id ,practice,specialization,product_id, subscription_uid):
logger.info(f"SubscriptionGenerative Data {member_id} ,{practice} ,{specialization},{product_id}, {subscription_uid} ")
subscription_generative_data = cls(
uid=str(uuid.uuid4()),
member_id=member_id,
practice=practice,
specialization=specialization,
product_id=product_id,
subscription_uid=subscription_uid,
added=datetime.now(timezone.utc)
)
try:
logger.info(f" About to Insert Subscription_Generative Data {subscription_generative_data.member_id} ")
db.session.add(subscription_generative_data)
db.session.flush()
except IntegrityError as err:
logger.error(f" Error inserting Subscription_Generative data {err} -- ")
raise ValueError(f"Database integrity error: {err}")
return subscription_generative_data
def to_dict(self):
"""
Convert the Loan object to a dictionary format for JSON serialization.
"""
return {
'id': self.id,
'uid': self.uid,
'member_id': self.member_id,
'practice': self.practice,
'specialization': self.specialization,
'product_id': self.product_id,
'subscription_uid': self.subscription_uid,
'added': self.added,
'status': self.status
}
def __repr__(self):
return f'<SubscriptionGenerative {self.id}>'
-2
View File
@@ -17,7 +17,6 @@ class SubscriptionOptions(db.Model):
updated = db.Column(db.DateTime(timezone=False), server_default=func.now(), onupdate=func.now())
stripe_product_id = db.Column(db.String(100), nullable=True)
stripe_price_id = db.Column(db.String(100), nullable=True)
country_code = db.Column(db.String(3), nullable=False)
@classmethod
@@ -65,7 +64,6 @@ class SubscriptionOptions(db.Model):
"display_name": self.display_name,
"status": self.status,
"monthly": self.monthly,
"country_code": self.country_code,
"stripe_product_id": self.stripe_product_id,
"stripe_price_id": self.stripe_price_id,
"added": self.added.isoformat() if self.added else None,
View File
-39
View File
@@ -1,39 +0,0 @@
import boto3
from botocore.exceptions import ClientError
from app.utils.logger import logger
# @staticmethod
def send_email_ses(to_email, subject, html_content, text_content=None):
AWS_REGION = "us-east-1"
FROM_EMAIL = "support@mermsemr.com" # Must be verified in SES
client = boto3.client(
"ses",
region_name=AWS_REGION,
# Credentials pulled from env vars: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
# or from IAM role if running on EC2/ECS
)
body = {"Html": {"Charset": "UTF-8", "Data": html_content}}
if text_content:
body["Text"] = {"Charset": "UTF-8", "Data": text_content}
try:
response = client.send_email(
Source=FROM_EMAIL,
Destination={"ToAddresses": [to_email]},
Message={
"Subject": {"Charset": "UTF-8", "Data": subject},
"Body": body,
},
)
logger.info(f"SES email sent. MessageId: {response['MessageId']}")
return response
except ClientError as e:
logger.error(f"SES ClientError: {e.response['Error']['Message']}")
raise
except Exception as e:
logger.error(f"SES send failed: {e}")
raise
-42
View File
@@ -1,42 +0,0 @@
import smtplib
import ssl
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from app.utils.logger import logger
def send_email_google(to_email, subject, html_content, text_content=None):
SMTP_SERVER = "smtp.gmail.com"
PORT = 587
FROM_EMAIL = "support@mermsemr.com"
APP_PASSWORD = "" # Set via env var: os.getenv("GMAIL_APP_PASSWORD")
msg = MIMEMultipart("alternative")
msg["Subject"] = subject
msg["From"] = FROM_EMAIL
msg["To"] = to_email
if text_content:
msg.attach(MIMEText(text_content, "plain"))
msg.attach(MIMEText(html_content, "html"))
context = ssl.create_default_context()
try:
with smtplib.SMTP(SMTP_SERVER, PORT) as server:
server.ehlo()
server.starttls(context=context)
server.ehlo()
server.login(FROM_EMAIL, APP_PASSWORD)
server.sendmail(FROM_EMAIL, to_email, msg.as_string())
logger.info(f"Google email sent to {to_email}")
except smtplib.SMTPAuthenticationError:
logger.error("Google SMTP auth failed: check FROM_EMAIL and APP_PASSWORD")
raise
except smtplib.SMTPConnectError as e:
logger.error(f"Google SMTP connection error: {e}")
raise
except Exception as e:
logger.error(f"Google SMTP send failed: {e}")
raise
-135
View File
@@ -1,135 +0,0 @@
from app.notifications.aws.aws_mailer import send_email_ses
from app.utils.logger import logger
def send_email_factory(to_email, subject, html_content, text_content=None):
try:
send_email_ses(
to_email=to_email,
subject=subject,
html_content=body_template(html_content)
)
except Exception as e:
logger.error(f"Send_Email_Factory failed: {e}")
raise
def alert_email_factory(to_email, subject, html_content, text_content=None):
try:
send_email_ses(
to_email=to_email,
subject=subject,
html_content=alert_template(html_content)
)
except Exception as e:
logger.error(f"Alert_Email_Factory failed: {e}")
raise
def body_template(html_content):
html_body = f"""\
<html>
<head></head>
<body style="font-size:14px;line-height:1.5;">
<div style="
font-family: 'Public Sans', helvetica, arial, sans-serif;
max-width: 480px; margin: 0 auto; padding: 16px;
color: #1b1b1b; font-size: 16px; line-height: 1.5;
background-color: #ffffff;">
<div style="text-align: center; padding: 16px 0 24px 0;">
<img src="https://www.mermsemr.com/images/logo-pink.png"
alt="MermsEmr"
height="40" />
</div>
<div style="border: 1px solid #dfe1e2; border-radius: 8px; padding: 20px 24px; margin-bottom: 24px;">
<div style="font-weight: 700; font-size: 18px; margin-bottom: 16px;">
{html_content}
</div>
</div>
<p style="margin: 0 0 16px 0;">
For any support<br>
Reach Out<br>
support@mermsemr.com<br>
https://www.mermsemr.com/
</p>
</div>
</body>
</html>
"""
return html_body
def alert_template(html_content):
html_body = f"""\
<html>
<head></head>
<body style="font-size:14px;line-height:1.5;">
<table width="550px" border="0" cellpadding="3" cellspacing="3" background-color="#F0F8FF" style="font-size:16px">
<tr>
<td style="text-align:center">
<img style="width:150px; height:auto;" src="https://www.mermsemr.com/images/logo-pink.png" />
</td>
</tr>
<tr>
<td>
{html_content}
</td>
</tr>
<tr>
<td>
<br />
LINKS --- ---- ---- -----
<br />
For any support<br>
Reach Out<br>
support@mermsemr.com<br>
https://www.mermsemr.com/
</td>
</tr>
</table>
</body>
</html>
"""
return html_body
# < table
# width = "550px"
# border = "0"
# cellpadding = "3"
# cellspacing = "3"
# background - color = "#F0F8FF"
# style = "font-size:16px" >
# < tr >
# < td
# style = "text-align:center" >
# < img
# style = "width:150px; height:auto;"
# src = "https://www.mermsemr.com/images/logo-pink.png" / >
# < / td >
# < / tr >
# < tr >
# < td >
# {html_content}
# < / td >
# < / tr >
#
# < tr >
# < td >
# For
# any
# support < br >
# Reach
# Out < br >
# support @ mermsemr.com < br >
# https: // www.mermsemr.com /
# < / td >
# < / tr >
# < / table >
@@ -1,37 +0,0 @@
from app.utils.logger import logger
from marshmallow import ValidationError
from flask_mail import Mail, Message
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
# @staticmethod
def send_email_sendgrid():
# Replace these with your actual details
SENDGRID_API_KEY = "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"
FROM_EMAIL = 'support@mermsemr.com' # Must be a verified sender in SendGrid
TO_EMAIL = 'works@chiefsoft.com'
message = Mail(
from_email=FROM_EMAIL,
to_emails=TO_EMAIL,
subject='Sending with Twilio SendGrid is Fun',
html_content='<strong>and easy to do anywhere, even with Python</strong>'
)
try:
# Initialize the SendGrid client
sg = SendGridAPIClient(SENDGRID_API_KEY)
# Send the email
response = sg.send(message)
# Print status codes: 202 means the request was accepted for delivery
print(f"Status Code: {response.status_code}")
print(f"Body: {response.body}")
print(f"Headers: {response.headers}")
except Exception as e:
logger.error(f"An unrelated error occurred: {e}")
-19
View File
@@ -1,19 +0,0 @@
services:
merms-backend-core:
image: registry.chiefsoft.net/merms-core-backend-flask:latest
build: .
env_file:
- .env.live
ports:
- "${APP_PORT:-14700}:5000"
environment:
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- FLASK_APP=${FLASK_APP}
- FLASK_ENV=${FLASK_ENV}
- DATABASE_URL=postgresql+psycopg2://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}
extra_hosts:
- smtp.gmail.com:10.10.33.15
volumes:
- .:/app
restart: always
-2
View File
@@ -7,8 +7,6 @@ services:
ports:
- "${APP_PORT:-14700}:5000"
environment:
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- FLASK_APP=${FLASK_APP}
- FLASK_ENV=${FLASK_ENV}
- DATABASE_URL=postgresql+psycopg2://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}
-2
View File
@@ -7,8 +7,6 @@ services:
ports:
- "${APP_PORT:-14700}:5000"
environment:
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- FLASK_APP=${FLASK_APP}
- FLASK_ENV=${FLASK_ENV}
- DATABASE_URL=postgresql+psycopg2://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}
+1 -9
View File
@@ -45,12 +45,4 @@ pycountry
stripe
requests
openai
redis
sendgrid
boto3
requests