Merge branch 'develop'
|
@ -1,6 +1,7 @@
|
|||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
parallelism: 2
|
||||
docker:
|
||||
- image: ruby:2.3.1
|
||||
- image: postgres:9.4.1
|
||||
|
@ -53,6 +54,9 @@ jobs:
|
|||
command: |
|
||||
TESTFILES=$(circleci tests glob "spec/**/*.rb"| xargs -n 1 echo | grep -v "spec/factories/" | tr " " "\n" | circleci tests split --split-by=timings)
|
||||
bundle exec rspec --color --require spec_helper -- ${TESTFILES}
|
||||
- run:
|
||||
name: Run rubocop
|
||||
command: bundle exec rubocop
|
||||
- run:
|
||||
name: Run haml-lint
|
||||
command: bundle exec haml-lint app/views/
|
||||
|
|
1062
.rubocop.yml
Normal file
13
Gemfile
|
@ -52,6 +52,7 @@ gem 'rest-client'
|
|||
gem 'clamav-client', require: 'clamav/client'
|
||||
|
||||
gem 'carrierwave'
|
||||
gem 'copy_carrierwave_file'
|
||||
gem 'fog'
|
||||
gem 'fog-openstack'
|
||||
|
||||
|
@ -101,6 +102,12 @@ gem 'sinatra', git: 'https://github.com/sinatra/sinatra.git', require: false
|
|||
|
||||
gem 'select2-rails'
|
||||
|
||||
# PDF Generation
|
||||
gem 'prawn', '~> 2.0.1'
|
||||
gem 'prawn_rails', '~> 0.0.11'
|
||||
|
||||
gem 'sentry-raven'
|
||||
|
||||
group :test do
|
||||
gem 'capybara'
|
||||
gem 'launchy'
|
||||
|
@ -122,6 +129,7 @@ group :development do
|
|||
gem 'web-console'
|
||||
gem 'rack-handlers'
|
||||
gem 'xray-rails'
|
||||
gem 'rubocop', require: false
|
||||
gem 'haml-lint'
|
||||
gem 'scss_lint', require: false
|
||||
end
|
||||
|
@ -142,8 +150,3 @@ group :development, :test do
|
|||
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
||||
gem 'dotenv-rails'
|
||||
end
|
||||
|
||||
group :production, :staging do
|
||||
gem 'sentry-raven'
|
||||
end
|
||||
|
||||
|
|
23
Gemfile.lock
|
@ -120,6 +120,8 @@ GEM
|
|||
coffee-script-source (1.12.2)
|
||||
concurrent-ruby (1.0.5)
|
||||
connection_pool (2.2.1)
|
||||
copy_carrierwave_file (1.3.0)
|
||||
carrierwave (>= 0.9)
|
||||
crack (0.4.3)
|
||||
safe_yaml (~> 1.0.0)
|
||||
database_cleaner (1.5.3)
|
||||
|
@ -417,14 +419,22 @@ GEM
|
|||
openstack (3.3.7)
|
||||
json
|
||||
orm_adapter (0.5.0)
|
||||
parallel (1.11.2)
|
||||
parser (2.4.0.0)
|
||||
ast (~> 2.2)
|
||||
pdf-core (0.6.1)
|
||||
pg (0.19.0)
|
||||
poltergeist (1.14.0)
|
||||
capybara (~> 2.1)
|
||||
cliver (~> 0.3.1)
|
||||
websocket-driver (>= 0.2.0)
|
||||
powerpack (0.1.1)
|
||||
prawn (2.0.2)
|
||||
pdf-core (~> 0.6.0)
|
||||
ttfunk (~> 1.4.0)
|
||||
prawn_rails (0.0.11)
|
||||
prawn (>= 0.11.1)
|
||||
railties (>= 3.0.0)
|
||||
pry (0.10.4)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.8.1)
|
||||
|
@ -471,7 +481,8 @@ GEM
|
|||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rainbow (2.2.1)
|
||||
rainbow (2.2.2)
|
||||
rake
|
||||
raindrops (0.17.0)
|
||||
rake (12.0.0)
|
||||
rb-fsevent (0.9.8)
|
||||
|
@ -522,7 +533,8 @@ GEM
|
|||
rspec-mocks (~> 3.5.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-support (3.5.0)
|
||||
rubocop (0.48.1)
|
||||
rubocop (0.49.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.3.3.1, < 3.0)
|
||||
powerpack (~> 0.1)
|
||||
rainbow (>= 1.99.1, < 3.0)
|
||||
|
@ -608,6 +620,7 @@ GEM
|
|||
tilt (2.0.5)
|
||||
timecop (0.8.1)
|
||||
trollop (2.1.2)
|
||||
ttfunk (1.4.0)
|
||||
turbolinks (5.0.1)
|
||||
turbolinks-source (~> 5)
|
||||
turbolinks-source (5.0.0)
|
||||
|
@ -618,7 +631,7 @@ GEM
|
|||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.2)
|
||||
unicode-display_width (1.1.3)
|
||||
unicode-display_width (1.2.1)
|
||||
unicode_utils (1.4.0)
|
||||
unicorn (5.2.0)
|
||||
kgio (~> 2.6)
|
||||
|
@ -674,6 +687,7 @@ DEPENDENCIES
|
|||
carrierwave
|
||||
chartkick
|
||||
clamav-client
|
||||
copy_carrierwave_file
|
||||
database_cleaner
|
||||
deep_cloneable (~> 2.2.1)
|
||||
devise
|
||||
|
@ -703,6 +717,8 @@ DEPENDENCIES
|
|||
openstack
|
||||
pg
|
||||
poltergeist
|
||||
prawn (~> 2.0.1)
|
||||
prawn_rails (~> 0.0.11)
|
||||
pry-byebug
|
||||
rack-handlers
|
||||
rails (= 5.0.0.1)
|
||||
|
@ -711,6 +727,7 @@ DEPENDENCIES
|
|||
rest-client
|
||||
rgeo-geojson
|
||||
rspec-rails (~> 3.0)
|
||||
rubocop
|
||||
sass-rails (~> 5.0)
|
||||
scenic
|
||||
scss_lint
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
# * zeus: 'zeus rspec' (requires the server to be started separetly)
|
||||
# * 'just' rspec: 'rspec'
|
||||
|
||||
|
||||
guard 'livereload' do
|
||||
extensions = {
|
||||
css: :css,
|
||||
|
|
|
@ -73,6 +73,7 @@ Pour exécuter les tests de l'application, plusieurs possibilités :
|
|||
|
||||
## Linting
|
||||
|
||||
- Faire tourner RuboCop : `bundle exec rubocop`
|
||||
- Linter les fichiers HAML : `bundle exec haml-lint app/views/`
|
||||
- Linter les fichiers SCSS : `bundle exec scss-lint app/assets/stylesheets/`
|
||||
|
||||
|
|
2
Rakefile
|
@ -19,7 +19,6 @@ task :deploy_ha do
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
task :deploy_old do
|
||||
domains = %w(37.187.154.237 37.187.249.111)
|
||||
domains.each do |domain|
|
||||
|
@ -27,7 +26,6 @@ task :deploy_old do
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
task :deploy_test do
|
||||
domains = %w(192.168.0.116)
|
||||
branch = 'clamav'
|
||||
|
|
1
app/assets/images/flag_of_europe.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="810" height="540"><desc>European flag</desc><defs><g id="d"><g id="b"><path id="a" d="M0 0v1h.5z" transform="rotate(18 3.157 -.5)"/><use xlink:href="#a" transform="scale(-1 1)"/></g><g id="c"><use xlink:href="#b" transform="rotate(72)"/><use xlink:href="#b" transform="rotate(144)"/></g><use xlink:href="#c" transform="scale(-1 1)"/></g></defs><path fill="#039" d="M0 0h810v540H0z"/><g fill="#fc0" transform="matrix(30 0 0 30 405 270)"><use xlink:href="#d" y="-6"/><use xlink:href="#d" y="6"/><g id="e"><use xlink:href="#d" x="-6"/><use xlink:href="#d" transform="rotate(-144 -2.344 -2.11)"/><use xlink:href="#d" transform="rotate(144 -2.11 -2.344)"/><use xlink:href="#d" transform="rotate(72 -4.663 -2.076)"/><use xlink:href="#d" transform="rotate(72 -5.076 .534)"/></g><use xlink:href="#e" transform="scale(-1 1)"/></g></svg>
|
After Width: | Height: | Size: 917 B |
1
app/assets/images/icons/account-circle.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><g stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M18.938 20.625C17.055 22.127 14.6 23.084 12 23.084c-2.614 0-5.015-.954-6.902-2.476l-.1-.943v-.831c0-2.33 4.67-3.5 7.002-3.5 2.33 0 6.999 1.17 6.999 3.5V20l-.063.625zM12 11.333a2.989 2.989 0 0 0 2.995-2.999c0-1.66-1.332-3-2.995-3a2.998 2.998 0 0 0-3.005 3A2.997 2.997 0 0 0 12 11.333z"/><path d="M23 12c0 6.075-4.925 11-11 11S1 18.075 1 12 5.925 1 12 1s11 4.925 11 11z"/></g><path d="M0 0h24v24H0z"/></g></svg>
|
After Width: | Height: | Size: 620 B |
1
app/assets/images/icons/search-blue.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path d="M17 9A8 8 0 1 1 1 9a8 8 0 0 1 16 0zm-2.187 5.875l8 8" stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/><path d="M0 0h24v24H0z"/></g></svg>
|
After Width: | Height: | Size: 298 B |
1
app/assets/images/icons/sign-out.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path d="M0 0h24v24H0z"/><g stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M13 12H3m6.438 4.242L13.68 12 9.437 7.757"/><path d="M3 16v3a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5c0-1.1-.901-2-2-2H5c-1.099 0-2 .9-2 2v3"/></g></g></svg>
|
After Width: | Height: | Size: 385 B |
1
app/assets/images/icons/switch-profile.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><g stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M11.595 11.813a2.319 2.319 0 0 0 2.323-2.327 2.319 2.319 0 0 0-2.323-2.326c-1.29 0-2.33 1.04-2.33 2.326a2.324 2.324 0 0 0 2.33 2.327zm-4.508 7.288V17.63c0-1.808 2.977-2.716 4.783-2.716 1.807 0 4.782.908 4.782 2.716v1.471l-.002.433a8.953 8.953 0 0 1-4.923 1.464A8.999 8.999 0 0 1 3.56 8.22m16.843 6.18A8.998 8.998 0 0 0 6.978 4.355"/><path d="M1 9.259l2.667-1.094 1.092 2.667m17.816 2.045l-2.154 1.606-1.607-2.152"/></g><path d="M0 0h24v24H0z"/></g></svg>
|
After Width: | Height: | Size: 665 B |
1
app/assets/images/login-with-fc-hover.svg
Normal file
After Width: | Height: | Size: 8.8 KiB |
1
app/assets/images/login-with-fc.svg
Normal file
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 1.9 KiB |
1
app/assets/images/pdf.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="550.801" height="550.801" viewBox="0 0 550.801 550.801"><path d="M160.381 282.225c0-14.832-10.299-23.684-28.474-23.684-7.414 0-12.437.715-15.071 1.432V307.6c3.114.707 6.942.949 12.192.949 19.391 0 31.353-9.809 31.353-26.324zM272.875 259.019c-8.145 0-13.397.717-16.519 1.435v105.523c3.116.729 8.142.729 12.69.729 33.017.231 54.554-17.946 54.554-56.474.242-33.513-19.385-51.213-50.725-51.213z"/><path d="M488.426 197.019H475.2v-63.816c0-.398-.063-.799-.116-1.202-.021-2.534-.827-5.023-2.562-6.995L366.325 3.694c-.032-.031-.063-.042-.085-.076-.633-.707-1.371-1.295-2.151-1.804a9.495 9.495 0 0 0-.706-.419 11.131 11.131 0 0 0-2.131-.896c-.2-.056-.38-.138-.58-.19A10.774 10.774 0 0 0 358.193 0H97.2C85.282 0 75.6 9.693 75.6 21.601v175.413H62.377c-17.049 0-30.873 13.818-30.873 30.873v160.545c0 17.043 13.824 30.87 30.873 30.87h13.224V529.2c0 11.907 9.682 21.601 21.6 21.601h356.4c11.907 0 21.6-9.693 21.6-21.601V419.302h13.226c17.044 0 30.871-13.827 30.871-30.87v-160.54c-.001-17.054-13.828-30.873-30.872-30.873zM97.2 21.605h250.193v110.513c0 5.967 4.841 10.8 10.8 10.8H453.6v54.108H97.2V21.605zm265.159 287.418c0 30.876-11.243 52.165-26.82 65.333-16.971 14.117-42.82 20.814-74.396 20.814-18.9 0-32.297-1.197-41.401-2.389V234.365c13.399-2.149 30.878-3.346 49.304-3.346 30.612 0 50.478 5.508 66.039 17.226 16.743 12.445 27.274 32.302 27.274 60.778zM80.7 393.499V234.365c11.241-1.904 27.042-3.346 49.296-3.346 22.491 0 38.527 4.308 49.291 12.928 10.292 8.131 17.215 21.534 17.215 37.328 0 15.799-5.25 29.198-14.829 38.285-12.442 11.728-30.865 16.996-52.407 16.996-4.778 0-9.1-.243-12.435-.723v57.67H80.7v-.004zm372.901 129.854H97.2V419.302h356.4v104.051zm31.297-261.226h-61.989v36.851h57.913v29.674h-57.913V393.5h-36.593V232.216h98.582v29.911z"/></svg>
|
After Width: | Height: | Size: 1.8 KiB |
18
app/assets/javascripts/new_design/application.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
||||
// listed below.
|
||||
//
|
||||
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
||||
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
||||
//
|
||||
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
||||
// compiled file.
|
||||
//
|
||||
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
||||
// about supported directives.
|
||||
//
|
||||
//= require jquery
|
||||
//= require jquery_ujs
|
||||
//= require turbolinks
|
||||
//= require highcharts
|
||||
//= require chartkick
|
||||
//= require_tree .
|
10
app/assets/javascripts/new_design/header.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
window.TPS = window.TPS || {};
|
||||
|
||||
$(document).on("click", "body", function () {
|
||||
$(".header-menu").removeClass("open fade-in-down");
|
||||
});
|
||||
|
||||
TPS.toggleHeaderMenu = function(event) {
|
||||
event.stopPropagation();
|
||||
$(".header-menu").toggleClass("open fade-in-down");
|
||||
}
|
|
@ -44,6 +44,8 @@
|
|||
// = require switch_menu
|
||||
// = require typeahead
|
||||
// = require users
|
||||
// = require attestation_template_edit
|
||||
// = require attestation_recapitulatif
|
||||
|
||||
// = require_self
|
||||
// = require bootstrap-datepicker3
|
||||
|
|
31
app/assets/stylesheets/attestation_recapitulatif.scss
Normal file
|
@ -0,0 +1,31 @@
|
|||
#attestation-recapitulatif {
|
||||
margin-top: 40px;
|
||||
|
||||
.details {
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
.left {
|
||||
position: relative;
|
||||
padding-left: 30px;
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 15px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.delivery {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
30
app/assets/stylesheets/attestation_template_edit.scss
Normal file
|
@ -0,0 +1,30 @@
|
|||
#attestation-template-edit {
|
||||
.notice {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.image-upload {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
input {
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
width: 90px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.balises {
|
||||
max-height: 180px;
|
||||
overflow-y: scroll;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.table {
|
||||
border: 1px solid #DDDDDD;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
|
@ -281,3 +281,8 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.motivation-text-area {
|
||||
color: #000000;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
|
|
@ -19,3 +19,8 @@
|
|||
max-width: $page-width + 2 * $default-padding;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
%animation {
|
||||
animation-fill-mode: forwards;
|
||||
animation-duration: 0.3s;
|
||||
}
|
||||
|
|
18
app/assets/stylesheets/new_design/animations.scss
Normal file
|
@ -0,0 +1,18 @@
|
|||
@import "placeholders";
|
||||
|
||||
@keyframes fade-in-down {
|
||||
0% {
|
||||
opacity: 0;
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.fade-in-down {
|
||||
@extend %animation;
|
||||
animation-name: fade-in-down;
|
||||
}
|
108
app/assets/stylesheets/new_design/auth.scss
Normal file
|
@ -0,0 +1,108 @@
|
|||
@import "colors";
|
||||
@import "placeholders";
|
||||
@import "mixins";
|
||||
|
||||
$auth-breakpoint: 820px;
|
||||
|
||||
@media (max-width: $auth-breakpoint) {
|
||||
.preview {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.two-columns .column.auth-form {
|
||||
@include horizontal-padding(0);
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $auth-breakpoint) {
|
||||
.two-columns.auth {
|
||||
background: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
.preview {
|
||||
font-size: 24px;
|
||||
|
||||
.paperless-logo {
|
||||
width: 100%;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: $blue;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.close-procedure {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.procedure-title {
|
||||
font-size: 30px;
|
||||
margin: 50px 0 32px;
|
||||
}
|
||||
|
||||
.procedure-description {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.procedure-logos {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
||||
img {
|
||||
max-height: 130px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.auth-form {
|
||||
font-size: 14px;
|
||||
|
||||
.reset-password {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.separation {
|
||||
font-size: 14px;
|
||||
color: $grey;
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.login-with-fc {
|
||||
display: inline-block;
|
||||
height: 52px;
|
||||
width: 186px;
|
||||
margin: auto;
|
||||
margin-bottom: 8px;
|
||||
background-image: image-url("login-with-fc.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-image: image-url("login-with-fc-hover.svg");
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
margin-top: 60px;
|
||||
margin-bottom: 20px;
|
||||
background-color: $grey;
|
||||
border: none;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.register {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,14 +2,6 @@
|
|||
@import "colors";
|
||||
|
||||
.avis-sign-up {
|
||||
display: flex;
|
||||
|
||||
.left,
|
||||
.right {
|
||||
width: 50%;
|
||||
padding: 60px 86px;
|
||||
}
|
||||
|
||||
.left {
|
||||
p {
|
||||
margin: auto;
|
||||
|
@ -28,64 +20,4 @@
|
|||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
background-color: $light-grey;
|
||||
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
form {
|
||||
max-width: 420px;
|
||||
}
|
||||
|
||||
label,
|
||||
input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 14px;
|
||||
line-height: 1.57;
|
||||
margin: 24px 0 8px;
|
||||
}
|
||||
|
||||
input {
|
||||
border: solid 1px $border-grey;
|
||||
border-radius: 4px;
|
||||
height: 56px;
|
||||
padding: 0 15px;
|
||||
font-family: Muli;
|
||||
font-size: 14px;
|
||||
|
||||
&:disabled {
|
||||
background-color: $border-grey;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
display: inline-block;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
border: none;
|
||||
border-radius: 60px;
|
||||
background-color: $blue;
|
||||
color: #FFFFFF;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin: 55px 0;
|
||||
|
||||
&:hover {
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
background-color: $light-blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
51
app/assets/stylesheets/new_design/buttons.scss
Normal file
|
@ -0,0 +1,51 @@
|
|||
@import "colors";
|
||||
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding: 8px 16px;
|
||||
border-radius: 30px;
|
||||
border: 1px solid $border-grey;
|
||||
font-size: 14px;
|
||||
background-color: #FFFFFF;
|
||||
color: $black;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: $light-grey;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.primary {
|
||||
color: #FFFFFF;
|
||||
border-color: $blue;
|
||||
background-color: $blue;
|
||||
|
||||
&:hover {
|
||||
background: $light-blue;
|
||||
}
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
color: $blue;
|
||||
border-color: $blue;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
&:hover {
|
||||
color: #FFFFFF;
|
||||
background: $light-blue;
|
||||
}
|
||||
}
|
||||
|
||||
&.large {
|
||||
font-size: 18px;
|
||||
padding: 15px 32px;
|
||||
}
|
||||
|
||||
&.expand {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.link {
|
||||
color: $blue;
|
||||
}
|
|
@ -5,3 +5,8 @@ body {
|
|||
font-size: 16px;
|
||||
line-height: 1.42857143;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
37
app/assets/stylesheets/new_design/forms.scss
Normal file
|
@ -0,0 +1,37 @@
|
|||
@import "colors";
|
||||
|
||||
.form {
|
||||
h1 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
label,
|
||||
input {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
label,
|
||||
input[type=submit] {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 8px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
input[type=text],
|
||||
input[type=email],
|
||||
input[type=password] {
|
||||
display: block;
|
||||
width: 100%;
|
||||
border-radius: 4px;
|
||||
border: solid 1px $border-grey;
|
||||
padding: 16px;
|
||||
|
||||
&:disabled {
|
||||
background-color: $border-grey;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,6 +70,7 @@ $landing-breakpoint: 1040px;
|
|||
color: #FFFFFF;
|
||||
font-size: 24px;
|
||||
margin-top: 30px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #FFFFFF;
|
||||
|
@ -286,6 +287,7 @@ $cta-panel-button-border-size: 2px;
|
|||
color: #FFFFFF;
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #FFFFFF;
|
||||
|
|
32
app/assets/stylesheets/new_design/layouts.scss
Normal file
|
@ -0,0 +1,32 @@
|
|||
@import "colors";
|
||||
@import "constants";
|
||||
@import "placeholders";
|
||||
|
||||
.two-columns {
|
||||
$column-padding: 60px;
|
||||
$two-columns-breakpoint: $page-width + (2 * $column-padding);
|
||||
|
||||
background: linear-gradient(to right, #FFFFFF 0%, #FFFFFF 50%, $light-grey 50%, $light-grey 100%);
|
||||
|
||||
.columns-container {
|
||||
@extend %page-width-container;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.column {
|
||||
width: 50%;
|
||||
padding: $column-padding;
|
||||
|
||||
@media (min-width: $two-columns-breakpoint) {
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,39 +17,100 @@
|
|||
@extend %page-width-container;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-top: 17px;
|
||||
}
|
||||
|
||||
.header-logo {
|
||||
margin-top: 17px;
|
||||
.header-right-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> li {
|
||||
@include horizontal-padding(8px);
|
||||
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$header-login-button-height: 36px;
|
||||
$header-login-button-border-size: 1px;
|
||||
.header-search {
|
||||
position: relative;
|
||||
|
||||
.header-login-button {
|
||||
@include horizontal-padding(16px);
|
||||
.form input[type=text] {
|
||||
padding: 9px;
|
||||
padding-right: 42px;
|
||||
float: right;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
display: inline-block;
|
||||
height: $header-login-button-height;
|
||||
line-height: $header-login-button-height - (2 * $header-login-button-border-size);
|
||||
border-radius: $header-login-button-height;
|
||||
border: $header-login-button-border-size solid $blue;
|
||||
color: $blue;
|
||||
font-size: 14px;
|
||||
margin-top: 18px;
|
||||
button {
|
||||
padding: 6px 9px;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
|
||||
&:hover {
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
background-color: $light-blue;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
color: $blue;
|
||||
text-decoration: none;
|
||||
.header-menu-opener {
|
||||
position: relative;
|
||||
|
||||
img {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover:focus {
|
||||
color: #FFFFFF;
|
||||
.header-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 34px;
|
||||
font-size: 14px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid $border-grey;
|
||||
min-width: 270px;
|
||||
max-width: 340px;
|
||||
|
||||
&.open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
li {
|
||||
border-bottom: 1px solid $border-grey;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
align-items: center;
|
||||
padding: 14px;
|
||||
color: $grey;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
img {
|
||||
margin-right: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
display: flex;
|
||||
color: $black;
|
||||
|
||||
&:hover {
|
||||
background: $light-grey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
app/assets/stylesheets/new_design/patron.scss
Normal file
|
@ -0,0 +1,11 @@
|
|||
@import "placeholders";
|
||||
|
||||
.patron {
|
||||
.patron-container {
|
||||
@extend %page-width-container;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,10 @@
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
|
64
app/controllers/admin/attestation_templates_controller.rb
Normal file
|
@ -0,0 +1,64 @@
|
|||
class Admin::AttestationTemplatesController < AdminController
|
||||
before_action :retrieve_procedure
|
||||
|
||||
def edit
|
||||
@attestation_template = @procedure.attestation_template || AttestationTemplate.new(procedure: @procedure)
|
||||
end
|
||||
|
||||
def update
|
||||
attestation_template = @procedure.attestation_template
|
||||
|
||||
if attestation_template.update_attributes(activated_attestation_params)
|
||||
flash.notice = "L'attestation a bien été modifiée"
|
||||
else
|
||||
flash.alert = attestation_template.errors.full_messages.join('<br>')
|
||||
end
|
||||
|
||||
redirect_to edit_admin_procedure_attestation_template_path(@procedure)
|
||||
end
|
||||
|
||||
def create
|
||||
attestation_template = AttestationTemplate.new(activated_attestation_params.merge(procedure_id: @procedure.id))
|
||||
|
||||
if attestation_template.save
|
||||
flash.notice = "L'attestation a bien été sauvegardée"
|
||||
else
|
||||
flash.alert = attestation_template.errors.full_messages.join('<br>')
|
||||
end
|
||||
|
||||
redirect_to edit_admin_procedure_attestation_template_path(@procedure)
|
||||
end
|
||||
|
||||
def disactivate
|
||||
attestation_template = @procedure.attestation_template
|
||||
attestation_template.activated = false
|
||||
attestation_template.save
|
||||
|
||||
flash.notice = "L'attestation a bien été désactivée"
|
||||
|
||||
redirect_to edit_admin_procedure_attestation_template_path(@procedure)
|
||||
end
|
||||
|
||||
def preview
|
||||
@title = activated_attestation_params[:title]
|
||||
@body = activated_attestation_params[:body]
|
||||
@footer = activated_attestation_params[:footer]
|
||||
@created_at = DateTime.now
|
||||
|
||||
# In a case of a preview, when the user does not change its images,
|
||||
# the images are not uploaded and thus should be retrieved from previous
|
||||
# attestation_template
|
||||
@logo = activated_attestation_params[:logo] || @procedure.attestation_template&.logo
|
||||
@signature = activated_attestation_params[:signature] || @procedure.attestation_template&.signature
|
||||
|
||||
render 'admin/attestation_templates/show', formats: [:pdf]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def activated_attestation_params
|
||||
params.require(:attestation_template)
|
||||
.permit(:title, :body, :footer, :logo, :signature)
|
||||
.merge(activated: true)
|
||||
end
|
||||
end
|
|
@ -7,10 +7,10 @@ class Admin::GestionnairesController < AdminController
|
|||
current_administrateur.gestionnaires,
|
||||
partial: "admin/gestionnaires/list",
|
||||
array: true
|
||||
|
||||
@gestionnaire ||= Gestionnaire.new
|
||||
end
|
||||
|
||||
|
||||
def create
|
||||
@gestionnaire = Gestionnaire.find_by_email(params[:gestionnaire][:email])
|
||||
procedure_id = params[:procedure_id]
|
||||
|
@ -47,7 +47,6 @@ class Admin::GestionnairesController < AdminController
|
|||
User.create(attributes)
|
||||
flash.notice = 'Accompagnateur ajouté'
|
||||
GestionnaireMailer.new_gestionnaire(@gestionnaire.email, @gestionnaire.password).deliver_now!
|
||||
GestionnaireMailer.new_assignement(@gestionnaire.email, current_administrateur.email).deliver_now!
|
||||
else
|
||||
flash.alert = @gestionnaire.errors.full_messages.join('<br />').html_safe
|
||||
end
|
||||
|
@ -57,7 +56,6 @@ class Admin::GestionnairesController < AdminController
|
|||
if current_administrateur.gestionnaires.include? @gestionnaire
|
||||
flash.alert = 'Accompagnateur déjà ajouté'
|
||||
else
|
||||
GestionnaireMailer.new_assignement(@gestionnaire.email, current_administrateur.email).deliver_now!
|
||||
@gestionnaire.administrateurs.push current_administrateur
|
||||
flash.notice = 'Accompagnateur ajouté'
|
||||
#TODO Mailer no assign_to
|
||||
|
|
|
@ -40,7 +40,14 @@ class Admin::ProceduresController < AdminController
|
|||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def hide
|
||||
procedure = Procedure.find(params[:id])
|
||||
procedure.hide!
|
||||
|
||||
flash.notice = "Procédure supprimée, en cas d'erreur contactez nous : contact@tps.apientreprise.fr"
|
||||
redirect_to admin_procedures_draft_path
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -122,20 +129,22 @@ class Admin::ProceduresController < AdminController
|
|||
end
|
||||
|
||||
def transfer
|
||||
admin = Administrateur.find_by_email(params[:email_admin])
|
||||
|
||||
return render '/admin/procedures/transfer', formats: 'js', status: 404 if admin.nil?
|
||||
admin = Administrateur.find_by_email(params[:email_admin].downcase)
|
||||
|
||||
if admin.nil?
|
||||
render '/admin/procedures/transfer', formats: 'js', status: 404
|
||||
else
|
||||
procedure = current_administrateur.procedures.find(params[:procedure_id])
|
||||
clone_procedure = procedure.clone
|
||||
|
||||
clone_procedure.administrateur = admin
|
||||
clone_procedure.save
|
||||
|
||||
flash.now.notice = "La procédure a correctement été cloné vers le nouvel administrateur."
|
||||
flash.now.notice = "La procédure a correctement été clonée vers le nouvel administrateur."
|
||||
|
||||
render '/admin/procedures/transfer', formats: 'js', status: 200
|
||||
end
|
||||
end
|
||||
|
||||
def archive
|
||||
procedure = current_administrateur.procedures.find(params[:procedure_id])
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Administrateurs::SessionsController < Sessions::SessionsController
|
||||
layout "new_application"
|
||||
|
||||
def demo
|
||||
return redirect_to root_path if Rails.env.production?
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@ class AdministrationsController < ApplicationController
|
|||
Administrateur.all.order(:email),
|
||||
partial: "administrations/list",
|
||||
array: true
|
||||
|
||||
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -20,7 +18,7 @@ class AdministrationsController < ApplicationController
|
|||
|
||||
if admin.save
|
||||
flash.notice = "Administrateur créé"
|
||||
NewAdminMailer.new_admin_email(admin, params[:administrateur][:password]).deliver_now!
|
||||
NewAdminMailer.new_admin_email(admin).deliver_now!
|
||||
else
|
||||
flash.alert = admin.errors.full_messages.join('<br>').html_safe
|
||||
end
|
||||
|
|
|
@ -13,5 +13,4 @@ class API::V1::ProceduresController < APIController
|
|||
Rails.logger.error(e.message)
|
||||
render json: {}, status: 404
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ class ApplicationController < ActionController::Base
|
|||
protect_from_forgery with: :exception
|
||||
before_action :check_browser
|
||||
before_action :load_navbar_left_pannel_partial_url
|
||||
before_action :set_raven_context
|
||||
|
||||
def default_url_options
|
||||
return {protocol: 'https'} if Rails.env.staging? || Rails.env.production?
|
||||
|
@ -40,4 +41,25 @@ class ApplicationController < ActionController::Base
|
|||
redirect_to new_user_session_path
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_raven_context
|
||||
context = { ip_address: request.ip }
|
||||
|
||||
logged_models = [
|
||||
current_user,
|
||||
current_gestionnaire,
|
||||
current_administrateur,
|
||||
current_administration
|
||||
].compact
|
||||
|
||||
context[:email] = logged_models.first&.email
|
||||
context[:id] = logged_models.first&.id
|
||||
|
||||
class_names = logged_models.map { |model| model.class.name }
|
||||
context[:classes] = class_names.any? ? class_names.join(', ') : 'Guest'
|
||||
|
||||
Raven.user_context(context)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class Backoffice::AvisController < ApplicationController
|
||||
|
||||
before_action :authenticate_gestionnaire!, except: [:sign_up, :create_gestionnaire]
|
||||
before_action :redirect_if_no_sign_up_needed, only: [:sign_up]
|
||||
before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up, :create_gestionnaire]
|
||||
|
@ -50,7 +49,7 @@ class Backoffice::AvisController < ApplicationController
|
|||
avis = Avis.find(params[:id])
|
||||
redirect_to url_for(backoffice_dossier_path(avis.dossier_id))
|
||||
else
|
||||
flash[:alert] = gestionnaire.errors.full_messages.join('<br>')
|
||||
flash[:alert] = gestionnaire.errors.full_messages
|
||||
redirect_to url_for(avis_sign_up_path(params[:id], email))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,5 +21,4 @@ class Backoffice::Dossiers::ProcedureController < Backoffice::DossiersListContro
|
|||
def retrieve_procedure
|
||||
current_gestionnaire.procedures.find params[:id]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Backoffice::DossiersController < Backoffice::DossiersListController
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
respond_to :html, :xlsx, :ods, :csv
|
||||
|
||||
prepend_before_action :store_current_location, only: :show
|
||||
|
@ -103,41 +105,44 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
redirect_to backoffice_dossier_path(id: dossier.id)
|
||||
end
|
||||
|
||||
def refuse
|
||||
def process_dossier
|
||||
create_dossier_facade params[:dossier_id]
|
||||
|
||||
dossier = @facade.dossier
|
||||
|
||||
dossier.next_step! 'gestionnaire', 'refuse'
|
||||
flash.notice = 'Dossier considéré comme refusé.'
|
||||
|
||||
NotificationMailer.send_notification(dossier, dossier.procedure.refused_mail_template).deliver_now!
|
||||
|
||||
redirect_to backoffice_dossier_path(id: dossier.id)
|
||||
if params[:dossier] && params[:dossier][:motivation].present?
|
||||
motivation = params[:dossier][:motivation]
|
||||
end
|
||||
|
||||
def without_continuation
|
||||
create_dossier_facade params[:dossier_id]
|
||||
|
||||
dossier = @facade.dossier
|
||||
|
||||
dossier.next_step! 'gestionnaire', 'without_continuation'
|
||||
flash.notice = 'Dossier considéré comme sans suite.'
|
||||
|
||||
NotificationMailer.send_notification(dossier, dossier.procedure.without_continuation_mail_template).deliver_now!
|
||||
|
||||
redirect_to backoffice_dossier_path(id: dossier.id)
|
||||
case params[:process_action]
|
||||
when "refuse"
|
||||
next_step = "refuse"
|
||||
notice = "Dossier considéré comme refusé."
|
||||
template = dossier.procedure.refused_mail_template
|
||||
when "without_continuation"
|
||||
next_step = "without_continuation"
|
||||
notice = "Dossier considéré comme sans suite."
|
||||
template = dossier.procedure.without_continuation_mail_template
|
||||
when "close"
|
||||
next_step = "close"
|
||||
notice = "Dossier traité avec succès."
|
||||
template = dossier.procedure.closed_mail_template
|
||||
end
|
||||
|
||||
def close
|
||||
create_dossier_facade params[:dossier_id]
|
||||
dossier.next_step! 'gestionnaire', next_step, motivation
|
||||
|
||||
dossier = @facade.dossier
|
||||
# needed to force Carrierwave to provide dossier.attestation.pdf.read
|
||||
# when the Feature.remote_storage is true, otherwise pdf.read is a closed stream.
|
||||
dossier.reload
|
||||
|
||||
dossier.next_step! 'gestionnaire', 'close'
|
||||
flash.notice = 'Dossier traité avec succès.'
|
||||
attestation_pdf = nil
|
||||
if check_attestation_emailable(dossier)
|
||||
attestation_pdf = dossier.attestation.pdf.read
|
||||
end
|
||||
|
||||
NotificationMailer.send_notification(dossier, dossier.procedure.closed_mail_template).deliver_now!
|
||||
flash.notice = notice
|
||||
|
||||
NotificationMailer.send_notification(dossier, template, attestation_pdf).deliver_now!
|
||||
|
||||
redirect_to backoffice_dossier_path(id: dossier.id)
|
||||
end
|
||||
|
@ -172,7 +177,6 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
redirect_to backoffice_dossiers_path
|
||||
end
|
||||
|
||||
|
||||
def unarchive
|
||||
@dossier = Dossier.find(params[:id])
|
||||
if @dossier.archived
|
||||
|
@ -193,6 +197,16 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
|
||||
private
|
||||
|
||||
def check_attestation_emailable(dossier)
|
||||
if dossier&.attestation&.emailable? == false
|
||||
human_size = number_to_human_size(dossier.attestation.pdf.size)
|
||||
msg = "the attestation of the dossier #{dossier.id} cannot be mailed because it is too heavy: #{human_size}"
|
||||
capture_message(msg, level: 'error')
|
||||
end
|
||||
|
||||
dossier&.attestation&.emailable?
|
||||
end
|
||||
|
||||
def store_current_location
|
||||
if !gestionnaire_signed_in?
|
||||
store_location_for(:gestionnaire, request.url)
|
||||
|
|
|
@ -31,7 +31,6 @@ class Backoffice::DossiersListController < ApplicationController
|
|||
dossiers_list_facade liste
|
||||
service = dossiers_list_facade.service
|
||||
|
||||
|
||||
if param_page.nil?
|
||||
params[:dossiers_smart_listing] = {page: dossiers_list_facade.service.default_page}
|
||||
end
|
||||
|
|
|
@ -11,7 +11,7 @@ class Backoffice::PrivateFormulairesController < ApplicationController
|
|||
if champs_service_errors.empty?
|
||||
flash[:notice] = "Formulaire enregistré"
|
||||
else
|
||||
flash[:alert] = champs_service_errors.join('<br>').html_safe
|
||||
flash[:alert] = champs_service_errors
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class CguController < ApplicationController
|
||||
def index
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Gestionnaires::SessionsController < Sessions::SessionsController
|
||||
layout "new_application"
|
||||
|
||||
def demo
|
||||
return redirect_to root_path if Rails.env.production?
|
||||
|
||||
|
|
13
app/controllers/new_gestionnaire/dossiers_controller.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
module NewGestionnaire
|
||||
class DossiersController < ProceduresController
|
||||
def attestation
|
||||
send_data(dossier.attestation.pdf.read, filename: 'attestation.pdf', type: 'application/pdf')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def dossier
|
||||
Dossier.find(params[:dossier_id])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
module NewGestionnaire
|
||||
class GestionnaireController < ApplicationController
|
||||
before_action :authenticate_gestionnaire!
|
||||
end
|
||||
end
|
18
app/controllers/new_gestionnaire/procedures_controller.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
module NewGestionnaire
|
||||
class ProceduresController < GestionnaireController
|
||||
before_action :ensure_ownership!
|
||||
|
||||
private
|
||||
|
||||
def procedure
|
||||
Procedure.find(params[:procedure_id])
|
||||
end
|
||||
|
||||
def ensure_ownership!
|
||||
if !procedure.gestionnaires.include?(current_gestionnaire)
|
||||
flash[:alert] = "Vous n'avez pas accès à cette procédure"
|
||||
redirect_to root_path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
22
app/controllers/new_user/dossiers_controller.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
module NewUser
|
||||
class DossiersController < UserController
|
||||
before_action :ensure_ownership!
|
||||
|
||||
def attestation
|
||||
send_data(dossier.attestation.pdf.read, filename: 'attestation.pdf', type: 'application/pdf')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def dossier
|
||||
Dossier.find(params[:dossier_id])
|
||||
end
|
||||
|
||||
def ensure_ownership!
|
||||
if dossier.user != current_user
|
||||
flash[:alert] = "Vous n'avez pas accès à ce dossier"
|
||||
redirect_to root_path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
5
app/controllers/new_user/user_controller.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
module NewUser
|
||||
class UserController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
end
|
||||
end
|
|
@ -1,4 +1,6 @@
|
|||
class RootController < ApplicationController
|
||||
layout 'new_application'
|
||||
|
||||
def index
|
||||
if administrateur_signed_in?
|
||||
return redirect_to admin_procedures_path
|
||||
|
@ -26,6 +28,9 @@ class RootController < ApplicationController
|
|||
return redirect_to administrations_path
|
||||
end
|
||||
|
||||
render 'landing', :layout => 'new_application'
|
||||
render 'landing'
|
||||
end
|
||||
|
||||
def patron
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,13 +29,20 @@ class StatsController < ApplicationController
|
|||
@avis_usage = avis_usage
|
||||
@avis_average_answer_time = avis_average_answer_time
|
||||
@avis_answer_percentages = avis_answer_percentages
|
||||
|
||||
@motivation_usage_dossier = motivation_usage_dossier
|
||||
@motivation_usage_procedure = motivation_usage_procedure
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def last_four_months_hash(association, date_attribute = :created_at)
|
||||
min_date = 3.months.ago.beginning_of_month.to_date
|
||||
if administration_signed_in?
|
||||
max_date = Time.now.to_date
|
||||
else
|
||||
max_date = Time.now.beginning_of_month - 1.second
|
||||
end
|
||||
|
||||
association
|
||||
.where(date_attribute => min_date..max_date)
|
||||
|
@ -70,6 +77,10 @@ class StatsController < ApplicationController
|
|||
(collection.sum.to_f / collection.size).round(2)
|
||||
end
|
||||
|
||||
def percentage(numerator, denominator)
|
||||
((numerator.to_f / denominator) * 100).round(2)
|
||||
end
|
||||
|
||||
def dossier_instruction_mean_time(dossiers)
|
||||
# In the 12 last months, we compute for each month
|
||||
# the average time it took to instruct a dossier
|
||||
|
@ -166,7 +177,7 @@ class StatsController < ApplicationController
|
|||
result = 0
|
||||
else
|
||||
weekly_dossier_with_avis_count = weekly_dossiers.select { |dossier| dossier.avis.present? }.count
|
||||
result = ((weekly_dossier_with_avis_count.to_f / weekly_dossiers_count) * 100).round(2)
|
||||
result = percentage(weekly_dossier_with_avis_count, weekly_dossiers_count)
|
||||
end
|
||||
|
||||
[min_date.to_i, result]
|
||||
|
@ -199,10 +210,58 @@ class StatsController < ApplicationController
|
|||
[min_date.to_i, 0]
|
||||
else
|
||||
answered_weekly_avis_count = weekly_avis.with_answer.count
|
||||
result = ((answered_weekly_avis_count.to_f / weekly_avis_count) * 100).round(2)
|
||||
result = percentage(answered_weekly_avis_count, weekly_avis_count)
|
||||
|
||||
[min_date.to_i, result]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def motivation_usage_dossier
|
||||
[3.week.ago, 2.week.ago, 1.week.ago].map do |date|
|
||||
min_date = date.beginning_of_week
|
||||
max_date = date.end_of_week
|
||||
|
||||
weekly_termine_dossiers = Dossier.where(processed_at: min_date..max_date)
|
||||
weekly_termine_dossiers_count = weekly_termine_dossiers.count
|
||||
weekly_termine_dossiers_with_motivation_count = weekly_termine_dossiers.where.not(motivation: nil).count
|
||||
|
||||
if weekly_termine_dossiers_count == 0
|
||||
result = 0
|
||||
else
|
||||
result = percentage(weekly_termine_dossiers_with_motivation_count, weekly_termine_dossiers_count)
|
||||
end
|
||||
|
||||
[l(max_date, format: '%d/%m/%Y'), result]
|
||||
end
|
||||
end
|
||||
|
||||
def motivation_usage_procedure
|
||||
[3.week.ago, 2.week.ago, 1.week.ago].map do |date|
|
||||
min_date = date.beginning_of_week
|
||||
max_date = date.end_of_week
|
||||
|
||||
procedures_with_dossier_processed_this_week = Procedure
|
||||
.joins(:dossiers)
|
||||
.where(dossiers: { processed_at: min_date..max_date })
|
||||
|
||||
procedures_with_dossier_processed_this_week_count = procedures_with_dossier_processed_this_week
|
||||
.uniq
|
||||
.count
|
||||
|
||||
procedures_with_dossier_processed_this_week_and_with_motivation_count = procedures_with_dossier_processed_this_week
|
||||
.where
|
||||
.not(dossiers: { motivation: nil })
|
||||
.uniq
|
||||
.count
|
||||
|
||||
if procedures_with_dossier_processed_this_week_count == 0
|
||||
result = 0
|
||||
else
|
||||
result = percentage(procedures_with_dossier_processed_this_week_and_with_motivation_count, procedures_with_dossier_processed_this_week_count)
|
||||
end
|
||||
|
||||
[l(max_date, format: '%d/%m/%Y'), result]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Users::RegistrationsController < Devise::RegistrationsController
|
||||
layout "new_application"
|
||||
|
||||
# before_action :configure_sign_up_params, only: [:create]
|
||||
# before_action :configure_account_update_params, only: [:update]
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Users::SessionsController < Sessions::SessionsController
|
||||
layout "new_application"
|
||||
|
||||
# before_action :configure_sign_in_params, only: [:create]
|
||||
|
||||
def demo
|
||||
|
|
|
@ -16,7 +16,7 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
def authorized_routes? controller
|
||||
redirect_to_root_path 'Le status de votre dossier n\'autorise pas cette URL' unless UserRoutesAuthorizationService.authorized_route?(
|
||||
redirect_to_root_path 'Le statut de votre dossier n\'autorise pas cette URL' unless UserRoutesAuthorizationService.authorized_route?(
|
||||
controller,
|
||||
current_user_dossier)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
class DossiersDecorator < Draper::CollectionDecorator
|
||||
delegate :current_page, :per_page, :offset, :total_entries, :total_pages
|
||||
|
||||
end
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
class EtablissementDecorator < Draper::Decorator
|
||||
delegate_all
|
||||
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class ProcedureDecorator < Draper::Decorator
|
||||
|
||||
delegate_all
|
||||
|
||||
def lien
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
class ProceduresDecorator < Draper::CollectionDecorator
|
||||
delegate :current_page, :per_page, :offset, :total_entries, :total_pages
|
||||
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class TypeDeChampDecorator < Draper::Decorator
|
||||
|
||||
delegate_all
|
||||
|
||||
def button_up params
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
class TypeDeChampPrivateDecorator < TypeDeChampDecorator
|
||||
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class DossierFacades
|
||||
|
||||
#TODO rechercher en fonction de la personne/email
|
||||
def initialize(dossier_id, email, champ_id = nil)
|
||||
@dossier = Dossier.find(dossier_id)
|
||||
|
|
|
@ -80,5 +80,4 @@ class DossiersListFacades
|
|||
def base_url liste
|
||||
@procedure.nil? ? backoffice_dossiers_path(liste: liste) : backoffice_dossiers_procedure_path(id: @procedure.id, liste: liste)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class InviteDossierFacades < DossierFacades
|
||||
|
||||
#TODO rechercher en fonction de la personne/email
|
||||
def initialize id, email
|
||||
@dossier = Invite.where(email: email, id: id).first!.dossier
|
||||
|
|
14
app/helpers/application_helper.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
module ApplicationHelper
|
||||
def flash_class(level)
|
||||
case level
|
||||
when "notice" then "alert-success"
|
||||
when "alert" then "alert-danger"
|
||||
end
|
||||
end
|
||||
|
||||
def current_email
|
||||
current_user.try(:email) ||
|
||||
current_gestionnaire.try(:email) ||
|
||||
current_administrateur.try(:email)
|
||||
end
|
||||
end
|
8
app/helpers/devise_helper.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
module DeviseHelper
|
||||
def devise_error_messages!
|
||||
if resource.errors.full_messages.any?
|
||||
flash.now[:alert] = resource.errors.full_messages
|
||||
end
|
||||
''
|
||||
end
|
||||
end
|
|
@ -1,7 +1,6 @@
|
|||
module Carto
|
||||
module GeoAPI
|
||||
class Driver
|
||||
|
||||
def self.regions
|
||||
call regions_url
|
||||
end
|
||||
|
@ -29,7 +28,6 @@ module Carto
|
|||
rescue RestClient::ServiceUnavailable
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,7 +12,6 @@ class SIADE::RNAAdapter
|
|||
|
||||
data_source[:association].each do |k, v|
|
||||
params[k] = v if attr_to_fetch.include?(k)
|
||||
|
||||
end
|
||||
|
||||
params[:association_id] = params[:id]
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
class AvisMailer < ApplicationMailer
|
||||
|
||||
def avis_invitation(avis)
|
||||
@avis = avis
|
||||
email = @avis.gestionnaire.try(:email) || @avis.email
|
||||
mail(to: email, subject: "Donnez votre avis sur le dossier nº #{@avis.dossier.id} (#{@avis.dossier.procedure.libelle})")
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
class GestionnaireMailer < ApplicationMailer
|
||||
layout 'mailers/layout'
|
||||
|
||||
def new_gestionnaire email, password
|
||||
send_mail email, password, "Vous avez été nommé accompagnateur sur la plateforme TPS"
|
||||
end
|
||||
|
||||
def new_assignement email, email_admin
|
||||
send_mail email, email_admin, "Vous avez été assigné à un nouvel administrateur sur la plateforme TPS"
|
||||
end
|
||||
|
||||
def last_week_overview(gestionnaire, overview)
|
||||
headers['X-mailjet-campaign'] = 'last_week_overview'
|
||||
send_mail gestionnaire.email, overview, 'Résumé de la semaine'
|
||||
send_mail gestionnaire.email, overview, 'Vos activités sur TPS'
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class InviteMailer < ApplicationMailer
|
||||
|
||||
def invite_user invite
|
||||
vars_mailer invite
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
class NewAdminMailer < ApplicationMailer
|
||||
def new_admin_email admin, password
|
||||
|
||||
def new_admin_email admin
|
||||
@admin = admin
|
||||
@password = password
|
||||
|
||||
mail(to: 'tech@tps.apientreprise.fr',
|
||||
subject: "Création d'un compte Admin TPS")
|
||||
|
|
|
@ -3,12 +3,16 @@ class NotificationMailer < ApplicationMailer
|
|||
|
||||
after_action :create_commentaire_for_notification, only: :send_notification
|
||||
|
||||
def send_notification(dossier, mail_template)
|
||||
def send_notification(dossier, mail_template, attestation = nil)
|
||||
vars_mailer(dossier)
|
||||
|
||||
@object = mail_template.object_for_dossier dossier
|
||||
@body = mail_template.body_for_dossier dossier
|
||||
|
||||
if attestation.present?
|
||||
attachments['attestation.pdf'] = attestation
|
||||
end
|
||||
|
||||
mail(subject: @object) { |format| format.html { @body } }
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
class WelcomeMailer < ApplicationMailer
|
||||
def welcome_email user
|
||||
|
||||
@user = user
|
||||
|
||||
mail(to: user.email,
|
||||
|
|
11
app/models/attestation.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
class Attestation < ApplicationRecord
|
||||
belongs_to :dossier
|
||||
|
||||
mount_uploader :pdf, AttestationUploader
|
||||
|
||||
MAX_SIZE_EMAILABLE = 2.megabytes
|
||||
|
||||
def emailable?
|
||||
pdf.size <= MAX_SIZE_EMAILABLE
|
||||
end
|
||||
end
|
145
app/models/attestation_template.rb
Normal file
|
@ -0,0 +1,145 @@
|
|||
class AttestationTemplate < ApplicationRecord
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
belongs_to :procedure
|
||||
|
||||
mount_uploader :logo, AttestationTemplateImageUploader
|
||||
mount_uploader :signature, AttestationTemplateImageUploader
|
||||
|
||||
validate :logo_signature_file_size
|
||||
validates :footer, length: { maximum: 190 }
|
||||
|
||||
FILE_MAX_SIZE_IN_MB = 0.5
|
||||
|
||||
def tags
|
||||
if procedure.for_individual?
|
||||
identity_tags = individual_tags
|
||||
else
|
||||
identity_tags = entreprise_tags + etablissement_tags
|
||||
end
|
||||
|
||||
identity_tags + dossier_tags + procedure_type_de_champ_public_private_tags
|
||||
end
|
||||
|
||||
def attestation_for(dossier)
|
||||
Attestation.new(title: replace_tags(title, dossier), pdf: build_pdf(dossier))
|
||||
end
|
||||
|
||||
def dup
|
||||
result = AttestationTemplate.new(title: title, body: body, footer: footer, activated: activated)
|
||||
|
||||
if logo.present?
|
||||
CopyCarrierwaveFile::CopyFileService.new(self, result, :logo).set_file
|
||||
end
|
||||
|
||||
if signature.present?
|
||||
CopyCarrierwaveFile::CopyFileService.new(self, result, :signature).set_file
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def logo_signature_file_size
|
||||
%i[logo signature]
|
||||
.select { |file_name| send(file_name).present? }
|
||||
.each { |file_name| file_size_check(file_name) }
|
||||
end
|
||||
|
||||
def file_size_check(file_name)
|
||||
if send(file_name).file.size.to_f > FILE_MAX_SIZE_IN_MB.megabyte.to_f
|
||||
errors.add(file_name, " : vous ne pouvez pas charger une image de plus de #{number_with_delimiter(FILE_MAX_SIZE_IN_MB, locale: :fr)} Mo")
|
||||
end
|
||||
end
|
||||
|
||||
def procedure_type_de_champ_public_private_tags
|
||||
(procedure.types_de_champ + procedure.types_de_champ_private)
|
||||
.map { |tdc| { libelle: tdc.libelle, description: tdc.description } }
|
||||
end
|
||||
|
||||
def dossier_tags
|
||||
[{ libelle: 'motivation', description: '', target: 'motivation' },
|
||||
{ libelle: 'numéro du dossier', description: '', target: 'id' }]
|
||||
end
|
||||
|
||||
def individual_tags
|
||||
[{ libelle: 'civilité', description: 'M., Mme', target: 'gender' },
|
||||
{ libelle: 'nom', description: "nom de l'usager", target: 'nom' },
|
||||
{ libelle: 'prénom', description: "prénom de l'usager", target: 'prenom' }]
|
||||
end
|
||||
|
||||
def entreprise_tags
|
||||
[{ libelle: 'SIREN', description: '', target: 'siren' },
|
||||
{ libelle: 'numéro de TVA intracommunautaire', description: '', target: 'numero_tva_intracommunautaire' },
|
||||
{ libelle: 'SIRET du siège social', description: '', target: 'siret_siege_social' },
|
||||
{ libelle: 'raison sociale', description: '', target: 'raison_sociale' }]
|
||||
end
|
||||
|
||||
def etablissement_tags
|
||||
[{ libelle: 'adresse', description: '', target: 'inline_adresse' }]
|
||||
end
|
||||
|
||||
def build_pdf(dossier)
|
||||
action_view = ActionView::Base.new(ActionController::Base.view_paths,
|
||||
logo: logo,
|
||||
title: replace_tags(title, dossier),
|
||||
body: replace_tags(body, dossier),
|
||||
signature: signature,
|
||||
footer: footer,
|
||||
created_at: Time.now)
|
||||
|
||||
attestation_view = action_view.render(file: 'admin/attestation_templates/show',
|
||||
formats: [:pdf])
|
||||
|
||||
view_to_memory_file(attestation_view)
|
||||
end
|
||||
|
||||
def view_to_memory_file(view)
|
||||
pdf = StringIO.new(view)
|
||||
|
||||
def pdf.original_filename
|
||||
'attestation'
|
||||
end
|
||||
|
||||
pdf
|
||||
end
|
||||
|
||||
def replace_tags(text, dossier)
|
||||
if text.nil?
|
||||
return ''
|
||||
end
|
||||
|
||||
text = replace_type_de_champ_tags(text, procedure.types_de_champ, dossier.champs)
|
||||
text = replace_type_de_champ_tags(text, procedure.types_de_champ_private, dossier.champs_private)
|
||||
|
||||
tags_and_datas = [
|
||||
[dossier_tags, dossier],
|
||||
[individual_tags, dossier.individual],
|
||||
[entreprise_tags, dossier.entreprise],
|
||||
[etablissement_tags, dossier.entreprise&.etablissement]]
|
||||
|
||||
tags_and_datas.inject(text) { |acc, (tags, data)| replace_tags_with_values_from_data(acc, tags, data) }
|
||||
end
|
||||
|
||||
def replace_type_de_champ_tags(text, types_de_champ, dossier_champs)
|
||||
types_de_champ.inject(text) do |acc, tag|
|
||||
value = dossier_champs
|
||||
.select { |champ| champ.libelle == tag[:libelle] }
|
||||
.first
|
||||
.value
|
||||
|
||||
acc.gsub("--#{tag[:libelle]}--", value.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
def replace_tags_with_values_from_data(text, tags, data)
|
||||
if data.present?
|
||||
tags.inject(text) do |acc, tag|
|
||||
acc.gsub("--#{tag[:libelle]}--", data.send(tag[:target].to_sym).to_s)
|
||||
end
|
||||
else
|
||||
text
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +1,2 @@
|
|||
class ChampPrivate < Champ
|
||||
|
||||
end
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
class ChampPublic < Champ
|
||||
|
||||
end
|
||||
|
|
|
@ -15,5 +15,4 @@ module CredentialsSyncableConcern
|
|||
def force_sync_credentials
|
||||
SyncCredentialsService.new(self.class, email_was, email, encrypted_password).change_credentials!
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -21,6 +21,10 @@ module MailTemplateConcern
|
|||
name: "date_de_decision",
|
||||
description: "Permet d'afficher la date à laquelle la décision finale (acceptation, refus, classement sans suite) sur le dossier a été prise."
|
||||
}
|
||||
TAGS << TAG_MOTIVATION = {
|
||||
name: "motivation",
|
||||
description: "Permet d'afficher la motivation associée à la décision finale (acceptation, refus, classement sans suite) sur le dossier. Attention, elle est facultative."
|
||||
}
|
||||
|
||||
def object_for_dossier(dossier)
|
||||
replace_tags(object, dossier)
|
||||
|
@ -55,6 +59,8 @@ module MailTemplateConcern
|
|||
dossier.procedure.libelle
|
||||
when TAG_DATE_DE_DECISION
|
||||
dossier.processed_at.present? ? dossier.processed_at.localtime.strftime("%d/%m/%Y") : ""
|
||||
when TAG_MOTIVATION
|
||||
dossier.motivation || ""
|
||||
else
|
||||
'--BALISE_NON_RECONNUE--'
|
||||
end
|
||||
|
|
|
@ -23,6 +23,7 @@ class Dossier < ActiveRecord::Base
|
|||
has_one :etablissement, dependent: :destroy
|
||||
has_one :entreprise, dependent: :destroy
|
||||
has_one :individual, dependent: :destroy
|
||||
has_one :attestation
|
||||
has_many :cerfa, dependent: :destroy
|
||||
|
||||
has_many :pieces_justificatives, dependent: :destroy
|
||||
|
@ -41,6 +42,7 @@ class Dossier < ActiveRecord::Base
|
|||
belongs_to :procedure
|
||||
belongs_to :user
|
||||
|
||||
default_scope { where(hidden_at: nil) }
|
||||
scope :state_brouillon, -> { where(state: BROUILLON) }
|
||||
scope :state_not_brouillon, -> { where.not(state: BROUILLON) }
|
||||
scope :state_nouveaux, -> { where(state: NOUVEAUX) }
|
||||
|
@ -130,7 +132,7 @@ class Dossier < ActiveRecord::Base
|
|||
commentaires.order(created_at: :desc)
|
||||
end
|
||||
|
||||
def next_step! role, action
|
||||
def next_step! role, action, motivation = nil
|
||||
unless %w(initiate follow update comment receive refuse without_continuation close).include?(action)
|
||||
fail 'action is not valid'
|
||||
end
|
||||
|
@ -169,15 +171,33 @@ class Dossier < ActiveRecord::Base
|
|||
end
|
||||
when 'close'
|
||||
if received?
|
||||
self.attestation = build_attestation
|
||||
save
|
||||
|
||||
closed!
|
||||
|
||||
if motivation
|
||||
self.motivation = motivation
|
||||
save
|
||||
end
|
||||
end
|
||||
when 'refuse'
|
||||
if received?
|
||||
refused!
|
||||
|
||||
if motivation
|
||||
self.motivation = motivation
|
||||
save
|
||||
end
|
||||
end
|
||||
when 'without_continuation'
|
||||
if received?
|
||||
without_continuation!
|
||||
|
||||
if motivation
|
||||
self.motivation = motivation
|
||||
save
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -223,6 +243,7 @@ class Dossier < ActiveRecord::Base
|
|||
serialized_dossier = DossierTableExportSerializer.new(self)
|
||||
data = serialized_dossier.attributes.values
|
||||
data += self.champs.order('type_de_champ_id ASC').map(&:value)
|
||||
data += self.champs_private.order('type_de_champ_id ASC').map(&:value)
|
||||
data += self.export_entreprise_data.values
|
||||
return data
|
||||
end
|
||||
|
@ -231,6 +252,7 @@ class Dossier < ActiveRecord::Base
|
|||
serialized_dossier = DossierTableExportSerializer.new(self)
|
||||
headers = serialized_dossier.attributes.keys
|
||||
headers += self.procedure.types_de_champ.order('id ASC').map { |types_de_champ| types_de_champ.libelle.parameterize.underscore.to_sym }
|
||||
headers += self.procedure.types_de_champ_private.order('id ASC').map { |types_de_champ| types_de_champ.libelle.parameterize.underscore.to_sym }
|
||||
headers += self.export_entreprise_data.keys
|
||||
return headers
|
||||
end
|
||||
|
@ -290,6 +312,12 @@ class Dossier < ActiveRecord::Base
|
|||
|
||||
private
|
||||
|
||||
def build_attestation
|
||||
if procedure.attestation_template.present? && procedure.attestation_template.activated?
|
||||
procedure.attestation_template.attestation_for(self)
|
||||
end
|
||||
end
|
||||
|
||||
def update_state_dates
|
||||
if initiated? && !self.initiated_at
|
||||
self.initiated_at = DateTime.now
|
||||
|
|
|
@ -9,4 +9,9 @@ class Etablissement < ActiveRecord::Base
|
|||
def geo_adresse
|
||||
[numero_voie, type_voie, nom_voie, complement_adresse, code_postal, localite].join(' ')
|
||||
end
|
||||
|
||||
def inline_adresse
|
||||
#squeeze needed because of space in excess in the data
|
||||
"#{numero_voie} #{type_voie} #{nom_voie}, #{complement_adresse}, #{code_postal} #{localite}".squeeze(' ')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,9 +20,13 @@ class Gestionnaire < ActiveRecord::Base
|
|||
include CredentialsSyncableConcern
|
||||
|
||||
def procedure_filter
|
||||
return nil unless assign_to.pluck(:procedure_id).include?(self[:procedure_filter])
|
||||
|
||||
self[:procedure_filter]
|
||||
procedure_id = self[:procedure_filter]
|
||||
if procedures.find_by(id: procedure_id).present?
|
||||
procedure_id
|
||||
else
|
||||
self.update_column(:procedure_filter, nil)
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def can_view_dossier?(dossier_id)
|
||||
|
@ -52,10 +56,8 @@ class Gestionnaire < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def build_default_preferences_list_dossier procedure_id=nil
|
||||
|
||||
PreferenceListDossier.available_columns_for(procedure_id).each do |table|
|
||||
table.second.each do |column|
|
||||
|
||||
if valid_couple_table_attr? table.first, column.first
|
||||
PreferenceListDossier.create(
|
||||
libelle: column.second[:libelle],
|
||||
|
@ -108,16 +110,15 @@ class Gestionnaire < ActiveRecord::Base
|
|||
active_procedure_overviews = procedures
|
||||
.where(published: true)
|
||||
.all
|
||||
.map { |procedure| procedure.procedure_overview(start_date, dossiers_with_notifications_count_for_procedure(procedure)) }
|
||||
.map { |procedure| procedure.procedure_overview(start_date) }
|
||||
.select(&:had_some_activities?)
|
||||
|
||||
if active_procedure_overviews.count == 0 && notifications.count == 0
|
||||
if active_procedure_overviews.count == 0
|
||||
nil
|
||||
else
|
||||
{
|
||||
start_date: start_date,
|
||||
procedure_overviews: active_procedure_overviews,
|
||||
notifications: notifications
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class Invite < ActiveRecord::Base
|
||||
|
||||
belongs_to :dossier
|
||||
belongs_to :user
|
||||
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
class InviteGestionnaire < Invite
|
||||
|
||||
end
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
class InviteUser < Invite
|
||||
|
||||
end
|
||||
|
|
|
@ -6,6 +6,6 @@ module Mails
|
|||
TEMPLATE_NAME = "mails/closed_mail"
|
||||
DISPLAYED_NAME = "Accusé d'acceptation"
|
||||
DEFAULT_OBJECT = 'Votre dossier TPS nº --numero_dossier-- a été accepté'
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE, TAG_DATE_DE_DECISION]
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE, TAG_DATE_DE_DECISION, TAG_MOTIVATION]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ module Mails
|
|||
SLUG = "initiated_mail"
|
||||
TEMPLATE_NAME = "mails/initiated_mail"
|
||||
DISPLAYED_NAME = 'Accusé de réception'
|
||||
DEFAULT_OBJECT = 'Votre dossier TPS nº --numero_dossier-- a été bien reçu'
|
||||
DEFAULT_OBJECT = 'Votre dossier TPS nº --numero_dossier-- a bien été reçu'
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,6 @@ module Mails
|
|||
TEMPLATE_NAME = "mails/refused_mail"
|
||||
DISPLAYED_NAME = 'Accusé de rejet du dossier'
|
||||
DEFAULT_OBJECT = 'Votre dossier TPS nº --numero_dossier-- a été refusé'
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE, TAG_DATE_DE_DECISION]
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE, TAG_DATE_DE_DECISION, TAG_MOTIVATION]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,6 @@ module Mails
|
|||
TEMPLATE_NAME = "mails/without_continuation_mail"
|
||||
DISPLAYED_NAME = 'Accusé de classement sans suite'
|
||||
DEFAULT_OBJECT = 'Votre dossier TPS nº --numero_dossier-- a été classé sans suite'
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE, TAG_DATE_DE_DECISION]
|
||||
ALLOWED_TAGS = [TAG_NUMERO_DOSSIER, TAG_LIEN_DOSSIER, TAG_LIBELLE_PROCEDURE, TAG_DATE_DE_DECISION, TAG_MOTIVATION]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,6 +7,7 @@ class Procedure < ActiveRecord::Base
|
|||
has_one :procedure_path, dependent: :destroy
|
||||
|
||||
has_one :module_api_carto, dependent: :destroy
|
||||
has_one :attestation_template, dependent: :destroy
|
||||
|
||||
belongs_to :administrateur
|
||||
|
||||
|
@ -30,12 +31,19 @@ class Procedure < ActiveRecord::Base
|
|||
|
||||
mount_uploader :logo, ProcedureLogoUploader
|
||||
|
||||
default_scope { where(hidden_at: nil) }
|
||||
scope :not_archived, -> { where(archived: false) }
|
||||
scope :by_libelle, -> { order(libelle: :asc) }
|
||||
|
||||
validates :libelle, presence: true, allow_blank: false, allow_nil: false
|
||||
validates :description, presence: true, allow_blank: false, allow_nil: false
|
||||
|
||||
def hide!
|
||||
now = DateTime.now
|
||||
self.update_attributes(hidden_at: now)
|
||||
self.dossiers.update_all(hidden_at: now)
|
||||
end
|
||||
|
||||
def path
|
||||
procedure_path.path unless procedure_path.nil?
|
||||
end
|
||||
|
@ -88,12 +96,13 @@ class Procedure < ActiveRecord::Base
|
|||
|
||||
def clone
|
||||
procedure = self.deep_clone(include:
|
||||
[:types_de_piece_justificative,
|
||||
:types_de_champ,
|
||||
:types_de_champ_private,
|
||||
:module_api_carto,
|
||||
types_de_champ: [:drop_down_list]
|
||||
])
|
||||
{
|
||||
types_de_piece_justificative: nil,
|
||||
module_api_carto: nil,
|
||||
attestation_template: nil,
|
||||
types_de_champ: :drop_down_list,
|
||||
types_de_champ_private: :drop_down_list
|
||||
})
|
||||
procedure.archived = false
|
||||
procedure.published = false
|
||||
procedure.logo_secure_token = nil
|
||||
|
@ -109,12 +118,12 @@ class Procedure < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def publish!(path)
|
||||
self.update_attributes!({published: true, archived: false})
|
||||
self.update_attributes!({ published: true, archived: false, published_at: Time.now })
|
||||
ProcedurePath.create!(path: path, procedure: self, administrateur: self.administrateur)
|
||||
end
|
||||
|
||||
def archive
|
||||
self.update_attributes!({archived: true})
|
||||
self.update_attributes!(archived: true, archived_at: Time.now)
|
||||
end
|
||||
|
||||
def total_dossier
|
||||
|
@ -133,8 +142,8 @@ class Procedure < ActiveRecord::Base
|
|||
}
|
||||
end
|
||||
|
||||
def procedure_overview(start_date, notifications_count)
|
||||
ProcedureOverview.new(self, start_date, notifications_count)
|
||||
def procedure_overview(start_date)
|
||||
ProcedureOverview.new(self, start_date)
|
||||
end
|
||||
|
||||
def initiated_mail_template
|
||||
|
|
|
@ -1,82 +1,72 @@
|
|||
class ProcedureOverview
|
||||
include Rails.application.routes.url_helpers
|
||||
attr_accessor :libelle, :notifications_count, :received_dossiers_count, :created_dossiers_count, :processed_dossiers_count, :date
|
||||
attr_accessor :procedure,
|
||||
:created_dossiers_count,
|
||||
:dossiers_en_instruction_count,
|
||||
:old_dossiers_en_instruction,
|
||||
:dossiers_en_construction_count,
|
||||
:old_dossiers_en_construction
|
||||
|
||||
def initialize(procedure, start_date, notifications_count)
|
||||
@libelle = procedure.libelle
|
||||
@procedure_url = backoffice_dossiers_procedure_url(procedure)
|
||||
@notifications_count = notifications_count
|
||||
def initialize(procedure, start_date)
|
||||
@start_date = start_date
|
||||
@procedure = procedure
|
||||
|
||||
@received_dossiers_count = procedure.dossiers.where(state: :received).count
|
||||
@created_dossiers_count = procedure.dossiers
|
||||
@dossiers_en_instruction_count = procedure.dossiers.state_en_instruction.count
|
||||
@old_dossiers_en_instruction = procedure
|
||||
.dossiers
|
||||
.state_en_instruction
|
||||
.where('received_at < ?', 1.week.ago)
|
||||
|
||||
@dossiers_en_construction_count = procedure.dossiers.state_en_construction.count
|
||||
@old_dossiers_en_construction = procedure
|
||||
.dossiers
|
||||
.state_en_construction
|
||||
.where('initiated_at < ?', 1.week.ago)
|
||||
|
||||
@created_dossiers_count = procedure
|
||||
.dossiers
|
||||
.where(created_at: start_date..DateTime.now)
|
||||
.where.not(state: :draft)
|
||||
.state_not_brouillon
|
||||
.count
|
||||
@processed_dossiers_count = procedure.dossiers.where(processed_at: start_date..DateTime.now).count
|
||||
end
|
||||
|
||||
def had_some_activities?
|
||||
[received_dossiers_count,
|
||||
created_dossiers_count,
|
||||
processed_dossiers_count,
|
||||
notifications_count].reduce(:+) > 0
|
||||
[@dossiers_en_instruction_count,
|
||||
@dossiers_en_construction_count,
|
||||
@created_dossiers_count].reduce(:+) > 0
|
||||
end
|
||||
|
||||
def to_html
|
||||
[libelle_description,
|
||||
dossiers_en_instruction_description,
|
||||
created_dossier_description,
|
||||
processed_dossier_description,
|
||||
notifications_description].compact.join('<br>')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def libelle_description
|
||||
"<a href='#{@procedure_url}'><strong>#{libelle}</strong></a>"
|
||||
end
|
||||
|
||||
def dossiers_en_instruction_description
|
||||
case received_dossiers_count
|
||||
def dossiers_en_construction_description
|
||||
case @dossiers_en_construction_count
|
||||
when 0
|
||||
nil
|
||||
when 1
|
||||
"1 dossier est en cours d'instruction"
|
||||
'dossier suivi en construction'
|
||||
else
|
||||
"#{received_dossiers_count} dossiers sont en cours d'instruction"
|
||||
'dossiers suivis en construction'
|
||||
end
|
||||
end
|
||||
|
||||
def dossiers_en_instruction_description
|
||||
case @dossiers_en_instruction_count
|
||||
when 0
|
||||
nil
|
||||
when 1
|
||||
"dossier est en cours d'instruction"
|
||||
else
|
||||
"dossiers sont en cours d'instruction"
|
||||
end
|
||||
end
|
||||
|
||||
def created_dossier_description
|
||||
case created_dossiers_count
|
||||
when 0
|
||||
nil
|
||||
when 1
|
||||
'1 nouveau dossier a été déposé'
|
||||
else
|
||||
"#{created_dossiers_count} nouveaux dossiers ont été déposés"
|
||||
end
|
||||
end
|
||||
formated_date = I18n.l(@start_date, format: '%d %B %Y')
|
||||
|
||||
def processed_dossier_description
|
||||
case processed_dossiers_count
|
||||
case @created_dossiers_count
|
||||
when 0
|
||||
nil
|
||||
when 1
|
||||
'1 dossier a été instruit'
|
||||
"nouveau dossier a été déposé depuis le #{formated_date}"
|
||||
else
|
||||
"#{processed_dossiers_count} dossiers ont été instruits"
|
||||
end
|
||||
end
|
||||
|
||||
def notifications_description
|
||||
case notifications_count
|
||||
when 0
|
||||
nil
|
||||
when 1
|
||||
'1 notification en attente sur les dossiers que vous suivez'
|
||||
else
|
||||
"#{notifications_count} notifications en attente sur les dossiers que vous suivez"
|
||||
"nouveaux dossiers ont été déposés depuis le #{formated_date}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
class TypeDeChampPrivate < TypeDeChamp
|
||||
|
||||
end
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
class TypeDeChampPublic < TypeDeChamp
|
||||
|
||||
end
|
||||
|
|
|
@ -9,6 +9,7 @@ class DossierSerializer < ActiveModel::Serializer
|
|||
:initiated_at,
|
||||
:received_at,
|
||||
:processed_at,
|
||||
:motivation,
|
||||
:accompagnateurs,
|
||||
:invites
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ class DossierTableExportSerializer < ActiveModel::Serializer
|
|||
:state,
|
||||
:initiated_at,
|
||||
:received_at,
|
||||
:processed_at
|
||||
:processed_at,
|
||||
:motivation
|
||||
|
||||
attribute :emails_accompagnateurs
|
||||
|
||||
|
|