From 4ea601de79fffeb1080a6f4aff974f7ea3ea22ab Mon Sep 17 00:00:00 2001 From: mfo Date: Tue, 21 May 2024 09:50:27 +0200 Subject: [PATCH 1/2] fix(champs.pj.clone): stop cloning private piece_justificative_file when user clone his dossier --- app/models/champ.rb | 2 +- spec/models/champ_spec.rb | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/app/models/champ.rb b/app/models/champ.rb index cbff3b54a..92fbca7d0 100644 --- a/app/models/champ.rb +++ b/app/models/champ.rb @@ -238,7 +238,7 @@ class Champ < ApplicationRecord kopy.write_attribute(:stable_id, original.stable_id) kopy.write_attribute(:stream, 'main') end - ClonePiecesJustificativesService.clone_attachments(original, kopy) + ClonePiecesJustificativesService.clone_attachments(original, kopy) if fork || !private? end end diff --git a/spec/models/champ_spec.rb b/spec/models/champ_spec.rb index 229b440a4..edde59295 100644 --- a/spec/models/champ_spec.rb +++ b/spec/models/champ_spec.rb @@ -569,4 +569,44 @@ describe Champ do it { expect(ActionView::RecordIdentifier.dom_id(champ.type_de_champ)).to eq("type_de_champ_#{champ.type_de_champ.id}") } it { expect(ActionView::RecordIdentifier.dom_class(champ)).to eq("champ") } end + + describe 'clone' do + subject { champ.clone(fork) } + + context 'when champ public' do + let(:champ) { create(:champ_piece_justificative, private: false) } + + context 'when fork' do + let(:fork) { true } + it do + expect(subject.piece_justificative_file).to be_attached + end + end + + context 'when not fork' do + let(:fork) { false } + it do + expect(subject.piece_justificative_file).to be_attached + end + end + end + + context 'champ private' do + let(:champ) { create(:champ_piece_justificative, private: true) } + + context 'when fork' do + let(:fork) { true } + it do + expect(subject.piece_justificative_file).to be_attached + end + end + + context 'when not fork' do + let(:fork) { false } + it do + expect(subject.piece_justificative_file).not_to be_attached + end + end + end + end end From 29ef5b313ce14445900647959845e5e604d87e36 Mon Sep 17 00:00:00 2001 From: mfo Date: Tue, 21 May 2024 14:21:21 +0200 Subject: [PATCH 2/2] fix(data): clean Champs::PieceJustificativeChamp for annotations that had been cloned --- app/models/champ.rb | 1 + ...hamps_private_piece_justificatives_task.rb | 34 ++++++++++++ ..._private_piece_justificatives_task_spec.rb | 54 +++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 app/tasks/maintenance/backfill_cloned_champs_private_piece_justificatives_task.rb create mode 100644 spec/tasks/maintenance/backfill_cloned_champs_private_piece_justificatives_task_spec.rb diff --git a/app/models/champ.rb b/app/models/champ.rb index 92fbca7d0..2cb0bb4ec 100644 --- a/app/models/champ.rb +++ b/app/models/champ.rb @@ -39,6 +39,7 @@ class Champ < ApplicationRecord :departement?, :region?, :textarea?, + :piece_justificative?, :titre_identite?, :header_section?, :checkbox?, diff --git a/app/tasks/maintenance/backfill_cloned_champs_private_piece_justificatives_task.rb b/app/tasks/maintenance/backfill_cloned_champs_private_piece_justificatives_task.rb new file mode 100644 index 000000000..ad32ece93 --- /dev/null +++ b/app/tasks/maintenance/backfill_cloned_champs_private_piece_justificatives_task.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Maintenance + class BackfillClonedChampsPrivatePieceJustificativesTask < MaintenanceTasks::Task + def collection + Dossier.en_brouillon.where.not(parent_dossier_id: nil) + end + + def process(cloned_dossier) + cloned_dossier.champs_private + .filter { checkable_pj?(_1, cloned_dossier) } + .map do |cloned_champ| + parent_champ = cloned_dossier.parent_dossier + .champs_private + .find { _1.stable_id == cloned_champ.stable_id } + + next if !parent_champ + + parent_blob_ids = parent_champ.piece_justificative_file.map(&:blob_id) + cloned_blob_ids = cloned_champ.piece_justificative_file.map(&:blob_id) + + if parent_blob_ids.sort == cloned_blob_ids.sort + cloned_champ.piece_justificative_file.detach + end + end + end + + def checkable_pj?(champ, dossier) + return false if champ.type != "Champs::PieceJustificativeChamp" + return false if !champ.piece_justificative_file.attached? + true + end + end +end diff --git a/spec/tasks/maintenance/backfill_cloned_champs_private_piece_justificatives_task_spec.rb b/spec/tasks/maintenance/backfill_cloned_champs_private_piece_justificatives_task_spec.rb new file mode 100644 index 000000000..2029c1991 --- /dev/null +++ b/spec/tasks/maintenance/backfill_cloned_champs_private_piece_justificatives_task_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require "rails_helper" + +module Maintenance + RSpec.describe BackfillClonedChampsPrivatePieceJustificativesTask do + describe "#process" do + let(:procedure) { create(:procedure, types_de_champ_private:) } + let(:types_de_champ_private) { [{ type: :piece_justificative }, { type: :text }] } + + let(:parent_dossier) { create(:dossier, procedure:) } + let(:cloned_dossier) { create(:dossier, procedure:) } + + let(:parent_champ_pj) { parent_dossier.champs_private.find(&:piece_justificative?) } + let(:cloned_champ_pj) { cloned_dossier.champs_private.find(&:piece_justificative?) } + + before do + cloned_dossier.update(parent_dossier:) # used on factorie, does not seed private_champs.. + parent_champ_pj.piece_justificative_file.attach( + io: StringIO.new("x" * 2), + filename: "me.jpg", + content_type: "image/png", + metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE } + ) + end + + subject { described_class.process(cloned_dossier) } + + context 'when dossier and parent have the same pjs' do + it 'detaches sames blob between parent_dossier and dossier' do + cloned_champ_pj.piece_justificative_file.attach(parent_champ_pj.piece_justificative_file.first.blob) + + subject + expect(cloned_champ_pj.reload.piece_justificative_file.attached?).to be_falsey + end + end + + context 'when dossier and parent have different pjs' do + it 'keeps different blobs between parent_dossier and dossier' do + cloned_champ_pj.piece_justificative_file.attach( + io: StringIO.new("x" * 2), + filename: "me.jpg", + content_type: "image/png", + metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE } + ) + + described_class.process(cloned_dossier) + subject + expect(cloned_champ_pj.reload.piece_justificative_file.attached?).to be_truthy + end + end + end + end +end