Skip to content

Commit

Permalink
Added minimum chart features and dummy database
Browse files Browse the repository at this point in the history
  • Loading branch information
supsa-ak committed Dec 17, 2021
1 parent 2314570 commit 9c5b7f2
Show file tree
Hide file tree
Showing 15 changed files with 402 additions and 9 deletions.
Binary file modified BudMan/__pycache__/urls.cpython-38.pyc
Binary file not shown.
4 changes: 2 additions & 2 deletions BudMan/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@

urlpatterns = [
path('admin/', admin.site.urls),
path('', include('app.urls')),
]
path('shop/', include('app.urls')),
]
Binary file modified app/__pycache__/admin.cpython-38.pyc
Binary file not shown.
Binary file modified app/__pycache__/models.cpython-38.pyc
Binary file not shown.
Binary file modified app/__pycache__/urls.cpython-38.pyc
Binary file not shown.
Binary file modified app/__pycache__/views.cpython-38.pyc
Binary file not shown.
4 changes: 3 additions & 1 deletion app/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from django.contrib import admin
from app.models import Item, Purchase

# Register your models here.
admin.site.register(Item)
admin.site.register(Purchase)
38 changes: 38 additions & 0 deletions app/management/commands/populate_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

import random
from datetime import datetime, timedelta

import pytz
from django.core.management.base import BaseCommand

from app.models import Item, Purchase


class Command(BaseCommand):
help = 'Populates the database with random generated data.'

def add_arguments(self, parser):
parser.add_argument('--amount', type=int, help='The number of purchases that should be created.')

def handle(self, *args, **options):
names = ['James', 'John', 'Robert', 'Michael', 'William', 'David', 'Richard', 'Joseph', 'Thomas', 'Charles']
surname = ['Smith', 'Jones', 'Taylor', 'Brown', 'Williams', 'Wilson', 'Johnson', 'Davies', 'Patel', 'Wright']
items = [
Item.objects.get_or_create(name='Socks', price=6.5), Item.objects.get_or_create(name='Pants', price=12),
Item.objects.get_or_create(name='T-Shirt', price=8), Item.objects.get_or_create(name='Boots', price=9),
Item.objects.get_or_create(name='Sweater', price=3), Item.objects.get_or_create(name='Underwear', price=9),
Item.objects.get_or_create(name='Leggings', price=7), Item.objects.get_or_create(name='Cap', price=5),
]
amount = options['amount'] if options['amount'] else 2500
for i in range(0, amount):
dt = pytz.utc.localize(datetime.now() - timedelta(days=random.randint(0, 1825)))
purchase = Purchase.objects.create(
customer_full_name=random.choice(names) + ' ' + random.choice(surname),
item=random.choice(items)[0],
payment_method=random.choice(Purchase.PAYMENT_METHODS)[0],
successful=True if random.randint(1, 2) == 1 else False,
)
purchase.time = dt
purchase.save()

self.stdout.write(self.style.SUCCESS('Successfully populated the database.'))
38 changes: 38 additions & 0 deletions app/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Generated by Django 4.0 on 2021-12-17 14:11

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='Item',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('description', models.TextField(null=True)),
('price', models.FloatField(default=0)),
],
),
migrations.CreateModel(
name='Purchase',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('customer_full_name', models.CharField(max_length=64)),
('payment_method', models.CharField(choices=[('CC', 'Credit card'), ('DC', 'Debit card'), ('ET', 'Ethereum'), ('BC', 'Bitcoin')], default='CC', max_length=2)),
('time', models.DateTimeField(auto_now_add=True)),
('successful', models.BooleanField(default=False)),
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.item')),
],
options={
'ordering': ['-time'],
},
),
]
28 changes: 27 additions & 1 deletion app/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
from django.db import models

# Create your models here.
class Item(models.Model):
name = models.CharField(max_length=255)
description = models.TextField(null=True)
price = models.FloatField(default=0)

def __str__(self):
return f'{self.name} (${self.price})'


class Purchase(models.Model):
customer_full_name = models.CharField(max_length=64)
item = models.ForeignKey(to=Item, on_delete=models.CASCADE)
PAYMENT_METHODS = [
('CC', 'Credit card'),
('DC', 'Debit card'),
('ET', 'Ethereum'),
('BC', 'Bitcoin'),
]
payment_method = models.CharField(max_length=2, default='CC', choices=PAYMENT_METHODS)
time = models.DateTimeField(auto_now_add=True)
successful = models.BooleanField(default=False)

