Update main.py
Browse files
main.py
CHANGED
|
@@ -772,6 +772,9 @@ def get_admin_dashboard_stats():
|
|
| 772 |
all_users_docs = list(db.collection('users').stream())
|
| 773 |
all_orgs_docs = list(db.collection('organizations').stream())
|
| 774 |
|
|
|
|
|
|
|
|
|
|
| 775 |
# Data structures for aggregation
|
| 776 |
user_sales_data = {}
|
| 777 |
global_item_revenue = {} # Will now be nested: {item: {currency: total}}
|
|
@@ -800,6 +803,9 @@ def get_admin_dashboard_stats():
|
|
| 800 |
user_stats = {'total': len(all_users_docs), 'admins': admin_count, 'approvedForBot': approved_users, 'pendingApproval': pending_approvals}
|
| 801 |
org_stats = {'total': len(all_orgs_docs)}
|
| 802 |
|
|
|
|
|
|
|
|
|
|
| 803 |
# --- Second Pass: Aggregate all financial data ---
|
| 804 |
sales_count = 0
|
| 805 |
for phone in approved_phone_numbers:
|
|
@@ -809,6 +815,9 @@ def get_admin_dashboard_stats():
|
|
| 809 |
user_sales_data[phone] = {'total_revenue_by_currency': {}, 'item_sales': {}}
|
| 810 |
last_seen_currency_code = normalize_currency_code(phone_to_user_map.get(phone, {}).get('defaultCurrency'), 'USD')
|
| 811 |
|
|
|
|
|
|
|
|
|
|
| 812 |
for sale_doc in bot_user_ref.collection('sales').stream():
|
| 813 |
details = sale_doc.to_dict().get('details', {})
|
| 814 |
currency_code = normalize_currency_code(details.get('currency'), last_seen_currency_code)
|
|
@@ -820,6 +829,7 @@ def get_admin_dashboard_stats():
|
|
| 820 |
global_sales_rev_by_curr[currency_code] = global_sales_rev_by_curr.get(currency_code, 0) + sale_revenue
|
| 821 |
global_cogs_by_curr[currency_code] = global_cogs_by_curr.get(currency_code, 0) + (cost * quantity)
|
| 822 |
sales_count += 1
|
|
|
|
| 823 |
|
| 824 |
user_sales_data[phone]['total_revenue_by_currency'][currency_code] = user_sales_data[phone]['total_revenue_by_currency'].get(currency_code, 0) + sale_revenue
|
| 825 |
|
|
@@ -836,10 +846,21 @@ def get_admin_dashboard_stats():
|
|
| 836 |
global_expenses_by_curr[currency_code] = global_expenses_by_curr.get(currency_code, 0) + amount
|
| 837 |
if category not in global_expense_totals: global_expense_totals[category] = {}
|
| 838 |
global_expense_totals[category][currency_code] = global_expense_totals[category].get(currency_code, 0) + amount
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 839 |
except Exception as e:
|
| 840 |
logging.error(f"Admin stats: Could not process data for phone {phone}. Error: {e}")
|
| 841 |
continue
|
| 842 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 843 |
# --- Post-Processing: Generate Leaderboards For Each Currency ---
|
| 844 |
all_currencies = set(global_sales_rev_by_curr.keys()) | set(global_expenses_by_curr.keys())
|
| 845 |
|
|
@@ -869,6 +890,10 @@ def get_admin_dashboard_stats():
|
|
| 869 |
sorted_expenses = sorted(expenses_in_curr, key=lambda item: item[1], reverse=True)
|
| 870 |
leaderboards['topExpenses'][currency] = [{'category': name, 'totalAmount': round(amount, 2)} for name, amount in sorted_expenses[:5]]
|
| 871 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 872 |
# --- Final Assembly ---
|
| 873 |
global_net_profit_by_curr = {}
|
| 874 |
for curr in all_currencies:
|
|
@@ -885,17 +910,30 @@ def get_admin_dashboard_stats():
|
|
| 885 |
'totalSalesCount': sales_count,
|
| 886 |
}
|
| 887 |
|
| 888 |
-
|
| 889 |
-
|
| 890 |
-
'
|
| 891 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 892 |
|
| 893 |
except PermissionError as e:
|
|
|
|
| 894 |
return jsonify({'error': str(e)}), 403
|
| 895 |
except Exception as e:
|
| 896 |
logging.error(f"Admin failed to fetch dashboard stats: {e}", exc_info=True)
|
| 897 |
return jsonify({'error': 'An internal error occurred while fetching stats'}), 500
|
| 898 |
-
|
| 899 |
# -----------------------------------------------------------------------------
|
| 900 |
# 8. SERVER EXECUTION
|
| 901 |
# -----------------------------------------------------------------------------
|
|
|
|
| 772 |
all_users_docs = list(db.collection('users').stream())
|
| 773 |
all_orgs_docs = list(db.collection('organizations').stream())
|
| 774 |
|
| 775 |
+
# Log initial data collection
|
| 776 |
+
logging.info(f"Admin Dashboard: Retrieved {len(all_users_docs)} users and {len(all_orgs_docs)} organizations")
|
| 777 |
+
|
| 778 |
# Data structures for aggregation
|
| 779 |
user_sales_data = {}
|
| 780 |
global_item_revenue = {} # Will now be nested: {item: {currency: total}}
|
|
|
|
| 803 |
user_stats = {'total': len(all_users_docs), 'admins': admin_count, 'approvedForBot': approved_users, 'pendingApproval': pending_approvals}
|
| 804 |
org_stats = {'total': len(all_orgs_docs)}
|
| 805 |
|
| 806 |
+
# Log user processing results
|
| 807 |
+
logging.info(f"Admin Dashboard: User stats - Total: {user_stats['total']}, Admins: {user_stats['admins']}, Approved: {user_stats['approvedForBot']}, Pending: {user_stats['pendingApproval']}")
|
| 808 |
+
|
| 809 |
# --- Second Pass: Aggregate all financial data ---
|
| 810 |
sales_count = 0
|
| 811 |
for phone in approved_phone_numbers:
|
|
|
|
| 815 |
user_sales_data[phone] = {'total_revenue_by_currency': {}, 'item_sales': {}}
|
| 816 |
last_seen_currency_code = normalize_currency_code(phone_to_user_map.get(phone, {}).get('defaultCurrency'), 'USD')
|
| 817 |
|
| 818 |
+
user_sales_count = 0
|
| 819 |
+
user_expenses_count = 0
|
| 820 |
+
|
| 821 |
for sale_doc in bot_user_ref.collection('sales').stream():
|
| 822 |
details = sale_doc.to_dict().get('details', {})
|
| 823 |
currency_code = normalize_currency_code(details.get('currency'), last_seen_currency_code)
|
|
|
|
| 829 |
global_sales_rev_by_curr[currency_code] = global_sales_rev_by_curr.get(currency_code, 0) + sale_revenue
|
| 830 |
global_cogs_by_curr[currency_code] = global_cogs_by_curr.get(currency_code, 0) + (cost * quantity)
|
| 831 |
sales_count += 1
|
| 832 |
+
user_sales_count += 1
|
| 833 |
|
| 834 |
user_sales_data[phone]['total_revenue_by_currency'][currency_code] = user_sales_data[phone]['total_revenue_by_currency'].get(currency_code, 0) + sale_revenue
|
| 835 |
|
|
|
|
| 846 |
global_expenses_by_curr[currency_code] = global_expenses_by_curr.get(currency_code, 0) + amount
|
| 847 |
if category not in global_expense_totals: global_expense_totals[category] = {}
|
| 848 |
global_expense_totals[category][currency_code] = global_expense_totals[category].get(currency_code, 0) + amount
|
| 849 |
+
user_expenses_count += 1
|
| 850 |
+
|
| 851 |
+
# Log per-user processing results
|
| 852 |
+
if user_sales_count > 0 or user_expenses_count > 0:
|
| 853 |
+
logging.info(f"Admin Dashboard: User {phone} - Sales: {user_sales_count}, Expenses: {user_expenses_count}")
|
| 854 |
+
|
| 855 |
except Exception as e:
|
| 856 |
logging.error(f"Admin stats: Could not process data for phone {phone}. Error: {e}")
|
| 857 |
continue
|
| 858 |
|
| 859 |
+
# Log financial aggregation results
|
| 860 |
+
logging.info(f"Admin Dashboard: Financial aggregation - Total sales: {sales_count}, Currencies found: {list(set(global_sales_rev_by_curr.keys()) | set(global_expenses_by_curr.keys()))}")
|
| 861 |
+
logging.info(f"Admin Dashboard: Revenue by currency: {global_sales_rev_by_curr}")
|
| 862 |
+
logging.info(f"Admin Dashboard: Expenses by currency: {global_expenses_by_curr}")
|
| 863 |
+
|
| 864 |
# --- Post-Processing: Generate Leaderboards For Each Currency ---
|
| 865 |
all_currencies = set(global_sales_rev_by_curr.keys()) | set(global_expenses_by_curr.keys())
|
| 866 |
|
|
|
|
| 890 |
sorted_expenses = sorted(expenses_in_curr, key=lambda item: item[1], reverse=True)
|
| 891 |
leaderboards['topExpenses'][currency] = [{'category': name, 'totalAmount': round(amount, 2)} for name, amount in sorted_expenses[:5]]
|
| 892 |
|
| 893 |
+
# Log leaderboard generation results
|
| 894 |
+
for currency in all_currencies:
|
| 895 |
+
logging.info(f"Admin Dashboard: Leaderboard for {currency} - Top users: {len(leaderboards['topUsersByRevenue'][currency])}, Top items: {len(leaderboards['topSellingItems'][currency])}, Top expenses: {len(leaderboards['topExpenses'][currency])}")
|
| 896 |
+
|
| 897 |
# --- Final Assembly ---
|
| 898 |
global_net_profit_by_curr = {}
|
| 899 |
for curr in all_currencies:
|
|
|
|
| 910 |
'totalSalesCount': sales_count,
|
| 911 |
}
|
| 912 |
|
| 913 |
+
# Log final response data structure
|
| 914 |
+
response_data = {
|
| 915 |
+
'userStats': user_stats,
|
| 916 |
+
'organizationStats': org_stats,
|
| 917 |
+
'systemStats': system_stats,
|
| 918 |
+
'leaderboards': leaderboards
|
| 919 |
+
}
|
| 920 |
+
|
| 921 |
+
logging.info(f"Admin Dashboard: Final response structure - userStats keys: {list(user_stats.keys())}, systemStats keys: {list(system_stats.keys())}, leaderboards keys: {list(leaderboards.keys())}")
|
| 922 |
+
logging.info(f"Admin Dashboard: System stats summary - Total currencies: {len(all_currencies)}, Net profit by currency: {global_net_profit_by_curr}")
|
| 923 |
+
|
| 924 |
+
# Log response data size for debugging
|
| 925 |
+
import json
|
| 926 |
+
response_size = len(json.dumps(response_data))
|
| 927 |
+
logging.info(f"Admin Dashboard: Response data size: {response_size} bytes")
|
| 928 |
+
|
| 929 |
+
return jsonify(response_data), 200
|
| 930 |
|
| 931 |
except PermissionError as e:
|
| 932 |
+
logging.error(f"Admin Dashboard: Permission denied - {e}")
|
| 933 |
return jsonify({'error': str(e)}), 403
|
| 934 |
except Exception as e:
|
| 935 |
logging.error(f"Admin failed to fetch dashboard stats: {e}", exc_info=True)
|
| 936 |
return jsonify({'error': 'An internal error occurred while fetching stats'}), 500
|
|
|
|
| 937 |
# -----------------------------------------------------------------------------
|
| 938 |
# 8. SERVER EXECUTION
|
| 939 |
# -----------------------------------------------------------------------------
|