From 06c758960c612dcbefdb5b83041eaac4be4dba76 Mon Sep 17 00:00:00 2001 From: JP <85654561+jp524@users.noreply.github.com> Date: Sat, 9 Nov 2024 18:47:32 -0600 Subject: [PATCH 1/3] Modify HistoricalTrendService to return quantity of distributed/donated/purchased items over the past year --- app/services/historical_trend_service.rb | 39 +++++++++++++++--------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/app/services/historical_trend_service.rb b/app/services/historical_trend_service.rb index f8615a625b..c2865cd528 100644 --- a/app/services/historical_trend_service.rb +++ b/app/services/historical_trend_service.rb @@ -4,26 +4,35 @@ def initialize(organization_id, type) @type = type end + # Returns: [{:name=>"Adult Briefs (XXL)", :data=>[0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0], :visible=>false}] + # :data contains quantity from 11 months ago to current month def series - # Preload line_items with a single query to avoid N+1 queries. - items_with_line_items = @organization.items.active - .includes(:line_items) - .where(line_items: {itemizable_type: @type, created_at: 1.year.ago.beginning_of_month..Time.current}) - .order(:name) + type_symbol = @type.tableize.to_sym # :distributions, :donations, :purchases + records_for_type = @organization.send(type_symbol) + .includes(items: :line_items) + .where(issued_at: 1.year.ago.beginning_of_month..Time.current) - month_offset = [*1..12].rotate(Time.zone.today.month) - default_dates = (1..12).index_with { |i| 0 } + array_of_items = [] - items_with_line_items.each_with_object([]) do |item, array_of_items| - dates = default_dates.deep_dup + records_for_type.each do |record| + index = record.issued_at.month - Date.current.month - 1 - item.line_items.each do |line_item| - month = line_item.created_at.month - index = month_offset.index(month) + 1 - dates[index] = dates[index] + line_item.quantity - end + record.line_items.each do |line_item| + name = line_item.item.name + quantity = line_item.quantity + next if quantity.zero? - array_of_items << {name: item.name, data: dates.values, visible: false} unless dates.values.sum.zero? + if (existing_item = array_of_items.find { |item| item[:name] == name }) + quantity_per_month = existing_item[:data] + quantity_per_month[index] += quantity + else + quantity_per_month = Array.new(12, 0) + quantity_per_month[index] += quantity + array_of_items << {name:, data: quantity_per_month, visible: false} + end + end end + + array_of_items.sort_by { |item| item[:name] } end end From 28ded65f7adfdbb4d9a9a43dcfc56156a743c946 Mon Sep 17 00:00:00 2001 From: JP <85654561+jp524@users.noreply.github.com> Date: Sun, 10 Nov 2024 08:49:13 -0600 Subject: [PATCH 2/3] Modify HistoricalTrendService tests --- .../services/historical_trend_service_spec.rb | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/spec/services/historical_trend_service_spec.rb b/spec/services/historical_trend_service_spec.rb index 5b94b00fb4..99ce523206 100644 --- a/spec/services/historical_trend_service_spec.rb +++ b/spec/services/historical_trend_service_spec.rb @@ -4,22 +4,29 @@ let(:service) { described_class.new(organization.id, type) } describe "#series" do - let!(:item1) { create(:item, organization: organization, name: "Item 1") } - let!(:item2) { create(:item, organization: organization, name: "Item 2") } + let(:item1) { create(:item, organization: organization, name: "Item 1") } + let(:item2) { create(:item, organization: organization, name: "Item 2") } + let(:donation1) { create(:donation, organization:, issued_at: Date.current) } + let(:donation2) { create(:donation, organization:, issued_at: 2.months.ago) } let!(:line_items) do (0..11).map do |n| - create(:line_item, item: item1, itemizable_type: type, quantity: 10 * (n + 1), created_at: n.months.ago) + create(:line_item, item: item1, itemizable_type: type, itemizable_id: donation1.id, quantity: 10, created_at: n.months.ago) end end - let!(:line_item2) { create(:line_item, item: item2, itemizable_type: type, quantity: 60, created_at: 6.months.ago) } - let!(:line_item3) { create(:line_item, item: item2, itemizable_type: type, quantity: 30, created_at: 3.months.ago) } + let!(:line_item2) { create(:line_item, item: item2, itemizable_type: type, itemizable_id: donation2.id, quantity: 60, created_at: 6.months.ago) } + let!(:line_item3) { create(:line_item, item: item2, itemizable_type: type, itemizable_id: donation2.id, quantity: 30, created_at: 3.months.ago) } it "returns an array of items with their monthly data" do expected_result = [ - {name: "Item 1", data: [120, 110, 100, 90, 80, 70, 60, 50, 40, 30, 20, 10], visible: false}, - {name: "Item 2", data: [0, 0, 0, 0, 0, 60, 0, 0, 30, 0, 0, 0], visible: false} + {name: "Item 1", data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120], visible: false}, + {name: "Item 2", data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0], visible: false} ] expect(service.series).to eq(expected_result) end + + it "the last data point is the quantity for the current month" do + item1_quantities = service.series.first[:data] + expect(item1_quantities.last).to be(line_items.pluck(:quantity).sum) + end end end From 0ad8aeae5931c16bca40a67b3f6c05afbc7b145b Mon Sep 17 00:00:00 2001 From: JP <85654561+jp524@users.noreply.github.com> Date: Sun, 17 Nov 2024 07:35:08 -0600 Subject: [PATCH 3/3] Refactor HistoricalTrendService --- app/services/historical_trend_service.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/services/historical_trend_service.rb b/app/services/historical_trend_service.rb index c2865cd528..5f0560804c 100644 --- a/app/services/historical_trend_service.rb +++ b/app/services/historical_trend_service.rb @@ -22,7 +22,8 @@ def series quantity = line_item.quantity next if quantity.zero? - if (existing_item = array_of_items.find { |item| item[:name] == name }) + existing_item = array_of_items.find { |item| item[:name] == name } + if existing_item quantity_per_month = existing_item[:data] quantity_per_month[index] += quantity else