diff --git a/app/dummydata.py b/app/dummydata.py index 6830324d22f00aad03e28ade8ec829800ba415c7..eca0fe3dc7493802abf81cf7ed3354010458a937 100644 --- a/app/dummydata.py +++ b/app/dummydata.py @@ -1,4 +1,5 @@ -from app.models import Restaurant, Menu, User, Inventory, db +from app.models import Restaurant, Menu, User, Inventory, db, Order, OrderItem, Payment +from datetime import timedelta from datetime import datetime from werkzeug.security import generate_password_hash from app import create_app @@ -419,6 +420,83 @@ def create_dummy_data(): db.session.commit() print(f"Created {menu_items_count} menu items") + + print("Creating orders and payments...") + users = User.query.filter_by(role="customer").all() + restaurants = Restaurant.query.all() + menu_items = Menu.query.all() + + # Generate orders for the last 6 months + end_date = datetime.utcnow() + start_date = end_date - timedelta(days=180) + + orders_count = 0 + payments_count = 0 + + while start_date <= end_date: + # Create 3-7 orders per day + daily_orders = random.randint(3, 7) + + for _ in range(daily_orders): + user = random.choice(users) + restaurant = random.choice(restaurants) + + # Select 1-4 menu items for the order + order_items = random.sample(menu_items, random.randint(1, 4)) + total_amount = sum(item.price for item in order_items) + + # Create order + order = Order( + restaurant_id=restaurant.id, + user_id=user.id, + table_number=random.randint(1, 20), + total_amount=total_amount, + order_status=random.choice( + ["completed", "completed", "completed", "pending"] + ), + payment_status=random.choice( + ["paid", "paid", "paid", "pending"] + ), + created_at=start_date, + ) + db.session.add(order) + db.session.flush() + + # Create order items + for menu_item in order_items: + quantity = random.randint(1, 3) + subtotal = menu_item.price * quantity + order_item = OrderItem( + order_id=order.id, + menu_id=menu_item.id, + quantity=quantity, + subtotal=subtotal, + ) + db.session.add(order_item) + + # Create payment for paid orders + if order.payment_status == "paid": + payment = Payment( + order_id=order.id, + user_id=user.id, + amount=total_amount, + payment_method=random.choice( + ["cash", "credit_card", "paypal"] + ), + transaction_id=f"TXN-{random.randint(100000, 999999)}", + status="success", + created_at=start_date, + ) + db.session.add(payment) + payments_count += 1 + + orders_count += 1 + + start_date += timedelta(days=1) + + db.session.commit() + print(f"Created {orders_count} orders and {payments_count} payments") + print("Dummy data created successfully!") except Exception as e: diff --git a/app/routes/home.py b/app/routes/home.py index abbb8ca0c248b25c0f5f86e9708e1fb7f2b590d0..eb3a8a10a054a5457b547876de7df6054b13544e 100644 --- a/app/routes/home.py +++ b/app/routes/home.py @@ -1,5 +1,8 @@ -from flask import Blueprint, render_template +from flask import Blueprint, render_template, request from app.routes.auth import login_required +from app.models import Order, Menu, User, Payment, db +from sqlalchemy import func +from datetime import datetime, timedelta home_bp = Blueprint("home", __name__) @@ -7,4 +10,170 @@ home_bp = Blueprint("home", __name__) @home_bp.route("/") @login_required def homepage(): - return render_template("home.html") + # Get total revenue from successful payments + total_revenue = ( + db.session.query(func.sum(Payment.amount)) + .filter(Payment.status == "success") + .scalar() + or 0 + ) + + # Get total number of orders + total_orders = Order.query.count() + + # Get total number of menu items + total_menu = Menu.query.count() + + # Get total number of staff (excluding customers) + total_staff = User.query.filter(User.role != "customer").count() + + # Get time period from request args, default to last 6 months + period = request.args.get("period", "last_6_months") + + # Get orders data for the last 6 months + today = datetime.utcnow() + if period == "last_3_months": + start_date = today - timedelta(days=90) + elif period == "this_year": + start_date = datetime(today.year, 1, 1) + else: # default to last 6 months + start_date = today - timedelta(days=180) + + # Get time period for revenue from request args + revenue_period = request.args.get("revenue_period", "monthly") + + # Calculate revenue data based on period + if revenue_period == "daily": + revenue_data = ( + db.session.query( + func.DATE_FORMAT(Payment.created_at, "%Y-%m-%d").label("date"), + func.sum(Payment.amount).label("total"), + ) + .filter(Payment.status == "success", Payment.created_at >= start_date) + .group_by(func.DATE_FORMAT(Payment.created_at, "%Y-%m-%d")) + .order_by(func.DATE_FORMAT(Payment.created_at, "%Y-%m-%d")) + .all() + ) + # Format daily data + revenue_labels = [] + revenue_amounts = [] + for date_str, amount in revenue_data: + date = datetime.strptime(date_str, "%Y-%m-%d") + revenue_labels.append(date.strftime("%d %b")) + revenue_amounts.append(float(amount)) + + elif revenue_period == "weekly": + revenue_data = ( + db.session.query( + func.DATE_FORMAT(Payment.created_at, "%X-%V").label("week"), + func.sum(Payment.amount).label("total"), + ) + .filter(Payment.status == "success", Payment.created_at >= start_date) + .group_by(func.DATE_FORMAT(Payment.created_at, "%X-%V")) + .order_by(func.DATE_FORMAT(Payment.created_at, "%X-%V")) + .all() + ) + # Format weekly data + revenue_labels = [] + revenue_amounts = [] + for week_str, amount in revenue_data: + year, week = week_str.split("-") + revenue_labels.append(f"Week {week}") + revenue_amounts.append(float(amount)) + + elif revenue_period == "yearly": + revenue_data = ( + db.session.query( + func.DATE_FORMAT(Payment.created_at, "%Y").label("year"), + func.sum(Payment.amount).label("total"), + ) + .filter(Payment.status == "success") + .group_by(func.DATE_FORMAT(Payment.created_at, "%Y")) + .order_by(func.DATE_FORMAT(Payment.created_at, "%Y")) + .all() + ) + # Format yearly data + revenue_labels = [] + revenue_amounts = [] + for year_str, amount in revenue_data: + revenue_labels.append(year_str) + revenue_amounts.append(float(amount)) + + else: # monthly (default) + revenue_data = ( + db.session.query( + func.DATE_FORMAT(Payment.created_at, "%Y-%m").label("month"), + func.sum(Payment.amount).label("total"), + ) + .filter(Payment.status == "success", Payment.created_at >= start_date) + .group_by(func.DATE_FORMAT(Payment.created_at, "%Y-%m")) + .order_by(func.DATE_FORMAT(Payment.created_at, "%Y-%m")) + .all() + ) + # Format monthly data + revenue_labels = [] + revenue_amounts = [] + for month_str, amount in revenue_data: + month_date = datetime.strptime(month_str, "%Y-%m") + revenue_labels.append(month_date.strftime("%b")) + revenue_amounts.append(float(amount)) + + monthly_orders = ( + db.session.query( + func.DATE_FORMAT(Order.created_at, "%Y-%m").label("month"), + func.count(Order.id).label("count"), + ) + .filter(Order.created_at >= start_date) + .group_by(func.DATE_FORMAT(Order.created_at, "%Y-%m")) + .order_by(func.DATE_FORMAT(Order.created_at, "%Y-%m")) + .all() + ) + + # Format data for the orders chart + order_months = [] + order_counts = [] + + for month_str, count in monthly_orders: + # Parse the month string into a datetime object + month_date = datetime.strptime(month_str, "%Y-%m") + order_months.append(month_date.strftime("%b")) + order_counts.append(count) + + # Get recent orders (last 5) + new_orders = ( + db.session.query(Order, User, Payment) + .join(User, Order.user_id == User.id) + .outerjoin(Payment, Order.id == Payment.order_id) + .order_by(Order.created_at.desc()) + .limit(5) + .all() + ) + + # Format orders for display + recent_orders = [] + for order, user, payment in new_orders: + recent_orders.append( + { + "id": order.id, + "customer_name": user.full_name, + "date": order.created_at.strftime("%B %d, %Y"), + "time": order.created_at.strftime("%I:%M %p"), + "amount": float(order.total_amount), + "payment_type": payment.payment_method if payment else "Pending", + "status": order.order_status, + } + ) + + return render_template( + "home.html", + total_revenue=total_revenue, + total_orders=total_orders, + total_menu=total_menu, + total_staff=total_staff, + new_orders=recent_orders, + order_months=order_months, + order_counts=order_counts, + revenue_labels=revenue_labels, + revenue_amounts=revenue_amounts, + revenue_period=revenue_period, + ) diff --git a/app/routes/inventory.py b/app/routes/inventory.py index 938209d78345b1ac0998c2bd19063c3872b122e7..4a72fe78bbaa2ac2c409165745d76c3a449f8ae3 100644 --- a/app/routes/inventory.py +++ b/app/routes/inventory.py @@ -10,7 +10,7 @@ def update_status_based_on_quantity(quantity): """Automatically determine status based on quantity""" if quantity <= 0: return "out" - elif quantity <= 20: # This threshold can be adjusted + elif quantity <= 20: return "low" else: return "sufficient" diff --git a/app/templates/home.html b/app/templates/home.html index 0c0077198174475e1fb3d444f0f83c964f76624c..5be5b0d9dca0324dff3c1590f420e5d0d11e3228 100644 --- a/app/templates/home.html +++ b/app/templates/home.html @@ -1,248 +1,292 @@ -{% extends 'base.html' %} - -{% block content %} +{% extends 'base.html' %} {% block content %} <div class="container-fluid"> - <h2 class="mb-4">Dashboard</h2> + <h2 class="mb-4">Dashboard</h2> - <!-- Stats Cards Row --> - <div class="row mb-4"> - <!-- Total Revenue Card --> - <div class="col-md-3 mb-3"> - <div class="card h-100 border-0 shadow-sm"> - <div class="card-body d-flex align-items-center"> - <div class="icon-container bg-light rounded-circle p-3 me-3"> - <i class="bi bi-currency-dollar text-success fs-4"></i> - </div> - <div> - <h6 class="text-muted mb-1">Total Revenue</h6> - <h3 class="mb-0">$120,800</h3> - </div> - </div> - </div> + <!-- Stats Cards Row --> + <div class="row mb-4"> + <!-- Total Revenue Card --> + <div class="col-md-3 mb-3"> + <div class="card h-100 border-0 shadow-sm"> + <div class="card-body d-flex align-items-center"> + <div class="icon-container bg-light rounded-circle p-3 me-3"> + <i class="bi bi-currency-dollar text-success fs-4"></i> + </div> + <div> + <h6 class="text-muted mb-1">Total Revenue</h6> + <h3 class="mb-0">${{ "%.2f"|format(total_revenue) }}</h3> + </div> </div> + </div> + </div> - <!-- Total Orders Card --> - <div class="col-md-3 mb-3"> - <div class="card h-100 border-0 shadow-sm"> - <div class="card-body d-flex align-items-center"> - <div class="icon-container bg-light rounded-circle p-3 me-3"> - <i class="bi bi-cart text-primary fs-4"></i> - </div> - <div> - <h6 class="text-muted mb-1">Total Orders</h6> - <h3 class="mb-0">18,000</h3> - </div> - </div> - </div> + <!-- Total Orders Card --> + <div class="col-md-3 mb-3"> + <div class="card h-100 border-0 shadow-sm"> + <div class="card-body d-flex align-items-center"> + <div class="icon-container bg-light rounded-circle p-3 me-3"> + <i class="bi bi-cart text-primary fs-4"></i> + </div> + <div> + <h6 class="text-muted mb-1">Total Orders</h6> + <h3 class="mb-0">{{ total_orders }}</h3> + </div> </div> + </div> + </div> - <!-- Total Menu Card --> - <div class="col-md-3 mb-3"> - <div class="card h-100 border-0 shadow-sm"> - <div class="card-body d-flex align-items-center"> - <div class="icon-container bg-light rounded-circle p-3 me-3"> - <i class="bi bi-journal-text text-info fs-4"></i> - </div> - <div> - <h6 class="text-muted mb-1">Total Menu</h6> - <h3 class="mb-0">150</h3> - </div> - </div> - </div> + <!-- Total Menu Card --> + <div class="col-md-3 mb-3"> + <div class="card h-100 border-0 shadow-sm"> + <div class="card-body d-flex align-items-center"> + <div class="icon-container bg-light rounded-circle p-3 me-3"> + <i class="bi bi-journal-text text-info fs-4"></i> + </div> + <div> + <h6 class="text-muted mb-1">Total Menu</h6> + <h3 class="mb-0">{{ total_menu }}</h3> + </div> </div> + </div> + </div> - <!-- Total Staff Card --> - <div class="col-md-3 mb-3"> - <div class="card h-100 border-0 shadow-sm"> - <div class="card-body d-flex align-items-center"> - <div class="icon-container bg-light rounded-circle p-3 me-3"> - <i class="bi bi-people text-warning fs-4"></i> - </div> - <div> - <h6 class="text-muted mb-1">Total Staff</h6> - <h3 class="mb-0">120</h3> - </div> - </div> - </div> + <!-- Total Staff Card --> + <div class="col-md-3 mb-3"> + <div class="card h-100 border-0 shadow-sm"> + <div class="card-body d-flex align-items-center"> + <div class="icon-container bg-light rounded-circle p-3 me-3"> + <i class="bi bi-people text-warning fs-4"></i> + </div> + <div> + <h6 class="text-muted mb-1">Total Staff</h6> + <h3 class="mb-0">{{ total_staff }}</h3> + </div> </div> + </div> </div> <!-- Charts Row --> <div class="row mb-4"> - <!-- Revenue Chart --> - <div class="col-md-6 mb-3"> - <div class="card border-0 shadow-sm"> - <div class="card-header bg-white d-flex justify-content-between align-items-center"> - <h5 class="card-title mb-0">Total Revenue</h5> - <div class="dropdown"> - <button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" id="revenueFilter" data-bs-toggle="dropdown" aria-expanded="false"> - Filter - </button> - <ul class="dropdown-menu" aria-labelledby="revenueFilter"> - <li><a class="dropdown-item" href="#">Daily</a></li> - <li><a class="dropdown-item" href="#">Weekly</a></li> - <li><a class="dropdown-item" href="#">Monthly</a></li> - <li><a class="dropdown-item" href="#">Yearly</a></li> - </ul> - </div> - </div> - <div class="card-body"> - <div id="revenueChart" style="height: 300px;"></div> - </div> + <!-- Revenue Chart --> + <div class="col-md-6 mb-3"> + <div class="card border-0 shadow-sm"> + <div + class="card-header bg-white d-flex justify-content-between align-items-center" + > + <h5 class="card-title mb-0">Total Revenue</h5> + <div class="dropdown"> + <button + class="btn btn-sm btn-outline-secondary dropdown-toggle" + type="button" + id="revenueFilter" + data-bs-toggle="dropdown" + aria-expanded="false" + > + {% if request.args.get('revenue_period') == 'daily' %} Daily {% + elif request.args.get('revenue_period') == 'weekly' %} Weekly {% + elif request.args.get('revenue_period') == 'yearly' %} Yearly {% + else %} Monthly {% endif %} + </button> + <ul class="dropdown-menu" aria-labelledby="revenueFilter"> + <li> + <a + class="dropdown-item" + href="{{ url_for('home.homepage', revenue_period='daily', period=request.args.get('period', 'last_6_months')) }}" + >Daily</a + > + </li> + <li> + <a + class="dropdown-item" + href="{{ url_for('home.homepage', revenue_period='weekly', period=request.args.get('period', 'last_6_months')) }}" + >Weekly</a + > + </li> + <li> + <a + class="dropdown-item" + href="{{ url_for('home.homepage', revenue_period='monthly', period=request.args.get('period', 'last_6_months')) }}" + >Monthly</a + > + </li> + <li> + <a + class="dropdown-item" + href="{{ url_for('home.homepage', revenue_period='yearly', period=request.args.get('period', 'last_6_months')) }}" + >Yearly</a + > + </li> + </ul> </div> + </div> + <div class="card-body"> + <div id="revenueChart" style="height: 300px"></div> + </div> </div> + </div> - <!-- Orders Chart --> - <div class="col-md-6 mb-3"> - <div class="card border-0 shadow-sm"> - <div class="card-header bg-white d-flex justify-content-between align-items-center"> - <h5 class="card-title mb-0">Total Orders</h5> - <div class="dropdown"> - <button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" id="ordersFilter" data-bs-toggle="dropdown" aria-expanded="false"> - Last 6 months - </button> - <ul class="dropdown-menu" aria-labelledby="ordersFilter"> - <li><a class="dropdown-item" href="#">Last 3 months</a></li> - <li><a class="dropdown-item" href="#">Last 6 months</a></li> - <li><a class="dropdown-item" href="#">This year</a></li> - </ul> - </div> - </div> - <div class="card-body"> - <div id="ordersChart" style="height: 300px;"></div> - </div> + <!-- Orders Chart --> + <div class="col-md-6 mb-3"> + <div class="card border-0 shadow-sm"> + <div + class="card-header bg-white d-flex justify-content-between align-items-center" + > + <h5 class="card-title mb-0">Total Orders</h5> + <div class="dropdown"> + <button + class="btn btn-sm btn-outline-secondary dropdown-toggle" + type="button" + id="ordersFilter" + data-bs-toggle="dropdown" + aria-expanded="false" + > + {% if request.args.get('period') == 'last_3_months' %} Last 3 + months {% elif request.args.get('period') == 'this_year' %} This + year {% else %} Last 6 months {% endif %} + </button> + <ul class="dropdown-menu" aria-labelledby="ordersFilter"> + <li> + <a + class="dropdown-item" + href="{{ url_for('home.homepage', period='last_3_months') }}" + >Last 3 months</a + > + </li> + <li> + <a + class="dropdown-item" + href="{{ url_for('home.homepage', period='last_6_months') }}" + >Last 6 months</a + > + </li> + <li> + <a + class="dropdown-item" + href="{{ url_for('home.homepage', period='this_year') }}" + >This year</a + > + </li> + </ul> </div> + </div> + <div class="card-body"> + <div id="ordersChart" style="height: 300px"></div> + </div> </div> + </div> </div> <!-- New Orders Table --> <div class="card border-0 shadow-sm mb-4"> - <div class="card-header bg-white d-flex justify-content-between align-items-center"> - <h5 class="card-title mb-0">New Orders</h5> - <div class="dropdown"> - <button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" id="newOrdersFilter" data-bs-toggle="dropdown" aria-expanded="false"> - Filter - </button> - <ul class="dropdown-menu" aria-labelledby="newOrdersFilter"> - <li><a class="dropdown-item" href="#">Today</a></li> - <li><a class="dropdown-item" href="#">Yesterday</a></li> - <li><a class="dropdown-item" href="#">Last 7 Days</a></li> - </ul> - </div> + <div + class="card-header bg-white d-flex justify-content-between align-items-center" + > + <h5 class="card-title mb-0">New Orders</h5> + <div class="dropdown"> + <button + class="btn btn-sm btn-outline-secondary dropdown-toggle" + type="button" + id="newOrdersFilter" + data-bs-toggle="dropdown" + aria-expanded="false" + > + Filter + </button> + <ul class="dropdown-menu" aria-labelledby="newOrdersFilter"> + <li><a class="dropdown-item" href="#">Today</a></li> + <li><a class="dropdown-item" href="#">Yesterday</a></li> + <li><a class="dropdown-item" href="#">Last 7 Days</a></li> + </ul> </div> - <div class="card-body"> - <div class="table-responsive"> - <table class="table table-hover"> - <thead> - <tr> - <th>Order ID</th> - <th>Customer Name</th> - <th>Date</th> - <th>Time</th> - <th>Amount</th> - <th>Payment Type</th> - <th>Status</th> - <th>Action</th> - </tr> - </thead> - <tbody> - <tr> - <td>#67961</td> - <td>Mark Allen</td> - <td>May 29, 2023</td> - <td>10:30 AM</td> - <td>$120</td> - <td>Online</td> - <td><span class="badge bg-danger">Reject</span></td> - <td> - <div class="d-flex"> - <button class="btn btn-sm btn-success me-2">Accept</button> - <button class="btn btn-sm btn-light"><i class="bi bi-three-dots"></i></button> - </div> - </td> - </tr> - <tr> - <td>#67961</td> - <td>Mark Allen</td> - <td>May 29, 2023</td> - <td>10:30 AM</td> - <td>$120</td> - <td>Online</td> - <td><span class="badge bg-danger">Reject</span></td> - <td> - <div class="d-flex"> - <button class="btn btn-sm btn-success me-2">Accept</button> - <button class="btn btn-sm btn-light"><i class="bi bi-three-dots"></i></button> - </div> - </td> - </tr> - <tr> - <td>#67961</td> - <td>Mark Allen</td> - <td>May 29, 2023</td> - <td>10:30 AM</td> - <td>$120</td> - <td>Online</td> - <td><span class="badge bg-danger">Reject</span></td> - <td> - <div class="d-flex"> - <button class="btn btn-sm btn-success me-2">Accept</button> - <button class="btn btn-sm btn-light"><i class="bi bi-three-dots"></i></button> - </div> - </td> - </tr> - <tr> - <td>#67961</td> - <td>Mark Allen</td> - <td>May 29, 2023</td> - <td>10:30 AM</td> - <td>$120</td> - <td>Online</td> - <td><span class="badge bg-danger">Reject</span></td> - <td> - <div class="d-flex"> - <button class="btn btn-sm btn-success me-2">Accept</button> - <button class="btn btn-sm btn-light"><i class="bi bi-three-dots"></i></button> - </div> - </td> - </tr> - </tbody> - </table> - </div> - <div class="d-flex justify-content-center mt-3"> - <a href="#" class="btn btn-outline-primary">See All</a> - </div> + </div> + <div class="card-body"> + <div class="table-responsive"> + <table class="table table-hover"> + <thead> + <tr> + <th>Order ID</th> + <th>Customer Name</th> + <th>Date</th> + <th>Time</th> + <th>Amount</th> + <th>Payment Type</th> + <th>Status</th> + <th>Action</th> + </tr> + </thead> + <tbody> + {% for order in new_orders %} + <tr> + <td>#{{ order.id }}</td> + <td>{{ order.customer_name }}</td> + <td>{{ order.date }}</td> + <td>{{ order.time }}</td> + <td>${{ "%.2f"|format(order.amount) }}</td> + <td>{{ order.payment_type|title }}</td> + <td> + <span + class="badge bg-{{ 'success' if order.status == 'completed' else 'warning' if order.status == 'pending' else 'danger' if order.status == 'cancelled' else 'info' }}" + >{{ order.status|title }}</span + > + </td> + <td> + <div class="d-flex"> + <a + href="{{ url_for('order.order_detail', order_id=order.id) }}" + class="btn btn-sm btn-success me-2" + >View</a + > + {% if order.status == 'pending' %} + <button class="btn btn-sm btn-light"> + <i class="bi bi-three-dots"></i> + </button> + {% endif %} + </div> + </td> + </tr> + {% else %} + <tr> + <td colspan="8" class="text-center">No orders found</td> + </tr> + {% endfor %} + </tbody> + </table> + </div> + <div class="d-flex justify-content-center mt-3"> + <a + href="{{url_for('order.order_history')}}" + class="btn btn-outline-primary" + >See All</a + > </div> + </div> </div> -</div> -{% endblock %} - -{% block scripts %} -<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script> -<script> + </div> + {% endblock %} {% block scripts %} + <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script> + <script> // Revenue Chart var revenueOptions = { series: [{ - name: 'Revenue', - data: [100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650] + name: "Revenue", + data: {{ revenue_amounts|tojson }} }], chart: { - type: 'area', + type: "area", height: 300, toolbar: { show: false } }, - colors: ['#00a389'], + colors: ["#00a389"], dataLabels: { enabled: false }, stroke: { - curve: 'smooth', + curve: "smooth", width: 2 }, fill: { - type: 'gradient', + type: "gradient", gradient: { shadeIntensity: 1, opacityFrom: 0.7, @@ -251,103 +295,115 @@ } }, xaxis: { - categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + categories: {{ revenue_labels|tojson }}, labels: { style: { - colors: '#888' + colors: "#888" } } }, yaxis: { labels: { formatter: function(val) { - return '$' + val; + return "$" + val.toFixed(2); }, style: { - colors: '#888' + colors: "#888" } } }, grid: { - borderColor: '#f1f1f1', + borderColor: "#f1f1f1", row: { - colors: ['transparent', 'transparent'], + colors: ["transparent", "transparent"], opacity: 0.5 } }, markers: { size: 4, - colors: ['#00a389'], - strokeColors: '#fff', + colors: ["#00a389"], + strokeColors: "#fff", strokeWidth: 2, hover: { - size: 7, + size: 7 } }, tooltip: { y: { formatter: function(val) { - return '$' + val; + return "$" + val.toFixed(2); } } } }; - var revenueChart = new ApexCharts(document.querySelector("#revenueChart"), revenueOptions); + var revenueChart = new ApexCharts( + document.querySelector("#revenueChart"), + revenueOptions + ); revenueChart.render(); // Orders Chart var ordersOptions = { series: [{ - name: 'Orders', - data: [200, 400, 300, 500, 350, 250] + name: "Orders", + data: {{ order_counts|tojson }} }], chart: { - type: 'bar', + type: "bar", height: 300, toolbar: { show: false } }, - colors: ['#00a389'], + colors: ["#00a389"], plotOptions: { bar: { borderRadius: 8, - columnWidth: '30%', + columnWidth: "30%" } }, dataLabels: { enabled: false }, xaxis: { - categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], + categories: {{ order_months|tojson }}, labels: { style: { - colors: '#888' + colors: "#888" } } }, yaxis: { labels: { style: { - colors: '#888' + colors: "#888" + }, + formatter: function(val) { + return Math.round(val); // Show whole numbers only } } }, grid: { - borderColor: '#f1f1f1', + borderColor: "#f1f1f1", row: { - colors: ['transparent', 'transparent'], + colors: ["transparent", "transparent"], opacity: 0.5 } }, tooltip: { shared: true, - intersect: false + intersect: false, + y: { + formatter: function(val) { + return val + " orders"; + } + } } }; var ordersChart = new ApexCharts(document.querySelector("#ordersChart"), ordersOptions); ordersChart.render(); -</script> -{% endblock %} \ No newline at end of file + </script> + {% endblock %} +</div> diff --git a/main.py b/main.py index 685a423a332d0da0a09897266055bcba728d15d6..827ca262bc876f28fca2894c633ff4ed2859a987 100644 --- a/main.py +++ b/main.py @@ -6,25 +6,26 @@ from app.dummydata import create_dummy_data app = create_app() -# def init_database(): -# """Initialize database and create dummy data""" -# with app.app_context(): -# # Drop all tables to start fresh -# db.drop_all() -# print("Dropped all existing tables.") +def init_database(): + """Initialize database and create dummy data only if not exists""" + with app.app_context(): + # Create tables only if they don't exist + db.create_all() + print("Ensured all tables exist.") -# # Create all tables -# db.create_all() -# print("Created new database tables.") + # Check if dummy data already exists before inserting + from app.models import User -# # Import dummy data -# create_dummy_data() -# print("Database setup complete!") + if not User.query.first(): + create_dummy_data() + print("Inserted dummy data.") + else: + print("Dummy data already exists. Skipping insertion.") if __name__ == "__main__": # Initialize database before running the app - # init_database() + init_database() # Run the application in debug mode when executed directly app.run(debug=True)