You are on page 1of 8

# views.

py

from django.shortcuts import render


from django.contrib.auth.decorators import login_required
from main.models import Donation
import plotly.offline as opy
import plotly.graph_objs as go
import pandas as pd
from datetime import datetime
from calendar import month_name as calendar_month_name
import calendar
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils.dateformat import DateFormat
from django.utils.formats import date_format

def render_chart(data, selected_month=None, selected_year=None,


current_month=True):
df = pd.DataFrame(data)
df['dates'] = pd.to_datetime(df['dates'])

# Sort the DataFrame by dates to ensure consistent ordering


df = df.sort_values(by='dates')

if selected_month is not None and selected_year is not None:


# Set the title based on the selected month and year
month_name = calendar.month_name[selected_month]
title = f'Collection Amount for {month_name} {selected_year}'
elif current_month:
# Set the title for the current month and year
current_month = datetime.now().month
current_year = datetime.now().year
month_name = calendar.month_name[current_month]
title = f'Collection Amount for {month_name} {current_year}'
else:
title = 'Collection Amount Over Time'

fig = go.Figure()

# Add trace for the line chart


fig.add_trace(go.Scatter(
x=df['dates'],
y=df['amounts'],
mode='lines+markers',
name='Collection Amount',
line=dict(color='#1f77b4', width=2), # Blue line
marker=dict(color='#1f77b4', size=8, line=dict(color='#ffffff', width=1)),
# Blue markers
))

# Update layout with the dynamically generated title


fig.update_layout(
title=title,
xaxis_title='Date',
yaxis_title='Amount',
template='plotly_white',
font=dict(family='Arial, sans-serif', size=12, color='#333'), # Darker
font color
margin=dict(l=60, r=60, t=80, b=60), # Increased margins
plot_bgcolor='#f5f5f5', # Light gray background color
paper_bgcolor='#f5f5f5', # Light gray paper background color
xaxis=dict(
showline=True,
showgrid=False,
showticklabels=True,
linecolor='#333',
linewidth=1,
ticks='outside',
tickfont=dict(family='Arial, sans-serif', size=10, color='#333'), #
Darker axis line and ticks
),
yaxis=dict(
showline=True,
showgrid=True,
showticklabels=True,
linecolor='#333',
linewidth=1,
ticks='outside',
tickfont=dict(family='Arial, sans-serif', size=10, color='#333') #
Darker axis line and ticks
),
)

plot_div = opy.plot(fig, auto_open=False, output_type='div')

return plot_div

def render_year_chart(data, selected_year=None):


# Prepare data for year-wise chart
year_data = {
'dates': [],
'amounts': []
}

# Group data by month and sum the amounts for each month
monthly_collection = {}
for donation in data:
month_year_key = donation['service_date'].strftime('%B-%Y')
if month_year_key not in monthly_collection:
monthly_collection[month_year_key] = 0
monthly_collection[month_year_key] += donation['amount']

# Convert the grouped data into lists for Plotly


for month_year, amount in monthly_collection.items():
year_data['dates'].append(month_year)
year_data['amounts'].append(amount)

# Define the order of months for correct ordering on the X-axis


ordered_months = [
'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'
]

# Sort the data based on the order of months


sorted_data = sorted(zip(year_data['dates'], year_data['amounts']), key=lambda
x: ordered_months.index(x[0].split('-')[0]))

# Unpack the sorted data only if it exists


if sorted_data:
sorted_dates, sorted_amounts = zip(*sorted_data)
else:
sorted_dates, sorted_amounts = [], []

fig = go.Figure()

# Add trace for the line chart only if there is data


if sorted_dates and sorted_amounts:
fig.add_trace(go.Scatter(
x=sorted_dates,
y=sorted_amounts,
mode='lines+markers',
name='Monthly Collection',
line=dict(color='#1f77b4', width=2), # Blue line
marker=dict(color='#1f77b4', size=8, line=dict(color='#ffffff',
width=1)), # Blue markers
))

# Update layout
if selected_year is not None:
title = f'Monthly Collection for {selected_year}'
else:
current_year = datetime.now().year
title = f'Monthly Collection for {current_year}'

