diff options
| author | Zog | 2018-02-26 09:58:16 +0100 |
|---|---|---|
| committer | Alban Peignier | 2018-03-14 15:03:03 +0100 |
| commit | 8baaa7947ea1e229f67149d221dea76450f040a5 (patch) | |
| tree | f70abb8951d0f682342452d66c2eca854c2651f6 | |
| parent | 1457744f19109a402f76b7d1aafcb1709e38f877 (diff) | |
| download | chouette-core-8baaa7947ea1e229f67149d221dea76450f040a5.tar.bz2 | |
Refs #5972 @1h; Automatic registration_number generation
| -rw-r--r-- | app/assets/javascripts/forms.coffee | 2 | ||||
| -rw-r--r-- | app/helpers/stop_areas_helper.rb | 16 | ||||
| -rw-r--r-- | app/models/chouette/stop_area.rb | 21 | ||||
| -rw-r--r-- | app/models/stop_area_referential.rb | 28 | ||||
| -rw-r--r-- | app/views/stop_areas/_form.html.slim | 2 | ||||
| -rw-r--r-- | config/locales/stop_areas.en.yml | 5 | ||||
| -rw-r--r-- | config/locales/stop_areas.fr.yml | 5 | ||||
| -rw-r--r-- | db/migrate/20180226074739_add_registration_number_format_to_stop_area_referentials.rb | 5 | ||||
| -rw-r--r-- | db/schema.rb | 2 | ||||
| -rw-r--r-- | spec/models/chouette/stop_area_spec.rb | 76 | ||||
| -rw-r--r-- | spec/models/stop_area_referential_spec.rb | 5 |
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 |
