From 0ce573c0aad9a53f047b0fb3399fa5740c11d09a Mon Sep 17 00:00:00 2001 From: Michael Crismali Date: Sun, 5 Jan 2025 12:42:25 -0600 Subject: [PATCH 1/2] Added a column for renewals count to the activity report --- .../reports/monthly_activities_controller.rb | 2 + app/models/monthly_appointment.rb | 1 + app/models/monthly_loan.rb | 1 + app/models/monthly_member.rb | 1 + app/models/monthly_renewal.rb | 3 + .../reports/monthly_activities/index.html.erb | 3 + .../20250105181935_create_monthly_renewals.rb | 5 + db/schema.rb | 20 +++- db/views/monthly_renewals_v01.sql | 15 +++ .../admin/reports/monthly_activities_test.rb | 97 ++++++++++--------- 10 files changed, 99 insertions(+), 49 deletions(-) create mode 100644 app/models/monthly_renewal.rb create mode 100644 db/migrate/20250105181935_create_monthly_renewals.rb create mode 100644 db/views/monthly_renewals_v01.sql diff --git a/app/controllers/admin/reports/monthly_activities_controller.rb b/app/controllers/admin/reports/monthly_activities_controller.rb index 995a96260..9fb4ea37a 100644 --- a/app/controllers/admin/reports/monthly_activities_controller.rb +++ b/app/controllers/admin/reports/monthly_activities_controller.rb @@ -12,10 +12,12 @@ def fetch_monthly_activities appointments = MonthlyAppointment.all loans = MonthlyLoan.all members = MonthlyMember.all + renewals = 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]) @monthly_activities = @monthly_activities.sort.to_h end diff --git a/app/models/monthly_appointment.rb b/app/models/monthly_appointment.rb index 3aeefaae5..c31f06003 100644 --- a/app/models/monthly_appointment.rb +++ b/app/models/monthly_appointment.rb @@ -1,2 +1,3 @@ +# View from the Scenic gem class MonthlyAppointment < ApplicationRecord end diff --git a/app/models/monthly_loan.rb b/app/models/monthly_loan.rb index 5ee9094c5..3a912b508 100644 --- a/app/models/monthly_loan.rb +++ b/app/models/monthly_loan.rb @@ -1,2 +1,3 @@ +# View from the Scenic gem class MonthlyLoan < ApplicationRecord end diff --git a/app/models/monthly_member.rb b/app/models/monthly_member.rb index d8fa479b4..6a45fff2f 100644 --- a/app/models/monthly_member.rb +++ b/app/models/monthly_member.rb @@ -1,2 +1,3 @@ +# View from the Scenic gem class MonthlyMember < ApplicationRecord end diff --git a/app/models/monthly_renewal.rb b/app/models/monthly_renewal.rb new file mode 100644 index 000000000..5c42e863a --- /dev/null +++ b/app/models/monthly_renewal.rb @@ -0,0 +1,3 @@ +# View from the Scenic gem +class MonthlyRenewal < ApplicationRecord +end diff --git a/app/views/admin/reports/monthly_activities/index.html.erb b/app/views/admin/reports/monthly_activities/index.html.erb index bd51687d7..83b81e43e 100644 --- a/app/views/admin/reports/monthly_activities/index.html.erb +++ b/app/views/admin/reports/monthly_activities/index.html.erb @@ -13,6 +13,7 @@ Month Loans + Renewals Members New Pending @@ -26,6 +27,7 @@ <% year, month = date.split("-") %> <%= Date::MONTHNAMES[month.to_i] %> <%= year %> <%= activities[:loans_count] %> + <%= activities[:renewals_count] %> <%= activities[:active_members_count] %> <%= activities[:new_members_count] %> <%= activities[:pending_members_count] %> @@ -37,6 +39,7 @@ 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] } %> diff --git a/db/migrate/20250105181935_create_monthly_renewals.rb b/db/migrate/20250105181935_create_monthly_renewals.rb new file mode 100644 index 000000000..a154ba838 --- /dev/null +++ b/db/migrate/20250105181935_create_monthly_renewals.rb @@ -0,0 +1,5 @@ +class CreateMonthlyRenewals < ActiveRecord::Migration[7.2] + def change + create_view :monthly_renewals + end +end diff --git a/db/schema.rb b/db/schema.rb index 11c972c16..2de6e2d5c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -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" @@ -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 diff --git a/db/views/monthly_renewals_v01.sql b/db/views/monthly_renewals_v01.sql new file mode 100644 index 000000000..530c12d5c --- /dev/null +++ b/db/views/monthly_renewals_v01.sql @@ -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; diff --git a/test/system/admin/reports/monthly_activities_test.rb b/test/system/admin/reports/monthly_activities_test.rb index b373894f2..2837977c5 100644 --- a/test/system/admin/reports/monthly_activities_test.rb +++ b/test/system/admin/reports/monthly_activities_test.rb @@ -4,8 +4,8 @@ module Admin class MonthlyActivitiesTest < ApplicationSystemTestCase include AdminHelper - def setup - @date = Time.zone.parse("2022-1-1") + setup do + @date = Time.zone.parse("2022-1-15") travel_to @date # 2 new (verified) members this month and 1 pending @@ -16,9 +16,10 @@ def setup # 1 existing member from November last year november_member_1 = create(:verified_member_with_membership, created_at: Time.zone.parse("2021-11-1")) - # 2 loans for the same member this month, giving us 1 active member + # 3 loans (1 renewal) for the same member this month, giving us 1 active member january_loan_1 = create(:loan, member: january_member_1) - january_loan_2 = create(:loan, member: january_member_1) + january_loan_2 = create(:loan, member: january_member_1, due_at: 1.week.ago, ended_at: 1.week.ago, created_at: 8.days.ago) + january_loan_3 = create(:loan, initial_loan: january_loan_2, member: january_member_1, renewal_count: 1, item: january_loan_2.item) # 1 loan for an old member last month, giving us 1 active member december_loan_1 = create(:loan, member: november_member_1, created_at: Time.zone.parse("2021-12-10")) @@ -27,7 +28,7 @@ def setup create(:appointment, member: january_member_1, starts_at: Time.zone.parse("2022-1-5"), ends_at: Time.zone.parse("2022-1-6"), loans: [january_loan_1]) create(:appointment, member: january_member_1, starts_at: Time.zone.parse("2022-1-27"), - ends_at: Time.zone.parse("2022-1-28"), completed_at: Time.zone.parse("2022-1-28"), loans: [january_loan_2]) + ends_at: Time.zone.parse("2022-1-28"), completed_at: Time.zone.parse("2022-1-28"), loans: [january_loan_3]) # 1 appointment which started and was completed last month but ended this month, # giving us 1 for last month @@ -37,20 +38,17 @@ def setup sign_in_as_admin end - def teardown - end - - # ╔═══════════════╦══════════════════════╦═════════════════════╦════════════════════════════╗ - # ║ ║ Activity ║ Members ║ Appointments ║ - # ├───────────────┼──────────────────────┼─────────────────────┼────────────────────────────┤ - # ║ Month ║ Loans ║ Members ║ New ║ Pending ║ Scheduled ║ Completed ║ - # ╠═══════════════╬═══════════╬══════════╬══════════╬══════════╬═══════════════╬════════════╣ - # ║ November 2021 ║ 0 ║ 0 ║ 1 ║ 0 ║ 0 ║ 0 ║ - # ║ December 2021 ║ 1 ║ 1 ║ 0 ║ 0 ║ 1 ║ 1 ║ - # ║ January 2022 ║ 2 ║ 1 ║ 2 ║ 1 ║ 2 ║ 1 ║ - # ╠═══════════════╬═══════════╬══════════╬══════════╬══════════╬═══════════════╬════════════╣ - # ║ Total ║ 3 ║ 2 ║ 3 ║ 1 ║ 3 ║ 2 ║ - # ╚═══════════════╩═══════════╩══════════╩══════════╩══════════╩═══════════════╩════════════╝ + # ╔═══════════════╦══════════════════════════════════╦═════════════════════╦════════════════════════════╗ + # ║ ║ 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 ║ + # ╠═══════════════╬═══════════╬═══════════╬══════════╬══════════╬══════════╬═══════════════╬════════════╣ + # ║ Total ║ 4 ║ 1 ║ 2 ║ 3 ║ 1 ║ 3 ║ 2 ║ + # ╚═══════════════╩═══════════╩═══════════╩══════════╩══════════╩══════════╩═══════════════╩════════════╝ test "table is populated accordingly" do visit admin_reports_monthly_activities_url @@ -63,74 +61,77 @@ def teardown within("th:nth-child(4)") { assert_text("Appointments") } end - # ║ Month ║ Loans ║ Members ║ New ║ Pending ║ Scheduled ║ Completed ║ + # ║ Month ║ Loans ║ Renewals ║ Members ║ New ║ Pending ║ Scheduled ║ Completed ║ 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("Members") } + within("th:nth-child(3)") { assert_text("Renewals") } + within("th:nth-child(4)") { assert_text("Members") } - within("th:nth-child(4)") { assert_text("New") } - within("th:nth-child(5)") { assert_text("Pending") } + within("th:nth-child(5)") { assert_text("New") } + within("th:nth-child(6)") { assert_text("Pending") } - within("th:nth-child(6)") { assert_text("Scheduled") } - within("th:nth-child(7)") { assert_text("Completed") } + within("th:nth-child(7)") { assert_text("Scheduled") } + within("th:nth-child(8)") { assert_text("Completed") } end - # ║ November 2021 ║ 0 ║ 0 ║ 1 ║ 0 ║ 0 ║ 0 ║ + # ║ November 2021 ║ 0 ║ 0 ║ 0 ║ 1 ║ 0 ║ 0 ║ 0 ║ 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(4)") { assert_text("1") } - within("td:nth-child(5)") { 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") } end - # ║ December 2021 ║ 1 ║ 1 ║ 0 ║ 0 ║ 1 ║ 1 ║ + # ║ 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("1") } + within("td:nth-child(3)") { assert_text("0") } + within("td:nth-child(4)") { assert_text("1") } - within("td:nth-child(4)") { assert_text("0") } within("td:nth-child(5)") { assert_text("0") } + within("td:nth-child(6)") { assert_text("0") } - within("td:nth-child(6)") { assert_text("1") } within("td:nth-child(7)") { assert_text("1") } + within("td:nth-child(8)") { assert_text("1") } end - # ║ January 2022 ║ 2 ║ 1 ║ 2 ║ 1 ║ 2 ║ 1 ║ + # ║ 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("2") } + within("td:nth-child(2)") { assert_text("3") } within("td:nth-child(3)") { assert_text("1") } - - within("td:nth-child(4)") { assert_text("2") } - within("td:nth-child(5)") { assert_text("1") } - - within("td:nth-child(6)") { assert_text("2") } - within("td:nth-child(7)") { 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") } end - # ║ Total ║ 3 ║ 2 ║ 3 ║ 1 ║ 3 ║ 2 ║ + # ║ 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("3") } - within("td:nth-child(3)") { assert_text("2") } + 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(4)") { assert_text("3") } - within("td:nth-child(5)") { assert_text("1") } + within("td:nth-child(5)") { assert_text("3") } + within("td:nth-child(6)") { assert_text("1") } - within("td:nth-child(6)") { assert_text("3") } - within("td:nth-child(7)") { assert_text("2") } + within("td:nth-child(7)") { assert_text("3") } + within("td:nth-child(8)") { assert_text("2") } end end end From e65f5bfc6bc6213eb2f4d58acc23400f2fd26e87 Mon Sep 17 00:00:00 2001 From: Michael Crismali Date: Sun, 12 Jan 2025 18:05:20 -0600 Subject: [PATCH 2/2] Split the report into multiple tables --- .../reports/monthly_activities_controller.rb | 47 ++++-- .../reports/monthly_activities/index.html.erb | 126 ++++++++------ .../admin/reports/monthly_activities_test.rb | 155 ++++++++++-------- 3 files changed, 196 insertions(+), 132 deletions(-) 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