aboutsummaryrefslogtreecommitdiffstats
path: root/app/models
diff options
context:
space:
mode:
authorAlban Peignier2017-12-14 11:09:05 +0100
committerAlban Peignier2018-01-05 10:22:59 +0100
commit638a1864a027226c9c0b26b01ca80a85435387f7 (patch)
tree133c131ea10a3635e91a6d7d64b9a00cb97c9e92 /app/models
parent63c8ca8680c9d77032abde84c7a5d969545d675a (diff)
downloadchouette-core-638a1864a027226c9c0b26b01ca80a85435387f7.tar.bz2
Create Merge operation. Refs #5299
Diffstat (limited to 'app/models')
-rw-r--r--app/models/merge.rb155
-rw-r--r--app/models/referential.rb9
2 files changed, 163 insertions, 1 deletions
diff --git a/app/models/merge.rb b/app/models/merge.rb
new file mode 100644
index 000000000..e87f83402
--- /dev/null
+++ b/app/models/merge.rb
@@ -0,0 +1,155 @@
+class Merge < ActiveRecord::Base
+ extend Enumerize
+
+ belongs_to :workbench
+ enumerize :status, in: %w[new pending successful failed running]
+
+ has_array_of :referentials, class_name: 'Referential'
+
+ delegate :output, to: :workbench
+
+ attr_reader :new
+
+ def merge!
+ update started_at: Time.now, status: :running
+
+ prepare_new
+
+ referentials.each do |referential|
+ merge_referential referential
+ end
+
+ save_current
+ ensure
+ update ended_at: Time.now, status: :successful
+ end
+
+ def prepare_new
+ new =
+ if workbench.output.current
+ Rails.logger.debug "Clone current output"
+ Referential.new_from(workbench.output.current, fixme_functional_scope).tap do |clone|
+ clone.inline_clone = true
+ end
+ else
+ Rails.logger.debug "Create a new output"
+ # 'empty' one
+ attributes = {
+ organisation: workbench.organisation, # TODO could be workbench.organisation by default
+ name: I18n.t("merges.referential_name"),
+ slug: "output_#{workbench.id}_#{Time.now.to_i}"
+ }
+ workbench.referentials.new attributes
+ end
+
+ new.save!
+
+ output.update new: new
+ @new = new
+ end
+
+ def merge_referential(referential)
+ Rails.logger.debug "Merge #{referential.slug}"
+ puts referential.metadatas.inspect
+
+ metadata_merger = MetadatasMerger.new new.metadatas, referential.metadatas
+ metadata_merger.merge
+
+ metadata_merger.conflits.each do |line_id, periods|
+ # clean new on given period
+ end
+ metadata_merger.destroyed_metadatas.each(&:destroy)
+
+ # let's merge data :)
+ end
+
+ def save_current
+ output.update current: new, new: nil
+ output.current.update referential_suite: output
+ end
+
+ def fixme_functional_scope
+ if attribute = workbench.organisation.sso_attributes.try(:[], "functional_scope")
+ JSON.parse(attribute)
+ end
+ end
+
+ def child_change
+
+ end
+
+ class MetadatasMerger
+
+ attr_reader :merge, :metadatas
+ def initialize(merge, metadatas)
+ @merge, @metadatas = merge, metadatas
+ end
+
+ def merge
+ metadatas.each do |metadata|
+ merge_one metadata
+ end
+ end
+
+ def line_metadatas(line_id)
+ merge.select do |m|
+ m.line_ids.include? line_id
+ end
+ end
+
+ def conflits
+ @conflits ||= Hash.new { |h,k| h[k] = [] }
+ end
+
+ def destroyed_metadatas
+ @destroyed_metadatas ||= []
+ end
+
+ def merge_one(metadata)
+ metadata.line_ids.each do |line_id|
+ line_metadatas = line_metadatas(line_id)
+
+ metadata.periodes do |period|
+ before = line_metadatas.find do |m|
+ m.periodes.any? { |p| p.include? period.begin }
+ end
+
+ if before
+ before.end = period.begin - 1
+ end
+
+ between = line_metadatas.select do |m|
+ m.periodes.any? do |p|
+ period.begin < p.begin && p.end < period.end
+ end
+ end
+
+ destroyed_metadatas.concat between
+
+ after = line_metadatas.find do |m|
+ m.periodes.any? { |p| p.include? period.end }
+ end
+
+ if after
+ after.begin = period.end + 1
+ end
+
+ if [before, between, after].any?(&:present?)
+ conflits[line_id] << period
+
+ attributes = {
+ line_ids: line_id,
+ periodes: [period],
+ referential_source_id: metadata.referential_source_id,
+ created_at: metadata.created_at
+ }
+ # line_metadatas should not contain conflicted metadatas
+ metadatas << ReferentialMetadata.new(attributes)
+ end
+ end
+ end
+ end
+
+ end
+
+end
diff --git a/app/models/referential.rb b/app/models/referential.rb
index 1cdda9e6a..c77fd4e3e 100644
--- a/app/models/referential.rb
+++ b/app/models/referential.rb
@@ -305,8 +305,15 @@ class Referential < ActiveRecord::Base
end
end
+ attr_accessor :inline_clone
def clone_schema
- ReferentialCloning.create(source_referential: created_from, target_referential: self)
+ cloning = ReferentialCloning.new source_referential: created_from, target_referential: self
+
+ if inline_clone
+ cloning.clone!
+ else
+ cloning.save!
+ end
end
def create_schema