fig.update_layout(
title=title,
xaxis_title='Month',
yaxis_title='Amount',
template='plotly_white',
font=dict(family='Arial, sans-serif', size=12, color='#333'), # Darker
font color
margin=dict(l=60, r=60, t=80, b=60), # Increased margins
plot_bgcolor='#f5f5f5', # Light gray background color
paper_bgcolor='#f5f5f5', # Light gray paper background color
xaxis=dict(
showline=True,
showgrid=False,
showticklabels=True,
linecolor='#333',
linewidth=1,
ticks='outside',
tickfont=dict(family='Arial, sans-serif', size=10, color='#333'), #
Darker axis line and ticks
categoryorder='array', # Specify ordering for categorical axis
categoryarray=ordered_months # Order the months according to the
predefined list
),
yaxis=dict(
showline=True,
showgrid=True,
showticklabels=True,
linecolor='#333',
linewidth=1,
ticks='outside',
tickfont=dict(family='Arial, sans-serif', size=10, color='#333') #
Darker axis line and ticks
),
)

plot_div = opy.plot(fig, auto_open=False, output_type='div')

return plot_div

def month_name(month):
# Function to get the name of the month from its number
return datetime.strptime(str(month), '%m').strftime('%B')

@login_required
def chart_view(request):
# Get referral code associated with the logged-in user
referral_code = request.user.referral_code

# Fetch donations for the current month and current year


current_month = datetime.now().month
current_year = datetime.now().year
current_month_donations = Donation.objects.filter(referral_code=referral_code,
service_date__month=current_month)
current_year_donations = Donation.objects.filter(referral_code=referral_code,
service_date__year=current_year)

# Prepare data for month-wise chart (default to current month)


month_data = {
'dates': [donation.service_date for donation in current_month_donations if
donation.service_date],
'amounts': [donation.amount for donation in current_month_donations if
donation.service_date],
}

# If a month is selected from the dropdown, update the month_data accordingly


selected_month = int(request.GET.get('month', current_month))
selected_year = int(request.GET.get('year', current_year))
if selected_month != current_month or selected_year != current_year:
selected_month_donations =
Donation.objects.filter(referral_code=referral_code,
service_date__month=selected_month, service_date__year=selected_year)
month_data = {
'dates': [donation.service_date for donation in
selected_month_donations if donation.service_date],
'amounts': [donation.amount for donation in selected_month_donations if
donation.service_date],
}

# Generate month-wise chart div


month_chart_div = render_chart(month_data, selected_month=selected_month,
selected_year=selected_year, current_month=False)

# Prepare data for year-wise chart


selected_year_for_year_chart = int(request.GET.get('year_for_year_chart',
current_year))
year_data = []
for donation in current_year_donations:
year_data.append({
'service_date': donation.service_date,
'amount': donation.amount
})

# Generate year-wise chart div


year_chart_div = render_year_chart(year_data,
selected_year=selected_year_for_year_chart)

# Get list of months and years for dropdowns


months = [(i, calendar_month_name[i]) for i in range(1, 13)]
years = range(2021, current_year + 1)

# Get list of years specifically for render_year_chart dropdown


years_for_year_chart = range(2021, current_year + 1)

# Generate dynamic title for the month-wise chart


if selected_month != current_month or selected_year != current_year:
month_name = DateFormat(datetime(selected_year, selected_month,
1)).format('F')
month_chart_title = f'Daily Collection for {month_name} {selected_year}'
else:
month_name = DateFormat(datetime.now()).format('F')
month_chart_title = f'Daily Collection for {month_name} {current_year}'

# Initialize year_chart_title with a default value


year_chart_title = f'Monthly Collection for {current_year}'

# Handle filtering for year-wise chart


if request.method == 'GET' and 'year_for_year_chart' in request.GET:
selected_year_for_year_chart = int(request.GET.get('year_for_year_chart'))
if selected_year_for_year_chart != current_year:
year_data = []
for donation in Donation.objects.filter(referral_code=referral_code,
service_date__year=selected_year_for_year_chart):
year_data.append({
'service_date': donation.service_date,
'amount': donation.amount
})
year_chart_div = render_year_chart(year_data,
selected_year=selected_year_for_year_chart) # Pass selected year to the function
# Update year-wise chart title when filtered
year_chart_title = f'Monthly Collection for
{selected_year_for_year_chart}'

