aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZog2018-02-26 09:58:16 +0100
committerAlban Peignier2018-03-14 15:03:03 +0100
commit8baaa7947ea1e229f67149d221dea76450f040a5 (patch)
treef70abb8951d0f682342452d66c2eca854c2651f6
parent1457744f19109a402f76b7d1aafcb1709e38f877 (diff)
downloadchouette-core-8baaa7947ea1e229f67149d221dea76450f040a5.tar.bz2
Refs #5972 @1h; Automatic registration_number generation
-rw-r--r--app/assets/javascripts/forms.coffee2
-rw-r--r--app/helpers/stop_areas_helper.rb16
-rw-r--r--app/models/chouette/stop_area.rb21
-rw-r--r--app/models/stop_area_referential.rb28
-rw-r--r--app/views/stop_areas/_form.html.slim2
-rw-r--r--config/locales/stop_areas.en.yml5
-rw-r--r--config/locales/stop_areas.fr.yml5
-rw-r--r--db/migrate/20180226074739_add_registration_number_format_to_stop_area_referentials.rb5
-rw-r--r--db/schema.rb2
-rw-r--r--spec/models/chouette/stop_area_spec.rb76
-rw-r--r--spec/models/stop_area_referential_spec.rb5
11 files changed, 164 insertions, 3 deletions
diff --git a/app/assets/javascripts/forms.coffee b/app/assets/javascripts/forms.coffee
index b7ae3c6ca..9543220d0 100644
--- a/app/assets/javascripts/forms.coffee
+++ b/app/assets/javascripts/forms.coffee
@@ -25,7 +25,7 @@ isEdge = !isIE && !!window.StyleMedia
if $('.page-action').children('.formSubmitr').length > 0
$('.page-action').children('.formSubmitr').remove()
- $('.formSubmitr').appendTo('.page-action')
+ $('.formSubmitr').appendTo('.page-action').addClass('sticky-action')
if isIE || isEdge
$('.formSubmitr').off()
diff --git a/app/helpers/stop_areas_helper.rb b/app/helpers/stop_areas_helper.rb
index 05ae042f5..fa99f1b4c 100644
--- a/app/helpers/stop_areas_helper.rb
+++ b/app/helpers/stop_areas_helper.rb
@@ -54,4 +54,20 @@ module StopAreasHelper
end
end
+ def stop_area_registration_number_title stop_area
+ if stop_area&.stop_area_referential&.registration_number_format.present?
+ return t("formtastic.titles.stop_area.registration_number_format", registration_number_format: stop_area.stop_area_referential.registration_number_format)
+ end
+ t "formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.registration_number"
+ end
+
+ def stop_area_registration_number_is_required stop_area
+ val = format_restriction_for_locales(@referential) == '.hub'
+ val ||= stop_area&.stop_area_referential&.registration_number_format.present?
+ val
+ end
+
+ def stop_area_registration_number_value stop_area
+ stop_area&.registration_number || stop_area&.stop_area_referential&.generate_registration_number
+ end
end
diff --git a/app/models/chouette/stop_area.rb b/app/models/chouette/stop_area.rb
index f58f97eee..0a27b2f39 100644
--- a/app/models/chouette/stop_area.rb
+++ b/app/models/chouette/stop_area.rb
@@ -46,6 +46,11 @@ module Chouette
validates_numericality_of :waiting_time, greater_than_or_equal_to: 0, only_integer: true, if: :waiting_time
validate :parent_area_type_must_be_greater
validate :area_type_of_right_kind
+ validate :registration_number_is_set
+
+ before_validation do
+ self.registration_number ||= self.stop_area_referential.generate_registration_number
+ end
def self.nullable_attributes
[:registration_number, :street_name, :country_code, :fare_code,
@@ -73,6 +78,22 @@ module Chouette
end
end
+ def registration_number_is_set
+ return unless self.stop_area_referential.registration_number_format.present?
+ if self.stop_area_referential.stop_areas.where(registration_number: self.registration_number).\
+ where.not(id: self.id).exists?
+ errors.add(:registration_number, I18n.t('stop_areas.errors.registration_number.already_taken'))
+ end
+
+ unless self.registration_number.present?
+ errors.add(:registration_number, I18n.t('stop_areas.errors.registration_number.cannot_be_empty'))
+ end
+
+ unless self.stop_area_referential.validates_registration_number(self.registration_number)
+ errors.add(:registration_number, I18n.t('stop_areas.errors.registration_number.invalid'))
+ end
+ end
+
after_update :clean_invalid_access_links
before_save :coordinates_to_lat_lng
diff --git a/app/models/stop_area_referential.rb b/app/models/stop_area_referential.rb
index 54e895cd0..ab416fd30 100644
--- a/app/models/stop_area_referential.rb
+++ b/app/models/stop_area_referential.rb
@@ -1,4 +1,6 @@
class StopAreaReferential < ActiveRecord::Base
+ validates :registration_number_format, format: { with: /\AX*\z/ }
+
include ObjectidFormatterSupport
has_many :stop_area_referential_memberships
has_many :organisations, through: :stop_area_referential_memberships
@@ -15,4 +17,30 @@ class StopAreaReferential < ActiveRecord::Base
def last_sync
stop_area_referential_syncs.last
end
+
+ def generate_registration_number
+ return "" unless registration_number_format.present?
+ last = self.stop_areas.order("registration_number DESC NULLS LAST").limit(1).first&.registration_number
+ if self.stop_areas.count == 26**self.registration_number_format.size
+ raise "NO MORE AVAILABLE VALUES FOR registration_number in referential #{self.name}"
+ end
+
+ return "A" * self.registration_number_format.size unless last
+
+ if last == "Z" * self.registration_number_format.size
+ val = "AAA"
+ while self.stop_areas.where(registration_number: val).exists?
+ val = val.next
+ end
+ val
+ else
+ last.next
+ end
+ end
+
+ def validates_registration_number value
+ return false unless value.size == registration_number_format.size
+ return false unless value =~ /^[A-Z]*$/
+ true
+ end
end
diff --git a/app/views/stop_areas/_form.html.slim b/app/views/stop_areas/_form.html.slim
index bb1fbe1e9..c63e95c89 100644
--- a/app/views/stop_areas/_form.html.slim
+++ b/app/views/stop_areas/_form.html.slim
@@ -48,7 +48,7 @@
- if has_feature?(:stop_area_waiting_time)
= f.input :waiting_time, input_html: { min: 0 }
- = f.input :registration_number, required: format_restriction_for_locales(@referential) == '.hub', :input_html => {:title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.registration_number")}
+ = f.input :registration_number, required: stop_area_registration_number_is_required(f.object), :input_html => {title: stop_area_registration_number_title(f.object), value: stop_area_registration_number_value(f.object)}
= f.input :fare_code
= f.input :nearest_topic_name, :input_html => {:title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.nearest_topic_name")}
= f.input :comment, as: :text, :input_html => {:rows => 5, :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.comment")}
diff --git a/config/locales/stop_areas.en.yml b/config/locales/stop_areas.en.yml
index ac3dce280..33722b60b 100644
--- a/config/locales/stop_areas.en.yml
+++ b/config/locales/stop_areas.en.yml
@@ -5,6 +5,10 @@ en:
errors:
empty: Aucun stop_area_id
parent_area_type: can not be of type %{area_type}
+ registration_number:
+ already_taken: Already taken
+ cannot_be_empty: This field is mandatory
+ invalid: Incorrect value
default_geometry_success: "%{count} modified stop areas"
stop_area:
no_position: "No Position"
@@ -148,6 +152,7 @@ en:
stop_area:
name: ""
registration_number: "only alphanumerical or underscore characters"
+ registration_number_format: "authorized format : %{registration_number_format}"
objectid: "[prefix]:StopArea:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
nearest_topic_name: ""
city_name: ""
diff --git a/config/locales/stop_areas.fr.yml b/config/locales/stop_areas.fr.yml
index f75c4ebe7..605e6158e 100644
--- a/config/locales/stop_areas.fr.yml
+++ b/config/locales/stop_areas.fr.yml
@@ -6,6 +6,10 @@ fr:
empty: Aucun stop_area_id
parent_area_type: ne peut être de type %{area_type}
incorrect_kind_area_type: Ce type d'arrêt est invalide pour cette catégorie
+ registration_number:
+ already_taken: Déjà utilisé
+ cannot_be_empty: Ce champ est requis
+ invalid: Valeur invalide
default_geometry_success: "%{count} arrêts édités"
stop_area:
no_position: "Pas de position"
@@ -150,6 +154,7 @@ fr:
stop_area:
name: ""
registration_number: "caractères autorisés : alphanumériques et 'souligné'"
+ registration_number_format: "format autorisé: %{registration_number_format}"
objectid: "[prefixe]:StopArea:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
nearest_topic_name: ""
city_name: ""
diff --git a/db/migrate/20180226074739_add_registration_number_format_to_stop_area_referentials.rb b/db/migrate/20180226074739_add_registration_number_format_to_stop_area_referentials.rb
new file mode 100644
index 000000000..3f4231acb
--- /dev/null
+++ b/db/migrate/20180226074739_add_registration_number_format_to_stop_area_referentials.rb
@@ -0,0 +1,5 @@
+class AddRegistrationNumberFormatToStopAreaReferentials < ActiveRecord::Migration
+ def change
+ add_column :stop_area_referentials, :registration_number_format, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 885f12e24..cf0a32a3b 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -12,7 +12,6 @@
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20180308095116) do
-
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
enable_extension "postgis"
@@ -806,6 +805,7 @@ ActiveRecord::Schema.define(version: 20180308095116) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "objectid_format"
+ t.string "registration_number_format"
end
create_table "stop_areas", id: :bigserial, force: :cascade do |t|
diff --git a/spec/models/chouette/stop_area_spec.rb b/spec/models/chouette/stop_area_spec.rb
index 32ee5a3a6..e35300caf 100644
--- a/spec/models/chouette/stop_area_spec.rb
+++ b/spec/models/chouette/stop_area_spec.rb
@@ -24,6 +24,82 @@ describe Chouette::StopArea, :type => :model do
end
end
+ describe "#registration_number" do
+ let(:registration_number){ nil }
+ let(:registration_number_format){ nil }
+ let(:stop_area_referential){ create :stop_area_referential, registration_number_format: registration_number_format}
+ let(:stop_area){ build :stop_area, stop_area_referential: stop_area_referential, registration_number: registration_number}
+ context "without registration_number_format on the StopAreaReferential" do
+ it "should not generate a registration_number" do
+ stop_area.save!
+ expect(stop_area.registration_number).to_not be_present
+ end
+
+ it "should not validate the registration_number format" do
+ stop_area.registration_number = "1234455"
+ expect(stop_area).to be_valid
+ end
+
+ it "should not validate the registration_number uniqueness" do
+ stop_area.registration_number = "1234455"
+ create :stop_area, stop_area_referential: stop_area_referential, registration_number: stop_area.registration_number
+ expect(stop_area).to be_valid
+ end
+ end
+
+ context "with a registration_number_format on the StopAreaReferential" do
+ let(:registration_number_format){ "XXX" }
+
+ it "should generate a registration_number" do
+ stop_area.save!
+ expect(stop_area.registration_number).to be_present
+ expect(stop_area.registration_number).to match /[A-Z]{3}/
+ end
+
+ context "with a previous stop_area" do
+ it "should generate a registration_number" do
+ create :stop_area, stop_area_referential: stop_area_referential, registration_number: "AAA"
+ stop_area.save!
+ expect(stop_area.registration_number).to be_present
+ expect(stop_area.registration_number).to eq "AAB"
+ end
+
+ it "should generate a registration_number" do
+ create :stop_area, stop_area_referential: stop_area_referential, registration_number: "ZZZ"
+ stop_area.save!
+ expect(stop_area.registration_number).to be_present
+ expect(stop_area.registration_number).to eq "AAA"
+ end
+
+ it "should generate a registration_number" do
+ create :stop_area, stop_area_referential: stop_area_referential, registration_number: "AAA"
+ create :stop_area, stop_area_referential: stop_area_referential, registration_number: "ZZZ"
+ stop_area.save!
+ expect(stop_area.registration_number).to be_present
+ expect(stop_area.registration_number).to eq "AAB"
+ end
+ end
+
+ it "should validate the registration_number format" do
+ stop_area.registration_number = "1234455"
+ expect(stop_area).to_not be_valid
+ stop_area.registration_number = "ABC"
+ expect(stop_area).to be_valid
+ expect{ stop_area.save! }.to_not raise_error
+ end
+
+ it "should validate the registration_number uniqueness" do
+ stop_area.registration_number = "ABC"
+ create :stop_area, stop_area_referential: stop_area_referential, registration_number: stop_area.registration_number
+ expect(stop_area).to_not be_valid
+
+ stop_area.registration_number = "ABD"
+ create :stop_area, registration_number: stop_area.registration_number
+ expect(stop_area).to be_valid
+ end
+ end
+ end
+
# describe ".latitude" do
# it "should accept -90 value" do
# subject = create :stop_area, :area_type => "BoardingPosition"
diff --git a/spec/models/stop_area_referential_spec.rb b/spec/models/stop_area_referential_spec.rb
index dd2bdce20..d68b5b809 100644
--- a/spec/models/stop_area_referential_spec.rb
+++ b/spec/models/stop_area_referential_spec.rb
@@ -8,4 +8,9 @@ RSpec.describe StopAreaReferential, :type => :model do
it { is_expected.to have_many(:stop_area_referential_syncs) }
it { is_expected.to have_many(:workbenches) }
it { should validate_presence_of(:objectid_format) }
+ it { should allow_value('').for(:registration_number_format) }
+ it { should allow_value('X').for(:registration_number_format) }
+ it { should allow_value('XXXXX').for(:registration_number_format) }
+ it { should_not allow_value('123').for(:registration_number_format) }
+ it { should_not allow_value('ABC').for(:registration_number_format) }
end