aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/controllers/compliance_control_sets_controller.rb8
-rw-r--r--app/controllers/stop_areas_controller.rb1
-rw-r--r--app/helpers/compliance_control_blocks_helper.rb10
-rw-r--r--app/helpers/compliance_controls_helper.rb11
-rw-r--r--app/helpers/table_builder_helper.rb24
-rw-r--r--app/models/compliance_control.rb72
-rw-r--r--app/models/import.rb3
-rw-r--r--app/views/compliance_control_sets/show.html.slim94
-rw-r--r--app/views/compliance_controls/_filters.html.slim46
-rw-r--r--app/views/layouts/navigation/_main_nav_left.html.slim21
-rw-r--r--app/workers/compliance_control_set_copy_worker.rb14
-rw-r--r--app/workers/workbench_import_worker.rb6
-rw-r--r--config/environments/test.rb3
-rw-r--r--config/locales/compliance_controls.en.yml13
-rw-r--r--config/locales/compliance_controls.fr.yml17
-rw-r--r--config/locales/import_messages.en.yml4
-rw-r--r--config/locales/import_messages.fr.yml4
-rw-r--r--config/locales/imports.en.yml6
-rw-r--r--config/locales/imports.fr.yml6
-rw-r--r--config/routes.rb1
-rw-r--r--db/schema.rb47
-rw-r--r--lib/compliance_control_set_copier.rb2
-rw-r--r--spec/controllers/api/v1/imports_controller_spec.rb2
-rw-r--r--spec/features/compliance_control_sets_spec.rb82
-rw-r--r--spec/features/connection_links_spec.rb2
-rw-r--r--spec/lib/compliance_control_set_copier_spec.rb4
-rw-r--r--spec/models/compliance_control_class_level_defaults/compliance_control_subclass_pattern_spec.rb17
-rw-r--r--spec/models/compliance_control_spec.rb4
-rw-r--r--spec/models/import_spec.rb2
-rw-r--r--spec/workers/compliance_control_set_copy_worker_spec.rb35
-rw-r--r--spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb3
-rw-r--r--spec/workers/workbench_import/workbench_import_worker_spec.rb4
32 files changed, 432 insertions, 136 deletions
diff --git a/app/controllers/compliance_control_sets_controller.rb b/app/controllers/compliance_control_sets_controller.rb
index f6002956b..cff67d5cb 100644
--- a/app/controllers/compliance_control_sets_controller.rb
+++ b/app/controllers/compliance_control_sets_controller.rb
@@ -17,8 +17,12 @@ class ComplianceControlSetsController < InheritedResources::Base
def show
show! do |format|
format.html {
+ @q_controls_form = @compliance_control_set.compliance_controls.ransack(params[:q])
@compliance_control_set = @compliance_control_set.decorate
- @compliance_controls_without_block = decorate_compliance_controls(@compliance_control_set.compliance_controls.where(compliance_control_block_id: nil))
+ @compliance_controls =
+ decorate_compliance_controls( @q_controls_form.result)
+ .group_by(&:compliance_control_block)
+ @indirect_compliance_controls = @compliance_controls.delete nil
}
end
end
@@ -58,4 +62,4 @@ class ComplianceControlSetsController < InheritedResources::Base
def compliance_control_set_params
params.require(:compliance_control_set).permit(:name, :id)
end
-end \ No newline at end of file
+end
diff --git a/app/controllers/stop_areas_controller.rb b/app/controllers/stop_areas_controller.rb
index 0c9f3067a..1d6f88068 100644
--- a/app/controllers/stop_areas_controller.rb
+++ b/app/controllers/stop_areas_controller.rb
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
class StopAreasController < InheritedResources::Base
include ApplicationHelper
diff --git a/app/helpers/compliance_control_blocks_helper.rb b/app/helpers/compliance_control_blocks_helper.rb
index 09e22d6e9..311e6fb46 100644
--- a/app/helpers/compliance_control_blocks_helper.rb
+++ b/app/helpers/compliance_control_blocks_helper.rb
@@ -1,10 +1,10 @@
module ComplianceControlBlocksHelper
def transport_mode(transport_mode, transport_submode)
- if (transport_mode) && (transport_submode) != ""
- transportMode = "[" + t("enumerize.transport_mode.#{transport_mode}") + "]" + "[" + t("enumerize.transport_submode.#{transport_submode}") + "]"
+ return "[Tous les modes de transport]" if transport_mode == ""
+ if transport_submode == ""
+ "[" + t("enumerize.transport_mode.#{transport_mode}") + "]"
else
- transportMode = "[Tous les modes de transport]"
+ "[" + t("enumerize.transport_mode.#{transport_mode}") + "]" + "[" + t("enumerize.transport_submode.#{transport_submode}") + "]"
end
- transportMode
end
-end \ No newline at end of file
+end
diff --git a/app/helpers/compliance_controls_helper.rb b/app/helpers/compliance_controls_helper.rb
new file mode 100644
index 000000000..ba0c538c9
--- /dev/null
+++ b/app/helpers/compliance_controls_helper.rb
@@ -0,0 +1,11 @@
+module ComplianceControlsHelper
+ def subclass_selection_list
+ ComplianceControl.subclass_patterns.map(&method(:make_subclass_selection_item))
+ end
+
+
+ def make_subclass_selection_item(key_pattern)
+ key, pattern = key_pattern
+ [t("compliance_controls.filters.subclasses.#{key}"), "-#{pattern}-"]
+ end
+end
diff --git a/app/helpers/table_builder_helper.rb b/app/helpers/table_builder_helper.rb
index 95f53a90d..37f01ce0d 100644
--- a/app/helpers/table_builder_helper.rb
+++ b/app/helpers/table_builder_helper.rb
@@ -83,17 +83,21 @@ module TableBuilderHelper
cls: '',
# A set of content, over the th line...
- overhead: []
+ overhead: [],
+
+ # Possibility to override the result of collection.model
+ model: nil
+
)
content_tag :table,
- thead(collection, columns, sortable, selectable, links.any?, overhead) +
+ thead(collection, columns, sortable, selectable, links.any?, overhead, model || collection.model) +
tbody(collection, columns, selectable, links, overhead),
class: cls
end
private
- def thead(collection, columns, sortable, selectable, has_links, overhead)
+ def thead(collection, columns, sortable, selectable, has_links, overhead, model )
content_tag :thead do
# Inserts overhead content if any specified
over_head = ''
@@ -121,7 +125,7 @@ module TableBuilderHelper
hcont << content_tag(:th, build_column_header(
column,
sortable,
- collection.model,
+ model,
params,
params[:sort],
params[:direction]
@@ -137,7 +141,7 @@ module TableBuilderHelper
hcont << content_tag(:th, build_column_header(
column,
sortable,
- collection.model,
+ model,
params,
params[:sort],
params[:direction]
@@ -147,7 +151,7 @@ module TableBuilderHelper
hcont << content_tag(:th, build_column_header(
column,
sortable,
- collection.model,
+ model,
params,
params[:sort],
params[:direction]
@@ -160,7 +164,7 @@ module TableBuilderHelper
hcont << content_tag(:th, build_column_header(
column,
sortable,
- collection.model,
+ model,
params,
params[:sort],
params[:direction]
@@ -299,14 +303,14 @@ module TableBuilderHelper
def build_column_header(
column,
table_is_sortable,
- collection_model,
+ model,
params,
sort_on,
sort_direction
)
if !table_is_sortable || !column.sortable
- return column.header_label(collection_model)
+ return column.header_label(model)
end
direction =
@@ -331,7 +335,7 @@ module TableBuilderHelper
arrow_icons = content_tag :span, arrow_up + arrow_down, class: 'orderers'
(
- column.header_label(collection_model) +
+ column.header_label(model) +
arrow_icons
).html_safe
end
diff --git a/app/models/compliance_control.rb b/app/models/compliance_control.rb
index 08efa7e9a..49fb6513f 100644
--- a/app/models/compliance_control.rb
+++ b/app/models/compliance_control.rb
@@ -1,29 +1,7 @@
class ComplianceControl < ActiveRecord::Base
- extend Enumerize
- belongs_to :compliance_control_set
- belongs_to :compliance_control_block
-
- enumerize :criticity, in: %i(warning error), scope: true, default: :warning
- hstore_accessor :control_attributes, {}
-
- validates :criticity, presence: true
- validates :name, presence: true
- validates :code, presence: true, uniqueness: { scope: :compliance_control_set }
- validates :origin_code, presence: true
- validates :compliance_control_set, presence: true
-
- validate def coherent_control_set
- return true if compliance_control_block_id.nil?
- ids = [compliance_control_block.compliance_control_set_id, compliance_control_set_id]
- return true if ids.first == ids.last
- names = ids.map{|id| ComplianceControlSet.find(id).name}
- errors.add(:coherent_control_set,
- I18n.t('compliance_controls.errors.incoherent_control_sets',
- indirect_set_name: names.first,
- direct_set_name: names.last))
- end
class << self
+ def criticities; %i(warning error) end
def default_code; "" end
def dynamic_attributes
hstore_metadata_for_control_attributes.keys
@@ -33,6 +11,17 @@ class ComplianceControl < ActiveRecord::Base
ComplianceControlPolicy
end
+ def subclass_patterns
+ {
+ generic: 'Generic',
+ journey_pattern: 'JourneyPattern',
+ line: 'Line',
+ route: 'Route',
+ routing_constraint_zone: 'RoutingConstraint',
+ vehicle_journey: 'VehicleJourney'
+ }
+ end
+
def inherited(child)
child.instance_eval do
def model_name
@@ -43,12 +32,37 @@ class ComplianceControl < ActiveRecord::Base
end
end
- def initialize(attributes = {})
- super
- self.name ||= I18n.t("activerecord.models.#{self.class.name.underscore}.one")
- self.code ||= self.class.default_code
- self.origin_code ||= self.class.default_code
- end
+ extend Enumerize
+ belongs_to :compliance_control_set
+ belongs_to :compliance_control_block
+
+ enumerize :criticity, in: criticities, scope: true, default: :warning
+ hstore_accessor :control_attributes, {}
+
+ validates :criticity, presence: true
+ validates :name, presence: true
+ validates :code, presence: true, uniqueness: { scope: :compliance_control_set }
+ validates :origin_code, presence: true
+ validates :compliance_control_set, presence: true
+
+ validate def coherent_control_set
+ return true if compliance_control_block_id.nil?
+ ids = [compliance_control_block.compliance_control_set_id, compliance_control_set_id]
+ return true if ids.first == ids.last
+ names = ids.map{|id| ComplianceControlSet.find(id).name}
+ errors.add(:coherent_control_set,
+ I18n.t('compliance_controls.errors.incoherent_control_sets',
+ indirect_set_name: names.first,
+ direct_set_name: names.last))
+end
+
+
+def initialize(attributes = {})
+ super
+ self.name ||= I18n.t("activerecord.models.#{self.class.name.underscore}.one")
+ self.code ||= self.class.default_code
+ self.origin_code ||= self.class.default_code
+end
end
diff --git a/app/models/import.rb b/app/models/import.rb
index e0aae6ef1..20e7f2d8a 100644
--- a/app/models/import.rb
+++ b/app/models/import.rb
@@ -16,9 +16,10 @@ class Import < ActiveRecord::Base
extend Enumerize
enumerize :status, in: %i(new pending successful warning failed running aborted canceled), scope: true, default: :new
+ validates :name, presence: true
validates :file, presence: true
validates_presence_of :workbench, :creator
- validates_format_of :file, with: %r{\.zip\z}i, message: I18n.t('activerecord.errors.models.imports.wrong_file_extension')
+ validates_format_of :file, with: %r{\.zip\z}i, message: I18n.t('activerecord.errors.models.import.attributes.file.wrong_file_extension')
before_create :initialize_fields
diff --git a/app/views/compliance_control_sets/show.html.slim b/app/views/compliance_control_sets/show.html.slim
index cf236feb8..294df6a53 100644
--- a/app/views/compliance_control_sets/show.html.slim
+++ b/app/views/compliance_control_sets/show.html.slim
@@ -24,54 +24,21 @@
.col-lg-6.col-md-6.col-sm-12.col-xs-12
= definition_list t('metadatas'),
ComplianceControlSet.human_attribute_name(:name) => @compliance_control_set.name
+ - if params[:q].present? or @compliance_controls.any?
+ .row
+ .col-lg-12
+ = render '/compliance_controls/filters'
+
.row
.col-lg-12
h2
= transport_mode("", "")
- .row
- .col-lg-12
- .select_table
- = table_builder_2 @compliance_controls_without_block,
- [ \
- TableBuilderHelper::Column.new( \
- key: :code, \
- attribute: 'code' \
- ), \
- TableBuilderHelper::Column.new( \
- key: :name, \
- attribute: 'name', \
- link_to: lambda do |compliance_control| \
- compliance_control_set_compliance_control_path(@compliance_control_set, compliance_control) \
- end \
- ), \
- TableBuilderHelper::Column.new( \
- key: :criticity, \
- attribute: 'criticity' \
- ), \
- TableBuilderHelper::Column.new( \
- key: :comment, \
- attribute: 'comment' \
- ), \
- ],
- sortable: true,
- cls: 'table has-filter has-search'
- - @compliance_control_set.compliance_control_blocks.each do |block|
- .row
- .col-lg-12
- h2
- = transport_mode(block.transport_mode, block.transport_submode)
- .btn-group
- .btn.dropdown-toggle{ data-toggle="dropdown" }
- .span.fa.fa-cog
- ul.dropdown-menu
- li
- = link_to t('compliance_control_sets.actions.edit'), edit_compliance_control_set_compliance_control_block_path(@compliance_control_set.id, block.id)
- = link_to t('compliance_control_sets.actions.destroy'), compliance_control_set_compliance_control_block_path(@compliance_control_set.id, block.id), :method => :delete, :data => {:confirm => t('compliance_control_sets.actions.destroy_confirm')}
+ - if @indirect_compliance_controls.try(:any?)
.row
.col-lg-12
.select_table
- = table_builder_2 ModelDecorator.decorate(block.compliance_controls, with: ComplianceControlDecorator),
+ = table_builder_2 @indirect_compliance_controls,
[ \
TableBuilderHelper::Column.new( \
key: :code, \
@@ -94,7 +61,52 @@
), \
],
sortable: true,
- cls: 'table has-filter has-search'
+ cls: 'table has-filter has-search',
+ model: ComplianceControl
+
+ - @compliance_controls.each do |block, compliance_controls|
+
+ - if compliance_controls.try(:any?)
+ .row
+ .col-lg-12
+ h2
+ = transport_mode(block.transport_mode, block.transport_submode)
+ .btn-group
+ .btn.dropdown-toggle{ data-toggle="dropdown" }
+ .span.fa.fa-cog
+ ul.dropdown-menu
+ li
+ = link_to t('compliance_control_sets.actions.edit'), edit_compliance_control_set_compliance_control_block_path(@compliance_control_set.id, block.id)
+ = link_to t('compliance_control_sets.actions.destroy'), compliance_control_set_compliance_control_block_path(@compliance_control_set.id, block.id), :method => :delete, :data => {:confirm => t('compliance_control_sets.actions.destroy_confirm')}
+ .row
+ .col-lg-12
+ .select_table
+ = table_builder_2 compliance_controls,
+ [ \
+ TableBuilderHelper::Column.new( \
+ key: :code, \
+ attribute: 'code' \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :name, \
+ attribute: 'name', \
+ link_to: lambda do |compliance_control| \
+ compliance_control_set_compliance_control_path(@compliance_control_set, compliance_control) \
+ end \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :criticity, \
+ attribute: 'criticity' \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :comment, \
+ attribute: 'comment' \
+ ), \
+ ],
+ sortable: true,
+ cls: 'table has-filter has-search',
+ model: ComplianceControl
+
.select_toolbox
ul
li.st_action.with_text
diff --git a/app/views/compliance_controls/_filters.html.slim b/app/views/compliance_controls/_filters.html.slim
new file mode 100644
index 000000000..c729190a0
--- /dev/null
+++ b/app/views/compliance_controls/_filters.html.slim
@@ -0,0 +1,46 @@
+= search_form_for @q_controls_form,
+ url: compliance_control_set_path(@compliance_control_set),
+ builder: SimpleForm::FormBuilder,
+ class: 'form form-filter' do |f|
+
+ .ffg-row
+ .input-group.search_bar
+ = f.search_field :name_cont,
+ class: 'form-control',
+ placeholder: t('compliance_controls.filters.name')
+ span.input-group-btn
+ button.btn.btn-default type='submit'
+ span.fa.fa-search
+
+ .ffg-row
+ .form-group.togglable#compliance_control_block-filter
+ = f.label t('activerecord.models.compliance_control_block.one'), required: false, class: 'control-label'
+ = f.input :compliance_control_block_id_eq_any,
+ collection: @compliance_control_set.compliance_control_blocks,
+ as: :check_boxes,
+ label: false,
+ label_method: lambda {|w| ("<span>#{transport_mode(w.transport_mode, w.transport_submode)}</span>").html_safe},
+ required: false,
+ wrapper_html: {class: 'checkbox_list'}
+ .form-group.togglable#subclass-filter
+ = f.label t('compliance_controls.filters.subclass'), required: false, class: 'control-label'
+ = f.input :origin_code_cont_any,
+ collection: subclass_selection_list,
+ as: :check_boxes,
+ label: false,
+ label_method: lambda {|w| ("<span>#{w.first}</span>").html_safe},
+ required: false,
+ wrapper_html: {class: 'checkbox_list'}
+ .form-group.togglable#severity-filter
+ = f.label t('compliance_controls.filters.criticity'), required: false, class: 'control-label'
+ = f.input :criticity_eq_any,
+ collection: ComplianceControl.criticities,
+ as: :check_boxes,
+ label: false,
+ label_method: lambda {|w| ("<span>#{w}</span>").html_safe},
+ required: false,
+ wrapper_html: {class: 'checkbox_list'}
+
+ .actions
+ = link_to t('actions.erase'), @compliance_control_set, class: 'btn btn-link'
+ = f.submit t('actions.filter'), class: 'btn btn-default', id: 'compliance_control_set_compliance_controls_filter_btn'
diff --git a/app/views/layouts/navigation/_main_nav_left.html.slim b/app/views/layouts/navigation/_main_nav_left.html.slim
index 062c9383c..837b9cb73 100644
--- a/app/views/layouts/navigation/_main_nav_left.html.slim
+++ b/app/views/layouts/navigation/_main_nav_left.html.slim
@@ -31,16 +31,17 @@
#miTwo.panel-collapse.collapse
.list-group
- = link_to workbench_path(current_offer_workbench), class: "list-group-item #{params[:controller] == 'workbenches' ? 'active' : ''}" do
- span Jeux de données
- = link_to workbench_imports_path(current_offer_workbench), class: "list-group-item #{(params[:controller] == 'imports') ? 'active' : ''}" do
- span Import
- = link_to calendars_path, class: 'list-group-item' do
- span Modèles de calendrier
- = link_to workbench_compliance_check_sets_path(current_offer_workbench), class: 'list-group-item' do
- span Rapport de contrôle
- = link_to compliance_control_sets_path, class: 'list-group-item' do
- span Jeux de contrôle
+ - if current_user
+ = link_to workbench_path(current_offer_workbench), class: "list-group-item #{params[:controller] == 'workbenches' ? 'active' : ''}" do
+ span Jeux de données
+ = link_to workbench_imports_path(current_offer_workbench), class: "list-group-item #{(params[:controller] == 'imports') ? 'active' : ''}" do
+ span Import
+ = link_to calendars_path, class: 'list-group-item' do
+ span Modèles de calendrier
+ = link_to workbench_compliance_check_sets_path(current_offer_workbench), class: 'list-group-item' do
+ span Rapport de contrôle
+ = link_to compliance_control_sets_path, class: 'list-group-item' do
+ span Jeux de contrôle
.menu-item.panel
.panel-heading
diff --git a/app/workers/compliance_control_set_copy_worker.rb b/app/workers/compliance_control_set_copy_worker.rb
new file mode 100644
index 000000000..d18bb0c88
--- /dev/null
+++ b/app/workers/compliance_control_set_copy_worker.rb
@@ -0,0 +1,14 @@
+class ComplianceControlSetCopyWorker
+ include Sidekiq::Worker
+
+ def perform(control_set_id, referential_id)
+ check_set = ComplianceControlSetCopier.new.copy(control_set_id, referential_id)
+
+ begin
+ Net::HTTP.get(URI("#{Rails.configuration.iev_url}/boiv_iev/referentials/validator/new?id=#{check_set.id}"))
+ rescue Exception => e
+ logger.error "IEV server error : #{e.message}"
+ logger.error e.backtrace.inspect
+ end
+ end
+end
diff --git a/app/workers/workbench_import_worker.rb b/app/workers/workbench_import_worker.rb
index 300fad9e2..de51efded 100644
--- a/app/workers/workbench_import_worker.rb
+++ b/app/workers/workbench_import_worker.rb
@@ -35,7 +35,7 @@ class WorkbenchImportWorker
end
def handle_corrupt_zip_file
- @workbench_import.messages.create(criticity: :error, message_key: 'corrupt_zip_file', message_attributes: {import_name: @workbench_import.name})
+ @workbench_import.messages.create(criticity: :error, message_key: 'corrupt_zip_file', message_attributes: {source_filename: @workbench_import.file.file.file})
end
def upload zip_service
@@ -55,8 +55,8 @@ class WorkbenchImportWorker
criticity: :warning,
message_key: 'inconsistent_zip_file',
message_attributes: {
- 'import_name' => @workbench_import.name,
- 'spurious_dirs' => entry.spurious.join(', ')
+ 'source_filename' => @workbench_import.file.file.file,
+ 'spurious_dirs' => entry.spurious.join(', ')
})
end
end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index b3312be4a..8bf94f5da 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -62,6 +62,9 @@ Rails.application.configure do
# Reflex api url
config.reflex_api_url = "https://195.46.215.128/ws/reflex/V1/service=getData"
+ # IEV url
+ config.iev_url = ENV.fetch('IEV_URL', 'http://localhost:8080')
+
config.rails_host = "http://www.example.com"
# file to data for demo
config.demo_data = "tmp/demo.zip"
diff --git a/config/locales/compliance_controls.en.yml b/config/locales/compliance_controls.en.yml
index 887bc2009..41971d9e9 100644
--- a/config/locales/compliance_controls.en.yml
+++ b/config/locales/compliance_controls.en.yml
@@ -2,6 +2,17 @@ en:
compliance_controls:
clone:
prefix: 'Copy of'
+ filters:
+ criticity: Severity
+ name: "Search by a control's name or code"
+ subclass: Object
+ subclasses:
+ generic: 'Generic'
+ journey_pattern: 'JourneyPattern'
+ line: 'Line'
+ route: 'Route'
+ routing_constraint_zone: 'RoutingConstraint'
+ vehicle_journey: 'VehicleJourney'
min_max_values: "the minimum (%{min}) is not supposed to be greater than the maximum (%{max})"
errors:
incoherent_control_sets: "Impossible to assign a control to a set (id: %{direct_set_name}) differing from the one of its group (id: %{indirect_set_name})"
@@ -179,4 +190,4 @@ en:
compliance_control_block: "Control Block"
minimum: "Minimum"
maximum: "Maximum"
- target: "Target" \ No newline at end of file
+ target: "Target"
diff --git a/config/locales/compliance_controls.fr.yml b/config/locales/compliance_controls.fr.yml
index 2feb201bf..3fa83a147 100644
--- a/config/locales/compliance_controls.fr.yml
+++ b/config/locales/compliance_controls.fr.yml
@@ -2,6 +2,17 @@ fr:
compliance_controls:
clone:
prefix: 'Copie de'
+ filters:
+ criticity: Criticité
+ name: "Chercher le nom ou code d'un contrôl"
+ subclass: Objet
+ subclasses:
+ generic: 'Généric'
+ journey_pattern: 'JourneyPattern'
+ line: 'Ligne'
+ route: 'Itinéraire'
+ routing_constraint_zone: 'ITL'
+ vehicle_journey: 'Course'
min_max_values: "la valeur de minimum (%{min}) ne doit pas être superieur à la valuer du maximum (%{max})"
errors:
incoherent_control_sets: "Le contrôle ne peut pas être associé à un jeu de contrôle (id: %{direct_set_name}) différent de celui de son groupe (id: %{indirect_set_name})"
@@ -119,7 +130,7 @@ fr:
activerecord:
models:
compliance_control:
- one: "controle"
+ one: "contrôle"
other: "contrôles"
route_control/zdl_stop_area:
one: "Deux arrêts d’une même ZDL ne peuvent pas se succéder dans un itinéraire"
@@ -130,7 +141,7 @@ fr:
route_control/duplicates:
one: "Détection de double définition d'itinéraire"
route_control/opposite_route_terminus:
- one: "Vérification des terminus de l'itinéraire inverse"
+ one: "Vérification des terminus de l'itinéraire inverse"
route_control/minimum_length:
one: "Un itinéraire doit contenir au moins 2 arrêts"
route_control/omnibus_journey_pattern:
@@ -179,4 +190,4 @@ fr:
compliance_control_block: "Groupe de contrôle"
minimum: "Minimum"
maximum: "Maximum"
- target: "Cible" \ No newline at end of file
+ target: "Cible"
diff --git a/config/locales/import_messages.en.yml b/config/locales/import_messages.en.yml
index 2048b9794..bf6b45020 100644
--- a/config/locales/import_messages.en.yml
+++ b/config/locales/import_messages.en.yml
@@ -1,8 +1,8 @@
en:
import_messages:
compliance_check_messages:
- corrupt_zip_file: "The zip file of WorkbenchImport %{import_name} is corrupted and cannot be read"
- inconsistent_zip_file: "The zip file of WorkbenchImport %{import_name} contains the following spurious directories %{spurious_dirs}, which are ignored"
+ corrupt_zip_file: "The zip file %{source_filename} is corrupted and cannot be read"
+ inconsistent_zip_file: "The zip file %{source_filename} contains unexpected directories: %{spurious_dirs}, which are ignored"
referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les même périodes et lignes"
1_netexstif_2: "Le fichier %{source_filename} ne respecte pas la syntaxe XML ou la XSD NeTEx : erreur '%{error_value}' rencontré"
1_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
diff --git a/config/locales/import_messages.fr.yml b/config/locales/import_messages.fr.yml
index 9f0af1faa..7d3bbf23b 100644
--- a/config/locales/import_messages.fr.yml
+++ b/config/locales/import_messages.fr.yml
@@ -1,8 +1,8 @@
fr:
import_messages:
compliance_check_messages:
- corrupt_zip_file: "Le fichier zip du WorkbenchImport %{import_name} est corrompu, et ne peut être lu"
- inconsistent_zip_file: "Le fichier zip du WorkbenchImport %{import_name} contient les repertoirs illegeaux %{spurious_dirs} qui seront ignorés"
+ corrupt_zip_file: "Le fichier zip %{source_filename} est corrompu, et ne peut être lu"
+ inconsistent_zip_file: "Le fichier zip %{source_filename} contient des repertoires non prévus : %{spurious_dirs} qui seront ignorés"
referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les même périodes et lignes"
1_netexstif_2: "Le fichier %{source_filename} ne respecte pas la syntaxe XML ou la XSD NeTEx : erreur '%{error_value}' rencontré"
1_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
diff --git a/config/locales/imports.en.yml b/config/locales/imports.en.yml
index f3bcad9e9..10434dd19 100644
--- a/config/locales/imports.en.yml
+++ b/config/locales/imports.en.yml
@@ -55,8 +55,10 @@ en:
other: "imports"
errors:
models:
- imports:
- wrong_file_extension: "The imported file must be a zip file"
+ import:
+ attributes:
+ file:
+ wrong_file_extension: "The imported file must be a zip file"
attributes:
import:
resources: "File to import"
diff --git a/config/locales/imports.fr.yml b/config/locales/imports.fr.yml
index 6e74fa33c..099488a6b 100644
--- a/config/locales/imports.fr.yml
+++ b/config/locales/imports.fr.yml
@@ -55,8 +55,10 @@ fr:
other: "imports"
errors:
models:
- imports:
- wrong_file_extension: "Le fichier importé doit être au format zip"
+ import:
+ attributes:
+ file:
+ wrong_file_extension: "Le fichier importé doit être au format zip"
attributes:
import:
resources: "Fichier à importer"
diff --git a/config/routes.rb b/config/routes.rb
index 214b12584..30ba51358 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -74,6 +74,7 @@ ChouetteIhm::Application.routes.draw do
resources :api_keys, :only => [:edit, :update, :new, :create, :destroy]
resources :compliance_control_sets do
+ get :simple, on: :member
get :clone, on: :member
get :select_compliance_control_set
resources :compliance_controls, except: :index do
diff --git a/db/schema.rb b/db/schema.rb
index a64a426de..dd9461c78 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -284,6 +284,22 @@ ActiveRecord::Schema.define(version: 20171016074044) do
add_index "connection_links", ["objectid"], name: "connection_links_objectid_key", unique: true, using: :btree
+ create_table "delayed_jobs", id: :bigserial, force: :cascade do |t|
+ t.integer "priority", default: 0
+ t.integer "attempts", default: 0
+ t.text "handler"
+ t.text "last_error"
+ t.datetime "run_at"
+ t.datetime "locked_at"
+ t.datetime "failed_at"
+ t.string "locked_by", limit: 255
+ t.string "queue", limit: 255
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority", using: :btree
+
create_table "exports", id: :bigserial, force: :cascade do |t|
t.integer "referential_id", limit: 8
t.string "status"
@@ -405,12 +421,12 @@ ActiveRecord::Schema.define(version: 20171016074044) do
t.datetime "started_at"
t.datetime "ended_at"
t.string "token_download"
- t.string "type"
+ t.string "type", limit: 255
t.integer "parent_id", limit: 8
t.string "parent_type"
+ t.integer "current_step", default: 0
+ t.integer "total_steps", default: 0
t.datetime "notified_parent_at"
- t.integer "current_step", default: 0
- t.integer "total_steps", default: 0
t.string "creator"
end
@@ -562,6 +578,11 @@ ActiveRecord::Schema.define(version: 20171016074044) do
add_index "networks", ["objectid"], name: "networks_objectid_key", unique: true, using: :btree
add_index "networks", ["registration_number"], name: "networks_registration_number_key", using: :btree
+ create_table "object_id_factories", id: :bigserial, force: :cascade do |t|
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
create_table "organisations", id: :bigserial, force: :cascade do |t|
t.string "name"
t.datetime "created_at"
@@ -750,7 +771,7 @@ ActiveRecord::Schema.define(version: 20171016074044) do
create_table "stop_areas", id: :bigserial, force: :cascade do |t|
t.integer "parent_id", limit: 8
- t.string "objectid", null: false
+ t.string "objectid", null: false
t.integer "object_version", limit: 8
t.string "creator_id"
t.string "name"
@@ -759,8 +780,8 @@ ActiveRecord::Schema.define(version: 20171016074044) do
t.string "registration_number"
t.string "nearest_topic_name"
t.integer "fare_code"
- t.decimal "longitude", precision: 19, scale: 16
- t.decimal "latitude", precision: 19, scale: 16
+ t.decimal "longitude", precision: 19, scale: 16
+ t.decimal "latitude", precision: 19, scale: 16
t.string "long_lat_type"
t.string "country_code"
t.string "street_name"
@@ -778,7 +799,7 @@ ActiveRecord::Schema.define(version: 20171016074044) do
t.datetime "deleted_at"
t.datetime "created_at"
t.datetime "updated_at"
- t.string "stif_type"
+ t.string "stif_type", limit: 255
end
add_index "stop_areas", ["name"], name: "index_stop_areas_on_name", using: :btree
@@ -849,18 +870,18 @@ ActiveRecord::Schema.define(version: 20171016074044) do
add_index "time_table_periods", ["time_table_id"], name: "index_time_table_periods_on_time_table_id", using: :btree
create_table "time_tables", id: :bigserial, force: :cascade do |t|
- t.string "objectid", null: false
- t.integer "object_version", limit: 8, default: 1
+ t.string "objectid", null: false
+ t.integer "object_version", limit: 8, default: 1
t.string "creator_id"
t.string "version"
t.string "comment"
- t.integer "int_day_types", default: 0
+ t.integer "int_day_types", default: 0
t.date "start_date"
t.date "end_date"
t.integer "calendar_id", limit: 8
t.datetime "created_at"
t.datetime "updated_at"
- t.string "color"
+ t.string "color", limit: 255
t.integer "created_from_id"
t.string "checksum"
t.text "checksum_source"
@@ -1007,9 +1028,13 @@ ActiveRecord::Schema.define(version: 20171016074044) do
add_foreign_key "compliance_controls", "compliance_control_blocks"
add_foreign_key "compliance_controls", "compliance_control_sets"
add_foreign_key "group_of_lines_lines", "group_of_lines", name: "groupofline_group_fkey", on_delete: :cascade
+ add_foreign_key "journey_frequencies", "timebands", name: "journey_frequencies_timeband_id_fk", on_delete: :nullify
add_foreign_key "journey_frequencies", "timebands", on_delete: :nullify
+ add_foreign_key "journey_frequencies", "vehicle_journeys", name: "journey_frequencies_vehicle_journey_id_fk", on_delete: :nullify
add_foreign_key "journey_frequencies", "vehicle_journeys", on_delete: :nullify
+ add_foreign_key "journey_pattern_sections", "journey_patterns", name: "journey_pattern_sections_journey_pattern_id_fk", on_delete: :cascade
add_foreign_key "journey_pattern_sections", "journey_patterns", on_delete: :cascade
+ add_foreign_key "journey_pattern_sections", "route_sections", name: "journey_pattern_sections_route_section_id_fk", on_delete: :cascade
add_foreign_key "journey_pattern_sections", "route_sections", on_delete: :cascade
add_foreign_key "journey_patterns", "routes", name: "jp_route_fkey", on_delete: :cascade
add_foreign_key "journey_patterns", "stop_points", column: "arrival_stop_point_id", name: "arrival_point_fkey", on_delete: :nullify
diff --git a/lib/compliance_control_set_copier.rb b/lib/compliance_control_set_copier.rb
index 20518ee0e..58d40cdbf 100644
--- a/lib/compliance_control_set_copier.rb
+++ b/lib/compliance_control_set_copier.rb
@@ -11,6 +11,8 @@ class ComplianceControlSetCopier
@referential_id = referential_id
check_organisation_coherence!
copy_set
+
+ cck_set
end
diff --git a/spec/controllers/api/v1/imports_controller_spec.rb b/spec/controllers/api/v1/imports_controller_spec.rb
index 266b25486..8077dd052 100644
--- a/spec/controllers/api/v1/imports_controller_spec.rb
+++ b/spec/controllers/api/v1/imports_controller_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Api::V1::ImportsController, type: :controller do
it 'should be successful' do
expect {
- post :create, workbench_id: workbench.id, workbench_import: {file: file, creator: 'test'}, format: :json
+ post :create, workbench_id: workbench.id, workbench_import: {name: "test", file: file, creator: 'test'}, format: :json
}.to change{WorkbenchImport.count}.by(1)
expect(response).to be_success
end
diff --git a/spec/features/compliance_control_sets_spec.rb b/spec/features/compliance_control_sets_spec.rb
new file mode 100644
index 000000000..500d4ce6f
--- /dev/null
+++ b/spec/features/compliance_control_sets_spec.rb
@@ -0,0 +1,82 @@
+RSpec.describe "ComplianceControlSets", type: :feature do
+
+ login_user
+
+ # We setup a control_set with two blocks and one direct control (meaning that it is not attached to a block)
+ # Then we add one control to the first block and two controls to the second block
+ let( :control_set ){ create :compliance_control_set, organisation: organisation }
+ let( :controls ){ control_set.compliance_controls }
+
+ let(:blox){
+ 2.times.map{ | _ | create :compliance_control_block, compliance_control_set: control_set }
+ }
+
+ before do
+ blox.first.update transport_mode: 'bus', transport_submode: 'bus'
+ blox.second.update transport_mode: 'train', transport_submode: 'train'
+
+ make_control
+ make_control blox.first, severity: :error
+ make_control blox.second, times: 2
+ end
+
+ describe 'show' do
+ before do
+ visit compliance_control_set_path( control_set )
+ end
+
+ it 'we can see the controls inside their blocks' do
+ controls.each do | control |
+ expect( page ).to have_content(control.code)
+ end
+ end
+
+ it 'we can apply a severity filter' do
+ controls.take(2).each do | control |
+ control.update criticity: 'error'
+ end
+ check('error')
+ click_on('Filtrer')
+ controls.each do | control |
+ if control.criticity == 'error'
+ expect( page ).to have_content(control.code)
+ else
+ expect( page ).not_to have_content(control.code)
+ end
+ end
+ end
+
+ it 'we can apply a subclass filter' do
+ controls.first.update(origin_code: 'x-Route-y')
+ controls.second.update(origin_code: 'x-Line-y')
+
+ within('#subclass-filter') do
+ check('Itinéraire')
+ check('Ligne')
+ end
+ click_on('Filtrer')
+ controls.each do | control |
+ if control.origin_code[/-Generic-/]
+ expect( page ).not_to have_content(control.code)
+ else
+ expect( page ).to have_content(control.code)
+ end
+ end
+ end
+
+ end
+
+ def make_control ccblock=nil, times: 1, severity: :warning
+ times.times do
+ make_one_control ccblock, severity
+ end
+ end
+
+ def make_one_control ccblock, severity
+ create( :generic_attribute_control_min_max,
+ code: random_string,
+ compliance_control_block: ccblock,
+ compliance_control_set: control_set)
+ end
+
+end
diff --git a/spec/features/connection_links_spec.rb b/spec/features/connection_links_spec.rb
index 7272242fe..2f6283dcd 100644
--- a/spec/features/connection_links_spec.rb
+++ b/spec/features/connection_links_spec.rb
@@ -1,4 +1,4 @@
-RSpec.describe "ConnectionLinks", :type => :feature do
+RSpec.describe "ConnectionLinks", type: :feature do
login_user
let!(:connection_links) { Array.new(2) { create(:connection_link) } }
diff --git a/spec/lib/compliance_control_set_copier_spec.rb b/spec/lib/compliance_control_set_copier_spec.rb
index a9e576cf7..0f15d86d0 100644
--- a/spec/lib/compliance_control_set_copier_spec.rb
+++ b/spec/lib/compliance_control_set_copier_spec.rb
@@ -99,6 +99,10 @@ RSpec.describe ComplianceControlSetCopier do
expect( actual ).to eq( expected )
end
+
+ it 'returns the newly-created ComplianceCheckSet' do
+ expect(subject.copy(cc_set.id, ref.id)).to eq(cck_set)
+ end
end
end
diff --git a/spec/models/compliance_control_class_level_defaults/compliance_control_subclass_pattern_spec.rb b/spec/models/compliance_control_class_level_defaults/compliance_control_subclass_pattern_spec.rb
new file mode 100644
index 000000000..868eca984
--- /dev/null
+++ b/spec/models/compliance_control_class_level_defaults/compliance_control_subclass_pattern_spec.rb
@@ -0,0 +1,17 @@
+RSpec.describe ComplianceControl do
+ let( :subject ){ described_class.subclass_patterns }
+
+ context 'subclass_patterns' do
+ it 'are correctly defined' do
+ expect_it.to eq(
+ generic: 'Generic',
+ journey_pattern: 'JourneyPattern',
+ line: 'Line',
+ route: 'Route',
+ routing_constraint_zone: 'RoutingConstraint',
+ vehicle_journey: 'VehicleJourney'
+ )
+ end
+ end
+
+end
diff --git a/spec/models/compliance_control_spec.rb b/spec/models/compliance_control_spec.rb
index db73dab21..4267459ea 100644
--- a/spec/models/compliance_control_spec.rb
+++ b/spec/models/compliance_control_spec.rb
@@ -4,10 +4,6 @@ RSpec.describe ComplianceControl, type: :model do
let(:compliance_control) { build_stubbed :compliance_control }
- it 'should have a valid factory' do
- expect(compliance_control).to be_valid
- end
-
it { should belong_to :compliance_control_set }
it { should belong_to :compliance_control_block }
diff --git a/spec/models/import_spec.rb b/spec/models/import_spec.rb
index c06d05dab..7be05908a 100644
--- a/spec/models/import_spec.rb
+++ b/spec/models/import_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Import, type: :model do
it { should validate_presence_of(:workbench) }
it { should validate_presence_of(:creator) }
- it { should allow_value('file.zip').for(:file).with_message(I18n.t('activerecord.errors.models.imports.wrong_file_extension')) }
+ it { should allow_value('file.zip').for(:file).with_message(I18n.t('activerecord.errors.models.import.attributes.file.wrong_file_extension')) }
it { should_not allow_values('file.json', 'file.png', 'file.pdf').for(:file) }
let(:workbench_import) { build_stubbed(:workbench_import) }
diff --git a/spec/workers/compliance_control_set_copy_worker_spec.rb b/spec/workers/compliance_control_set_copy_worker_spec.rb
new file mode 100644
index 000000000..0ff721e75
--- /dev/null
+++ b/spec/workers/compliance_control_set_copy_worker_spec.rb
@@ -0,0 +1,35 @@
+RSpec.describe ComplianceControlSetCopyWorker do
+ let(:control_set_id) { 55 }
+ let(:referential_id) { 99 }
+ let(:check_set) { double(ComplianceCheckSet, id: 888) }
+ let(:stub_validation_request) do
+ stub_request(
+ :get,
+ "#{Rails.configuration.iev_url}/boiv_iev/referentials/validator/new?id=#{check_set.id}"
+ )
+ end
+
+ before(:each) do
+ allow_any_instance_of(
+ ComplianceControlSetCopier
+ ).to receive(:copy).and_return(check_set)
+
+ stub_validation_request
+ end
+
+ it "calls ComplianceControlSetCopier" do
+ expect_any_instance_of(
+ ComplianceControlSetCopier
+ ).to receive(:copy)
+ .with(control_set_id, referential_id)
+ .and_return(check_set)
+
+ ComplianceControlSetCopyWorker.new.perform(control_set_id, referential_id)
+ end
+
+ it "calls the Java API to launch validation" do
+ ComplianceControlSetCopyWorker.new.perform(control_set_id, referential_id)
+
+ expect(stub_validation_request).to have_been_requested
+ end
+end
diff --git a/spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb b/spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb
index 5e34b208a..47626f5a1 100644
--- a/spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb
+++ b/spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb
@@ -1,6 +1,5 @@
RSpec.describe WorkbenchImportWorker do
-
shared_examples_for 'corrupt zipfile data' do
subject { described_class.new }
let( :workbench_import ){ create :workbench_import, status: :pending }
@@ -23,7 +22,7 @@ RSpec.describe WorkbenchImportWorker do
message = workbench_import.messages.last
expect( message.criticity ).to eq('error')
expect( message.message_key ).to eq('corrupt_zip_file')
- expect( message.message_attributes ).to eq( 'import_name' => workbench_import.name )
+ expect( message.message_attributes ).to eq( 'source_filename' => workbench_import.file.file.file )
end
it 'does not change current step' do
diff --git a/spec/workers/workbench_import/workbench_import_worker_spec.rb b/spec/workers/workbench_import/workbench_import_worker_spec.rb
index deaa1e3a5..47ca2b4ff 100644
--- a/spec/workers/workbench_import/workbench_import_worker_spec.rb
+++ b/spec/workers/workbench_import/workbench_import_worker_spec.rb
@@ -115,8 +115,8 @@ RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do
let( :spurious ){ [spurious1, spurious2] }
let( :messages ){ double('messages') }
let( :message_attributes ){{criticity: :warning, message_key: 'inconsistent_zip_file'}}
- let( :message1_attributes ){ message_attributes.merge(message_attributes: {'import_name' => import.name, 'spurious_dirs' => spurious1.join(', ')}) }
- let( :message2_attributes ){ message_attributes.merge(message_attributes: {'import_name' => import.name, 'spurious_dirs' => spurious2.join(', ')}) }
+ let( :message1_attributes ){ message_attributes.merge(message_attributes: {'source_filename' => import.file.file.file, 'spurious_dirs' => spurious1.join(', ')}) }
+ let( :message2_attributes ){ message_attributes.merge(message_attributes: {'source_filename' => import.file.file.file, 'spurious_dirs' => spurious2.join(', ')}) }
before do
allow(import).to receive(:messages).and_return(messages)