diff --git a/app/services/exports/case_log_export_service.rb b/app/services/exports/case_log_export_service.rb
index 0506a91af..46d105b61 100644
--- a/app/services/exports/case_log_export_service.rb
+++ b/app/services/exports/case_log_export_service.rb
@@ -4,7 +4,7 @@ module Exports
0 => "jan_mar",
1 => "apr_jun",
2 => "jul_sep",
- 3 => "oct_dec"
+ 3 => "oct_dec",
}.freeze
LOG_ID_OFFSET = 300_000_000_000
@@ -19,7 +19,7 @@ module Exports
case_logs = retrieve_case_logs
daily_run_number = get_next_run_number
write_master_manifest(daily_run_number)
- write_export_data(case_logs)
+ write_export_archive(case_logs)
export = LogsExport.new(daily_run_number:)
export.save!
@@ -63,12 +63,12 @@ module Exports
"core_#{collection_start}_#{collection_start + 1}_#{quarter}_#{base_number_str}_#{increment_str}"
end
- def write_export_data(case_logs)
+ def write_export_archive(case_logs)
# Order case logs per archive
case_logs_per_archive = {}
case_logs.each do |case_log|
archive = get_archive_name(case_log, 1, 1)
- if case_logs_per_archive.has_key?(archive)
+ if case_logs_per_archive.key?(archive)
case_logs_per_archive[archive] << case_log
else
case_logs_per_archive[archive] = [case_log]
@@ -77,9 +77,11 @@ module Exports
# Write all archives
case_logs_per_archive.each do |archive, case_logs_to_export|
- xml = build_export_xml(case_logs_to_export)
+ data_xml = build_export_xml(case_logs_to_export)
+ manifest_xml = build_manifest_xml(case_logs_to_export.count)
zip_io = Zip::File.open_buffer(StringIO.new)
- zip_io.add("#{archive}.xml", xml)
+ zip_io.add("#{archive}.xml", data_xml)
+ zip_io.add("manifest.xml", manifest_xml)
@storage_service.write_file("#{archive}.zip", zip_io.write_buffer)
end
end
@@ -96,6 +98,22 @@ module Exports
StringIO.new(csv_string)
end
+ def xml_doc_to_temp_file(xml_doc)
+ file = Tempfile.new
+ xml_doc.write_xml_to(file, encoding: "UTF-8")
+ file.rewind
+ file
+ end
+
+ def build_manifest_xml(record_number)
+ doc = Nokogiri::XML("")
+ doc.at("report") << doc.create_element("form-data-summary")
+ doc.at("form-data-summary") << doc.create_element("records")
+ doc.at("records") << doc.create_element("count-of-records", record_number)
+
+ xml_doc_to_temp_file(doc)
+ end
+
def build_export_xml(case_logs)
doc = Nokogiri::XML("")
@@ -114,10 +132,7 @@ module Exports
form << doc.create_element("providertype", case_log.owning_organisation.read_attribute_before_type_cast(:provider_type))
end
- file = Tempfile.new
- doc.write_xml_to(file, encoding: "UTF-8")
- file.rewind
- file
+ xml_doc_to_temp_file(doc)
end
end
end
diff --git a/spec/fixtures/exports/manifest.xml b/spec/fixtures/exports/manifest.xml
new file mode 100644
index 000000000..8c171ae01
--- /dev/null
+++ b/spec/fixtures/exports/manifest.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ {recno}
+
+
+
diff --git a/spec/services/exports/case_log_export_service_spec.rb b/spec/services/exports/case_log_export_service_spec.rb
index 99d81674c..c79140357 100644
--- a/spec/services/exports/case_log_export_service_spec.rb
+++ b/spec/services/exports/case_log_export_service_spec.rb
@@ -2,8 +2,8 @@ require "rails_helper"
RSpec.describe Exports::CaseLogExportService do
let(:storage_service) { instance_double(StorageService) }
- let(:export_filepath) { "spec/fixtures/exports/case_logs.xml" }
- let(:export_file) { File.open(export_filepath, "r:UTF-8") }
+ let(:export_file) { File.open("spec/fixtures/exports/case_logs.xml", "r:UTF-8") }
+ let(:local_manifest_file) { File.open("spec/fixtures/exports/manifest.xml", "r:UTF-8") }
let(:expected_master_manifest_filename) { "Manifest_2022_05_01_0001.csv" }
let(:case_log) { FactoryBot.create(:case_log, :completed) }
@@ -14,6 +14,10 @@ RSpec.describe Exports::CaseLogExportService do
export_template.sub!(/\{created_by_id\}/, case_log["created_by_id"].to_s)
end
+ def replace_record_number(export_template, record_number)
+ export_template.sub!(/\{recno\}/, record_number.to_s)
+ end
+
context "when exporting daily case logs" do
subject(:export_service) { described_class.new(storage_service) }
@@ -43,10 +47,19 @@ RSpec.describe Exports::CaseLogExportService do
context "and one case log is available for export" do
let(:expected_zip_filename) { "core_2021_2022_jan_mar_f0001_inc001.zip" }
let(:expected_data_filename) { "core_2021_2022_jan_mar_f0001_inc001.xml" }
+ let(:expected_manifest_filename) { "manifest.xml" }
it "generates a ZIP export file with the expected filename" do
expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args)
+ export_service.export_case_logs
+ end
+ it "generates an XML manifest file with the expected filename within the ZIP file" do
+ allow(storage_service).to receive(:write_file).with(expected_zip_filename, any_args) do |_, content|
+ entry = Zip::File.open_buffer(content).find_entry(expected_manifest_filename)
+ expect(entry).not_to be_nil
+ expect(entry.name).to eq(expected_manifest_filename)
+ end
export_service.export_case_logs
end
@@ -59,6 +72,17 @@ RSpec.describe Exports::CaseLogExportService do
export_service.export_case_logs
end
+ it "generates an XML manifest file with the expected content within the ZIP file" do
+ expected_content = replace_record_number(local_manifest_file.read, 1)
+ allow(storage_service).to receive(:write_file).with(expected_zip_filename, any_args) do |_, content|
+ entry = Zip::File.open_buffer(content).find_entry(expected_manifest_filename)
+ expect(entry).not_to be_nil
+ expect(entry.get_input_stream.read).to eq(expected_content)
+ end
+
+ export_service.export_case_logs
+ end
+
it "generates an XML export file with the expected content within the ZIP file" do
expected_content = replace_entity_ids(export_file.read)
allow(storage_service).to receive(:write_file).with(expected_zip_filename, any_args) do |_, content|
@@ -72,7 +96,7 @@ RSpec.describe Exports::CaseLogExportService do
end
context "and multiple case logs are available for export" do
- let!(:case_log_2) { FactoryBot.create(:case_log, startdate: Time.zone.local(2022, 4, 1)) }
+ before { FactoryBot.create(:case_log, startdate: Time.zone.local(2022, 4, 1)) }
context "when case logs are across multiple quarters" do
it "generates multiple ZIP export files with the expected filenames" do
@@ -86,6 +110,7 @@ RSpec.describe Exports::CaseLogExportService do
context "and a previous export has run the same day" do
let(:expected_master_manifest_rerun) { "Manifest_2022_05_01_0002.csv" }
+
before do
export_service.export_case_logs
end