class Meta:
ordering = ['-time']

def __str__(self):
return f'{self.customer_full_name}, {self.payment_method} ({self.item.name})'
138 changes: 138 additions & 0 deletions app/templates/app/statistics.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Statistics</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/bootstrap-grid.min.css">
</head>
<body>
<div class="container">
<form id="filterForm">
<label for="year">Choose a year:</label>
<select name="year" id="year"></select>
<input type="submit" value="Load" name="_load">
</form>
<div class="row">
<div class="col-6">
<canvas id="salesChart"></canvas>
</div>
<div class="col-6">
<canvas id="paymentSuccessChart"></canvas>
</div>
<div class="col-6">
<canvas id="spendPerCustomerChart"></canvas>
</div>
<div class="col-6">
<canvas id="paymentMethodChart"></canvas>
</div>
</div>
<script>
let salesCtx = document.getElementById("salesChart").getContext("2d");
let salesChart = new Chart(salesCtx, {
type: "bar",
options: {
responsive: true,
}
});
let spendPerCustomerCtx = document.getElementById("spendPerCustomerChart").getContext("2d");
let spendPerCustomerChart = new Chart(spendPerCustomerCtx, {
type: "line",
options: {
responsive: true,
}
});
let paymentSuccessCtx = document.getElementById("paymentSuccessChart").getContext("2d");
let paymentSuccessChart = new Chart(paymentSuccessCtx, {
type: "pie",
options: {
responsive: true,
layout: {
padding: {
left: 0,
right: 0,
top: 0,
bottom: 25
}
}
}
});
let paymentMethodCtx = document.getElementById("paymentMethodChart").getContext("2d");
let paymentMethodChart = new Chart(paymentMethodCtx, {
type: "pie",
options: {
responsive: true,
layout: {
padding: {
left: 0,
right: 0,
top: 0,
bottom: 25
}
}
}
});
</script>
</div>
<script>
$(document).ready(function() {
$.ajax({
url: "/shop/chart/filter-options/",
type: "GET",
dataType: "json",
success: (jsonResponse) => {
// Load all the options
jsonResponse.options.forEach(option => {
$("#year").append(new Option(option, option));
});
// Load data for the first option
loadAllCharts($("#year").children().first().val());
},
error: () => console.log("Failed to fetch chart filter options!")
});
});

$("#filterForm").on("submit", (event) => {
event.preventDefault();

const year = $("#year").val();
loadAllCharts(year)
});

function loadChart(chart, endpoint) {
$.ajax({
url: endpoint,
type: "GET",
dataType: "json",
success: (jsonResponse) => {
// Extract data from the response
const title = jsonResponse.title;
const labels = jsonResponse.data.labels;
const datasets = jsonResponse.data.datasets;

// Reset the current chart
chart.data.datasets = [];
chart.data.labels = [];

// Load new data into the chart
chart.options.title.text = title;
chart.options.title.display = true;
chart.data.labels = labels;
datasets.forEach(dataset => {
chart.data.datasets.push(dataset);
});
chart.update();
},
error: () => console.log("Failed to fetch chart data from " + endpoint + "!")
});
}

function loadAllCharts(year) {
loadChart(salesChart, `/shop/chart/sales/${year}/`);
loadChart(spendPerCustomerChart, `/shop/chart/spend-per-customer/${year}/`);
loadChart(paymentSuccessChart, `/shop/chart/payment-success/${year}/`);
loadChart(paymentMethodChart, `/shop/chart/payment-method/${year}/`);
}
</script>
</body>
</html>
10 changes: 8 additions & 2 deletions app/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from django.urls import path
from .views import *

from . import views

urlpatterns = [
path('', home, name='home'),
path('statistics/', views.statistics_view, name='shop-statistics'),
path('chart/filter-options/', views.get_filter_options, name='chart-filter-options'),
path('chart/sales/<int:year>/', views.get_sales_chart, name='chart-sales'),
path('chart/spend-per-customer/<int:year>/', views.spend_per_customer_chart, name='chart-spend-per-customer'),
path('chart/payment-success/<int:year>/', views.payment_success_chart, name='chart-payment-success'),
path('chart/payment-method/<int:year>/', views.payment_method_chart, name='chart-payment-method'),
]
Loading

0 comments on commit 9c5b7f2

Please sign in to comment.