diff --git a/app/controllers/admin/reports/monthly_activities_controller.rb b/app/controllers/admin/reports/monthly_activities_controller.rb index 9fb4ea37a..cc593cd60 100644 --- a/app/controllers/admin/reports/monthly_activities_controller.rb +++ b/app/controllers/admin/reports/monthly_activities_controller.rb @@ -2,32 +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 - renewals = MonthlyRenewal.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]) - assign_monthlies(renewals, %i[renewals_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 diff --git a/app/views/admin/reports/monthly_activities/index.html.erb b/app/views/admin/reports/monthly_activities/index.html.erb index 83b81e43e..c26e56b7e 100644 --- a/app/views/admin/reports/monthly_activities/index.html.erb +++ b/app/views/admin/reports/monthly_activities/index.html.erb @@ -2,49 +2,83 @@ <%= index_header "Activity" %> <% end %> - - - - - - - - - - - - - - - - - - - - - <% @monthly_activities.each do |date, activities| %> - - <% year, month = date.split("-") %> - - - - - - - - - - <% end %> - - - - - - - - - - - - -
ActivityMembersAppointments
MonthLoansRenewalsMembersNewPendingScheduledCompleted
<%= Date::MONTHNAMES[month.to_i] %> <%= year %><%= activities[:loans_count] %><%= activities[:renewals_count] %><%= activities[:active_members_count] %><%= activities[:new_members_count] %><%= activities[:pending_members_count] %><%= activities[:appointments_count] %><%= activities[:completed_appointments_count] %>
Total<%= @monthly_activities.values.sum { |a| a[:loans_count] } %><%= @monthly_activities.values.sum { |a| a[:renewals_count] } %><%= @monthly_activities.values.sum { |a| a[:active_members_count] } %><%= @monthly_activities.values.sum { |a| a[:new_members_count] } %><%= @monthly_activities.values.sum { |a| a[:pending_members_count] } %><%= @monthly_activities.values.sum { |a| a[:appointments_count] } %><%= @monthly_activities.values.sum { |a| a[:completed_appointments_count] } %>
+<% @monthly_activities.each do |(year, activities_by_month)| %> +
+

<%= year -%>

+ + + + + + + + + + + + + + + + + + + + + <% activities_by_month.each do |month, activities| %> + + + + + + + + + + + <% end %> + + + + + + + + + + + + +
ActivityMembersAppointments
MonthLoansRenewalsMembersNewPendingScheduledCompleted
<%= Date::MONTHNAMES[month.to_i] %>"> + <%= activities[:loans_count] %> + "> + <%= activities[:renewals_count] %> + "> + <%= activities[:active_members_count] %> + "> + <%= activities[:new_members_count] %> + "> + <%= activities[:pending_members_count] %> + "> + <%= activities[:appointments_count] %> + "> + <%= activities[:completed_appointments_count] %> +
Total"> + <%= activities_by_month.map(&:second).sum { |a| a[:loans_count] } %> + "> + <%= activities_by_month.map(&:second).sum { |a| a[:renewals_count] } %> + "> + <%= activities_by_month.map(&:second).sum { |a| a[:active_members_count] } %> + "> + <%= activities_by_month.map(&:second).sum { |a| a[:new_members_count] } %> + "> + <%= activities_by_month.map(&:second).sum { |a| a[:pending_members_count] } %> + "> + <%= activities_by_month.map(&:second).sum { |a| a[:appointments_count] } %> + "> + <%= activities_by_month.map(&:second).sum { |a| a[:completed_appointments_count] } %> +
+
+
+
+<% end %> diff --git a/test/system/admin/reports/monthly_activities_test.rb b/test/system/admin/reports/monthly_activities_test.rb index 2837977c5..159a93020 100644 --- a/test/system/admin/reports/monthly_activities_test.rb +++ b/test/system/admin/reports/monthly_activities_test.rb @@ -38,100 +38,119 @@ class MonthlyActivitiesTest < ApplicationSystemTestCase sign_in_as_admin end + # Table for 2021 # ╔═══════════════╦══════════════════════════════════╦═════════════════════╦════════════════════════════╗ # ║ ║ Activity ║ Members ║ Appointments ║ # ├───────────────┼──────────────────────────────────┼─────────────────────┼────────────────────────────┤ # ║ Month ║ Loans ║ Renewals ║ Members ║ New ║ Pending ║ Scheduled ║ Completed ║ # ╠═══════════════╬═══════════╬═══════════╬══════════╬══════════╬══════════╬═══════════════╬════════════╣ - # ║ November 2021 ║ 0 ║ 0 ║ 0 ║ 1 ║ 0 ║ 0 ║ 0 ║ - # ║ December 2021 ║ 1 ║ 0 ║ 1 ║ 0 ║ 0 ║ 1 ║ 1 ║ - # ║ January 2022 ║ 3 ║ 1 ║ 1 ║ 2 ║ 1 ║ 2 ║ 1 ║ + # ║ November ║ 0 ║ 0 ║ 0 ║ 1 ║ 0 ║ 0 ║ 0 ║ + # ║ December ║ 1 ║ 0 ║ 1 ║ 0 ║ 0 ║ 1 ║ 1 ║ # ╠═══════════════╬═══════════╬═══════════╬══════════╬══════════╬══════════╬═══════════════╬════════════╣ - # ║ Total ║ 4 ║ 1 ║ 2 ║ 3 ║ 1 ║ 3 ║ 2 ║ + # ║ Total ║ 1 ║ 0 ║ 1 ║ 1 ║ 0 ║ 1 ║ 1 ║ + # ╚═══════════════╩═══════════╩═══════════╩══════════╩══════════╩══════════╩═══════════════╩════════════╝ + # Table for 2022 + # ╔═══════════════╦══════════════════════════════════╦═════════════════════╦════════════════════════════╗ + # ║ ║ Activity ║ Members ║ Appointments ║ + # ├───────────────┼──────────────────────────────────┼─────────────────────┼────────────────────────────┤ + # ║ Month ║ Loans ║ Renewals ║ Members ║ New ║ Pending ║ Scheduled ║ Completed ║ + # ╠═══════════════╬═══════════╬═══════════╬══════════╬══════════╬══════════╬═══════════════╬════════════╣ + # ║ January ║ 3 ║ 1 ║ 1 ║ 2 ║ 1 ║ 2 ║ 1 ║ + # ╠═══════════════╬═══════════╬═══════════╬══════════╬══════════╬══════════╬═══════════════╬════════════╣ + # ║ Total ║ 3 ║ 1 ║ 1 ║ 2 ║ 1 ║ 2 ║ 1 ║ # ╚═══════════════╩═══════════╩═══════════╩══════════╩══════════╩══════════╩═══════════════╩════════════╝ test "table is populated accordingly" do visit admin_reports_monthly_activities_url - assert_selector ".monthly-adjustments" - within(".monthly-adjustments") do - # ║ ║ Activity ║ Members ║ Appointments ║ - within("thead > tr:nth-child(1)") do - within("th:nth-child(2)") { assert_text("Activity") } - within("th:nth-child(3)") { assert_text("Members") } - within("th:nth-child(4)") { assert_text("Appointments") } - end + assert_selector "#year-2021" + assert_selector "#year-2022" + + # table headings + ["#year-2021", "#year-2022"].each do |selector| + within("#year-2021") do + within("thead > tr:nth-child(1)") do + within("th:nth-child(2)") { assert_text("Activity") } + within("th:nth-child(3)") { assert_text("Members") } + within("th:nth-child(4)") { assert_text("Appointments") } + end - # ║ Month ║ Loans ║ Renewals ║ Members ║ New ║ Pending ║ Scheduled ║ Completed ║ - within("thead > tr:nth-child(2)") do - within("th:nth-child(1)") { assert_text("Month") } + within("thead > tr:nth-child(2)") do + within("th:nth-child(1)") { assert_text("Month") } - within("th:nth-child(2)") { assert_text("Loans") } - within("th:nth-child(3)") { assert_text("Renewals") } - within("th:nth-child(4)") { assert_text("Members") } + within("th:nth-child(2)") { assert_text("Loans") } + within("th:nth-child(3)") { assert_text("Renewals") } + within("th:nth-child(4)") { assert_text("Members") } - within("th:nth-child(5)") { assert_text("New") } - within("th:nth-child(6)") { assert_text("Pending") } + within("th:nth-child(5)") { assert_text("New") } + within("th:nth-child(6)") { assert_text("Pending") } - within("th:nth-child(7)") { assert_text("Scheduled") } - within("th:nth-child(8)") { assert_text("Completed") } + within("th:nth-child(7)") { assert_text("Scheduled") } + within("th:nth-child(8)") { assert_text("Completed") } + end end + end - # ║ November 2021 ║ 0 ║ 0 ║ 0 ║ 1 ║ 0 ║ 0 ║ 0 ║ + within("#year-2021") do within("tbody > tr:nth-child(1)") do - within("td:nth-child(1)") { assert_text("November 2021") } - - within("td:nth-child(2)") { assert_text("0") } - within("td:nth-child(3)") { assert_text("0") } - within("td:nth-child(4)") { assert_text("0") } - - within("td:nth-child(5)") { assert_text("1") } - within("td:nth-child(6)") { assert_text("0") } - - within("td:nth-child(7)") { assert_text("0") } - within("td:nth-child(8)") { assert_text("0") } + within("td.month") { assert_text("November") } + + within("td.loans_count-2021-11") { assert_text("0") } + within("td.renewals_count-2021-11") { assert_text("0") } + within("td.active_members_count-2021-11") { assert_text("0") } + within("td.new_members_count-2021-11") { assert_text("1") } + within("td.pending_members_count-2021-11") { assert_text("0") } + within("td.appointments_count-2021-11") { assert_text("0") } + within("td.completed_appointments_count-2021-11") { assert_text("0") } end - # ║ December 2021 ║ 1 ║ 0 ║ 1 ║ 0 ║ 0 ║ 1 ║ 1 ║ within("tbody > tr:nth-child(2)") do - within("td:nth-child(1)") { assert_text("December 2021") } - - within("td:nth-child(2)") { assert_text("1") } - within("td:nth-child(3)") { assert_text("0") } - within("td:nth-child(4)") { assert_text("1") } - - within("td:nth-child(5)") { assert_text("0") } - within("td:nth-child(6)") { assert_text("0") } + within("td.month") { assert_text("December") } + + within("td.loans_count-2021-12") { assert_text("1") } + within("td.renewals_count-2021-12") { assert_text("0") } + within("td.active_members_count-2021-12") { assert_text("1") } + within("td.new_members_count-2021-12") { assert_text("0") } + within("td.pending_members_count-2021-12") { assert_text("0") } + within("td.appointments_count-2021-12") { assert_text("1") } + within("td.completed_appointments_count-2021-12") { assert_text("1") } + end - within("td:nth-child(7)") { assert_text("1") } - within("td:nth-child(8)") { assert_text("1") } + within("tfoot > tr") do + within("td.total") { assert_text("Total") } + + within("td.loans_count-2021") { assert_text("1") } + within("td.renewals_count-2021") { assert_text("0") } + within("td.active_members_count-2021") { assert_text("1") } + within("td.new_members_count-2021") { assert_text("1") } + within("td.pending_members_count-2021") { assert_text("0") } + within("td.appointments_count-2021") { assert_text("1") } + within("td.completed_appointments_count-2021") { assert_text("1") } end + end - # ║ January 2022 ║ 3 ║ 1 ║ 1 ║ 2 ║ 1 ║ 2 ║ 1 ║ - within("tbody > tr:nth-child(3)") do - within("td:nth-child(1)") { assert_text("January 2022") } - - within("td:nth-child(2)") { assert_text("3") } - within("td:nth-child(3)") { assert_text("1") } - within("td:nth-child(4)") { assert_text("1") } - within("td:nth-child(5)") { assert_text("2") } - within("td:nth-child(6)") { assert_text("1") } - within("td:nth-child(7)") { assert_text("2") } - within("td:nth-child(8)") { assert_text("1") } + within("#year-2022") do + within("tbody > tr:nth-child(1)") do + within("td.month") { assert_text("January") } + + within("td.loans_count-2022-1") { assert_text("3") } + within("td.renewals_count-2022-1") { assert_text("1") } + within("td.active_members_count-2022-1") { assert_text("1") } + within("td.new_members_count-2022-1") { assert_text("2") } + within("td.pending_members_count-2022-1") { assert_text("1") } + within("td.appointments_count-2022-1") { assert_text("2") } + within("td.completed_appointments_count-2022-1") { assert_text("1") } end - # ║ Total ║ 4 ║ 1 ║ 2 ║ 3 ║ 1 ║ 3 ║ 2 ║ within("tfoot > tr") do - within("td:nth-child(1)") { assert_text("Total") } - - within("td:nth-child(2)") { assert_text("4") } - within("td:nth-child(3)") { assert_text("1") } - within("td:nth-child(4)") { assert_text("2") } - - within("td:nth-child(5)") { assert_text("3") } - within("td:nth-child(6)") { assert_text("1") } - - within("td:nth-child(7)") { assert_text("3") } - within("td:nth-child(8)") { assert_text("2") } + within("td.total") { assert_text("Total") } + + within("td.loans_count-2022") { assert_text("3") } + within("td.renewals_count-2022") { assert_text("1") } + within("td.active_members_count-2022") { assert_text("1") } + within("td.new_members_count-2022") { assert_text("2") } + within("td.pending_members_count-2022") { assert_text("1") } + within("td.appointments_count-2022") { assert_text("2") } + within("td.completed_appointments_count-2022") { assert_text("1") } end end end