Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a column for renewals count to the activity report #1809

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 29 additions & 16 deletions app/controllers/admin/reports/monthly_activities_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,43 @@ module Admin
module Reports
class MonthlyActivitiesController < BaseController
def index
fetch_monthly_activities
@monthly_activities = fetch_activities
end

def fetch_monthly_activities
@monthly_activities = {}
private

# TODO: load_async in Rails 7
appointments = MonthlyAppointment.all
loans = MonthlyLoan.all
members = MonthlyMember.all
def fetch_activities
records = [*MonthlyAppointment.all, *MonthlyLoan.all, *MonthlyMember.all, *MonthlyRenewal.all]

assign_monthlies(appointments, %i[appointments_count completed_appointments_count])
assign_monthlies(loans, %i[loans_count active_members_count])
assign_monthlies(members, %i[new_members_count pending_members_count])
records.group_by(&:year).each_with_object([]) do |(year, records_for_year), grouped_year|
monthly_values = records_for_year.group_by(&:month).each_with_object([]) do |(month, records_for_month), grouped_month|
grouped_month << [month, records_to_amount_hash(records_for_month)]
end

@monthly_activities = @monthly_activities.sort.to_h
grouped_year << [year, monthly_values.sort_by(&:first)]
end.sort_by(&:first)
end

def assign_monthlies(records, columns)
records.each do |record|
key = "#{record.year}-#{record.month.to_s.rjust(2, "0")}"
monthly = @monthly_activities[key] ||= Hash.new(0)
def columns_for_record(record)
case record
when MonthlyAppointment
%i[appointments_count completed_appointments_count]
when MonthlyLoan
%i[loans_count active_members_count]
when MonthlyMember
%i[new_members_count pending_members_count]
when MonthlyRenewal
%i[renewals_count]
else
raise "Unknow record type: #{record}"
end
end

columns.each { |column| monthly[column] = record[column] }
def records_to_amount_hash(records)
records.each_with_object(Hash.new(0)) do |record, hash|
columns_for_record(record).each do |column|
hash[column] = record[column]
end
end
end
end
Expand Down
1 change: 1 addition & 0 deletions app/models/monthly_appointment.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# View from the Scenic gem
class MonthlyAppointment < ApplicationRecord
end
1 change: 1 addition & 0 deletions app/models/monthly_loan.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# View from the Scenic gem
class MonthlyLoan < ApplicationRecord
end
1 change: 1 addition & 0 deletions app/models/monthly_member.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# View from the Scenic gem
class MonthlyMember < ApplicationRecord
end
3 changes: 3 additions & 0 deletions app/models/monthly_renewal.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# View from the Scenic gem
class MonthlyRenewal < ApplicationRecord
end
123 changes: 80 additions & 43 deletions app/views/admin/reports/monthly_activities/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,83 @@
<%= index_header "Activity" %>
<% end %>