return render(request, 'referral/chart.html', {


'month_chart_div': month_chart_div,
'year_chart_div': year_chart_div,
'months': months,
'years': years,
'years_for_year_chart': years_for_year_chart,
'selected_month': selected_month,
'selected_year': selected_year,
'selected_year_for_year_chart': selected_year_for_year_chart,
'month_chart_title': month_chart_title,
'year_chart_title': year_chart_title,
})

{% extends 'referral/base.html' %}
{% block content %}
<style>
/* Custom CSS */
.chart-container {
border: 1px solid #dee2e6; /* Gray border */
border-radius: 5px; /* Rounded corners */
padding: 20px; /* Padding around the chart */
background-color: #fff; /* White background color */
margin-top: 20px; /* Add margin to separate from title */
}

.chart-container h2 {
color: #343a40; /* Dark text color */
margin-bottom: 20px; /* Bottom margin for heading */
}

/* Optional: Add more styling as needed */


</style>

<!-- Dropdown for selecting month and year -->


<div class="container mt-4">
<div class="row justify-content-center">
<div class="col-md-4 mb-3">
<select id="month-dropdown" class="form-select">
{% for month in months %}
<option value="{{ month.0 }}" {% if month.0 == selected_month
%}selected{% endif %}>{{ month.1 }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-4 mb-3">
<select id="year-dropdown" class="form-select">
{% for year in years %}
<option value="{{ year }}" {% if year == selected_year %}selected{% endif
%}>{{ year }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-4 mb-3">
<button id="apply-filter-btn" class="btn btn-primary">Apply Filter</button>
</div>
</div>
</div>

<!-- Display month-wise chart -->


<hr>
<div class="container my-4">
<h2 class="text-center">{{ month_chart_title }}</h2> <!-- Display month-wise
chart title -->
<div id="month_chart_div" class="chart-container">
{{ month_chart_div|safe }}
</div>
</div>

<!-- Display year-wise chart -->


<hr>

<!-- Dropdown for selecting year for year-wise chart -->


<div class="container mt-4">
<div class="row justify-content-center">
<div class="col-md-4 mb-3">
<select id="year-dropdown-year-chart" class="form-select">
{% for year in years_for_year_chart %}
<option value="{{ year }}" {% if year == selected_year_for_year_chart
%}selected{% endif %}>{{ year }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-2 mb-3">
<button id="filter-btn" class="btn btn-primary">Filter</button>
</div>
</div>
</div>

<!-- ... (existing HTML) ... -->

<hr>
<div class="container my-4">
<h2 class="text-center">{{ year_chart_title }}</h2> <!-- Display year-wise chart
title -->
<div id="year_chart_div" class="chart-container">
{{ year_chart_div|safe }}
</div>
</div>

<script>
// JavaScript code for handling dropdown selection and applying filters for
month-wise chart
document.getElementById('apply-filter-btn').addEventListener('click', function()
{
var selectedMonth = document.getElementById('month-dropdown').value;
var selectedYear = document.getElementById('year-dropdown').value;
window.location.href = '/referral/chart/?month=' + selectedMonth + '&year=' +
selectedYear;
});

// JavaScript code for handling dropdown selection for year-wise chart


document.getElementById('year-dropdown-year-chart').addEventListener('change',
function() {
var selectedYear = document.getElementById('year-dropdown-year-chart').value;
// Call function to update year-wise chart based on selected year
updateYearChart(selectedYear);
});

// Function to update year-wise chart based on selected year


function updateYearChart(selectedYear) {
// Make AJAX call to fetch data for year-wise chart based on selected year
// Update the chart with the fetched data
// Example:
// $.ajax({
// url: '/referral/chart/yearly/?year=' + selectedYear,
// success: function(data) {
// // Update year-wise chart with the fetched data
// },
// error: function(xhr, status, error) {
// console.error(error);
// }
// });
}

// JavaScript code for handling year-wise chart filter


document.getElementById('filter-btn').addEventListener('click', function() {
var selectedYear = document.getElementById('year-dropdown-year-chart').value;
window.location.href = '/referral/chart/?year_for_year_chart=' + selectedYear;
});
</script>

{% endblock %}

You might also like