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 | 
