|
|
import pandas as pd |
|
|
import numpy as np |
|
|
from datetime import datetime, timedelta |
|
|
|
|
|
class Analytics: |
|
|
def __init__(self, db_manager): |
|
|
self.db = db_manager |
|
|
|
|
|
def get_sales_summary(self): |
|
|
"""Get comprehensive sales summary statistics""" |
|
|
try: |
|
|
sales_df = self.db.get_dataframe('sales') |
|
|
payments_df = self.db.get_dataframe('payments') |
|
|
|
|
|
if sales_df.empty: |
|
|
return { |
|
|
'total_sales': 0, |
|
|
'total_payments': 0, |
|
|
'pending_amount': 0, |
|
|
'total_transactions': 0, |
|
|
'avg_sale_value': 0 |
|
|
} |
|
|
|
|
|
total_sales = sales_df['total_amount'].sum() |
|
|
total_payments = payments_df['amount'].sum() if not payments_df.empty else 0 |
|
|
pending_amount = total_sales - total_payments |
|
|
|
|
|
return { |
|
|
'total_sales': total_sales, |
|
|
'total_payments': total_payments, |
|
|
'pending_amount': pending_amount, |
|
|
'total_transactions': len(sales_df), |
|
|
'avg_sale_value': sales_df['total_amount'].mean() |
|
|
} |
|
|
except Exception as e: |
|
|
return { |
|
|
'total_sales': 0, |
|
|
'total_payments': 0, |
|
|
'pending_amount': 0, |
|
|
'total_transactions': 0, |
|
|
'avg_sale_value': 0 |
|
|
} |
|
|
|
|
|
def get_customer_analysis(self): |
|
|
"""Analyze customer data""" |
|
|
try: |
|
|
customers_df = self.db.get_dataframe('customers') |
|
|
sales_df = self.db.get_dataframe('sales') |
|
|
|
|
|
if customers_df.empty: |
|
|
return { |
|
|
'total_customers': 0, |
|
|
'village_distribution': {}, |
|
|
'top_customers': {} |
|
|
} |
|
|
|
|
|
|
|
|
village_stats = customers_df['village'].value_counts().head(10) |
|
|
|
|
|
|
|
|
if not sales_df.empty: |
|
|
customer_sales = sales_df.groupby('customer_id')['total_amount'].sum() |
|
|
top_customers = customer_sales.nlargest(10) |
|
|
else: |
|
|
top_customers = pd.Series(dtype=float) |
|
|
|
|
|
return { |
|
|
'total_customers': len(customers_df), |
|
|
'village_distribution': village_stats.to_dict(), |
|
|
'top_customers': top_customers.to_dict() |
|
|
} |
|
|
except Exception as e: |
|
|
return { |
|
|
'total_customers': 0, |
|
|
'village_distribution': {}, |
|
|
'top_customers': {} |
|
|
} |
|
|
|
|
|
def get_payment_analysis(self): |
|
|
"""Analyze payment data""" |
|
|
try: |
|
|
pending_payments = self.db.get_pending_payments() |
|
|
payments_df = self.db.get_dataframe('payments') |
|
|
|
|
|
if pending_payments.empty: |
|
|
return { |
|
|
'total_pending': 0, |
|
|
'customer_pending': {}, |
|
|
'payment_methods': {} |
|
|
} |
|
|
|
|
|
|
|
|
customer_pending = pending_payments.groupby('customer_id')['pending_amount'].sum() |
|
|
|
|
|
|
|
|
if not payments_df.empty: |
|
|
payment_methods = payments_df['payment_method'].value_counts() |
|
|
else: |
|
|
payment_methods = pd.Series(dtype=object) |
|
|
|
|
|
return { |
|
|
'total_pending': pending_payments['pending_amount'].sum(), |
|
|
'customer_pending': customer_pending.to_dict(), |
|
|
'payment_methods': payment_methods.to_dict() |
|
|
} |
|
|
except Exception as e: |
|
|
return { |
|
|
'total_pending': 0, |
|
|
'customer_pending': {}, |
|
|
'payment_methods': {} |
|
|
} |
|
|
|
|
|
def get_demo_conversion_rates(self): |
|
|
"""Calculate demo conversion rates""" |
|
|
try: |
|
|
demos_df = self.db.get_demo_conversions() |
|
|
|
|
|
if demos_df.empty: |
|
|
return { |
|
|
'total_demos': 0, |
|
|
'converted_demos': 0, |
|
|
'conversion_rate': 0 |
|
|
} |
|
|
|
|
|
total_demos = len(demos_df) |
|
|
converted_demos = len(demos_df[demos_df['conversion_status'] == 'Converted']) |
|
|
conversion_rate = (converted_demos / total_demos) * 100 if total_demos > 0 else 0 |
|
|
|
|
|
return { |
|
|
'total_demos': total_demos, |
|
|
'converted_demos': converted_demos, |
|
|
'conversion_rate': conversion_rate |
|
|
} |
|
|
except Exception as e: |
|
|
return { |
|
|
'total_demos': 0, |
|
|
'converted_demos': 0, |
|
|
'conversion_rate': 0 |
|
|
} |
|
|
|
|
|
def get_sales_trend(self): |
|
|
"""Get sales trend data for charts""" |
|
|
try: |
|
|
sales_df = self.db.get_dataframe('sales') |
|
|
|
|
|
if sales_df.empty: |
|
|
return pd.DataFrame() |
|
|
|
|
|
|
|
|
sales_df['sale_date'] = pd.to_datetime(sales_df['sale_date']) |
|
|
|
|
|
|
|
|
daily_sales = sales_df.groupby('sale_date')['total_amount'].sum().reset_index() |
|
|
daily_sales = daily_sales.sort_values('sale_date') |
|
|
|
|
|
return daily_sales |
|
|
except Exception as e: |
|
|
return pd.DataFrame() |
|
|
|
|
|
def get_payment_distribution(self): |
|
|
"""Get payment distribution for charts""" |
|
|
try: |
|
|
payments_df = self.db.get_dataframe('payments') |
|
|
|
|
|
if payments_df.empty: |
|
|
return pd.DataFrame() |
|
|
|
|
|
payment_dist = payments_df.groupby('payment_method')['amount'].sum().reset_index() |
|
|
return payment_dist |
|
|
except Exception as e: |
|
|
return pd.DataFrame() |
|
|
|
|
|
def get_product_performance(self): |
|
|
"""Get product performance data""" |
|
|
try: |
|
|
sale_items_df = self.db.get_dataframe('sale_items', ''' |
|
|
SELECT si.*, p.product_name |
|
|
FROM sale_items si |
|
|
JOIN products p ON si.product_id = p.product_id |
|
|
''') |
|
|
|
|
|
if sale_items_df.empty: |
|
|
return pd.DataFrame() |
|
|
|
|
|
product_perf = sale_items_df.groupby('product_name').agg({ |
|
|
'quantity': 'sum', |
|
|
'amount': 'sum' |
|
|
}).reset_index() |
|
|
|
|
|
return product_perf |
|
|
except Exception as e: |
|
|
return pd.DataFrame() |