aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZakaria BOUZIANE2015-04-03 14:03:58 +0200
committerZakaria BOUZIANE2015-04-03 14:03:58 +0200
commit5b8d33f04f8679f1d1c3bf19d84760ca8c7a8269 (patch)
treec5599aab9d2c083fb196fe2a0e931ca16b513014
parentfa7e745459aefd64086869882fcca73f948b46fa (diff)
downloadchouette-core-5b8d33f04f8679f1d1c3bf19d84760ca8c7a8269.tar.bz2
IEV index of imports
-rw-r--r--app/controllers/exports_controller.rb85
-rw-r--r--app/controllers/imports_controller.rb2
-rw-r--r--app/helpers/exports_helper.rb36
-rw-r--r--app/helpers/imports_helper.rb23
-rw-r--r--app/models/export.rb102
-rw-r--r--app/models/export_report.rb113
-rw-r--r--app/models/export_service.rb23
-rw-r--r--app/models/export_task.rb171
-rw-r--r--app/models/export_type.rb7
-rw-r--r--db/migrate/20150319082515_change_collation_for_tag_names.acts_as_taggable_on_engine.rb10
10 files changed, 505 insertions, 67 deletions
diff --git a/app/controllers/exports_controller.rb b/app/controllers/exports_controller.rb
index 941d293ae..0fb66294d 100644
--- a/app/controllers/exports_controller.rb
+++ b/app/controllers/exports_controller.rb
@@ -1,20 +1,91 @@
require 'will_paginate/array'
class ExportsController < ChouetteController
- respond_to :html, :xml, :json
+ defaults :resource_class => Export
+
+ respond_to :xml, :json
+ respond_to :html, :only => [:show, :index, :new, :create, :delete]
respond_to :js, :only => [:show, :index]
belongs_to :referential
- protected
+ #curl -F "file=@corolis.zip;filename=corolis_gtfs.zip" -F "file=@parameters.json;filename=parameters.json" http://localhost:8080/chouette_iev/referentials/corolis/exporter/gtfs
+
+ def index
+ begin
+ index! do
+ build_breadcrumb :index
+ end
+ rescue Ievkit::Error => error
+ logger.error("Iev failure : #{error.message}")
+ flash[:error] = t('iev.failure')
+ redirect_to referential_path(@referential)
+ end
+ end
- def test
- test = IevApi.jobs(@referential.slug, { :action => "exporter" }).map do |export_hash|
- export = Export.new(export_hash)
+ def show
+ begin
+ show! do
+ build_breadcrumb :show
+ end
+ rescue Ievkit::Error => error
+ logger.error("Iev failure : #{error.message}")
+ flash[:error] = t('iev.failure')
+ redirect_to referential_path(@referential)
end
end
- def collection
- @exports ||= test.paginate(:page => params[:page])
+ def new
+ begin
+ new! do
+ puts "OK"
+ end
+ rescue Ievkit::Error => error
+ logger.error("Iev failure : #{error.message}")
+ flash[:error] = t('iev.failure')
+ redirect_to referential_path(@referential)
+ end
+ end
+
+ def create
+ begin
+ create! do
+ puts "OK"
+ end
+ rescue Ievkit::Error => error
+ logger.error("Iev failure : #{error.message}")
+ flash[:error] = t('iev.failure')
+ redirect_to referential_path(@referential)
+ end
end
+ def delete
+ begin
+ delete! do
+ export_service.delete(@export.id)
+ redirect_to referential_exports_path(@referential)
+ end
+ rescue Ievkit::Error => error
+ logger.error("Iev failure : #{error.message}")
+ flash[:error] = t('iev.failure')
+ redirect_to referential_path(@referential)
+ end
+ end
+
+ protected
+
+ def export_service
+ ExportService.new(@referential)
+ end
+
+ def build_resource(attributes = {})
+ @export ||= ExportTask.new
+ end
+
+ def resource
+ @export ||= export_service.find( params[:id] )
+ end
+
+ def collection
+ @exports ||= export_service.all.paginate(:page => params[:page])
+ end
end
diff --git a/app/controllers/imports_controller.rb b/app/controllers/imports_controller.rb
index 927c188e2..e7ff7ff15 100644
--- a/app/controllers/imports_controller.rb
+++ b/app/controllers/imports_controller.rb
@@ -7,7 +7,7 @@ class ImportsController < ChouetteController
respond_to :js, :only => [:show, :index]
belongs_to :referential
- # create => curl -F "file=@Citura_050115_220215_ref.zip;filename=Citura_050115_220215_ref.zip" -F "file=@parameters.json;filename=parameters.json" http://localhost:8080/mobi.chouette.api/referentials/test/importer/neptune
+ # create => curl -F "file=@Citura.zip;filename=Citura.zip" -F "file=@parameters.json;filename=parameters.json" http://localhost:8080/chouette_iev/referentials/test/importer/neptune
# index curl http://localhost:8080/mobi.chouette.api/referentials/test/jobs
# show curl http://localhost:8080/mobi.chouette.api/referentials/test/jobs
diff --git a/app/helpers/exports_helper.rb b/app/helpers/exports_helper.rb
index 9ee5778d6..cb1f42f36 100644
--- a/app/helpers/exports_helper.rb
+++ b/app/helpers/exports_helper.rb
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
module ExportsHelper
-
- def fields_for_export_format(form)
+
+ def fields_for_export_task_format(form)
begin
render :partial => export_partial_name(form), :locals => { :form => form }
rescue ActionView::MissingTemplate
@@ -10,29 +10,27 @@ module ExportsHelper
end
def export_partial_name(form)
- "fields_#{form.object.format.underscore}"
+ "fields_#{form.object.format.underscore}_export"
+ end
+
+ def compliance_icon( export_task)
+ return nil unless export_task.compliance_check_task
+ export_task.compliance_check_task.tap do |cct|
+ if cct.failed? || cct.any_error_severity_failure?
+ return 'icons/link_page_alert.png'
+ else
+ return 'icons/link_page.png'
+ end
+ end
end
def export_progress_bar_tag(export)
-
- if export.canceled? || export.aborted?
- div_class = "progress-bar progress-bar-danger"
- elsif export.scheduled?
- div_class = "progress-bar progress-bar-info"
- elsif export.created?
- div_class = "progress-bar progress-bar-info"
- elsif export.terminated?
- div_class = "progress-bar progress-bar-success"
- else
- div_class = ""
- end
-
+ div_class = ""
content_tag :div, :class => "progress" do
content_tag :div, :class => div_class, role: "progressbar", :'aria-valuenow' => "#{export.percentage_progress}", :'aria-valuemin' => "0", :'aria-valuemax' => "100", :style => "width: #{export.percentage_progress}%;" do
- "#{export.percentage_progress}% " + I18n.t("exports.statuses.#{export.export_status}")
+ "#{export.percentage_progress}% " + I18n.t("export_tasks.statuses.#{export.status}")
end
end
-
end
-
+
end
diff --git a/app/helpers/imports_helper.rb b/app/helpers/imports_helper.rb
index 498d03bf9..2df2de93f 100644
--- a/app/helpers/imports_helper.rb
+++ b/app/helpers/imports_helper.rb
@@ -1,9 +1,7 @@
# -*- coding: utf-8 -*-
module ImportsHelper
-
+
def fields_for_import_task_format(form)
- #partial_name = "fields_#{form.object.format.underscore}_import"
-
begin
render :partial => import_partial_name(form), :locals => { :form => form }
rescue ActionView::MissingTemplate
@@ -14,7 +12,7 @@ module ImportsHelper
def import_partial_name(form)
"fields_#{form.object.format.underscore}_import"
end
-
+
def compliance_icon( import_task)
return nil unless import_task.compliance_check_task
import_task.compliance_check_task.tap do |cct|
@@ -25,27 +23,14 @@ module ImportsHelper
end
end
end
-
+
def import_progress_bar_tag(import)
-
- # if import.canceled? || import.aborted?
- # div_class = "progress-bar progress-bar-danger"
- # elsif import.scheduled?
- # div_class = "progress-bar progress-bar-info"
- # elsif import.created?
- # div_class = "progress-bar progress-bar-info"
- # elsif import.terminated?
- # div_class = "progress-bar progress-bar-success"
- # else
- div_class = ""
- # end
-
+ div_class = ""
content_tag :div, :class => "progress" do
content_tag :div, :class => div_class, role: "progressbar", :'aria-valuenow' => "#{import.percentage_progress}", :'aria-valuemin' => "0", :'aria-valuemax' => "100", :style => "width: #{import.percentage_progress}%;" do
"#{import.percentage_progress}% " + I18n.t("import_tasks.statuses.#{import.status}")
end
end
-
end
end
diff --git a/app/models/export.rb b/app/models/export.rb
index 7ee9704f6..6b60f3df1 100644
--- a/app/models/export.rb
+++ b/app/models/export.rb
@@ -3,53 +3,113 @@ class Export
extend ActiveModel::Naming
include ActiveModel::Model
- enumerize :export_status, in: %w{created scheduled terminated canceled aborted}, default: "created", predicates: true
- enumerize :export_format, in: %w{neptune netex gtfs hub kml}, default: "neptune", predicates: true
-
attr_reader :datas
- def initialize(options=Hashie::Mash.new)
- @datas = options
- @export_status = @datas.status.downcase if @datas.status
- @export_format = @datas.type.downcase if @datas.type
+ def initialize(response)
+ @datas = response
+ end
+
+ def report
+ report_path = datas.links[:report]
+ if report_path
+ response = IevApi.request(:get, compliance_check_path, params)
+ ExportReport.new(response)
+ else
+ raise IevApi::IevError("Impossible to access report path link for import")
+ end
+ end
+
+ def compliance_check
+ compliance_check_path = datas.links[:validation]
+ if compliance_check_path
+ response = IevApi.request(:get, compliance_check_path, params)
+ ComplianceCheck.new(response)
+ else
+ raise IevApi::IevError("Impossible to access compliance check path link for import")
+ end
+ end
+
+ def delete
+ delete_path = datas.links[:delete]
+ if delete_path
+ IevApi.request(:delete, delete_path, params)
+ else
+ raise IevApi::IevError("Impossible to access delete path link for import")
+ end
+ end
+
+ def cancel
+ cancel_path = datas.links[:cancel]
+ if cancel_path
+ IevApi.request(:delete, cancel_path, params)
+ else
+ raise IevApi::IevError("Impossible to access cancel path link for import")
+ end
+ end
+
+ def id
+ datas.id
+ end
+
+ def status
+ datas.status
+ end
+
+ def format
+ datas.format
end
+ def filename
+ datas.filename
+ end
+
+ def filename_extension
+ File.extname(filename) if filename
+ end
+
def percentage_progress
- if %w{created}.include? export_status
+ if %w{created}.include? status
0
- elsif %w{ terminated canceled aborted }.include? export_status
+ elsif %w{ terminated canceled aborted }.include? status
100
else
20
end
end
-
- def links
- @datas.links
+
+ def referential_name
+ datas.referential
end
-
+
def name
- @datas.parameters.name
+ datas.action_parameters.name
end
-
+
def user_name
- @datas.parameters.user_name
+ datas.action_parameters.user_name
end
def no_save
- @datas.parameters.no_save
+ datas.action_parameters.no_save
end
def filename
- @datas.filename
+ datas.filename
end
+ def created_at?
+ datas.created?
+ end
+
def created_at
- Time.at(@datas.created.to_i / 1000)
+ Time.at(datas.created.to_i / 1000) if created_at?
end
+ def updated_at?
+ datas.updated?
+ end
+
def updated_at
- Time.at(@datas.updated.to_i / 1000)
+ Time.at(datas.updated.to_i / 1000) if updated_at?
end
-
end
diff --git a/app/models/export_report.rb b/app/models/export_report.rb
new file mode 100644
index 000000000..1bbf1bd6a
--- /dev/null
+++ b/app/models/export_report.rb
@@ -0,0 +1,113 @@
+class ExportReport
+ extend ActiveModel::Naming
+ include ActiveModel::Model
+
+ attr_reader :datas, :errors, :metadatas
+
+ def initialize( response )
+ @datas = response.datas
+ @errors = response.errors
+ @metadatas = response.metadatas
+ end
+
+ def zip_file
+ datas.zip_file
+ end
+
+ def error_files
+ datas.files.select{ |file| file[:status] == "ERROR"}
+ end
+
+ def ignored_files
+ datas.files.select{ |file| file[:status] == "IGNORED"}
+ end
+
+ def ok_files
+ datas.files.select{ |file| file[:status] == "OK"}
+ end
+
+ def files
+ datas.files
+ end
+
+ def line_items
+ [].tap do |line_items|
+ datas.lines.each do |line|
+ line_items << LineItem.new(line)
+ end
+ end
+ end
+
+ def lines
+ datas.stats.line_count if datas.stats_.line_count?
+ end
+
+ def routes
+ datas.stats.route_count if datas.stats_.route_count?
+ end
+
+ def connection_links
+ datas.stats.connection_link_count if datas.stats_.connection_link_count?
+ end
+
+ def time_tables
+ datas.stats.time_table_count if datas.stats_.time_table_count?
+ end
+
+ def stop_areas
+ datas.stats.stop_area_count if datas.stats_.stop_area_count?
+ end
+
+ def access_points
+ datas.stats.access_point_count if datas.stats_.access_point_count?
+ end
+
+ def vehicle_journeys
+ datas.stats.vehicle_journey_count if datas.stats_.vehicle_journey_count?
+ end
+
+ def journey_patterns
+ datas.stats.journey_pattern_count if datas.stats_.journey_pattern_count?
+ end
+
+ class LineItem
+ attr_reader :name, :status, :stats
+
+ def initialize( options = Hashie::Mash.new )
+ @name = options.name if options.name?
+ @status = options.status if options.status?
+ @stats = options.stats if options.stats?
+ end
+
+ def routes
+ stats.route_count
+ end
+
+ def connection_links
+ stats.connection_link_count
+ end
+
+ def time_tables
+ stats.time_table_count
+ end
+
+ def stop_areas
+ stats.stop_area_count
+ end
+
+ def access_points
+ stats.access_point_count
+ end
+
+ def vehicle_journeys
+ stats.vehicle_journey_count
+ end
+
+ def journey_patterns
+ stats.journey_pattern_count
+ end
+
+ end
+
+end
+
diff --git a/app/models/export_service.rb b/app/models/export_service.rb
new file mode 100644
index 000000000..307ec34cd
--- /dev/null
+++ b/app/models/export_service.rb
@@ -0,0 +1,23 @@
+class ExportService
+
+ attr_reader :referential
+
+ def initialize(referential)
+ @referential = referential
+ end
+
+ # Find an export whith his id
+ def find(id)
+ Export.new(IevApi.scheduled_job(referential.slug, id, { :action => "exporter" }))
+ end
+
+ # Find all exports
+ def all
+ [].tap do |jobs|
+ Ievkit.jobs(referential.slug, { :action => "exporter" }).each do |job|
+ jobs << Export.new( job )
+ end
+ end
+ end
+
+end
diff --git a/app/models/export_task.rb b/app/models/export_task.rb
new file mode 100644
index 000000000..09c0aeef4
--- /dev/null
+++ b/app/models/export_task.rb
@@ -0,0 +1,171 @@
+class ExportTask < ActiveRecord::Base
+ attr_accessor :resources, :rule_parameter_set_id
+
+ belongs_to :referential
+
+ has_one :user
+ has_one :compliance_check_task, :dependent => :delete
+
+ serialize :parameter_set, JSON
+ serialize :result, JSON
+
+ validates_presence_of :referential_id
+ validates_presence_of :resources
+ validates_presence_of :user_id
+ validates_presence_of :user_name
+ validates_inclusion_of :status, :in => %w{ pending processing completed failed }
+
+ def references_types
+ []
+ end
+
+ protected
+
+ def self.option(name, type=nil)
+ name = name.to_s
+
+ define_method(name) do
+ self.parameter_set and self.parameter_set[name]
+ end
+
+ if type.to_s == "boolean"
+ define_method("#{name}=") do |prefix|
+ (self.parameter_set ||= {})[name] = (prefix=="1" || prefix==true)
+ end
+ else
+ define_method("#{name}=") do |prefix|
+ (self.parameter_set ||= {})[name] = prefix
+ end
+ end
+ end
+
+ public
+
+ def self.formats
+ %w{Neptune Csv Gtfs Netex Hub}
+ end
+
+ def self.format_label(format)
+ I18n.t 'exchange.format.'+format.downcase
+ end
+
+ def delayed_export
+ delay.export
+ end
+
+ def save_requested?
+ !parameter_set["no_save"]
+ end
+
+ protected
+
+ option :no_save, :boolean
+ option :format
+ option :file_path
+ option :references_type
+
+ validates_inclusion_of :no_save, :in => [ true, false]
+ validates_inclusion_of :format, :in => self.formats
+
+ def chouette_command
+ Chouette::Command.new(:schema => referential.slug)
+ end
+
+ before_validation :define_default_attributes, :on => :create
+ def define_default_attributes
+ self.status ||= "pending"
+ end
+
+ @@root = "#{Rails.root}/tmp/exports"
+ cattr_accessor :root
+
+ def compliance_check_task_attributes
+ {:referential_id => referential.id,
+ :user_id => user_id,
+ :user_name => user_name,
+ :rule_parameter_set_id => rule_parameter_set_id}
+ end
+
+ after_create :update_info, :save_resources
+ def update_info
+ self.file_path = saved_resources
+ self.update_attribute :parameter_set, self.parameter_set
+
+ self.create_compliance_check_task( self.compliance_check_task_attributes)
+ end
+
+ def save_resources
+ FileUtils.mkdir_p root
+ FileUtils.cp resources.path, saved_resources
+ end
+
+ after_destroy :destroy_resources
+ def destroy_resources
+ FileUtils.rm file_path if File.exists? file_path
+ end
+
+ def saved_resources
+ raise Exception.new("Illegal call") if self.new_record?
+ "#{root}/#{id}#{File.extname(resources.original_filename)}"
+ end
+
+ def chouette_command_args
+ {:c => "export", :id => id}
+ end
+
+ public
+
+ def failed?
+ status == "failed"
+ end
+
+ def completed?
+ status == "completed"
+ end
+
+ def file_path_extension
+ extension = File.extname( self.file_path )
+ if extension == ".xml"
+ "xml"
+ elsif extension == ".zip"
+ "zip"
+ else
+ "basic"
+ end
+ end
+
+ def name
+ "#{ExportTask.model_name.human} #{self.format} #{self.id}"
+ end
+
+ def full_name
+ return name unless no_save
+ "#{name} - #{I18n.t('activerecord.attributes.export_task.no_save')}"
+ end
+
+ # Create ExportTask and ComplianceCheckTask associated and give export id to Chouette Loader
+ def export
+ return nil if self.new_record?
+ begin
+ chouette_command.run! chouette_command_args
+ reload
+ update_attribute :status, "completed"
+ compliance_check_task.update_attribute :status, "completed"
+ rescue => e
+ Rails.logger.error "Export #{id} failed : #{e}, #{e.backtrace}"
+ reload
+ update_attribute :status, "failed"
+ compliance_check_task.update_attribute :status, "failed"
+ end
+ end
+
+ def self.new(attributes = {}, parameter_set = {}, &block)
+ if self == ExportTask
+ attributes[:format] = "Neptune" unless attributes[:format]
+ Object.const_get( attributes[:format] + "Export").new(attributes, parameter_set)
+ else
+ super
+ end
+ end
+
+end
diff --git a/app/models/export_type.rb b/app/models/export_type.rb
new file mode 100644
index 000000000..69b0e2367
--- /dev/null
+++ b/app/models/export_type.rb
@@ -0,0 +1,7 @@
+class ExportType < ActiveEnum::Base
+ value :id => 'Neptune', :name => 'Neptune'
+ value :id => 'Csv', :name => 'Csv'
+ value :id => 'Gtfs', :name => 'GTFS'
+ value :id => 'Netex', :name => 'NeTEx'
+ value :id => 'Hub', :name => 'HUB'
+end
diff --git a/db/migrate/20150319082515_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/db/migrate/20150319082515_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
new file mode 100644
index 000000000..bfb06bc7c
--- /dev/null
+++ b/db/migrate/20150319082515_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
@@ -0,0 +1,10 @@
+# This migration comes from acts_as_taggable_on_engine (originally 5)
+# This migration is added to circumvent issue #623 and have special characters
+# work properly
+class ChangeCollationForTagNames < ActiveRecord::Migration
+ def up
+ if ActsAsTaggableOn::Utils.using_mysql?
+ execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;")
+ end
+ end
+end