Compare commits
282 Commits
paymants-work
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| b7f0348f72 | |||
| acd6224616 | |||
| 55650b3aa3 | |||
| 9784de43b3 | |||
| 968a2ce6a3 | |||
| 5e5edf27b2 | |||
| 1c43454dea | |||
| b4e277cdbb | |||
| 9888becc26 | |||
| f3e7a746af | |||
| 970cf7e1e9 | |||
| 23614114ea | |||
| 8e8e64dd38 | |||
| 314ae7bee6 | |||
| ceed7fd066 | |||
| 570061caef | |||
| 25a44dd7a5 | |||
| 117abbf870 | |||
| 74af6a2c5c | |||
| 41f61ce0c4 | |||
| 50f44764fd | |||
| 8c34102954 | |||
| b909f1c987 | |||
| 7c0adae905 | |||
| a94050d32b | |||
| 26b6c1fa63 | |||
| 91ee789f71 | |||
| bd7aae51ab | |||
| 972873e570 | |||
| 9ca753df59 | |||
| 5412582763 | |||
| ea331cb23c | |||
| da51720e2c | |||
| 9ea5b872fc | |||
| cef4ba0f19 | |||
| 98d0be017d | |||
| d70df88eca | |||
| 80316f1221 | |||
| 0461bad40f | |||
| 5b21696067 | |||
| 8825884281 | |||
| 627445e9e2 | |||
| 42c06f8790 | |||
| 9441037256 | |||
| 88f6e8259d | |||
| fe19511d11 | |||
| 86e897c54d | |||
| 8bc157b6ba | |||
| 37b54e7390 | |||
| 58e70cb655 | |||
| 98c1b1fa75 | |||
| 5f4a9112c3 | |||
| 2bfb802b10 | |||
| f25975e140 | |||
| 2d806534f6 | |||
| 2b58b8b0a6 | |||
| a6fbce89a1 | |||
| 2f03fd8992 | |||
| a8f94b9017 | |||
| a2e2950c38 | |||
| ddc172a1d5 | |||
| fbbb8569cf | |||
| 80361b4267 | |||
| 5367766dc8 | |||
| fe4ffb3d3e | |||
| 7c97667340 | |||
| 3218de1f1b | |||
| c0ff046455 | |||
| 6cd8cea6ea | |||
| 454545e127 | |||
| e6631e1ab1 | |||
| 56a51186f5 | |||
| 887632c707 | |||
| d846913bda | |||
| aad148dba3 | |||
| f14877ae69 | |||
| d95533ecdd | |||
| 7c07dfdff8 | |||
| 63bcf5e6e6 | |||
| 83e29b0cb5 | |||
| 394901f4df | |||
| 7b626f69eb | |||
| ec160702f1 | |||
| 4024e05021 | |||
| 8b3d77fa62 | |||
| e69359e7c3 | |||
| 3f7639329d | |||
| f2443b99cb | |||
| ddff043e97 | |||
| ae09366826 | |||
| 718651128f | |||
| fb24b84a46 | |||
| 2d8993150b | |||
| 581941dba8 | |||
| 6b0e289bd7 | |||
| f49d4d5017 | |||
| 890ee19201 | |||
| aa64b984e4 | |||
| c4b28e02e9 | |||
| bd4128ad04 | |||
| 05c3428c04 | |||
| 407cbc3f77 | |||
| defde3911e | |||
| 424338e5f7 | |||
| f34c5c4cfb | |||
| ccfcbee727 | |||
| 357c3e0f50 | |||
| b5e4203558 | |||
| b291f75679 | |||
| 5a45449636 | |||
| a521fce94c | |||
| 817e929b3f | |||
| a57945e77e | |||
| 565fb8a35d | |||
| 42f9d7fb24 | |||
| d4efa21d0a | |||
| 39feca114c | |||
| 7906987bea | |||
| 9e42248711 | |||
| 9dbc4ec686 | |||
| 416dbfdbe0 | |||
| c34ec35329 | |||
| 109de7d60a | |||
| e157f8a715 | |||
| 1051dd44ad | |||
| abfef493f7 | |||
| 21f55b2e5c | |||
| 33c38652d5 | |||
| 7f1fd7a156 | |||
| 26f77cf79c | |||
| 6544879998 | |||
| bebc9aaa1f | |||
| ac0714eba8 | |||
| 775dc683d6 | |||
| d9e8a29326 | |||
| 07fb27fbf3 | |||
| fd2edc356c | |||
| 0d3078c665 | |||
| 59c7e4fdb9 | |||
| 05840aae17 | |||
| 28fabda7bf | |||
| ec0e1fc952 | |||
| f2a5ec9e76 | |||
| 2720b4e1f5 | |||
| 0d6e4c8f87 | |||
| d83eee6629 | |||
| e3bccc9bfe | |||
| 989f3dc37e | |||
| 4a53f57bbc | |||
| c94982fd2c | |||
| bb73540b59 | |||
| 7ce2f50375 | |||
| 4654098043 | |||
| 749d01a3a9 | |||
| 19b606af48 | |||
| de2691f871 | |||
| 780242f4e0 | |||
| d2abfa3ce5 | |||
| c2e29dd93f | |||
| 6545e5b94c | |||
| dea390cb8b | |||
| 9c8916d67c | |||
| 33dc63331c | |||
| 9d2e0df144 | |||
| 2baf7c9a55 | |||
| ee7004236e | |||
| 9d7909fb42 | |||
| 88e96bf70a | |||
| 706ee60d3e | |||
| d9f9e7d6b7 | |||
| cf0964b6a7 | |||
| 341d92b1ee | |||
| bf553f3f61 | |||
| a87f482240 | |||
| 08337f1dbd | |||
| 825d4c0438 | |||
| e06948643a | |||
| ea06665f6d | |||
| dc27865c47 | |||
| d561d942dd | |||
| 18562c922e | |||
| e8b9c0ba1c | |||
| b207aee9fd | |||
| 3d4fbba98e | |||
| 2558b51aa4 | |||
| 172acb1e20 | |||
| 9f60427a42 | |||
| 53dad90ef4 | |||
| 1c5535cf5d | |||
| 42bbffb68b | |||
| 9570a5e914 | |||
| e49a92d1ae | |||
| 156b57d01e | |||
| f8a2278903 | |||
| 8759bc8457 | |||
| be1bd1e450 | |||
| 704c8bd7ed | |||
| b8f4d98381 | |||
| 808ee0ff3d | |||
| f55b76d5e8 | |||
| 67cbd777db | |||
| 862eaeb075 | |||
| 008ddb53b4 | |||
| 53e2171e0b | |||
| 0119f70100 | |||
| b902465112 | |||
| 7ba12caf0b | |||
| 884ccda732 | |||
| cd95765898 | |||
| 32f0a69598 | |||
| 500b4c5931 | |||
| 1c6a29d36b | |||
| 411b7a8b2d | |||
| d6c7da9233 | |||
| a0c99bfca5 | |||
| b7128db867 | |||
| 0629824a6d | |||
| 3282815627 | |||
| 714393a39b | |||
| 4a5f2ee946 | |||
| 108aed76c1 | |||
| 9809d3e7f3 | |||
| 4d894d8214 | |||
| ff8513292b | |||
| 52a0a72702 | |||
| f3d81e662e | |||
| 2088eb0227 | |||
| da3b68ff90 | |||
| 22ee86a198 | |||
| ef53fcf03e | |||
| 2b494ffe3c | |||
| 375db52cad | |||
| 4b82f5a9d4 | |||
| aa70994148 | |||
| 87cbdbb220 | |||
| 31c9785ec8 | |||
| ff3ff1c6ba | |||
| f992bc8bfe | |||
| 4888d58112 | |||
| f7ba53a230 | |||
| 78dd6fec6e | |||
| 399ccc25ee | |||
| 44e9c893b6 | |||
| d4c8b502f1 | |||
| 60c3158caa | |||
| eec13ea764 | |||
| 6db6b6cf8e | |||
| d113bd37b4 | |||
| d81af8d5ce | |||
| c268cbdd1c | |||
| 3f26d4c2bc | |||
| fba363f2a7 | |||
| 9373ab8572 | |||
| 271ac7a69a | |||
| d4b2cd1457 | |||
| 61a6fe3f10 | |||
| 9dd33a6187 | |||
| 36f094bba3 | |||
| 290d0b5c22 | |||
| 61f47ed6a9 | |||
| edd62a8174 | |||
| 477d97e045 | |||
| a604aeba8a | |||
| 037ef64694 | |||
| 8e1c841379 | |||
| 9d8aab3585 | |||
| 57c5e8afc5 | |||
| defe9006ca | |||
| e5364cbb4d | |||
| e8a53e63cc | |||
| 74d78bd883 | |||
| a0cde39737 | |||
| 6c9f7666e0 | |||
| a2c84b7b5c | |||
| f621a716ea | |||
| c807cbdbe4 | |||
| f6b7d9dceb | |||
| bf982238ee | |||
| 3b224b0243 | |||
| 6c660c873f | |||
| 2a42af5997 | |||
| 7dd788f559 |
@@ -20,6 +20,7 @@ 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"
|
||||
@@ -28,13 +29,26 @@ 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!
|
||||
JWT_SECRET_KEY=dce6bd64f7d7101de4fed7cfc185a12851611a79bd60bbfdcc5b414b85f1fdb75e0905691c2a77ce94a7351b261fab4e183e17731ed40089f68f7290a793119f285d8ec7902d248ce15e8b1d4996ebacf5e7bcb06a38ac7ce0736f17d5c2895a499661d27095ac20aa174f9af2fba9a849dd2e6fd0aad8aa7e1ecc030c11eb8dc8dcb71d32233de3530d04f85918b9582f8b02587a7350aa34232825d4831707c7c5775026f3fdd92c5df555e6ff8b785525922709830206bbd49c371fb6e16bcab01ffccaf904108bb9789c578bce6afbb33bc77960051e680b2428d1f026473e71ef0f9997b2a6dc496e1c40509a1d289e3ff8b384c2d49e1d7719f9f4aaa1
|
||||
# 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"
|
||||
@@ -45,3 +59,9 @@ 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=sG2yL+x95MqflugQfiPjSf793O8MyjxZSNWEqKqu
|
||||
@@ -9,7 +9,7 @@ BASIC_AUTH_PASSWORD=password
|
||||
SWAGGER_URL="/documentation"
|
||||
API_URL="/swagger.json"
|
||||
|
||||
THIS_SITE_URL="http://localhost:8090"
|
||||
THIS_SITE_URL="https://panel.mermsemr.com"
|
||||
|
||||
SWAGGER_URL="/documentation"
|
||||
API_URL="/swagger.json"
|
||||
@@ -18,8 +18,9 @@ DATABASE_USER=merms_panel
|
||||
DATABASE_PASSWORD=merms_panel
|
||||
DATABASE_HOST=10.13.3.60
|
||||
DATABASE_PORT=5432
|
||||
DATABASE_NAME=merms_panel_live
|
||||
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"
|
||||
@@ -33,12 +34,31 @@ 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_test_51RqL5WLjZLojw6IZmEpwFidNZSl9lLlVUHNvuFZNEz1eTR9XXepnyyVhfvXe9cp4eMnqkDPpoe9wxLLRSV0dxRee00UfhayUOT"
|
||||
STRIPE_PUB_KEY="pk_live_51RqL5OQ8vepTmh4AbXAnFmbgWDNJys2sfDcsLPVnOKRFx8EVOBOlO2RRN4lRNh6wNPhAj1A28xL3R0wHlMJ4WECo00rOM5iOto"
|
||||
STRIPE_PUB_KEY_0="pk_test_51RqL5WLjZLojw6IZmEpwFidNZSl9lLlVUHNvuFZNEz1eTR9XXepnyyVhfvXe9cp4eMnqkDPpoe9wxLLRSV0dxRee00UfhayUOT"
|
||||
#Secret key
|
||||
STRIPE_PRIV_KEY="sk_test_51RqL5WLjZLojw6IZZa921BftQWmxZ4JDxrHUrFZvc5kwJhxtK3ijZguUw42c4Rl5yjmpkdYlbpslDOaMGtOSrsL100oaN72Lne"
|
||||
STRIPE_PRIV_KEY="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"
|
||||
STRIPE_PRIV_KEY_0="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
|
||||
|
||||
@@ -31,6 +31,8 @@ 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'
|
||||
@@ -41,3 +43,6 @@ 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"
|
||||
@@ -24,6 +24,7 @@ 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
|
||||
@@ -44,7 +45,14 @@ 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"
|
||||
@@ -53,3 +61,7 @@ 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"
|
||||
+3
-2
@@ -27,5 +27,6 @@ STRIPE_PUB_KEY="pk_test_51RqL5WLjZLojw6IZmEpwFidNZSl9lLlVUHNvuFZNEz1eTR9XXepnyyV
|
||||
#Secret key
|
||||
STRIPE_PRIV_KEY="sk_test_51RqL5WLjZLojw6IZZa921BftQWmxZ4JDxrHUrFZvc5kwJhxtK3ijZguUw42c4Rl5yjmpkdYlbpslDOaMGtOSrsL100oaN72Lne"
|
||||
|
||||
|
||||
SIMBRELLA_BASE_URL=***************
|
||||
# UPLOAD PATHS
|
||||
UPLOAD_FOLDER="/app/uploads/DEV"
|
||||
MEDIA_SERVER="https://qa-media.mermsemr.com"
|
||||
@@ -44,6 +44,8 @@ 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
|
||||
@@ -53,3 +55,17 @@ 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=sG2yL+x95MqflugQfiPjSf793O8MyjxZSNWEqKqu
|
||||
|
||||
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/
|
||||
@@ -39,6 +39,8 @@ 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
|
||||
@@ -54,4 +56,11 @@ JWT_SECRET_KEY=dce6bd64f7d7101de4f
|
||||
# MAIL_PORT= 465
|
||||
# MAIL_USERNAME=message@chiefsoft.com
|
||||
# MAIL_PASSWORD=may12002!
|
||||
# JWT_SECRET=dce6bd64f7d7101de4f
|
||||
# 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=sG2yL+x95MqflugQfiPjSf793O8MyjxZSNWEqKqu
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
"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
|
||||
+725
-9
@@ -46,7 +46,15 @@ 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 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);
|
||||
|
||||
|
||||
CREATE TABLE members_profile(
|
||||
id SERIAL,
|
||||
@@ -64,6 +72,7 @@ ALTER TABLE ONLY members_profile
|
||||
|
||||
ALTER TABLE members_profile OWNER TO merms_panel
|
||||
|
||||
ALTER TABLE members_profile ADD url_name VARCHAR(25);
|
||||
|
||||
|
||||
|
||||
@@ -105,6 +114,38 @@ 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,
|
||||
@@ -228,6 +269,53 @@ 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(),
|
||||
@@ -244,6 +332,9 @@ merms_panel=# select product_id,description from products;
|
||||
ALTER TABLE products_templates OWNER TO merms_panel;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
INSERT INTO products_templates(product_id,name,provision_name,status)
|
||||
VALUES(
|
||||
'A000001',
|
||||
@@ -289,6 +380,89 @@ 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,
|
||||
@@ -314,8 +488,9 @@ 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 url_status INT DEFAULT 0;
|
||||
ALTER TABLE members_products ADD product_template VARCHAR(100);
|
||||
ALTER TABLE members_products ADD custom_template VARCHAR(100);
|
||||
|
||||
-- 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');
|
||||
@@ -329,6 +504,54 @@ 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,
|
||||
@@ -395,6 +618,9 @@ 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"},
|
||||
@@ -493,23 +719,29 @@ 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),
|
||||
description VARCHAR(100) NOT NULL,
|
||||
list_order INT DEFAULT 0,
|
||||
option_type VARCHAR(25),
|
||||
payment_uid VARCHAR(100) UNIQUE NOT NULL,
|
||||
amount INT DEFAULT 0,
|
||||
status INT DEFAULT 1,
|
||||
added timestamp without time zone DEFAULT now()
|
||||
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
|
||||
);
|
||||
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'}
|
||||
|
||||
|
||||
|
||||
@@ -573,6 +805,124 @@ 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()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -724,10 +1074,26 @@ 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);
|
||||
|
||||
|
||||
|
||||
@@ -761,6 +1127,331 @@ 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';
|
||||
|
||||
|
||||
|
||||
@@ -768,3 +1459,28 @@ grant all privileges on database merms_panel to merms_panel;
|
||||
|
||||
|
||||
|
||||
|
||||
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,2 +1,5 @@
|
||||
from .transaction_type import TransactionType
|
||||
from .loan_status import LoanStatus
|
||||
from .loan_status import LoanStatus
|
||||
from .settings_items_data import SettingsItemsData
|
||||
from .generatives_list import GenerativesList
|
||||
from .kafka_messages import KafkaMessage
|
||||
@@ -0,0 +1,977 @@
|
||||
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"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,74 @@
|
||||
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
|
||||
@@ -0,0 +1,6 @@
|
||||
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"
|
||||
@@ -0,0 +1,84 @@
|
||||
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 +1,3 @@
|
||||
from .kafka import KafkaIntegration
|
||||
from .merms_stripe import StripeIntegration
|
||||
from .merms_stripe import StripeIntegration
|
||||
from .generative_engine import GenerativeEngineIntegration
|
||||
@@ -0,0 +1,43 @@
|
||||
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
|
||||
@@ -1,23 +1,37 @@
|
||||
import stripe
|
||||
import json
|
||||
import logging
|
||||
from app.config import settings
|
||||
from app.config import settings, Config
|
||||
|
||||
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"],
|
||||
payment_method="pm_card_visa",
|
||||
description="Customer for Merms Subscription",
|
||||
invoice_settings={"default_payment_method": "pm_card_visa"},
|
||||
description="Customer for MERMS Subscription",
|
||||
)
|
||||
# payment_method="pm_card_visa", # Replace with a valid payment method ID or attach one later
|
||||
return customer
|
||||
@@ -58,8 +72,8 @@ class StripeIntegration:
|
||||
},
|
||||
],
|
||||
mode='subscription',
|
||||
success_url='https://qa-panel.mermsemr.com/subscription-success?session_id={CHECKOUT_SESSION_ID}',
|
||||
cancel_url='https://qa-panel.mermsemr.com/subscription',
|
||||
success_url= StripeIntegration.STRIPE_SUCCESS_URL,
|
||||
cancel_url=StripeIntegration.STRIPE_CANCEL_URL,
|
||||
)
|
||||
return checkout_session
|
||||
except stripe.error.StripeError as e:
|
||||
|
||||
+595
-847
File diff suppressed because it is too large
Load Diff
@@ -3,3 +3,4 @@ from marshmallow import Schema, fields
|
||||
class LoginSchema(Schema):
|
||||
username = fields.Str(required=True)
|
||||
password = fields.Str(required=True)
|
||||
turnstileToken = fields.Str(required=False)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
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)
|
||||
@@ -0,0 +1,11 @@
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
from marshmallow import Schema, fields
|
||||
|
||||
class ProfileLinksSchema(Schema):
|
||||
token = fields.Str(required=True)
|
||||
uid = fields.Str(required=True)
|
||||
# url_list = fields.Str( required=False)
|
||||
@@ -4,6 +4,8 @@ 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)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
from marshmallow import Schema, fields
|
||||
|
||||
class ReportSchema(Schema):
|
||||
token = fields.Str(required=True)
|
||||
uid = fields.Str(required=True)
|
||||
page = fields.Int(required=True)
|
||||
@@ -2,3 +2,4 @@ from marshmallow import Schema, fields
|
||||
|
||||
class ResetPassStart(Schema):
|
||||
username = fields.Str(required=True)
|
||||
turnstileToken = fields.Str(required=False)
|
||||
|
||||
@@ -5,4 +5,5 @@ class StartProfileSchema(Schema):
|
||||
uid = fields.Str(required=True)
|
||||
practice =fields.Str(required=True)
|
||||
specialization =fields.Str(required=True)
|
||||
introduction = fields.Str(required=True)
|
||||
introduction = fields.Str(required=True)
|
||||
url_name = fields.Str(required=True)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
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)
|
||||
@@ -7,12 +7,22 @@ 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.subscription import SubscriptionService
|
||||
from app.api.services.subscriptions import SubscriptionsService
|
||||
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
|
||||
|
||||
|
||||
+405
-52
@@ -1,18 +1,18 @@
|
||||
from flask import session, jsonify
|
||||
# from app.models.loan import Loan
|
||||
from app.api.schemas.user_update import UserUpdateSchema
|
||||
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
|
||||
# from app.api.services.offer_analysis import OfferAnalysis
|
||||
from app.models import Members, MembersActions, MembersProfile, Payments, MembersProducts, ProvisionActions, \
|
||||
ProductsContacts
|
||||
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,7 +20,15 @@ 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):
|
||||
@@ -28,17 +36,81 @@ 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):
|
||||
|
||||
@@ -52,21 +124,20 @@ class AccountService(BaseService):
|
||||
|
||||
member_actions = MembersActions.get_recent_member_actions(member_data.id)
|
||||
member_actions_data = []
|
||||
|
||||
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
|
||||
})
|
||||
|
||||
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
|
||||
})
|
||||
|
||||
action_data = {
|
||||
"recent_actions": member_actions_data,
|
||||
@@ -97,8 +168,6 @@ class AccountService(BaseService):
|
||||
db.session.rollback()
|
||||
return ResponseHelper.internal_server_error()
|
||||
|
||||
|
||||
|
||||
@staticmethod
|
||||
def process_request(data):
|
||||
try:
|
||||
@@ -113,14 +182,15 @@ 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,
|
||||
"room": member.uid,
|
||||
"picture": 'https://media.mermsemr.com/media/show/merms-profile',
|
||||
"token": user_token
|
||||
}
|
||||
|
||||
@@ -142,7 +212,6 @@ class AccountService(BaseService):
|
||||
db.session.rollback()
|
||||
return ResponseHelper.internal_server_error()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def process_startprofile(data):
|
||||
try:
|
||||
@@ -154,6 +223,17 @@ 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)
|
||||
@@ -161,24 +241,27 @@ 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:
|
||||
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_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:
|
||||
profile_completed = Members.set_member_profile_completed(member_data['uid'])
|
||||
|
||||
result_data = {
|
||||
@@ -205,7 +288,6 @@ class AccountService(BaseService):
|
||||
db.session.rollback()
|
||||
return ResponseHelper.internal_server_error()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def process_calendar(data):
|
||||
try:
|
||||
@@ -215,15 +297,42 @@ 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 = []
|
||||
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)
|
||||
# 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)
|
||||
|
||||
calendar_data = {
|
||||
"last_update": datetime.datetime.utcnow(),
|
||||
@@ -264,4 +373,248 @@ 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()
|
||||
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)
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
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)
|
||||
|
||||
|
||||
|
||||
+235
-214
@@ -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,6 +22,25 @@ 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 = {
|
||||
@@ -32,46 +51,64 @@ 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},
|
||||
|
||||
Password Reset Completed
|
||||
|
||||
|
||||
For any Support
|
||||
Reach Out
|
||||
support@mermsemr.com
|
||||
"""
|
||||
|
||||
sender_email = BaseService.SEND_EMAIL_FROM
|
||||
sender_password = BaseService.SEND_EMAIL_PASS
|
||||
# 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>
|
||||
"""
|
||||
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):
|
||||
@@ -90,46 +127,115 @@ 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
|
||||
|
||||
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>
|
||||
# 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>
|
||||
# """
|
||||
|
||||
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
|
||||
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>
|
||||
"""
|
||||
receiver_email = signup_email
|
||||
subject = "Reset Password Email"
|
||||
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
|
||||
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
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
@classmethod
|
||||
@@ -140,164 +246,79 @@ 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)}")
|
||||
|
||||
@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"}
|
||||
# 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={}
|
||||
|
||||
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"])
|
||||
response_data = {
|
||||
"provision_uid": str(provision_uid),
|
||||
"data": res_data,
|
||||
# "product_id": product_id,
|
||||
}
|
||||
|
||||
# Separate fees into upfront and postpaid
|
||||
upfront_fees = [
|
||||
fee["fee"]
|
||||
for fee in [interest, management, insurance, vat]
|
||||
if fee["due_days"] == 0
|
||||
]
|
||||
return response_data
|
||||
|
||||
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}")
|
||||
except Exception as e:
|
||||
logger.error(f"An error occurred while get_site_imges_data data: {str(e)}", exc_info=True)
|
||||
return None
|
||||
|
||||
# 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
|
||||
@staticmethod
|
||||
def write_cache_data(cacheSection, cacheId, cacheData):
|
||||
|
||||
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)
|
||||
|
||||
# Repayment amount: (principal + only those fees not due immediately i.e due_days != 0)
|
||||
# repayment_amount = amount + (sum(postpaid_fees) * tenor)
|
||||
if r.exists(cacheKey):
|
||||
r.unlink(cacheKey)
|
||||
|
||||
# Total amount: (upfront_payment + repayment_amount)
|
||||
total_amount = upfront_payment + repayment_amount
|
||||
# Set a key 'foo' with value 'bar'
|
||||
json_string = json.dumps(cacheData, indent=4)
|
||||
r.set(cacheKey, json_string, ex=BaseService.CACHE_DEFAULT_EXPIRE)
|
||||
|
||||
# Calculate the installment amount
|
||||
installment_amount = repayment_amount / offer.schedule
|
||||
# Verify by getting the value
|
||||
value = r.get(cacheKey)
|
||||
print(f"Value of {cacheKey}: {value}") # Output: Value of 'foo': bar
|
||||
|
||||
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}
|
||||
response_data = {
|
||||
"session_details": value,
|
||||
# "product_id": product_id,
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
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 Augustine’s 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
|
||||
+108
-66
@@ -1,25 +1,13 @@
|
||||
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.models import MembersProducts, Products, Members, ProductsContacts
|
||||
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):
|
||||
@@ -27,7 +15,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')
|
||||
@@ -35,57 +23,75 @@ 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']
|
||||
|
||||
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)
|
||||
page = 1
|
||||
limit = 20
|
||||
|
||||
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": "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)
|
||||
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)
|
||||
|
||||
# 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
|
||||
"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
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseHelper.success(data=response_data)
|
||||
@@ -106,13 +112,49 @@ class ContactService(BaseService):
|
||||
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 Augustine’s 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 dummy_message():
|
||||
dmm = "Dmummy Message" + str(random.randint(100, 400))
|
||||
mss = f"""
|
||||
{dmm}I truly believe Augustine’s 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
|
||||
|
||||
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.
|
||||
@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 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
|
||||
@@ -1,60 +1,60 @@
|
||||
from flask import request, jsonify
|
||||
from app.api.helpers.response_helper import ResponseHelper
|
||||
# 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 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 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 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()
|
||||
@@ -0,0 +1,214 @@
|
||||
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
|
||||
@@ -0,0 +1,142 @@
|
||||
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')
|
||||
+42
-36
@@ -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.error("GOT HERE 000001 ")
|
||||
data ={}
|
||||
logger.info("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.error("GOT HERE 000002 ")
|
||||
logger.info("GOT HERE 000002 ")
|
||||
if not data:
|
||||
invalid_data = {
|
||||
"error_message": "The link is invalid please try again later",
|
||||
@@ -155,11 +155,14 @@ 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)
|
||||
|
||||
logger.error(f"GOT HERE 000003 {reset_data} id = {reset_data.id}")
|
||||
username = user_data["username"]
|
||||
username = reset_data.username
|
||||
|
||||
member = Members.get_member_by_username(username)
|
||||
if not member:
|
||||
invalid_data = {
|
||||
@@ -170,10 +173,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": "",
|
||||
@@ -218,7 +221,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 = {
|
||||
@@ -226,44 +229,47 @@ 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)
|
||||
|
||||
@@ -294,7 +300,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 = {
|
||||
@@ -305,24 +311,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=[]
|
||||
|
||||
+664
-59
@@ -1,10 +1,20 @@
|
||||
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
|
||||
MembersProductsSettings, ProductsTemplates, MembersProfile, SubscriptionGenerative, ProductsColorStyle, \
|
||||
MembersWebfiles
|
||||
from app.api.helpers.response_helper import ResponseHelper
|
||||
from app.api.schemas.myproduct import MyProductSchema
|
||||
from app.api.schemas.provision import ProvisionSchema
|
||||
@@ -18,11 +28,102 @@ 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:
|
||||
@@ -35,42 +136,24 @@ class MyProductsService(BaseService):
|
||||
member_id = member_data.id
|
||||
|
||||
product_id = validated_data.get('product_id')
|
||||
|
||||
# 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({
|
||||
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({
|
||||
'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(),
|
||||
}
|
||||
@@ -94,6 +177,62 @@ 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:
|
||||
@@ -107,32 +246,38 @@ 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 product_id",
|
||||
"message": "Please provide valid product_id",
|
||||
"error_message": "Error - Please select a valid product to view",
|
||||
"data": None,
|
||||
"error": "Bad request"
|
||||
"error": f"Product with ID {product_id} does not exist."
|
||||
}, 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 = []
|
||||
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,
|
||||
})
|
||||
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,
|
||||
})
|
||||
|
||||
response_data = {
|
||||
"subscription_uid": subscription.uid,
|
||||
"subscription_id": subscription.id,
|
||||
"last_update": datetime.datetime.utcnow(),
|
||||
"percent_completed": random.randint(10, 99),
|
||||
"percent_completed": percent_completed,
|
||||
"activities": provision_activities_data
|
||||
}
|
||||
return ResponseHelper.success(data=response_data)
|
||||
@@ -165,15 +310,40 @@ 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:
|
||||
return {
|
||||
"message": "Please provide product_id",
|
||||
"data": None,
|
||||
"error": "Bad request"
|
||||
}, 400
|
||||
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
|
||||
|
||||
logger.info(f"GET HERE ******************************** : {data}", exc_info=True)
|
||||
mumberSub = MembersProducts.get_member_product_by_product_member_id(member_id, product_id)
|
||||
@@ -188,12 +358,21 @@ 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,
|
||||
@@ -241,15 +420,6 @@ 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]
|
||||
@@ -265,7 +435,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, "REFRESH_PRODUCT_SETTINGS"))
|
||||
args=(response_data, subscription_uid, KafkaMessage.REFRESH_PRODUCT_SETTINGS))
|
||||
thread.start()
|
||||
logger.error(f"After the Thread ******************** ")
|
||||
|
||||
@@ -302,9 +472,20 @@ 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}")
|
||||
@@ -312,6 +493,8 @@ 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 = {
|
||||
@@ -328,6 +511,8 @@ 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"
|
||||
@@ -373,6 +558,14 @@ 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
|
||||
|
||||
@@ -414,3 +607,415 @@ 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()
|
||||
|
||||
@@ -4,7 +4,9 @@ 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
|
||||
@@ -19,37 +21,101 @@ class OfficeAuthService:
|
||||
"test": "test123"
|
||||
}
|
||||
|
||||
# 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
|
||||
}
|
||||
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))
|
||||
|
||||
# Get the secret key from config
|
||||
secret_key = Config.JWT_SECRET_KEY
|
||||
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
|
||||
|
||||
# Generate the token
|
||||
token = jwt.encode(payload, secret_key, algorithm='HS256')
|
||||
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
|
||||
|
||||
# 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):
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
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
|
||||
|
||||
@@ -4,11 +4,74 @@ 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, ProductsDetails, ProductsDetails, ProvisionActions
|
||||
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
|
||||
|
||||
|
||||
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:
|
||||
|
||||
@@ -1,155 +1,725 @@
|
||||
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 datetime import datetime, timedelta, timezone
|
||||
from app.extensions import db
|
||||
from app.models import MembersProducts, Products, Members, ProductsDetails, ProductsDetails, ProvisionActions
|
||||
from app.models import MembersProducts, Products, Payments, Members, CustomTemplates, ProductsTemplates, MembersProfile, \
|
||||
ProductsDetails, MembersWebfiles, Signup
|
||||
|
||||
|
||||
class OfficeDashboardService(BaseService):
|
||||
@staticmethod
|
||||
def get_subscriptions_data():
|
||||
pass
|
||||
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
|
||||
|
||||
@staticmethod
|
||||
def get_dashboard_data():
|
||||
try:
|
||||
# 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)
|
||||
|
||||
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]
|
||||
subscription_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)
|
||||
|
||||
dashboard_data = {
|
||||
"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
|
||||
},
|
||||
"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
|
||||
},
|
||||
|
||||
"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
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
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
|
||||
@@ -0,0 +1,43 @@
|
||||
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
|
||||
|
||||
|
||||
@@ -184,15 +184,22 @@ class ProductsService(BaseService):
|
||||
}
|
||||
return ResponseHelper.success(data=response_data)
|
||||
|
||||
MembersProductsRefresh.create_subscription_refresh(member_id,product_id, subscription_uid)
|
||||
# if memberSubscription.uid != subscription_uid :
|
||||
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
|
||||
|
||||
|
||||
#products = MembersProducts.get_member_productlist_by_member_id(member_id)
|
||||
plannedRefresh = MembersProductsRefresh.create_subscription_refresh(member_id,product_id, subscription_uid)
|
||||
|
||||
# Simulate processing
|
||||
response_data = {
|
||||
"products_data": [],
|
||||
"message": "Rebuild Planned - will be completed in 90 seconds",
|
||||
"error_message": "",
|
||||
"refresh_uid": plannedRefresh.uid,
|
||||
"member_id":member_id,
|
||||
"uid": member_data.uid,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
from app.models import MembersPending, Members, Country, Signup
|
||||
from app.api.helpers.response_helper import ResponseHelper
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
|
||||
@@ -31,6 +31,7 @@ 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):
|
||||
@@ -60,7 +61,7 @@ class RegisterService(BaseService):
|
||||
previousAcc = Members.get_member_by_username(username)
|
||||
if previousAcc:
|
||||
response_data = {
|
||||
"error_message": "try another username ",
|
||||
"error_message": "Please try another username!",
|
||||
"error_message_key": "use_another_username",
|
||||
}
|
||||
return ResponseHelper.error(data=response_data)
|
||||
@@ -122,10 +123,21 @@ 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": [
|
||||
"list": country_list,
|
||||
"lists": [
|
||||
{"code": "US", "description": "United States"},
|
||||
{"code": "CA", "description": "Canada"},
|
||||
]
|
||||
@@ -156,7 +168,7 @@ class RegisterService(BaseService):
|
||||
|
||||
|
||||
@staticmethod
|
||||
def process_request(data):
|
||||
def start_account_register(data):
|
||||
try:
|
||||
with db.session.begin():
|
||||
|
||||
@@ -164,10 +176,24 @@ class RegisterService(BaseService):
|
||||
# Simulate processing
|
||||
firstname = validated_data.get('firstname')
|
||||
lastname = validated_data.get('lastname')
|
||||
email = validated_data.get('email')
|
||||
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
|
||||
|
||||
regData = MembersPending.add_members_pending( firstname, lastname, email)
|
||||
send_register_mail(regData.email, regData.uid, regData.id, firstname, lastname)
|
||||
BaseService.send_verify_signup_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,
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
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()
|
||||
|
||||
|
||||
@@ -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'])
|
||||
SubscriptionOptions.set_stripe_price_id(t.uid,price_create_result['price_id'])
|
||||
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
|
||||
|
||||
res_options.append({
|
||||
'option_id': t.id,
|
||||
|
||||
@@ -0,0 +1,291 @@
|
||||
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()
|
||||
@@ -0,0 +1,167 @@
|
||||
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()
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
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
|
||||
from app.models import MembersProductsSettings, MembersProducts, ProductsColorStyle, ProductsTemplates
|
||||
from threading import Thread
|
||||
import requests
|
||||
|
||||
|
||||
class WebContentsService(BaseService):
|
||||
@@ -14,28 +17,70 @@ 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 site description in the header",
|
||||
"site_logo_text": "MY-GOOD-LOGO",
|
||||
"site_contact_email": "email@specialemail.com",
|
||||
"site_description": "This is the site description in the header",
|
||||
"site_logo_text": "MY-SITE-LOGO",
|
||||
"site_contact_email": "email@email.com",
|
||||
"site_contact_phone": "911 111 1111",
|
||||
"site_keywords": "Responsive, HTML5, DSAThemes, Landing, Software, Mobile App, SaaS, Startup, Creative, Digital Product",
|
||||
"site_keywords": "Health, Practioner, myPage, telemedicine, Software, Mobile App, Health Specialty, Startup, Creative, Digital Health",
|
||||
"facebook": "myface.facebook.com",
|
||||
"twitter": "mytwit.twitter.com",
|
||||
"youtube": "myyou.youtube.com",
|
||||
"banner_text": "This is the main business text on the web page",
|
||||
"banner_description": "Naira",
|
||||
"banner_description": "We focus on your better health outcomes ",
|
||||
"footer_description": "Any text under the logo on the footer",
|
||||
"about_description": "Naira",
|
||||
"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",
|
||||
"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.",
|
||||
"about_title": "This is about title section",
|
||||
"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 ",
|
||||
"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. ",
|
||||
"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 we’ll get back to you right away",
|
||||
"contact_introduction": "Want to learn more about us, or speak with an expert? Let us know what you are looking for, and we’ll 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,
|
||||
}
|
||||
|
||||
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:
|
||||
@@ -45,8 +90,89 @@ 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
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
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
|
||||
@@ -0,0 +1,8 @@
|
||||
class MemberFileData:
|
||||
member_id: int
|
||||
member_uid: str
|
||||
file_group: str
|
||||
filename: str
|
||||
save_filename: str
|
||||
file_type: str
|
||||
file_size: str
|
||||
+34
-53
@@ -1,9 +1,10 @@
|
||||
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")
|
||||
@@ -14,21 +15,24 @@ class Config:
|
||||
|
||||
THIS_SITE_URL = os.getenv("THIS_SITE_URL", "https://qa-panel.mermsemr.com")
|
||||
|
||||
#Email Server
|
||||
SEND_EMAIL_FROM = os.environ.get("SEND_EMAIL_FROM","message@chiefsoft.com")
|
||||
SEND_EMAIL_PASS = os.environ.get("SEND_EMAIL_PASS","may12002!")
|
||||
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!")
|
||||
|
||||
# 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))
|
||||
@@ -36,60 +40,37 @@ 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")
|
||||
|
||||
# SIMBRELLA_ENDPOINT_RAC_CHECKS = os.getenv("SIMBRELLA_ENDPOINT_RAC_CHECKS", "RACCheck")
|
||||
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")
|
||||
|
||||
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()
|
||||
|
||||
+19
-25
@@ -1,16 +1,4 @@
|
||||
# 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
|
||||
@@ -21,21 +9,27 @@ 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','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']
|
||||
__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']
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
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);
|
||||
|
||||
'''
|
||||
@@ -0,0 +1,70 @@
|
||||
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}>'
|
||||
@@ -0,0 +1,95 @@
|
||||
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
@@ -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
@@ -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}>"
|
||||
|
||||
@@ -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}>'
|
||||
|
||||
@@ -30,7 +30,12 @@ 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
|
||||
@@ -46,7 +51,7 @@ class MembersProductsRefresh(db.Model):
|
||||
)
|
||||
|
||||
try:
|
||||
logger.info(f" About to Insert Subscription Data {subscription.member_id} ")
|
||||
logger.info(f" About to Insert Subscription REfresh Data {subscription.member_id} ")
|
||||
db.session.add(subscription)
|
||||
db.session.flush()
|
||||
except IntegrityError as err:
|
||||
|
||||
+127
-13
@@ -1,10 +1,11 @@
|
||||
from datetime import datetime, timezone
|
||||
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 Members(db.Model):
|
||||
__tablename__ = 'members'
|
||||
|
||||
@@ -19,36 +20,56 @@ 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(100), nullable=True)
|
||||
lastname = db.Column(db.String(25), 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.account_id,
|
||||
"account_id": self.username,
|
||||
"username": 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,
|
||||
"stripe_customer_id": self.stripe_customer_id
|
||||
"next_billing": self.next_billing,
|
||||
"trial_end": self.trial_end,
|
||||
"stripe_customer_id": self.stripe_customer_id,
|
||||
"profile_picture": self.profile_picture,
|
||||
}
|
||||
|
||||
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()
|
||||
@@ -59,7 +80,6 @@ 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
|
||||
@@ -76,19 +96,83 @@ 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 add_member(cls, firstname, lastname, email, username,password, country):
|
||||
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)
|
||||
|
||||
# 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)
|
||||
)
|
||||
@@ -99,10 +183,9 @@ 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.")
|
||||
|
||||
@@ -111,14 +194,33 @@ 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"Reset with UID {member_uid} does not exist.")
|
||||
raise ValueError(f"Member 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):
|
||||
@@ -142,4 +244,16 @@ class Members(db.Model):
|
||||
offset = (page - 1) * limit
|
||||
query = query.limit(limit).offset(offset)
|
||||
|
||||
return query.all(), total_count
|
||||
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()
|
||||
|
||||
@@ -40,10 +40,30 @@ 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:
|
||||
raise ValueError(f"No Member Actions")
|
||||
return None
|
||||
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.
|
||||
|
||||
@@ -55,38 +55,9 @@ 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=#
|
||||
'''
|
||||
@@ -30,6 +30,12 @@ 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)
|
||||
@@ -41,6 +47,15 @@ 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))
|
||||
@@ -64,11 +79,51 @@ class MembersProducts(db.Model):
|
||||
|
||||
@classmethod
|
||||
def get_member_product_by_subscription_uid(cls, subscription_uid):
|
||||
member_product = cls.query.filter_by(subscription_uid=str(subscription_uid)).all()
|
||||
member_product = cls.query.filter_by(uid=str(subscription_uid)).first()
|
||||
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):
|
||||
@@ -130,20 +185,22 @@ 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,
|
||||
# 'name': self.products.name,
|
||||
# 'description': self.products.description,
|
||||
'member_id': self.member_id,
|
||||
'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
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,30 @@ 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
|
||||
@@ -96,8 +120,17 @@ 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 ):
|
||||
@@ -118,6 +151,23 @@ 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.
|
||||
|
||||
@@ -26,6 +26,7 @@ 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())
|
||||
|
||||
@@ -43,6 +44,13 @@ 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):
|
||||
@@ -53,7 +61,7 @@ class MembersProfile(db.Model):
|
||||
|
||||
|
||||
@classmethod
|
||||
def create_member_profile(cls, member_id ,practice,specialization,introduction):
|
||||
def create_member_profile(cls, member_id ,practice,specialization,introduction,url_name):
|
||||
# Create the subscription
|
||||
'''
|
||||
merms_panel=# select * from members_profile;
|
||||
@@ -62,13 +70,14 @@ class MembersProfile(db.Model):
|
||||
(0 rows)
|
||||
'''
|
||||
|
||||
logger.info(f" Data for Profile Data {member_id} ,{practice} ,{specialization}, {introduction} ")
|
||||
logger.info(f" Data for Profile Data {member_id} ,{practice} ,{specialization}, {introduction} {url_name} ")
|
||||
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)
|
||||
)
|
||||
@@ -92,6 +101,7 @@ 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
|
||||
}
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
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
@@ -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}>'
|
||||
@@ -0,0 +1,87 @@
|
||||
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}>'
|
||||
@@ -28,13 +28,13 @@ class PasswordReset(db.Model):
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_rest_with_uid(cls, pening_uid):
|
||||
def get_rest_with_uid(cls, pending_uid):
|
||||
"""
|
||||
Return all offers in dictionary format.
|
||||
"""
|
||||
pass_reset = cls.query.filter_by(uid = pening_uid).first()
|
||||
pass_reset = cls.query.filter_by(uid = pending_uid).first()
|
||||
if not pass_reset:
|
||||
raise ValueError(f"Password Reset with UID {pening_uid} does not exist.")
|
||||
raise ValueError(f"Password Reset with UID {pending_uid} does not exist.")
|
||||
return pass_reset
|
||||
|
||||
@classmethod
|
||||
|
||||
+78
-26
@@ -1,10 +1,10 @@
|
||||
from datetime import datetime, timezone
|
||||
from datetime import datetime, timezone, timedelta
|
||||
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,48 +16,100 @@ class Payments(db.Model):
|
||||
)
|
||||
uid = db.Column(db.String(150), nullable=True)
|
||||
member_id = db.Column(db.Integer, nullable=False)
|
||||
product_id = db.Column(db.String(25), nullable=False)
|
||||
processor = db.Column(db.String(25), nullable=False)
|
||||
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)
|
||||
status = db.Column(db.Integer, nullable=True, default=1)
|
||||
added = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
updated = db.Column(db.DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
||||
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"
|
||||
'''
|
||||
|
||||
@classmethod
|
||||
def add_payment(cls, customer_id, account_id, transaction_id, data=None):
|
||||
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)
|
||||
|
||||
# Save the response
|
||||
rac_check = cls(
|
||||
customer_id=customer_id,
|
||||
account_id=account_id,
|
||||
transaction_id=transaction_id,
|
||||
pay_data = cls(
|
||||
member_id=member_id,
|
||||
payment_uid=payment_uid,
|
||||
option_name=option_name,
|
||||
amount=amount,
|
||||
option_type=option_type,
|
||||
added=datetime.now(timezone.utc),
|
||||
updated=datetime.now(timezone.utc)
|
||||
sub_start=datetime.now(timezone.utc),
|
||||
next_billing = next_billing_date
|
||||
)
|
||||
|
||||
try:
|
||||
db.session.add(rac_check)
|
||||
db.session.add(pay_data)
|
||||
except IntegrityError as err:
|
||||
raise ValueError(f"Database integrity error: {err}")
|
||||
return rac_check
|
||||
return pay_data
|
||||
|
||||
|
||||
@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 {
|
||||
"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
|
||||
"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
|
||||
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<LoanOffer {self.id}>'
|
||||
return f'<Payments {self.id}>'
|
||||
|
||||
+28
-3
@@ -27,11 +27,15 @@ 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",
|
||||
@@ -68,12 +72,26 @@ 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.all()
|
||||
product_list = cls.query.order_by(cls.list_order.asc()).all()
|
||||
|
||||
if not product_list:
|
||||
raise ValueError(f"No available Products")
|
||||
@@ -86,7 +104,9 @@ 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.")
|
||||
# raise ValueError(f"pProduct with ID {product_id} does not exist.")
|
||||
logger.error(f"Product with ID {product_id} does not exist.")
|
||||
return None
|
||||
return productItem
|
||||
|
||||
def to_dict(self):
|
||||
@@ -97,9 +117,14 @@ 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
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
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}>'
|
||||
@@ -0,0 +1,113 @@
|
||||
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}>'
|
||||
|
||||
@@ -37,7 +37,7 @@ class ProductsDetails(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.")
|
||||
raise ValueError(f"Product with ID {product_id} does not exist.")
|
||||
return productItem
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,11 @@ 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'
|
||||
@@ -15,16 +20,48 @@ 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")
|
||||
# raise ValueError(f"Templates with Product ID {product_id} not found")
|
||||
return None
|
||||
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,
|
||||
@@ -34,8 +71,9 @@ class ProductsTemplates(db.Model):
|
||||
"status": self.status,
|
||||
"owner_uid": self.owner_uid,
|
||||
"provision_name": self.provision_name,
|
||||
"provision_name": self.provision_name
|
||||
"flavor": self.flavor,
|
||||
"added": self.added.isoformat() if self.added else None
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<LoanOffer {self.id}>'
|
||||
return f'<ProductsTemplates {self.id}>'
|
||||
|
||||
@@ -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,6 +47,24 @@ 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.
|
||||
@@ -56,6 +74,7 @@ class ProvisionActions(db.Model):
|
||||
'uid': self.uid,
|
||||
'product_uid': self.product_uid,
|
||||
'action': self.action,
|
||||
'percent_completed': self.percent_completed,
|
||||
'added': self.added,
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
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
|
||||
@@ -0,0 +1,102 @@
|
||||
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}>'
|
||||
|
||||
@@ -17,6 +17,7 @@ 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
|
||||
@@ -64,6 +65,7 @@ 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,
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
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
|
||||
@@ -0,0 +1,42 @@
|
||||
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
|
||||
@@ -0,0 +1,135 @@
|
||||
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 >
|
||||
@@ -0,0 +1,37 @@
|
||||
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}")
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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
|
||||
@@ -7,6 +7,8 @@ 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}
|
||||
|
||||
@@ -7,6 +7,8 @@ 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}
|
||||
|
||||
+9
-1
@@ -45,4 +45,12 @@ pycountry
|
||||
|
||||
stripe
|
||||
|
||||
requests
|
||||
requests
|
||||
|
||||
openai
|
||||
|
||||
redis
|
||||
|
||||
sendgrid
|
||||
|
||||
boto3
|
||||
Reference in New Issue
Block a user