From 313eecbacb7af19517f840758a25fb58acee37ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Meny?= Date: Tue, 17 May 2022 16:52:17 +0100 Subject: [PATCH] Add local manifest XML --- .../exports/case_log_export_service.rb | 35 +++++++++++++------ spec/fixtures/exports/manifest.xml | 8 +++++ .../exports/case_log_export_service_spec.rb | 31 ++++++++++++++-- 3 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 spec/fixtures/exports/manifest.xml 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