diff --git a/.circleci/config.yml b/.circleci/config.yml index b28ae8fe2..a7d5edd1e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -116,6 +116,9 @@ jobs: eval $COMMAND - store_test_results: path: ~/test_results + - store_artifacts: + path: tmp/capybara + destination: screenshots lint: <<: *defaults steps: diff --git a/.rubocop.yml b/.rubocop.yml index 3c9ae87c8..0be36f46e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,9 @@ require: - rubocop/rspec/focused - ./lib/cops/unscoped.rb +inherit_gem: + rubocop-rails_config: + - config/rails.yml AllCops: Exclude: @@ -30,13 +33,13 @@ Gemspec/RequiredRubyVersion: Layout/AccessModifierIndentation: Enabled: true -Layout/AlignArray: +Layout/ArrayAlignment: Enabled: true -Layout/AlignHash: +Layout/HashAlignment: Enabled: false -Layout/AlignParameters: +Layout/ParameterAlignment: Enabled: true EnforcedStyle: with_fixed_indentation @@ -89,6 +92,7 @@ Layout/EmptyLineAfterGuardClause: # FIXME: private should not be a column name on TypeDeChamp Layout/EmptyLinesAroundAccessModifier: Enabled: true + EnforcedStyle: around Exclude: - "spec/factories/type_de_champ.rb" @@ -141,22 +145,23 @@ Layout/FirstMethodParameterLineBreak: Layout/FirstParameterIndentation: Enabled: true -Layout/IndentArray: +Layout/FirstArrayElementIndentation: Enabled: true EnforcedStyle: consistent -Layout/IndentAssignment: +Layout/AssignmentIndentation: Enabled: true -Layout/IndentHash: +Layout/FirstHashElementIndentation: Enabled: true EnforcedStyle: consistent -Layout/IndentHeredoc: +Layout/HeredocIndentation: Enabled: true Layout/IndentationConsistency: Enabled: true + EnforcedStyle: normal Layout/IndentationWidth: Enabled: true @@ -275,7 +280,7 @@ Layout/SpaceInsideStringInterpolation: Layout/Tab: Enabled: true -Layout/TrailingBlankLines: +Layout/TrailingEmptyLines: Enabled: true Layout/TrailingWhitespace: @@ -314,7 +319,7 @@ Lint/DuplicateCaseCondition: Lint/DuplicateMethods: Enabled: true -Lint/DuplicatedKey: +Lint/DuplicateHashKey: Enabled: true Lint/EachWithObjectArgument: @@ -347,7 +352,7 @@ Lint/FloatOutOfRange: Lint/FormatParameterMismatch: Enabled: true -Lint/HandleExceptions: +Lint/SuppressedException: Enabled: false Lint/ImplicitStringConcatenation: @@ -374,7 +379,7 @@ Lint/Loop: Lint/MissingCopEnableDirective: Enabled: true -Lint/MultipleCompare: +Lint/MultipleComparison: Enabled: true Lint/NestedMethodDefinition: @@ -445,7 +450,7 @@ Lint/ShadowedException: Lint/ShadowingOuterLocalVariable: Enabled: false -Lint/StringConversionInInterpolation: +Lint/RedundantStringCoercion: Enabled: true Lint/Syntax: @@ -457,16 +462,16 @@ Lint/UnderscorePrefixedVariableName: Lint/UnifiedInteger: Enabled: true -Lint/UnneededCopDisableDirective: +Lint/RedundantCopDisableDirective: Enabled: true -Lint/UnneededCopEnableDirective: +Lint/RedundantCopEnableDirective: Enabled: true -Lint/UnneededRequireStatement: +Lint/RedundantRequireStatement: Enabled: true -Lint/UnneededSplatExpansion: +Lint/RedundantSplatExpansion: Enabled: false Lint/UnreachableCode: @@ -519,7 +524,7 @@ Metrics/ClassLength: Metrics/CyclomaticComplexity: Enabled: false -Metrics/LineLength: +Layout/LineLength: Enabled: false Metrics/MethodLength: @@ -567,10 +572,10 @@ Naming/MethodName: Naming/PredicateName: Enabled: false -Naming/UncommunicativeBlockParamName: +Naming/BlockParameterName: Enabled: true -Naming/UncommunicativeMethodParamName: +Naming/MethodParameterName: Enabled: false Naming/VariableName: @@ -593,6 +598,8 @@ Performance/CompareWithBlock: Performance/Count: Enabled: true + Exclude: + - "app/services/administrateur_usage_statistics_service.rb" Performance/Detect: Enabled: true @@ -609,9 +616,6 @@ Performance/FixedSize: Performance/FlatMap: Enabled: true -Performance/LstripRstrip: - Enabled: true - Performance/RangeInclude: Enabled: true @@ -624,7 +628,7 @@ Performance/RedundantMatch: Performance/RedundantMerge: Enabled: true -Performance/RedundantSortBy: +Style/RedundantSortBy: Enabled: true Performance/RegexpMatch: @@ -633,7 +637,7 @@ Performance/RegexpMatch: Performance/ReverseEach: Enabled: true -Performance/Sample: +Style/Sample: Enabled: true Performance/Size: @@ -669,6 +673,12 @@ Rails/ApplicationJob: Rails/ApplicationRecord: Enabled: true +Rails/ApplicationController: + Enabled: false + +Rails/RakeEnvironment: + Enabled: false + Rails/Blank: Enabled: true @@ -707,7 +717,7 @@ Rails/Exit: Enabled: true Rails/FilePath: - Enabled: true + Enabled: false Rails/FindBy: Enabled: true @@ -754,6 +764,9 @@ Rails/Present: Rails/ReadWriteAttribute: Enabled: false +Rails/RedundantAllowNil: + Enabled: false + Rails/RedundantReceiverInWithOptions: Enabled: true @@ -766,9 +779,6 @@ Rails/RequestReferer: Rails/ReversibleMigration: Enabled: false -Rails/SafeNavigation: - Enabled: true - Rails/SaveBang: Enabled: false @@ -846,9 +856,6 @@ Style/BlockDelimiters: Exclude: - "spec/**/*" -Style/BracesAroundHashParameters: - Enabled: false - Style/CaseEquality: Enabled: true @@ -955,9 +962,6 @@ Style/EvenOdd: Style/ExpandPathArguments: Enabled: true -Style/FlipFlop: - Enabled: true - Style/For: Enabled: true @@ -965,7 +969,7 @@ Style/FormatString: Enabled: true Style/FormatStringToken: - Enabled: true + Enabled: false EnforcedStyle: template Style/FrozenStringLiteralComment: @@ -1267,13 +1271,13 @@ Style/TrivialAccessors: Style/UnlessElse: Enabled: true -Style/UnneededCapitalW: +Style/RedundantCapitalW: Enabled: true -Style/UnneededInterpolation: +Style/RedundantInterpolation: Enabled: true -Style/UnneededPercentQ: +Style/RedundantPercentQ: Enabled: true Style/VariableInterpolation: diff --git a/Gemfile b/Gemfile index 6293849d7..ada4d9e22 100644 --- a/Gemfile +++ b/Gemfile @@ -9,7 +9,6 @@ gem 'activestorage-openstack' gem 'administrate' gem 'after_party' gem 'anchored' -gem 'axlsx', '~> 3.0.0.pre' # https://github.com/randym/axlsx/issues/501#issuecomment-373640365 gem 'bcrypt' gem 'bootstrap-sass', '>= 3.4.1' gem 'bootstrap-wysihtml5-rails', '~> 0.3.3.8' @@ -29,8 +28,6 @@ gem 'dotenv-rails', require: 'dotenv/rails-now' # dotenv should always be loaded gem 'flipper' gem 'flipper-active_record' gem 'flipper-ui' -gem 'fog-openstack' -gem 'font-awesome-rails' gem 'geocoder' gem 'gon' gem 'graphiql-rails' @@ -48,12 +45,10 @@ gem 'mailjet' gem 'omniauth-github' gem 'omniauth-rails_csrf_protection', '~> 0.1' gem 'openid_connect' -gem 'openstack' gem 'pg' gem 'phonelib' -gem 'prawn' # PDF Generation +gem 'prawn-rails' # PDF Generation gem 'prawn-svg' -gem 'prawn_rails' gem 'premailer-rails' gem 'puma' # Use Puma as the app server gem 'pundit' @@ -63,15 +58,14 @@ gem 'rails' gem 'rails-i18n' # Locales par défaut gem 'rake-progressbar', require: false gem 'react-rails' -gem 'rest-client' gem 'rgeo-geojson' gem 'sanitize-url' gem 'sassc-rails' # Use SCSS for stylesheets -gem 'scenic' gem 'sentry-raven' gem 'skylight' gem 'smart_listing' gem 'spreadsheet_architect' +gem 'sprockets', '< 4' gem 'turbolinks' # Turbolinks makes following links in your web application faster gem 'typhoeus' gem 'warden' @@ -103,6 +97,7 @@ group :development do gem 'haml-lint' gem 'letter_opener_web' gem 'rubocop', require: false + gem 'rubocop-rails_config' gem 'rubocop-rspec-focused', require: false gem 'scss_lint', require: false gem 'web-console' @@ -114,7 +109,7 @@ group :development, :test do gem 'graphql-schema_comparator' gem 'mina', git: 'https://github.com/mina-deploy/mina.git', require: false # Deploy gem 'pry-byebug' - gem 'rspec-rails' + gem 'rspec-rails', '~> 4.0.0.beta' gem 'rspec_junit_formatter', require: false gem 'ruby-debug-ide', require: false gem 'simple_xlsx_reader' diff --git a/Gemfile.lock b/Gemfile.lock index da412fd65..224b5f9a5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -78,16 +78,16 @@ GEM tzinfo (~> 1.1) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) - administrate (0.11.0) - actionpack (>= 4.2, < 6.0) - actionview (>= 4.2, < 6.0) - activerecord (>= 4.2, < 6.0) + administrate (0.12.0) + actionpack (>= 4.2) + actionview (>= 4.2) + activerecord (>= 4.2) autoprefixer-rails (>= 6.0) datetime_picker_rails (~> 0.0.7) jquery-rails (>= 4.0) kaminari (>= 1.0) momentjs-rails (~> 2.8) - sass-rails (~> 5.0) + sassc-rails (~> 2.1) selectize-rails (~> 0.6) aes_key_wrap (1.0.1) after_party (1.10.0) @@ -95,16 +95,11 @@ GEM arel (9.0.0) ast (2.4.0) attr_required (1.0.1) - autoprefixer-rails (9.4.4) + autoprefixer-rails (9.7.4) execjs - axlsx (3.0.0.pre) - htmlentities (~> 4.3, >= 4.3.4) - mimemagic (~> 0.3) - nokogiri (~> 1.8, >= 1.8.2) - rubyzip (~> 1.2, >= 1.2.1) - axlsx_styler (0.2.0) + axlsx_styler (1.0.0) activesupport (>= 3.1) - axlsx (>= 2.0, < 4) + caxlsx (>= 2.0.2) babel-source (5.8.35) babel-transpiler (0.7.0) babel-source (>= 4.0, < 6) @@ -118,7 +113,7 @@ GEM bootstrap-wysihtml5-rails (0.3.3.8) railties (>= 3.0) brakeman (4.3.1) - browser (2.5.3) + browser (4.0.0) builder (3.2.4) byebug (10.0.2) capybara (3.29.0) @@ -140,6 +135,11 @@ GEM selenium-webdriver case_transform (0.2) activesupport + caxlsx (3.0.1) + htmlentities (~> 4.3, >= 4.3.4) + mimemagic (~> 0.3) + nokogiri (~> 1.10, >= 1.10.4) + rubyzip (>= 1.3.0, < 3) chartkick (3.3.1) childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) @@ -158,21 +158,21 @@ GEM crack (0.4.3) safe_yaml (~> 1.0.0) crass (1.0.6) - css_parser (1.6.0) + css_parser (1.7.1) addressable curb (0.9.10) daemons (1.3.1) database_cleaner (1.7.0) datetime_picker_rails (0.0.7) momentjs-rails (>= 2.8.1) - deep_cloneable (2.3.2) - activerecord (>= 3.1.0, < 6) + deep_cloneable (3.0.0) + activerecord (>= 3.1.0, < 7) delayed_cron_job (0.7.2) delayed_job (>= 4.1) - delayed_job (4.1.5) - activesupport (>= 3.0, < 5.3) - delayed_job_active_record (4.1.3) - activerecord (>= 3.0, < 5.3) + delayed_job (4.1.8) + activesupport (>= 3.0, < 6.1) + delayed_job_active_record (4.1.4) + activerecord (>= 3.0, < 6.1) delayed_job (>= 3.0, < 5) delayed_job_web (1.4.3) activerecord (> 3.0.0) @@ -193,10 +193,11 @@ GEM activerecord (>= 4.2, < 7) domain_name (0.5.20180417) unf (>= 0.0.5, < 1.0.0) - dotenv (2.5.0) - dotenv-rails (2.5.0) - dotenv (= 2.5.0) - railties (>= 3.2, < 6.0) + dotenv (2.7.5) + dotenv-rails (2.7.5) + dotenv (= 2.7.5) + railties (>= 3.2, < 6.1) + dry-inflector (0.2.0) em-websocket (0.5.1) eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) @@ -233,8 +234,6 @@ GEM fog-core (~> 2.1) fog-json (>= 1.0) ipaddress (>= 0.8) - font-awesome-rails (4.7.0.4) - railties (>= 3.2, < 6.0) formatador (0.2.5) geocoder (1.6.0) globalid (0.4.2) @@ -260,8 +259,8 @@ GEM bundler (>= 1.14) graphql (~> 1.10) thor (>= 0.19, < 2.0) - groupdate (4.1.1) - activesupport (>= 4.2) + groupdate (5.0.0) + activesupport (>= 5) guard (2.15.0) formatador (>= 0.2.4) listen (>= 2.7, < 4.0) @@ -281,21 +280,20 @@ GEM guard (~> 2.1) guard-compat (~> 1.1) rspec (>= 2.99.0, < 4.0) - haml (5.0.4) + haml (5.1.2) temple (>= 0.8.0) tilt haml-lint (0.999.999) haml_lint - haml-rails (1.0.0) - actionpack (>= 4.0.1) - activesupport (>= 4.0.1) + haml-rails (2.0.1) + actionpack (>= 5.1) + activesupport (>= 5.1) haml (>= 4.0.6, < 6.0) html2haml (>= 1.0.1) - railties (>= 4.0.1) - haml_lint (0.28.0) - haml (>= 4.0, < 5.1) + railties (>= 5.1) + haml_lint (0.35.0) + haml (>= 4.0, < 5.2) rainbow - rake (>= 10, < 13) rubocop (>= 0.50.0) sysexits (~> 1.1) hashdiff (0.3.8) @@ -313,12 +311,11 @@ GEM i18n (1.8.2) concurrent-ruby (~> 1.0) ipaddress (0.8.3) - jaro_winkler (1.5.2) - jquery-rails (4.3.3) + jaro_winkler (1.5.4) + jquery-rails (4.3.5) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - json (2.2.0) json-jwt (1.11.0) activesupport (>= 4.2) aes_key_wrap @@ -418,31 +415,31 @@ GEM validate_email validate_url webfinger (>= 1.0.1) - openstack (3.3.21) - json orm_adapter (0.5.0) - parallel (1.12.1) - parser (2.5.3.0) + parallel (1.19.1) + parser (2.7.0.4) ast (~> 2.4.0) pdf-core (0.7.0) pg (1.1.3) phonelib (0.6.39) - powerpack (0.1.2) prawn (2.2.2) pdf-core (~> 0.7.0) ttfunk (~> 1.5) + prawn-rails (1.3.0) + prawn + prawn-table + rails (>= 3.1.0) prawn-svg (0.29.1) css_parser (~> 1.6) prawn (>= 0.11.1, < 3) - prawn_rails (0.0.11) - prawn (>= 0.11.1) - railties (>= 3.0.0) + prawn-table (0.2.2) + prawn (>= 1.3.0, < 3.0.0) premailer (1.11.1) addressable css_parser (>= 1.6.0) htmlentities (>= 4.0.0) - premailer-rails (1.10.2) - actionmailer (>= 3, < 6) + premailer-rails (1.10.3) + actionmailer (>= 3) premailer (~> 1.7, >= 1.7.9) promise.rb (0.7.4) pry (0.12.2) @@ -507,7 +504,7 @@ GEM rake (12.3.3) rake-progressbar (0.0.5) rb-fsevent (0.10.3) - rb-inotify (0.10.0) + rb-inotify (0.10.1) ffi (~> 1.0) react-rails (2.4.7) babel-transpiler (>= 0.7.0) @@ -525,12 +522,13 @@ GEM http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) + rexml (3.2.4) rgeo (2.0.0) rgeo-geojson (2.1.1) rgeo (>= 1.0.0) - rodf (1.0.0) - activesupport (>= 3.0) + rodf (1.1.1) builder (>= 3.0) + dry-inflector (~> 0.1) rubyzip (>= 1.0) rouge (3.16.0) rspec (3.9.0) @@ -545,47 +543,51 @@ GEM rspec-mocks (3.9.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.9.0) - rspec-rails (3.9.0) - actionpack (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-support (~> 3.9.0) + rspec-rails (4.0.0.beta4) + actionpack (>= 4.2) + activesupport (>= 4.2) + railties (>= 4.2) + rspec-core (~> 3.9) + rspec-expectations (~> 3.9) + rspec-mocks (~> 3.9) + rspec-support (~> 3.9) rspec-support (3.9.2) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.62.0) + rubocop (0.80.1) jaro_winkler (~> 1.5.1) parallel (~> 1.10) - parser (>= 2.5, != 2.5.1.1) - powerpack (~> 0.1) + parser (>= 2.7.0.1) rainbow (>= 2.2.2, < 4.0) + rexml ruby-progressbar (~> 1.7) - unicode-display_width (~> 1.4.0) + unicode-display_width (>= 1.4.0, < 1.7) + rubocop-performance (1.5.2) + rubocop (>= 0.71.0) + rubocop-rails (2.4.2) + rack (>= 1.1) + rubocop (>= 0.72.0) + rubocop-rails_config (0.10.0) + railties (>= 5.0) + rubocop (~> 0.80) + rubocop-performance (~> 1.3) + rubocop-rails (~> 2.0) rubocop-rspec-focused (1.0.0) rubocop (>= 0.51) ruby-debug-ide (0.6.1) rake (>= 0.8.1) - ruby-progressbar (1.10.0) + ruby-progressbar (1.10.1) ruby_dep (1.5.0) - ruby_parser (3.12.0) + ruby_parser (3.14.2) sexp_processor (~> 4.9) rubyzip (1.3.0) safe_yaml (1.0.4) sanitize-url (0.1.4) - sass (3.7.3) + sass (3.7.4) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.0.7) - railties (>= 4.0.0, < 6) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) sassc (2.0.0) ffi (~> 1.9.6) rake @@ -595,9 +597,6 @@ GEM sprockets (> 3.0) sprockets-rails tilt - scenic (1.4.1) - activerecord (>= 4.0.0) - railties (>= 4.0.0) scss_lint (0.57.1) rake (>= 0.9, < 13) sass (~> 3.5, >= 3.5.5) @@ -607,7 +606,7 @@ GEM rubyzip (~> 1.2, >= 1.2.2) sentry-raven (2.7.4) faraday (>= 0.7.6, < 1.0) - sexp_processor (4.11.0) + sexp_processor (4.14.1) shellany (0.0.1) shoulda-matchers (4.0.1) activesupport (>= 4.2.0) @@ -628,9 +627,9 @@ GEM jquery-rails kaminari (>= 0.17) rails (>= 3.2) - spreadsheet_architect (3.2.0) - axlsx (>= 2, < 4) - axlsx_styler (>= 0.1.7, < 2) + spreadsheet_architect (4.0.0) + axlsx_styler (>= 1.0.0, < 2) + caxlsx (>= 2.0.2, < 4) rodf (>= 1.0.0, < 2) spring (2.0.2) activesupport (>= 4.2) @@ -648,10 +647,10 @@ GEM attr_required (>= 0.0.5) httpclient (>= 2.4) sysexits (1.2.0) - temple (0.8.0) + temple (0.8.2) thor (1.0.1) thread_safe (0.3.6) - tilt (2.0.9) + tilt (2.0.10) timecop (0.9.1) ttfunk (1.5.1) turbolinks (5.2.0) @@ -664,7 +663,7 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.7.5) - unicode-display_width (1.4.1) + unicode-display_width (1.6.1) validate_email (0.1.6) activemodel (>= 3.0) mail (>= 2.2.5) @@ -721,7 +720,6 @@ DEPENDENCIES administrate after_party anchored - axlsx (~> 3.0.0.pre) bcrypt bootstrap-sass (>= 3.4.1) bootstrap-wysihtml5-rails (~> 0.3.3.8) @@ -749,8 +747,6 @@ DEPENDENCIES flipper flipper-active_record flipper-ui - fog-openstack - font-awesome-rails geocoder gon graphiql-rails @@ -776,12 +772,10 @@ DEPENDENCIES omniauth-github omniauth-rails_csrf_protection (~> 0.1) openid_connect - openstack pg phonelib - prawn + prawn-rails prawn-svg - prawn_rails premailer-rails pry-byebug puma @@ -793,16 +787,15 @@ DEPENDENCIES rails-i18n rake-progressbar react-rails - rest-client rgeo-geojson - rspec-rails + rspec-rails (~> 4.0.0.beta) rspec_junit_formatter rubocop + rubocop-rails_config rubocop-rspec-focused ruby-debug-ide sanitize-url sassc-rails - scenic scss_lint sentry-raven shoulda-matchers @@ -812,6 +805,7 @@ DEPENDENCIES spreadsheet_architect spring spring-commands-rspec + sprockets (< 4) timecop turbolinks typhoeus diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 2f3b5b45e..121de171b 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -34,7 +34,6 @@ // = require_self // = require leaflet -// = require font-awesome // = require franceconnect // = require bootstrap-wysihtml5 diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c192c0f75..5ec259b6f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -198,7 +198,7 @@ class ApplicationController < ActionController::Base # return at this location # after the device is trusted - store_location_for(:user, request.fullpath) + store_location_for(:user, request.fullpath) if get_stored_location_for(:user).blank? send_login_token_or_bufferize(current_instructeur) redirect_to link_sent_path(email: current_instructeur.email) @@ -233,7 +233,7 @@ class ApplicationController < ActionController::Base key: sentry[:client_key], enabled: sentry[:enabled], environment: sentry[:environment], - browser: { modern: browser.modern? }, + browser: { modern: BrowserSupport.supported?(browser) }, user: sentry_user } end diff --git a/app/controllers/champs/carte_controller.rb b/app/controllers/champs/carte_controller.rb index 059c4554f..3fdd88b7b 100644 --- a/app/controllers/champs/carte_controller.rb +++ b/app/controllers/champs/carte_controller.rb @@ -62,7 +62,7 @@ class Champs::CarteController < ApplicationController @champ.save end - rescue RestClient::ResourceNotFound + rescue ApiCarto::API::ResourceNotFound flash.alert = 'Les données cartographiques sont temporairement indisponibles. Réessayez dans un instant.' response.status = 503 end diff --git a/app/controllers/champs/siret_controller.rb b/app/controllers/champs/siret_controller.rb index f78a35fb6..0eabd821e 100644 --- a/app/controllers/champs/siret_controller.rb +++ b/app/controllers/champs/siret_controller.rb @@ -16,7 +16,7 @@ class Champs::SiretController < ApplicationController begin etablissement = find_etablissement_with_siret - rescue RestClient::RequestFailed + rescue ApiEntreprise::API::RequestFailed return siret_error(:network_error) end if etablissement.blank? diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index fea994a0a..9e3934c35 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -58,7 +58,6 @@ class StatsController < ApplicationController .includes(:procedure, :user) .in_batches .flat_map do |dossiers| - dossiers .pluck( "dossiers.id", diff --git a/app/controllers/users/commencer_controller.rb b/app/controllers/users/commencer_controller.rb index a6d4ea649..a5ddcf5fe 100644 --- a/app/controllers/users/commencer_controller.rb +++ b/app/controllers/users/commencer_controller.rb @@ -16,6 +16,20 @@ module Users render 'commencer/show' end + def dossier_vide_pdf + @procedure = retrieve_procedure + return procedure_not_found if @procedure.blank? || @procedure.brouillon? + + generate_empty_pdf(@procedure) + end + + def dossier_vide_pdf_test + @procedure = retrieve_procedure + return procedure_not_found if @procedure.blank? || @procedure.publiee? + + generate_empty_pdf(@procedure) + end + def sign_in @procedure = retrieve_procedure return procedure_not_found if @procedure.blank? @@ -65,5 +79,11 @@ module Users def store_user_location!(procedure) store_location_for(:user, helpers.procedure_lien(procedure)) end + + def generate_empty_pdf(procedure) + @dossier = procedure.new_dossier + s = render_to_string(file: 'dossiers/dossier_vide', formats: [:pdf]) + send_data(s, :filename => "#{procedure.libelle}.pdf") + end end end diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index e66aaf44b..2e70cd862 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -106,7 +106,7 @@ module Users sanitized_siret = siret_model.siret begin etablissement_attributes = ApiEntrepriseService.get_etablissement_params_for_siret(sanitized_siret, @dossier.procedure.id) - rescue RestClient::RequestFailed + rescue ApiEntreprise::API::RequestFailed return render_siret_error(t('errors.messages.siret_network_error')) end if etablissement_attributes.blank? diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 9929ab7f6..e45d95781 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -131,4 +131,12 @@ module ApplicationHelper def has_dismissed_outdated_browser_banner? cookies[:dismissed_outdated_browser_banner] == 'true' end + + def supported_browser? + BrowserSupport.supported?(browser) + end + + def show_outdated_browser_banner? + !supported_browser? && !has_dismissed_outdated_browser_banner? + end end diff --git a/app/helpers/flipper_helper.rb b/app/helpers/flipper_helper.rb index aa81299c5..8f1cf221a 100644 --- a/app/helpers/flipper_helper.rb +++ b/app/helpers/flipper_helper.rb @@ -2,4 +2,8 @@ module FlipperHelper def feature_enabled?(feature_name) Flipper.enabled?(feature_name, current_user) end + + def feature_enabled_for?(feature_name, item) + Flipper.enabled?(feature_name, item) + end end diff --git a/app/lib/api_carto/api.rb b/app/lib/api_carto/api.rb index eadb813f8..865a8b192 100644 --- a/app/lib/api_carto/api.rb +++ b/app/lib/api_carto/api.rb @@ -1,4 +1,7 @@ class ApiCarto::API + class ResourceNotFound < StandardError + end + def self.search_qp(geojson) url = [API_CARTO_URL, "quartiers-prioritaires", "search"].join("/") call(url, geojson) @@ -19,7 +22,7 @@ class ApiCarto::API else message = response.code == 0 ? response.return_message : response.code.to_s Rails.logger.error "[ApiCarto] Error on #{url}: #{message}" - raise RestClient::ResourceNotFound + raise ResourceNotFound end end end diff --git a/app/lib/api_entreprise/adapter.rb b/app/lib/api_entreprise/adapter.rb index 8c4b21de4..4e26e8a1f 100644 --- a/app/lib/api_entreprise/adapter.rb +++ b/app/lib/api_entreprise/adapter.rb @@ -9,7 +9,7 @@ class ApiEntreprise::Adapter def data_source begin @data_source ||= get_resource - rescue RestClient::ResourceNotFound + rescue ApiEntreprise::API::ResourceNotFound @data_source = nil end end diff --git a/app/lib/api_entreprise/api.rb b/app/lib/api_entreprise/api.rb index 818d1e833..af5b6acef 100644 --- a/app/lib/api_entreprise/api.rb +++ b/app/lib/api_entreprise/api.rb @@ -6,6 +6,12 @@ class ApiEntreprise::API TIMEOUT = 15 + class ResourceNotFound < StandardError + end + + class RequestFailed < StandardError + end + def self.entreprise(siren, procedure_id) call(ENTREPRISE_RESOURCE_NAME, siren, procedure_id) end @@ -35,9 +41,9 @@ class ApiEntreprise::API if response.success? JSON.parse(response.body, symbolize_names: true) elsif response.code&.between?(401, 499) - raise RestClient::ResourceNotFound + raise ResourceNotFound else - raise RestClient::RequestFailed + raise RequestFailed end end @@ -56,6 +62,7 @@ class ApiEntreprise::API context: "demarches-simplifiees.fr", recipient: siret_or_siren, object: "procedure_id: #{procedure_id}", + non_diffusables: true, token: token } end diff --git a/app/lib/api_entreprise/etablissement_adapter.rb b/app/lib/api_entreprise/etablissement_adapter.rb index 58f63c689..7e9139957 100644 --- a/app/lib/api_entreprise/etablissement_adapter.rb +++ b/app/lib/api_entreprise/etablissement_adapter.rb @@ -24,7 +24,8 @@ class ApiEntreprise::EtablissementAdapter < ApiEntreprise::Adapter :siret, :siege_social, :naf, - :libelle_naf + :libelle_naf, + :diffusable_commercialement ] end diff --git a/app/lib/pipedrive/api.rb b/app/lib/pipedrive/api.rb index c537a4e50..2c4201e7f 100644 --- a/app/lib/pipedrive/api.rb +++ b/app/lib/pipedrive/api.rb @@ -51,20 +51,29 @@ class Pipedrive::API api_token: token }) - response = RestClient.get(url, params: params) - JSON.parse(response.body)['data'] + response = Typhoeus.get(url, params: params) + + if response.success? + JSON.parse(response.body)['data'] + end end def self.put(url, params) - url = "#{url}?api_token=#{token}" - - RestClient.put(url, params.to_json, { content_type: :json }) + Typhoeus.put( + url, + params: { api_token: token }, + body: params.to_json, + headers: { 'content-type' => 'application/json' } + ) end def self.post(url, params) - url = "#{url}?api_token=#{token}" - - RestClient.post(url, params.to_json, { content_type: :json }) + Typhoeus.post( + url, + params: { api_token: token }, + body: params.to_json, + headers: { 'content-type' => 'application/json' } + ) end def self.token diff --git a/app/models/administrateur.rb b/app/models/administrateur.rb index 3d3e878ef..2f57bf5bc 100644 --- a/app/models/administrateur.rb +++ b/app/models/administrateur.rb @@ -85,6 +85,11 @@ class Administrateur < ApplicationRecord next_administrateur = procedure.administrateurs.where.not(id: self.id).first procedure.service.update(administrateur: next_administrateur) end + + services.each do |service| + service.destroy unless service.procedures.any? + end + destroy end end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index da98331c1..8e3734e5b 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -692,7 +692,6 @@ class Dossier < ApplicationRecord .includes(:procedure, :user) .group_by(&:user) .each do |(user, dossiers)| - dossier_hashes = dossiers.map(&:hash_for_deletion_mail) DossierMailer.notify_brouillon_deletion(user, dossier_hashes).deliver_later diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb index 93289e0da..d580694ae 100644 --- a/app/models/instructeur.rb +++ b/app/models/instructeur.rb @@ -148,11 +148,12 @@ class Instructeur < ApplicationRecord def email_notification_data groupe_instructeur_with_email_notifications .reduce([]) do |acc, groupe| - procedure = groupe.procedure h = { nb_en_construction: groupe.dossiers.en_construction.count, + nb_en_instruction: groupe.dossiers.en_instruction.count, + nb_accepted: groupe.dossiers.accepte.where(processed_at: Time.zone.yesterday.beginning_of_day..Time.zone.yesterday.end_of_day).count, nb_notification: notifications_for_procedure(procedure, :not_archived).count } @@ -162,6 +163,14 @@ class Instructeur < ApplicationRecord acc << h end + [["en_instruction", h[:nb_en_instruction]], ["accepte", h[:nb_accepted]]].each do |state, count| + if procedure.declarative_with_state == state && count > 0 + h[:procedure_id] = procedure.id + h[:procedure_libelle] = procedure.libelle + acc << h + end + end + acc end end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index a27e57b47..807899628 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -496,6 +496,10 @@ class Procedure < ApplicationRecord dossiers.discard_all end + def flipper_id + "Procedure;#{id}" + end + private def move_type_de_champ_attributes(types_de_champ, type_de_champ, new_index) diff --git a/app/services/api_entreprise_service.rb b/app/services/api_entreprise_service.rb index feb687544..32fa8ada7 100644 --- a/app/services/api_entreprise_service.rb +++ b/app/services/api_entreprise_service.rb @@ -4,7 +4,7 @@ class ApiEntrepriseService # Returns nil if the SIRET is unknown; and nested params # suitable for being saved into a Etablissement object otherwise. # - # Raises a RestClient::RequestFailed exception on transcient errors + # Raises a ApiEntreprise::API::RequestFailed exception on transcient errors # (timeout, 5XX HTTP error code, etc.) def self.get_etablissement_params_for_siret(siret, procedure_id) etablissement_params = ApiEntreprise::EtablissementAdapter.new(siret, procedure_id).to_params @@ -14,13 +14,13 @@ class ApiEntrepriseService begin association_params = ApiEntreprise::RNAAdapter.new(siret, procedure_id).to_params etablissement_params.merge!(association_params) - rescue RestClient::RequestFailed + rescue ApiEntreprise::API::RequestFailed end begin exercices_params = ApiEntreprise::ExercicesAdapter.new(siret, procedure_id).to_params etablissement_params.merge!(exercices_params) - rescue RestClient::RequestFailed + rescue ApiEntreprise::API::RequestFailed end etablissement_params.merge(entreprise_params) diff --git a/app/services/browser_support.rb b/app/services/browser_support.rb new file mode 100644 index 000000000..46f5a372d --- /dev/null +++ b/app/services/browser_support.rb @@ -0,0 +1,13 @@ +class BrowserSupport + def self.supported?(browser) + # See .browserslistrc + [ + browser.chrome? && browser.version.to_i >= 50 && !browser.platform.ios?, + browser.edge? && browser.version.to_i >= 14 && !browser.compatibility_view?, + browser.firefox? && browser.version.to_i >= 50 && !browser.platform.ios?, + browser.opera? && browser.version.to_i >= 40, + browser.safari? && browser.version.to_i >= 8, + browser.platform.ios? && browser.platform.version.to_i >= 8 + ].any? + end +end diff --git a/app/views/commencer/show.html.haml b/app/views/commencer/show.html.haml index 661b2b4d2..e37559876 100644 --- a/app/views/commencer/show.html.haml +++ b/app/views/commencer/show.html.haml @@ -40,3 +40,15 @@ %h2.huge-title Vous avez déjà des dossiers pour cette démarche = link_to 'Voir mes dossiers en cours', dossiers_path, class: ['button large expand primary'] = link_to 'Commencer un nouveau dossier', url_for_new_dossier(@procedure), class: ['button large expand'] + + - if feature_enabled_for?(:dossier_pdf_vide, @procedure) + - pdf_link = commencer_dossier_vide_path(path: @procedure.path) + - if @procedure.brouillon? + - pdf_link = commencer_dossier_vide_test_path(path: @procedure.path) + %hr + %p + Vous souhaitez effectuer une demande par papier ? Vous pouvez télécharger un dossier vide au format PDF, + et l'envoyer à l’administration concernée : + #{@procedure&.service&.nom} - #{@procedure&.service&.adresse} + %br + = link_to 'Télécharger un dossier vide au format PDF', pdf_link, class: ['button large expand'] diff --git a/app/views/dossiers/dossier_vide.pdf.prawn b/app/views/dossiers/dossier_vide.pdf.prawn new file mode 100644 index 000000000..fda36b022 --- /dev/null +++ b/app/views/dossiers/dossier_vide.pdf.prawn @@ -0,0 +1,196 @@ +require 'prawn/measurement_extensions' + +def render_in_2_columns(pdf, label, text) + pdf.text_box label, width: 200, height: 100, overflow: :expand, at: [0, pdf.cursor] + pdf.text_box ":", width: 10, height: 100, overflow: :expand, at: [100, pdf.cursor] + pdf.text_box text, width: 420, height: 100, overflow: :expand, at: [110, pdf.cursor] + pdf.text "\n" +end + +def format_in_2_lines(pdf, label, nb_lines = 1) + add_single_line(pdf, label, 12, :bold) + + height = 10 * (nb_lines+1) + pdf.bounding_box([0, pdf.cursor],:width => 460,:height => height) do + pdf.stroke_bounds + end + pdf.text "\n" +end + +def format_in_2_columns(pdf, label) + pdf.text_box label, width: 200, height: 100, overflow: :expand, at: [0, pdf.cursor] + pdf.bounding_box([110, pdf.cursor+5],:width => 350,:height => 20) do + pdf.stroke_bounds + end + + pdf.text "\n" +end + +def format_with_checkbox(pdf, label, offset = 0) + pdf.font 'liberation serif', size: 12 do + pdf.stroke_rectangle [0 + offset, pdf.cursor], 10, 10 + pdf.text_box label, at: [15 + offset, pdf.cursor] + end + pdf.text "\n" +end + +def add_page_numbering(pdf) + # This method should be called at the end of the drawing since pages drawn after + # do not have page numbering + string = ' / ' + options = { + at: [0, -15], + align: :right + } + pdf.number_pages string, options +end + +def add_procedure(pdf, dossier) + pdf.repeat(lambda {|page| page > 1 }) do + pdf.draw_text dossier.procedure.libelle, :at => pdf.bounds.top_left + end +end + +def format_date(date) + I18n.l(date, format: :message_date_with_year) +end + +def add_identite_individual(pdf, dossier) + format_in_2_columns(pdf, "Civilité") + format_in_2_columns(pdf, "Nom") + format_in_2_columns(pdf, "Prénom") + format_in_2_columns(pdf, "Date de naissance") +end + +def add_identite_etablissement(pdf, libelle) + add_single_line(pdf, libelle, 12, :bold) + + format_in_2_columns(pdf, "SIRET") + format_in_2_columns(pdf, "Dénomination") + format_in_2_columns(pdf, "Forme juridique") +end + +def add_single_line(pdf, libelle, size, style) + pdf.font 'liberation serif', style: style, size: size do + pdf.text libelle + end +end + +def add_title(pdf, title) + add_single_line(pdf, title, 24, :bold) + pdf.text "\n" +end + +def add_libelle(pdf, champ) + add_single_line(pdf, champ.libelle, 12, :bold) +end + +def add_explanation(pdf, explanation) + add_single_line(pdf, explanation, 9, :italic) +end + +def render_single_champ(pdf, champ) + case champ.type + when 'Champs::RepetitionChamp' + raise 'There should not be a RepetitionChamp here !' + when 'Champs::PieceJustificativeChamp' + add_single_line(pdf, 'Pièce justificative à joindre', 12, :bold) + pdf.text champ.libelle + pdf.text champ.description + pdf.text "\n" + when 'Champs::YesNoChamp', 'Champs::CheckboxChamp' + add_libelle(pdf, champ) + add_explanation(pdf, 'Cochez la mention applicable') + format_with_checkbox(pdf, 'Oui') + format_with_checkbox(pdf, 'Non') + pdf.text "\n" + when 'Champs::CiviliteChamp' + add_libelle(pdf, champ) + format_with_checkbox(pdf, Individual::GENDER_FEMALE) + format_with_checkbox(pdf, Individual::GENDER_MALE) + pdf.text "\n" + when 'Champs::HeaderSectionChamp' + add_single_line(pdf, champ.libelle, 18, :bold) + pdf.text "\n" + when 'Champs::ExplicationChamp' + add_libelle(pdf, champ) + pdf.text champ.description + pdf.text "\n" + when 'Champs::AddressChamp', 'Champs::CarteChamp', 'Champs::TextareaChamp' + format_in_2_lines(pdf, champ.libelle, 3) + when 'Champs::DropDownListChamp' + add_libelle(pdf, champ) + add_explanation(pdf, 'Cochez la mention applicable, une seule valeur possible') + champ.drop_down_list.options.reject(&:blank?).each do |option| + format_with_checkbox(pdf, option) + end + pdf.text "\n" + when 'Champs::MultipleDropDownListChamp' + add_libelle(pdf, champ) + add_explanation(pdf, 'Cochez la mention applicable, plusieurs valeurs possibles') + champ.drop_down_list.options.reject(&:blank?).each do |option| + format_with_checkbox(pdf, option) + end + pdf.text "\n" + when 'Champs::LinkedDropDownListChamp' + add_libelle(pdf, champ) + champ.primary_options.reject(&:blank?).each do |o| + format_with_checkbox(pdf, o) + champ.secondary_options[o].reject(&:blank?).each do |secondary_option| + format_with_checkbox(pdf, secondary_option, 15) + end + end + pdf.text "\n" + when 'Champs::SiretChamp' + add_identite_etablissement(pdf, champ.libelle) + else + format_in_2_lines(pdf, champ.libelle) + end +end + +def add_champs(pdf, champs) + champs.each do |champ| + if champ.type == 'Champs::RepetitionChamp' + add_libelle(pdf, champ) + (1..3).each do + champ.rows.each do |row| + row.each do |inner_champ| + render_single_champ(pdf, inner_champ) + end + end + end + else + render_single_champ(pdf, champ) + end + end +end + +prawn_document(page_size: "A4") do |pdf| + pdf.font_families.update( 'liberation serif' => { + normal: Rails.root.join('lib/prawn/fonts/liberation_serif/LiberationSerif-Regular.ttf' ), + bold: Rails.root.join('lib/prawn/fonts/liberation_serif/LiberationSerif-Bold.ttf' ), + italic: Rails.root.join('lib/prawn/fonts/liberation_serif/LiberationSerif-Italic.ttf' ), + }) + pdf.font 'liberation serif' + pdf.svg IO.read("app/assets/images/header/logo-ds-wide.svg"), width: 300, position: :center + pdf.move_down(40) + + render_in_2_columns(pdf, 'Démarche', @dossier.procedure.libelle) + render_in_2_columns(pdf, 'Organisme', @dossier.procedure.organisation_name) + pdf.text "\n" + + add_title(pdf, "Identité du demandeur") + + format_in_2_columns(pdf, "Email") + if @dossier.procedure.for_individual? + add_identite_individual(pdf, @dossier) + else + render_identite_etablissement(pdf, @dossier.etablissement) if @dossier.etablissement.present? + end + pdf.text "\n" + + add_title(pdf, 'Formulaire') + add_champs(pdf, @dossier.champs) + add_page_numbering(pdf) + add_procedure(pdf, @dossier) +end diff --git a/app/views/instructeur_mailer/send_notifications.html.haml b/app/views/instructeur_mailer/send_notifications.html.haml index 50f76c55f..04a44c9fe 100644 --- a/app/views/instructeur_mailer/send_notifications.html.haml +++ b/app/views/instructeur_mailer/send_notifications.html.haml @@ -16,5 +16,12 @@ - if datum[:nb_notification] > 0 %br #{datum[:nb_notification]} #{'notification'.pluralize(datum[:nb_notification])} + - if datum[:nb_en_instruction] > 0 + %br + #{datum[:nb_en_instruction]} #{'dossier'.pluralize(datum[:nb_en_instruction])} + - if datum[:nb_accepted] > 0 + %br + #{datum[:nb_accepted]} #{'dossier'.pluralize(datum[:nb_accepted])} + = render partial: "layouts/mailers/signature" diff --git a/app/views/layouts/_outdated_browser_banner.html.haml b/app/views/layouts/_outdated_browser_banner.html.haml index ee39e191d..25a8bcbd8 100644 --- a/app/views/layouts/_outdated_browser_banner.html.haml +++ b/app/views/layouts/_outdated_browser_banner.html.haml @@ -1,5 +1,4 @@ --# See config/browser.rb -- if !browser.modern? && !has_dismissed_outdated_browser_banner? +- if show_outdated_browser_banner? #outdated-browser-banner.site-banner .container .site-banner-icon ⚠️ diff --git a/app/views/new_administrateur/procedures/_informations.html.haml b/app/views/new_administrateur/procedures/_informations.html.haml index 3bd815ca5..9a3385173 100644 --- a/app/views/new_administrateur/procedures/_informations.html.haml +++ b/app/views/new_administrateur/procedures/_informations.html.haml @@ -121,4 +121,4 @@ Par défaut, un dossier déposé peut être complété ou corrigé par le demandeur jusqu'à sa mise en instruction.
Dans une démarche déclarative, une fois déposé, un dossier ne peut plus être modifié. Soit il passe immédiatement « en instruction » pour être traité soit il est immédiatement « accepté ». - = f.select :declarative_with_state, Procedure.declarative_attributes_for_select, { prompt: 'Non' }, class: 'form-control' + = f.select :declarative_with_state, Procedure.declarative_attributes_for_select, { include_blank: 'Non' }, class: 'form-control' diff --git a/app/views/shared/dossiers/_identite_entreprise.html.haml b/app/views/shared/dossiers/_identite_entreprise.html.haml index 9fcd2a0c9..f1d18f84d 100644 --- a/app/views/shared/dossiers/_identite_entreprise.html.haml +++ b/app/views/shared/dossiers/_identite_entreprise.html.haml @@ -1,76 +1,80 @@ %table.table.vertical.dossier-champs %tbody - %tr - %th.libelle Dénomination : - %td= raison_sociale_or_name(etablissement) - %tr - %th.libelle SIRET : - %td= etablissement.siret + - if etablissement.diffusable_commercialement == false && profile != 'instructeur' + %tr + %td= t('warning_for_private_info', etablissement: raison_sociale_or_name(etablissement), scope: 'views.shared.dossiers.identite_entreprise') + - else + %tr + %th.libelle Dénomination : + %td= raison_sociale_or_name(etablissement) + %tr + %th.libelle SIRET : + %td= etablissement.siret - - if etablissement.siret != etablissement.entreprise.siret_siege_social + - if etablissement.siret != etablissement.entreprise.siret_siege_social + %tr + %th.libelle SIRET du siège social: + %td= etablissement.entreprise.siret_siege_social %tr - %th.libelle SIRET du siège social: - %td= etablissement.entreprise.siret_siege_social - %tr - %th.libelle Forme juridique : - %td= sanitize(etablissement.entreprise.forme_juridique) - %tr - %th.libelle Libellé NAF : - %td= etablissement.libelle_naf - %tr - %th.libelle Code NAF : - %td= etablissement.naf - %tr - %th.libelle Date de création : - %td= try_format_date(etablissement.entreprise.date_creation) - %tr - %th.libelle Effectif de l'organisation : - %td= effectif(etablissement) - %tr - %th.libelle Code effectif : - %td= etablissement.entreprise.code_effectif_entreprise - %tr - %th.libelle Numéro de TVA intracommunautaire : - %td= etablissement.entreprise.numero_tva_intracommunautaire - %tr - %th.libelle Adresse : - %td - - etablissement.adresse.split("\n").each do |line| - = line - %br - %tr - %th.libelle Capital social : - %td= pretty_currency(etablissement.entreprise.capital_social) - %tr - %th.libelle Exercices : - %td - - if profile == 'instructeur' - - etablissement.exercices.each_with_index do |exercice, index| - = "#{exercice.date_fin_exercice.year} : " - = pretty_currency(exercice.ca) - %br - - elsif etablissement.exercices.present? - = t('activemodel.models.exercices_summary', count: etablissement.exercices.count) - - - if etablissement.association? + %th.libelle Forme juridique : + %td= sanitize(etablissement.entreprise.forme_juridique) %tr - %th.libelle Numéro RNA : - %td= etablissement.association_rna + %th.libelle Libellé NAF : + %td= etablissement.libelle_naf %tr - %th.libelle Titre : - %td= etablissement.association_titre - %tr - %th.libelle Objet : - %td= etablissement.association_objet + %th.libelle Code NAF : + %td= etablissement.naf %tr %th.libelle Date de création : - %td= try_format_date(etablissement.association_date_creation) + %td= try_format_date(etablissement.entreprise.date_creation) %tr - %th.libelle Date de publication : - %td= try_format_date(etablissement.association_date_publication) + %th.libelle Effectif de l'organisation : + %td= effectif(etablissement) %tr - %th.libelle Date de déclaration : - %td= try_format_date(etablissement.association_date_declaration) + %th.libelle Code effectif : + %td= etablissement.entreprise.code_effectif_entreprise + %tr + %th.libelle Numéro de TVA intracommunautaire : + %td= etablissement.entreprise.numero_tva_intracommunautaire + %tr + %th.libelle Adresse : + %td + - etablissement.adresse.split("\n").each do |line| + = line + %br + %tr + %th.libelle Capital social : + %td= pretty_currency(etablissement.entreprise.capital_social) + %tr + %th.libelle Exercices : + %td + - if profile == 'instructeur' + - etablissement.exercices.each_with_index do |exercice, index| + = "#{exercice.date_fin_exercice.year} : " + = pretty_currency(exercice.ca) + %br + - elsif etablissement.exercices.present? + = t('activemodel.models.exercices_summary', count: etablissement.exercices.count) + + - if etablissement.association? + %tr + %th.libelle Numéro RNA : + %td= etablissement.association_rna + %tr + %th.libelle Titre : + %td= etablissement.association_titre + %tr + %th.libelle Objet : + %td= etablissement.association_objet + %tr + %th.libelle Date de création : + %td= try_format_date(etablissement.association_date_creation) + %tr + %th.libelle Date de publication : + %td= try_format_date(etablissement.association_date_publication) + %tr + %th.libelle Date de déclaration : + %td= try_format_date(etablissement.association_date_declaration) %p = link_to '➡ Autres informations sur l’organisme sur « entreprise.data.gouv.fr »', diff --git a/app/views/users/dossiers/etablissement.html.haml b/app/views/users/dossiers/etablissement.html.haml index a12999c1d..5c469a98d 100644 --- a/app/views/users/dossiers/etablissement.html.haml +++ b/app/views/users/dossiers/etablissement.html.haml @@ -7,20 +7,25 @@ .container %h1 Informations sur l’établissement - %p - Nous avons récupéré auprès de l’INSEE et d’Infogreffe les informations suivantes concernant votre établissement. + - etablissement = @dossier.etablissement + - if etablissement.diffusable_commercialement == false + %p= t('warning_for_private_info', etablissement: raison_sociale_or_name(etablissement), scope: 'views.shared.dossiers.identite_entreprise') - %p - Ces informations seront jointes à votre dossier. + - else + %p + Nous avons récupéré auprès de l’INSEE et d’Infogreffe les informations suivantes concernant votre établissement. - .etablissement-infos.card.featured - - etablissement = @dossier.etablissement - %h2.card-title= raison_sociale_or_name(etablissement) + %p + Ces informations seront jointes à votre dossier. - = render partial: 'users/dossiers/etablissement/infos_entreprise', locals: { etablissement: etablissement } + .etablissement-infos.card.featured - - if etablissement.association? - = render partial: 'users/dossiers/etablissement/infos_association', locals: { etablissement: etablissement } + %h2.card-title= raison_sociale_or_name(etablissement) + + = render partial: 'users/dossiers/etablissement/infos_entreprise', locals: { etablissement: etablissement } + + - if etablissement.association? + = render partial: 'users/dossiers/etablissement/infos_association', locals: { etablissement: etablissement } .actions = link_to 'Utiliser un autre numéro SIRET', siret_dossier_path(@dossier), class: 'button' diff --git a/config/initializers/browser.rb b/config/initializers/browser.rb deleted file mode 100644 index f9d22d40b..000000000 --- a/config/initializers/browser.rb +++ /dev/null @@ -1,8 +0,0 @@ -# See .browserslistrc -Browser.modern_rules.clear -Browser.modern_rules << -> b { b.chrome? && b.version.to_i >= 50 && !b.platform.ios? } -Browser.modern_rules << -> b { b.edge? && b.version.to_i >= 14 && !b.compatibility_view? } -Browser.modern_rules << -> b { b.firefox? && b.version.to_i >= 50 && !b.platform.ios? } -Browser.modern_rules << -> b { b.opera? && b.version.to_i >= 40 } -Browser.modern_rules << -> b { b.safari? && b.version.to_i >= 8 } -Browser.modern_rules << -> b { b.platform.ios? && b.platform.version.to_i >= 8 } diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index 588cd5079..63eaa7b7a 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -1,9 +1,4 @@ Rails.application.config.content_security_policy do |policy| - if Rails.env.development? - # les CSP ne sont pas appliquées en dev: on notifie cependant une url quelconque de la violation - # pour détecter les erreurs lors de l'ajout d'une nouvelle brique externe durant le développement - policy.report_uri "http://#{ENV['APP_HOST']}/csp/" - end # Whitelist image policy.img_src :self, "*.openstreetmap.org", "static.demarches-simplifiees.fr", "*.cloud.ovh.net", "stats.data.gouv.fr", "*", :data # Whitelist JS: nous, sendinblue et matomo @@ -17,4 +12,11 @@ Rails.application.config.content_security_policy do |policy| # Pour tout le reste, par défaut on accepte uniquement ce qui vient de chez nous # et dans la notification on inclue la source de l'erreur policy.default_src :self, :data, :report_sample, "fonts.gstatic.com", "in-automate.sendinblue.com", "player.vimeo.com", "app.franceconnect.gouv.fr", "sentry.io", "static.demarches-simplifiees.fr", "*.crisp.chat", "crisp.chat", "*.crisp.help", "*.sibautomation.com", "sibautomation.com", "data" + if Rails.env.development? + # Les CSP ne sont pas appliquées en dev: on notifie cependant une url quelconque de la violation + # pour détecter les erreurs lors de l'ajout d'une nouvelle brique externe durant le développement + policy.report_uri "http://#{ENV['APP_HOST']}/csp/" + # En développement, quand bin/webpack-dev-server est utilisé, on autorise les requêtes faites par le live-reload + policy.connect_src(*policy.connect_src, "ws://localhost:3035", "localhost:3035") + end end diff --git a/config/initializers/openstack_version.rb b/config/initializers/openstack_version.rb deleted file mode 100644 index 0ebdec459..000000000 --- a/config/initializers/openstack_version.rb +++ /dev/null @@ -1 +0,0 @@ -OpenStack::VERSION = 2.0 diff --git a/config/locales/views/shared/fr.yml b/config/locales/views/shared/fr.yml new file mode 100644 index 000000000..d832dc33c --- /dev/null +++ b/config/locales/views/shared/fr.yml @@ -0,0 +1,6 @@ +fr: + views: + shared: + dossiers: + identite_entreprise: + warning_for_private_info: "L'établissement %{etablissement} a exercé son droit à la non publication des informations relatives à son identité. Les informations ne seront donc visibles que de la part des services instructeurs" diff --git a/config/routes.rb b/config/routes.rb index 30d4a3402..32bc4a620 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -242,8 +242,10 @@ Rails.application.routes.draw do scope module: 'users' do namespace :commencer do + get '/test/:path/dossier_vide', action: 'dossier_vide_pdf_test', as: :dossier_vide_test get '/test/:path', action: 'commencer_test', as: :test get '/:path', action: 'commencer' + get '/:path/dossier_vide', action: 'dossier_vide_pdf', as: :dossier_vide get '/:path/sign_in', action: 'sign_in', as: :sign_in get '/:path/sign_up', action: 'sign_up', as: :sign_up get '/:path/france_connect', action: 'france_connect', as: :france_connect diff --git a/db/migrate/20200304155418_add_diffusable_commercialement_to_etablissements.rb b/db/migrate/20200304155418_add_diffusable_commercialement_to_etablissements.rb new file mode 100644 index 000000000..9be80c571 --- /dev/null +++ b/db/migrate/20200304155418_add_diffusable_commercialement_to_etablissements.rb @@ -0,0 +1,5 @@ +class AddDiffusableCommercialementToEtablissements < ActiveRecord::Migration[5.2] + def change + add_column :etablissements, :diffusable_commercialement, :boolean + end +end diff --git a/db/schema.rb b/db/schema.rb index 557bf1d0e..fe75b1601 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_02_27_100001) do +ActiveRecord::Schema.define(version: 2020_03_04_155418) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -304,6 +304,7 @@ ActiveRecord::Schema.define(version: 2020_02_27_100001) do t.date "association_date_publication" t.datetime "created_at" t.datetime "updated_at" + t.boolean "diffusable_commercialement" t.index ["dossier_id"], name: "index_etablissements_on_dossier_id" end diff --git a/db/seeds.rb b/db/seeds.rb index 6849cda9a..06d251d3f 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -16,4 +16,4 @@ user = User.create!( confirmed_at: Time.zone.now ) user.create_instructeur! -user.create_administrateur!(email: user.email) +user.create_administrateur! diff --git a/lib/tasks/deployment/20190704133852_create_dummy_paths_for_archived_and_hidden_procedures.rake b/lib/tasks/deployment/20190704133852_create_dummy_paths_for_archived_and_hidden_procedures.rake deleted file mode 100644 index ceefc8b86..000000000 --- a/lib/tasks/deployment/20190704133852_create_dummy_paths_for_archived_and_hidden_procedures.rake +++ /dev/null @@ -1,18 +0,0 @@ -namespace :after_party do - desc 'Deployment task: create_dummy_paths_for_archived_and_hidden_procedures' - task create_dummy_paths_for_archived_and_hidden_procedures: :environment do - rake_puts "Running deploy task 'create_dummy_paths_for_archived_procedures'" - - Procedure.with_discarded.archivees.where(path: nil).each do |p| - p.update_column(:path, SecureRandom.uuid) - end - - Procedure.hidden.where(path: nil).each do |p| - p.update_column(:path, SecureRandom.uuid) - end - - # Update task as completed. If you remove the line below, the task will - # run with every deploy (or every time you call after_party:run). - AfterParty::TaskRecord.create version: '20190704133852' - end -end diff --git a/lib/tasks/deployment/20190731152733_migrate_geo_area_data.rake b/lib/tasks/deployment/20190731152733_migrate_geo_area_data.rake deleted file mode 100644 index e5821d722..000000000 --- a/lib/tasks/deployment/20190731152733_migrate_geo_area_data.rake +++ /dev/null @@ -1,28 +0,0 @@ -namespace :after_party do - desc 'Deployment task: migrate_geo_area_data' - task migrate_geo_area_data: :environment do - rake_puts "Running deploy task 'migrate_geo_area_data'" - - progress = ProgressReport.new(Champs::CarteChamp.count) - - Champs::CarteChamp.includes(:geo_areas).find_each do |champ| - geo_area = champ.geo_areas.find(&:selection_utilisateur?) - geo_json = champ.geo_json_from_value - - if geo_area.blank? && geo_json.present? - GeoArea.create( - champ: champ, - geometry: geo_json, - source: GeoArea.sources.fetch(:selection_utilisateur) - ) - progress.inc - end - end - - progress.finish - - # Update task as completed. If you remove the line below, the task will - # run with every deploy (or every time you call after_party:run). - AfterParty::TaskRecord.create version: '20190731152733' - end -end diff --git a/lib/tasks/deployment/20190829065022_migrate_flipflop_to_flipper.rake b/lib/tasks/deployment/20190829065022_migrate_flipflop_to_flipper.rake deleted file mode 100644 index 4892d71de..000000000 --- a/lib/tasks/deployment/20190829065022_migrate_flipflop_to_flipper.rake +++ /dev/null @@ -1,33 +0,0 @@ -namespace :after_party do - desc 'Deployment task: migrate_flipflop_to_flipper' - task migrate_flipflop_to_flipper: :environment do - rake_puts "Running deploy task 'migrate_flipflop_to_flipper'" - - Instructeur.includes(:user).find_each do |instructeur| - if instructeur.features['download_as_zip_enabled'] - pp "enable :instructeur_download_as_zip for #{instructeur.user.email}" - Flipper.enable_actor(:instructeur_download_as_zip, instructeur.user) - end - if instructeur.features['bypass_email_login_token'] - pp "enable :instructeur_bypass_email_login_token for #{instructeur.user.email}" - Flipper.enable_actor(:instructeur_bypass_email_login_token, instructeur.user) - end - end - - Administrateur.includes(:user).find_each do |administrateur| - if administrateur.features['web_hook'] - pp "enable :administrateur_web_hook for #{administrateur.user.email}" - Flipper.enable_actor(:administrateur_web_hook, administrateur.user) - end - - if administrateur.features['champ_integer_number'] - pp "enable :administrateur_champ_integer_number for #{administrateur.user.email}" - Flipper.enable_actor(:administrateur_champ_integer_number, administrateur.user) - end - end - - # Update task as completed. If you remove the line below, the task will - # run with every deploy (or every time you call after_party:run). - AfterParty::TaskRecord.create version: '20190829065022' - end -end diff --git a/lib/tasks/deployment/20200220142710_backfill_daily_email_notification_columns.rake b/lib/tasks/deployment/20200220142710_backfill_daily_email_notification_columns.rake deleted file mode 100644 index 919441434..000000000 --- a/lib/tasks/deployment/20200220142710_backfill_daily_email_notification_columns.rake +++ /dev/null @@ -1,16 +0,0 @@ -namespace :after_party do - desc 'Deployment task: backfill_daily_email_notification_columns' - task backfill_daily_email_notification_columns: :environment do - puts "Running deploy task 'backfill_daily_email_notification_columns'" - AssignTo.find_each do |assign_to| - columns_to_update = {} - if assign_to.email_notifications_enabled != assign_to.daily_email_notifications_enabled - columns_to_update[:daily_email_notifications_enabled] = assign_to.email_notifications_enabled - end - assign_to.update_columns(columns_to_update) unless columns_to_update.empty? - end - # Update task as completed. If you remove the line below, the task will - # run with every deploy (or every time you call after_party:run). - AfterParty::TaskRecord.create version: '20200220142710' - end # task :backfill_daily_email_notification_columns -end # namespace :after_party diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 990c55961..8289c3482 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -164,6 +164,7 @@ describe ApplicationController, type: :controller do allow(@controller).to receive(:instructeur_signed_in?).and_return(instructeur_signed_in) allow(@controller).to receive(:sensitive_path).and_return(sensitive_path) allow(@controller).to receive(:send_login_token_or_bufferize) + allow(@controller).to receive(:get_stored_location_for).and_return(nil) allow(@controller).to receive(:store_location_for) allow(IPService).to receive(:ip_trusted?).and_return(ip_trusted) end diff --git a/spec/controllers/champs/carte_controller_spec.rb b/spec/controllers/champs/carte_controller_spec.rb index e420323f6..dbba13ebb 100644 --- a/spec/controllers/champs/carte_controller_spec.rb +++ b/spec/controllers/champs/carte_controller_spec.rb @@ -75,7 +75,7 @@ describe Champs::CarteController, type: :controller do allow_any_instance_of(ApiCarto::QuartiersPrioritairesAdapter) .to receive(:results) - .and_raise(RestClient::ResourceNotFound) + .and_raise(ApiCarto::API::ResourceNotFound) post :show, params: params, format: 'js' end diff --git a/spec/controllers/champs/siret_controller_spec.rb b/spec/controllers/champs/siret_controller_spec.rb index e374ce4a1..cd7163803 100644 --- a/spec/controllers/champs/siret_controller_spec.rb +++ b/spec/controllers/champs/siret_controller_spec.rb @@ -59,7 +59,7 @@ describe Champs::SiretController, type: :controller do let(:siret) { '82161143100015' } before do - allow(controller).to receive(:find_etablissement_with_siret).and_raise(RestClient::RequestFailed) + allow(controller).to receive(:find_etablissement_with_siret).and_raise(ApiEntreprise::API::RequestFailed) end subject! { get :show, params: params, format: 'js' } diff --git a/spec/factories/etablissement.rb b/spec/factories/etablissement.rb index 1d2040ea8..be7520415 100644 --- a/spec/factories/etablissement.rb +++ b/spec/factories/etablissement.rb @@ -29,6 +29,10 @@ FactoryBot.define do create(:exercice, etablissement: etablissement) end end + + trait :non_diffusable do + diffusable_commercialement { false } + end end trait :is_association do diff --git a/spec/factories/procedure.rb b/spec/factories/procedure.rb index 32c4a6586..c42b22194 100644 --- a/spec/factories/procedure.rb +++ b/spec/factories/procedure.rb @@ -14,7 +14,7 @@ FactoryBot.define do path { SecureRandom.uuid } transient do - administrateur {} + administrateur { } instructeurs { [] } end diff --git a/spec/features/users/dossier_creation_spec.rb b/spec/features/users/dossier_creation_spec.rb index 662d02918..e54228974 100644 --- a/spec/features/users/dossier_creation_spec.rb +++ b/spec/features/users/dossier_creation_spec.rb @@ -110,4 +110,16 @@ feature 'Creating a new dossier:' do end end end + + context 'when the user is not signed in' do + let(:instructeur) { create(:instructeur) } + let(:procedure) { create(:procedure, :published) } + scenario 'the user is an instructeur with untrusted device' do + visit commencer_path(path: procedure.path) + click_on "J’ai déjà un compte" + sign_in_with(instructeur.email, instructeur.user.password, true) + + expect(page).to have_current_path(commencer_path(path: procedure.path)) + end + end end diff --git a/spec/fixtures/files/api_entreprise/etablissements.json b/spec/fixtures/files/api_entreprise/etablissements.json index 835a18bf1..aa5aa7603 100644 --- a/spec/fixtures/files/api_entreprise/etablissements.json +++ b/spec/fixtures/files/api_entreprise/etablissements.json @@ -26,7 +26,7 @@ "code": null, "value": null }, - "diffusable_commercialement": null, + "diffusable_commercialement": true, "adresse": { "l1": "OCTO TECHNOLOGY", "l2": null, diff --git a/spec/fixtures/files/api_entreprise/etablissements_private.json b/spec/fixtures/files/api_entreprise/etablissements_private.json new file mode 100644 index 000000000..e2d58cf04 --- /dev/null +++ b/spec/fixtures/files/api_entreprise/etablissements_private.json @@ -0,0 +1,49 @@ +{ + "etablissement": { + "siege_social": true, + "siret": "41816609600051", + "naf": "6202A", + "libelle_naf": "Conseil en systèmes et logiciels informatiques", + "date_mise_a_jour": 1449183600, + "tranche_effectif_salarie_etablissement": { + "de": 200, + "a": 249, + "code": "31", + "date_reference": "2014", + "intitule": "200 à 249 salariés" + }, + "date_creation_etablissement": 1108594800, + "enseigne": null, + "region_implantation": { + "code": "11", + "value": "Île-de-France" + }, + "commune_implantation": { + "code": "75108", + "value": "PARIS 8" + }, + "pays_implantation": { + "code": null, + "value": null + }, + "diffusable_commercialement": false, + "adresse": { + "l1": "OCTO TECHNOLOGY", + "l2": null, + "l3": null, + "l4": "50 AVENUE DES CHAMPS ELYSEES", + "l5": null, + "l6": "75008 PARIS", + "l7": "FRANCE", + "numero_voie": "50", + "type_voie": "AV", + "nom_voie": "DES CHAMPS ELYSEES", + "complement_adresse": "complement_adresse", + "code_postal": "75008", + "localite": "PARIS 8", + "code_insee_localite": "75108", + "cedex": null + } + }, + "gateway_error": false +} diff --git a/spec/lib/api_carto/api_spec.rb b/spec/lib/api_carto/api_spec.rb index 2e52a58b1..bb03c40e5 100644 --- a/spec/lib/api_carto/api_spec.rb +++ b/spec/lib/api_carto/api_spec.rb @@ -15,8 +15,8 @@ describe ApiCarto::API do let(:status) { 404 } let(:body) { '' } - it 'raises RestClient::ResourceNotFound' do - expect { subject }.to raise_error(RestClient::ResourceNotFound) + it 'raises ApiCarto::API::ResourceNotFound' do + expect { subject }.to raise_error(ApiCarto::API::ResourceNotFound) end end @@ -25,8 +25,8 @@ describe ApiCarto::API do let(:status) { 500 } let(:body) { 'toto' } - it 'raises RestClient::ResourceNotFound' do - expect { subject }.to raise_error(RestClient::ResourceNotFound) + it 'raises ApiCarto::API::ResourceNotFound' do + expect { subject }.to raise_error(ApiCarto::API::ResourceNotFound) end end @@ -63,8 +63,8 @@ describe ApiCarto::API do let(:status) { 404 } let(:body) { '' } - it 'raises RestClient::ResourceNotFound' do - expect { subject }.to raise_error(RestClient::ResourceNotFound) + it 'raises ApiCarto::API::ResourceNotFound' do + expect { subject }.to raise_error(ApiCarto::API::ResourceNotFound) end end diff --git a/spec/lib/api_carto/cadastre_adapter_spec.rb b/spec/lib/api_carto/cadastre_adapter_spec.rb index aaba3cae7..63d7f83c9 100644 --- a/spec/lib/api_carto/cadastre_adapter_spec.rb +++ b/spec/lib/api_carto/cadastre_adapter_spec.rb @@ -60,6 +60,6 @@ describe ApiCarto::CadastreAdapter do let(:status) { 404 } let(:body) { '' } - it { expect { subject }.to raise_error(RestClient::ResourceNotFound) } + it { expect { subject }.to raise_error(ApiCarto::API::ResourceNotFound) } end end diff --git a/spec/lib/api_carto/quartiers_prioritaires_adapter_spec.rb b/spec/lib/api_carto/quartiers_prioritaires_adapter_spec.rb index 32f5eb60b..70593327d 100644 --- a/spec/lib/api_carto/quartiers_prioritaires_adapter_spec.rb +++ b/spec/lib/api_carto/quartiers_prioritaires_adapter_spec.rb @@ -33,6 +33,6 @@ describe ApiCarto::QuartiersPrioritairesAdapter do let(:status) { 404 } let(:body) { '' } - it { expect { subject }.to raise_error(RestClient::ResourceNotFound) } + it { expect { subject }.to raise_error(ApiCarto::API::ResourceNotFound) } end end diff --git a/spec/lib/api_entreprise/api_spec.rb b/spec/lib/api_entreprise/api_spec.rb index abd7c07c2..d247e0f37 100644 --- a/spec/lib/api_entreprise/api_spec.rb +++ b/spec/lib/api_entreprise/api_spec.rb @@ -16,8 +16,8 @@ describe ApiEntreprise::API do let(:status) { 502 } let(:body) { File.read('spec/fixtures/files/api_entreprise/entreprises_unavailable.json') } - it 'raises RestClient::RequestFailed' do - expect { subject }.to raise_error(RestClient::RequestFailed) + it 'raises ApiEntreprise::API::RequestFailed' do + expect { subject }.to raise_error(ApiEntreprise::API::RequestFailed) end end @@ -26,8 +26,8 @@ describe ApiEntreprise::API do let(:status) { 404 } let(:body) { File.read('spec/fixtures/files/api_entreprise/entreprises_not_found.json') } - it 'raises RestClient::ResourceNotFound' do - expect { subject }.to raise_error(RestClient::ResourceNotFound) + it 'raises ApiEntreprise::API::ResourceNotFound' do + expect { subject }.to raise_error(ApiEntreprise::API::ResourceNotFound) end end @@ -36,8 +36,8 @@ describe ApiEntreprise::API do let(:status) { 403 } let(:body) { File.read('spec/fixtures/files/api_entreprise/entreprises_private.json') } - it 'raises RestClient::ResourceNotFound' do - expect { subject }.to raise_error(RestClient::ResourceNotFound) + it 'raises ApiEntreprise::API::ResourceNotFound' do + expect { subject }.to raise_error(ApiEntreprise::API::ResourceNotFound) end end @@ -55,7 +55,7 @@ describe ApiEntreprise::API do describe '.etablissement' do subject { described_class.etablissement(siret, procedure_id) } before do - stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/) + stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*non_diffusables=true&.*token=/) .to_return(status: status, body: body) end @@ -64,8 +64,8 @@ describe ApiEntreprise::API do let(:status) { 404 } let(:body) { '' } - it 'raises RestClient::ResourceNotFound' do - expect { subject }.to raise_error(RestClient::ResourceNotFound) + it 'raises ApiEntreprise::API::ResourceNotFound' do + expect { subject }.to raise_error(ApiEntreprise::API::ResourceNotFound) end end @@ -93,8 +93,8 @@ describe ApiEntreprise::API do let(:status) { 404 } let(:body) { '' } - it 'raises RestClient::ResourceNotFound' do - expect { subject }.to raise_error(RestClient::ResourceNotFound) + it 'raises ApiEntreprise::API::ResourceNotFound' do + expect { subject }.to raise_error(ApiEntreprise::API::ResourceNotFound) end end @@ -105,7 +105,7 @@ describe ApiEntreprise::API do let(:status) { 200 } let(:body) { File.read('spec/fixtures/files/api_entreprise/exercices.json') } - it 'raises RestClient::Unauthorized' do + it 'success' do expect(subject).to eq(JSON.parse(body, symbolize_names: true)) end end @@ -124,8 +124,8 @@ describe ApiEntreprise::API do let(:status) { 404 } let(:body) { '' } - it 'raises RestClient::ResourceNotFound' do - expect { subject }.to raise_error(RestClient::ResourceNotFound) + it 'raises ApiEntreprise::API::ResourceNotFound' do + expect { subject }.to raise_error(ApiEntreprise::API::ResourceNotFound) end end diff --git a/spec/lib/api_entreprise/entreprise_adapter_spec.rb b/spec/lib/api_entreprise/entreprise_adapter_spec.rb index 51f120d2d..56c78d8aa 100644 --- a/spec/lib/api_entreprise/entreprise_adapter_spec.rb +++ b/spec/lib/api_entreprise/entreprise_adapter_spec.rb @@ -84,7 +84,7 @@ describe ApiEntreprise::EntrepriseAdapter do let(:status) { 502 } it 'raises an exception' do - expect { subject }.to raise_error(RestClient::RequestFailed) + expect { subject }.to raise_error(ApiEntreprise::API::RequestFailed) end end end diff --git a/spec/lib/api_entreprise/etablissement_adapter_spec.rb b/spec/lib/api_entreprise/etablissement_adapter_spec.rb index 86646148f..ba1876a5e 100644 --- a/spec/lib/api_entreprise/etablissement_adapter_spec.rb +++ b/spec/lib/api_entreprise/etablissement_adapter_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe ApiEntreprise::EtablissementAdapter do let(:procedure_id) { 33 } - context 'SIRET valide' do + context 'SIRET valide avec infos diffusables' do let(:siret) { '41816609600051' } subject { described_class.new(siret, procedure_id).to_params } @@ -33,6 +33,10 @@ describe ApiEntreprise::EtablissementAdapter do expect(subject[:libelle_naf]).to eq('Conseil en systèmes et logiciels informatiques') end + it 'L\'entreprise contient bien un diffusable_commercialement qui vaut true' do + expect(subject[:diffusable_commercialement]).to eq(true) + end + context 'Concaténation lignes adresse' do it 'L\'entreprise contient bien une adresse sur plusieurs lignes' do expect(subject[:adresse]).to eq("OCTO TECHNOLOGY\r\n50 AVENUE DES CHAMPS ELYSEES\r\n75008 PARIS\r\nFRANCE") @@ -70,6 +74,20 @@ describe ApiEntreprise::EtablissementAdapter do end end + context 'SIRET valide avec infos non diffusables' do + let(:siret) { '41816609600051' } + subject { described_class.new(siret, procedure_id).to_params } + + before do + stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/) + .to_return(body: File.read('spec/fixtures/files/api_entreprise/etablissements_private.json', status: 200)) + end + + it 'L\'entreprise contient bien un diffusable_commercialement qui vaut false' do + expect(subject[:diffusable_commercialement]).to eq(false) + end + end + context 'when siret is not found' do let(:bad_siret) { 11_111_111_111_111 } subject { described_class.new(bad_siret, 12).to_params } diff --git a/spec/models/administrateur_spec.rb b/spec/models/administrateur_spec.rb index 3b1a023cd..f7581dc15 100644 --- a/spec/models/administrateur_spec.rb +++ b/spec/models/administrateur_spec.rb @@ -59,6 +59,14 @@ describe Administrateur, type: :model do expect(Administrateur.find_by(id: administrateur.id)).to be_nil expect(service.reload.administrateur).to eq(autre_administrateur) end + + it "delete service if not associated to procedures" do + service_without_procedure = create(:service, administrateur: administrateur) + administrateur.delete_and_transfer_services + + expect(Service.find_by(id: service_without_procedure.id)).to be_nil + expect(Administrateur.find_by(id: administrateur.id)).to be_nil + end end # describe '#password_complexity' do diff --git a/spec/models/instructeur_spec.rb b/spec/models/instructeur_spec.rb index 8e205cce8..e6de354c2 100644 --- a/spec/models/instructeur_spec.rb +++ b/spec/models/instructeur_spec.rb @@ -401,6 +401,8 @@ describe Instructeur, type: :model do expect(instructeur.email_notification_data).to eq([ { nb_en_construction: 1, + nb_en_instruction: 0, + nb_accepted: 0, nb_notification: 0, procedure_id: procedure_to_assign.id, procedure_libelle: procedure_to_assign.libelle @@ -420,6 +422,8 @@ describe Instructeur, type: :model do expect(instructeur.email_notification_data).to eq([ { nb_en_construction: 0, + nb_en_instruction: 0, + nb_accepted: 0, nb_notification: 3, procedure_id: procedure_to_assign.id, procedure_libelle: procedure_to_assign.libelle @@ -428,6 +432,75 @@ describe Instructeur, type: :model do end end + context 'when a declarated dossier in instruction exists' do + let!(:dossier) { create(:dossier, procedure: procedure_to_assign, state: Dossier.states.fetch(:en_construction)) } + + before do + procedure_to_assign.update(declarative_with_state: "en_instruction") + DeclarativeProceduresJob.new.perform + dossier.reload + end + + it { expect(procedure_to_assign.declarative_with_state).to eq("en_instruction") } + it { expect(dossier.state).to eq("en_instruction") } + it do + expect(instructeur.email_notification_data).to eq([ + { + nb_en_construction: 0, + nb_en_instruction: 1, + nb_accepted: 0, + nb_notification: 0, + procedure_id: procedure_to_assign.id, + procedure_libelle: procedure_to_assign.libelle + } + ]) + end + end + + context 'when a declarated dossier in accepte processed at today exists' do + let!(:dossier) { create(:dossier, procedure: procedure_to_assign, state: Dossier.states.fetch(:en_construction)) } + + before do + procedure_to_assign.update(declarative_with_state: "accepte") + DeclarativeProceduresJob.new.perform + dossier.reload + end + + it { expect(procedure_to_assign.declarative_with_state).to eq("accepte") } + it { expect(dossier.state).to eq("accepte") } + + it do + expect(instructeur.email_notification_data).to eq([]) + end + end + + context 'when a declarated dossier in accepte processed at yesterday exists' do + let!(:dossier) { create(:dossier, procedure: procedure_to_assign, state: Dossier.states.fetch(:en_construction)) } + + before do + procedure_to_assign.update(declarative_with_state: "accepte") + DeclarativeProceduresJob.new.perform + dossier.update(processed_at: Time.zone.yesterday.beginning_of_day) + dossier.reload + end + + it { expect(procedure_to_assign.declarative_with_state).to eq("accepte") } + it { expect(dossier.state).to eq("accepte") } + + it do + expect(instructeur.email_notification_data).to eq([ + { + nb_en_construction: 0, + nb_en_instruction: 0, + nb_accepted: 1, + nb_notification: 0, + procedure_id: procedure_to_assign.id, + procedure_libelle: procedure_to_assign.libelle + } + ]) + end + end + context 'otherwise' do it { expect(instructeur.email_notification_data).to eq([]) } end diff --git a/spec/services/api_entreprise_service_spec.rb b/spec/services/api_entreprise_service_spec.rb index 0fefcb99e..192f16400 100644 --- a/spec/services/api_entreprise_service_spec.rb +++ b/spec/services/api_entreprise_service_spec.rb @@ -66,8 +66,8 @@ describe ApiEntrepriseService do let(:entreprises_status) { 400 } let(:entreprises_body) { '' } - it 'should raise RestClient::RequestFailed' do - expect { result }.to raise_error(RestClient::RequestFailed) + it 'should raise ApiEntreprise::API::RequestFailed' do + expect { result }.to raise_error(ApiEntreprise::API::RequestFailed) end end @@ -75,8 +75,8 @@ describe ApiEntrepriseService do let(:etablissements_status) { 400 } let(:etablissements_body) { '' } - it 'should raise RestClient::RequestFailed' do - expect { result }.to raise_error(RestClient::RequestFailed) + it 'should raise ApiEntreprise::API::RequestFailed' do + expect { result }.to raise_error(ApiEntreprise::API::RequestFailed) end end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index e5db1502c..9cb1952ef 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -47,6 +47,49 @@ describe NotificationService do end end + context 'when a declarative dossier in instruction exists on this procedure' do + let!(:dossier) { create(:dossier, :en_construction, procedure: procedure) } + before do + procedure.update(declarative_with_state: "en_instruction") + DeclarativeProceduresJob.new.perform + dossier.reload + end + + it do + subject + expect(InstructeurMailer).to have_received(:send_notifications) + end + end + + context 'when a declarative dossier in accepte on yesterday exists on this procedure' do + let!(:dossier) { create(:dossier, :en_construction, procedure: procedure) } + before do + procedure.update(declarative_with_state: "accepte") + DeclarativeProceduresJob.new.perform + dossier.update(processed_at: Time.zone.yesterday.beginning_of_day) + dossier.reload + end + + it do + subject + expect(InstructeurMailer).to have_received(:send_notifications) + end + end + + context 'when a declarative dossier in accepte on today exists on this procedure' do + let!(:dossier) { create(:dossier, :en_construction, procedure: procedure) } + before do + procedure.update(declarative_with_state: "accepte") + DeclarativeProceduresJob.new.perform + dossier.reload + end + + it do + subject + expect(InstructeurMailer).not_to have_received(:send_notifications) + end + end + context 'when there is a notification on this procedure' do before do allow_any_instance_of(Instructeur).to receive(:notifications_for_procedure) diff --git a/spec/views/instructeur_mailer/send_notifications.html.haml_spec.rb b/spec/views/instructeur_mailer/send_notifications.html.haml_spec.rb index 0c8be4c27..82575aae8 100644 --- a/spec/views/instructeur_mailer/send_notifications.html.haml_spec.rb +++ b/spec/views/instructeur_mailer/send_notifications.html.haml_spec.rb @@ -16,6 +16,8 @@ describe 'instructeur_mailer/send_notifications.html.haml', type: :view do procedure_libelle: 'une superbe démarche', procedure_id: 213, nb_en_construction: 1, + nb_en_instruction: 0, + nb_accepted: 0, nb_notification: 0 } ] @@ -27,6 +29,50 @@ describe 'instructeur_mailer/send_notifications.html.haml', type: :view do it { expect(rendered).not_to have_text('notification') } end + context 'when there is one declarated dossier in instruction' do + let(:data) do + [ + { + procedure_libelle: 'une superbe démarche', + procedure_id: 213, + nb_en_construction: 0, + nb_en_instruction: 1, + nb_accepted: 0, + nb_notification: 0 + } + ] + end + + it { expect(rendered).to have_link('une superbe démarche', href: procedure_url(213)) } + it { expect(rendered).to have_text('une superbe démarche') } + it { expect(rendered).to have_text('1 dossier') } + it { expect(rendered).not_to have_text('notification') } + it { expect(rendered).not_to have_text('construction') } + it { expect(rendered).not_to have_text('accepte') } + end + + context 'when there is one declarated dossier in accepte' do + let(:data) do + [ + { + procedure_libelle: 'une superbe démarche', + procedure_id: 213, + nb_en_construction: 0, + nb_en_instruction: 0, + nb_accepted: 1, + nb_notification: 0 + } + ] + end + + it { expect(rendered).to have_link('une superbe démarche', href: procedure_url(213)) } + it { expect(rendered).to have_text('une superbe démarche') } + it { expect(rendered).to have_text('1 dossier') } + it { expect(rendered).not_to have_text('notification') } + it { expect(rendered).not_to have_text('construction') } + it { expect(rendered).not_to have_text('instruction') } + end + context 'when there is one notification' do let(:data) do [ @@ -34,6 +80,8 @@ describe 'instructeur_mailer/send_notifications.html.haml', type: :view do procedure_libelle: 'une superbe démarche', procedure_id: 213, nb_en_construction: 0, + nb_en_instruction: 0, + nb_accepted: 0, nb_notification: 1 } ] diff --git a/spec/views/shared/dossiers/_identite_entreprise.html.haml_spec.rb b/spec/views/shared/dossiers/_identite_entreprise.html.haml_spec.rb index 91189a6e2..db3c527d9 100644 --- a/spec/views/shared/dossiers/_identite_entreprise.html.haml_spec.rb +++ b/spec/views/shared/dossiers/_identite_entreprise.html.haml_spec.rb @@ -12,4 +12,13 @@ describe 'shared/dossiers/identite_entreprise.html.haml', type: :view do end end end + + context "for an entreprise with private infos" do + let(:etablissement) { create(:etablissement, :non_diffusable) } + + it "displays only public infos" do + expect(rendered).to have_text(etablissement.entreprise_raison_sociale) + expect(rendered).not_to have_text(etablissement.entreprise.forme_juridique) + end + end end diff --git a/spec/views/users/dossiers/etablissement.html.haml_spec.rb b/spec/views/users/dossiers/etablissement.html.haml_spec.rb index 3f7b7ff5f..7f74e05f1 100644 --- a/spec/views/users/dossiers/etablissement.html.haml_spec.rb +++ b/spec/views/users/dossiers/etablissement.html.haml_spec.rb @@ -29,6 +29,14 @@ describe 'users/dossiers/etablissement.html.haml', type: :view do end end + context 'etablissement avec infos non diffusables' do + let(:etablissement) { create(:etablissement, :with_exercices, :non_diffusable) } + it "affiche uniquement le nom de l'établissement si infos non diffusables" do + expect(rendered).to have_text(etablissement.entreprise_raison_sociale) + expect(rendered).not_to have_text(etablissement.entreprise.forme_juridique) + end + end + it 'prépare le footer' do expect(footer).to have_selector('footer') end diff --git a/yarn.lock b/yarn.lock index 43276e44d..c2b25f432 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1254,9 +1254,9 @@ acorn-walk@^6.1.1: integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== acorn@^6.0.7, acorn@^6.2.1: - version "6.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" - integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== + version "6.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" + integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== acorn@^7.1.0: version "7.1.0"