Browse Source

Update merge orgs task (#2003)

* Allow custom merge date in merge organisations service

* Allow optional merge date in merge orgs task

* Add a rake task for merging into a new organinsation
demo-branch
kosiakkatrina 1 year ago committed by GitHub
parent
commit
a5fdf42540
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      app/services/merge/merge_organisations_service.rb
  2. 33
      lib/tasks/merge_organisations.rake
  3. 67
      spec/lib/tasks/merge_organisations_spec.rb
  4. 186
      spec/services/merge/merge_organisations_service_spec.rb

15
app/services/merge/merge_organisations_service.rb

@ -1,7 +1,9 @@
class Merge::MergeOrganisationsService
def initialize(absorbing_organisation_id:, merging_organisation_ids:)
def initialize(absorbing_organisation_id:, merging_organisation_ids:, merge_date: Time.zone.today, absorbing_organisation_active_from_merge_date: false)
@absorbing_organisation = Organisation.find(absorbing_organisation_id)
@merging_organisations = Organisation.find(merging_organisation_ids)
@merge_date = merge_date || Time.zone.today
@absorbing_organisation_active_from_merge_date = absorbing_organisation_active_from_merge_date
end
def call
@ -18,6 +20,7 @@ class Merge::MergeOrganisationsService
merge_sales_logs(merging_organisation)
mark_organisation_as_merged(merging_organisation)
end
@absorbing_organisation.available_from = @merge_date if @absorbing_organisation_active_from_merge_date
@absorbing_organisation.save!
log_success_message
rescue ActiveRecord::RecordInvalid => e
@ -70,12 +73,12 @@ private
new_scheme.locations << Location.new(location.attributes.except("id", "scheme_id")) unless location.deactivated?
end
@merged_schemes[merging_organisation.name] << { name: new_scheme.service_name, code: new_scheme.id }
SchemeDeactivationPeriod.create!(scheme:, deactivation_date: Time.zone.now)
SchemeDeactivationPeriod.create!(scheme:, deactivation_date: @merge_date)
end
end
def merge_lettings_logs(merging_organisation)
merging_organisation.owned_lettings_logs.after_date(Time.zone.today).each do |lettings_log|
merging_organisation.owned_lettings_logs.after_date(@merge_date.to_time).each do |lettings_log|
if lettings_log.scheme.present?
scheme_to_set = @absorbing_organisation.owned_schemes.find_by(service_name: lettings_log.scheme.service_name)
location_to_set = scheme_to_set.locations.find_by(name: lettings_log.location&.name, postcode: lettings_log.location&.postcode)
@ -86,20 +89,20 @@ private
lettings_log.owning_organisation = @absorbing_organisation
lettings_log.save!
end
merging_organisation.managed_lettings_logs.after_date(Time.zone.today).each do |lettings_log|
merging_organisation.managed_lettings_logs.after_date(@merge_date.to_time).each do |lettings_log|
lettings_log.managing_organisation = @absorbing_organisation
lettings_log.save!
end
end
def merge_sales_logs(merging_organisation)
merging_organisation.sales_logs.after_date(Time.zone.today).each do |sales_log|
merging_organisation.sales_logs.after_date(@merge_date.to_time).each do |sales_log|
sales_log.update(owning_organisation: @absorbing_organisation)
end
end
def mark_organisation_as_merged(merging_organisation)
merging_organisation.update(merge_date: Time.zone.today, absorbing_organisation: @absorbing_organisation)
merging_organisation.update(merge_date: @merge_date, absorbing_organisation: @absorbing_organisation)
end
def log_success_message

33
lib/tasks/merge_organisations.rake

@ -1,12 +1,37 @@
namespace :merge do
desc "Merge organisations into one"
task :merge_organisations, %i[absorbing_organisation_id merging_organisation_ids] => :environment do |_task, args|
desc "Merge organisations into an existing organisation"
task :merge_organisations, %i[absorbing_organisation_id merging_organisation_ids merge_date] => :environment do |_task, args|
absorbing_organisation_id = args[:absorbing_organisation_id]
merging_organisation_ids = args[:merging_organisation_ids]&.split(" ")&.map(&:to_i)
begin
merge_date = args[:merge_date].present? ? Date.parse(args[:merge_date]) : nil
rescue StandardError
raise "Usage: rake merge:merge_organisations[absorbing_organisation_id, merging_organisation_ids, merge_date]. Merge date must be in format YYYY-MM-DD"
end
raise "Usage: rake merge:merge_organisations[absorbing_organisation_id, merging_organisation_ids]" if merging_organisation_ids.blank? || absorbing_organisation_id.blank?
if merging_organisation_ids.blank? || absorbing_organisation_id.blank?
raise "Usage: rake merge:merge_organisations[absorbing_organisation_id, merging_organisation_ids, merge_date]"
end
service = Merge::MergeOrganisationsService.new(absorbing_organisation_id:, merging_organisation_ids:)
service = Merge::MergeOrganisationsService.new(absorbing_organisation_id:, merging_organisation_ids:, merge_date:)
service.call
end
desc "Merge organisations into an existing organisation, make the absorbing organisation active from merge date only"
task :merge_organisations_into_new_organisation, %i[absorbing_organisation_id merging_organisation_ids merge_date] => :environment do |_task, args|
absorbing_organisation_id = args[:absorbing_organisation_id]
merging_organisation_ids = args[:merging_organisation_ids]&.split(" ")&.map(&:to_i)
begin
merge_date = args[:merge_date].present? ? Date.parse(args[:merge_date]) : nil
rescue StandardError
raise "Usage: rake merge:merge_organisations_into_new_organisation[absorbing_organisation_id, merging_organisation_ids, merge_date]. Merge date must be in format YYYY-MM-DD"
end
if merging_organisation_ids.blank? || absorbing_organisation_id.blank?
raise "Usage: rake merge:merge_organisations_into_new_organisation[absorbing_organisation_id, merging_organisation_ids, merge_date]"
end
service = Merge::MergeOrganisationsService.new(absorbing_organisation_id:, merging_organisation_ids:, merge_date:, absorbing_organisation_active_from_merge_date: true)
service.call
end
end

67
spec/lib/tasks/merge_organisations_spec.rb

@ -20,22 +20,79 @@ RSpec.describe "emails" do
context "when the rake task is run" do
it "raises an error when no parameters are given" do
expect { task.invoke(nil) }.to raise_error(RuntimeError, "Usage: rake merge:merge_organisations[absorbing_organisation_id, merging_organisation_ids]")
expect { task.invoke(nil) }.to raise_error(RuntimeError, "Usage: rake merge:merge_organisations[absorbing_organisation_id, merging_organisation_ids, merge_date]")
end
it "raises an error when only absorbing organisation is given" do
expect { task.invoke(1, nil) }.to raise_error(RuntimeError, "Usage: rake merge:merge_organisations[absorbing_organisation_id, merging_organisation_ids]")
expect { task.invoke(1, nil) }.to raise_error(RuntimeError, "Usage: rake merge:merge_organisations[absorbing_organisation_id, merging_organisation_ids, merge_date]")
end
it "raises an error when only merging organisations are given" do
expect { task.invoke(nil, "1 2") }.to raise_error(RuntimeError, "Usage: rake merge:merge_organisations[absorbing_organisation_id, merging_organisation_ids]")
expect { task.invoke(nil, "1 2") }.to raise_error(RuntimeError, "Usage: rake merge:merge_organisations[absorbing_organisation_id, merging_organisation_ids, merge_date]")
end
it "raises runs the service with correct organisation IDs" do
expect(Merge::MergeOrganisationsService).to receive(:new).with(absorbing_organisation_id: 1, merging_organisation_ids: [2, 3]).once
it "raises an error when the merge date given is not valid" do
expect { task.invoke("3", "1 2", "invalid_date") }.to raise_error(RuntimeError, "Usage: rake merge:merge_organisations[absorbing_organisation_id, merging_organisation_ids, merge_date]. Merge date must be in format YYYY-MM-DD")
end
it "runs the service with correct organisation IDs" do
expect(Merge::MergeOrganisationsService).to receive(:new).with(absorbing_organisation_id: 1, merging_organisation_ids: [2, 3], merge_date: nil).once
expect(merge_organisations_service).to receive(:call).once
task.invoke(1, "2 3")
end
it "runs the service with correct date when date is given" do
expect(Merge::MergeOrganisationsService).to receive(:new).with(absorbing_organisation_id: 1, merging_organisation_ids: [2, 3], merge_date: Time.zone.local(2021, 1, 13)).once
expect(merge_organisations_service).to receive(:call).once
task.invoke(1, "2 3", "2021-01-13")
end
end
end
describe ":merge_organisations_into_new_organisation", type: :task do
subject(:task) { Rake::Task["merge:merge_organisations_into_new_organisation"] }
let(:organisation) { create(:organisation) }
let(:merging_organisation) { create(:organisation) }
let(:merge_organisations_service) { Merge::MergeOrganisationsService.new(absorbing_organisation_id: organisation.id, merging_organisation_ids: [merging_organisation.id]) }
before do
allow(Merge::MergeOrganisationsService).to receive(:new).and_return(merge_organisations_service)
allow(merge_organisations_service).to receive(:call).and_return(nil)
Rake.application.rake_require("tasks/merge_organisations")
Rake::Task.define_task(:environment)
task.reenable
end
context "when the rake task is run" do
it "raises an error when no parameters are given" do
expect { task.invoke(nil) }.to raise_error(RuntimeError, "Usage: rake merge:merge_organisations_into_new_organisation[absorbing_organisation_id, merging_organisation_ids, merge_date]")
end
it "raises an error when only absorbing organisation is given" do
expect { task.invoke(1, nil) }.to raise_error(RuntimeError, "Usage: rake merge:merge_organisations_into_new_organisation[absorbing_organisation_id, merging_organisation_ids, merge_date]")
end
it "raises an error when only merging organisations are given" do
expect { task.invoke(nil, "1 2") }.to raise_error(RuntimeError, "Usage: rake merge:merge_organisations_into_new_organisation[absorbing_organisation_id, merging_organisation_ids, merge_date]")
end
it "raises an error when the merge date given is not valid" do
expect { task.invoke("3", "1 2", "invalid_date") }.to raise_error(RuntimeError, "Usage: rake merge:merge_organisations_into_new_organisation[absorbing_organisation_id, merging_organisation_ids, merge_date]. Merge date must be in format YYYY-MM-DD")
end
it "runs the service with correct organisation IDs" do
expect(Merge::MergeOrganisationsService).to receive(:new).with(absorbing_organisation_id: 1, merging_organisation_ids: [2, 3], merge_date: nil, absorbing_organisation_active_from_merge_date: true).once
expect(merge_organisations_service).to receive(:call).once
task.invoke(1, "2 3")
end
it "runs the service with correct date when date is given" do
expect(Merge::MergeOrganisationsService).to receive(:new).with(absorbing_organisation_id: 1, merging_organisation_ids: [2, 3], merge_date: Time.zone.local(2021, 1, 13), absorbing_organisation_active_from_merge_date: true).once
expect(merge_organisations_service).to receive(:call).once
task.invoke(1, "2 3", "2021-01-13")
end
end
end
end

186
spec/services/merge/merge_organisations_service_spec.rb

@ -1,7 +1,7 @@
require "rails_helper"
RSpec.describe Merge::MergeOrganisationsService do
subject(:merge_organisations_service) { described_class.new(absorbing_organisation_id: absorbing_organisation.id, merging_organisation_ids: [merging_organisation_ids]) }
subject(:merge_organisations_service) { described_class.new(absorbing_organisation_id: absorbing_organisation.id, merging_organisation_ids: [merging_organisation_ids], merge_date: nil) }
let(:absorbing_organisation) { create(:organisation, holds_own_stock: false) }
let(:absorbing_organisation_user) { create(:user, organisation: absorbing_organisation) }
@ -54,6 +54,13 @@ RSpec.describe Merge::MergeOrganisationsService do
expect(merging_organisation_user.organisation).to eq(merging_organisation)
end
it "does not set available_from for absorbing organisation" do
merge_organisations_service.call
absorbing_organisation.reload
expect(absorbing_organisation.available_from).to be_nil
end
context "and merging organisation rent periods" do
before do
OrganisationRentPeriod.create!(organisation: absorbing_organisation, rent_period: 1)
@ -215,6 +222,168 @@ RSpec.describe Merge::MergeOrganisationsService do
expect(sales_log.owning_organisation).to eq(merging_organisation)
end
end
context "and merge date is provided" do
subject(:merge_organisations_service) { described_class.new(absorbing_organisation_id: absorbing_organisation.id, merging_organisation_ids: [merging_organisation_ids], merge_date: Time.zone.yesterday) }
it "sets merge date on merged organisation" do
merge_organisations_service.call
merging_organisation.reload
expect(merging_organisation.merge_date.to_date).to eq(Time.zone.yesterday)
expect(merging_organisation.absorbing_organisation_id).to eq(absorbing_organisation.id)
end
context "and merging sales logs" do
let!(:sales_log) { create(:sales_log, saledate: Time.zone.today, owning_organisation: merging_organisation) }
before do
create(:sales_log, saledate: Time.zone.today - 2.days, owning_organisation: merging_organisation)
end
it "moves relevant logs" do
merge_organisations_service.call
absorbing_organisation.reload
expect(SalesLog.filter_by_owning_organisation(absorbing_organisation).count).to eq(1)
expect(SalesLog.filter_by_owning_organisation(absorbing_organisation).first).to eq(sales_log)
end
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with([merging_organisation_ids]).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
merge_organisations_service.call
absorbing_organisation.reload
expect(absorbing_organisation.sales_logs.count).to eq(0)
expect(sales_log.owning_organisation).to eq(merging_organisation)
end
end
context "and merging lettings logs" do
let(:owning_organisation) { create(:organisation, holds_own_stock: true) }
let!(:owned_lettings_log) { create(:lettings_log, startdate: Time.zone.today, owning_organisation: merging_organisation, created_by: merging_organisation_user) }
let!(:managed_lettings_log) { create(:lettings_log, startdate: Time.zone.today) }
before do
create(:organisation_relationship) { create(:organisation_relationship, parent_organisation: owning_organisation, child_organisation: merging_organisation) }
managed_lettings_log.update!(owning_organisation:, managing_organisation: merging_organisation, created_by: merging_organisation_user)
create(:lettings_log, startdate: Time.zone.today - 2.days, owning_organisation: merging_organisation, created_by: merging_organisation_user)
create(:lettings_log, startdate: Time.zone.today - 2.days, owning_organisation:, managing_organisation: merging_organisation, created_by: merging_organisation_user)
end
it "moves relevant logs" do
merge_organisations_service.call
absorbing_organisation.reload
expect(LettingsLog.filter_by_owning_organisation(absorbing_organisation).count).to eq(1)
expect(LettingsLog.filter_by_owning_organisation(absorbing_organisation).first).to eq(owned_lettings_log)
expect(LettingsLog.filter_by_managing_organisation(absorbing_organisation).count).to eq(2)
expect(LettingsLog.filter_by_managing_organisation(absorbing_organisation)).to include(managed_lettings_log)
expect(LettingsLog.filter_by_managing_organisation(absorbing_organisation)).to include(owned_lettings_log)
end
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with([merging_organisation_ids]).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
merge_organisations_service.call
absorbing_organisation.reload
expect(absorbing_organisation.lettings_logs.count).to eq(0)
expect(owned_lettings_log.owning_organisation).to eq(merging_organisation)
expect(managed_lettings_log.managing_organisation).to eq(merging_organisation)
end
end
context "and merging organisation schemes and locations" do
let!(:scheme) { create(:scheme, owning_organisation: merging_organisation) }
let!(:location) { create(:location, scheme:) }
let!(:deactivated_location) { create(:location, scheme:) }
let!(:deactivated_scheme) { create(:scheme, owning_organisation: merging_organisation) }
let!(:owned_lettings_log) { create(:lettings_log, :sh, scheme:, location:, startdate: Time.zone.tomorrow, owning_organisation: merging_organisation) }
let!(:owned_lettings_log_no_location) { create(:lettings_log, :sh, scheme:, startdate: Time.zone.tomorrow, owning_organisation: merging_organisation) }
before do
create(:location, scheme:, name: "fake location", postcode: "A1 1AA")
create(:location, scheme: deactivated_scheme)
create(:scheme_deactivation_period, scheme: deactivated_scheme, deactivation_date: Time.zone.today - 1.month)
create(:location_deactivation_period, location: deactivated_location, deactivation_date: Time.zone.today - 1.month)
create(:lettings_log, scheme:, location:, startdate: Time.zone.yesterday)
create(:lettings_log, startdate: Time.zone.tomorrow, managing_organisation: merging_organisation)
end
it "combines organisation schemes and locations" do
expect(Rails.logger).to receive(:info).with("Merged users from fake org:")
expect(Rails.logger).to receive(:info).with("\tDanny Rojas (#{merging_organisation.data_protection_officers.first.email})")
expect(Rails.logger).to receive(:info).with("\tfake name (fake@email.com)")
expect(Rails.logger).to receive(:info).with("New schemes from fake org:")
expect(Rails.logger).to receive(:info).with(/\t#{scheme.service_name} \(S/)
merge_organisations_service.call
absorbing_organisation.reload
expect(absorbing_organisation.owned_schemes.count).to eq(1)
expect(absorbing_organisation.owned_schemes.first.service_name).to eq(scheme.service_name)
expect(absorbing_organisation.owned_schemes.first.locations.count).to eq(2)
expect(absorbing_organisation.owned_schemes.first.locations.first.postcode).to eq(location.postcode)
expect(scheme.scheme_deactivation_periods.count).to eq(1)
expect(scheme.scheme_deactivation_periods.first.deactivation_date.to_date).to eq(Time.zone.yesterday)
end
it "moves relevant logs and assigns the new scheme" do
merge_organisations_service.call
absorbing_organisation.reload
merging_organisation.reload
expect(absorbing_organisation.owned_lettings_logs.count).to eq(2)
expect(absorbing_organisation.managed_lettings_logs.count).to eq(1)
expect(absorbing_organisation.owned_lettings_logs.find(owned_lettings_log.id).scheme).to eq(absorbing_organisation.owned_schemes.first)
expect(absorbing_organisation.owned_lettings_logs.find(owned_lettings_log.id).location).to eq(absorbing_organisation.owned_schemes.first.locations.first)
expect(absorbing_organisation.owned_lettings_logs.find(owned_lettings_log_no_location.id).scheme).to eq(absorbing_organisation.owned_schemes.first)
expect(absorbing_organisation.owned_lettings_logs.find(owned_lettings_log_no_location.id).location).to eq(nil)
end
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with([merging_organisation_ids]).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
merge_organisations_service.call
absorbing_organisation.reload
merging_organisation.reload
expect(absorbing_organisation.owned_schemes.count).to eq(0)
expect(scheme.scheme_deactivation_periods.count).to eq(0)
expect(owned_lettings_log.owning_organisation).to eq(merging_organisation)
expect(owned_lettings_log_no_location.owning_organisation).to eq(merging_organisation)
end
end
context "and absorbing_organisation_active_from_merge_date is true" do
subject(:merge_organisations_service) { described_class.new(absorbing_organisation_id: absorbing_organisation.id, merging_organisation_ids: [merging_organisation_ids], merge_date: Time.zone.yesterday, absorbing_organisation_active_from_merge_date: true) }
it "sets available from to merge_date for absorbing organisation" do
merge_organisations_service.call
absorbing_organisation.reload
expect(absorbing_organisation.available_from.to_date).to eq(Time.zone.yesterday)
end
end
end
context "and absorbing_organisation_active_from_merge_date is true" do
subject(:merge_organisations_service) { described_class.new(absorbing_organisation_id: absorbing_organisation.id, merging_organisation_ids: [merging_organisation_ids], absorbing_organisation_active_from_merge_date: true) }
it "sets available from to merge_date (today) for absorbing organisation" do
merge_organisations_service.call
absorbing_organisation.reload
expect(absorbing_organisation.available_from.to_date).to eq(Time.zone.today)
end
end
end
context "when merging a multiple organisations into an existing organisation" do
@ -318,6 +487,21 @@ RSpec.describe Merge::MergeOrganisationsService do
expect(absorbing_organisation.child_organisations).to include(absorbing_organisation_relationship.child_organisation)
end
end
context "and merge date is provided" do
subject(:merge_organisations_service) { described_class.new(absorbing_organisation_id: absorbing_organisation.id, merging_organisation_ids: [merging_organisation_ids], merge_date: Time.zone.yesterday) }
it "sets merge date and absorbing organisation on merged organisations" do
merge_organisations_service.call
merging_organisation.reload
merging_organisation_too.reload
expect(merging_organisation.merge_date.to_date).to eq(Time.zone.yesterday)
expect(merging_organisation.absorbing_organisation_id).to eq(absorbing_organisation.id)
expect(merging_organisation_too.merge_date.to_date).to eq(Time.zone.yesterday)
expect(merging_organisation_too.absorbing_organisation_id).to eq(absorbing_organisation.id)
end
end
end
end
end

Loading…
Cancel
Save