diff options
| -rw-r--r-- | app/models/merge.rb | 155 | ||||
| -rw-r--r-- | app/models/referential.rb | 9 | ||||
| -rw-r--r-- | config/initializers/apartment.rb | 3 | ||||
| -rw-r--r-- | db/migrate/20171212152452_create_merges.rb | 16 | ||||
| -rw-r--r-- | db/schema.rb | 13 | ||||
| -rw-r--r-- | spec/models/merge_spec.rb | 14 |
6 files changed, 208 insertions, 2 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 diff --git a/config/initializers/apartment.rb b/config/initializers/apartment.rb index 69204a5d7..8becd23c2 100644 --- a/config/initializers/apartment.rb +++ b/config/initializers/apartment.rb @@ -77,7 +77,8 @@ Apartment.configure do |config| 'ComplianceCheckSet', 'ComplianceCheckBlock', 'ComplianceCheckResource', - 'ComplianceCheckMessage' + 'ComplianceCheckMessage', + 'Merge' ] # use postgres schemas? diff --git a/db/migrate/20171212152452_create_merges.rb b/db/migrate/20171212152452_create_merges.rb new file mode 100644 index 000000000..7915bd91b --- /dev/null +++ b/db/migrate/20171212152452_create_merges.rb @@ -0,0 +1,16 @@ +class CreateMerges < ActiveRecord::Migration + def change + create_table :merges do |t| + t.bigint :workbench_id, index: true, foreign_key: true + t.bigint :referential_ids, array: true + + t.string :creator + t.string :status + + t.datetime :started_at + t.datetime :ended_at + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index e6fdd9d74..667b95c84 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -522,6 +522,19 @@ ActiveRecord::Schema.define(version: 20171227113809) do add_index "lines", ["registration_number"], name: "lines_registration_number_key", using: :btree add_index "lines", ["secondary_company_ids"], name: "index_lines_on_secondary_company_ids", using: :gin + create_table "merges", id: :bigserial, force: :cascade do |t| + t.integer "workbench_id", limit: 8 + t.integer "referential_ids", limit: 8, array: true + t.string "creator" + t.string "status" + t.datetime "started_at" + t.datetime "ended_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "merges", ["workbench_id"], name: "index_merges_on_workbench_id", using: :btree + create_table "networks", id: :bigserial, force: :cascade do |t| t.string "objectid", null: false t.integer "object_version", limit: 8 diff --git a/spec/models/merge_spec.rb b/spec/models/merge_spec.rb new file mode 100644 index 000000000..674311f38 --- /dev/null +++ b/spec/models/merge_spec.rb @@ -0,0 +1,14 @@ +require "rails_helper" + +RSpec.describe Merge do + + it "should work" do + workbench = FactoryGirl.create :workbench + referential = FactoryGirl.create :referential, workbench: workbench, organisation: workbench.organisation + + merge = Merge.create!(workbench: workbench, referentials: [referential]) + + merge.merge! + end + +end |