<table class="table monthly-adjustments">
<thead>
<tr>
<th></th>
<th class="left-lined" colspan="2">Activity</th>
<th class="left-lined" colspan="2">Members</th>
<th class="left-lined" colspan="2">Appointments</th>
</tr>
<tr>
<th>Month</th>
<th class="left-lined">Loans</th>
<th>Members</th>
<th class="left-lined">New</th>
<th>Pending</th>
<th class="left-lined">Scheduled</th>
<th>Completed</th>
</tr>
</thead>
<tbody>
<% @monthly_activities.each do |date, activities| %>
<tr>
<% year, month = date.split("-") %>
<td><%= Date::MONTHNAMES[month.to_i] %> <%= year %></td>
<td class="left-lined"><%= activities[:loans_count] %></td>
<td class="left-lined"><%= activities[:active_members_count] %></td>
<td class="left-lined"><%= activities[:new_members_count] %></td>
<td class="left-lined"><%= activities[:pending_members_count] %></td>
<td class="left-lined"><%= activities[:appointments_count] %></td>
<td class="left-lined"><%= activities[:completed_appointments_count] %></td>
</tr>
<% end %>
<tfoot>
<tr>
<td>Total</td>
<td class="left-lined"><%= @monthly_activities.values.sum { |a| a[:loans_count] } %></td>
<td class="left-lined"><%= @monthly_activities.values.sum { |a| a[:active_members_count] } %></td>
<td class="left-lined"><%= @monthly_activities.values.sum { |a| a[:new_members_count] } %></td>
<td class="left-lined"><%= @monthly_activities.values.sum { |a| a[:pending_members_count] } %></td>
<td class="left-lined"><%= @monthly_activities.values.sum { |a| a[:appointments_count] } %></td>
<td class="left-lined"><%= @monthly_activities.values.sum { |a| a[:completed_appointments_count] } %></td>
</tr>
</tfoot>
</table>
<% @monthly_activities.each do |(year, activities_by_month)| %>
<div id="year-<%= year %>">
<h2><%= year -%></h2>
<table class="table monthly-adjustments">
<thead>
<tr>
<th></th>
<th class="left-lined" colspan="2">Activity</th>
<th class="left-lined" colspan="2">Members</th>
<th class="left-lined" colspan="2">Appointments</th>
</tr>
<tr>
<th>Month</th>
<th class="left-lined">Loans</th>
<th class="left-lined">Renewals</th>
<th>Members</th>
<th class="left-lined">New</th>
<th>Pending</th>
<th class="left-lined">Scheduled</th>
<th>Completed</th>
</tr>
</thead>
<tbody>
<% activities_by_month.each do |month, activities| %>
<tr>
<td class="month"><%= Date::MONTHNAMES[month.to_i] %></td>
<td class="left-lined <%= "loans_count-#{year}-#{month}" %>">
<%= activities[:loans_count] %>
</td>
<td class="left-lined <%= "renewals_count-#{year}-#{month}" %>">
<%= activities[:renewals_count] %>
</td>
<td class="left-lined <%= "active_members_count-#{year}-#{month}" %>">
<%= activities[:active_members_count] %>
</td>
<td class="left-lined <%= "new_members_count-#{year}-#{month}" %>">
<%= activities[:new_members_count] %>
</td>
<td class="left-lined <%= "pending_members_count-#{year}-#{month}" %>">
<%= activities[:pending_members_count] %>
</td>
<td class="left-lined <%= "appointments_count-#{year}-#{month}" %>">
<%= activities[:appointments_count] %>
</td>
<td class="left-lined <%= "completed_appointments_count-#{year}-#{month}" %>">
<%= activities[:completed_appointments_count] %>
</td>
</tr>
<% end %>
<tfoot>
<tr>
<td class="total">Total</td>
<td class="left-lined <%= "loans_count-#{year}" %>">
<%= activities_by_month.map(&:second).sum { |a| a[:loans_count] } %>
</td>
<td class="left-lined <%= "renewals_count-#{year}" %>">
<%= activities_by_month.map(&:second).sum { |a| a[:renewals_count] } %>
</td>
<td class="left-lined <%= "active_members_count-#{year}" %>">
<%= activities_by_month.map(&:second).sum { |a| a[:active_members_count] } %>
</td>
<td class="left-lined <%= "new_members_count-#{year}" %>">
<%= activities_by_month.map(&:second).sum { |a| a[:new_members_count] } %>
</td>
<td class="left-lined <%= "pending_members_count-#{year}" %>">
<%= activities_by_month.map(&:second).sum { |a| a[:pending_members_count] } %>
</td>
<td class="left-lined <%= "appointments_count-#{year}" %>">
<%= activities_by_month.map(&:second).sum { |a| a[:appointments_count] } %>
</td>
<td class="left-lined <%= "completed_appointments_count-#{year}" %>">
<%= activities_by_month.map(&:second).sum { |a| a[:completed_appointments_count] } %>
</td>
</tr>
</tfoot>
</table>
<br>
<br>
</div>
<% end %>
5 changes: 5 additions & 0 deletions db/migrate/20250105181935_create_monthly_renewals.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class CreateMonthlyRenewals < ActiveRecord::Migration[7.2]
def change
create_view :monthly_renewals
end
end
20 changes: 19 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.2].define(version: 2024_12_18_224853) do
ActiveRecord::Schema[7.2].define(version: 2025_01_05_181935) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

Expand Down Expand Up @@ -1145,4 +1145,22 @@
GROUP BY months.month
ORDER BY months.month;
SQL
create_view "monthly_renewals", sql_definition: <<-SQL
WITH dates AS (
SELECT min(date_trunc('month'::text, loans.created_at)) AS startm,
max(date_trunc('month'::text, loans.created_at)) AS endm
FROM loans
), months AS (
SELECT generate_series(dates.startm, dates.endm, 'P1M'::interval) AS month
FROM dates
)
SELECT (EXTRACT(year FROM months.month))::integer AS year,
(EXTRACT(month FROM months.month))::integer AS month,
count(DISTINCT l.id) AS renewals_count
FROM (months
LEFT JOIN loans l ON ((date_trunc('month'::text, l.created_at) = months.month)))
WHERE (l.initial_loan_id IS NOT NULL)
GROUP BY months.month
ORDER BY months.month;
SQL
end
15 changes: 15 additions & 0 deletions db/views/monthly_renewals_v01.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
WITH dates AS
(SELECT min(date_trunc('month', created_at)) AS startm,
max(date_trunc('month', created_at)) AS endm
FROM loans),
months AS
(SELECT generate_series(startm, endm, '1 month') AS month
FROM dates)
SELECT extract(YEAR FROM months.month) ::integer AS year,
extract(MONTH FROM months.month)::integer AS month,
count(DISTINCT l.id) AS renewals_count
FROM months
LEFT JOIN loans l ON date_trunc('month', l.created_at) = months.month
WHERE l.initial_loan_id IS NOT NULL
GROUP BY months.month
ORDER BY months.month;
Loading
Loading