Dashboard update

This commit is contained in:
2025-10-25 09:35:47 +05:30
parent 7cfe522512
commit e5c5044ff3
15 changed files with 1137 additions and 350 deletions

View File

@ -6,14 +6,14 @@ PAYU_MERCHANT_SALT=DusXSSjqqSMTPSpw32hlFXF6LKY2Zm3y
PAYU_SUCCESS_URL=http://localhost:4200/payment-success
PAYU_FAILURE_URL=http://localhost:4200/payment-failure
FLASK_ENV=production
FLASK_ENV=development
MYSQL_HOST=db
MYSQL_USER=vendinguser
MYSQL_PASSWORD=vendingpass
MYSQL_DATABASE=vending
SQLITE_DB_PATH=machines
SQLITE_DB_PATH=machines.db
BREVO_SMTP_EMAIL=smukeshsn2000@gmail.com
BREVO_SMTP_KEY=your-brevo-smtp-key

View File

@ -1,5 +1,5 @@
from app import db # Add this if not already there
from sqlalchemy import func # Add this
from sqlalchemy import func, extract # Add this
from flask import Blueprint, request, jsonify, send_from_directory
from app.services.services import MachineService, UserService, ProductService, serial_service, TransactionService, RoleService
from app.models.models import Machine, User, Transaction, Product, VendingSlot, Role
@ -853,6 +853,10 @@ def get_current_user_from_token():
return None
from flask import jsonify, request
from sqlalchemy import func, extract
from datetime import datetime
@bp.route('/dashboard-metrics', methods=['GET'])
def get_dashboard_metrics_role_based():
"""Get dashboard metrics filtered by user role"""
@ -877,16 +881,12 @@ def get_dashboard_metrics_role_based():
# ROLE-BASED FILTERING
if user_role in ['Management', 'SuperAdmin', 'Admin']:
# Show overall system stats
response = get_admin_dashboard_metrics(filter_type)
elif user_role == 'Client':
# Show only this client's data
response = get_Client_dashboard_metrics(current_user.id, filter_type)
elif user_role == 'Refiller':
# Show product/warehouse related stats
response = get_refiller_dashboard_metrics(filter_type)
elif user_role == 'Servicer':
# Show machine maintenance stats
response = get_servicer_dashboard_metrics(filter_type)
else:
return jsonify({'error': 'Invalid role'}), 403
@ -914,23 +914,52 @@ def get_admin_dashboard_metrics(filter_type):
machine_count = Machine.query.count()
machine_title = 'All Machines'
# Client count (users with role 'Client')
# Client count
clients = User.query.filter_by(roles='Client').count()
# Company users (Admin, SuperAdmin, Management, Refiller, Servicer)
# Company users
company_users = User.query.filter(
User.roles.in_(['Management', 'SuperAdmin', 'Admin', 'Refiller', 'Servicer'])
).count()
# Active and inactive machines
active_machines = Machine.query.filter_by(operation_status='active').count()
inactive_machines = Machine.query.filter_by(operation_status='inactive').count()
# COUNT TRANSACTIONS AND CALCULATE SALES
transactions_count = Transaction.query.count()
# Calculate total sales (sum of all successful transaction amounts)
from sqlalchemy import func
# Calculate total sales
total_sales = db.session.query(func.sum(Transaction.amount))\
.filter(Transaction.status == 'Success')\
.scalar() or 0.0
# PAYMENT BREAKDOWN
payment_breakdown = get_payment_breakdown()
# MACHINE OPERATION STATUS
machine_operation_status = {
'Online': Machine.query.filter_by(connection_status='online').count(),
'Offline': Machine.query.filter_by(connection_status='offline').count(),
'Down (Planned)': Machine.query.filter_by(operation_status='down_planned').count(),
'Down': Machine.query.filter_by(operation_status='down').count(),
'Standby': Machine.query.filter_by(operation_status='standby').count(),
'Terminated': Machine.query.filter_by(operation_status='terminated').count(),
'N/A': Machine.query.filter(Machine.operation_status.is_(None)).count()
}
# MACHINE STOCK STATUS - Calculate based on vending slots
machine_stock_status = calculate_machine_stock_status()
# PRODUCT SALES YEARLY
product_sales_yearly = get_product_sales_yearly()
# SALES YEARLY
sales_yearly = get_sales_yearly()
# TOP SELLING PRODUCTS
top_selling_products = get_top_selling_products()
return {
'machine_title': machine_title,
'machine_count': machine_count,
@ -939,13 +968,21 @@ def get_admin_dashboard_metrics(filter_type):
'client_users': clients,
'transactions': transactions_count,
'sales': f'{total_sales:.2f}',
'active_machines': active_machines,
'inactive_machines': inactive_machines,
'payment_breakdown': payment_breakdown,
'machine_operation_status': machine_operation_status,
'machine_stock_status': machine_stock_status,
'product_sales_yearly': product_sales_yearly,
'sales_yearly': sales_yearly,
'top_selling_products': top_selling_products,
'user_role': 'admin',
'user_type': 'Overall System'
}
def get_Client_dashboard_metrics(user_id, filter_type):
"""Get metrics for Client/Client - Only their own data"""
"""Get metrics for Client - Only their own data"""
# Get only machines belonging to this client
if filter_type == 'active':
machine_count = Machine.query.filter_by(
@ -963,28 +1000,53 @@ def get_Client_dashboard_metrics(user_id, filter_type):
machine_count = Machine.query.filter_by(client_id=user_id).count()
machine_title = 'My Machines'
# For Client, clients = 1 (themselves)
clients = 1
# Company users not relevant for Client
company_users = 0
# GET THIS CLIENT'S TRANSACTIONS AND SALES
# Get machine IDs for this client
client_machine_ids = [m.machine_id for m in Machine.query.filter_by(client_id=user_id).all()]
# Active and inactive machines for this client
active_machines = Machine.query.filter_by(client_id=user_id, operation_status='active').count()
inactive_machines = Machine.query.filter_by(client_id=user_id, operation_status='inactive').count()
# Count transactions for this client's machines
transactions_count = Transaction.query.filter(
Transaction.machine_id.in_(client_machine_ids)
).count() if client_machine_ids else 0
# Calculate sales for this client's machines
from sqlalchemy import func
total_sales = db.session.query(func.sum(Transaction.amount))\
.filter(Transaction.machine_id.in_(client_machine_ids))\
.filter(Transaction.status == 'Success')\
.scalar() or 0.0 if client_machine_ids else 0.0
# PAYMENT BREAKDOWN for client's machines
payment_breakdown = get_payment_breakdown(client_machine_ids)
# MACHINE OPERATION STATUS for client's machines
machine_operation_status = {
'Online': Machine.query.filter(Machine.client_id == user_id, Machine.connection_status == 'online').count(),
'Offline': Machine.query.filter(Machine.client_id == user_id, Machine.connection_status == 'offline').count(),
'Down (Planned)': Machine.query.filter(Machine.client_id == user_id, Machine.operation_status == 'down_planned').count(),
'Down': Machine.query.filter(Machine.client_id == user_id, Machine.operation_status == 'down').count(),
'Standby': Machine.query.filter(Machine.client_id == user_id, Machine.operation_status == 'standby').count(),
'Terminated': Machine.query.filter(Machine.client_id == user_id, Machine.operation_status == 'terminated').count(),
'N/A': Machine.query.filter(Machine.client_id == user_id, Machine.operation_status.is_(None)).count()
}
# MACHINE STOCK STATUS for client's machines
machine_stock_status = calculate_machine_stock_status(client_machine_ids)
# PRODUCT SALES YEARLY for client's machines
product_sales_yearly = get_product_sales_yearly(client_machine_ids)
# SALES YEARLY for client's machines
sales_yearly = get_sales_yearly(client_machine_ids)
# TOP SELLING PRODUCTS for client's machines
top_selling_products = get_top_selling_products(client_machine_ids)
return {
'machine_title': machine_title,
'machine_count': machine_count,
@ -993,6 +1055,14 @@ def get_Client_dashboard_metrics(user_id, filter_type):
'client_users': clients,
'transactions': transactions_count,
'sales': f'{total_sales:.2f}',
'active_machines': active_machines,
'inactive_machines': inactive_machines,
'payment_breakdown': payment_breakdown,
'machine_operation_status': machine_operation_status,
'machine_stock_status': machine_stock_status,
'product_sales_yearly': product_sales_yearly,
'sales_yearly': sales_yearly,
'top_selling_products': top_selling_products,
'user_role': 'Client',
'user_type': 'My Business'
}
@ -1000,21 +1070,32 @@ def get_Client_dashboard_metrics(user_id, filter_type):
def get_refiller_dashboard_metrics(filter_type):
"""Get metrics for Refiller - Product/warehouse focused"""
# Machines they need to service
machine_count = Machine.query.count()
# Products in warehouse
product_count = Product.query.count()
# Transaction count (all)
transactions_count = Transaction.query.count()
# Total sales
from sqlalchemy import func
total_sales = db.session.query(func.sum(Transaction.amount))\
.filter(Transaction.status == 'Success')\
.scalar() or 0.0
active_machines = Machine.query.filter_by(operation_status='active').count()
inactive_machines = Machine.query.filter_by(operation_status='inactive').count()
payment_breakdown = get_payment_breakdown()
machine_operation_status = {
'Online': Machine.query.filter_by(connection_status='online').count(),
'Offline': Machine.query.filter_by(connection_status='offline').count(),
'Down (Planned)': Machine.query.filter_by(operation_status='down_planned').count(),
'Down': Machine.query.filter_by(operation_status='down').count(),
'Standby': Machine.query.filter_by(operation_status='standby').count(),
'Terminated': Machine.query.filter_by(operation_status='terminated').count(),
'N/A': Machine.query.filter(Machine.operation_status.is_(None)).count()
}
machine_stock_status = calculate_machine_stock_status()
product_sales_yearly = get_product_sales_yearly()
sales_yearly = get_sales_yearly()
top_selling_products = get_top_selling_products()
return {
'machine_title': 'Machines to Service',
'machine_count': machine_count,
@ -1023,7 +1104,15 @@ def get_refiller_dashboard_metrics(filter_type):
'client_users': 0,
'transactions': transactions_count,
'sales': f'{total_sales:.2f}',
'active_machines': active_machines,
'inactive_machines': inactive_machines,
'product_count': product_count,
'payment_breakdown': payment_breakdown,
'machine_operation_status': machine_operation_status,
'machine_stock_status': machine_stock_status,
'product_sales_yearly': product_sales_yearly,
'sales_yearly': sales_yearly,
'top_selling_products': top_selling_products,
'user_role': 'refiller',
'user_type': 'Inventory Management'
}
@ -1031,7 +1120,6 @@ def get_refiller_dashboard_metrics(filter_type):
def get_servicer_dashboard_metrics(filter_type):
"""Get metrics for Servicer - Machine maintenance focused"""
# All machines they can service
if filter_type == 'active':
machine_count = Machine.query.filter_by(operation_status='active').count()
machine_title = 'Active Machines'
@ -1042,18 +1130,31 @@ def get_servicer_dashboard_metrics(filter_type):
machine_count = Machine.query.count()
machine_title = 'Total Machines'
# Machines needing maintenance
maintenance_count = Machine.query.filter_by(operation_status='maintenance').count()
# Transaction count (all)
transactions_count = Transaction.query.count()
# Total sales
from sqlalchemy import func
total_sales = db.session.query(func.sum(Transaction.amount))\
.filter(Transaction.status == 'Success')\
.scalar() or 0.0
active_machines = Machine.query.filter_by(operation_status='active').count()
inactive_machines = Machine.query.filter_by(operation_status='inactive').count()
payment_breakdown = get_payment_breakdown()
machine_operation_status = {
'Online': Machine.query.filter_by(connection_status='online').count(),
'Offline': Machine.query.filter_by(connection_status='offline').count(),
'Down (Planned)': Machine.query.filter_by(operation_status='down_planned').count(),
'Down': Machine.query.filter_by(operation_status='down').count(),
'Standby': Machine.query.filter_by(operation_status='standby').count(),
'Terminated': Machine.query.filter_by(operation_status='terminated').count(),
'N/A': Machine.query.filter(Machine.operation_status.is_(None)).count()
}
machine_stock_status = calculate_machine_stock_status()
product_sales_yearly = get_product_sales_yearly()
sales_yearly = get_sales_yearly()
top_selling_products = get_top_selling_products()
return {
'machine_title': machine_title,
'machine_count': machine_count,
@ -1062,11 +1163,374 @@ def get_servicer_dashboard_metrics(filter_type):
'client_users': 0,
'transactions': transactions_count,
'sales': f'{total_sales:.2f}',
'active_machines': active_machines,
'inactive_machines': inactive_machines,
'maintenance_count': maintenance_count,
'payment_breakdown': payment_breakdown,
'machine_operation_status': machine_operation_status,
'machine_stock_status': machine_stock_status,
'product_sales_yearly': product_sales_yearly,
'sales_yearly': sales_yearly,
'top_selling_products': top_selling_products,
'user_role': 'servicer',
'user_type': 'Machine Maintenance'
}
# HELPER FUNCTIONS
def get_payment_breakdown(machine_ids=None):
"""Calculate payment breakdown from transactions"""
query = db.session.query(
Transaction.payment_type,
func.sum(Transaction.amount).label('total')
)
if machine_ids:
query = query.filter(Transaction.machine_id.in_(machine_ids))
query = query.filter(Transaction.status == 'Success')\
.group_by(Transaction.payment_type)
payment_data = query.all()
breakdown = {
'cash': 0.0,
'cashless': 0.0,
'upi_wallet_card': 0.0,
'upi_wallet_paytm': 0.0,
'refund': 0.0,
'refund_processed': 0.0,
'total': 0.0
}
for payment_type, total in payment_data:
if payment_type and total:
payment_type_lower = payment_type.lower()
if 'cash' in payment_type_lower and 'cashless' not in payment_type_lower:
breakdown['cash'] += float(total)
elif 'cashless' in payment_type_lower:
breakdown['cashless'] += float(total)
elif 'phonepe' in payment_type_lower or 'card' in payment_type_lower:
breakdown['upi_wallet_card'] += float(total)
elif 'paytm' in payment_type_lower:
breakdown['upi_wallet_paytm'] += float(total)
# Calculate refunds
refund_query = db.session.query(func.sum(Transaction.return_amount))
if machine_ids:
refund_query = refund_query.filter(Transaction.machine_id.in_(machine_ids))
breakdown['refund'] = float(refund_query.filter(
Transaction.amount_receiving_status == 'Dispense failed refund'
).scalar() or 0.0)
breakdown['refund_processed'] = float(refund_query.filter(
Transaction.amount_receiving_status == 'Refund processed'
).scalar() or 0.0)
breakdown['total'] = sum([
breakdown['cash'],
breakdown['cashless'],
breakdown['upi_wallet_card'],
breakdown['upi_wallet_paytm']
])
return breakdown
def calculate_machine_stock_status(machine_ids=None):
"""Calculate machine stock status based on vending slots"""
query = Machine.query
if machine_ids:
query = query.filter(Machine.machine_id.in_(machine_ids))
machines = query.all()
status_counts = {
'75 - 100%': 0,
'50 - 75%': 0,
'25 - 50%': 0,
'0 - 25%': 0,
'N/A': 0
}
for machine in machines:
slots = VendingSlot.query.filter_by(machine_id=machine.machine_id).all()
if not slots:
status_counts['N/A'] += 1
continue
total_slots = len(slots)
filled_slots = sum(1 for slot in slots if slot.units and slot.units > 0)
if total_slots == 0:
status_counts['N/A'] += 1
else:
fill_percentage = (filled_slots / total_slots) * 100
if fill_percentage >= 75:
status_counts['75 - 100%'] += 1
elif fill_percentage >= 50:
status_counts['50 - 75%'] += 1
elif fill_percentage >= 25:
status_counts['25 - 50%'] += 1
elif fill_percentage > 0:
status_counts['0 - 25%'] += 1
else:
status_counts['0 - 25%'] += 1
return status_counts
def get_product_sales_yearly(machine_ids=None):
"""Get product sales aggregated by year"""
query = db.session.query(
extract('year', Transaction.created_at).label('year'),
func.sum(Transaction.amount).label('total_sales')
)
if machine_ids:
query = query.filter(Transaction.machine_id.in_(machine_ids))
query = query.filter(Transaction.status == 'Success')\
.group_by(extract('year', Transaction.created_at))\
.order_by('year')
results = query.all()
return [{'year': str(int(year)), 'amount': float(total_sales)}
for year, total_sales in results if year]
def get_sales_yearly(machine_ids=None):
"""Get sales aggregated by year"""
return get_product_sales_yearly(machine_ids)
def get_top_selling_products(machine_ids=None, limit=10):
"""Get top selling products"""
query = db.session.query(
Transaction.product_name,
func.sum(Transaction.quantity).label('total_quantity')
)
if machine_ids:
query = query.filter(Transaction.machine_id.in_(machine_ids))
query = query.filter(Transaction.status == 'Success')\
.group_by(Transaction.product_name)\
.order_by(func.sum(Transaction.quantity).desc())\
.limit(limit)
results = query.all()
return [{'product_name': product_name, 'quantity': int(total_quantity)}
for product_name, total_quantity in results]
@bp.route('/product-sales', methods=['GET'])
def get_product_sales_filtered():
"""Get product sales data filtered by time range"""
try:
current_user = get_current_user_from_token()
if not current_user:
return jsonify({'error': 'Authentication required'}), 401
time_range = request.args.get('time_range', 'year')
user_role = current_user.roles
print(f"Product Sales Filter - User: {current_user.username}, Range: {time_range}")
# Get machine IDs based on role
machine_ids = None
if user_role == 'Client':
machine_ids = [m.machine_id for m in Machine.query.filter_by(client_id=current_user.id).all()]
# Fetch data based on time range
product_sales = get_sales_data_by_range(time_range, machine_ids)
return jsonify({'product_sales': product_sales}), 200
except Exception as e:
print(f"Error in product sales filter: {str(e)}")
return jsonify({'error': str(e)}), 500
@bp.route('/sales-data', methods=['GET'])
def get_sales_filtered():
"""Get sales data filtered by time range"""
try:
current_user = get_current_user_from_token()
if not current_user:
return jsonify({'error': 'Authentication required'}), 401
time_range = request.args.get('time_range', 'year')
user_role = current_user.roles
print(f"Sales Filter - User: {current_user.username}, Range: {time_range}")
# Get machine IDs based on role
machine_ids = None
if user_role == 'Client':
machine_ids = [m.machine_id for m in Machine.query.filter_by(client_id=current_user.id).all()]
# Fetch data based on time range
sales_data = get_sales_data_by_range(time_range, machine_ids)
return jsonify({'sales_data': sales_data}), 200
except Exception as e:
print(f"Error in sales filter: {str(e)}")
return jsonify({'error': str(e)}), 500
@bp.route('/top-products', methods=['GET'])
def get_top_products_filtered():
"""Get top selling products filtered by time range"""
try:
current_user = get_current_user_from_token()
if not current_user:
return jsonify({'error': 'Authentication required'}), 401
time_range = request.args.get('time_range', 'year')
user_role = current_user.roles
print(f"Top Products Filter - User: {current_user.username}, Range: {time_range}")
# Get machine IDs based on role
machine_ids = None
if user_role == 'Client':
machine_ids = [m.machine_id for m in Machine.query.filter_by(client_id=current_user.id).all()]
# Fetch data based on time range
top_products = get_top_products_by_range(time_range, machine_ids)
return jsonify({'top_products': top_products}), 200
except Exception as e:
print(f"Error in top products filter: {str(e)}")
return jsonify({'error': str(e)}), 500
# Helper function to get date filter based on time range
def get_date_filter(time_range):
"""Return date filter based on time range"""
now = datetime.now()
if time_range == 'day':
# Last 24 hours
return now - timedelta(days=1)
elif time_range == 'week':
# Last 7 days
return now - timedelta(weeks=1)
elif time_range == 'month':
# Last 30 days
return now - timedelta(days=30)
elif time_range == 'year':
# All time, grouped by year
return None
else:
return None
def get_sales_data_by_range(time_range, machine_ids=None):
"""Get sales data aggregated by time range"""
date_filter = get_date_filter(time_range)
# Base query
query = db.session.query(Transaction.created_at, Transaction.amount)\
.filter(Transaction.status == 'Success')
# Apply machine filter if needed
if machine_ids:
query = query.filter(Transaction.machine_id.in_(machine_ids))
# Apply date filter
if date_filter:
query = query.filter(Transaction.created_at >= date_filter)
transactions = query.all()
# Aggregate based on time range
if time_range == 'day':
# Group by hour
aggregated = {}
for txn in transactions:
hour = txn.created_at.strftime('%H:00')
if hour not in aggregated:
aggregated[hour] = 0
aggregated[hour] += float(txn.amount)
return [{'year': k, 'amount': v} for k, v in sorted(aggregated.items())]
elif time_range == 'week':
# Group by day
aggregated = {}
for txn in transactions:
day = txn.created_at.strftime('%a') # Mon, Tue, etc.
if day not in aggregated:
aggregated[day] = 0
aggregated[day] += float(txn.amount)
# Sort by weekday order
days_order = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
return [{'year': day, 'amount': aggregated.get(day, 0)} for day in days_order]
elif time_range == 'month':
# Group by day
aggregated = {}
for txn in transactions:
day = txn.created_at.strftime('%d')
if day not in aggregated:
aggregated[day] = 0
aggregated[day] += float(txn.amount)
return [{'year': k, 'amount': v} for k, v in sorted(aggregated.items())]
else: # year or all time
# Group by year
query = db.session.query(
extract('year', Transaction.created_at).label('year'),
func.sum(Transaction.amount).label('total_sales')
).filter(Transaction.status == 'Success')
if machine_ids:
query = query.filter(Transaction.machine_id.in_(machine_ids))
query = query.group_by(extract('year', Transaction.created_at))\
.order_by('year')
results = query.all()
return [{'year': str(int(year)), 'amount': float(total_sales)}
for year, total_sales in results if year]
def get_top_products_by_range(time_range, machine_ids=None, limit=10):
"""Get top selling products filtered by time range"""
date_filter = get_date_filter(time_range)
# Base query
query = db.session.query(
Transaction.product_name,
func.sum(Transaction.quantity).label('total_quantity')
).filter(Transaction.status == 'Success')
# Apply machine filter if needed
if machine_ids:
query = query.filter(Transaction.machine_id.in_(machine_ids))
# Apply date filter
if date_filter:
query = query.filter(Transaction.created_at >= date_filter)
query = query.group_by(Transaction.product_name)\
.order_by(func.sum(Transaction.quantity).desc())\
.limit(limit)
results = query.all()
return [{'product_name': product_name, 'quantity': int(total_quantity)}
for product_name, total_quantity in results]
# Additional utility routes for PayU integration
@bp.route('/verify-payu-hash', methods=['POST'])
@ -1603,7 +2067,7 @@ def get_roles():
return jsonify({'error': 'Authentication required'}), 401
# Only Management and SuperAdmin can view roles
if current_user.roles not in ['Management', 'SuperAdmin']:
if current_user.roles not in ['Management', 'SuperAdmin','Admin']:
return jsonify({'error': 'Permission denied'}), 403
roles = RoleService.get_all_roles()
@ -1622,7 +2086,7 @@ def create_role():
return jsonify({'error': 'Authentication required'}), 401
# Only Management and SuperAdmin can create roles
if current_user.roles not in ['Management', 'SuperAdmin']:
if current_user.roles not in ['Management', 'SuperAdmin','Admin']:
return jsonify({'error': 'Permission denied'}), 403
data = request.json
@ -1645,7 +2109,7 @@ def update_role(role_id):
return jsonify({'error': 'Authentication required'}), 401
# Only Management and SuperAdmin can update roles
if current_user.roles not in ['Management', 'SuperAdmin']:
if current_user.roles not in ['Management', 'SuperAdmin','Admin']:
return jsonify({'error': 'Permission denied'}), 403
data = request.json
@ -1668,7 +2132,7 @@ def delete_role(role_id):
return jsonify({'error': 'Authentication required'}), 401
# Only Management and SuperAdmin can delete roles
if current_user.roles not in ['Management', 'SuperAdmin']:
if current_user.roles not in ['Management', 'SuperAdmin','Admin']:
return jsonify({'error': 'Permission denied'}), 403
RoleService.delete_role(role_id)
@ -1690,7 +2154,7 @@ def get_available_permissions():
return jsonify({'error': 'Authentication required'}), 401
# Only Management and SuperAdmin can view permissions
if current_user.roles not in ['Management', 'SuperAdmin']:
if current_user.roles not in ['Management', 'SuperAdmin','Admin']:
return jsonify({'error': 'Permission denied'}), 403
# Define all available permissions

View File

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

View File

@ -0,0 +1,18 @@
from app import create_app, db
from app.models.models import User
from werkzeug.security import generate_password_hash
app = create_app()
with app.app_context():
email = "test@example.com"
new_password = "test123"
user = User.query.filter_by(email=email).first()
if not user:
print("User not found ❌")
else:
# Hash password in the way your model expects
user.password = generate_password_hash(new_password, method='pbkdf2:sha256')
db.session.commit()
print(f"Password reset successfully for {email}. Login with: {new_password}")