From a9ccc54d14ba743a2aeda84b65f21cc20bf316b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 04:56:32 +0000 Subject: [PATCH 01/18] Bump bullet from 7.1.3 to 7.1.4 Bumps [bullet](https://github.com/flyerhzm/bullet) from 7.1.3 to 7.1.4. - [Changelog](https://github.com/flyerhzm/bullet/blob/main/CHANGELOG.md) - [Commits](https://github.com/flyerhzm/bullet/compare/7.1.3...7.1.4) --- updated-dependencies: - dependency-name: bullet dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index eef0ca9edd..e065f8eb6b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -101,7 +101,7 @@ GEM bugsnag (6.26.0) concurrent-ruby (~> 1.0) builder (3.2.4) - bullet (7.1.3) + bullet (7.1.4) activesupport (>= 3.0.0) uniform_notifier (~> 1.11) capybara (3.39.2) From 233e902ab5a9092834ad44a716446f0301c52ca1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Nov 2023 18:27:37 +0000 Subject: [PATCH 02/18] Bump nokogiri from 1.15.4 to 1.15.5 Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.15.4 to 1.15.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.15.4...v1.15.5) --- updated-dependencies: - dependency-name: nokogiri dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1d8ed8b125..3586074e01 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -359,11 +359,11 @@ GEM newrelic_rpm (9.6.0) base64 nio4r (2.5.9) - nokogiri (1.15.4-arm64-darwin) + nokogiri (1.15.5-arm64-darwin) racc (~> 1.4) - nokogiri (1.15.4-x86_64-darwin) + nokogiri (1.15.5-x86_64-darwin) racc (~> 1.4) - nokogiri (1.15.4-x86_64-linux) + nokogiri (1.15.5-x86_64-linux) racc (~> 1.4) notiffany (0.1.3) nenv (~> 0.1) From 043d2dec47bcf3df22b30b3bc9759f4bbbe234e7 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Sat, 25 Nov 2023 18:23:24 -0500 Subject: [PATCH 03/18] Allow for partial audits (don't blow away existing inventory) --- app/events/event_types/inventory.rb | 13 +++++++++++++ app/events/inventory_aggregate.rb | 14 ++++++++++++-- spec/events/inventory_aggregate_spec.rb | 1 + 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/app/events/event_types/inventory.rb b/app/events/event_types/inventory.rb index 5c3da47279..60cd032e04 100644 --- a/app/events/event_types/inventory.rb +++ b/app/events/event_types/inventory.rb @@ -16,6 +16,19 @@ def self.from(organization_id) storage_locations: org.storage_locations.map { |s| [s.id, EventTypes::EventStorageLocation.from(s)] }.to_h) end + # @param item_id [Integer] + # @param quantity [Integer] + # @param location [Integer] + def set_item_quantity(item_id:, quantity:, location:) + storage_locations[location] ||= EventTypes::EventStorageLocation.new(id: location, items: {}) + storage_locations[location].set_inventory(item_id, quantity) + end + + # @param item_id [Integer] + # @param quantity [Integer] + # @param from_location [Integer] + # @param to_location [Integer] + # @param validate [Boolean] def move_item(item_id:, quantity:, from_location: nil, to_location: nil, validate: true) if from_location if storage_locations[from_location].nil? && validate diff --git a/app/events/inventory_aggregate.rb b/app/events/inventory_aggregate.rb index dada21f0f8..cf1c0ebd65 100644 --- a/app/events/inventory_aggregate.rb +++ b/app/events/inventory_aggregate.rb @@ -43,6 +43,17 @@ def handle_inventory_event(payload, inventory, validate: true) validate: validate) end end + + # @param payload [EventTypes::InventoryPayload] + # @param inventory [EventTypes::Inventory] + # @param validate [Boolean] + def handle_audit_event(payload, inventory) + payload.items.each do |line_item| + inventory.set_item_quantity(item_id: line_item.item_id, + quantity: line_item.quantity, + location: line_item.to_storage_location) + end + end end on DonationEvent, DistributionEvent, AdjustmentEvent, PurchaseEvent, @@ -53,8 +64,7 @@ def handle_inventory_event(payload, inventory, validate: true) end on AuditEvent do |event, inventory| - inventory.storage_locations[event.data.storage_location_id].reset! - handle_inventory_event(event.data, inventory, validate: false) + handle_audit_event(event.data, inventory) end on SnapshotEvent do |event, inventory| diff --git a/spec/events/inventory_aggregate_spec.rb b/spec/events/inventory_aggregate_spec.rb index cd9c066f62..8899b17d85 100644 --- a/spec/events/inventory_aggregate_spec.rb +++ b/spec/events/inventory_aggregate_spec.rb @@ -336,6 +336,7 @@ id: storage_location1.id, items: { item1.id => EventTypes::EventItem.new(item_id: item1.id, quantity: 20), + item2.id => EventTypes::EventItem.new(item_id: item2.id, quantity: 10), item3.id => EventTypes::EventItem.new(item_id: item3.id, quantity: 10) } ), From dd78b91009b5e286c839cec93944164072324c11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Nov 2023 04:04:42 +0000 Subject: [PATCH 04/18] Bump terser from 1.1.19 to 1.1.20 Bumps [terser](https://github.com/ahorek/terser-ruby) from 1.1.19 to 1.1.20. - [Release notes](https://github.com/ahorek/terser-ruby/releases) - [Changelog](https://github.com/ahorek/terser-ruby/blob/master/CHANGELOG.md) - [Commits](https://github.com/ahorek/terser-ruby/compare/1.1.19...1.1.20) --- updated-dependencies: - dependency-name: terser dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1d8ed8b125..fcd6b847bd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -609,7 +609,7 @@ GEM railties (>= 6.0.0) strong_migrations (1.6.4) activerecord (>= 5.2) - terser (1.1.19) + terser (1.1.20) execjs (>= 0.3.0, < 3) thor (1.3.0) tilt (2.2.0) From 4f2704e2cc865f6d2f8a3872e504b9480ed2e112 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 05:00:10 +0000 Subject: [PATCH 05/18] Bump knapsack_pro from 5.7.0 to 6.0.0 Bumps [knapsack_pro](https://github.com/KnapsackPro/knapsack_pro-ruby) from 5.7.0 to 6.0.0. - [Changelog](https://github.com/KnapsackPro/knapsack_pro-ruby/blob/master/CHANGELOG.md) - [Commits](https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v5.7.0...v6.0.0) --- updated-dependencies: - dependency-name: knapsack_pro dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index fcd6b847bd..32ec03bdd2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -290,7 +290,7 @@ GEM activerecord kaminari-core (= 1.2.2) kaminari-core (1.2.2) - knapsack_pro (5.7.0) + knapsack_pro (6.0.0) rake language_server-protocol (3.17.0.3) launchy (2.5.2) From 8c98bbdbbed73efc56a15a5ddf45d3c44a562e41 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 1 Dec 2023 15:11:17 -0500 Subject: [PATCH 06/18] Fix event timing --- app/events/adjustment_event.rb | 2 +- app/events/audit_event.rb | 2 +- app/events/distribution_event.rb | 2 +- app/events/donation_event.rb | 2 +- app/events/inventory_aggregate.rb | 16 ++++++++++++---- app/events/purchase_event.rb | 2 +- app/events/transfer_event.rb | 2 +- db/migrate/20231201194409_fix_event_times.rb | 9 +++++++++ db/schema.rb | 2 +- 9 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 db/migrate/20231201194409_fix_event_times.rb diff --git a/app/events/adjustment_event.rb b/app/events/adjustment_event.rb index a472e5f744..e0f1978c57 100644 --- a/app/events/adjustment_event.rb +++ b/app/events/adjustment_event.rb @@ -4,7 +4,7 @@ def self.publish(adjustment) create( eventable: adjustment, organization_id: adjustment.organization_id, - event_time: Time.zone.now, + event_time: adjustment.created_at, data: EventTypes::InventoryPayload.new( items: EventTypes::EventLineItem.from_line_items(adjustment.line_items, to: adjustment.storage_location_id) ) diff --git a/app/events/audit_event.rb b/app/events/audit_event.rb index 247400ae94..c4ed421e8e 100644 --- a/app/events/audit_event.rb +++ b/app/events/audit_event.rb @@ -6,7 +6,7 @@ def self.publish(audit) create( eventable: audit, organization_id: audit.organization_id, - event_time: Time.zone.now, + event_time: audit.updated_at, data: EventTypes::AuditPayload.new( storage_location_id: audit.storage_location_id, items: EventTypes::EventLineItem.from_line_items(audit.line_items, to: audit.storage_location_id) diff --git a/app/events/distribution_event.rb b/app/events/distribution_event.rb index 6efc7f6984..11a256172a 100644 --- a/app/events/distribution_event.rb +++ b/app/events/distribution_event.rb @@ -4,7 +4,7 @@ def self.publish(distribution) create( eventable: distribution, organization_id: distribution.organization_id, - event_time: Time.zone.now, + event_time: distribution.created_at, data: EventTypes::InventoryPayload.new( items: EventTypes::EventLineItem.from_line_items(distribution.line_items, from: distribution.storage_location_id) ) diff --git a/app/events/donation_event.rb b/app/events/donation_event.rb index 83f5207d76..adf923c461 100644 --- a/app/events/donation_event.rb +++ b/app/events/donation_event.rb @@ -4,7 +4,7 @@ def self.publish(donation) create( eventable: donation, organization_id: donation.organization_id, - event_time: Time.zone.now, + event_time: donation.created_at, data: EventTypes::InventoryPayload.new( items: EventTypes::EventLineItem.from_line_items(donation.line_items, to: donation.storage_location_id) ) diff --git a/app/events/inventory_aggregate.rb b/app/events/inventory_aggregate.rb index cf1c0ebd65..3fcbe3a5a5 100644 --- a/app/events/inventory_aggregate.rb +++ b/app/events/inventory_aggregate.rb @@ -8,14 +8,22 @@ def on(*event_types, &block) end end - # @param organization_id + # @param organization_id [Integer] + # @param first_event [Integer] + # @param last_event [Integer] # @return [EventTypes::Inventory] - def inventory_for(organization_id) + def inventory_for(organization_id, first_event: nil, last_event: nil) events = Event.for_organization(organization_id) + if first_event + events = events.where('id >= ?', first_event) + end + if last_event + events = events.where('id <= ?', last_event) + end inventory = EventTypes::Inventory.from(organization_id) events.group_by { |e| [e.eventable_type, e.eventable_id] }.each do |_, event_batch| - last_event = event_batch.max_by(&:event_time) - handle(last_event, inventory) + last_grouped_event = event_batch.max_by(&:updated_at) + handle(last_grouped_event, inventory) end inventory end diff --git a/app/events/purchase_event.rb b/app/events/purchase_event.rb index 910c295916..ac00a67003 100644 --- a/app/events/purchase_event.rb +++ b/app/events/purchase_event.rb @@ -4,7 +4,7 @@ def self.publish(purchase) create( eventable: purchase, organization_id: purchase.organization_id, - event_time: Time.zone.now, + event_time: purchase.created_at, data: EventTypes::InventoryPayload.new( items: EventTypes::EventLineItem.from_line_items(purchase.line_items, to: purchase.storage_location_id) ) diff --git a/app/events/transfer_event.rb b/app/events/transfer_event.rb index e0343a4028..f8cf4f9624 100644 --- a/app/events/transfer_event.rb +++ b/app/events/transfer_event.rb @@ -4,7 +4,7 @@ def self.publish(transfer) create( eventable: transfer, organization_id: transfer.organization_id, - event_time: Time.zone.now, + event_time: transfer.created_at, data: EventTypes::InventoryPayload.new( items: EventTypes::EventLineItem.from_line_items(transfer.line_items, from: transfer.from.id, diff --git a/db/migrate/20231201194409_fix_event_times.rb b/db/migrate/20231201194409_fix_event_times.rb new file mode 100644 index 0000000000..f6ec957a82 --- /dev/null +++ b/db/migrate/20231201194409_fix_event_times.rb @@ -0,0 +1,9 @@ +class FixEventTimes < ActiveRecord::Migration[7.0] + def change + Event.where(type: %i(DistributionEvent DonationEvent PurchaseEvent)).find_each do |event| + next if event.eventable.nil? + + event.update_attribute(:event_time, event.eventable.created_at) + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 6fa13acbfc..54906d1330 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.0].define(version: 2023_11_17_141301) do +ActiveRecord::Schema[7.0].define(version: 2023_12_01_194409) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" From 4e49c729273a290435d65071374403c9fc8178ed Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 1 Dec 2023 15:14:25 -0500 Subject: [PATCH 07/18] lint fixes --- app/events/inventory_aggregate.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/events/inventory_aggregate.rb b/app/events/inventory_aggregate.rb index 3fcbe3a5a5..2ed837cb2e 100644 --- a/app/events/inventory_aggregate.rb +++ b/app/events/inventory_aggregate.rb @@ -15,10 +15,10 @@ def on(*event_types, &block) def inventory_for(organization_id, first_event: nil, last_event: nil) events = Event.for_organization(organization_id) if first_event - events = events.where('id >= ?', first_event) + events = events.where("id >= ?", first_event) end if last_event - events = events.where('id <= ?', last_event) + events = events.where("id <= ?", last_event) end inventory = EventTypes::Inventory.from(organization_id) events.group_by { |e| [e.eventable_type, e.eventable_id] }.each do |_, event_batch| From c191ddc0bf908fbb29f484388884796dc634eb3c Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Sat, 2 Dec 2023 20:47:25 -0500 Subject: [PATCH 08/18] Add specs --- app/events/inventory_aggregate.rb | 19 ++-- spec/events/inventory_aggregate_spec.rb | 132 ++++++++++++++++-------- 2 files changed, 97 insertions(+), 54 deletions(-) diff --git a/app/events/inventory_aggregate.rb b/app/events/inventory_aggregate.rb index 2ed837cb2e..e1bdb995ae 100644 --- a/app/events/inventory_aggregate.rb +++ b/app/events/inventory_aggregate.rb @@ -11,8 +11,9 @@ def on(*event_types, &block) # @param organization_id [Integer] # @param first_event [Integer] # @param last_event [Integer] + # @param validate [Boolean] # @return [EventTypes::Inventory] - def inventory_for(organization_id, first_event: nil, last_event: nil) + def inventory_for(organization_id, first_event: nil, last_event: nil, validate: false) events = Event.for_organization(organization_id) if first_event events = events.where("id >= ?", first_event) @@ -23,20 +24,21 @@ def inventory_for(organization_id, first_event: nil, last_event: nil) inventory = EventTypes::Inventory.from(organization_id) events.group_by { |e| [e.eventable_type, e.eventable_id] }.each do |_, event_batch| last_grouped_event = event_batch.max_by(&:updated_at) - handle(last_grouped_event, inventory) + handle(last_grouped_event, inventory, validate: validate) end inventory end # @param event [Event] # @param inventory [Inventory] - def handle(event, inventory) + # @param validate [Boolean] + def handle(event, inventory, validate: false) handler = @handlers[event.class] if handler.nil? Rails.logger.warn("No handler found for #{event.class}, skipping") return end - handler.call(event, inventory) + handler.call(event, inventory, validate: validate) end # @param payload [EventTypes::InventoryPayload] @@ -54,7 +56,6 @@ def handle_inventory_event(payload, inventory, validate: true) # @param payload [EventTypes::InventoryPayload] # @param inventory [EventTypes::Inventory] - # @param validate [Boolean] def handle_audit_event(payload, inventory) payload.items.each do |line_item| inventory.set_item_quantity(item_id: line_item.item_id, @@ -67,15 +68,15 @@ def handle_audit_event(payload, inventory) on DonationEvent, DistributionEvent, AdjustmentEvent, PurchaseEvent, TransferEvent, DistributionDestroyEvent, DonationDestroyEvent, PurchaseDestroyEvent, TransferDestroyEvent, - KitAllocateEvent, KitDeallocateEvent do |event, inventory| - handle_inventory_event(event.data, inventory, validate: false) + KitAllocateEvent, KitDeallocateEvent do |event, inventory, validate: false| + handle_inventory_event(event.data, inventory, validate: validate) end - on AuditEvent do |event, inventory| + on AuditEvent do |event, inventory, validate: false| handle_audit_event(event.data, inventory) end - on SnapshotEvent do |event, inventory| + on SnapshotEvent do |event, inventory, validate: false| inventory.storage_locations.clear inventory.storage_locations.merge!(event.data.storage_locations) end diff --git a/spec/events/inventory_aggregate_spec.rb b/spec/events/inventory_aggregate_spec.rb index 8899b17d85..d15a99217b 100644 --- a/spec/events/inventory_aggregate_spec.rb +++ b/spec/events/inventory_aggregate_spec.rb @@ -447,50 +447,92 @@ end end - it "should process multiple events" do - donation = FactoryBot.create(:donation, organization: organization, storage_location: storage_location1) - donation.line_items << build(:line_item, quantity: 50, item: item1) - donation.line_items << build(:line_item, quantity: 30, item: item2) - DonationEvent.publish(donation) - - donation2 = FactoryBot.create(:donation, organization: organization, storage_location: storage_location1) - donation2.line_items << build(:line_item, quantity: 30, item: item1) - DonationEvent.publish(donation2) - - donation3 = FactoryBot.create(:donation, organization: organization, storage_location: storage_location2) - donation3.line_items << build(:line_item, quantity: 50, item: item2) - DonationEvent.publish(donation3) - - # correction event - donation3.line_items = [build(:line_item, quantity: 40, item: item2)] - DonationEvent.publish(donation3) - - dist = FactoryBot.create(:distribution, organization: organization, storage_location: storage_location1) - dist.line_items << build(:line_item, quantity: 10, item: item1) - DistributionEvent.publish(dist) - - dist2 = FactoryBot.create(:distribution, organization: organization, storage_location: storage_location2) - dist2.line_items << build(:line_item, quantity: 15, item: item2) - DistributionEvent.publish(dist2) - - inventory = described_class.inventory_for(organization.id) - expect(inventory).to eq(EventTypes::Inventory.new( - organization_id: organization.id, - storage_locations: { - storage_location1.id => EventTypes::EventStorageLocation.new( - id: storage_location1.id, - items: { - item1.id => EventTypes::EventItem.new(item_id: item1.id, quantity: 70), - item2.id => EventTypes::EventItem.new(item_id: item2.id, quantity: 30) - } - ), - storage_location2.id => EventTypes::EventStorageLocation.new( - id: storage_location2.id, - items: { - item2.id => EventTypes::EventItem.new(item_id: item2.id, quantity: 25) - } - ) - } - )) + describe "multiple events" do + it "should process multiple events" do + donation = FactoryBot.create(:donation, organization: organization, storage_location: storage_location1) + donation.line_items << build(:line_item, quantity: 50, item: item1) + donation.line_items << build(:line_item, quantity: 30, item: item2) + DonationEvent.publish(donation) + + donation2 = FactoryBot.create(:donation, organization: organization, storage_location: storage_location1) + donation2.line_items << build(:line_item, quantity: 30, item: item1) + DonationEvent.publish(donation2) + + donation3 = FactoryBot.create(:donation, organization: organization, storage_location: storage_location2) + donation3.line_items << build(:line_item, quantity: 50, item: item2) + DonationEvent.publish(donation3) + + # correction event + donation3.line_items = [build(:line_item, quantity: 40, item: item2)] + DonationEvent.publish(donation3) + + dist = FactoryBot.create(:distribution, organization: organization, storage_location: storage_location1) + dist.line_items << build(:line_item, quantity: 10, item: item1) + DistributionEvent.publish(dist) + + dist2 = FactoryBot.create(:distribution, organization: organization, storage_location: storage_location2) + dist2.line_items << build(:line_item, quantity: 15, item: item2) + DistributionEvent.publish(dist2) + + inventory = described_class.inventory_for(organization.id) + expect(inventory).to eq(EventTypes::Inventory.new( + organization_id: organization.id, + storage_locations: { + storage_location1.id => EventTypes::EventStorageLocation.new( + id: storage_location1.id, + items: { + item1.id => EventTypes::EventItem.new(item_id: item1.id, quantity: 70), + item2.id => EventTypes::EventItem.new(item_id: item2.id, quantity: 30) + } + ), + storage_location2.id => EventTypes::EventStorageLocation.new( + id: storage_location2.id, + items: { + item2.id => EventTypes::EventItem.new(item_id: item2.id, quantity: 25) + } + ) + } + )) + end + + it "should validate incorrect events" do + donation = FactoryBot.create(:donation, organization: organization, storage_location: storage_location1) + donation.line_items << build(:line_item, quantity: 10, item: item1) + DonationEvent.publish(donation) + + dist = FactoryBot.create(:distribution, organization: organization, storage_location: storage_location1) + dist.line_items << build(:line_item, quantity: 20, item: item1) + DistributionEvent.publish(dist) + + expect { described_class.inventory_for(organization.id, validate: true) } + .to raise_error("Could not reduce quantity by 20 for item #{item1.id} in storage location #{storage_location1.id} - current quantity is 10") + end + + it "should handle timing correctly" do + donation = FactoryBot.create(:donation, organization: organization, storage_location: storage_location1) + donation.line_items << build(:line_item, quantity: 30, item: item1) + DonationEvent.publish(donation) + + dist = FactoryBot.create(:distribution, organization: organization, storage_location: storage_location1) + dist.line_items << build(:line_item, quantity: 10, item: item1) + DistributionEvent.publish(dist) + + # correction event + donation.line_items[0].quantity = 20 + DonationEvent.publish(donation) + + inventory = described_class.inventory_for(organization.id) + expect(inventory).to eq(EventTypes::Inventory.new( + organization_id: organization.id, + storage_locations: { + storage_location1.id => EventTypes::EventStorageLocation.new( + id: storage_location1.id, + items: { + item1.id => EventTypes::EventItem.new(item_id: item1.id, quantity: 10) + } + ) + } + )) + end end end From db0f64f82235474c757e5c0695ee7d4ca3493dd5 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Sat, 2 Dec 2023 20:47:55 -0500 Subject: [PATCH 09/18] ensure validation --- spec/events/inventory_aggregate_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/events/inventory_aggregate_spec.rb b/spec/events/inventory_aggregate_spec.rb index d15a99217b..f310d1be94 100644 --- a/spec/events/inventory_aggregate_spec.rb +++ b/spec/events/inventory_aggregate_spec.rb @@ -521,7 +521,7 @@ donation.line_items[0].quantity = 20 DonationEvent.publish(donation) - inventory = described_class.inventory_for(organization.id) + inventory = described_class.inventory_for(organization.id, validate: true) expect(inventory).to eq(EventTypes::Inventory.new( organization_id: organization.id, storage_locations: { From da25380da9dcf756e2e3c06926ee8d82d8a59302 Mon Sep 17 00:00:00 2001 From: Krunal Date: Sat, 2 Dec 2023 22:34:20 -0500 Subject: [PATCH 10/18] addressing a bug where partners were not able to use their previous email address --- app/models/partner.rb | 13 ++++++++++++- spec/models/partner_spec.rb | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/app/models/partner.rb b/app/models/partner.rb index 23c8dec134..392ac9a388 100644 --- a/app/models/partner.rb +++ b/app/models/partner.rb @@ -235,6 +235,17 @@ def invite_new_partner end def should_invite_because_email_changed? - email_changed? and (invited? or awaiting_review? or recertification_required? or approved?) + email_changed? && + ( + invited? || + awaiting_review? || + recertification_required? || + approved? + ) && + !partner_user_with_same_email_exist? + end + + def partner_user_with_same_email_exist? + User.exists?(email: email) && User.find_by(email: email).has_role?(Role::PARTNER, self) end end diff --git a/spec/models/partner_spec.rb b/spec/models/partner_spec.rb index 5f7f97b4be..8a9ab494f4 100644 --- a/spec/models/partner_spec.rb +++ b/spec/models/partner_spec.rb @@ -218,6 +218,24 @@ end end + it "should not call the UserInviteService.invite when the partner is changing email to previously used email" do + previous_email = partner.email + partner.email = "randomtest@email.com" + partner.save! + partner.email = previous_email + partner.save! + expect(UserInviteService).not_to have_received(:invite).with( + email: previous_email, + roles: [Role::PARTNER], + resource: partner + ) + expect(UserInviteService).to have_received(:invite).with( + email: "randomtest@email.com", + roles: [Role::PARTNER], + resource: partner + ) + end + [:uninvited, :deactivated].each do |test_status| it "should not call the UserInviteService.invite when the partner has status #{test_status} and the email is changed" do partner.status = test_status From f8e837ad386d587bf591a8f0c73411e5911c251e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 04:32:07 +0000 Subject: [PATCH 11/18] Bump icalendar from 2.10.0 to 2.10.1 Bumps [icalendar](https://github.com/icalendar/icalendar) from 2.10.0 to 2.10.1. - [Changelog](https://github.com/icalendar/icalendar/blob/main/History.txt) - [Commits](https://github.com/icalendar/icalendar/compare/v2.10.0...v2.10.1) --- updated-dependencies: - dependency-name: icalendar dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7a0d6ff287..47de1b941c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -262,7 +262,7 @@ GEM multi_xml (>= 0.5.2) i18n (1.14.1) concurrent-ruby (~> 1.0) - icalendar (2.10.0) + icalendar (2.10.1) ice_cube (~> 0.16) ice_cube (0.16.4) ice_nine (0.11.2) From 3678572c5bd4b237e4e0d6e4f63d1ecb5d323d85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 04:23:17 +0000 Subject: [PATCH 12/18] Bump standard from 1.32.0 to 1.32.1 Bumps [standard](https://github.com/standardrb/standard) from 1.32.0 to 1.32.1. - [Release notes](https://github.com/standardrb/standard/releases) - [Changelog](https://github.com/standardrb/standard/blob/main/CHANGELOG.md) - [Commits](https://github.com/standardrb/standard/compare/v1.32.0...v1.32.1) --- updated-dependencies: - dependency-name: standard dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 47de1b941c..db123a1590 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -276,7 +276,7 @@ GEM jbuilder (2.11.5) actionview (>= 5.0.0) activesupport (>= 5.0.0) - json (2.6.3) + json (2.7.1) jwt (2.7.1) kaminari (1.2.2) activesupport (>= 4.1.0) @@ -486,7 +486,7 @@ GEM redis-client (>= 0.17.0) redis-client (0.18.0) connection_pool - regexp_parser (2.8.2) + regexp_parser (2.8.3) request_store (1.5.1) rack (>= 1.4) responders (3.1.1) @@ -593,7 +593,7 @@ GEM actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - standard (1.32.0) + standard (1.32.1) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.0) rubocop (~> 1.57.2) From 3ad098ae9bb4f539582a368a88bcbc29c640733d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 04:11:45 +0000 Subject: [PATCH 13/18] Bump brakeman from 6.0.1 to 6.1.0 Bumps [brakeman](https://github.com/presidentbeef/brakeman) from 6.0.1 to 6.1.0. - [Release notes](https://github.com/presidentbeef/brakeman/releases) - [Changelog](https://github.com/presidentbeef/brakeman/blob/main/CHANGES.md) - [Commits](https://github.com/presidentbeef/brakeman/compare/v6.0.1...v6.1.0) --- updated-dependencies: - dependency-name: brakeman dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index db123a1590..80e352941b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -96,7 +96,7 @@ GEM autoprefixer-rails (>= 9.1.0) popper_js (>= 2.11.6, < 3) sassc-rails (>= 2.0.0) - brakeman (6.0.1) + brakeman (6.1.0) brow (0.4.1) bugsnag (6.26.0) concurrent-ruby (~> 1.0) From 2965c6cfc03a8f649f873e51497d9dde533ea8c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 04:11:23 +0000 Subject: [PATCH 14/18] Bump selenium-webdriver from 4.15.0 to 4.16.0 Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 4.15.0 to 4.16.0. - [Release notes](https://github.com/SeleniumHQ/selenium/releases) - [Changelog](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES) - [Commits](https://github.com/SeleniumHQ/selenium/compare/selenium-4.15.0...selenium-4.16.0) --- updated-dependencies: - dependency-name: selenium-webdriver dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 2720484e1f..088e3a1064 100644 --- a/Gemfile +++ b/Gemfile @@ -202,7 +202,7 @@ group :test do # More concise test ("should") matchers gem 'shoulda-matchers', '~> 5.3' # Selenium webdriver automatic installation and update. - gem 'selenium-webdriver', '~> 4.10' + gem 'selenium-webdriver', '~> 4.16' # Mock HTTP requests and ensure they are not called during tests. gem "webmock", "~> 3.19" end diff --git a/Gemfile.lock b/Gemfile.lock index 80e352941b..81221ae6a7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -561,7 +561,7 @@ GEM sprockets (> 3.0) sprockets-rails tilt - selenium-webdriver (4.15.0) + selenium-webdriver (4.16.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) @@ -728,7 +728,7 @@ DEPENDENCIES rubocop-rails (~> 2.22.2) rufus-scheduler sass-rails - selenium-webdriver (~> 4.10) + selenium-webdriver (~> 4.16) shoulda-matchers (~> 5.3) simple_form simplecov From 60cb20bcca8d9eb76db8316434701fdc01dc0ead Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Dec 2023 04:30:34 +0000 Subject: [PATCH 15/18] Bump knapsack_pro from 6.0.0 to 6.0.3 Bumps [knapsack_pro](https://github.com/KnapsackPro/knapsack_pro-ruby) from 6.0.0 to 6.0.3. - [Changelog](https://github.com/KnapsackPro/knapsack_pro-ruby/blob/master/CHANGELOG.md) - [Commits](https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v6.0.0...v6.0.3) --- updated-dependencies: - dependency-name: knapsack_pro dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 81221ae6a7..cb5a2320cc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -290,7 +290,7 @@ GEM activerecord kaminari-core (= 1.2.2) kaminari-core (1.2.2) - knapsack_pro (6.0.0) + knapsack_pro (6.0.3) rake language_server-protocol (3.17.0.3) launchy (2.5.2) From 8e7edcc6ef9d82fd34050fba0ea3a30d95b7a2ce Mon Sep 17 00:00:00 2001 From: cancelei Date: Thu, 7 Dec 2023 15:19:12 -0300 Subject: [PATCH 16/18] Add automated email message for password reset --- app/views/users/mailer/reset_password_instructions.html.erb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/views/users/mailer/reset_password_instructions.html.erb b/app/views/users/mailer/reset_password_instructions.html.erb index f667dc12fe..ddbf976c7f 100644 --- a/app/views/users/mailer/reset_password_instructions.html.erb +++ b/app/views/users/mailer/reset_password_instructions.html.erb @@ -1,5 +1,7 @@

Hello <%= @resource.email %>!

+

This is an automated email from the human essentials application. Please contact your diaper bank directly with any request-related questions.

+

Someone has requested a link to change your password. You can do this through the link below.

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

From 1d40fc4adb00ff0a31a4d6f836d5a23d2a468f88 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Sun, 10 Dec 2023 10:07:08 -0500 Subject: [PATCH 17/18] Upgrade to Ruby 3.2 (#3950) * Upgrade to Ruby 3.2 * gemfile.lock --- .ruby-version | 2 +- Gemfile | 2 -- Gemfile.lock | 3 --- manifest.yml | 3 +++ 4 files changed, 4 insertions(+), 6 deletions(-) create mode 100644 manifest.yml diff --git a/.ruby-version b/.ruby-version index ef538c2810..be94e6f53d 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.1.2 +3.2.2 diff --git a/Gemfile b/Gemfile index 088e3a1064..3ff38e6a9d 100644 --- a/Gemfile +++ b/Gemfile @@ -5,8 +5,6 @@ git_source(:github) do |repo_name| "https://github.com/#{repo_name}.git" end -ruby "3.1.2" - ###### BASIC FRAMEWORKS ###### # User management and login workflow. diff --git a/Gemfile.lock b/Gemfile.lock index cb5a2320cc..8650af4284 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -741,8 +741,5 @@ DEPENDENCIES web-console webmock (~> 3.19) -RUBY VERSION - ruby 3.1.2p20 - BUNDLED WITH 2.4.22 diff --git a/manifest.yml b/manifest.yml new file mode 100644 index 0000000000..da5448e6e5 --- /dev/null +++ b/manifest.yml @@ -0,0 +1,3 @@ +rails: + configuration: + ruby_version: 3.2.2 From b6916570c272e93229fb0bfb372efb91e33b1ac0 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Sun, 10 Dec 2023 10:18:21 -0500 Subject: [PATCH 18/18] Move manifest file to correct location --- manifest.yml => .cloud66/manifest.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename manifest.yml => .cloud66/manifest.yml (100%) diff --git a/manifest.yml b/.cloud66/manifest.yml similarity index 100% rename from manifest.yml rename to .cloud66/manifest.yml