Skip to content

Commit

Permalink
Merge pull request #2263 from UKGovernmentBEIS/feature/2932-add-iati-…
Browse files Browse the repository at this point in the history
…scope-to-xml

(2932) Add IATI Scope to xml
  • Loading branch information
mec committed Nov 29, 2023
2 parents a083f70 + 4bf9667 commit 559f826
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 10 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

[Full changelog][unreleased]

- The IATI activity scope is calculated based on the benefitting countries and
included in the IATI XML download as applicable

## Release 140 - 2023-11-28

[Full changelog][140]
Expand Down
4 changes: 4 additions & 0 deletions app/models/activity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,10 @@ def iati_identifier
end
end

def iati_scope
Iati::ActivityScopeService.new(benefitting_countries).call
end

def actual_total_for_report_financial_quarter(report:)
Actual::Overview.new(report: report, include_adjustments: true).value_for_report_quarter(self)
end
Expand Down
40 changes: 40 additions & 0 deletions app/services/iati/activity_scope_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
class Iati::ActivityScopeService
# see vendor/data/beis_organisation_references/codelists/BEIS/benefitting_regions.yml
REGION_LEVEL_CODE = 1

SCOPES = {
national: 4,
regional: 2,
multi_national: 3
}.freeze

def initialize(benefitting_country_codes)
@benefitting_country_codes = benefitting_country_codes
end

def call
return false unless @benefitting_country_codes.present?

return SCOPES[:national] if benefitting_countries.count == 1 && benefitting_regions.count == 1
return SCOPES[:regional] if benefitting_countries.count > 1 && benefitting_regions.count == 1
return SCOPES[:multi_national] if benefitting_countries.count > 1 && benefitting_regions.count > 1
end

private def benefitting_countries
return [] if @benefitting_country_codes.nil?

@_benefitting_countries ||= @benefitting_country_codes.map do |country_code|
BenefittingCountry.find_by_code(country_code)
end
end

private def benefitting_regions
level = BenefittingRegion::Level.find_by_code(REGION_LEVEL_CODE)

@_benefitting_regions ||= benefitting_countries.map do |benefitting_country|
benefitting_country.regions.select { |region| region.level == level }
end

@_benefitting_regions.uniq.flatten
end
end
2 changes: 2 additions & 0 deletions app/views/shared/xml/_activity.xml.haml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
%website= I18n.t("contact_info.website")
%mailing-address
%narrative= I18n.t("contact_info.mailing_address")
- if activity.iati_scope
%activity-scope{"code" => activity.iati_scope}/
- if activity.benefitting_countries.present?
- benefitting_countries_with_percentages(activity.benefitting_countries).each do |country|
%recipient-country{"code" => country.code, "percentage" => country.percentage}
Expand Down
22 changes: 22 additions & 0 deletions spec/features/beis_users_can_view_an_activity_as_xml_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@
expect(xml.at("iati-activity/recipient-country/@percentage").text).to eq("100.0")
expect(xml.at("iati-activity/recipient-country/narrative").text).to eq("Cabo Verde")
end

it "contains the IATI scope element" do
visit organisation_activity_path(organisation, activity, format: :xml)

expect(xml.at("iati-activity/activity-scope/@code").text).to eql("4")
end
end

context "when the activity has multiple benefitting countries" do
Expand All @@ -69,6 +75,22 @@
expect(results[1].at("@percentage").text).to eq("50.0")
expect(results[1].at("narrative").text).to eq("Belize")
end

it "contains the IATI scope element" do
visit organisation_activity_path(organisation, activity, format: :xml)

expect(xml.at("iati-activity/activity-scope/@code").text).to eql("3")
end
end

context "when the activity has no benefitting countries" do
let(:activity) { create(:project_activity, organisation: organisation, benefitting_countries: nil) }

it "does not contain the IATI scope element" do
visit organisation_activity_path(organisation, activity, format: :xml)

expect(xml.at("iati-activity/activity-scope")).to be_nil
end
end

context "when the activity has a legacy recipient_region and no benefitting countries" do
Expand Down
18 changes: 18 additions & 0 deletions spec/models/activity_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2770,6 +2770,24 @@ def create_report(organisation, fund)
end
end

describe "#iati_scope" do
context "when the activity has benefitting countries" do
let(:activity) { build(:programme_activity, benefitting_countries: %w[ZA]) }

it "returns the code for the scope" do
expect(activity.iati_scope).to eql(4)
end
end

context "when the activity has no benefitting countries" do
let(:activity) { build(:programme_activity, benefitting_countries: nil) }

it "returns false" do
expect(activity.iati_scope).to eql(false)
end
end
end

def factory_name_by_activity_level(level)
(level.underscore.parameterize(separator: "_") + "_activity").to_sym
end
Expand Down
45 changes: 45 additions & 0 deletions spec/services/iati/activity_scope_service_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require "rails_helper"

RSpec.describe Iati::ActivityScopeService do
describe "#call" do
context "when there is a single benefitting country in one region" do
it "returns the IATI code for national: 4" do
country_codes = ["DZ"]

expect(described_class.new(country_codes).call).to eql 4
end
end

context "when there are multiple benefitting countries in one region" do
it "returns the IATI code for regional: 2" do
country_codes = ["DZ", "MA", "EG"]

expect(described_class.new(country_codes).call).to eql 2
end
end

context "when there are multiple benefitting countries across multiple regions" do
it "returns the IATI code for multi-national: 3" do
country_codes = ["DZ", "SV", "MY"]

expect(described_class.new(country_codes).call).to eql 3
end
end

context "when the activity has no benefitting countries" do
it "returns false" do
country_codes = []

expect(described_class.new(country_codes).call).to eql false
end
end

context "when the activity benefitting countries is nil" do
it "returns false" do
country_codes = nil

expect(described_class.new(country_codes).call).to eql false
end
end
end
end
42 changes: 32 additions & 10 deletions spec/views/shared/xml/activity_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
RSpec.describe "shared/xml/activity" do
let(:activity) { create(:programme_activity) }

before do
reporting_organisation = build(:partner_organisation)
render partial: "shared/xml/activity",
Expand All @@ -14,17 +12,41 @@
}
end

context "when there is a commitment" do
let!(:commitment) { build(:commitment, activity: activity) }
it "renders the commitment" do
expect(rendered).to include("<transaction-type code='2'>")
describe "commitment" do
let(:activity) { create(:programme_activity) }

context "when there is a commitment" do
let!(:commitment) { build(:commitment, activity: activity) }
it "renders the commitment" do
expect(rendered).to include("<transaction-type code='2'>")
end
end

context "when there is no commitment" do
let!(:commitment) { nil }
it "does not render the commitment" do
expect(rendered).not_to include("<transaction-type code='2'>")
end
end
end

context "when there is no commitment" do
let!(:commitment) { nil }
it "does not render the commitment" do
expect(rendered).not_to include("<transaction-type code='2'>")
describe "activity-scope" do
context "when there are benefitting countries" do
let(:commitment) { nil }
let(:activity) { build(:project_activity, :gcrf_funded, benefitting_countries: %w[ZA]) }

it "inlcudes the scope element" do
expect(rendered).to include("<activity-scope")
end
end

context "when there are no benefitting countries" do
let(:commitment) { nil }
let(:activity) { build(:project_activity, :gcrf_funded, benefitting_countries: nil) }

it "does not include the scope element" do
expect(rendered).not_to include("<activity-scope")
end
end
end
end

0 comments on commit 559f826

Please sign in to comment.