customeranalytics 0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- customeranalytics/__init__.py +319 -0
- customeranalytics/configs.py +480 -0
- customeranalytics/data_storage_configurations/__init__.py +245 -0
- customeranalytics/data_storage_configurations/data_access.py +165 -0
- customeranalytics/data_storage_configurations/data_works_pipeline.py +207 -0
- customeranalytics/data_storage_configurations/es_create_index.py +544 -0
- customeranalytics/data_storage_configurations/logger.py +36 -0
- customeranalytics/data_storage_configurations/query_es.py +157 -0
- customeranalytics/data_storage_configurations/reports.py +684 -0
- customeranalytics/data_storage_configurations/schedule_data_integration.py +355 -0
- customeranalytics/docs/queries.yaml +245 -0
- customeranalytics/docs/web_configs.yaml +2 -0
- customeranalytics/exploratory_analysis/__init__.py +109 -0
- customeranalytics/exploratory_analysis/churn.py +232 -0
- customeranalytics/exploratory_analysis/cohorts.py +535 -0
- customeranalytics/exploratory_analysis/descriptive_statistics.py +470 -0
- customeranalytics/exploratory_analysis/funnels.py +407 -0
- customeranalytics/exploratory_analysis/product_analytics.py +340 -0
- customeranalytics/exploratory_analysis/promotion_analytics.py +299 -0
- customeranalytics/exploratory_analysis/rfm.py +202 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_avg_order_count_per_promo_per_cust.csv +99 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_chart_1_search.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_chart_2_search.csv +46 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_chart_3_search.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_chart_4_search.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_churn.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_churn_weekly.csv +10 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_client_feature_predicted.csv +1590 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_client_kpis.csv +7060 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_clvrfm_anomaly.csv +561 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_clvsegments_amount.csv +8 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_customer_journey.csv +18 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_clv.csv +103 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_downloads.csv +68 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_from_1_to_2.csv +66 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_from_2_to_3.csv +64 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_from_3_to_4.csv +55 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_dimension_values.csv +199 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_funnel.csv +36 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_funnel_downloads.csv +68 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_inorganic_ratio.csv +6070 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_orders.csv +57 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_organic_orders.csv +64 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_products_of_sales.csv +12574 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_promotion_discount.csv +64 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_promotion_revenue.csv +6070 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_dcohort_anomaly.csv +6 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_dcohort_anomaly_2.csv +118 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_deliver.csv +47 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_deliver_kpis.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_deliver_weekday_hour.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_dfunnel_anomaly.csv +118 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_dimension_kpis.csv +199 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_dorders_anomaly.csv +85 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_frequency_clusters.csv +6 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_frequency_recency.csv +3740 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_funnel.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_funnel_downloads.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_inorganic_ratio.csv +2353 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_orders.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_organic_orders.csv +2353 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_inorganic_orders_per_promotion_per_day.csv +6070 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_kpis.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_monetary_clusters.csv +6 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_monetary_frequency.csv +3740 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_monthly_funnel.csv +5 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_monthly_funnel_downloads.csv +5 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_monthly_orders.csv +4 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_most_combined_products.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_most_ordered_categories.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_most_ordered_products.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_order_and_payment_amount_differences.csv +91 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_prepare.csv +101 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_prepare_weekday_hour.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_product_kpis.csv +201 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_amount_accept.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_amount_reject.csv +7 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_orders_accept.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_orders_reject.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_comparison.csv +91 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_kpis.csv +99 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_number_of_customer.csv +99 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_amount_accept.csv +81 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_amount_reject.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_orders_accept.csv +55 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_orders_reject.csv +37 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_purchase_amount_distribution.csv +22 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_recency_clusters.csv +6 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_recency_monetary.csv +3740 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_rfm.csv +2001 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_ride.csv +101 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_ride_weekday_hour.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segmentation.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_daily_before_after_amount.csv +10 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_daily_before_after_orders.csv +9 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_monthly_before_after_amount.csv +10 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_monthly_before_after_orders.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_weekly_before_after_amount.csv +10 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_weekly_before_after_orders.csv +10 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_user_counts_per_order_seq.csv +47 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_average_order_per_user.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_average_payment_amount.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_average_session_per_user.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_downloads.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_from_1_to_2.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_from_2_to_3.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_from_3_to_4.csv +12 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_funnel.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_funnel_downloads.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_orders.csv +10 -0
- customeranalytics/ml_process/__init__.py +64 -0
- customeranalytics/ml_process/ab_test.py +615 -0
- customeranalytics/ml_process/anomaly_detection.py +456 -0
- customeranalytics/ml_process/clv_prediction.py +301 -0
- customeranalytics/ml_process/customer_segmentation.py +354 -0
- customeranalytics/ml_process/delivery_analytics.py +754 -0
- customeranalytics/utils.py +186 -0
- customeranalytics/web/app/__init__.py +37 -0
- customeranalytics/web/app/base/__init__.py +9 -0
- customeranalytics/web/app/base/forms.py +16 -0
- customeranalytics/web/app/base/models.py +43 -0
- customeranalytics/web/app/base/routes.py +126 -0
- customeranalytics/web/app/base/static/assets/css/app.css +20 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Black.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Black.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-BlackItalic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-BlackItalic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Bold.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Bold.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-BoldItalic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-BoldItalic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBold.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBold.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBoldItalic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBoldItalic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLight-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLight-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLightItalic-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLightItalic-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Italic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Italic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Light-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Light-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-LightItalic-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-LightItalic-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Medium.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Medium.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-MediumItalic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-MediumItalic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Regular.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Regular.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBold.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBold.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBoldItalic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBoldItalic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Thin-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Thin-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ThinItalic-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ThinItalic-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-italic.var.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-upright.var.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter.var.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.eot +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.svg +3570 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.ttf +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.eot +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.svg +801 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.ttf +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.eot +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.svg +5028 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.ttf +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/avatar-1.png +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/avatar-2.png +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/avatar-3.png +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/avatar-4.png +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/avatar-5.png +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/info.jpeg +0 -0
- customeranalytics/web/app/base/static/assets/img/icons/customanality.png +0 -0
- customeranalytics/web/app/base/static/assets/img/icons/icon-48x48.png +0 -0
- customeranalytics/web/app/base/static/assets/js/app.js +2 -0
- customeranalytics/web/app/base/static/assets/js/app.js.LICENSE +566 -0
- customeranalytics/web/app/base/static/assets/js/app.js.LICENSE.txt +556 -0
- customeranalytics/web/app/base/static/assets/js/modules/bootstrap.js +15 -0
- customeranalytics/web/app/base/static/assets/js/modules/chartjs.js +4 -0
- customeranalytics/web/app/base/static/assets/js/modules/feather.js +8 -0
- customeranalytics/web/app/base/static/assets/js/modules/flatpickr.js +4 -0
- customeranalytics/web/app/base/static/assets/js/modules/moment.js +4 -0
- customeranalytics/web/app/base/static/assets/js/modules/sidebar.js +23 -0
- customeranalytics/web/app/base/static/assets/js/modules/theme.js +16 -0
- customeranalytics/web/app/base/templates/accounts/login.html +81 -0
- customeranalytics/web/app/base/templates/accounts/register.html +80 -0
- customeranalytics/web/app/base/templates/includes/footer.html +28 -0
- customeranalytics/web/app/base/templates/includes/navigation.html +51 -0
- customeranalytics/web/app/base/templates/includes/scripts.html +3 -0
- customeranalytics/web/app/base/templates/includes/sidebar.html +146 -0
- customeranalytics/web/app/base/templates/layouts/base-fullscreen.html +36 -0
- customeranalytics/web/app/base/templates/layouts/base.html +84 -0
- customeranalytics/web/app/base/util.py +30 -0
- customeranalytics/web/app/home/__init__.py +9 -0
- customeranalytics/web/app/home/forms.py +1039 -0
- customeranalytics/web/app/home/models.py +438 -0
- customeranalytics/web/app/home/profiles.py +310 -0
- customeranalytics/web/app/home/routes.py +386 -0
- customeranalytics/web/app/home/search.py +288 -0
- customeranalytics/web/app/home/static/assets/img/avatars/avatar-1.png +0 -0
- customeranalytics/web/app/home/static/assets/img/avatars/avatar-2.png +0 -0
- customeranalytics/web/app/home/static/assets/img/avatars/avatar-3.png +0 -0
- customeranalytics/web/app/home/static/assets/img/avatars/avatar-4.png +0 -0
- customeranalytics/web/app/home/static/assets/img/avatars/avatar-5.png +0 -0
- customeranalytics/web/app/home/static/assets/img/icons/customanality.png +0 -0
- customeranalytics/web/app/home/static/assets/img/icons/icon-48x48.png +0 -0
- customeranalytics/web/app/home/templates/abtest-product.html +280 -0
- customeranalytics/web/app/home/templates/abtest-promotion.html +362 -0
- customeranalytics/web/app/home/templates/abtest-segments.html +298 -0
- customeranalytics/web/app/home/templates/add-data-delivery.html +184 -0
- customeranalytics/web/app/home/templates/add-data-product.html +177 -0
- customeranalytics/web/app/home/templates/add-data-purchase.html +392 -0
- customeranalytics/web/app/home/templates/anomaly.html +261 -0
- customeranalytics/web/app/home/templates/clv.html +211 -0
- customeranalytics/web/app/home/templates/cohorts.html +308 -0
- customeranalytics/web/app/home/templates/customer-segmentation.html +308 -0
- customeranalytics/web/app/home/templates/data-es.html +152 -0
- customeranalytics/web/app/home/templates/data-execute.html +397 -0
- customeranalytics/web/app/home/templates/delivery.html +404 -0
- customeranalytics/web/app/home/templates/funnel-customer.html +240 -0
- customeranalytics/web/app/home/templates/funnel-session.html +236 -0
- customeranalytics/web/app/home/templates/index.html +524 -0
- customeranalytics/web/app/home/templates/index2.html +515 -0
- customeranalytics/web/app/home/templates/page-403.html +46 -0
- customeranalytics/web/app/home/templates/page-404.html +45 -0
- customeranalytics/web/app/home/templates/page-500.html +45 -0
- customeranalytics/web/app/home/templates/pages-blank.html +33 -0
- customeranalytics/web/app/home/templates/pages-sign-in.html +67 -0
- customeranalytics/web/app/home/templates/pages-sign-up.html +61 -0
- customeranalytics/web/app/home/templates/product.html +203 -0
- customeranalytics/web/app/home/templates/profile.html +1009 -0
- customeranalytics/web/app/home/templates/rfm.html +254 -0
- customeranalytics/web/app/home/templates/search.html +167 -0
- customeranalytics/web/app/home/templates/settings.html +205 -0
- customeranalytics/web/app/home/templates/stats-desc.html +230 -0
- customeranalytics/web/app/home/templates/stats-purchase.html +221 -0
- customeranalytics/web/config.py +30 -0
- customeranalytics/web/db.sqlite3 +0 -0
- customeranalytics/web/run.py +30 -0
- customeranalytics-0.1.dist-info/METADATA +1102 -0
- customeranalytics-0.1.dist-info/RECORD +254 -0
- customeranalytics-0.1.dist-info/WHEEL +4 -0
- customeranalytics-0.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import os
|
|
3
|
+
import inspect
|
|
4
|
+
from os.path import join
|
|
5
|
+
import yaml
|
|
6
|
+
|
|
7
|
+
from customeranalytics.configs import none_types
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def current_date_to_day():
|
|
11
|
+
"""
|
|
12
|
+
recent date of converting to datetime from isoformat.
|
|
13
|
+
:return: datetime
|
|
14
|
+
"""
|
|
15
|
+
return datetime.datetime.strptime(str(datetime.datetime.now())[0:19], '%Y-%m-%d %H:%M:%S')
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def find_week_of_monday(date):
|
|
19
|
+
"""
|
|
20
|
+
Monday of each week. This helps us to aggregate data per week.
|
|
21
|
+
:param date: datetime format; %Y-%m-%d %H:%M:%S
|
|
22
|
+
:return: datetime
|
|
23
|
+
"""
|
|
24
|
+
week_day = datetime.datetime.strptime(str(date)[0:10], "%Y-%m-%d").isoweekday()
|
|
25
|
+
return datetime.datetime.strptime(str(date)[0:10], "%Y-%m-%d") - datetime.timedelta(days=week_day-1)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def convert_dt_to_day_str(date):
|
|
29
|
+
"""
|
|
30
|
+
converting date time to str date. e.g; 2020-12-12 00:00:14 - 2020-12-12.
|
|
31
|
+
:param date: datetime format; %Y-%m-%d %H:%M:%S
|
|
32
|
+
:return: string date
|
|
33
|
+
"""
|
|
34
|
+
return datetime.datetime.strptime(str(date)[0:10], "%Y-%m-%d")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def convert_str_to_hour(date):
|
|
38
|
+
"""
|
|
39
|
+
string date is converting to datetime and grabbing hour from it.
|
|
40
|
+
:param date: datetime format; %Y-%m-%d %H:%M:%S
|
|
41
|
+
:return: hour [0 - 24)
|
|
42
|
+
"""
|
|
43
|
+
return datetime.datetime.strptime(str(date)[0:10] + ' ' + str(date)[11:19], "%Y-%m-%d %H:%M:%S").hour
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def convert_to_date(date):
|
|
47
|
+
"""
|
|
48
|
+
Convert str date to datetime. If is NULL skip the process and return None.
|
|
49
|
+
:param date: str format; %Y-%m-%d %H:%M:%S
|
|
50
|
+
:return:
|
|
51
|
+
"""
|
|
52
|
+
if date == date and date not in none_types:
|
|
53
|
+
return datetime.datetime.strptime(str(date)[0:10] + ' ' + str(date)[11:19], "%Y-%m-%d %H:%M:%S")
|
|
54
|
+
else:
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def calculate_time_diff(date1, date2, period):
|
|
59
|
+
"""
|
|
60
|
+
- Calculating total seconds between date1 (start date) and date2 (end date).
|
|
61
|
+
- Calculated total seconds is divided to time period.
|
|
62
|
+
:param date1: start date
|
|
63
|
+
:param date2: end date
|
|
64
|
+
:param period: period of time that can be measured a countable number of times between start date and end date.
|
|
65
|
+
:return: difference float
|
|
66
|
+
"""
|
|
67
|
+
diff = 0
|
|
68
|
+
division = (60 * 60)
|
|
69
|
+
if date1 == date1 and date2 == date2:
|
|
70
|
+
if period == 'hour':
|
|
71
|
+
division = (60 * 60)
|
|
72
|
+
if period == 'day':
|
|
73
|
+
division = (60 * 60 * 24)
|
|
74
|
+
if period == 'week':
|
|
75
|
+
division = (60 * 60 * 24 * 7)
|
|
76
|
+
diff = int(abs(date1 - date2).total_seconds() / division)
|
|
77
|
+
return diff
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def convert_to_day(date):
|
|
81
|
+
"""
|
|
82
|
+
Convert str date to day.
|
|
83
|
+
:param date: str format; %Y-%m-%d
|
|
84
|
+
:return:
|
|
85
|
+
"""
|
|
86
|
+
return datetime.datetime.strptime(str(date)[0:10], "%Y-%m-%d")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def read_yaml(directory, filename):
|
|
90
|
+
"""
|
|
91
|
+
reading yaml file with given directory
|
|
92
|
+
:param directory: path
|
|
93
|
+
:param filename: file name with .yaml format
|
|
94
|
+
:return:
|
|
95
|
+
"""
|
|
96
|
+
with open(join(directory, "", filename)) as file:
|
|
97
|
+
docs = yaml.full_load(file)
|
|
98
|
+
return docs
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def convert_to_iso_format(date):
|
|
102
|
+
"""
|
|
103
|
+
converting iso-format to timestamp Ex: from 2021-01-01T00:00:00 to 2021-01-01 00:00:00
|
|
104
|
+
"""
|
|
105
|
+
if len(str(date)) == 10:
|
|
106
|
+
return datetime.datetime.strptime(str(date)[0:10] + ' 00:00:00', "%Y-%m-%d %H:%M:%S").isoformat()
|
|
107
|
+
if len(str(date)) == 19:
|
|
108
|
+
return datetime.datetime.strptime(str(date)[0:10] + ' ' + str(date)[11:19], "%Y-%m-%d %H:%M:%S").isoformat()
|
|
109
|
+
if len(str(date)) != 10 and len(str(date)) != 19:
|
|
110
|
+
return date.isoformat()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def get_index_group(index):
|
|
114
|
+
"""
|
|
115
|
+
when Exploratory Analysis or Ml Processes work on dimension this will hep us to get exact dimension name.
|
|
116
|
+
If it is calculating for aLL data, this will return 'main'.
|
|
117
|
+
"""
|
|
118
|
+
if index in ['orders', 'downloads']:
|
|
119
|
+
return 'main'
|
|
120
|
+
else:
|
|
121
|
+
return index
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def convert_dt_to_month_str(date):
|
|
125
|
+
"""
|
|
126
|
+
converting date time to str date. e.g; 2020-12-12 00:00:14 - 2020-12-12.
|
|
127
|
+
:param date: datetime format; %Y-%m-%d %H:%M:%S
|
|
128
|
+
:return: string date
|
|
129
|
+
"""
|
|
130
|
+
return datetime.datetime.strptime(str(date)[0:7], "%Y-%m")
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def sqlite_string_converter(_str, back_to_normal=False):
|
|
134
|
+
"""
|
|
135
|
+
when query or path is inserted into the sqlite db, it is need to be convert ''' and removing back slashes.
|
|
136
|
+
:param _str: query string Ex: " SELECT * FROm table ..."
|
|
137
|
+
:param back_to_normal: convert back to normal True / False
|
|
138
|
+
:return: string query
|
|
139
|
+
"""
|
|
140
|
+
if back_to_normal:
|
|
141
|
+
return _str.replace("#&_5", "'").replace("+", " ") + ' '
|
|
142
|
+
else:
|
|
143
|
+
return _str.replace("'", "#&_5").replace("\r", " ").replace("\n", " ").replace(" ", "+")
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def abspath_for_sample_data():
|
|
147
|
+
"""
|
|
148
|
+
get customer_analytics path. Ex: ....../customer_analytics
|
|
149
|
+
:return: current folder path
|
|
150
|
+
"""
|
|
151
|
+
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
|
152
|
+
base_name = os.path.basename(currentdir)
|
|
153
|
+
while base_name != 'customeranalytics':
|
|
154
|
+
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
|
155
|
+
base_name = os.path.basename(currentdir)
|
|
156
|
+
return currentdir
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def dimension_decision(order_index):
|
|
160
|
+
"""
|
|
161
|
+
Decision of dimension.
|
|
162
|
+
if order_index = 'Orders' it will be whole data, if it is not it will be executed for a dimension
|
|
163
|
+
:param order_index:
|
|
164
|
+
:return: True/False
|
|
165
|
+
"""
|
|
166
|
+
if order_index != 'orders':
|
|
167
|
+
return True
|
|
168
|
+
else:
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def formating_numbers(num):
|
|
173
|
+
"""
|
|
174
|
+
Human formatting for long numbers as strings
|
|
175
|
+
"""
|
|
176
|
+
magnitude = 0
|
|
177
|
+
while abs(num) >= 1000:
|
|
178
|
+
magnitude += 1
|
|
179
|
+
num /= 1000.0
|
|
180
|
+
# add more suffixes if you need them
|
|
181
|
+
if num % 1 == 0:
|
|
182
|
+
num = int(num)
|
|
183
|
+
return num + ['', 'K', 'M', 'G', 'T', 'P'][magnitude]
|
|
184
|
+
|
|
185
|
+
else:
|
|
186
|
+
return '%.2f%s' % (num, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from flask import Flask
|
|
2
|
+
from flask_login import LoginManager
|
|
3
|
+
from flask_sqlalchemy import SQLAlchemy
|
|
4
|
+
from importlib import import_module
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
db = SQLAlchemy()
|
|
8
|
+
login_manager = LoginManager()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def register_extensions(app):
|
|
12
|
+
db.init_app(app)
|
|
13
|
+
login_manager.init_app(app)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def register_blueprints(app):
|
|
17
|
+
for module_name in ('base', 'home'):
|
|
18
|
+
module = import_module('.{}.routes'.format(module_name), package=__name__)
|
|
19
|
+
app.register_blueprint(module.blueprint)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def configure_database(app):
|
|
23
|
+
with app.app_context():
|
|
24
|
+
db.create_all()
|
|
25
|
+
|
|
26
|
+
@app.teardown_request
|
|
27
|
+
def shutdown_session(exception=None):
|
|
28
|
+
db.session.remove()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def create_app(config):
|
|
32
|
+
app = Flask(__name__, static_folder='base/static')
|
|
33
|
+
app.config.from_object(config)
|
|
34
|
+
register_extensions(app)
|
|
35
|
+
register_blueprints(app)
|
|
36
|
+
configure_database(app)
|
|
37
|
+
return app
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from flask_wtf import FlaskForm
|
|
2
|
+
from wtforms import StringField, PasswordField
|
|
3
|
+
from wtforms.validators import InputRequired, Email, DataRequired
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LoginForm(FlaskForm):
|
|
7
|
+
username = StringField('Username', id='username_login', validators=[DataRequired()])
|
|
8
|
+
password = PasswordField('Password', id='pwd_login', validators=[DataRequired()])
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CreateAccountForm(FlaskForm):
|
|
12
|
+
username = StringField('Username', id='username_create', validators=[DataRequired()])
|
|
13
|
+
email= StringField('Email', id='email_create', validators=[DataRequired(), Email()])
|
|
14
|
+
password = PasswordField('Password', id='pwd_create', validators=[DataRequired()])
|
|
15
|
+
|
|
16
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from flask_login import UserMixin
|
|
2
|
+
from sqlalchemy import Column, Integer, String
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from sqlalchemy import Binary
|
|
6
|
+
except:
|
|
7
|
+
from sqlalchemy import LargeBinary as Binary
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
from .. import db, login_manager
|
|
11
|
+
from .util import hash_pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class User(db.Model, UserMixin):
|
|
15
|
+
__tablename__ = 'User'
|
|
16
|
+
id = Column(Integer, primary_key=True)
|
|
17
|
+
username = Column(String, unique=True)
|
|
18
|
+
email = Column(String, unique=True)
|
|
19
|
+
password = Column(Binary)
|
|
20
|
+
|
|
21
|
+
def __init__(self, **kwargs):
|
|
22
|
+
for property, value in kwargs.items():
|
|
23
|
+
if hasattr(value, '__iter__') and not isinstance(value, str):
|
|
24
|
+
value = value[0]
|
|
25
|
+
|
|
26
|
+
if property == 'password':
|
|
27
|
+
value = hash_pass(value)
|
|
28
|
+
setattr(self, property, value)
|
|
29
|
+
|
|
30
|
+
def __repr__(self):
|
|
31
|
+
return str(self.username)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@login_manager.user_loader
|
|
35
|
+
def user_loader(id):
|
|
36
|
+
return User.query.filter_by(id=id).first()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@login_manager.request_loader
|
|
40
|
+
def request_loader(request):
|
|
41
|
+
username = request.form.get('username')
|
|
42
|
+
user = User.query.filter_by(username=username).first()
|
|
43
|
+
return user if user else None
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from flask import jsonify, render_template, redirect, request, url_for
|
|
3
|
+
from flask_login import (
|
|
4
|
+
current_user,
|
|
5
|
+
login_required,
|
|
6
|
+
login_user,
|
|
7
|
+
logout_user
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from .. import db, login_manager
|
|
11
|
+
from . import blueprint
|
|
12
|
+
from .forms import LoginForm, CreateAccountForm
|
|
13
|
+
from .models import User
|
|
14
|
+
from customeranalytics.data_storage_configurations.logger import LogsBasicConfeger
|
|
15
|
+
|
|
16
|
+
from .util import verify_pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
LogsBasicConfeger()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@blueprint.route('/')
|
|
23
|
+
def route_default():
|
|
24
|
+
return redirect(url_for('base_blueprint.login'))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@blueprint.route('/login', methods=['GET', 'POST'])
|
|
28
|
+
def login():
|
|
29
|
+
login_form = LoginForm(request.form)
|
|
30
|
+
if 'login' in request.form:
|
|
31
|
+
|
|
32
|
+
# read form data
|
|
33
|
+
username = request.form['username']
|
|
34
|
+
password = request.form['password']
|
|
35
|
+
|
|
36
|
+
# Locate user
|
|
37
|
+
user = User.query.filter_by(username=username).first()
|
|
38
|
+
|
|
39
|
+
# Check the password
|
|
40
|
+
if user and verify_pass( password, user.password):
|
|
41
|
+
|
|
42
|
+
login_user(user)
|
|
43
|
+
|
|
44
|
+
return redirect(url_for('base_blueprint.route_default'))
|
|
45
|
+
|
|
46
|
+
# Something (user or pass) is not ok
|
|
47
|
+
return render_template('accounts/login.html', msg='Wrong user or password', form=login_form)
|
|
48
|
+
|
|
49
|
+
if not current_user.is_authenticated:
|
|
50
|
+
return render_template( 'accounts/login.html',
|
|
51
|
+
form=login_form)
|
|
52
|
+
return redirect(url_for('home_blueprint.index'))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@blueprint.route('/register', methods=['GET', 'POST'])
|
|
56
|
+
def register():
|
|
57
|
+
login_form = LoginForm(request.form)
|
|
58
|
+
create_account_form = CreateAccountForm(request.form)
|
|
59
|
+
if 'register' in request.form:
|
|
60
|
+
|
|
61
|
+
username, email = request.form['username'], request.form['email']
|
|
62
|
+
|
|
63
|
+
# check username exists
|
|
64
|
+
user = User.query.filter_by(username=username).first()
|
|
65
|
+
if user:
|
|
66
|
+
return render_template('accounts/register.html',
|
|
67
|
+
msg='Username already registered',
|
|
68
|
+
success=False,
|
|
69
|
+
form=create_account_form)
|
|
70
|
+
|
|
71
|
+
# check email exists
|
|
72
|
+
user = User.query.filter_by(email=email).first()
|
|
73
|
+
if user:
|
|
74
|
+
return render_template('accounts/register.html',
|
|
75
|
+
msg='Email already registered',
|
|
76
|
+
success=False,
|
|
77
|
+
form=create_account_form)
|
|
78
|
+
|
|
79
|
+
# else we can create the user
|
|
80
|
+
user = User(**request.form)
|
|
81
|
+
db.session.add(user)
|
|
82
|
+
db.session.commit()
|
|
83
|
+
|
|
84
|
+
return render_template('accounts/register.html',
|
|
85
|
+
msg='User created please <a href="/login">login</a>',
|
|
86
|
+
success=True,
|
|
87
|
+
form=create_account_form)
|
|
88
|
+
|
|
89
|
+
else:
|
|
90
|
+
return render_template('accounts/register.html', form=create_account_form)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@blueprint.route('/logout')
|
|
94
|
+
def logout():
|
|
95
|
+
logout_user()
|
|
96
|
+
return redirect(url_for('base_blueprint.login'))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@blueprint.route('/shutdown')
|
|
100
|
+
def shutdown():
|
|
101
|
+
func = request.environ.get('werkzeug.server.shutdown')
|
|
102
|
+
if func is None:
|
|
103
|
+
raise RuntimeError('Not running with the Werkzeug Server')
|
|
104
|
+
func()
|
|
105
|
+
return 'Server shutting down...'
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# errors
|
|
109
|
+
@login_manager.unauthorized_handler
|
|
110
|
+
def unauthorized_handler():
|
|
111
|
+
return render_template('page-403.html'), 403
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@blueprint.errorhandler(403)
|
|
115
|
+
def access_forbidden(error):
|
|
116
|
+
return render_template('page-403.html'), 403
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@blueprint.errorhandler(404)
|
|
120
|
+
def not_found_error(error):
|
|
121
|
+
return render_template('page-404.html'), 404
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@blueprint.errorhandler(500)
|
|
125
|
+
def internal_error(error):
|
|
126
|
+
return render_template('page-500.html'), 500
|